DELETED COPYRIGHT.md Index: COPYRIGHT.md ================================================================== --- COPYRIGHT.md +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright © 2008 D. Richard Hipp - -This program is free software. As far as the author is -concerned, you can redistribute it and/or modify the code -as you see fit. No attribution is required. Use whichever -of the following license terms best applies to your situation. - - 1. GNU General Public License - 2. BSD License - 3. MIT License - 4. CC0 License - -This program is distributed in the hope that it will be useful, -but without any warranty; without even the implied warranty of -merchantability or fitness for a particular purpose. Index: src/run-all.tcl ================================================================== --- src/run-all.tcl +++ src/run-all.tcl @@ -34,11 +34,11 @@ # set totalerr 0 set totaltest 0 set totalrun 0 foreach tx [lsort [array names tcase]] { - foreach opt {0 -1} { + foreach opt {0 0xfff} { set opt "integrity_check;optimizer=[expr {$opt+0}]" catch { exec $BIN -verify -parameter $opt $tx } res puts $res Index: src/sqlite3.c ================================================================== --- src/sqlite3.c +++ src/sqlite3.c @@ -1,8 +1,8 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.49.0. By combining all the individual C code files into this +** version 3.20.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 ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. @@ -14,22 +14,768 @@ ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. -** -** The content in this amalgamation comes from Fossil check-in -** 602d4dd69ec9a724c69cb41ab15376ec731b with changes in files: -** -** */ -#ifndef SQLITE_AMALGAMATION #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #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_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 ** ** The author disclaims copyright to this source code. In place of @@ -54,24 +800,24 @@ ** NO_TEST - The branches on this line are not ** measured by branch coverage. This is ** used on lines of code that actually ** implement parts of coverage testing. ** -** OPTIMIZATION-IF-TRUE - This branch is allowed to always be false +** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false ** and the correct answer is still obtained, ** though perhaps more slowly. ** -** OPTIMIZATION-IF-FALSE - This branch is allowed to always be true +** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true ** and the correct answer is still obtained, ** though perhaps more slowly. ** ** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread ** that would be harmless and undetectable -** if it did occur. +** if it did occur. ** ** In all cases, the special comment must be enclosed in the usual -** slash-asterisk...asterisk-slash comment marks, with no spaces between the +** slash-asterisk...asterisk-slash comment marks, with no spaces between the ** asterisks and the comment text. */ /* ** Make sure the Tcl calling convention macro is defined. This macro is @@ -79,10 +825,18 @@ */ #ifndef SQLITE_TCLAPI # 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 ** compiler warnings due to subsequent content in this file and other files ** that are included by this file. @@ -122,19 +876,10 @@ #pragma warning(disable : 4306) #pragma warning(disable : 4702) #pragma warning(disable : 4706) #endif /* defined(_MSC_VER) */ -#if defined(_MSC_VER) && !defined(_WIN64) -#undef SQLITE_4_BYTE_ALIGNED_MALLOC -#define SQLITE_4_BYTE_ALIGNED_MALLOC -#endif /* defined(_MSC_VER) && !defined(_WIN64) */ - -#if !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800 -#define HAVE_LOG2 0 -#endif /* !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800 */ - #endif /* SQLITE_MSVC_H */ /************** End of msvc.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -233,43 +978,19 @@ # define MSVC_VERSION _MSC_VER #else # define MSVC_VERSION 0 #endif -/* -** Some C99 functions in "math.h" are only present for MSVC when its version -** is associated with Visual Studio 2013 or higher. -*/ -#ifndef SQLITE_HAVE_C99_MATH_FUNCS -# if MSVC_VERSION==0 || MSVC_VERSION>=1800 -# define SQLITE_HAVE_C99_MATH_FUNCS (1) -# else -# define SQLITE_HAVE_C99_MATH_FUNCS (0) -# endif -#endif - /* Needed for various definitions... */ #if defined(__GNUC__) && !defined(_GNU_SOURCE) # define _GNU_SOURCE #endif #if defined(__OpenBSD__) && !defined(_BSD_SOURCE) # define _BSD_SOURCE #endif -/* -** Macro to disable warnings about missing "break" at the end of a "case". -*/ -#if defined(__has_attribute) -# if __has_attribute(fallthrough) -# define deliberate_fall_through __attribute__((fallthrough)); -# endif -#endif -#if !defined(deliberate_fall_through) -# define deliberate_fall_through -#endif - /* ** For MinGW, check to see if we can include the header file containing its ** version information, among other things. Normally, this internal MinGW ** header file would [only] be included automatically by other MinGW header ** files; however, the contained version information is now required by this @@ -298,21 +1019,10 @@ defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ defined(__MSVCRT__) # define _USE_32BIT_TIME_T #endif -/* Optionally #include a user-defined header, whereby compilation options -** may be set prior to where they take effect, but after platform setup. -** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include -** file. -*/ -#ifdef SQLITE_CUSTOM_INCLUDE -# define INC_STRINGIFY_(f) #f -# define INC_STRINGIFY(f) INC_STRINGIFY_(f) -# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE) -#endif - /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for ** MinGW. */ /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ @@ -360,34 +1070,11 @@ extern "C" { #endif /* -** Facilitate override of interface linkage and calling conventions. -** Be aware that these macros may not be used within this particular -** translation of the amalgamation and its associated header file. -** -** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the -** compiler that the target identifier should have external linkage. -** -** The SQLITE_CDECL macro is used to set the calling convention for -** public functions that accept a variable number of arguments. -** -** The SQLITE_APICALL macro is used to set the calling convention for -** public functions that accept a fixed number of arguments. -** -** The SQLITE_STDCALL macro is no longer used and is now deprecated. -** -** The SQLITE_CALLBACK macro is used to set the calling convention for -** function pointers. -** -** The SQLITE_SYSAPI macro is used to set the calling convention for -** functions provided by the operating system. -** -** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and -** SQLITE_SYSAPI macros are used only when building for environments -** that require non-default calling conventions. +** Provide the ability to override linkage features of the interface. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif #ifndef SQLITE_API @@ -448,28 +1135,26 @@ ** The SQLITE_VERSION_NUMBER for any given release of SQLite will also ** be larger than the release from which it is derived. Either Y will ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** -** Since [version 3.6.18] ([dateof:3.6.18]), +** Since [version 3.6.18] ([dateof:3.6.18]), ** SQLite source code has been stored in the ** Fossil configuration management ** 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 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. +** or SHA3-256 hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.49.0" -#define SQLITE_VERSION_NUMBER 3049000 -#define SQLITE_SOURCE_ID "2025-02-02 18:01:32 602d4dd69ec9a724c69cb41ab15376ec731bfd4894fac0a2b25076b857786c6d" +#define SQLITE_VERSION "3.20.0" +#define SQLITE_VERSION_NUMBER 3020000 +#define SQLITE_SOURCE_ID "2017-07-15 13:49:56 47cf83a0682b7b3219cf255457f5fbe05f3c1f46be42f6bbab33b78a57a252f6" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** @@ -481,25 +1166,23 @@ ** the header, and thus ensure that the application is ** compiled with matching library and header files. ** **
 ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
-** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
 ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
 ** 
)^ ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to -** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns -** a pointer to a string constant whose value is the same as the -** [SQLITE_SOURCE_ID] C preprocessor macro. 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].)^ +** [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. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; SQLITE_API const char *sqlite3_libversion(void); @@ -507,35 +1190,32 @@ SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics ** -** ^The sqlite3_compileoption_used() function returns 0 or 1 -** indicating whether the specified option was defined at -** compile time. ^The SQLITE_ prefix may be omitted from the -** option name passed to sqlite3_compileoption_used(). +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). ** ** ^The sqlite3_compileoption_get() function allows iterating ** over the list of options that were defined at compile time by ** returning the N-th compile time option string. ^If N is out of range, -** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ -** prefix is omitted from any strings returned by +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by ** sqlite3_compileoption_get(). ** ** ^Support for the diagnostic functions sqlite3_compileoption_used() -** and sqlite3_compileoption_get() may be omitted by specifying the +** and sqlite3_compileoption_get() may be omitted by specifying the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_API int sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *sqlite3_compileoption_get(int N); -#else -# define sqlite3_compileoption_used(X) 0 -# define sqlite3_compileoption_get(X) ((void*)0) #endif /* ** CAPI3REF: Test To See If The Library Is Threadsafe ** @@ -544,11 +1224,11 @@ ** [SQLITE_THREADSAFE] compile-time option being set to 0. ** ** SQLite can be compiled with or without mutexes. When ** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes ** are enabled and SQLite is threadsafe. When the -** [SQLITE_THREADSAFE] macro is 0, +** [SQLITE_THREADSAFE] macro is 0, ** the mutexes are omitted. Without the mutexes, it is not safe ** to use SQLite concurrently from more than one thread. ** ** Enabling mutexes incurs a measurable performance penalty. ** So if speed is of utmost importance, it makes sense to disable @@ -601,18 +1281,18 @@ ** The sqlite_int64 and sqlite_uint64 types are supported for backwards ** compatibility only. ** ** ^The sqlite3_int64 and sqlite_int64 types can store integer values ** between -9223372036854775808 and +9223372036854775807 inclusive. ^The -** sqlite3_uint64 and sqlite_uint64 types can store integer values +** sqlite3_uint64 and sqlite_uint64 types can store integer values ** between 0 and +18446744073709551615 inclusive. */ #ifdef SQLITE_INT64_TYPE typedef SQLITE_INT64_TYPE sqlite_int64; # ifdef SQLITE_UINT64_TYPE typedef SQLITE_UINT64_TYPE sqlite_uint64; -# else +# else typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; # endif #elif defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; @@ -639,26 +1319,30 @@ ** for the [sqlite3] object. ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if ** the [sqlite3] object is successfully destroyed and all associated ** resources are deallocated. ** -** Ideally, applications should [sqlite3_finalize | finalize] all -** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and -** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated -** with the [sqlite3] object prior to attempting to close the object. ** ^If the database connection is associated with unfinalized prepared -** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then -** sqlite3_close() will leave the database connection open and return -** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared -** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups, -** it returns [SQLITE_OK] regardless, but instead of deallocating the database -** connection immediately, it marks the database connection as an unusable -** "zombie" and makes arrangements to automatically deallocate the database -** connection after all prepared statements are finalized, all BLOB handles -** are closed, and all backups have finished. The sqlite3_close_v2() interface -** is intended for use with host languages that are garbage collected, and -** where the order in which destructors are called is arbitrary. +** statements or unfinished sqlite3_backup objects then sqlite3_close() +** will leave the database connection open and return [SQLITE_BUSY]. +** ^If sqlite3_close_v2() is called with unfinalized prepared statements +** and/or unfinished sqlite3_backups, then the database connection becomes +** an unusable "zombie" which will automatically be deallocated when the +** last prepared statement is finalized or the last sqlite3_backup is +** finished. The sqlite3_close_v2() interface is intended for use with +** host languages that are garbage collected, and where the order in which +** destructors are called is arbitrary. +** +** Applications should [sqlite3_finalize | finalize] all [prepared statements], +** [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated +** with the [sqlite3] object prior to attempting to close the object. ^If +** sqlite3_close_v2() is called on a [database connection] that still has +** outstanding [prepared statements], [BLOB handles], and/or +** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation +** of resources is deferred until all [prepared statements], [BLOB handles], +** and [sqlite3_backup] objects are also destroyed. ** ** ^If an [sqlite3] object is destroyed while a transaction is open, ** the transaction is automatically rolled back. ** ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] @@ -684,11 +1368,11 @@ ** METHOD: sqlite3 ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], ** that allows an application to run multiple statements of SQL -** without having to use a lot of C code. +** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, ** semicolon-separate SQL statements passed into its 2nd argument, ** in the context of the [database connection] passed in as its 1st ** argument. ^If the callback function of the 3rd argument to @@ -724,11 +1408,11 @@ ** sqlite3_exec() callback is an array of pointers to strings where each ** entry represents the name of corresponding result column as obtained ** from [sqlite3_column_name()]. ** ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer -** to an empty string, or a pointer that contains only whitespace and/or +** to an empty string, or a pointer that contains only whitespace and/or ** SQL comments, then no SQL statements are evaluated and the database ** is not changed. ** ** Restrictions: ** @@ -737,12 +1421,10 @@ ** is a valid and open [database connection]. **
  • The application must not close the [database connection] specified by ** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. **
  • The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. -**
  • The application must not dereference the arrays or string pointers -** passed as the 3rd and 4th callback parameters after it returns. ** */ SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ @@ -777,11 +1459,11 @@ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ #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 /* Internal use only */ +#define SQLITE_EMPTY 16 /* Not used */ #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 */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ @@ -811,13 +1493,10 @@ ** on a per database connection basis using the ** [sqlite3_extended_result_codes()] API. Or, the extended code for ** 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_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<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)) #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) #define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) @@ -842,36 +1521,22 @@ #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) #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_IOERR_DATA (SQLITE_IOERR | (32<<8)) -#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) -#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) -#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) -#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) -#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ -#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) -#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) -#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #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)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) @@ -879,39 +1544,22 @@ #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) -#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8)) -#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) -#define SQLITE_NOTICE_RBU (SQLITE_NOTICE | (3<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) -#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. -** -** Only those flags marked as "Ok for sqlite3_open_v2()" may be -** used as the third argument to the [sqlite3_open_v2()] interface. -** The other flags have historically been ignored by sqlite3_open_v2(), -** though future versions of SQLite might change so that an error is -** raised if any of the disallowed bits are passed into sqlite3_open_v2(). -** Applications should not depend on the historical behavior. -** -** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into -** [sqlite3_open_v2()] does *not* cause the underlying database file -** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into -** [sqlite3_open_v2()] has historically be a no-op and might become an -** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ @@ -923,23 +1571,18 @@ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ -#define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ -#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ /* Reserved: 0x00F00000 */ -/* Legacy compatibility: */ -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ - /* ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods] @@ -964,22 +1607,10 @@ ** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN ** 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]. -** -** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read -** from the database file in amounts that are not a multiple of the -** page size and that do not begin at a page boundary. Without this -** property, SQLite is careful to only do full-page reads and write -** on aligned pages, with the one exception that it will do a sub-page -** read of the first page to access the database header. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC1K 0x00000004 #define SQLITE_IOCAP_ATOMIC2K 0x00000008 @@ -991,29 +1622,23 @@ #define SQLITE_IOCAP_SAFE_APPEND 0x00000200 #define SQLITE_IOCAP_SEQUENTIAL 0x00000400 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_IMMUTABLE 0x00002000 -#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 -#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000 /* ** CAPI3REF: File Locking Levels ** ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. These values are ordered from -** lest restrictive to most restrictive. -** -** The argument to xLock() is always SHARED or higher. The argument to -** xUnlock is either SHARED or NONE. +** of an [sqlite3_io_methods] object. */ -#define SQLITE_LOCK_NONE 0 /* xUnlock() only */ -#define SQLITE_LOCK_SHARED 1 /* xLock() or xUnlock() */ -#define SQLITE_LOCK_RESERVED 2 /* xLock() only */ -#define SQLITE_LOCK_PENDING 3 /* xLock() only */ -#define SQLITE_LOCK_EXCLUSIVE 4 /* xLock() only */ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 /* ** CAPI3REF: Synchronization Type Flags ** ** When SQLite invokes the xSync() method of an @@ -1044,11 +1669,11 @@ #define SQLITE_SYNC_DATAONLY 0x00010 /* ** CAPI3REF: OS Interface Open File Handle ** -** An [sqlite3_file] object represents an open file in the +** An [sqlite3_file] object represents an open file in the ** [sqlite3_vfs | OS interface layer]. Individual OS interface ** implementations will ** want to subclass this object by appending additional fields ** for their own use. The pMethods entry is a pointer to an ** [sqlite3_io_methods] object that defines methods for performing @@ -1066,11 +1691,11 @@ ** [sqlite3_file] object (or, more commonly, a subclass of the ** [sqlite3_file] object) with a pointer to an instance of this object. ** This object defines the methods used to perform various operations ** against the open file represented by the [sqlite3_file] object. ** -** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method ** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The ** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] ** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element ** to NULL. @@ -1087,22 +1712,15 @@ **
  • [SQLITE_LOCK_SHARED], **
  • [SQLITE_LOCK_RESERVED], **
  • [SQLITE_LOCK_PENDING], or **
  • [SQLITE_LOCK_EXCLUSIVE]. ** -** xLock() upgrades the database file lock. In other words, xLock() moves the -** database file lock in the direction NONE toward EXCLUSIVE. The argument to -** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never -** SQLITE_LOCK_NONE. If the database file lock is already at or above the -** requested lock, then the call to xLock() is a no-op. -** xUnlock() downgrades the database file lock to either SHARED or NONE. -** If the lock is already at or below the requested lock state, then the call -** to xUnlock() is a no-op. +** xLock() increases the lock. xUnlock() decreases the lock. ** The xCheckReservedLock() method checks whether any database connection, ** either in this process or in some other process, is holding a RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns, via its output -** pointer parameter, true if such a lock exists and false otherwise. +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. ** ** The xFileControl() method is a generic interface that allows custom ** VFS implementations to directly control an open file using the ** [sqlite3_file_control()] interface. The second "op" argument is an ** integer opcode. The third argument is a generic pointer intended to @@ -1138,12 +1756,10 @@ **
  • [SQLITE_IOCAP_SAFE_APPEND] **
  • [SQLITE_IOCAP_SEQUENTIAL] **
  • [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] **
  • [SQLITE_IOCAP_POWERSAFE_OVERWRITE] **
  • [SQLITE_IOCAP_IMMUTABLE] -**
  • [SQLITE_IOCAP_BATCH_ATOMIC] -**
  • [SQLITE_IOCAP_SUBPAGE_READ] ** ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and @@ -1200,34 +1816,26 @@ **
  • [[SQLITE_FCNTL_LOCKSTATE]] ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. -** This capability is only available if SQLite is compiled with [SQLITE_DEBUG]. +** into an integer that the pArg argument points to. This capability +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. ** **
  • [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the ** current transaction. This hint is not guaranteed to be accurate but it ** is often close. The underlying VFS might choose to preallocate database ** file space based on this hint in order to help writes to the database ** file run faster. ** -**
  • [[SQLITE_FCNTL_SIZE_LIMIT]] -** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that -** implements [sqlite3_deserialize()] to set an upper bound on the size -** of the in-memory database. The argument is a pointer to a [sqlite3_int64]. -** If the integer pointed to is negative, then it is filled in with the -** current limit. Otherwise the limit is set to the larger of the value -** of the integer pointed to and the current database size. The integer -** pointed to is set to the new limit. -** **
  • [[SQLITE_FCNTL_CHUNK_SIZE]] ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS ** extends and truncates the database file in chunks of a size specified -** by the user. The fourth argument to [sqlite3_file_control()] should +** by the user. The fourth argument to [sqlite3_file_control()] should ** point to an integer (type int) containing the new chunk-size to use ** for the nominated database. Allocating database file space in large ** chunks (say 1MB at a time), may reduce file-system fragmentation and ** improve performance on some systems. ** @@ -1246,28 +1854,28 @@ ** No longer in use. ** **
  • [[SQLITE_FCNTL_SYNC]] ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and ** sent to the VFS immediately before the xSync method is invoked on a -** database file descriptor. Or, if the xSync method is not invoked -** because the user has configured SQLite with -** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place ** of the xSync method. In most cases, the pointer argument passed with ** this file-control is NULL. However, if the database file is being synced ** as part of a multi-database commit, the argument points to a nul-terminated -** string containing the transactions super-journal file name. VFSes that -** do not need this signal should silently ignore this opcode. Applications -** should not call [sqlite3_file_control()] with this opcode as doing so may -** disrupt the operation of the specialized VFSes that do require it. +** string containing the transactions master-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. ** **
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] ** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite ** and sent to the VFS after a transaction has been committed immediately ** but before the database is unlocked. VFSes that do not need this signal ** should silently ignore this opcode. Applications should not call -** [sqlite3_file_control()] with this opcode as doing so may disrupt the -** operation of the specialized VFSes that do require it. +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. ** **
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic ** retry counts and intervals for certain disk I/O operations for the ** windows [VFS] in order to provide robustness in the presence of @@ -1285,12 +1893,11 @@ ** interrogated. The zDbName parameter is ignored. ** **
  • [[SQLITE_FCNTL_PERSIST_WAL]] ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary -** write ahead log ([WAL file]) and shared memory -** files used for transaction control +** write ahead log and shared memory files used for transaction control ** are automatically deleted when the latest connection to the database ** closes. Setting persistent WAL mode causes those files to persist after ** close. Persisting the files is useful when other processes that do not ** have write permission on the directory containing the database file want ** to read the database file, as the WAL and shared memory files must exist @@ -1311,17 +1918,17 @@ ** zero-damage mode setting. ** **
  • [[SQLITE_FCNTL_OVERWRITE]] ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening ** a write transaction to indicate that, unless it is rolled back for some -** reason, the entire database file will be overwritten by the current +** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. ** **
  • [[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of ** all [VFSes] in the VFS stack. The names are of all VFS shims and the -** final bottom-level VFS are written into memory obtained from +** final bottom-level VFS are written into memory obtained from ** [sqlite3_malloc()] and the result is stored in the char* variable ** that the fourth parameter of [sqlite3_file_control()] points to. ** The caller is responsible for freeing the memory when done. As with ** all file-control actions, there is no guarantee that this will actually ** do anything. Callers should initialize the char* variable to a NULL @@ -1336,11 +1943,11 @@ ** to a pointer to the top-level VFS.)^ ** ^When there are multiple VFS shims in the stack, this opcode finds the ** upper-most shim only. ** **
  • [[SQLITE_FCNTL_PRAGMA]] -** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] ** file control is sent to the open [sqlite3_file] object corresponding ** to the database file to which the pragma statement refers. ^The argument ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of ** pointers to strings (char**) in which the second element of the array ** is the name of the pragma and the third element is the argument to the @@ -1347,11 +1954,11 @@ ** pragma or NULL if the pragma has no argument. ^The handler for an ** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element ** of the char** argument point to a string obtained from [sqlite3_mprintf()] ** or the equivalent and that string will become the result of the pragma or ** the error message if the pragma fails. ^If the -** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] ** file control returns [SQLITE_OK], then the parser assumes that the ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement if result string is NULL, or that returns a copy ** of the result string if the string is non-NULL. @@ -1364,20 +1971,20 @@ ** **
  • [[SQLITE_FCNTL_BUSYHANDLER]] ** ^The [SQLITE_FCNTL_BUSYHANDLER] ** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access -** to the connection's busy-handler callback. The argument is of type (void**) +** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points -** to a function of type (int (*)(void *)). In order to invoke the connection's +** to a function of type (int (*)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. ** **
  • [[SQLITE_FCNTL_TEMPFILENAME]] -** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control ** to have SQLite generate a ** temporary filename using the same algorithm that is followed to generate ** temporary filenames for TEMP tables and other internal uses. The ** argument should be a char** which will be filled with the filename ** written into memory obtained from [sqlite3_malloc()]. The caller should @@ -1387,11 +1994,11 @@ ** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the ** maximum number of bytes that will be used for memory-mapped I/O. ** The argument is a pointer to a value of type sqlite3_int64 that ** is an advisory maximum number of bytes in the file to memory map. The ** pointer is overwritten with the old value. The limit is not changed if -** the value originally pointed to is negative, and so the current limit +** the value originally pointed to is negative, and so the current limit ** can be queried by passing in a pointer to a negative number. This ** file-control is used internally to implement [PRAGMA mmap_size]. ** **
  • [[SQLITE_FCNTL_TRACE]] ** The [SQLITE_FCNTL_TRACE] file control provides advisory information @@ -1417,15 +2024,10 @@ ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This ** opcode causes the xFileControl method to swap the file handle with the one ** pointed to by the pArg argument. This capability is used during testing ** and only needs to be supported when SQLITE_TEST is defined. ** -**
  • [[SQLITE_FCNTL_NULL_IO]] -** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor -** or file handle for the [sqlite3_file] object such that it will no longer -** read or write to the database file. -** **
  • [[SQLITE_FCNTL_WAL_BLOCK]] ** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might ** be advantageous to block on the next WAL lock if the lock is not immediately ** available. The WAL subsystem issues this signal during rare ** circumstances in order to fix a problem with priority inversion. @@ -1436,106 +2038,11 @@ ** VFS should return SQLITE_NOTFOUND for this opcode. ** **
  • [[SQLITE_FCNTL_RBU]] ** 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]. -** -**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] -** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS -** to block for up to M milliseconds before failing when attempting to -** obtain a file lock using the xLock or xShmLock methods of the VFS. -** The parameter is a pointer to a 32-bit signed integer that contains -** the value that M is to be set to. Before returning, the 32-bit signed -** integer is overwritten with the previous value of M. -** -**
  • [[SQLITE_FCNTL_DATA_VERSION]] -** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to -** a database file. The argument is a pointer to a 32-bit unsigned integer. -** The "data version" for the pager is written into the pointer. The -** "data version" changes whenever any change occurs to the corresponding -** database file, either through SQL statements on the same database -** connection or through transactions committed by separate database -** connections possibly in other processes. The [sqlite3_total_changes()] -** interface can be used to find if any database on the connection has changed, -** but that interface responds to changes on TEMP as well as MAIN and does -** not provide a mechanism to detect changes to MAIN only. Also, the -** [sqlite3_total_changes()] interface responds to internal changes only and -** omits changes made by other database connections. The -** [PRAGMA data_version] command provides a mechanism to detect changes to -** a single attached database that occur due to other database connections, -** but omits changes implemented by the database connection on which it is -** called. This file control is the only mechanism to detect changes that -** happen either internally or externally and that are associated with -** a particular attached database. -** -**
  • [[SQLITE_FCNTL_CKPT_START]] -** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint -** in wal mode before the client starts to copy pages from the wal -** file to the database file. -** -**
  • [[SQLITE_FCNTL_CKPT_DONE]] -** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint -** in wal mode after the client has finished copying pages from the wal -** file to the database file, but before the *-shm file is updated to -** record the fact that the pages have been checkpointed. -** -**
  • [[SQLITE_FCNTL_EXTERNAL_READER]] -** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect -** whether or not there is a database client in another process with a wal-mode -** transaction open on the database or not. It is only available on unix.The -** (void*) argument passed with this file-control should be a pointer to a -** value of type (int). The integer value is set to 1 if the database is a wal -** mode database and there exists at least one client in another process that -** currently has an SQL transaction open on the database. It is set to 0 if -** the database is not a wal-mode db, or if there is no such connection in any -** other process. This opcode cannot be used to detect transactions opened -** by clients within the current process, only within other processes. -** -**
  • [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the -** [checksum VFS shim] only. -** -**
  • [[SQLITE_FCNTL_RESET_CACHE]] -** If there is currently no transaction open on the database, and the -** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control -** purges the contents of the in-memory page cache. If there is an open -** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. +** this opcode. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 @@ -1563,23 +2070,10 @@ #define SQLITE_FCNTL_RBU 26 #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 -#define SQLITE_FCNTL_LOCK_TIMEOUT 34 -#define SQLITE_FCNTL_DATA_VERSION 35 -#define SQLITE_FCNTL_SIZE_LIMIT 36 -#define SQLITE_FCNTL_CKPT_DONE 37 -#define SQLITE_FCNTL_RESERVE_BYTES 38 -#define SQLITE_FCNTL_CKPT_START 39 -#define SQLITE_FCNTL_EXTERNAL_READER 40 -#define SQLITE_FCNTL_CKSM_FILE 41 -#define SQLITE_FCNTL_RESET_CACHE 42 -#define SQLITE_FCNTL_NULL_IO 43 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO @@ -1605,50 +2099,24 @@ ** structure must be typedefed in order to work around compiler warnings ** on some platforms. */ typedef struct sqlite3_api_routines sqlite3_api_routines; -/* -** CAPI3REF: File Name -** -** Type [sqlite3_filename] is used by SQLite to pass filenames to the -** xOpen method of a [VFS]. It may be cast to (const char*) and treated -** as a normal, nul-terminated, UTF-8 buffer containing the filename, but -** may also be passed to special APIs such as: -** -** -*/ -typedef const char *sqlite3_filename; - /* ** CAPI3REF: OS Interface Object ** ** An instance of the sqlite3_vfs object defines the interface between ** the SQLite core and the underlying operating system. The "vfs" ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. ** -** 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 due to an oversight, the structure -** of the sqlite3_vfs object changed 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 increased. +** 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 szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of ** a pathname in this VFS. ** @@ -1679,18 +2147,18 @@ ** the string will be valid and unchanged until xClose() is ** called. Because of the previous sentence, ** the [sqlite3_file] can safely store a pointer to the ** filename if it needs to remember the filename for some reason. ** If the zFilename parameter to xOpen is a NULL pointer then xOpen -** must invent its own temporary name for the file. ^Whenever the +** must invent its own temporary name for the file. ^Whenever the ** xFilename parameter is NULL it will also be the case that the ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. ** ** The flags argument to xOpen() includes all bits set in ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] ** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. ** If xOpen() opens a file read-only then it sets *pOutFlags to ** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. ** ** ^(SQLite will also add one of the following flags to the xOpen() ** call, depending on the object being opened: @@ -1700,11 +2168,11 @@ **
  • [SQLITE_OPEN_MAIN_JOURNAL] **
  • [SQLITE_OPEN_TEMP_DB] **
  • [SQLITE_OPEN_TEMP_JOURNAL] **
  • [SQLITE_OPEN_TRANSIENT_DB] **
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_SUPER_JOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] **
  • [SQLITE_OPEN_WAL] ** )^ ** ** The file I/O implementation can use the object type flags to ** change the way it deals with files. For example, an application @@ -1728,18 +2196,18 @@ ** databases, and subjournals. ** ** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction ** with the [SQLITE_OPEN_CREATE] flag, which are both directly ** analogous to the O_EXCL and O_CREAT flags of the POSIX open() -** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the ** SQLITE_OPEN_CREATE, is used to indicate that file should always ** be created, and that it is an error if it already exists. -** It is not used to indicate the file should be opened +** It is not used to indicate the file should be opened ** for exclusive access. ** ** ^At least szOsFile bytes of memory are allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third +** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to ** allocate the structure; it should just fill it in. Note that ** the xOpen method must set the sqlite3_file.pMethods to either ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods @@ -1748,18 +2216,12 @@ ** ** [[sqlite3_vfs.xAccess]] ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test whether a file is at least readable. The SQLITE_ACCESS_READ -** flag is never actually used and is not implemented in the built-in -** VFSes of SQLite. The file is named by the second argument and can be a -** directory. The xAccess method returns [SQLITE_OK] on success or some -** non-zero error code if there is an I/O error or if the name of -** the file given in the second argument is illegal. If SQLITE_OK -** is returned, then non-zero or zero is written into *pResOut to indicate -** whether or not the file is accessible. +** to test whether a file is at least readable. The file can be a +** directory. ** ** ^SQLite will always allocate at least mxPathname+1 bytes for the ** output buffer xFullPathname. The exact size of the output buffer ** is also passed as a parameter to both methods. If the output buffer ** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is @@ -1775,20 +2237,20 @@ ** The xSleep() method causes the calling thread to sleep for at ** least the number of microseconds given. ^The xCurrentTime() ** method returns a Julian Day Number for the current date and time as ** a floating point value. ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian -** Day Number multiplied by 86400000 (the number of milliseconds in -** a 24-hour day). +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). ** ^SQLite will use the xCurrentTimeInt64() method to get the current -** date and time if that method is available (if iVersion is 2 or +** date and time if that method is available (if iVersion is 2 or ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** ** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided -** by some VFSes to facilitate testing of the VFS code. By overriding +** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can ** simulate faults and error conditions that would otherwise be difficult ** or impossible to induce. The set of system calls that can be overridden ** varies from one VFS to another, and from one version of the same VFS to the ** next. Applications that use these interfaces must be prepared for any @@ -1803,11 +2265,11 @@ int szOsFile; /* Size of subclassed sqlite3_file */ int mxPathname; /* Maximum file pathname length */ sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*, + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); @@ -1831,11 +2293,11 @@ sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. ** New fields may be appended in future versions. The iVersion - ** value will increment whenever this happens. + ** value will increment whenever this happens. */ }; /* ** CAPI3REF: Flags for the xAccess VFS method @@ -1875,11 +2337,11 @@ **
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED **
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE ** ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as -** was given on the corresponding lock. +** was given on the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED ** and EXCLUSIVE. */ @@ -1990,27 +2452,24 @@ ** ** The sqlite3_config() interface is not threadsafe. The application ** must ensure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running. ** +** The sqlite3_config() interface +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** ** The first argument to sqlite3_config() is an integer ** [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** -** For most configuration options, the sqlite3_config() interface -** may only be invoked prior to library initialization using -** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. -** The exceptional configuration options that may be invoked at any time -** are called "anytime configuration options". -** ^If sqlite3_config() is called after [sqlite3_initialize()] and before -** [sqlite3_shutdown()] with a first argument that is not an anytime -** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE. -** Note, however, that ^sqlite3_config() can be called as part of the -** implementation of an application-defined [sqlite3_os_init()]. -** ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(int, ...); @@ -2023,11 +2482,11 @@ ** changes to a [database connection]. The interface is similar to ** [sqlite3_config()] except that the changes apply to a single ** [database connection] (specified in the first argument). ** ** The second argument to sqlite3_db_config(D,V,...) is the -** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code ** that indicates what aspect of the [database connection] is being configured. ** Subsequent arguments vary depending on the configuration verb. ** ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. @@ -2041,11 +2500,11 @@ ** and low-level memory allocation routines. ** ** This object is used in only one place in the SQLite interface. ** A pointer to an instance of this object is the argument to ** [sqlite3_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. ** By creating an instance of this object ** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) ** during configuration, an application can specify an alternative ** memory allocation subsystem for SQLite to use for all of its ** dynamic memory needs. @@ -2071,21 +2530,21 @@ ** The xRoundup method returns what would be the allocated size of ** a memory allocation given a particular requested size. Most memory ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. ** Every memory allocation request coming in through [sqlite3_malloc()] -** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, ** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. For example, -** it might allocate any required mutexes or initialize internal data +** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. ** -** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes ** the xInit method, so the xInit method need not be threadsafe. The ** xShutdown method is only called from [sqlite3_shutdown()] so it does ** not need to be threadsafe either. For all other methods, SQLite ** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the ** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which @@ -2114,27 +2573,10 @@ ** KEYWORDS: {configuration option} ** ** These constants are the available integer configuration options that ** can be passed as the first argument to the [sqlite3_config()] interface. ** -** Most of the configuration options for sqlite3_config() -** will only work if invoked prior to [sqlite3_initialize()] or after -** [sqlite3_shutdown()]. The few exceptions to this rule are called -** "anytime configuration options". -** ^Calling [sqlite3_config()] with a first argument that is not an -** anytime configuration option in between calls to [sqlite3_initialize()] and -** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE. -** -** The set of anytime configuration options can change (by insertions -** and/or deletions) from one release of SQLite to the next. -** As of SQLite version 3.42.0, the complete set of anytime configuration -** options is: -** -** ** New configuration options may be added in future releases of SQLite. ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_config()] to make sure that ** the call worked. The [sqlite3_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option @@ -2146,11 +2588,11 @@ ** [threading mode] to Single-thread. In other words, it disables ** all mutexing and puts SQLite into a mode where it can only be used ** by a single thread. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to change the [threading mode] from its default -** value of Single-thread and so [sqlite3_config()] will return +** value of Single-thread and so [sqlite3_config()] will return ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD ** configuration option. ** ** [[SQLITE_CONFIG_MULTITHREAD]]
    SQLITE_CONFIG_MULTITHREAD
    **
    There are no arguments to this option. ^This option sets the @@ -2181,11 +2623,11 @@ ** it is not possible to set the Serialized [threading mode] and ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the ** SQLITE_CONFIG_SERIALIZED configuration option.
    ** ** [[SQLITE_CONFIG_MALLOC]]
    SQLITE_CONFIG_MALLOC
    -**
    ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is +**
    ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is ** a pointer to an instance of the [sqlite3_mem_methods] structure. ** The argument specifies ** alternative low-level memory allocation routines to be used in place of ** the memory allocation routines built into SQLite.)^ ^SQLite makes ** its own private copy of the content of the [sqlite3_mem_methods] structure @@ -2198,27 +2640,16 @@ ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation ** 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 ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: ** )^ @@ -2226,18 +2657,36 @@ ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory ** allocation statistics are disabled by default. **
    ** ** [[SQLITE_CONFIG_SCRATCH]]
    SQLITE_CONFIG_SCRATCH
    -**
    The SQLITE_CONFIG_SCRATCH option is no longer used. +**
    ^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. **

    ** ** [[SQLITE_CONFIG_PAGECACHE]]
    SQLITE_CONFIG_PAGECACHE
    **
    ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool ** that SQLite can use for the database page cache with the default page -** cache implementation. -** This configuration option is a no-op if an application-defined page +** cache implementation. +** This configuration option is a no-op if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to ** 8-byte aligned memory (pMem), the size of each page cache line (sz), ** and the number of cache lines (N). ** The sz argument should be the size of the largest database page @@ -2260,13 +2709,14 @@ ** page cache memory is needed beyond what is provided by the initial ** allocation, then SQLite goes to [sqlite3_malloc()] separately for each ** additional cache line.
    ** ** [[SQLITE_CONFIG_HEAP]]
    SQLITE_CONFIG_HEAP
    -**
    ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer +**
    ^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_PAGECACHE]. +** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and +** [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. ** ^There are three arguments to SQLITE_CONFIG_HEAP: ** An 8-byte aligned pointer to the memory, @@ -2315,11 +2765,11 @@ ** sets the default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] ** option to [sqlite3_db_config()] can be used to change the lookaside ** configuration on individual connections.)^
    ** ** [[SQLITE_CONFIG_PCACHE2]]
    SQLITE_CONFIG_PCACHE2
    -**
    ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is +**
    ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.
    ** ** [[SQLITE_CONFIG_GETPCACHE2]]
    SQLITE_CONFIG_GETPCACHE2
    @@ -2329,11 +2779,11 @@ ** ** [[SQLITE_CONFIG_LOG]]
    SQLITE_CONFIG_LOG
    **
    The SQLITE_CONFIG_LOG option is used to configure the SQLite ** global [error log]. ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,int,const char*), +** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger @@ -2438,95 +2888,48 @@ ** [PRAGMA cache_size] setting and this value. ** ** [[SQLITE_CONFIG_STMTJRNL_SPILL]] **
    SQLITE_CONFIG_STMTJRNL_SPILL **
    ^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which -** becomes the [statement journal] spill-to-disk threshold. +** becomes the [statement journal] spill-to-disk threshold. ** [Statement journals] are held in memory until their size (in bytes) ** exceeds this threshold, at which point they are written to disk. ** Or if the threshold is -1, statement journals are always held ** exclusively in memory. ** Since many statement journals never become large, setting the spill ** threshold to a value such as 64KiB can greatly reduce the amount of ** I/O required to support statement rollback. ** The default value for this setting is controlled by the ** [SQLITE_STMTJRNL_SPILL] compile-time option. -** -** [[SQLITE_CONFIG_SORTERREF_SIZE]] -**
    SQLITE_CONFIG_SORTERREF_SIZE -**
    The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter -** of type (int) - the new value of the sorter-reference size threshold. -** Usually, when SQLite uses an external sort to order records according -** to an ORDER BY clause, all fields required by the caller are present in the -** sorted records. However, if SQLite determines based on the declared type -** of a table column that its values are likely to be very large - larger -** than the configured sorter-reference size threshold - then a reference -** is stored in each sorted record and the required column values loaded -** from the database as records are returned in sorted order. The default -** value for this option is to never use this optimization. Specifying a -** negative value for this option restores the default behavior. -** This option is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. -** -** [[SQLITE_CONFIG_MEMDB_MAXSIZE]] -**
    SQLITE_CONFIG_MEMDB_MAXSIZE -**
    The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter -** [sqlite3_int64] parameter which is the default maximum size for an in-memory -** database created using [sqlite3_deserialize()]. This default maximum -** size can be adjusted up or down for individual databases using the -** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this -** configuration setting is never used, then the default maximum is determined -** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that -** compile-time option is not set, then the default maximum is 1073741824. -** -** [[SQLITE_CONFIG_ROWID_IN_VIEW]] -**
    SQLITE_CONFIG_ROWID_IN_VIEW -**
    The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability -** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is -** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability -** defaults to on. This configuration option queries the current setting or -** changes the setting to off or on. The argument is a pointer to an integer. -** If that integer initially holds a value of 1, then the ability for VIEWs to -** have ROWIDs is activated. If the integer initially holds zero, then the -** ability is deactivated. Any other initial value for the integer leaves the -** setting unchanged. After changes, if any, the integer is written with -** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite -** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and -** recommended case) then the integer is always filled with zero, regardless -** if its initial value. ** */ -#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ -#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ -#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 /* 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 */ -#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ -#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ -/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ -#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ -#define SQLITE_CONFIG_PCACHE 14 /* no-op */ -#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ -#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ -#define SQLITE_CONFIG_URI 17 /* int */ -#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ -#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#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_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ -#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ -#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ +#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #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 */ -#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ -#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ -#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that @@ -2538,18 +2941,13 @@ ** the call worked. ^The [sqlite3_db_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** **
    -** [[SQLITE_DBCONFIG_LOOKASIDE]] **
    SQLITE_DBCONFIG_LOOKASIDE
    -**
    The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the -** configuration of the lookaside memory allocator within a database -** connection. -** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are not -** in the [DBCONFIG arguments|usual format]. -** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two. +**
    ^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. ** ^The first argument (the third parameter to [sqlite3_db_config()] is a ** pointer to a memory buffer to use for lookaside memory. ** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb ** may be NULL in which case SQLite will allocate the ** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the @@ -2560,82 +2958,54 @@ ** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally ** rounded down to the next smaller multiple of 8. ^(The lookaside memory ** configuration for a database connection can only be changed when that ** connection is not currently using lookaside memory, or in other words ** when the "current value" returned by -** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero. +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. ** Any attempt to change the lookaside memory configuration when lookaside -** memory is in use leaves the configuration unchanged and returns +** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^
    ** -** [[SQLITE_DBCONFIG_ENABLE_FKEY]] **
    SQLITE_DBCONFIG_ENABLE_FKEY
    **
    ^This option is used to enable or disable the enforcement of -** [foreign key constraints]. This is the same setting that is -** enabled or disabled by the [PRAGMA foreign_keys] statement. +** [foreign key constraints]. There should be two additional arguments. ** The first argument is an integer which is 0 to disable FK enforcement, ** positive to enable FK enforcement or negative to leave FK enforcement ** unchanged. The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether FK enforcement is off or on ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back.
    ** -** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] **
    SQLITE_DBCONFIG_ENABLE_TRIGGER
    **
    ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in -** which case the trigger setting is not reported back. -** -**

    Originally this option disabled all triggers. ^(However, since -** SQLite version 3.35.0, TEMP triggers are still allowed even if -** this option is off. So, in other words, this option now only disables -** triggers in the main database schema or in the schemas of [ATTACH]-ed -** databases.)^

    -** -** [[SQLITE_DBCONFIG_ENABLE_VIEW]] -**
    SQLITE_DBCONFIG_ENABLE_VIEW
    -**
    ^This option is used to enable or disable [CREATE VIEW | views]. -** There must be two additional arguments. -** The first argument is an integer which is 0 to disable views, -** positive to enable views or negative to leave the setting unchanged. -** The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether views are disabled or enabled -** following this call. The second parameter may be a NULL pointer, in -** which case the view setting is not reported back. -** -**

    Originally this option disabled all views. ^(However, since -** SQLite version 3.35.0, TEMP views are still allowed even if -** this option is off. So, in other words, this option now only disables -** views in the main database schema or in the schemas of ATTACH-ed -** databases.)^

    -** -** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] +** which case the trigger setting is not reported back.
    +** **
    SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
    -**
    ^This option is used to enable or disable the -** [fts3_tokenizer()] function which is part of the +**
    ^This option is used to enable or disable the two-argument +** version of the [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. -** There must be two additional arguments. +** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or ** positive to enable fts3_tokenizer() or negative to leave the setting ** unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back.
    ** -** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] **
    SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
    **
    ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. -** There must be two additional arguments. +** There should be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. ** If the first argument is -1, then no changes are made to state of either the ** C-API or the SQL function. @@ -2643,310 +3013,53 @@ ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may ** be a NULL pointer, in which case the new setting is not reported back. **
    ** -** [[SQLITE_DBCONFIG_MAINDBNAME]]
    SQLITE_DBCONFIG_MAINDBNAME
    +**
    SQLITE_DBCONFIG_MAINDBNAME
    **
    ^This option is used to change the name of the "main" database -** schema. This option does not follow the -** [DBCONFIG arguments|usual SQLITE_DBCONFIG argument format]. -** This option takes exactly one argument, which ust be a pointer -** to a constant UTF8 string which will become the new schema name -** in place of "main". ^SQLite does not make a copy of the new main -** schema name string, so the application must ensure that the argument -** passed into SQLITE_DBCONFIG MAINDBNAME is unchanged +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged ** until after the database connection closes. **
    ** -** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] **
    SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
    -**
    Usually, when a database in [WAL mode] is closed or detached from a -** database handle, SQLite checks if if there are other connections to the -** same database, and if there are no other database connection (if the -** connection being closed is the last open connection to the database), -** then SQLite performs a [checkpoint] before closing the connection and -** deletes the WAL file. The SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE option can -** be used to override that behavior. The first parameter passed to this -** operation is an integer - positive to disable checkpoints-on-close, or -** zero (the default) to enable them, and negative to leave the setting unchanged. -** The second parameter is a pointer to an integer +**
    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]]
    SQLITE_DBCONFIG_ENABLE_QPSG
    +**
    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. -** The first argument to this setting is an integer which is 0 to disable -** the QPSG, positive to enable QPSG, or negative to leave the setting -** unchanged. The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether the QPSG is disabled or enabled -** following this call. -**
    -** -** [[SQLITE_DBCONFIG_TRIGGER_EQP]]
    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 - -** positive to enable output for trigger programs, or zero to disable it, -** or negative to leave the setting unchanged. -** 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. -**
    -** -** [[SQLITE_DBCONFIG_RESET_DATABASE]]
    SQLITE_DBCONFIG_RESET_DATABASE
    -**
    Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run -** [VACUUM] in order to reset a database back to an empty database -** with no schema and no content. The following process works even for -** a badly corrupted database file: -**
      -**
    1. If the database connection is newly opened, make sure it has read the -** database schema by preparing then discarding some query against the -** database, or calling sqlite3_table_column_metadata(), ignoring any -** errors. This step is only necessary if the application desires to keep -** the database in WAL mode after the reset if it was in WAL mode before -** the reset. -**
    2. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); -**
    3. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); -**
    4. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); -**
    -** Because resetting a database is destructive and irreversible, the -** process requires the use of this obscure API and multiple steps to -** help ensure that it does not happen by accident. Because this -** feature must be capable of resetting corrupt databases, and -** shutting down virtual tables may require access to that corrupt -** storage, the library must abandon any installed virtual tables -** without calling their xDestroy() methods. -** -** [[SQLITE_DBCONFIG_DEFENSIVE]]
    SQLITE_DBCONFIG_DEFENSIVE
    -**
    The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the -** "defensive" flag for a database connection. When the defensive -** flag is enabled, language features that allow ordinary SQL to -** deliberately corrupt the database file are disabled. The disabled -** features include but are not limited to the following: -** -**
    -** -** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]]
    SQLITE_DBCONFIG_WRITABLE_SCHEMA
    -**
    The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the -** "writable_schema" flag. This has the same effect and is logically equivalent -** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF]. -** The first argument to this setting is an integer which is 0 to disable -** the writable_schema, positive to enable writable_schema, or negative to -** leave the setting unchanged. The second parameter is a pointer to an -** integer into which is written 0 or 1 to indicate whether the writable_schema -** is enabled or disabled following this call. -**
    -** -** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] -**
    SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
    -**
    The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates -** the legacy behavior of the [ALTER TABLE RENAME] command such it -** behaves as it did prior to [version 3.24.0] (2018-06-04). See the -** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for -** additional information. This feature can also be turned on and off -** using the [PRAGMA legacy_alter_table] statement. -**
    -** -** [[SQLITE_DBCONFIG_DQS_DML]] -**
    SQLITE_DBCONFIG_DQS_DML
    -**
    The SQLITE_DBCONFIG_DQS_DML option activates or deactivates -** the legacy [double-quoted string literal] misfeature for DML statements -** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The -** default value of this setting is determined by the [-DSQLITE_DQS] -** compile-time option. -**
    -** -** [[SQLITE_DBCONFIG_DQS_DDL]] -**
    SQLITE_DBCONFIG_DQS_DDL
    -**
    The SQLITE_DBCONFIG_DQS option activates or deactivates -** the legacy [double-quoted string literal] misfeature for DDL statements, -** such as CREATE TABLE and CREATE INDEX. The -** default value of this setting is determined by the [-DSQLITE_DQS] -** compile-time option. -**
    -** -** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] -**
    SQLITE_DBCONFIG_TRUSTED_SCHEMA
    -**
    The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to -** assume that database schemas are untainted by malicious content. -** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite -** takes additional defensive steps to protect the application from harm -** including: -** -** This setting defaults to "on" for legacy compatibility, however -** all applications are advised to turn it off if possible. This setting -** can also be controlled using the [PRAGMA trusted_schema] statement. -**
    -** -** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] -**
    SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
    -**
    The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates -** the legacy file format flag. When activated, this flag causes all newly -** created database file to have a schema format version number (the 4-byte -** integer found at offset 44 into the database header) of 1. This in turn -** means that the resulting database file will be readable and writable by -** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, -** newly created databases are generally not understandable by SQLite versions -** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there -** is now scarcely any need to generate database files that are compatible -** all the way back to version 3.0.0, and so this setting is of little -** practical use, but is provided so that SQLite can continue to claim the -** ability to generate new database files that are compatible with version -** 3.0.0. -**

    Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on, -** the [VACUUM] command will fail with an obscure error when attempting to -** process a table with generated columns and a descending index. This is -** not considered a bug since SQLite versions 3.3.0 and earlier do not support -** either generated columns or descending indexes. -**

    -** -** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] -**
    SQLITE_DBCONFIG_STMT_SCANSTATUS
    -**
    The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears -** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() -** statistics. For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is prepared and when it -** is stepped. The flag is set (collection of statistics is enabled) -** by default.

    This option takes two arguments: an integer and a pointer to -** an integer.. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the statement scanstatus option. If the second argument -** is not NULL, then the value of the statement scanstatus setting after -** processing the first argument is written into the integer that the second -** argument points to. -**

    -** -** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]] -**
    SQLITE_DBCONFIG_REVERSE_SCANORDER
    -**
    The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order -** in which tables and indexes are scanned so that the scans start at the end -** and work toward the beginning rather than starting at the beginning and -** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the -** same as setting [PRAGMA reverse_unordered_selects].

    This option takes -** two arguments which are an integer and a pointer to an integer. The first -** argument is 1, 0, or -1 to enable, disable, or leave unchanged the -** reverse scan order flag, respectively. If the second argument is not NULL, -** then 0 or 1 is written into the integer that the second argument points to -** depending on if the reverse scan order flag is set after processing the -** first argument. -**

    -** -** [[SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]] -**
    SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE
    -**
    The SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE option enables or disables -** the ability of the [ATTACH DATABASE] SQL command to create a new database -** file if the database filed named in the ATTACH command does not already -** exist. This ability of ATTACH to create a new database is enabled by -** default. Applications can disable or reenable the ability for ATTACH to -** create new database files using this DBCONFIG option.

    -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the attach-create flag, respectively. If the second -** argument is not NULL, then 0 or 1 is written into the integer that the -** second argument points to depending on if the attach-create flag is set -** after processing the first argument. -**

    -** -** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]] -**
    SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE
    -**
    The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the -** ability of the [ATTACH DATABASE] SQL command to open a database for writing. -** This capability is enabled by default. Applications can disable or -** reenable this capability using the current DBCONFIG option. If the -** the this capability is disabled, the [ATTACH] command will still work, -** but the database will be opened read-only. If this option is disabled, -** then the ability to create a new database using [ATTACH] is also disabled, -** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE] -** option.

    -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the ability to ATTACH another database for writing, -** respectively. If the second argument is not NULL, then 0 or 1 is written -** into the integer to which the second argument points, depending on whether -** the ability to ATTACH a read/write database is enabled or disabled -** after processing the first argument. -**

    -** -** [[SQLITE_DBCONFIG_ENABLE_COMMENTS]] -**
    SQLITE_DBCONFIG_ENABLE_COMMENTS
    -**
    The SQLITE_DBCONFIG_ENABLE_COMMENTS option enables or disables the -** ability to include comments in SQL text. Comments are enabled by default. -** An application can disable or reenable comments in SQL text using this -** DBCONFIG option.

    -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the ability to use comments in SQL text, -** respectively. If the second argument is not NULL, then 0 or 1 is written -** into the integer that the second argument points to depending on if -** comments are allowed in SQL text after processing the first argument. **

    ** ** -** -** [[DBCONFIG arguments]]

    Arguments To SQLITE_DBCONFIG Options

    -** -**

    Most of the SQLITE_DBCONFIG options take two arguments: an integer -** and a pointer to an integer. If the first integer argument is 1, then -** the option becomes enabled. If the first integer argument is 0, then the -** option is disabled. If the first argument is -1, then the option setting -** is unchanged. The second argument, the pointer to an integer, may be NULL. -** If the second argument is not NULL, then a value of 0 or 1 is written into -** the integer to which the second argument points, depending on whether the -** setting is disabled or enabled after applying any changes specified by -** the first argument. -** -**

    While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] -** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the -** documentation of those exceptional options for details. */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #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_RESET_DATABASE 1009 /* int int* */ -#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ -#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ -#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ -#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ -#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ -#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ -#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */ -#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */ -#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ + /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 ** @@ -2969,30 +3082,30 @@ ** is another alias for the rowid. ** ** ^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 +** 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 +** 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 +** 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 +** ^(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 ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, @@ -3021,122 +3134,91 @@ /* ** 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 +** 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 ** -** ^These functions return the number of rows modified, inserted or +** ^This function returns the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE ** statement on the database connection specified by the only parameter. -** The two functions are identical except for the type of the return value -** and that if the number of rows modified by the most recent INSERT, UPDATE, -** or DELETE is greater than the maximum value supported by type "int", then -** the return value of sqlite3_changes() is undefined. ^Executing any other -** type of SQL statement does not modify the value returned by these functions. -** For the purposes of this interface, a CREATE TABLE AS SELECT statement -** does not count as an INSERT, UPDATE or DELETE statement and hence the rows -** added to the new table by the CREATE TABLE AS SELECT statement are not -** counted. +** ^Executing any other type of SQL statement does not modify the value +** returned by this function. ** ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are -** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], +** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], ** [foreign key actions] or [REPLACE] constraint resolution are not counted. -** -** Changes to a view that are intercepted by -** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value -** returned by sqlite3_changes() immediately after an INSERT, UPDATE or -** DELETE statement run on a view is always zero. Only changes made to real +** +** Changes to a view that are intercepted by +** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value +** returned by sqlite3_changes() immediately after an INSERT, UPDATE or +** DELETE statement run on a view is always zero. Only changes made to real ** tables are counted. ** ** Things are more complicated if the sqlite3_changes() function is ** executed while a trigger program is running. This may happen if the ** program uses the [changes() SQL function], or if some other callback ** function invokes sqlite3_changes() directly. Essentially: -** +** **

    -** +** ** ^This means that if the changes() SQL function (or similar) is used -** by the first INSERT, UPDATE or DELETE statement within a trigger, it +** by the first INSERT, UPDATE or DELETE statement within a trigger, it ** returns the value as set when the calling statement began executing. -** ^If it is used by the second or subsequent such statement within a trigger -** program, the value returned reflects the number of rows modified by the +** ^If it is used by the second or subsequent such statement within a trigger +** program, the value returned reflects the number of rows modified by the ** previous INSERT, UPDATE or DELETE statement within the same trigger. ** +** See also the [sqlite3_total_changes()] interface, the +** [count_changes pragma], and the [changes() SQL function]. +** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. -** -** See also: -** */ SQLITE_API int sqlite3_changes(sqlite3*); -SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** -** ^These functions return the total number of rows inserted, modified or +** ^This function returns the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed ** since the database connection was opened, including those executed as -** part of trigger programs. The two functions are identical except for the -** type of the return value and that if the number of rows modified by the -** connection exceeds the maximum value supported by type "int", then -** the return value of sqlite3_total_changes() is undefined. ^Executing -** any other type of SQL statement does not affect the value returned by -** sqlite3_total_changes(). -** +** part of trigger programs. ^Executing any other type of SQL statement +** does not affect the value returned by sqlite3_total_changes(). +** ** ^Changes made as part of [foreign key actions] are included in the ** count, but those made as part of REPLACE constraint resolution are -** not. ^Changes to a view that are intercepted by INSTEAD OF triggers +** not. ^Changes to a view that are intercepted by INSTEAD OF triggers ** are not counted. -** -** The [sqlite3_total_changes(D)] interface only reports the number -** of rows that changed due to SQL statement run against database -** connection D. Any changes by other database connections are ignored. -** To detect changes against a database file from other database -** connections use the [PRAGMA data_version] command or the -** [SQLITE_FCNTL_DATA_VERSION] [file control]. +** +** See also the [sqlite3_changes()] interface, the +** [count_changes pragma], and the [total_changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. -** -** See also: -** */ SQLITE_API int sqlite3_total_changes(sqlite3*); -SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** @@ -3160,25 +3242,20 @@ ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** ** ^The sqlite3_interrupt(D) call is in effect until all currently running ** SQL statements on [database connection] D complete. ^Any new SQL statements -** that are started after the sqlite3_interrupt() call and before the -** running statement count reaches zero are interrupted as if they had been +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^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. -** -** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether -** or not an interrupt is currently in effect for [database connection] D. -** It returns 1 if an interrupt is currently in effect, or 0 otherwise. */ SQLITE_API void sqlite3_interrupt(sqlite3*); -SQLITE_API int sqlite3_is_interrupted(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete ** ** These routines are useful during command-line input to determine if the @@ -3197,11 +3274,11 @@ ** memory allocation fails, then SQLITE_NOMEM is returned. ** ** ^These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. ** -** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked ** automatically by sqlite3_complete16(). If that initialization fails, ** then the return value from sqlite3_complete16() will be non-zero ** regardless of whether or not the input SQL is complete.)^ ** @@ -3242,11 +3319,11 @@ ** is made to access the database and the cycle repeats. ** ** The presence of a busy handler does not guarantee that it will be invoked ** when there is lock contention. ^If SQLite determines that invoking the busy ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] -** to the application instead of invoking the +** to the application instead of invoking the ** busy handler. ** Consider a scenario where one process is holding a read lock that ** it is trying to promote to a reserved lock and ** a second process is holding a reserved lock that it is trying ** to promote to an exclusive lock. The first process cannot proceed @@ -3267,11 +3344,11 @@ ** ** The busy callback should not take any actions which modify the ** database connection that invoked the busy handler. In other words, ** the busy handler is not reentrant. Any such actions ** result in undefined behavior. -** +** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); @@ -3334,13 +3411,13 @@ ** Alice | 43 ** Bob | 28 ** Cindy | 21 ** ** -** There are two columns (M==2) and three rows (N==3). Thus the +** There are two column (M==2) and three rows (N==3). Thus the ** result table has 8 entries. Suppose the result table is stored -** in an array named azResult. Then azResult holds this content: +** in an array names azResult. Then azResult holds this content: ** **
     **        azResult[0] = "Name";
     **        azResult[1] = "Age";
     **        azResult[2] = "Alice";
    @@ -3384,20 +3461,20 @@
     /*
     ** CAPI3REF: Formatted String Printing Functions
     **
     ** These routines are work-alikes of the "printf()" family of functions
     ** from the standard C library.
    -** These routines understand most of the common formatting options from
    -** the standard library printf()
    -** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
    -** See the [built-in printf()] documentation for details.
    +** These routines understand most of the common K&R formatting options,
    +** plus some additional non-standard formats, detailed below.
    +** Note that some of the more obscure formatting options from recent
    +** C-library standards are omitted from this implementation.
     **
     ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
    -** results into memory obtained from [sqlite3_malloc64()].
    +** results into memory obtained from [sqlite3_malloc()].
     ** The strings returned by these two routines should be
     ** released by [sqlite3_free()].  ^Both routines return a
    -** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
    +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
     ** memory to hold the resulting string.
     **
     ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
     ** the standard C library.  The result is written into the
     ** buffer supplied as the second parameter whose size is given by
    @@ -3417,11 +3494,75 @@
     ** the zero terminator.  So the longest string that can be completely
     ** written will be n-1 characters.
     **
     ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
     **
    -** See also:  [built-in printf()], [printf() SQL function]
    +** These routines all implement some additional formatting
    +** options that are useful for constructing SQL statements.
    +** All of the usual printf() formatting options apply.  In addition, there
    +** is are "%q", "%Q", "%w" and "%z" options.
    +**
    +** ^(The %q option works like %s in that it substitutes a nul-terminated
    +** string from the argument list.  But %q also doubles every '\'' character.
    +** %q is designed for use inside a string literal.)^  By doubling each '\''
    +** character it escapes that character and allows it to be inserted into
    +** the string.
    +**
    +** For example, assume the string variable zText contains text as follows:
    +**
    +** 
    +**  char *zText = "It's a happy day!";
    +** 
    +** +** One can use this text in an SQL statement as follows: +** +**
    +**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
    +**  sqlite3_exec(db, zSQL, 0, 0, 0);
    +**  sqlite3_free(zSQL);
    +** 
    +** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
    +**  INSERT INTO table1 VALUES('It''s a happy day!')
    +** 
    +** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
    +**  INSERT INTO table1 VALUES('It's a happy day!');
    +** 
    +** +** This second example is an SQL syntax error. As a general rule you should +** always use %q instead of %s when inserting text into a string literal. +** +** ^(The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes).)^ So, for example, one could say: +** +**
    +**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
    +**  sqlite3_exec(db, zSQL, 0, 0, 0);
    +**  sqlite3_free(zSQL);
    +** 
    +** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** ^(The "%w" formatting option is like "%q" except that it expects to +** be contained within double-quotes instead of single quotes, and it +** escapes the double-quote character instead of the single-quote +** character.)^ The "%w" formatting option is intended for safely inserting +** table and column names into a constructed SQL statement. +** +** ^(The "%z" formatting option works like "%s" but with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string.)^ */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); @@ -3429,11 +3570,11 @@ /* ** CAPI3REF: Memory Allocation Subsystem ** ** The SQLite core uses these three routines for all of its own ** internal memory allocation needs. "Core" in the previous sentence -** does not include operating-system specific [VFS] implementation. The +** does not include operating-system specific VFS implementation. The ** Windows VFS uses native malloc() and free() for some operations. ** ** ^The sqlite3_malloc() routine returns a pointer to a block ** of memory at least N bytes in length, where N is the parameter. ** ^If sqlite3_malloc() is unable to obtain sufficient free @@ -3489,10 +3630,23 @@ ** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), ** sqlite3_malloc64(), and sqlite3_realloc64() ** is always aligned to at least an 8 byte boundary, or to a ** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time ** option is used. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be used. +** +** Prior to SQLite version 3.7.10, the Windows OS interface layer called +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular Windows +** installation. Memory allocation errors were detected, but +** they were reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] ** must be either NULL or else pointers obtained from a prior ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. @@ -3538,11 +3692,11 @@ ** CAPI3REF: Pseudo-Random Number Generator ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to ** select random [ROWID | ROWIDs] when inserting new records into a table that ** already uses the largest possible [ROWID]. The PRNG is also used for -** the built-in random() and randomblob() SQL functions. This interface allows +** the build-in random() and randomblob() SQL functions. This interface allows ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. ** ^The P parameter can be a NULL pointer. ** @@ -3581,11 +3735,11 @@ ** ** When the callback returns [SQLITE_OK], that means the operation ** requested is ok. ^When the callback returns [SQLITE_DENY], the ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that -** access is denied. +** access is denied. ** ** ^The first parameter to the authorizer callback is a copy of the third ** parameter to the sqlite3_set_authorizer() interface. ^The second parameter ** to the callback is an integer [SQLITE_COPY | action code] that specifies ** the particular action to be authorized. ^The third through sixth parameters @@ -3634,11 +3788,11 @@ ** the database connection that invoked the authorizer callback. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the -** statement might be re-prepared during [sqlite3_step()] due to a +** statement might be re-prepared during [sqlite3_step()] due to a ** schema change. Hence, the application should ensure that the ** correct authorizer callback remains in place during the [sqlite3_step()]. ** ** ^Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not @@ -3721,12 +3875,12 @@ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* -** CAPI3REF: Deprecated Tracing And Profiling Functions -** DEPRECATED +** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 ** ** These routines are deprecated. Use the [sqlite3_trace_v2()] interface ** instead of the routines described here. ** ** These routines register callback functions that can be used for @@ -3748,13 +3902,13 @@ ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite -** might provide greater resolution on the profiler callback. Invoking -** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the -** profile callback. +** might provide greater resolution on the profiler callback. The +** sqlite3_profile() function is considered experimental and is +** subject to change in future versions of SQLite. */ SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); @@ -3762,12 +3916,12 @@ /* ** CAPI3REF: SQL Trace Event Codes ** KEYWORDS: SQLITE_TRACE ** ** These constants identify classes of events that can be monitored -** 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 +** using the [sqlite3_trace_v2()] tracing logic. The third argument +** to [sqlite3_trace_v2()] 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. ** ** New tracing constants may be added in future releases. ** @@ -3782,27 +3936,27 @@ **
    ^An SQLITE_TRACE_STMT callback is invoked when a prepared statement ** first begins running and possibly at other times during the ** execution of the prepared statement, such as at the start of each ** trigger subprogram. ^The P argument is a pointer to the ** [prepared statement]. ^The X argument is a pointer to a string which -** is the unexpanded SQL text of the prepared statement or an SQL comment +** is the unexpanded SQL text of the prepared statement or an SQL comment ** that indicates the invocation of a trigger. ^The callback can compute ** the same text that would have been returned by the legacy [sqlite3_trace()] ** interface by using the X argument when X begins with "--" and invoking ** [sqlite3_expanded_sql(P)] otherwise. ** ** [[SQLITE_TRACE_PROFILE]]
    SQLITE_TRACE_PROFILE
    **
    ^An SQLITE_TRACE_PROFILE callback provides approximately the same ** information as is provided by the [sqlite3_profile()] callback. ** ^The P argument is a pointer to the [prepared statement] and the -** X argument points to a 64-bit integer which is approximately -** the number of nanoseconds that the prepared statement took to run. +** X argument points to a 64-bit integer which is the estimated of +** the number of nanosecond that the prepared statement took to run. ** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. ** ** [[SQLITE_TRACE_ROW]]
    SQLITE_TRACE_ROW
    **
    ^An SQLITE_TRACE_ROW callback is invoked whenever a prepared -** statement generates a single row of result. +** statement generates a single row of result. ** ^The P argument is a pointer to the [prepared statement] and the ** X argument is unused. ** ** [[SQLITE_TRACE_CLOSE]]
    SQLITE_TRACE_CLOSE
    **
    ^An SQLITE_TRACE_CLOSE callback is invoked when a database @@ -3825,16 +3979,14 @@ ** and context pointer P. ^If the X callback is ** NULL or if the M mask is zero, then tracing is disabled. The ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** -** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P) -** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or -** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each -** database connection may have at most one trace callback. +** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides +** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). ** -** ^The X callback is invoked whenever any of the events identified by +** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently ** ignored, though this may change in future releases. Callback ** implementations should return zero to ensure future compatibility. ** ** ^A trace callback is invoked with four arguments: callback(T,C,P,X). @@ -3858,16 +4010,16 @@ ** CAPI3REF: Query Progress Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to -** [sqlite3_step()] and [sqlite3_prepare()] and similar for +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** -** ^The parameter P is passed through as the only parameter to the -** callback function X. ^The parameter N is the approximate number of +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the approximate number of ** [virtual machine instructions] that are evaluated between successive ** invocations of the callback X. ^If N is less than one then the progress ** handler is disabled. ** ** ^Only a single progress handler may be defined at one time per @@ -3883,25 +4035,18 @@ ** The progress handler callback must not do anything that will modify ** the database connection that invoked the progress handler. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** -** The progress handler callback would originally only be invoked from the -** bytecode engine. It still might be invoked during [sqlite3_prepare()] -** and similar because those routines might force a reparse of the schema -** which involves running the bytecode engine. However, beginning with -** SQLite version 3.41.0, the progress handler callback might also be -** invoked directly from [sqlite3_prepare()] while analyzing and generating -** code for complex queries. */ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection ** CONSTRUCTOR: sqlite3 ** -** ^These routines open an SQLite database file as specified by the +** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte ** order for sqlite3_open16(). ^(A [database connection] handle is usually ** returned in *ppDb, even if an error occurs. The only exception is that ** if SQLite is unable to allocate memory to hold the [sqlite3] object, @@ -3921,97 +4066,47 @@ ** passing it to [sqlite3_close()] when it is no longer required. ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. ^(The flags parameter to -** sqlite3_open_v2() must include, at a minimum, one of the following -** three flag combinations:)^ +** sqlite3_open_v2() can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ ** **
    ** ^(
    [SQLITE_OPEN_READONLY]
    -**
    The database is opened in read-only mode. If the database does -** not already exist, an error is returned.
    )^ +**
    The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
    )^ ** ** ^(
    [SQLITE_OPEN_READWRITE]
    -**
    The database is opened for reading and writing if possible, or -** reading only if the file is write protected by the operating -** system. In either case the database must already exist, otherwise -** an error is returned. For historical reasons, if opening in -** read-write mode fails due to OS-level permissions, an attempt is -** made to open it in read-only mode. [sqlite3_db_readonly()] can be -** used to determine whether the database is actually -** read-write.
    )^ +**
    The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
    )^ ** ** ^(
    [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
    **
    The database is opened for reading and writing, and is created if ** it does not already exist. This is the behavior that is always used for ** sqlite3_open() and sqlite3_open16().
    )^ **
    ** -** In addition to the required flags, the following optional flags are -** also supported: -** -**
    -** ^(
    [SQLITE_OPEN_URI]
    -**
    The filename can be interpreted as a URI if this flag is set.
    )^ -** -** ^(
    [SQLITE_OPEN_MEMORY]
    -**
    The database will be opened as an in-memory database. The database -** is named by the "filename" argument for the purposes of cache-sharing, -** if shared cache mode is enabled, but the "filename" is otherwise ignored. -**
    )^ -** -** ^(
    [SQLITE_OPEN_NOMUTEX]
    -**
    The new database connection will use the "multi-thread" -** [threading mode].)^ This means that separate threads are allowed -** to use SQLite at the same time, as long as each thread is using -** a different [database connection]. -** -** ^(
    [SQLITE_OPEN_FULLMUTEX]
    -**
    The new database connection will use the "serialized" -** [threading mode].)^ This means the multiple threads can safely -** attempt to use the same database connection at the same time. -** (Mutexes will block any actual concurrency, but in this mode -** there is no harm in trying.) -** -** ^(
    [SQLITE_OPEN_SHAREDCACHE]
    -**
    The database is opened [shared cache] enabled, overriding -** the default shared cache setting provided by -** [sqlite3_enable_shared_cache()].)^ -** The [use of shared cache mode is discouraged] and hence shared cache -** capabilities may be omitted from many builds of SQLite. In such cases, -** this option is a no-op. -** -** ^(
    [SQLITE_OPEN_PRIVATECACHE]
    -**
    The database is opened [shared cache] disabled, overriding -** the default shared cache setting provided by -** [sqlite3_enable_shared_cache()].)^ -** -** [[OPEN_EXRESCODE]] ^(
    [SQLITE_OPEN_EXRESCODE]
    -**
    The database connection comes up in "extended result code mode". -** In other words, the database behaves as if -** [sqlite3_extended_result_codes(db,1)] were called on the database -** connection as soon as the connection is created. In addition to setting -** the extended result code mode, this flag also causes [sqlite3_open_v2()] -** to return an extended result code.
    -** -** [[OPEN_NOFOLLOW]] ^(
    [SQLITE_OPEN_NOFOLLOW]
    -**
    The database filename is not allowed to contain a symbolic link
    -**
    )^ -** ** If the 3rd parameter to sqlite3_open_v2() is not one of the -** required combinations shown above optionally combined with other +** combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] -** then the behavior is undefined. Historic versions of SQLite -** have silently ignored surplus bits in the flags parameter to -** sqlite3_open_v2(), however that behavior might not be carried through -** into future versions of SQLite and so applications should not rely -** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op -** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause -** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE -** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not -** by sqlite3_open_v2(). +** then the behavior is undefined. +** +** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. ^If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. ^The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. @@ -4031,30 +4126,30 @@ ** [[URI filenames in sqlite3_open()]]

    URI Filenames

    ** ** ^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 third argument to sqlite3_open_v2(), or if it has +** set in the fourth 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. -** URI filename interpretation is turned off +** As of SQLite version 3.7.7, 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. ** ** URI filenames are parsed according to RFC 3986. ^If the URI contains an -** authority, then it must be either an empty string or the string -** "localhost". ^If the authority is not an empty string or "localhost", an -** error is returned to the caller. ^The fragment component of a URI, if +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file -** which contains the database. ^If the path begins with a '/' character, -** then it is interpreted as an absolute path. ^If the path does not begin +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) -** then the path is interpreted as a relative path. -** ^(On windows, the first component of an absolute path +** then the path is interpreted as a relative path. +** ^(On windows, the first component of an absolute path ** is a drive specification (e.g. "C:").)^ ** ** [[core URI query parameters]] ** The query component of a URI may contain parameters that are interpreted ** either by SQLite itself, or by a [VFS | custom VFS implementation]. @@ -4070,27 +4165,27 @@ ** present, then the VFS specified by the option takes precedence over ** the value passed as the fourth parameter to sqlite3_open_v2(). ** **
  • mode: ^(The mode parameter may be set to either "ro", "rw", ** "rwc", or "memory". Attempting to set it to any other value is -** an error)^. -** ^If "ro" is specified, then the database is opened for read-only -** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the -** third argument to sqlite3_open_v2(). ^If the mode option is set to -** "rw", then the database is opened for read-write (but not create) -** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had -** been set. ^Value "rwc" is equivalent to setting both +** an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_open_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both ** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is ** set to "memory" then a pure [in-memory database] that never reads ** or writes from disk is used. ^It is an error to specify a value for ** the mode parameter that is less restrictive than that specified by ** the flags passed in the third parameter to sqlite3_open_v2(). ** **
  • cache: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to -** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** @@ -4112,11 +4207,11 @@ ** privilege, and so the database is opened read-only and all locking ** and change detection is disabled. Caution: Setting the immutable ** property on a database file that does in fact change can result ** in incorrect query results and/or [SQLITE_CORRUPT] errors. ** See also: [SQLITE_IOCAP_IMMUTABLE]. -** +** ** ** ** ^Specifying an unknown parameter in the query component of a URI is not an ** error. Future versions of SQLite might understand additional query ** parameters. See "[query parameters with special meaning to SQLite]" for @@ -4124,41 +4219,40 @@ ** ** [[URI filename examples]]

    URI filename examples

    ** ** **
    URI filenames Results -**
    file:data.db +**
    file:data.db ** Open the file "data.db" in the current directory. **
    file:/home/fred/data.db
    -** file:///home/fred/data.db
    -** file://localhost/home/fred/data.db
    +** file:///home/fred/data.db
    +** file://localhost/home/fred/data.db
    ** Open the database file "/home/fred/data.db". -**
    file://darkstar/home/fred/data.db +**
    file://darkstar/home/fred/data.db ** An error. "darkstar" is not a recognized authority. -**
    +**
    ** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db ** Windows only: Open the file "data.db" on fred's desktop on drive -** C:. Note that the %20 escaping in this example is not strictly +** C:. Note that the %20 escaping in this example is not strictly ** necessary - space characters can be used literally ** in URI filenames. -**
    file:data.db?mode=ro&cache=private +**
    file:data.db?mode=ro&cache=private ** Open file "data.db" in the current directory for read-only access. ** Regardless of whether or not shared-cache mode is enabled by ** default, use a private cache. **
    file:/home/fred/data.db?vfs=unix-dotfile ** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" ** that uses dot-files in place of posix advisory locking. -**
    file:data.db?mode=readonly +**
    file:data.db?mode=readonly ** An error. "readonly" is not a valid option for the "mode" parameter. -** Use "ro" instead: "file:data.db?mode=ro". **
    ** ** ^URI hexadecimal escape sequences (%HH) are supported within the path and ** query components of a URI. A hexadecimal escape sequence consists of a -** percent sign - "%" - followed by exactly two hexadecimal digits +** percent sign - "%" - followed by exactly two hexadecimal digits ** specifying an octet value. ^Before the path or query components of a -** URI filename are interpreted, they are encoded using UTF-8 and all +** URI filename are interpreted, they are encoded using UTF-8 and all ** hexadecimal escape sequences replaced by a single byte containing the ** corresponding octet. If this process generates an invalid UTF-8 encoding, ** the results are undefined. ** ** Note to Windows users: The encoding used for the filename argument @@ -4189,231 +4283,78 @@ ); /* ** CAPI3REF: Obtain Values For URI Parameters ** -** These are utility routines, useful to [VFS|custom VFS implementations], -** that check if a database file was a URI that contained a specific query +** These are utility routines, useful to VFS implementations, that check +** to see if a database file was a URI that contained a specific query ** parameter, and if so obtains the value of that query parameter. ** -** The first parameter to these interfaces (hereafter referred to -** as F) must be one of: -**
      -**
    • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implementation, or -**
    • A filename obtained from [sqlite3_db_filename()], or -**
    • A new filename constructed using [sqlite3_create_filename()]. -**
    -** If the F parameter is not one of the above, then the behavior is -** undefined and probably undesirable. Older versions of SQLite were -** more tolerant of invalid F parameters than newer versions. -** -** If F is a suitable filename (as described in the previous paragraph) -** and if P is the name of the query parameter, then +** If F is the database filename pointer passed into the xOpen() method of +** a VFS implementation when the flags parameter to xOpen() has one or +** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and +** P is the name of the query parameter, then ** sqlite3_uri_parameter(F,P) returns the value of the P -** parameter if it exists or a NULL pointer if P does not appear as a -** query parameter on F. If P is a query parameter of F and it +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F ** has no explicit value, then sqlite3_uri_parameter(F,P) returns ** a pointer to an empty string. ** ** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean ** parameter and returns true (1) or false (0) according to the value ** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the ** value of query parameter P is one of "yes", "true", or "on" in any -** case or if the value begins with a non-zero number. The +** case or if the value begins with a non-zero number. The ** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of ** query parameter P is one of "no", "false", or "off" in any case or ** if the value begins with a numeric zero. If P is not a query -** parameter on F or if the value of P does not match any of the +** parameter on F or if the value of P is does not match any of the ** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). ** ** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a ** 64-bit signed integer and returns that integer, or D if P does not ** exist. If the value of P is something other than an integer, then ** zero is returned. -** -** The sqlite3_uri_key(F,N) returns a pointer to the name (not -** the value) of the N-th query parameter for filename F, or a NULL -** pointer if N is less than zero or greater than the number of query -** parameters minus 1. The N value is zero-based so N should be 0 to obtain -** the name of the first query parameter, 1 for the second parameter, and -** so forth. -** +** ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and ** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and -** is not a database file pathname pointer that the SQLite core passed -** into the xOpen VFS method, then the behavior of this routine is undefined -** and probably undesirable. -** -** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F -** parameter can also be the name of a rollback journal file or WAL file -** in addition to the main database file. Prior to version 3.31.0, these -** routines would only work if F was the name of the main database file. -** When the F parameter is the name of the rollback journal or WAL file, -** it has access to all the same query parameters as were found on the -** main database file. -** -** See the [URI filename] documentation for additional information. -*/ -SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam); -SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64); -SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N); - -/* -** CAPI3REF: Translate filenames -** -** These routines are available to [VFS|custom VFS implementations] for -** translating filenames between the main database file, the journal file, -** and the WAL file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** passed by the SQLite core into the VFS, then sqlite3_filename_database(F) -** returns the name of the corresponding database file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** passed by the SQLite core into the VFS, or if F is a database filename -** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F) -** returns the name of the corresponding rollback journal file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** that was passed by the SQLite core into the VFS, or if F is a database -** filename obtained from [sqlite3_db_filename()], then -** sqlite3_filename_wal(F) returns the name of the corresponding -** WAL file. -** -** In all of the above, if F is not the name of a database, journal or WAL -** filename passed into the VFS from the SQLite core and F is not the -** return value from [sqlite3_db_filename()], then the result is -** undefined and is likely a memory access violation. -*/ -SQLITE_API const char *sqlite3_filename_database(sqlite3_filename); -SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename); -SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename); - -/* -** CAPI3REF: Database File Corresponding To A Journal -** -** ^If X is the name of a rollback or WAL-mode journal file that is -** passed into the xOpen method of [sqlite3_vfs], then -** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file] -** object that represents the main database file. -** -** This routine is intended for use in custom [VFS] implementations -** only. It is not a general-purpose interface. -** The argument sqlite3_file_object(X) must be a filename pointer that -** has been passed into [sqlite3_vfs].xOpen method where the -** flags parameter to xOpen contains one of the bits -** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use -** of this routine results in undefined and probably undesirable -** behavior. -*/ -SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); - -/* -** CAPI3REF: Create and Destroy VFS Filenames -** -** These interfaces are provided for use by [VFS shim] implementations and -** are not useful outside of that context. -** -** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of -** database filename D with corresponding journal file J and WAL file W and -** with N URI parameters key/values pairs in the array P. The result from -** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that -** is safe to pass to routines like: -**
      -**
    • [sqlite3_uri_parameter()], -**
    • [sqlite3_uri_boolean()], -**
    • [sqlite3_uri_int64()], -**
    • [sqlite3_uri_key()], -**
    • [sqlite3_filename_database()], -**
    • [sqlite3_filename_journal()], or -**
    • [sqlite3_filename_wal()]. -**
    -** If a memory allocation error occurs, sqlite3_create_filename() might -** return a NULL pointer. The memory obtained from sqlite3_create_filename(X) -** must be released by a corresponding call to sqlite3_free_filename(Y). -** -** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array -** of 2*N pointers to strings. Each pair of pointers in this array corresponds -** to a key and value for a query parameter. The P parameter may be a NULL -** pointer if N is zero. None of the 2*N pointers in the P array may be -** NULL pointers and key pointers should not be empty strings. -** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may -** be NULL pointers, though they can be empty strings. -** -** The sqlite3_free_filename(Y) routine releases a memory allocation -** previously obtained from sqlite3_create_filename(). Invoking -** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op. -** -** If the Y parameter to sqlite3_free_filename(Y) is anything other -** than a NULL pointer or a pointer previously acquired from -** sqlite3_create_filename(), then bad things such as heap -** corruption or segfaults may occur. The value Y should not be -** used again after sqlite3_free_filename(Y) has been called. This means -** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y, -** then the corresponding [sqlite3_module.xClose() method should also be -** invoked prior to calling sqlite3_free_filename(Y). -*/ -SQLITE_API sqlite3_filename sqlite3_create_filename( - const char *zDatabase, - const char *zJournal, - const char *zWal, - int nParam, - const char **azParam -); -SQLITE_API void sqlite3_free_filename(sqlite3_filename); +** is not a database file pathname pointer that SQLite passed into the xOpen +** VFS method, then the behavior of this routine is undefined and probably +** undesirable. +*/ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); + /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** -** ^If the most recent sqlite3_* API call associated with +** ^If the most recent sqlite3_* API call associated with ** [database connection] D failed, then the sqlite3_errcode(D) interface ** returns the numeric [result code] or [extended result code] for that ** API call. +** If the most recent API call was successful, +** then the return value from sqlite3_errcode() is undefined. ** ^The sqlite3_extended_errcode() -** interface is the same except that it always returns the +** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. ** -** The values returned by sqlite3_errcode() and/or -** sqlite3_extended_errcode() might change with each API call. -** Except, there are some interfaces that are guaranteed to never -** change the value of the error code. The error-code preserving -** interfaces include the following: -** -**
      -**
    • sqlite3_errcode() -**
    • sqlite3_extended_errcode() -**
    • sqlite3_errmsg() -**
    • sqlite3_errmsg16() -**
    • sqlite3_error_offset() -**
    -** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF-8 or UTF-16 respectively, -** or NULL if no error message is available. -** (See how SQLite handles [invalid UTF] for exceptions to this rule.) +** text that describes the error, as either UTF-8 or UTF-16 respectively. ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** -** ^The sqlite3_errstr(E) interface returns the English-language text -** that describes the [result code] E, as UTF-8, or NULL if E is not an -** result code for which a text error message is available. +** ^The sqlite3_errstr() interface returns the English-language text +** that describes the [result code], as UTF-8. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** -** ^If the most recent error references a specific token in the input -** SQL, the sqlite3_error_offset() interface returns the byte offset -** of the start of that token. ^The byte offset returned by -** sqlite3_error_offset() assumes that the input SQL is UTF8. -** ^If the most recent error does not reference a specific token in the input -** SQL, then the sqlite3_error_offset() function returns -1. -** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. ** When that happens, the second error will be reported since these ** interfaces always report the most recent result. To avoid @@ -4429,21 +4370,20 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db); SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); SQLITE_API const char *sqlite3_errmsg(sqlite3*); SQLITE_API const void *sqlite3_errmsg16(sqlite3*); SQLITE_API const char *sqlite3_errstr(int); -SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* ** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** ** An instance of this object represents a single SQL statement that ** has been compiled into binary form and is ready to be evaluated. ** ** Think of each SQL statement as a separate computer program. The -** original SQL text is source code. A prepared statement object +** original SQL text is source code. A prepared statement object ** is the compiled object code. All SQL must be converted into a ** prepared statement before it can be run. ** ** The life-cycle of a prepared statement object usually goes like this: ** @@ -4469,19 +4409,19 @@ ** second parameter is one of the [limit categories] that define a ** class of constructs to be size limited. The third parameter is the ** new limit for that construct.)^ ** ** ^If the new limit is a negative number, the limit is unchanged. -** ^(For each limit category SQLITE_LIMIT_NAME there is a +** ^(For each limit category SQLITE_LIMIT_NAME there is a ** [limits | hard upper bound] ** set at compile-time by a C preprocessor macro called ** [limits | SQLITE_MAX_NAME]. ** (The "_LIMIT_" in the name is changed to "_MAX_".))^ ** ^Attempts to increase a limit above its hard upper bound are ** silently truncated to the hard upper bound. ** -** ^Regardless of whether or not the limit was changed, the +** ^Regardless of whether or not the limit was changed, the ** [sqlite3_limit()] interface returns the prior value of the limit. ** ^Hence, to find the current value of a limit without changing it, ** simply invoke this interface with the third parameter set to -1. ** ** Run-time limits are intended for use in applications that manage @@ -4582,45 +4522,19 @@ **
    ** [[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 +** 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. -** -** [[SQLITE_PREPARE_NORMALIZE]]
    SQLITE_PREPARE_NORMALIZE
    -**
    The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used -** to be required for any prepared statement that wanted to use the -** [sqlite3_normalized_sql()] interface. However, the -** [sqlite3_normalized_sql()] interface is now available to all -** prepared statements, regardless of whether or not they use this -** flag. -** -** [[SQLITE_PREPARE_NO_VTAB]]
    SQLITE_PREPARE_NO_VTAB
    -**
    The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler -** to return an error (error code SQLITE_ERROR) if the statement uses -** any virtual tables. -** -** [[SQLITE_PREPARE_DONT_LOG]]
    SQLITE_PREPARE_DONT_LOG
    -**
    The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler -** errors from being sent to the error log defined by -** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test -** compiles to see if some SQL syntax is well-formed, without generating -** messages on the global error log when it is not. If the test compile -** fails, the sqlite3_prepare_v3() call returns the same error indications -** with or without this flag; it just omits the call to [sqlite3_log()] that -** logs the error. **
    */ #define SQLITE_PREPARE_PERSISTENT 0x01 -#define SQLITE_PREPARE_NORMALIZE 0x02 -#define SQLITE_PREPARE_NO_VTAB 0x04 -#define SQLITE_PREPARE_DONT_LOG 0x10 /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** METHOD: sqlite3 @@ -4649,21 +4563,17 @@ ** 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 maximum -** number of bytes read from zSql. When nByte is positive, zSql is read -** up to the first zero terminator or until the nByte bytes have been read, -** whichever comes first. ^If nByte is zero, then no prepared +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared ** statement is generated. ** If the caller knows that the supplied string is nul-terminated, then ** there is a small performance advantage to passing an nByte parameter that ** is the number of bytes in the input string including ** the nul-terminator. -** Note that nByte measure the length of the input in bytes, not -** characters, even for the UTF-16 interfaces. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only ** compile the first statement in zSql, so *pzTail is left pointing to ** what remains uncompiled. @@ -4704,27 +4614,27 @@ ** in order to find the underlying cause of the problem. With the "v2" prepare ** interfaces, the underlying reason for the error is returned immediately. **
  • ** **
  • -** ^If the specific value bound to a [parameter | host parameter] in the +** ^If the specific value bound to [parameter | host parameter] in the ** WHERE clause might influence the choice of query plan for a statement, -** then the statement will be automatically recompiled, as if there had been -** a schema change, on the first [sqlite3_step()] call following any change -** to the [sqlite3_bind_text | bindings] of that [parameter]. -** ^The specific value of a WHERE-clause [parameter] might influence the +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column -** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. +** 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( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -4762,11 +4672,11 @@ ); 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 */ + unsigned int prepFalgs, /* Zero or more SQLITE_PREPARE_ flags */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); /* @@ -4778,15 +4688,10 @@ ** 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. -** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 -** string containing the normalized SQL text of prepared statement P. The -** semantics used to normalize a SQL statement are unspecified and subject -** to change. At a minimum, literal values will be replaced with suitable -** placeholders. ** ** ^(For example, if a prepared statement is created using the SQL ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** and parameter :xyz is unbound, then sqlite3_sql() will return ** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() @@ -4798,25 +4703,18 @@ ** ** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** -** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) -** are managed by SQLite and are automatically freed when the prepared -** statement is finalized. +** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +** automatically freed when the prepared statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, -** is obtained from [sqlite3_malloc()] and must be freed by the application +** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. -** -** ^The sqlite3_normalized_sql() interface is only available if -** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); -#endif /* ** CAPI3REF: Determine If An SQL Statement Writes The Database ** METHOD: sqlite3_stmt ** @@ -4823,12 +4721,12 @@ ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to ** the content of the database file. ** ** Note that [application-defined SQL functions] or -** [virtual tables] might change the database indirectly as a side effect. -** ^(For example, if an application defines a function "eval()" that +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that ** calls [sqlite3_exec()], then the following SQL statement would ** change the database file through side-effects: ** **

     **    SELECT eval('DELETE FROM t1') FROM t2;
    @@ -4838,99 +4736,39 @@
     ** directly, sqlite3_stmt_readonly() would still return true.)^
     **
     ** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
     ** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
     ** since the statements themselves do not actually modify the database but
    -** rather they control the timing of when other statements modify the
    +** rather they control the timing of when other statements modify the 
     ** database.  ^The [ATTACH] and [DETACH] statements also cause
     ** sqlite3_stmt_readonly() to return true since, while those statements
    -** change the configuration of a database connection, they do not make
    +** 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.
    -**
    -** ^This routine returns false if there is any possibility that the
    -** statement might change the database file.  ^A false return does
    -** not guarantee that the statement will change the database file.
    -** ^For example, an UPDATE statement might have a WHERE clause that
    -** makes it a no-op, but the sqlite3_stmt_readonly() result would still
    -** be false.  ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
    -** read-only no-op if the table already exists, but
    -** sqlite3_stmt_readonly() still returns false for such a statement.
    -**
    -** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
    -** statement, then sqlite3_stmt_readonly(X) returns the same value as
    -** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
     */
     SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
     
    -/*
    -** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
    -** METHOD: sqlite3_stmt
    -**
    -** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
    -** prepared statement S is an EXPLAIN statement, or 2 if the
    -** statement S is an EXPLAIN QUERY PLAN.
    -** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
    -** an ordinary statement or a NULL pointer.
    -*/
    -SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
    -
    -/*
    -** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement
    -** METHOD: sqlite3_stmt
    -**
    -** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN
    -** setting for [prepared statement] S.  If E is zero, then S becomes
    -** a normal prepared statement.  If E is 1, then S behaves as if
    -** its SQL text began with "[EXPLAIN]".  If E is 2, then S behaves as if
    -** its SQL text began with "[EXPLAIN QUERY PLAN]".
    -**
    -** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.
    -** SQLite tries to avoid a reprepare, but a reprepare might be necessary
    -** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.
    -**
    -** Because of the potential need to reprepare, a call to
    -** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be
    -** reprepared because it was created using [sqlite3_prepare()] instead of
    -** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and
    -** hence has no saved SQL text with which to reprepare.
    -**
    -** Changing the explain setting for a prepared statement does not change
    -** the original SQL text for the statement.  Hence, if the SQL text originally
    -** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)
    -** is called to convert the statement into an ordinary statement, the EXPLAIN
    -** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)
    -** output, even though the statement now acts like a normal SQL statement.
    -**
    -** This routine returns SQLITE_OK if the explain mode is successfully
    -** changed, or an error code if the explain mode could not be changed.
    -** The explain mode cannot be changed while a statement is active.
    -** Hence, it is good practice to call [sqlite3_reset(S)]
    -** immediately prior to calling sqlite3_stmt_explain(S,E).
    -*/
    -SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);
    -
     /*
     ** CAPI3REF: Determine If A Prepared Statement Has Been Reset
     ** METHOD: sqlite3_stmt
     **
     ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
    -** [prepared statement] S has been stepped at least once using
    +** [prepared statement] S has been stepped at least once using 
     ** [sqlite3_step(S)] but has neither run to completion (returned
     ** [SQLITE_DONE] from [sqlite3_step(S)]) nor
     ** been reset using [sqlite3_reset(S)].  ^The sqlite3_stmt_busy(S)
    -** interface returns false if S is a NULL pointer.  If S is not a
    +** interface returns false if S is a NULL pointer.  If S is not a 
     ** NULL pointer and is not a pointer to a valid [prepared statement]
     ** object, then the behavior is undefined and probably undesirable.
     **
     ** This interface can be used in combination [sqlite3_next_stmt()]
    -** to locate all prepared statements associated with a database
    +** to locate all prepared statements associated with a database 
     ** connection that are in need of being reset.  This can be used,
    -** for example, in diagnostic routines to search for prepared
    +** for example, in diagnostic routines to search for prepared 
     ** statements that are holding a transaction open.
     */
     SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
     
     /*
    @@ -4945,35 +4783,32 @@
     ** An sqlite3_value object may be either "protected" or "unprotected".
     ** Some interfaces require a protected sqlite3_value.  Other interfaces
     ** will accept either a protected or an unprotected sqlite3_value.
     ** Every interface that accepts sqlite3_value arguments specifies
     ** whether or not it requires a protected sqlite3_value.  The
    -** [sqlite3_value_dup()] interface can be used to construct a new
    +** [sqlite3_value_dup()] interface can be used to construct a new 
     ** protected sqlite3_value from an unprotected sqlite3_value.
     **
     ** The terms "protected" and "unprotected" refer to whether or not
     ** a mutex is held.  An internal mutex is held for a protected
     ** sqlite3_value object but no mutex is held for an unprotected
     ** sqlite3_value object.  If SQLite is compiled to be single-threaded
     ** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
    -** or if SQLite is run in one of reduced mutex modes
    +** or if SQLite is run in one of reduced mutex modes 
     ** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
     ** then there is no distinction between protected and unprotected
     ** sqlite3_value objects and they can be used interchangeably.  However,
     ** for maximum code portability it is recommended that applications
     ** still make the distinction between protected and unprotected
     ** sqlite3_value objects even when not strictly required.
     **
     ** ^The sqlite3_value objects that are passed as parameters into the
     ** implementation of [application-defined SQL functions] are protected.
    -** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()]
    -** are protected.
     ** ^The sqlite3_value object returned by
     ** [sqlite3_column_value()] is unprotected.
    -** Unprotected sqlite3_value objects may only be used as arguments
    -** to [sqlite3_result_value()], [sqlite3_bind_value()], and
    -** [sqlite3_value_dup()].
    +** Unprotected sqlite3_value objects may only be used with
    +** [sqlite3_result_value()] and [sqlite3_bind_value()].
     ** The [sqlite3_value_blob | sqlite3_value_type()] family of
     ** interfaces require protected sqlite3_value objects.
     */
     typedef struct sqlite3_value sqlite3_value;
     
    @@ -5024,34 +4859,16 @@
     ** occurrences have the same index as the first occurrence.
     ** ^The index for named parameters can be looked up using the
     ** [sqlite3_bind_parameter_index()] API if desired.  ^The index
     ** for "?NNN" parameters is the value of NNN.
     ** ^The NNN value must be between 1 and the [sqlite3_limit()]
    -** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
    +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
     **
     ** ^The third argument is the value to bind to the parameter.
     ** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
     ** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
     ** is ignored and the end result is the same as sqlite3_bind_null().
    -** ^If the third parameter to sqlite3_bind_text() is not NULL, then
    -** it should be a pointer to well-formed UTF8 text.
    -** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
    -** it should be a pointer to well-formed UTF16 text.
    -** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
    -** it should be a pointer to a well-formed unicode string that is
    -** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
    -** otherwise.
    -**
    -** [[byte-order determination rules]] ^The byte-order of
    -** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
    -** found in first character, which is removed, or in the absence of a BOM
    -** the byte order is the native byte order of the host
    -** machine for sqlite3_bind_text16() or the byte order specified in
    -** the 6th parameter for sqlite3_bind_text64().)^
    -** ^If UTF16 input text contains invalid unicode
    -** characters, then SQLite might change those invalid characters
    -** into the unicode replacement character: U+FFFD.
     **
     ** ^(In those routines that have a fourth argument, its value is the
     ** number of bytes in the parameter.  To be clear: the value is the
     ** number of bytes in the value, not the number of characters.)^
     ** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
    @@ -5061,31 +4878,25 @@
     ** the behavior is undefined.
     ** If a non-negative fourth parameter is provided to sqlite3_bind_text()
     ** or sqlite3_bind_text16() or sqlite3_bind_text64() then
     ** that parameter must be the byte offset
     ** where the NUL terminator would occur assuming the string were NUL
    -** terminated.  If any NUL characters occurs at byte offsets less than
    +** terminated.  If any NUL characters occur at byte offsets less than 
     ** the value of the fourth parameter then the resulting string value will
     ** contain embedded NULs.  The result of expressions involving strings
     ** with embedded NULs is undefined.
     **
    -** ^The fifth argument to the BLOB and string binding interfaces controls
    -** or indicates the lifetime of the object referenced by the third parameter.
    -** These three options exist:
    -** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
    -** with it may be passed. ^It is called to dispose of the BLOB or string even
    -** if the call to the bind API fails, except the destructor is not called if
    -** the third parameter is a NULL pointer or the fourth parameter is negative.
    -** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that
    -** the application remains responsible for disposing of the object. ^In this
    -** case, the object and the provided pointer to it must remain valid until
    -** either the prepared statement is finalized or the same SQL parameter is
    -** bound to something else, whichever occurs sooner.
    -** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
    -** object is to be copied prior to the return from sqlite3_bind_*(). ^The
    -** object and pointer to it must remain valid until then. ^SQLite will then
    -** manage the lifetime of its private copy.
    +** ^The fifth argument to the BLOB and string binding interfaces
    +** is a destructor used to dispose of the BLOB or
    +** string after SQLite has finished with it.  ^The destructor is called
    +** to dispose of the BLOB or string even if the call to bind API fails.
    +** ^If the fifth argument is
    +** the special value [SQLITE_STATIC], then SQLite assumes that the
    +** information is in static, unmanaged space and does not need to be freed.
    +** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
    +** SQLite makes its own private copy of the data immediately, before
    +** the sqlite3_bind_*() routine returns.
     **
     ** ^The sixth argument to sqlite3_bind_text64() must be one of
     ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
     ** to specify the encoding of the text in the third parameter.  If
     ** the sixth argument to sqlite3_bind_text64() is not one of the
    @@ -5099,18 +4910,18 @@
     ** Zeroblobs are intended to serve as placeholders for BLOBs whose
     ** content is later written using
     ** [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
    +** ^The sqlite3_bind_pointer(S,I,P) 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.
    +** associated with the pointer P.
    +** ^The sqlite3_bind_pointer() routine can be used to pass
    +** host-language pointers into [application-defined SQL functions].
    +** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
    +** to be an ordinary SQL NULL value to everything other than
    +** [sqlite3_value_pointer()].
     **
     ** ^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()],
     ** then the call will return [SQLITE_MISUSE].  If any sqlite3_bind_()
    @@ -5141,11 +4952,11 @@
     SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
     SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(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_pointer(sqlite3_stmt*, int, void*);
     SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
     SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
     
     /*
     ** CAPI3REF: Number Of SQL Parameters
    @@ -5227,11 +5038,11 @@
     /*
     ** CAPI3REF: Number Of Columns In A Result Set
     ** METHOD: sqlite3_stmt
     **
     ** ^Return the number of columns in the result set returned by the
    -** [prepared statement]. ^If this routine returns 0, that means the
    +** [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.
    @@ -5295,19 +5106,23 @@
     ** the statement, where N is the second function argument.
     ** ^The left-most column is column 0 for these routines.
     **
     ** ^If the Nth column returned by the statement is an expression or
     ** subquery and is not a column value, then all of these functions return
    -** NULL.  ^These routines might also return NULL if a memory allocation error
    +** NULL.  ^These routine might also return NULL if a memory allocation error
     ** occurs.  ^Otherwise, they return the name of the attached database, table,
     ** or column that query result column was extracted from.
     **
     ** ^As with all other SQLite APIs, those whose names end with "16" return
     ** UTF-16 encoded strings and the other functions return UTF-8.
     **
     ** ^These APIs are only available if the library was compiled with the
     ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
    +**
    +** If two or more threads call one or more of these routines against the same
    +** prepared statement and column at the same time then the results are
    +** undefined.
     **
     ** If two or more threads call one or more
     ** [sqlite3_column_database_name | column metadata interfaces]
     ** for the same [prepared statement] and result column
     ** at the same time then the results are undefined.
    @@ -5409,11 +5224,11 @@
     ** more threads at the same moment in time.
     **
     ** For all versions of SQLite up to and including 3.6.23.1, a call to
     ** [sqlite3_reset()] was required after sqlite3_step() returned anything
     ** other than [SQLITE_ROW] before any subsequent invocation of
    -** sqlite3_step().  Failure to reset the prepared statement using
    +** sqlite3_step().  Failure to reset the prepared statement using 
     ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
     ** sqlite3_step().  But after [version 3.6.23.1] ([dateof:3.6.23.1],
     ** sqlite3_step() began
     ** calling [sqlite3_reset()] automatically in this circumstance rather
     ** than returning [SQLITE_MISUSE].  This is not considered a compatibility
    @@ -5441,11 +5256,11 @@
     ** METHOD: sqlite3_stmt
     **
     ** ^The sqlite3_data_count(P) interface returns the number of columns in the
     ** current row of the result set of [prepared statement] P.
     ** ^If prepared statement P does not have results ready to return
    -** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
    +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
     ** interfaces) then sqlite3_data_count(P) returns 0.
     ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
     ** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
     ** [sqlite3_step](P) returned [SQLITE_DONE].  ^The sqlite3_data_count(P)
     ** will return non-zero if previous call to [sqlite3_step](P) returned
    @@ -5500,11 +5315,11 @@
     ** 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_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  
    @@ -5548,11 +5363,11 @@
     ** of the result column.  ^The returned value is one of [SQLITE_INTEGER],
     ** [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.
    +** 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.
     **
    @@ -5576,38 +5391,34 @@
     ** ^If the result is a numeric value then sqlite3_column_bytes16() uses
     ** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns
     ** the number of bytes in that string.
     ** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
     **
    -** ^The values returned by [sqlite3_column_bytes()] and
    +** ^The values returned by [sqlite3_column_bytes()] and 
     ** [sqlite3_column_bytes16()] do not include the zero terminators at the end
     ** of the string.  ^For clarity: the values returned by
     ** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
     ** bytes in the string, not the number of characters.
     **
     ** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
     ** even empty strings, are always zero-terminated.  ^The return
     ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
     **
    -** ^Strings returned by sqlite3_column_text16() always have the endianness
    -** which is native to the platform, regardless of the text encoding set
    -** for the database.
    -**
     ** Warning: ^The object returned by [sqlite3_column_value()] is an
     ** [unprotected sqlite3_value] object.  In a multithreaded environment,
     ** an unprotected sqlite3_value object may only be used safely with
     ** [sqlite3_bind_value()] and [sqlite3_result_value()].
     ** If the [unprotected sqlite3_value] object returned by
     ** [sqlite3_column_value()] is used in any other way, including calls
     ** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
     ** or [sqlite3_value_bytes()], the behavior is not threadsafe.
     ** Hence, the sqlite3_column_value() interface
    -** is normally only useful within the implementation of
    +** is normally only useful within the implementation of 
     ** [application-defined SQL functions] or [virtual tables], not within
     ** top-level application code.
     **
    -** These routines may attempt to convert the datatype of the 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:
     **
    @@ -5628,11 +5439,11 @@
     **   TEXT     INTEGER    [CAST] to INTEGER
     **   TEXT      FLOAT     [CAST] to REAL
     **   TEXT       BLOB     No change
     **   BLOB     INTEGER    [CAST] to INTEGER
     **   BLOB      FLOAT     [CAST] to REAL
    -**   BLOB       TEXT     [CAST] to TEXT, ensure zero terminator
    +**   BLOB       TEXT     Add a zero terminator if needed
     ** 
     ** 
    )^ ** ** Note that when type conversions occur, pointers returned by prior ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or @@ -5680,29 +5491,15 @@ ** [sqlite3_finalize()] is called. ^The memory space used to hold strings ** and BLOBs is freed automatically. Do not pass the pointers returned ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** [sqlite3_free()]. ** -** As long as the input parameters are correct, these routines will only -** fail if an out-of-memory error occurs during a format conversion. -** Only the following subset of interfaces are subject to out-of-memory -** errors: -** -**
      -**
    • sqlite3_column_blob() -**
    • sqlite3_column_text() -**
    • sqlite3_column_text16() -**
    • sqlite3_column_bytes() -**
    • sqlite3_column_bytes16() -**
    -** -** If an out-of-memory error occurs, then the return value from these -** routines is the same as if the column had contained an SQL NULL value. -** Valid SQL NULL returns can be distinguished from out-of-memory errors -** by invoking the [sqlite3_errcode()] immediately after the suspect -** return value is obtained and before any -** other SQLite interface is called on the same [database connection]. +** ^(If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM].)^ */ SQLITE_API const void *sqlite3_column_blob(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); @@ -5752,61 +5549,48 @@ ** Use [sqlite3_clear_bindings()] to reset the bindings. ** ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** -** ^The return code from [sqlite3_reset(S)] indicates whether or not -** the previous evaluation of prepared statement S completed successfully. -** ^If [sqlite3_step(S)] has never before been called on S or if -** [sqlite3_step(S)] has not been called since the previous call -** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return -** [SQLITE_OK]. +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. -** ^The [sqlite3_reset(S)] interface might also return an [error code] -** if there were no prior errors but the process of resetting -** the prepared statement caused a new error. ^For example, if an -** [INSERT] statement with a [RETURNING] clause is only stepped one time, -** that one call to [sqlite3_step(S)] might return SQLITE_ROW but -** the overall statement might still fail and the [sqlite3_reset(S)] call -** might return SQLITE_BUSY if locking constraints prevent the -** database change from committing. Therefore, it is important that -** applications check the return code from [sqlite3_reset(S)] even if -** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); - /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} ** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior -** of existing SQL functions or aggregates. The only differences between -** the three "sqlite3_create_function*" routines are the text encoding -** expected for the second parameter (the name of the function being -** created) and the presence or absence of a destructor callback for -** the application data pointer. Function sqlite3_create_window_function() -** is similar, but allows the user to supply the extra callback functions -** needed by [aggregate window functions]. +** of existing SQL functions or aggregates. The only differences between +** these routines are the text encoding expected for +** the second parameter (the name of the function being created) +** and the presence or absence of a destructor callback for +** the application data pointer. ** ** ^The first parameter is the [database connection] to which the SQL ** function is to be added. ^If an application uses more than one database ** connection then application-defined SQL functions must be added ** to each database connection separately. ** ** ^The second parameter is the name of the SQL function to be created or ** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 ** representation, exclusive of the zero-terminator. ^Note that the name -** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. ** ^Any attempt to create a function with a longer name ** will result in [SQLITE_MISUSE] being returned. ** ** ^The third parameter (nArg) ** is the number of arguments that the SQL function or @@ -5817,11 +5601,11 @@ ** undefined. ** ** ^The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for ** its parameters. The application should set this parameter to -** [SQLITE_UTF16LE] if the function implementation invokes +** [SQLITE_UTF16LE] if the function implementation invokes ** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the ** implementation invokes [sqlite3_value_text16be()] on an input, or ** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] ** otherwise. ^The same SQL function may be registered multiple times using ** different preferred text encodings, with different implementations for @@ -5835,66 +5619,41 @@ ** deterministic. The built-in [random()] SQL function is an example of a ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** -** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] -** flag, which if present prevents the function from being invoked from -** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, -** index expressions, or the WHERE clause of partial indexes. -** -** For best security, the [SQLITE_DIRECTONLY] flag is recommended for -** all application-defined SQL functions that do not need to be -** used inside of triggers, view, CHECK constraints, or other elements of -** the database schema. This flags is especially recommended for SQL -** functions that have side effects or reveal internal application state. -** Without this flag, an attacker might be able to modify the schema of -** a database file to include invocations of the function with parameters -** chosen by the attacker, which the application will then execute when -** the database file is opened and read. -** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** -** ^The sixth, seventh and eighth parameters passed to the three -** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are +** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ** aggregate. ^A scalar SQL function requires an implementation of the xFunc ** callback only; NULL pointers must be passed as the xStep and xFinal ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** -** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue -** and xInverse) passed to sqlite3_create_window_function are pointers to -** C-language callbacks that implement the new function. xStep and xFinal -** must both be non-NULL. xValue and xInverse may either both be NULL, in -** which case a regular aggregate function is created, or must both be -** non-NULL, in which case the new function may be used as either an aggregate -** or aggregate window function. More details regarding the implementation -** of aggregate window functions are -** [user-defined window functions|available here]. -** -** ^(If the final parameter to sqlite3_create_function_v2() or -** sqlite3_create_window_function() is not NULL, then it is destructor for -** the application data pointer. The destructor is invoked when the function -** is deleted, either by being overloaded or when the database connection -** closes.)^ ^The destructor is also invoked if the call to -** sqlite3_create_function_v2() fails. ^When the destructor callback is -** invoked, it is passed a single argument which is a copy of the application -** data pointer which was the fifth parameter to sqlite3_create_function_v2(). +** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +** then it is destructor for the application data pointer. +** The destructor is invoked when the function is deleted, either by being +** overloaded or when the database connection closes.)^ +** ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. +** ^When the destructor callback of the tenth parameter is invoked, it +** is passed a single argument which is a copy of the application data +** pointer which was the fifth parameter to sqlite3_create_function_v2(). ** ** ^It is permitted to register multiple implementations of the same ** functions with the same name but with either differing numbers of ** arguments or differing preferred text encodings. ^SQLite will use ** the implementation that most closely matches the way in which the ** SQL function is used. ^A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with ** a negative nArg. ^A function where the preferred text encoding ** matches the database encoding is a better -** match than a function where the encoding is different. +** match than a function where the encoding is different. ** ^A function where the encoding difference is between UTF16le and UTF16be ** is a closer match than a function where the encoding difference is ** between UTF8 and UTF16. ** ** ^Built-in functions may be overloaded by new application-defined functions. @@ -5933,22 +5692,10 @@ void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void(*xDestroy)(void*) ); -SQLITE_API int sqlite3_create_window_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*) -); /* ** CAPI3REF: Text Encodings ** ** These constant define integer codes that represent the various @@ -5962,119 +5709,23 @@ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ /* ** CAPI3REF: Function Flags ** -** These constants may be ORed together with the +** These constants may be ORed together with the ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument ** to [sqlite3_create_function()], [sqlite3_create_function16()], or ** [sqlite3_create_function_v2()]. -** -**
    -** [[SQLITE_DETERMINISTIC]]
    SQLITE_DETERMINISTIC
    -** The SQLITE_DETERMINISTIC flag means that the new function always gives -** the same output when the input parameters are the same. -** The [abs|abs() function] is deterministic, for example, but -** [randomblob|randomblob()] is not. Functions must -** be deterministic in order to be used in certain contexts such as -** with the WHERE clause of [partial indexes] or in [generated columns]. -** SQLite might also optimize deterministic functions by factoring them -** out of inner loops. -**
    -** -** [[SQLITE_DIRECTONLY]]
    SQLITE_DIRECTONLY
    -** The SQLITE_DIRECTONLY flag means that the function may only be invoked -** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in -** schema structures such as [CHECK constraints], [DEFAULT clauses], -** [expression indexes], [partial indexes], or [generated columns]. -**

    -** The SQLITE_DIRECTONLY flag is recommended for any -** [application-defined SQL function] -** that has side-effects or that could potentially leak sensitive information. -** This will prevent attacks in which an application is tricked -** into using a database file that has had its schema surreptitiously -** modified to invoke the application-defined function in ways that are -** harmful. -**

    -** Some people say it is good practice to set SQLITE_DIRECTONLY on all -** [application-defined SQL functions], regardless of whether or not they -** are security sensitive, as doing so prevents those functions from being used -** inside of the database schema, and thus ensures that the database -** can be inspected and modified using generic tools (such as the [CLI]) -** that do not have access to the application-defined functions. -**

    -** -** [[SQLITE_INNOCUOUS]]
    SQLITE_INNOCUOUS
    -** The SQLITE_INNOCUOUS flag means that the function is unlikely -** to cause problems even if misused. An innocuous function should have -** no side effects and should not depend on any values other than its -** input parameters. The [abs|abs() function] is an example of an -** innocuous function. -** The [load_extension() SQL function] is not innocuous because of its -** side effects. -**

    SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not -** exactly the same. The [random|random() function] is an example of a -** function that is innocuous but not deterministic. -**

    Some heightened security settings -** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF]) -** disable the use of SQL functions inside views and triggers and in -** schema structures such as [CHECK constraints], [DEFAULT clauses], -** [expression indexes], [partial indexes], and [generated columns] unless -** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions -** are innocuous. Developers are advised to avoid using the -** SQLITE_INNOCUOUS flag for application-defined functions unless the -** function has been carefully audited and found to be free of potentially -** security-adverse side-effects and information-leaks. -**

    -** -** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    -** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** This flag instructs SQLite to omit some corner-case optimizations that -** might disrupt the operation of the [sqlite3_value_subtype()] function, -** causing it to return zero rather than the correct subtype(). -** All SQL functions that invoke [sqlite3_value_subtype()] should have this -** property. If the SQLITE_SUBTYPE property is omitted, then the return -** value from [sqlite3_value_subtype()] might sometimes be zero even though -** a non-zero subtype was specified by the function argument expression. -** -** [[SQLITE_RESULT_SUBTYPE]]
    SQLITE_RESULT_SUBTYPE
    -** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_result_subtype()] to cause a sub-type to be associated with its -** result. -** Every function that invokes [sqlite3_result_subtype()] should have this -** property. If it does not, then the call to [sqlite3_result_subtype()] -** might become a no-op if the function is used as term in an -** [expression index]. On the other hand, SQL functions that never invoke -** [sqlite3_result_subtype()] should avoid setting this property, as the -** purpose of this property is to disable certain optimizations that are -** incompatible with subtypes. -** -** [[SQLITE_SELFORDER1]]
    SQLITE_SELFORDER1
    -** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate -** that internally orders the values provided to the first argument. The -** ordered-set aggregate SQL notation with a single ORDER BY term can be -** used to invoke this function. If the ordered-set aggregate notation is -** used on a function that lacks this flag, then an error is raised. Note -** that the ordered-set aggregate syntax is only available if SQLite is -** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option. -**
    -**
    */ -#define SQLITE_DETERMINISTIC 0x000000800 -#define SQLITE_DIRECTONLY 0x000080000 -#define SQLITE_SUBTYPE 0x000100000 -#define SQLITE_INNOCUOUS 0x000200000 -#define SQLITE_RESULT_SUBTYPE 0x001000000 -#define SQLITE_SELFORDER1 0x002000000 +#define SQLITE_DETERMINISTIC 0x800 /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** ** These functions are [deprecated]. In order to maintain -** backwards compatibility with older code, these functions continue +** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid ** the use of these functions. To encourage programmers to avoid ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED @@ -6111,23 +5762,18 @@ ** 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. -** sqlite3_value_frombind   -** →  True if value originated from a [bound parameter] **
    ** ** Details: ** ** These routines extract type, size, and content information from ** [protected sqlite3_value] objects. Protected sqlite3_value objects -** are used to pass parameter information into the functions that -** implement [application-defined SQL functions] and [virtual tables]. +** 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] ** is not threadsafe. ** @@ -6138,16 +5784,14 @@ ** ^The sqlite3_value_text16() interface extracts a UTF-16 string ** in the native byte-order of the host machine. ^The ** 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. +** ^If [sqlite3_value] object V was initialized +** using [sqlite3_bind_pointer(S,I,P)] or [sqlite3_result_pointer(C,P)], then +** sqlite3_value_pointer(V) will return the pointer P. Otherwise, +** sqlite3_value_pointer(V) returns a NULL. ** ** ^(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].)^ @@ -6164,96 +5808,32 @@ ** such a conversion is possible without loss of information (in other ** words, if the value is a string that looks like a number) ** 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. -** -** ^The sqlite3_value_frombind(X) interface returns non-zero if the -** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] -** interfaces. ^If X comes from an SQL literal value, or a table column, -** or an expression, then sqlite3_value_frombind(X) returns zero. -** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. -** -** As long as the input parameter is correct, these routines can only -** fail if an out-of-memory error occurs during a format conversion. -** Only the following subset of interfaces are subject to out-of-memory -** errors: -** -** -** -** If an out-of-memory error occurs, then the return value from these -** routines is the same as if the column had contained an SQL NULL value. -** Valid SQL NULL returns can be distinguished from out-of-memory errors -** by invoking the [sqlite3_errcode()] immediately after the suspect -** return value is obtained and before any -** other SQLite interface is called on the same [database connection]. */ SQLITE_API const void *sqlite3_value_blob(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 void *sqlite3_value_pointer(sqlite3_value*); 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*); -SQLITE_API int sqlite3_value_frombind(sqlite3_value*); - -/* -** CAPI3REF: Report the internal text encoding state of an sqlite3_value object -** METHOD: sqlite3_value -** -** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding -** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X) -** returns something other than SQLITE_TEXT, then the return value from -** sqlite3_value_encoding(X) is meaningless. ^Calls to -** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)], -** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or -** [sqlite3_value_bytes16(X)] might change the encoding of the value X and -** thus change the return from subsequent calls to sqlite3_value_encoding(X). -** -** This routine is intended for used by applications that test and validate -** the SQLite implementation. This routine is inquiring about the opaque -** internal state of an [sqlite3_value] object. Ordinary applications should -** not need to know what the internal state of an sqlite3_value object is and -** hence should not need to use this interface. -*/ -SQLITE_API int sqlite3_value_encoding(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values ** METHOD: sqlite3_value ** @@ -6260,16 +5840,10 @@ ** The sqlite3_value_subtype(V) function returns the subtype for ** an [application-defined SQL function] argument V. The subtype ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_SUBTYPE] property in the text -** encoding argument when the function is [sqlite3_create_function|registered]. -** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() -** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -6277,12 +5851,11 @@ ** ** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a -** memory allocation fails. ^If V is a [pointer value], then the result -** of sqlite3_value_dup(V) is a NULL value. +** memory allocation fails. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ @@ -6294,13 +5867,13 @@ ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** -** ^The first time the sqlite3_aggregate_context(C,N) routine is called -** for a particular aggregate function, SQLite allocates -** N bytes of memory, zeroes out that memory, and returns a pointer +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite +** allocates N of memory, zeroes out that memory, and returns a pointer ** to the new memory. ^On second and subsequent calls to ** sqlite3_aggregate_context() for the same aggregate function instance, ** the same buffer is returned. Sqlite3_aggregate_context() is normally ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match @@ -6307,23 +5880,23 @@ ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** -** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory -** allocation error occurs. +** allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the -** value of N in any subsequent call to sqlite3_aggregate_context() within +** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ Within the xFinal callback, it is customary to set -** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** N=0 in calls to sqlite3_aggregate_context(C,N) so that no ** pointless memory allocations occur. ** -** ^SQLite automatically frees the memory allocated by +** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ** ** The first parameter must be a copy of the ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate @@ -6364,130 +5937,65 @@ /* ** CAPI3REF: Function Auxiliary Data ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to -** associate auxiliary data with argument values. If the same argument -** value is passed to multiple invocations of the same SQL function during -** query execution, under some circumstances the associated auxiliary data -** might be preserved. An example of where this might be useful is in a -** regular-expression matching function. The compiled version of the regular -** expression can be stored as auxiliary data associated with the pattern string. +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. An example +** of where this might be useful is in a regular-expression matching +** function. The compiled version of the regular expression can be stored as +** metadata associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. ** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data +** ^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 auxiliary data +** 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 auxiliary data for the -** N-th argument of the application-defined function. ^Subsequent +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th +** argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or -** NULL if the auxiliary data has been discarded. +** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or +** NULL if the metadata has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly -** once, when the auxiliary data is discarded. -** SQLite is free to discard the auxiliary data at any time, including: ** -** Note the last two bullets in particular. The destructor X in +** Note the last bullet in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. Furthermore, a call to -** sqlite3_get_auxdata() that occurs immediately after a corresponding call -** to sqlite3_set_auxdata() might still return NULL if an out-of-memory -** condition occurred during the sqlite3_set_auxdata() call or if the -** function is being evaluated during query planning rather than during -** query execution. +** sqlite3_set_auxdata() has been called. ** -** ^(In practice, auxiliary data is preserved between function calls for +** ^(In practice, metadata is preserved between function calls for ** 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. -** -** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); -/* -** CAPI3REF: Database Connection Client Data -** METHOD: sqlite3 -** -** These functions are used to associate one or more named pointers -** with a [database connection]. -** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P -** to be attached to [database connection] D using name N. Subsequent -** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P -** or a NULL pointer if there were no prior calls to -** sqlite3_set_clientdata() with the same values of D and N. -** Names are compared using strcmp() and are thus case sensitive. -** -** If P and X are both non-NULL, then the destructor X is invoked with -** argument P on the first of the following occurrences: -** -** -** SQLite does not do anything with client data other than invoke -** destructors on the client data at the appropriate time. The intended -** use for client data is to provide a mechanism for wrapper libraries -** to store additional information about an SQLite database connection. -** -** There is no limit (other than available memory) on the number of different -** client data pointers (with different names) that can be attached to a -** single database connection. However, the implementation is optimized -** for the case of having only one or two different client data names. -** Applications and wrapper libraries are discouraged from using more than -** one client data name each. -** -** There is no way to enumerate the client data pointers -** associated with a database connection. The N parameter can be thought -** of as a secret key such that only code that knows the secret key is able -** to access the associated data. -** -** Security Warning: These interfaces should not be exposed in scripting -** languages or in other circumstances where it might be possible for an -** an attacker to invoke them. Any agent that can invoke these interfaces -** can probably also take control of the process. -** -** Database connection client data is only available for SQLite -** version 3.44.0 ([dateof:3.44.0]) and later. -** -** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()]. -*/ -SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*); -SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior ** ** These are special values for the destructor that is passed in as the @@ -6535,13 +6043,12 @@ ** cause the implemented SQL function to throw an exception. ** ^SQLite uses the string pointed to by the ** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() ** as the text of an error message. ^SQLite interprets the error ** message string from sqlite3_result_error() as UTF-8. ^SQLite -** interprets the string from sqlite3_result_error16() as UTF-16 using -** the same [byte-order determination rules] as [sqlite3_bind_text16()]. -** ^If the third parameter to sqlite3_result_error() +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. ^If the third parameter to sqlite3_result_error() ** or sqlite3_result_error16() is negative then SQLite takes as the error ** message all text up through the first zero character. ** ^If the third parameter to sqlite3_result_error() or ** sqlite3_result_error16() is non-negative then SQLite takes that many ** bytes (not characters) from the 2nd parameter as the error message. @@ -6579,14 +6086,13 @@ ** application-defined function to be a text string in an encoding ** specified by the fifth (and last) parameter, which must be one ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. -** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces -** other than sqlite3_result_text64() is negative, then SQLite computes -** the string length itself by searching the 2nd parameter for the first -** zero character. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is non-negative, then as many bytes (not characters) of the text ** pointed to by the 2nd parameter are taken as the application-defined ** function result. If the 3rd parameter is non-negative, then it ** must be the byte offset into the string where the NUL terminator would @@ -6606,29 +6112,10 @@ ** ^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 [sqlite3_malloc()] before it returns. ** -** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and -** sqlite3_result_text16be() routines, and for sqlite3_result_text64() -** when the encoding is not UTF8, if the input UTF16 begins with a -** byte-order mark (BOM, U+FEFF) then the BOM is removed from the -** string and the rest of the string is interpreted according to the -** byte-order specified by the BOM. ^The byte-order specified by -** the BOM at the beginning of the text overrides the byte-order -** specified by the interface procedure. ^So, for example, if -** sqlite3_result_text16le() is invoked with text that begins -** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the -** first two bytes of input are skipped and the remaining input -** is interpreted as UTF16BE text. -** -** ^For UTF16 input text to the sqlite3_result_text16(), -** sqlite3_result_text16be(), sqlite3_result_text16le(), and -** sqlite3_result_text64() routines, if the text contains invalid -** UTF16 characters, the invalid characters might be converted -** into the unicode replacement character, U+FFFD. -** ** ^The sqlite3_result_value() interface sets the result of ** the application-defined function to be a copy of the ** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The ** sqlite3_result_value() interface makes a copy of the [sqlite3_value] ** so that the [sqlite3_value] specified in the parameter may change or @@ -6635,20 +6122,17 @@ ** be deallocated after sqlite3_result_value() returns without harm. ** ^A [protected sqlite3_value] object may always be used where an ** [unprotected sqlite3_value] object is required, so either ** kind of [sqlite3_value] object can be used with this interface. ** -** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an +** ^The sqlite3_result_pointer(C,P) 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 +** also associates the host-language pointer P 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. +** This mechanism can be used to pass non-SQL values between +** application-defined functions. ** ** 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. */ @@ -6669,40 +6153,26 @@ void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); 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_pointer(sqlite3_context*, void*); SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Setting The Subtype Of An SQL Function ** METHOD: sqlite3_context ** ** The sqlite3_result_subtype(C,T) function causes the subtype of -** the result from the [application-defined SQL function] with -** [sqlite3_context] C to be the value T. Only the lower 8 bits +** the result from the [application-defined SQL function] with +** [sqlite3_context] C to be the value T. Only the lower 8 bits ** of the subtype T are preserved in current versions of SQLite; ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_RESULT_SUBTYPE] property in its -** text encoding argument when the SQL function is -** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] -** property is omitted from the function that invokes sqlite3_result_subtype(), -** then in some cases the sqlite3_result_subtype() might fail to set -** the result subtype. -** -** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any -** SQL function that invokes the sqlite3_result_subtype() interface -** and that does not have the SQLITE_RESULT_SUBTYPE property will raise -** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 -** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -6724,32 +6194,31 @@ **
  • [SQLITE_UTF16BE], **
  • [SQLITE_UTF16], or **
  • [SQLITE_UTF16_ALIGNED]. ** )^ ** ^The eTextRep argument determines the encoding of strings passed -** to the collating function callback, xCompare. +** to the collating function callback, xCallback. ** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep ** force strings to be UTF16 with native byte order. ** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin ** on an even byte address. ** ** ^The fourth argument, pArg, is an application data pointer that is passed ** through as the first argument to the collating function callback. ** -** ^The fifth argument, xCompare, is a pointer to the collating function. +** ^The fifth argument, xCallback, is a pointer to the collating function. ** ^Multiple collating functions can be registered using the same name but ** with different eTextRep parameters and SQLite will use whichever ** function requires the least amount of data transformation. -** ^If the xCompare argument is NULL then the collating function is +** ^If the xCallback argument is NULL then the collating function is ** deleted. ^When all collating functions having the same name are deleted, ** that collation is no longer usable. ** -** ^The collating function callback is invoked with a copy of the pArg +** ^The collating function callback is invoked with a copy of the pArg ** application data pointer and with two strings in the encoding specified -** by the eTextRep argument. The two integer parameters to the collating -** function callback are the length of the two strings, in bytes. The collating -** function must return an integer that is negative, zero, or positive +** by the eTextRep argument. The collating function must return an +** integer that is negative, zero, or positive ** if the first string is less than, equal to, or greater than the second, ** respectively. A collating function must always return the same answer ** given the same inputs. If two or more collating functions are registered ** to the same collation name (using different eTextRep values) then all ** must give an equivalent answer when invoked with equivalent strings. @@ -6762,50 +6231,50 @@ **
  • If A<B THEN B>A. **
  • If A<B and B<C then A<C. ** ** ** If a collating function fails any of the above constraints and that -** collating function is registered and used, then the behavior of SQLite +** collating function is registered and used, then the behavior of SQLite ** is undefined. ** ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() ** with the addition that the xDestroy callback is invoked on pArg when ** the collating function is deleted. ** ^Collating functions are deleted when they are overridden by later ** calls to the collation creation functions or when the ** [database connection] is closed using [sqlite3_close()]. ** -** ^The xDestroy callback is not called if the +** ^The xDestroy callback is not called if the ** sqlite3_create_collation_v2() function fails. Applications that invoke -** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should ** check the return code and dispose of the application data pointer ** themselves rather than expecting SQLite to deal with it for them. -** This is different from every other SQLite interface. The inconsistency -** is unfortunate but cannot be changed without breaking backwards +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards ** compatibility. ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ SQLITE_API int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, + sqlite3*, + const char *zName, + int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); SQLITE_API int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, + sqlite3*, + const char *zName, + int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); SQLITE_API int sqlite3_create_collation16( - sqlite3*, + sqlite3*, const void *zName, - int eTextRep, + int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); /* @@ -6834,23 +6303,68 @@ ** The callback function should register the desired collation using ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ SQLITE_API int sqlite3_collation_needed( - sqlite3*, - void*, + sqlite3*, + void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); SQLITE_API int sqlite3_collation_needed16( - sqlite3*, + sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); + +#ifdef SQLITE_HAS_CODEC +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); +SQLITE_API int sqlite3_key_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); +SQLITE_API int sqlite3_rekey_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The new key */ +); + +/* +** Specify the activation key for a SEE database. Unless +** activated, none of the SEE routines will work. +*/ +SQLITE_API void sqlite3_activate_see( + const char *zPassPhrase /* Activation phrase */ +); +#endif #ifdef SQLITE_ENABLE_CEROD /* -** Specify the activation key for a CEROD database. Unless +** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); @@ -6870,17 +6384,10 @@ ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. -** -** If a negative argument is passed to sqlite3_sleep() the results vary by -** VFS and operating system. Some system treat a negative argument as an -** instruction to sleep forever. Others understand it to mean do not sleep -** at all. ^In SQLite version 3.42.0 and later, a negative -** argument passed into sqlite3_sleep() is changed to zero before it is relayed -** down into the xSleep method of the VFS. */ SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -6909,11 +6416,11 @@ ** thereafter. ** ** ^The [temp_store_directory pragma] may modify this variable and cause ** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, ** the [temp_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from +** that this variable points to is held in memory obtained from ** [sqlite3_malloc] and the pragma may attempt to free that memory ** using [sqlite3_free]. ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [temp_store_directory pragma] should be avoided. @@ -6966,54 +6473,19 @@ ** thereafter. ** ** ^The [data_store_directory pragma] may modify this variable and cause ** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, ** the [data_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from +** that this variable points to is held in memory obtained from ** [sqlite3_malloc] and the pragma may attempt to free that memory ** using [sqlite3_free]. ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [data_store_directory pragma] should be avoided. */ SQLITE_API char *sqlite3_data_directory; -/* -** CAPI3REF: Win32 Specific Interface -** -** These interfaces are available only on Windows. The -** [sqlite3_win32_set_directory] interface is used to set the value associated -** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to -** zValue, depending on the value of the type parameter. The zValue parameter -** should be NULL to cause the previous value to be freed via [sqlite3_free]; -** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] -** prior to being used. The [sqlite3_win32_set_directory] interface returns -** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, -** or [SQLITE_NOMEM] if memory could not be allocated. The value of the -** [sqlite3_data_directory] variable is intended to act as a replacement for -** the current directory on the sub-platforms of Win32 where that concept is -** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and -** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the -** sqlite3_win32_set_directory interface except the string parameter must be -** UTF-8 or UTF-16, respectively. -*/ -SQLITE_API int sqlite3_win32_set_directory( - unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ -); -SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); -SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); - -/* -** CAPI3REF: Win32 Directory Types -** -** These macros are only available on Windows. They define the allowed values -** for the type argument to the [sqlite3_win32_set_directory] interface. -*/ -#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 -#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 - /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} ** METHOD: sqlite3 ** @@ -7047,63 +6519,26 @@ ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); -/* -** CAPI3REF: Return The Schema Name For A Database Connection -** METHOD: sqlite3 -** -** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name -** for the N-th database on database connection D, or a NULL pointer of N is -** out of range. An N value of 0 means the main database file. An N of 1 is -** the "temp" schema. Larger values of N correspond to various ATTACH-ed -** databases. -** -** Space to hold the string that is returned by sqlite3_db_name() is managed -** by SQLite itself. The string might be deallocated by any operation that -** changes the schema, including [ATTACH] or [DETACH] or calls to -** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that -** occur on a different thread. Applications that need to -** remember the string long-term should make their own copy. Applications that -** are accessing the same database connection simultaneously on multiple -** threads should mutex-protect calls to this API and should make their own -** private copy of the result prior to releasing the mutex. -*/ -SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N); - /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** -** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename -** associated with database N of connection D. -** ^If there is no attached database N on the database +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then -** this function will return either a NULL pointer or an empty string. -** -** ^The string value returned by this routine is owned and managed by -** the database connection. ^The value will be valid until the database N -** is [DETACH]-ed or until the database connection closes. +** a NULL pointer is returned. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. -** -** If the filename pointer returned by this routine is not NULL, then it -** can be used as the filename input parameter to these routines: -** */ -SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only ** METHOD: sqlite3 ** @@ -7111,61 +6546,10 @@ ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); -/* -** CAPI3REF: Determine the transaction state of a database -** METHOD: sqlite3 -** -** ^The sqlite3_txn_state(D,S) interface returns the current -** [transaction state] of schema S in database connection D. ^If S is NULL, -** then the highest transaction state of any schema on database connection D -** is returned. Transaction states are (in order of lowest to highest): -**
      -**
    1. SQLITE_TXN_NONE -**
    2. SQLITE_TXN_READ -**
    3. SQLITE_TXN_WRITE -**
    -** ^If the S argument to sqlite3_txn_state(D,S) is not the name of -** a valid schema, then -1 is returned. -*/ -SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); - -/* -** CAPI3REF: Allowed return values from sqlite3_txn_state() -** KEYWORDS: {transaction state} -** -** These constants define the current transaction state of a database file. -** ^The [sqlite3_txn_state(D,S)] interface returns one of these -** constants in order to describe the transaction state of schema S -** in [database connection] D. -** -**
    -** [[SQLITE_TXN_NONE]]
    SQLITE_TXN_NONE
    -**
    The SQLITE_TXN_NONE state means that no transaction is currently -** pending.
    -** -** [[SQLITE_TXN_READ]]
    SQLITE_TXN_READ
    -**
    The SQLITE_TXN_READ state means that the database is currently -** in a read transaction. Content has been read from the database file -** but nothing in the database file has changed. The transaction state -** will advanced to SQLITE_TXN_WRITE if any changes occur and there are -** no other conflicting concurrent write transactions. The transaction -** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or -** [COMMIT].
    -** -** [[SQLITE_TXN_WRITE]]
    SQLITE_TXN_WRITE
    -**
    The SQLITE_TXN_WRITE state means that the database is currently -** in a write transaction. Content has been written to the database file -** but has not yet committed. The transaction state will change to -** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
    -*/ -#define SQLITE_TXN_NONE 0 -#define SQLITE_TXN_READ 1 -#define SQLITE_TXN_WRITE 2 - /* ** CAPI3REF: Find the next prepared statement ** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after @@ -7227,76 +6611,10 @@ ** ** See also the [sqlite3_update_hook()] interface. */ SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Autovacuum Compaction Amount Callback -** METHOD: sqlite3 -** -** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback -** function C that is invoked prior to each autovacuum of the database -** file. ^The callback is passed a copy of the generic data pointer (P), -** the schema-name of the attached database that is being autovacuumed, -** the size of the database file in pages, the number of free pages, -** and the number of bytes per page, respectively. The callback should -** return the number of free pages that should be removed by the -** autovacuum. ^If the callback returns zero, then no autovacuum happens. -** ^If the value returned is greater than or equal to the number of -** free pages, then a complete autovacuum happens. -** -**

    ^If there are multiple ATTACH-ed database files that are being -** modified as part of a transaction commit, then the autovacuum pages -** callback is invoked separately for each file. -** -**

    The callback is not reentrant. The callback function should -** not attempt to invoke any other SQLite interface. If it does, bad -** things may happen, including segmentation faults and corrupt database -** files. The callback function should be a simple function that -** does some arithmetic on its input parameters and returns a result. -** -** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional -** destructor for the P parameter. ^If X is not NULL, then X(P) is -** invoked whenever the database connection closes or when the callback -** is overwritten by another invocation of sqlite3_autovacuum_pages(). -** -**

    ^There is only one autovacuum pages callback per database connection. -** ^Each call to the sqlite3_autovacuum_pages() interface overrides all -** previous invocations for that database connection. ^If the callback -** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, -** then the autovacuum steps callback is canceled. The return value -** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might -** be some other error code if something goes wrong. The current -** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other -** return codes might be added in future releases. -** -**

    If no autovacuum pages callback is specified (the usual case) or -** a NULL pointer is provided for the callback, -** then the default behavior is to vacuum all free pages. So, in other -** words, the default behavior is the same as if the callback function -** were something like this: -** -**

    -**     unsigned int demonstration_autovac_pages_callback(
    -**       void *pClientData,
    -**       const char *zSchema,
    -**       unsigned int nDbPage,
    -**       unsigned int nFreePage,
    -**       unsigned int nBytePerPage
    -**     ){
    -**       return nFreePage;
    -**     }
    -** 
    -*/ -SQLITE_API int sqlite3_autovacuum_pages( - sqlite3 *db, - unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), - void*, - void(*)(void*) -); - /* ** CAPI3REF: Data Change Notification Callbacks ** METHOD: sqlite3 ** @@ -7318,26 +6636,20 @@ ** database and table name containing the affected row. ** ^The final callback parameter is the [rowid] of the row. ** ^In the case of an update, this is the [rowid] after the update takes place. ** ** ^(The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_sequence).)^ +** modified (i.e. sqlite_master and sqlite_sequence).)^ ** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. ** ** ^In the current implementation, the update hook ** 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 ** release of SQLite. ** -** Whether the update hook is invoked before or after the -** corresponding change is currently unspecified and may differ -** depending on the type of change. Do not rely on the order of the -** hook call with regards to the final result of the operation which -** triggers the hook. -** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the update hook. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their @@ -7350,11 +6662,11 @@ ** ** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], ** and [sqlite3_preupdate_hook()] interfaces. */ SQLITE_API void *sqlite3_update_hook( - sqlite3*, + sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* ); /* @@ -7363,39 +6675,30 @@ ** ^(This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] ** to the same database. Sharing is enabled if the argument is true ** and disabled if the argument is false.)^ ** -** This interface is omitted if SQLite is compiled with -** [-DSQLITE_OMIT_SHARED_CACHE]. The [-DSQLITE_OMIT_SHARED_CACHE] -** compile-time option is recommended because the -** [use of shared cache mode is discouraged]. -** ** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). ** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent ** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** Existing database connections continue to use the sharing mode +** Existing database connections continue use the sharing mode ** that was in effect at the time they were opened.)^ ** ** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled ** successfully. An [error code] is returned otherwise.)^ ** -** ^Shared cache is disabled by default. It is recommended that it stay -** that way. In other words, do not use this routine. This interface -** continues to be provided for historical compatibility, but its use is -** discouraged. Any use of shared cache is discouraged. If shared cache -** must be used, it is recommended that shared cache only be enabled for -** individual database connections using the [sqlite3_open_v2()] interface -** with the [SQLITE_OPEN_SHAREDCACHE] flag. +** ^Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. ** ** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 -** and will always return SQLITE_MISUSE. On those systems, -** shared cache mode should be enabled per-database connection via +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via ** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. ** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** @@ -7434,58 +6737,34 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** -** These interfaces impose limits on the amount of heap memory that will be -** by all database connections within a single process. -** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap ** limit by reducing the number of pages held in the page cache ** as heap memory usages approaches the limit. ** ^The soft heap limit is "soft" because even though SQLite strives to stay ** below the limit, it will exceed the limit rather than generate -** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** an [SQLITE_NOMEM] error. In other words, the soft heap limit ** is advisory only. ** -** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of -** N bytes on the amount of memory that will be allocated. ^The -** sqlite3_hard_heap_limit64(N) interface is similar to -** sqlite3_soft_heap_limit64(N) except that memory allocations will fail -** when the hard heap limit is reached. -** -** ^The return value from both sqlite3_soft_heap_limit64() and -** sqlite3_hard_heap_limit64() is the size of -** the heap limit prior to the call, or negative in the case of an +** ^The return value from sqlite3_soft_heap_limit64() is the size of +** the soft heap limit prior to the call, or negative in the case of an ** error. ^If the argument N is negative -** then no change is made to the heap limit. Hence, the current -** size of heap limits can be determined by invoking -** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1). -** -** ^Setting the heap limits to zero disables the heap limiter mechanism. -** -** ^The soft heap limit may not be greater than the hard heap limit. -** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N) -** is invoked with a value of N that is greater than the hard heap limit, -** the soft heap limit is set to the value of the hard heap limit. -** ^The soft heap limit is automatically enabled whenever the hard heap -** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and -** the soft heap limit is outside the range of 1..N, then the soft heap -** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the -** hard heap limit is enabled makes the soft heap limit equal to the -** hard heap limit. -** -** The memory allocation limits can also be adjusted using -** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit]. -** -** ^(The heap limits are not enforced in the current implementation +** then no change is made to the soft heap limit. Hence, the current +** size of the soft heap limit can be determined by invoking +** sqlite3_soft_heap_limit64() with a negative argument. +** +** ^If the argument N is zero then the soft heap limit is disabled. +** +** ^(The soft heap limit is not enforced in the current implementation ** if one or more of following conditions are true: ** ** )^ ** -** The circumstances under which SQLite will enforce the heap limits may +** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), +** the soft heap limit is enforced +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], +** the soft heap limit is enforced on every memory allocation. Without +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced +** when memory is allocated by the page cache. Testing suggests that because +** the page cache is the predominate memory user in SQLite, most +** applications will achieve adequate soft heap limit enforcement without +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); -SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED ** @@ -7520,11 +6809,11 @@ ** information about column C of table T in database D ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() ** interface returns SQLITE_OK and fills in the non-NULL pointers in ** the final five arguments with appropriate values if the specified ** column exists. ^The sqlite3_table_column_metadata() interface returns -** SQLITE_ERROR if the specified column does not exist. +** SQLITE_ERROR and if the specified column does not exist. ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it ** 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 @@ -7560,11 +6849,11 @@ ** declaration type and collation sequence is valid until the next ** call to any SQLite API function. ** ** ^If the specified table is actually a view, an [error code] is returned. ** -** ^If the specified column is "rowid", "oid" or "_rowid_" and the table +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table ** is not a [WITHOUT ROWID] table and an ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output ** parameters are set for the explicitly declared column. ^(If there is no ** [INTEGER PRIMARY KEY] column, then the outputs ** for the [rowid] are set as follows: @@ -7626,11 +6915,11 @@ ** [sqlite3_enable_load_extension()] or ** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) ** prior to calling this API, ** otherwise an error will be returned. ** -** Security warning: It is recommended that the +** Security warning: It is recommended that the ** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this ** interface. The use of the [sqlite3_enable_load_extension()] interface ** should be avoided. This will keep the SQL function [load_extension()] ** disabled and prevent SQL injections from giving attackers ** access to extension loading capabilities. @@ -7662,11 +6951,11 @@ ** [sqlite3_load_extension()] and the SQL function [load_extension()]. ** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) ** to enable or disable only the C-API.)^ ** ** Security warning: It is recommended that extension loading -** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method +** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method ** rather than this interface, so the [load_extension()] SQL function ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); @@ -7713,11 +7002,11 @@ ** CAPI3REF: Cancel Automatic Extension Loading ** ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the ** initialization routine X that was registered using a prior call to ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] -** routine returns 1 if initialization routine X was successfully +** routine returns 1 if initialization routine X was successfully ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); @@ -7727,10 +7016,19 @@ ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ SQLITE_API void sqlite3_reset_auto_extension(void); +/* +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + /* ** Structures used by the virtual table interface */ typedef struct sqlite3_vtab sqlite3_vtab; typedef struct sqlite3_index_info sqlite3_index_info; @@ -7739,12 +7037,12 @@ /* ** CAPI3REF: Virtual Table Object ** KEYWORDS: sqlite3_module {virtual table module} ** -** This structure, sometimes called a "virtual table module", -** defines the implementation of a [virtual table]. +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual tables]. ** This structure consists mostly of methods for the module. ** ** ^A virtual table module is created by filling in a persistent ** instance of this structure and passing a pointer to that instance ** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. @@ -7779,22 +7077,15 @@ int (*xRollback)(sqlite3_vtab *pVTab); int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg); int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); - /* The methods above are in version 1 of the sqlite_module object. Those + /* The methods above are in version 1 of the sqlite_module object. Those ** below are for version 2 and greater. */ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); - /* The methods above are in versions 1 and 2 of the sqlite_module object. - ** Those below are for version 3 and greater. */ - int (*xShadowName)(const char*); - /* The methods above are in versions 1 through 3 of the sqlite_module object. - ** Those below are for version 4 and greater. */ - int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, - const char *zTabName, int mFlags, char **pzErr); }; /* ** CAPI3REF: Virtual Table Indexing Information ** KEYWORDS: sqlite3_index_info @@ -7833,50 +7124,42 @@ ** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), ** the corresponding bit is set within the colUsed mask if the column may be ** required by SQLite. If the table has at least 64 columns and any column ** to the right of the first 63 is required, then bit 63 of colUsed is also ** set. In other words, column iCol may be required if the expression -** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to +** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to ** non-zero. ** ** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the -** virtual table and might not be checked again by the byte code.)^ ^(The -** aConstraintUsage[].omit flag is an optimization hint. When the omit flag -** is left in its default setting of false, the constraint will always be -** checked separately in byte code. If the omit flag is change to true, then -** the constraint may or may not be checked in byte code. In other words, -** when the omit flag is true there is no guarantee that the constraint will -** not be checked again using byte code.)^ +** virtual table and is not checked again by SQLite.)^ ** -** ^The idxNum and idxStr values are recorded and passed into the +** ^The idxNum and idxPtr values are recorded and passed into the ** [xFilter] method. -** ^[sqlite3_free()] is used to free idxStr if and only if -** needToFreeIdxStr is true. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate ** sorting step is required. ** ** ^The estimatedCost value is an estimate of the cost of a particular ** strategy. A cost of N indicates that the cost of the strategy is similar -** to a linear scan of an SQLite table with N rows. A cost of log(N) +** to a linear scan of an SQLite table with N rows. A cost of log(N) ** indicates that the expense of the operation is similar to that of a ** binary search on a unique indexed field of an SQLite table with N rows. ** ** ^The estimatedRows value is an estimate of the number of rows that ** will be returned by the strategy. ** -** The xBestIndex method may optionally populate the idxFlags field with a -** mask of SQLITE_INDEX_SCAN_* flags. One such flag is -** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN] -** output to show the idxNum has hex instead of as decimal. Another flag is -** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will -** return at most one row. +** The xBestIndex method may optionally populate the idxFlags field with a +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite +** assumes that the strategy may visit at most one row. ** ** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then ** SQLite also assumes that if a call to the xUpdate() method is made as ** part of the same statement to delete or update a virtual table row and the ** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback @@ -7885,18 +7168,18 @@ ** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not ** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by ** the xUpdate method are automatically rolled back by SQLite. ** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info -** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). ** If a virtual table extension is -** used with an SQLite version earlier than 3.8.2, the results of attempting -** to read or write the estimatedRows field are undefined (but are likely -** to include crashing the application). The estimatedRows field should +** used with an SQLite version earlier than 3.8.2, the results of attempting +** to read or write the estimatedRows field are undefined (but are likely +** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a ** value greater than or equal to 3008002. Similarly, the idxFlags field -** was added for [version 3.9.0] ([dateof:3.9.0]). +** was added for [version 3.9.0] ([dateof:3.9.0]). ** It may therefore only be used if ** sqlite3_libversion_number() returns a value greater than or equal to ** 3009000. */ struct sqlite3_index_info { @@ -7931,74 +7214,30 @@ sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ }; /* ** CAPI3REF: Virtual Table Scan Flags -** -** Virtual table implementations are allowed to set the -** [sqlite3_index_info].idxFlags field to some combination of -** these bits. */ -#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */ -#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */ - /* in EXPLAIN QUERY PLAN */ +#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** -** These macros define the allowed values for the +** These macros defined the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents -** an operator that is part of a constraint term in the WHERE clause of +** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. -** -** ^The left-hand operand of the operator is given by the corresponding -** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand -** operand is the rowid. -** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET -** operators have no left-hand operand, and so for those operators the -** corresponding aConstraint[].iColumn is meaningless and should not be -** used. -** -** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through -** value 255 are reserved to represent functions that are overloaded -** by the [xFindFunction|xFindFunction method] of the virtual table -** implementation. -** -** The right-hand operands for each constraint might be accessible using -** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand -** operand is only available if it appears as a single constant literal -** in the input SQL. If the right-hand operand is another column or an -** expression (even a constant expression) or a parameter, then the -** sqlite3_vtab_rhs_value() probably will not be able to extract it. -** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and -** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand -** and hence calls to sqlite3_vtab_rhs_value() for those operators will -** always return SQLITE_NOTFOUND. -** -** The collating sequence to be used for comparison can be found using -** the [sqlite3_vtab_collation()] interface. For most real-world virtual -** tables, the collating sequence of constraints does not matter (for example -** because the constraints are numeric) and so the sqlite3_vtab_collation() -** interface is not commonly needed. */ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 -#define SQLITE_INDEX_CONSTRAINT_NE 68 -#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 -#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 -#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 -#define SQLITE_INDEX_CONSTRAINT_IS 72 -#define SQLITE_INDEX_CONSTRAINT_LIMIT 73 -#define SQLITE_INDEX_CONSTRAINT_OFFSET 74 -#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 +#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 /* ** CAPI3REF: Register A Virtual Table Implementation ** METHOD: sqlite3 ** @@ -8006,11 +7245,11 @@ ** ^Module names must be registered before ** creating a new [virtual table] using the module and before using a ** preexisting [virtual table] for the module. ** ** ^The module name is registered on the [database connection] specified -** by the first parameter. ^The name of the module is given by the +** by the first parameter. ^The name of the module is given by the ** second parameter. ^The third parameter is a pointer to ** the implementation of the [virtual table module]. ^The fourth ** parameter is an arbitrary client data pointer that is passed through ** into the [xCreate] and [xConnect] methods of the virtual table module ** when a new virtual table is be being created or reinitialized. @@ -8021,16 +7260,10 @@ ** no longer needs the pClientData pointer. ^The destructor will also ** be invoked if the call to sqlite3_create_module_v2() fails. ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. -** -** ^If the third parameter (the pointer to the sqlite3_module object) is -** NULL then no new module is created and any existing modules with the -** same name are dropped. -** -** See also: [sqlite3_drop_modules()] */ SQLITE_API int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -8042,27 +7275,10 @@ const sqlite3_module *p, /* Methods for the module */ void *pClientData, /* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ ); -/* -** CAPI3REF: Remove Unnecessary Virtual Table Implementations -** METHOD: sqlite3 -** -** ^The sqlite3_drop_modules(D,L) interface removes all virtual -** table modules from database connection D except those named on list L. -** The L parameter must be either NULL or a pointer to an array of pointers -** to strings where the array is terminated by a single NULL pointer. -** ^If the L parameter is NULL, then all virtual table modules are removed. -** -** See also: [sqlite3_create_module()] -*/ -SQLITE_API int sqlite3_drop_modules( - sqlite3 *db, /* Remove modules from this connection */ - const char **azKeep /* Except, do not remove the ones named here */ -); - /* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab ** ** Every [virtual table module] implementation uses a subclass @@ -8121,11 +7337,11 @@ /* ** CAPI3REF: Overload A Function For A Virtual Table ** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions -** using the [xFindFunction] method of the [virtual table module]. +** using the [xFindFunction] method of the [virtual table module]. ** But global versions of those functions ** must exist in order to be overloaded.)^ ** ** ^(This API makes sure a global version of a function with a particular ** name and number of parameters exists. If no such function exists @@ -8134,10 +7350,20 @@ ** the new function is not good for anything by itself. Its only ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ /* ** CAPI3REF: A Handle To An Open BLOB ** KEYWORDS: {BLOB handle} {BLOB handles} ** @@ -8162,11 +7388,11 @@ ** **
     **     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
     ** 
    )^ ** -** ^(Parameter zDb is not the filename that contains the database, but +** ^(Parameter zDb is not the filename that contains the database, but ** rather the symbolic name of the database. For attached databases, this is ** the name that appears after the AS keyword in the [ATTACH] statement. ** For the main database file, the database name is "main". For TEMP ** tables, the database name is "temp".)^ ** @@ -8175,32 +7401,32 @@ ** read-only access. ** ** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored ** in *ppBlob. Otherwise an [error code] is returned and, unless the error ** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided -** the API is not misused, it is always safe to call [sqlite3_blob_close()] +** the API is not misused, it is always safe to call [sqlite3_blob_close()] ** on *ppBlob after this function it returns. ** ** This function fails with SQLITE_ERROR if any of the following are true: ** ** -** ^Unless it returns SQLITE_MISUSE, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** ^Unless it returns SQLITE_MISUSE, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** A BLOB referenced by sqlite3_blob_open() may be read using the ** [sqlite3_blob_read()] interface and modified by using ** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a ** different row of the same table using the [sqlite3_blob_reopen()] @@ -8222,11 +7448,11 @@ ** the opened blob. ^The size of a blob may not be changed by this ** interface. Use the [UPDATE] SQL command to change the size of a ** blob. ** ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces -** and the built-in [zeroblob] SQL function may be used to create a +** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. ** @@ -8272,33 +7498,33 @@ /* ** CAPI3REF: Close A BLOB Handle ** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed -** unconditionally. Even if this routine returns an error code, the +** unconditionally. Even if this routine returns an error code, the ** handle is still closed.)^ ** ** ^If the blob handle being closed was opened for read-write access, and if ** the database is in auto-commit mode and there are no other open read-write ** blob handles or active write statements, the current transaction is ** committed. ^If an error occurs while committing the transaction, an error ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behavior. ^Calling this routine -** with a null pointer (such as would be returned by a failed call to +** open blob handle results in undefined behaviour. ^Calling this routine +** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function -** is passed a valid open blob handle, the values returned by the +** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB ** METHOD: sqlite3_blob ** -** ^Returns the size in bytes of the BLOB accessible via the +** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The ** incremental blob I/O routines can only read or overwriting existing ** blob content; they cannot change the size of a blob. ** ** This routine only works on a [BLOB handle] which has been created @@ -8345,24 +7571,24 @@ ** caller-supplied buffer. N bytes of data are copied from the buffer Z ** into the open BLOB, starting at offset iOffset.)^ ** ** ^(On success, sqlite3_blob_write() returns SQLITE_OK. ** Otherwise, an [error code] or an [extended error code] is returned.)^ -** ^Unless SQLITE_MISUSE is returned, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** ^Unless SQLITE_MISUSE is returned, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** ^If the [BLOB handle] passed as the first argument was not opened for ** writing (the flags parameter to [sqlite3_blob_open()] was zero), ** this function returns [SQLITE_READONLY]. ** ** This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is written. The size of the -** BLOB (and hence the maximum value of N+iOffset) can be determined -** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less +** [SQLITE_ERROR] is returned and no data is written. The size of the +** BLOB (and hence the maximum value of N+iOffset) can be determined +** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less ** than zero [SQLITE_ERROR] is returned and no data is written. ** ** ^An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the @@ -8452,11 +7678,11 @@ ** integer constants: ** ** )^ ** ** The only difference is that the public sqlite3_XXX functions enumerated ** above silently ignore any invocations that pass a NULL pointer instead ** of a valid mutex handle. The implementations of the methods defined -** by this structure are not required to handle this case. The results +** by this structure are not required to handle this case, the results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). ** ** The xMutexInit() method must be threadsafe. It must be harmless to @@ -8656,11 +7880,11 @@ ** next. Applications that override the built-in mutex logic must be ** prepared to accommodate additional static mutexes. */ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MAIN 2 +#define SQLITE_MUTEX_STATIC_MASTER 2 #define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ #define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ @@ -8670,20 +7894,16 @@ #define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */ #define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */ #define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */ #define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */ #define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */ - -/* Legacy compatibility: */ -#define SQLITE_MUTEX_STATIC_MASTER 2 - /* ** CAPI3REF: Retrieve the mutex for a database connection ** METHOD: sqlite3 ** -** ^This interface returns a pointer the [sqlite3_mutex] object that +** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ @@ -8690,11 +7910,10 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files ** METHOD: sqlite3 -** KEYWORDS: {file control} ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated ** with a particular database identified by the second argument. ^The ** name of the database is "main" for the main database or "temp" for the @@ -8705,32 +7924,25 @@ ** ^The third and fourth parameters to this routine ** are passed directly through to the second and third parameters of ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** -** A few opcodes for [sqlite3_file_control()] are handled directly -** by the SQLite core and never invoke the -** sqlite3_io_methods.xFileControl method. -** ^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_JOURNAL_POINTER] works similarly except that it returns -** the [sqlite3_file] object associated with the journal file instead of -** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns -** a pointer to the underlying [sqlite3_vfs] object for the file. -** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter -** from the pager. +** 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. ** ** ^If the second parameter (zDbName) does not match the name of any ** open database file, then SQLITE_ERROR is returned. ^This error ** code is not remembered and will not be recalled by [sqlite3_errcode()] ** or [sqlite3_errmsg()]. The underlying xFileControl method might ** also return SQLITE_ERROR. There is no way to distinguish between ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** -** See also: [file control opcodes] +** See also: [SQLITE_FCNTL_LOCKSTATE] */ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -8763,227 +7975,31 @@ ** [sqlite3_test_control()] interface. */ #define SQLITE_TESTCTRL_FIRST 5 #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 -#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ -#define SQLITE_TESTCTRL_FK_NO_ACTION 7 +#define SQLITE_TESTCTRL_PRNG_RESET 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 -#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ -#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 +#define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ -#define SQLITE_TESTCTRL_GETOPT 16 -#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ -#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 +#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 -#define SQLITE_TESTCTRL_RESULT_INTREAL 27 -#define SQLITE_TESTCTRL_PRNG_SEED 28 -#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 -#define SQLITE_TESTCTRL_SEEK_COUNT 30 -#define SQLITE_TESTCTRL_TRACEFLAGS 31 -#define SQLITE_TESTCTRL_TUNE 32 -#define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ -#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ - -/* -** CAPI3REF: SQL Keyword Checking -** -** These routines provide access to the set of SQL language keywords -** recognized by SQLite. Applications can uses these routines to determine -** whether or not a specific identifier needs to be escaped (for example, -** by enclosing in double-quotes) so as not to confuse the parser. -** -** The sqlite3_keyword_count() interface returns the number of distinct -** keywords understood by SQLite. -** -** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and -** makes *Z point to that keyword expressed as UTF8 and writes the number -** of bytes in the keyword into *L. The string that *Z points to is not -** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns -** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z -** or L are NULL or invalid pointers then calls to -** sqlite3_keyword_name(N,Z,L) result in undefined behavior. -** -** The sqlite3_keyword_check(Z,L) interface checks to see whether or not -** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero -** if it is and zero if not. -** -** The parser used by SQLite is forgiving. It is often possible to use -** a keyword as an identifier as long as such use does not result in a -** parsing ambiguity. For example, the statement -** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and -** creates a new table named "BEGIN" with three columns named -** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid -** using keywords as identifiers. Common techniques used to avoid keyword -** name collisions include: -** -** -** Note that the number of keywords understood by SQLite can depend on -** compile-time options. For example, "VACUUM" is not a keyword if -** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, -** new keywords may be added to future releases of SQLite. -*/ -SQLITE_API int sqlite3_keyword_count(void); -SQLITE_API int sqlite3_keyword_name(int,const char**,int*); -SQLITE_API int sqlite3_keyword_check(const char*,int); - -/* -** CAPI3REF: Dynamic String Object -** KEYWORDS: {dynamic string} -** -** An instance of the sqlite3_str object contains a dynamically-sized -** string under construction. -** -** The lifecycle of an sqlite3_str object is as follows: -**
      -**
    1. ^The sqlite3_str object is created using [sqlite3_str_new()]. -**
    2. ^Text is appended to the sqlite3_str object using various -** methods, such as [sqlite3_str_appendf()]. -**
    3. ^The sqlite3_str object is destroyed and the string it created -** is returned using the [sqlite3_str_finish()] interface. -**
    -*/ -typedef struct sqlite3_str sqlite3_str; - -/* -** CAPI3REF: Create A New Dynamic String Object -** CONSTRUCTOR: sqlite3_str -** -** ^The [sqlite3_str_new(D)] interface allocates and initializes -** a new [sqlite3_str] object. To avoid memory leaks, the object returned by -** [sqlite3_str_new()] must be freed by a subsequent call to -** [sqlite3_str_finish(X)]. -** -** ^The [sqlite3_str_new(D)] interface always returns a pointer to a -** valid [sqlite3_str] object, though in the event of an out-of-memory -** error the returned object might be a special singleton that will -** silently reject new text, always return SQLITE_NOMEM from -** [sqlite3_str_errcode()], always return 0 for -** [sqlite3_str_length()], and always return NULL from -** [sqlite3_str_finish(X)]. It is always safe to use the value -** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter -** to any of the other [sqlite3_str] methods. -** -** The D parameter to [sqlite3_str_new(D)] may be NULL. If the -** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum -** length of the string contained in the [sqlite3_str] object will be -** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead -** of [SQLITE_MAX_LENGTH]. -*/ -SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); - -/* -** CAPI3REF: Finalize A Dynamic String -** DESTRUCTOR: sqlite3_str -** -** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X -** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] -** that contains the constructed string. The calling application should -** pass the returned value to [sqlite3_free()] to avoid a memory leak. -** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any -** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the -** string in [sqlite3_str] object X is zero bytes long. -*/ -SQLITE_API char *sqlite3_str_finish(sqlite3_str*); - -/* -** CAPI3REF: Add Content To A Dynamic String -** METHOD: sqlite3_str -** -** These interfaces add content to an sqlite3_str object previously obtained -** from [sqlite3_str_new()]. -** -** ^The [sqlite3_str_appendf(X,F,...)] and -** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] -** functionality of SQLite to append formatted text onto the end of -** [sqlite3_str] object X. -** -** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S -** onto the end of the [sqlite3_str] object X. N must be non-negative. -** S must contain at least N non-zero bytes of content. To append a -** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] -** method instead. -** -** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of -** zero-terminated string S onto the end of [sqlite3_str] object X. -** -** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the -** single-byte character C onto the end of [sqlite3_str] object X. -** ^This method can be used, for example, to add whitespace indentation. -** -** ^The [sqlite3_str_reset(X)] method resets the string under construction -** inside [sqlite3_str] object X back to zero bytes in length. -** -** These methods do not return a result code. ^If an error occurs, that fact -** is recorded in the [sqlite3_str] object and can be recovered by a -** subsequent call to [sqlite3_str_errcode(X)]. -*/ -SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); -SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); -SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); -SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); -SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); -SQLITE_API void sqlite3_str_reset(sqlite3_str*); - -/* -** CAPI3REF: Status Of A Dynamic String -** METHOD: sqlite3_str -** -** These interfaces return the current status of an [sqlite3_str] object. -** -** ^If any prior errors have occurred while constructing the dynamic string -** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return -** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns -** [SQLITE_NOMEM] following any out-of-memory error, or -** [SQLITE_TOOBIG] if the size of the dynamic string exceeds -** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. -** -** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, -** of the dynamic string under construction in [sqlite3_str] object X. -** ^The length returned by [sqlite3_str_length(X)] does not include the -** zero-termination byte. -** -** ^The [sqlite3_str_value(X)] method returns a pointer to the current -** content of the dynamic string under construction in X. The value -** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X -** and might be freed or altered by any subsequent method on the same -** [sqlite3_str] object. Applications must not used the pointer returned -** [sqlite3_str_value(X)] after any subsequent method call on the same -** object. ^Applications may change the content of the string returned -** by [sqlite3_str_value(X)] as long as they do not write into any bytes -** outside the range of 0 to [sqlite3_str_length(X)] and do not read or -** write any byte after any subsequent sqlite3_str method call. -*/ -SQLITE_API int sqlite3_str_errcode(sqlite3_str*); -SQLITE_API int sqlite3_str_length(sqlite3_str*); -SQLITE_API char *sqlite3_str_value(sqlite3_str*); +#define SQLITE_TESTCTRL_LAST 25 /* ** CAPI3REF: SQLite Runtime Status ** ** ^These interfaces are used to retrieve runtime status information @@ -9028,33 +8044,34 @@ **
    ** [[SQLITE_STATUS_MEMORY_USED]] ^(
    SQLITE_STATUS_MEMORY_USED
    **
    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. Auxiliary page-cache +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and 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].
    )^ ** ** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
    SQLITE_STATUS_MALLOC_SIZE
    **
    This parameter records the largest memory allocation request ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their ** internal equivalents). Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. +** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
    )^ ** ** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
    SQLITE_STATUS_MALLOC_COUNT
    **
    This parameter records the number of separate memory allocations ** currently checked out.
    )^ ** ** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
    SQLITE_STATUS_PAGECACHE_USED
    **
    This parameter returns the number of pages used out of the -** [pagecache memory allocator] that was configured using +** [pagecache memory allocator] that was configured using ** [SQLITE_CONFIG_PAGECACHE]. The ** value returned is in pages, not in bytes.
    )^ ** -** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] ** ^(
    SQLITE_STATUS_PAGECACHE_OVERFLOW
    **
    This parameter returns the number of bytes of page cache ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] ** buffer and where forced to overflow to [sqlite3_malloc()]. The ** returned value includes allocations that overflowed because they @@ -9062,52 +8079,67 @@ ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because ** no space was left in the page cache.
    )^ ** ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
    SQLITE_STATUS_PAGECACHE_SIZE
    **
    This parameter records the largest memory allocation request -** handed to the [pagecache memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
    )^ ** -** [[SQLITE_STATUS_SCRATCH_USED]]
    SQLITE_STATUS_SCRATCH_USED
    -**
    No longer used.
    +** [[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_OVERFLOW]] ^(
    SQLITE_STATUS_SCRATCH_OVERFLOW
    -**
    No longer used.
    +**
    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
    -**
    No longer used.
    +** [[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.
    )^ ** ** [[SQLITE_STATUS_PARSER_STACK]] ^(
    SQLITE_STATUS_PARSER_STACK
    -**
    The *pHighwater parameter records the deepest parser stack. +**
    The *pHighwater parameter records the deepest parser stack. ** The *pCurrent value is undefined. The *pHighwater value is only ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
    )^ **
    ** ** New status parameters may be added from time to time. */ #define SQLITE_STATUS_MEMORY_USED 0 #define SQLITE_STATUS_PAGECACHE_USED 1 #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 -#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ -#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 #define SQLITE_STATUS_MALLOC_SIZE 5 #define SQLITE_STATUS_PARSER_STACK 6 #define SQLITE_STATUS_PAGECACHE_SIZE 7 -#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_SIZE 8 #define SQLITE_STATUS_MALLOC_COUNT 9 /* ** CAPI3REF: Database Connection Status ** METHOD: sqlite3 ** -** ^This interface is used to retrieve runtime status information +** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the ** database connection object to be interrogated. ^The second argument ** is an integer constant, taken from the set of ** [SQLITE_DBSTATUS options], that -** determines the parameter to interrogate. The set of +** determines the parameter to interrogate. The set of ** [SQLITE_DBSTATUS options] is likely ** to grow in future releases of SQLite. ** ** ^The current value of the requested parameter is written into *pCur ** and the highest instantaneous value is written into *pHiwtr. ^If @@ -9138,11 +8170,11 @@ ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
    SQLITE_DBSTATUS_LOOKASIDE_USED
    **
    This parameter returns the number of lookaside memory slots currently ** checked out.
    )^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
    SQLITE_DBSTATUS_LOOKASIDE_HIT
    -**
    This parameter returns the number of malloc attempts that were +**
    This parameter returns the number malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] ** ^(
    SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
    @@ -9163,11 +8195,11 @@ ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
    SQLITE_DBSTATUS_CACHE_USED
    **
    This parameter returns the approximate number of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** -** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] +** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] ** ^(
    SQLITE_DBSTATUS_CACHE_USED_SHARED
    **
    This parameter is similar to DBSTATUS_CACHE_USED, except that if a ** pager cache is shared between two or more connections the bytes of heap ** memory used by that pager cache is divided evenly between the attached ** connections.)^ In other words, if none of the pager caches associated @@ -9178,11 +8210,11 @@ ** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
    SQLITE_DBSTATUS_SCHEMA_USED
    **
    This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated -** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the ** schema memory is shared with other database connections due to ** [shared cache mode] being enabled. ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. ** @@ -9193,17 +8225,17 @@ ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. **
    ** ** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
    SQLITE_DBSTATUS_CACHE_HIT
    **
    This parameter returns the number of pager cache hits that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT ** is always 0. **
    ** ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
    SQLITE_DBSTATUS_CACHE_MISS
    **
    This parameter returns the number of pager cache misses that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. **
    ** ** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
    SQLITE_DBSTATUS_CACHE_WRITE
    **
    This parameter returns the number of dirty cache entries that have @@ -9214,19 +8246,10 @@ ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. **
    ** -** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(
    SQLITE_DBSTATUS_CACHE_SPILL
    -**
    This parameter returns the number of dirty cache entries that have -** been written to disk in the middle of a transaction due to the page -** cache overflowing. Transactions are more efficient if they are written -** to disk all at once. When pages spill mid-transaction, that introduces -** additional overhead. This parameter can be used help identify -** inefficiencies that can be resolved by increasing the cache size. -**
    -** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
    SQLITE_DBSTATUS_DEFERRED_FKS
    **
    This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. **
    @@ -9242,12 +8265,11 @@ #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_CACHE_SPILL 12 -#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** METHOD: sqlite3_stmt @@ -9257,11 +8279,11 @@ ** of times it has performed specific operations.)^ These counters can ** be used to monitor the performance characteristics of the prepared ** statements. For example, if the number of table steps greatly exceeds ** the number of table searches or result rows, that would tend to indicate ** that the prepared statement is using a full table scan rather than -** an index. +** an index. ** ** ^(This interface is used to retrieve and reset counter values from ** a [prepared statement]. The first argument is the prepared statement ** object to be interrogated. The second argument ** is an integer code for a specific [SQLITE_STMTSTATUS counter] @@ -9284,11 +8306,11 @@ ** **
    ** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
    SQLITE_STMTSTATUS_FULLSCAN_STEP
    **
    ^This is the number of times that SQLite has stepped forward in ** a table as part of a full table scan. Large numbers for this counter -** may indicate opportunities for performance improvement through +** may indicate opportunities for performance improvement through ** careful use of indices.
    ** ** [[SQLITE_STMTSTATUS_SORT]]
    SQLITE_STMTSTATUS_SORT
    **
    ^This is the number of sort operations that have occurred. ** A non-zero value in this counter may indicate an opportunity to @@ -9302,37 +8324,27 @@ ** need to be reinitialized each time the statement is run.
    ** ** [[SQLITE_STMTSTATUS_VM_STEP]]
    SQLITE_STMTSTATUS_VM_STEP
    **
    ^This is the number of virtual machine operations executed ** by the prepared statement if that number is less than or equal -** to 2147483647. The number of virtual machine operations can be +** to 2147483647. The number of virtual machine operations can be ** used as a proxy for the total work done by the prepared statement. ** If the number of virtual machine operations exceeds 2147483647 ** then the value returned by this statement status code is undefined. ** ** [[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 changes to +** 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_FILTER_MISS]] -** [[SQLITE_STMTSTATUS_FILTER HIT]] -**
    SQLITE_STMTSTATUS_FILTER_HIT
    -** SQLITE_STMTSTATUS_FILTER_MISS
    -**
    ^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join -** step was bypassed because a Bloom filter returned not-found. The -** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of -** times that the Bloom filter returned a find, and thus the join step -** had to be processed as normal. -** ** [[SQLITE_STMTSTATUS_MEMUSED]]
    SQLITE_STMTSTATUS_MEMUSED
    **
    ^This is the approximate number of bytes of heap memory ** 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. @@ -9343,12 +8355,10 @@ #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_FILTER_MISS 7 -#define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** @@ -9381,19 +8391,19 @@ /* ** CAPI3REF: Application Defined Page Cache. ** KEYWORDS: {page cache} ** ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can -** register an alternative page cache implementation by passing in an +** register an alternative page cache implementation by passing in an ** instance of the sqlite3_pcache_methods2 structure.)^ -** In many applications, most of the heap memory allocated by +** In many applications, most of the heap memory allocated by ** SQLite is used for the page cache. -** By implementing a +** By implementing a ** custom page cache using this API, an application can better control -** the amount of memory consumed by SQLite, the way in which -** that memory is allocated and released, and the policies used to -** determine exactly which parts of a database file are cached and for +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for ** how long. ** ** The alternative page cache mechanism is an ** extreme measure that is only needed by the most demanding applications. ** The built-in page cache is recommended for most uses. @@ -9402,23 +8412,23 @@ ** internal buffer by SQLite within the call to [sqlite3_config]. Hence ** the application may discard the parameter after the call to ** [sqlite3_config()] returns.)^ ** ** [[the xInit() page cache method]] -** ^(The xInit() method is called once for each effective +** ^(The xInit() method is called once for each effective ** call to [sqlite3_initialize()])^ ** (usually only once during the lifetime of the process). ^(The xInit() ** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ -** The intent of the xInit() method is to set up global data structures -** required by the custom page cache implementation. -** ^(If the xInit() method is NULL, then the +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the ** built-in default page cache is used instead of the application defined ** page cache.)^ ** ** [[the xShutdown() page cache method]] ** ^The xShutdown() method is called by [sqlite3_shutdown()]. -** It can be used to clean up +** It can be used to clean up ** any outstanding resources before process shutdown, if required. ** ^The xShutdown() method may be NULL. ** ** ^SQLite automatically serializes calls to the xInit method, ** so the xInit method need not be threadsafe. ^The @@ -9433,11 +8443,11 @@ ** ^SQLite invokes the xCreate() method to construct a new cache instance. ** SQLite will typically create one cache instance for each open database file, ** though this is not guaranteed. ^The ** first parameter, szPage, is the size in bytes of the pages that must ** be allocated by the cache. ^szPage will always a power of two. ^The -** second parameter szExtra is a number of bytes of extra storage +** second parameter szExtra is a number of bytes of extra storage ** associated with each page cache entry. ^The szExtra parameter will ** a number less than 250. SQLite will use the ** extra szExtra bytes on each page to store metadata about the underlying ** database page on disk. The value passed into szExtra depends ** on the SQLite version, the target platform, and how SQLite was compiled. @@ -9446,11 +8456,11 @@ ** false if it is used for an in-memory database. The cache implementation ** does not have to do anything special based with the value of bPurgeable; ** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will ** never invoke xUnpin() except to deliberately delete a page. ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to -** false will always have the "discard" flag set to true. +** false will always have the "discard" flag set to true. ** ^Hence, a cache created with bPurgeable false will ** never contain any unpinned pages. ** ** [[the xCachesize() page cache method]] ** ^(The xCachesize() method may be called at any time by SQLite to set the @@ -9461,16 +8471,16 @@ ** value; it is advisory only. ** ** [[the xPagecount() page cache methods]] ** The xPagecount() method must return the number of pages currently ** stored in the cache, both pinned and unpinned. -** +** ** [[the xFetch() page cache methods]] -** The xFetch() method locates a page in the cache and returns a pointer to +** The xFetch() method locates a page in the cache and returns a pointer to ** an sqlite3_pcache_page object associated with that page, or a NULL pointer. ** The pBuf element of the returned sqlite3_pcache_page object will be a -** pointer to a buffer of szPage bytes used to store the content of a +** pointer to a buffer of szPage bytes used to store the content of a ** single database page. The pExtra element of sqlite3_pcache_page will be ** a pointer to the szExtra bytes of extra storage that SQLite has requested ** for each entry in the page cache. ** ** The page to be fetched is determined by the key. ^The minimum key value @@ -9492,11 +8502,11 @@ ** NULL if allocating a new page is effectively impossible. ** ** ** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite ** will only use a createFlag of 2 after a prior call with a createFlag of 1 -** failed.)^ In between the xFetch() calls, SQLite may +** failed.)^ In between the to xFetch() calls, SQLite may ** attempt to unpin one or more cache pages by spilling the content of ** pinned pages to disk and synching the operating system disk cache. ** ** [[the xUnpin() page cache method]] ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page @@ -9505,12 +8515,12 @@ ** ^If the discard parameter is ** zero, then the page may be discarded or retained at the discretion of ** page cache implementation. ^The page cache implementation ** may choose to evict unpinned pages at any time. ** -** The cache must not perform any reference counting. A single -** call to xUnpin() unpins the page regardless of the number of prior calls +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls ** to xFetch(). ** ** [[the xRekey() page cache methods]] ** The xRekey() method is used to change the key value associated with the ** page passed as the second argument. If the cache @@ -9546,11 +8556,11 @@ sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); void (*xCachesize)(sqlite3_pcache*, int nCachesize); int (*xPagecount)(sqlite3_pcache*); sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); - void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, unsigned oldKey, unsigned newKey); void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); void (*xDestroy)(sqlite3_pcache*); void (*xShrink)(sqlite3_pcache*); }; @@ -9591,11 +8601,11 @@ /* ** CAPI3REF: Online Backup API. ** ** The backup API copies the content of one database into another. ** It is useful either for creating backups of databases or -** for copying in-memory databases to or from persistent files. +** for copying in-memory databases to or from persistent files. ** ** See Also: [Using the SQLite Online Backup API] ** ** ^SQLite holds a write transaction open on the destination database file ** for the duration of the backup operation. @@ -9602,40 +8612,40 @@ ** ^The source database is read-locked only while it is being read; ** it is not locked continuously for the entire backup operation. ** ^Thus, the backup may be performed on a live source database without ** preventing other database connections from ** reading or writing to the source database while the backup is underway. -** -** ^(To perform a backup operation: +** +** ^(To perform a backup operation: **
      **
    1. sqlite3_backup_init() is called once to initialize the -** backup, -**
    2. sqlite3_backup_step() is called one or more times to transfer +** backup, +**
    3. sqlite3_backup_step() is called one or more times to transfer ** the data between the two databases, and finally -**
    4. sqlite3_backup_finish() is called to release all resources -** associated with the backup operation. +**
    5. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. **
    )^ ** There should be exactly one call to sqlite3_backup_finish() for each ** successful call to sqlite3_backup_init(). ** ** [[sqlite3_backup_init()]] sqlite3_backup_init() ** -** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the -** [database connection] associated with the destination database +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database ** and the database name, respectively. ** ^The database name is "main" for the main database, "temp" for the ** temporary database, or the name specified after the AS keyword in ** an [ATTACH] statement for an attached database. -** ^The S and M arguments passed to +** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** -** ^A call to sqlite3_backup_init() will fail, returning NULL, if -** there is already a read or read-write transaction open on the +** ^A call to sqlite3_backup_init() will fail, returning NULL, if +** there is already a read or read-write transaction open on the ** destination database. ** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. @@ -9643,18 +8653,18 @@ ** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or ** [sqlite3_errmsg16()] functions. ** ^A successful call to sqlite3_backup_init() returns a pointer to an ** [sqlite3_backup] object. ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and -** sqlite3_backup_finish() functions to perform the specified backup +** sqlite3_backup_finish() functions to perform the specified backup ** operation. ** ** [[sqlite3_backup_step()]] sqlite3_backup_step() ** -** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between ** the source and destination databases specified by [sqlite3_backup] object B. -** ^If N is negative, all remaining source pages are copied. +** ^If N is negative, all remaining source pages are copied. ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there ** are still more pages to be copied, then the function returns [SQLITE_OK]. ** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages ** from source to destination, then it returns [SQLITE_DONE]. ** ^If an error occurs while running sqlite3_backup_step(B,N), @@ -9672,48 +8682,48 @@ ** destination and source page sizes differ. ** )^ ** ** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then ** the [sqlite3_busy_handler | busy-handler function] -** is invoked (if one is specified). ^If the -** busy-handler returns non-zero before the lock is available, then +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then ** [SQLITE_BUSY] is returned to the caller. ^In this case the call to ** sqlite3_backup_step() can be retried later. ^If the source ** [database connection] ** is being used to write to the source database when sqlite3_backup_step() ** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this ** case the call to sqlite3_backup_step() can be retried later on. ^(If ** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or -** [SQLITE_READONLY] is returned, then -** there is no point in retrying the call to sqlite3_backup_step(). These -** errors are considered fatal.)^ The application must accept -** that the backup operation has failed and pass the backup operation handle +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle ** to the sqlite3_backup_finish() to release associated resources. ** ** ^The first call to sqlite3_backup_step() obtains an exclusive lock -** on the destination file. ^The exclusive lock is not released until either -** sqlite3_backup_finish() is called or the backup operation is complete +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete ** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to ** sqlite3_backup_step() obtains a [shared lock] on the source database that ** lasts for the duration of the sqlite3_backup_step() call. ** ^Because the source database is not locked between calls to ** sqlite3_backup_step(), the source database may be modified mid-way ** through the backup process. ^If the source database is modified by an ** external process or via a database connection other than the one being ** used by the backup operation, then the backup will be automatically -** restarted by the next call to sqlite3_backup_step(). ^If the source +** restarted by the next call to sqlite3_backup_step(). ^If the source ** database is modified by the using the same database connection as is used ** by the backup operation, then the backup database is automatically ** updated at the same time. ** ** [[sqlite3_backup_finish()]] sqlite3_backup_finish() ** -** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the ** application wishes to abandon the backup operation, the application ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). ** ^The sqlite3_backup_finish() interfaces releases all -** resources associated with the [sqlite3_backup] object. +** resources associated with the [sqlite3_backup] object. ** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any ** active write-transaction on the destination database is rolled back. ** The [sqlite3_backup] object is invalid ** and may not be used following a call to sqlite3_backup_finish(). ** @@ -9749,42 +8759,32 @@ ** purposes while a backup operation is underway or being initialized. ** ^If SQLite is compiled and configured to support threadsafe database ** connections, then the source database connection may be used concurrently ** from within other threads. ** -** However, the application must guarantee that the destination -** [database connection] is not passed to any other API (by any thread) after +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after ** sqlite3_backup_init() is called and before the corresponding call to ** sqlite3_backup_finish(). SQLite does not currently check to see ** if the application incorrectly accesses the destination [database connection] ** and so no error code is reported, but the operations may malfunction ** nevertheless. Use of the destination database connection while a -** backup is in progress might also cause a mutex deadlock. +** backup is in progress might also also cause a mutex deadlock. ** ** If running in [shared cache mode], the application must ** guarantee that the shared cache used by the destination database ** is not accessed while the backup is running. In practice this means -** that the application must guarantee that the disk file being +** that the application must guarantee that the disk file being ** backed up to is not accessed by any connection within the process, ** not just the specific connection that was passed to sqlite3_backup_init(). ** -** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** The [sqlite3_backup] object itself is partially threadsafe. Multiple ** threads may safely make multiple concurrent calls to sqlite3_backup_step(). ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** APIs are not strictly speaking threadsafe. If they are invoked at the ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. -** -** Alternatives To Using The Backup API -** -** Other techniques for safely creating a consistent backup of an SQLite -** database include: -** -**
      -**
    • The [VACUUM INTO] command. -**
    • The [sqlite3_rsync] utility program. -**
    */ SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ @@ -9800,49 +8800,49 @@ ** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or ** individual tables within the shared-cache cannot be obtained. See -** [SQLite Shared-Cache Mode] for a description of shared-cache locking. -** ^This API may be used to register a callback that SQLite will invoke +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke ** when the connection currently holding the required lock relinquishes it. ** ^This API is only available if the library was compiled with the ** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. ** ** See Also: [Using the SQLite Unlock Notification Feature]. ** ** ^Shared-cache locks are released when a database connection concludes -** its current transaction, either by committing it or rolling it back. +** its current transaction, either by committing it or rolling it back. ** ** ^When a connection (known as the blocked connection) fails to obtain a ** shared-cache lock and SQLITE_LOCKED is returned to the caller, the ** identity of the database connection (the blocking connection) that -** has locked the required resource is stored internally. ^After an +** has locked the required resource is stored internally. ^After an ** application receives an SQLITE_LOCKED error, it may call the -** sqlite3_unlock_notify() method with the blocked connection handle as +** sqlite3_unlock_notify() method with the blocked connection handle as ** the first argument to register for a callback that will be invoked ** when the blocking connections current transaction is concluded. ^The ** callback is invoked from within the [sqlite3_step] or [sqlite3_close] -** call that concludes the blocking connection's transaction. +** call that concludes the blocking connections transaction. ** ** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, ** there is a chance that the blocking connection will have already ** concluded its transaction by the time sqlite3_unlock_notify() is invoked. ** If this happens, then the specified callback is invoked immediately, ** from within the call to sqlite3_unlock_notify().)^ ** ** ^If the blocked connection is attempting to obtain a write-lock on a ** shared-cache table, and more than one other connection currently holds -** a read-lock on the same table, then SQLite arbitrarily selects one of +** a read-lock on the same table, then SQLite arbitrarily selects one of ** the other connections to use as the blocking connection. ** -** ^(There may be at most one unlock-notify callback registered by a +** ^(There may be at most one unlock-notify callback registered by a ** blocked connection. If sqlite3_unlock_notify() is called when the ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback is canceled. ^The blocked connections ** unlock-notify callback may also be canceled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes ** any sqlite3_xxx API functions from within an unlock-notify callback, a @@ -9851,29 +8851,29 @@ ** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always ** returns SQLITE_OK. ** ** Callback Invocation Details ** -** When an unlock-notify callback is registered, the application provides a +** When an unlock-notify callback is registered, the application provides a ** single void* pointer that is passed to the callback when it is invoked. ** However, the signature of the callback function allows SQLite to pass ** it an array of void* context pointers. The first argument passed to ** an unlock-notify callback is a pointer to an array of void* pointers, ** and the second is the number of entries in the array. ** -** When a blocking connection's transaction is concluded, there may be +** When a blocking connections transaction is concluded, there may be ** more than one blocked connection that has registered for an unlock-notify ** callback. ^If two or more such blocked connections have specified the ** same callback function, then instead of invoking the callback function ** multiple times, it is invoked once with the set of void* context pointers ** specified by the blocked connections bundled together into an array. -** This gives the application an opportunity to prioritize any actions +** This gives the application an opportunity to prioritize any actions ** related to the set of unblocked database connections. ** ** Deadlock Detection ** -** Assuming that after registering for an unlock-notify callback a +** Assuming that after registering for an unlock-notify callback a ** database waits for the callback to be issued before taking any further ** action (a reasonable assumption), then using this API may cause the ** application to deadlock. For example, if connection X is waiting for ** connection Y's transaction to be concluded, and similarly connection ** Y is waiting on connection X's transaction, then neither connection @@ -9892,11 +8892,11 @@ ** C's transaction, where connection C is waiting on connection A. ^Any ** number of levels of indirection are allowed. ** ** The "DROP TABLE" Exception ** -** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost ** always appropriate to call sqlite3_unlock_notify(). There is however, ** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, ** SQLite checks if there are any currently executing SELECT statements ** that belong to the same connection. If there are, SQLITE_LOCKED is ** returned. In this case there is no "blocking connection", so invoking @@ -9905,11 +8905,11 @@ ** or "DROP INDEX" query, an infinite loop might be the result. ** ** One way around this problem is to check the extended error code returned ** by an sqlite3_step() call. ^(If there is a blocking connection, then the ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in -** the special "DROP TABLE/INDEX" case, the extended error code is just +** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ @@ -9996,12 +8996,12 @@ ** METHOD: sqlite3 ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** is invoked each time data is committed to a database in wal mode. ** -** ^(The callback is invoked by SQLite after the commit has taken place and -** the associated write-lock on the database released)^, so the implementation +** ^(The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released)^, so the implementation ** may read, write or [checkpoint] the database as required. ** ** ^The first parameter passed to the callback function when it is invoked ** is a copy of the third parameter passed to sqlite3_wal_hook() when ** registering the callback. ^The second is a copy of the database handle. @@ -10016,20 +9016,19 @@ ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** -** A single database handle may have at most a single write-ahead log callback +** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any -** previously registered write-ahead log callback. ^The return value is -** a copy of the third parameter from the previous call, if any, or 0. -** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the +** previously registered write-ahead log callback. ^Note that the +** [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( - sqlite3*, + sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* ); /* @@ -10038,11 +9037,11 @@ ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D ** to automatically [checkpoint] ** after committing a transaction if there are N or -** more frames in the [write-ahead log] file. ^Passing zero or +** more frames in the [write-ahead log] file. ^Passing zero or ** a negative value as the nFrame parameter disables automatic ** checkpoints entirely. ** ** ^The callback registered by this function replaces any existing callback ** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback @@ -10068,11 +9067,11 @@ ** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ ** -** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the ** [write-ahead log] for database X on [database connection] D to be ** transferred into the database file and for the write-ahead log to ** be reset. See the [checkpointing] documentation for addition ** information. ** @@ -10094,14 +9093,14 @@ ** information is written back into integers pointed to by L and C.)^ ** ^(The M parameter must be a valid [checkpoint mode]:)^ ** **
    **
    SQLITE_CHECKPOINT_PASSIVE
    -** ^Checkpoint as many frames as possible without waiting for any database -** readers or writers to finish, then sync the database file if all frames +** ^Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish, then sync the database file if all frames ** in the log were checkpointed. ^The [busy-handler callback] -** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. ** ^On the other hand, passive mode might leave the checkpoint unfinished ** if there are concurrent readers or writers. ** **
    SQLITE_CHECKPOINT_FULL
    ** ^This mode blocks (it invokes the @@ -10111,13 +9110,13 @@ ** database file. ^This mode blocks new database writers while it is pending, ** but new database readers are allowed to continue unimpeded. ** **
    SQLITE_CHECKPOINT_RESTART
    ** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition -** that after checkpointing the log file it blocks (calls the +** that after checkpointing the log file it blocks (calls the ** [busy-handler callback]) -** until all readers are reading from the database file only. ^This ensures +** until all readers are reading from the database file only. ^This ensures ** that the next writer will restart the log file from the beginning. ** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new ** database writer attempts while it is pending, but does not impede readers. ** **
    SQLITE_CHECKPOINT_TRUNCATE
    @@ -10135,35 +9134,35 @@ ** because the database is not in WAL mode. ^Note that upon successful ** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been ** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. ** ** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If -** any other process is running a checkpoint operation at the same time, the -** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a ** busy-handler configured, it will not be invoked in this case. ** -** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the ** exclusive "writer" lock on the database file. ^If the writer lock cannot be ** obtained immediately, and a busy-handler is configured, it is invoked and ** the writer lock retried until either the busy-handler returns 0 or the lock ** is successfully obtained. ^The busy-handler is also invoked while waiting for ** database readers as described above. ^If the busy-handler returns 0 before ** the writer lock is obtained or while waiting for database readers, the -** checkpoint operation proceeds from that point in the same way as -** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible ** without blocking any further. ^SQLITE_BUSY is returned in this case. ** ** ^If parameter zDb is NULL or points to a zero length string, then the -** specified operation is attempted on all WAL databases [attached] to +** specified operation is attempted on all WAL databases [attached] to ** [database connection] db. In this case the -** values written to output parameters *pnLog and *pnCkpt are undefined. ^If -** an SQLITE_BUSY error is encountered when processing one or more of the -** attached WAL databases, the operation is still attempted on any remaining -** attached databases and SQLITE_BUSY is returned at the end. ^If any other -** error occurs while processing an attached database, processing is abandoned -** and the error code is returned to the caller immediately. ^If no error -** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned at the end. ^If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code is returned to the caller immediately. ^If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached ** databases, SQLITE_OK is returned. ** ** ^If database zDb is the name of an attached database that is not in WAL ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If ** zDb is not NULL (or a zero length string) and is not the name of any @@ -10194,11 +9193,11 @@ ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the ** meaning of each of these checkpoint modes. */ #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ -#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ #define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ /* ** CAPI3REF: Virtual Table Interface Configuration ** @@ -10207,32 +9206,25 @@ ** various facets of the virtual table interface. ** ** If this interface is invoked outside the context of an xConnect or ** xCreate virtual table method then the behavior is undefined. ** -** In the call sqlite3_vtab_config(D,C,...) the D parameter is the -** [database connection] in which the virtual table is being created and -** which is passed in as the first argument to the [xConnect] or [xCreate] -** method that is invoking sqlite3_vtab_config(). The C parameter is one -** of the [virtual table configuration options]. The presence and meaning -** of parameters after C depend on which [virtual table configuration option] -** is used. +** At present, there is only one option that may be configured using +** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options +** may be added in the future. */ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options -** KEYWORDS: {virtual table configuration options} -** KEYWORDS: {virtual table configuration option} ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** **
    -** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] -**
    SQLITE_VTAB_CONSTRAINT_SUPPORT
    +**
    SQLITE_VTAB_CONSTRAINT_SUPPORT **
    Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if @@ -10242,60 +9234,28 @@ ** ON CONFLICT mode specified. ** ** If X is non-zero, then the virtual table implementation guarantees ** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before ** any modifications to internal or persistent data structures have been made. -** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite ** is able to roll back a statement or database transaction, and abandon -** or continue processing the current SQL statement as appropriate. +** or continue processing the current SQL statement as appropriate. ** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns ** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode ** had been ABORT. ** ** Virtual table implementations that are required to handle OR REPLACE -** must do so within the [xUpdate] method. If a call to the -** [sqlite3_vtab_on_conflict()] function indicates that the current ON -** CONFLICT policy is REPLACE, the virtual table implementation should +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should ** silently replace the appropriate rows within the xUpdate callback and ** return SQLITE_OK. Or, if this is not possible, it may return -** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT ** constraint handling. -**
    -** -** [[SQLITE_VTAB_DIRECTONLY]]
    SQLITE_VTAB_DIRECTONLY
    -**
    Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** prohibits that virtual table from being used from within triggers and -** views. -**
    -** -** [[SQLITE_VTAB_INNOCUOUS]]
    SQLITE_VTAB_INNOCUOUS
    -**
    Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** identify that virtual table as being safe to use from within triggers -** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the -** virtual table can do no serious harm even if it is controlled by a -** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS -** flag unless absolutely necessary. -**
    -** -** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]
    SQLITE_VTAB_USES_ALL_SCHEMAS
    -**
    Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** instruct the query planner to begin at least a read transaction on -** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the -** virtual table is used. -**
    **
    */ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 -#define SQLITE_VTAB_INNOCUOUS 2 -#define SQLITE_VTAB_DIRECTONLY 3 -#define SQLITE_VTAB_USES_ALL_SCHEMAS 4 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy ** ** This function may only be called from within a call to the [xUpdate] method @@ -10305,328 +9265,10 @@ ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ 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 might return true if the -** column is being fetched as part of an UPDATE operation during which the -** column value will not change. The virtual table implementation can use -** this hint as permission to substitute a return value that is less -** expensive to compute and that the corresponding -** [xUpdate] method understands as a "no-change" value. -** -** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that -** the column is not changed by the UPDATE statement, then 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. -** -** The sqlite3_vtab_nochange() routine is an optimization. Virtual table -** implementations should continue to give a correct answer even if the -** sqlite3_vtab_nochange() interface were to always return false. In the -** current implementation, the sqlite3_vtab_nochange() interface does always -** returns false for the enhanced [UPDATE FROM] statement. -*/ -SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); - -/* -** CAPI3REF: Determine The Collation For a Virtual Table Constraint -** METHOD: sqlite3_index_info -** -** This function may only be called from within a call to the [xBestIndex] -** method of a [virtual table]. This function returns a pointer to a string -** that is the name of the appropriate collation sequence to use for text -** comparisons on the constraint identified by its arguments. -** -** The first argument must be the pointer to the [sqlite3_index_info] object -** that is the first parameter to the xBestIndex() method. The second argument -** must be an index into the aConstraint[] array belonging to the -** sqlite3_index_info structure passed to xBestIndex. -** -** Important: -** The first parameter must be the same pointer that is passed into the -** xBestMethod() method. The first parameter may not be a pointer to a -** different [sqlite3_index_info] object, even an exact copy. -** -** The return value is computed as follows: -** -**
      -**
    1. If the constraint comes from a WHERE clause expression that contains -** a [COLLATE operator], then the name of the collation specified by -** that COLLATE operator is returned. -**

    2. If there is no COLLATE operator, but the column that is the subject -** of the constraint specifies an alternative collating sequence via -** a [COLLATE clause] on the column definition within the CREATE TABLE -** statement that was passed into [sqlite3_declare_vtab()], then the -** name of that alternative collating sequence is returned. -**

    3. Otherwise, "BINARY" is returned. -**

    -*/ -SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); - -/* -** CAPI3REF: Determine if a virtual table query is DISTINCT -** METHOD: sqlite3_index_info -** -** This API may only be used from within an [xBestIndex|xBestIndex method] -** of a [virtual table] implementation. The result of calling this -** interface from outside of xBestIndex() is undefined and probably harmful. -** -** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and -** 3. The integer returned by sqlite3_vtab_distinct() -** gives the virtual table additional information about how the query -** planner wants the output to be ordered. As long as the virtual table -** can meet the ordering requirements of the query planner, it may set -** the "orderByConsumed" flag. -** -**
    1. -** ^If the sqlite3_vtab_distinct() interface returns 0, that means -** that the query planner needs the virtual table to return all rows in the -** sort order defined by the "nOrderBy" and "aOrderBy" fields of the -** [sqlite3_index_info] object. This is the default expectation. If the -** virtual table outputs all rows in sorted order, then it is always safe for -** the xBestIndex method to set the "orderByConsumed" flag, regardless of -** the return value from sqlite3_vtab_distinct(). -**

    2. -** ^(If the sqlite3_vtab_distinct() interface returns 1, that means -** that the query planner does not need the rows to be returned in sorted order -** as long as all rows with the same values in all columns identified by the -** "aOrderBy" field are adjacent.)^ This mode is used when the query planner -** is doing a GROUP BY. -**

    3. -** ^(If the sqlite3_vtab_distinct() interface returns 2, that means -** that the query planner does not need the rows returned in any particular -** order, as long as rows with the same values in all columns identified -** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows -** contain the same values for all columns identified by "colUsed", all but -** one such row may optionally be omitted from the result.)^ -** The virtual table is not required to omit rows that are duplicates -** over the "colUsed" columns, but if the virtual table can do that without -** too much extra effort, it could potentially help the query to run faster. -** This mode is used for a DISTINCT query. -**

    4. -** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the -** virtual table must return rows in the order defined by "aOrderBy" as -** if the sqlite3_vtab_distinct() interface had returned 0. However if -** two or more rows in the result have the same values for all columns -** identified by "colUsed", then all but one such row may optionally be -** omitted.)^ Like when the return value is 2, the virtual table -** is not required to omit rows that are duplicates over the "colUsed" -** columns, but if the virtual table can do that without -** too much extra effort, it could potentially help the query to run faster. -** This mode is used for queries -** that have both DISTINCT and ORDER BY clauses. -**

    -** -**

    The following table summarizes the conditions under which the -** virtual table is allowed to set the "orderByConsumed" flag based on -** the value returned by sqlite3_vtab_distinct(). This table is a -** restatement of the previous four paragraphs: -** -** -** -**
    sqlite3_vtab_distinct() return value -** Rows are returned in aOrderBy order -** Rows with the same value in all aOrderBy columns are adjacent -** Duplicates over all colUsed columns may be omitted -**
    0yesyesno -**
    1noyesno -**
    2noyesyes -**
    3yesyesyes -**
    -** -** ^For the purposes of comparing virtual table output values to see if the -** values are same value for sorting purposes, two NULL values are considered -** to be the same. In other words, the comparison operator is "IS" -** (or "IS NOT DISTINCT FROM") and not "==". -** -** If a virtual table implementation is unable to meet the requirements -** specified above, then it must not set the "orderByConsumed" flag in the -** [sqlite3_index_info] object or an incorrect answer may result. -** -** ^A virtual table implementation is always free to return rows in any order -** it wants, as long as the "orderByConsumed" flag is not set. ^When the -** the "orderByConsumed" flag is unset, the query planner will add extra -** [bytecode] to ensure that the final results returned by the SQL query are -** ordered correctly. The use of the "orderByConsumed" flag and the -** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful -** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" -** flag might help queries against a virtual table to run faster. Being -** overly aggressive and setting the "orderByConsumed" flag when it is not -** valid to do so, on the other hand, might cause SQLite to return incorrect -** results. -*/ -SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); - -/* -** CAPI3REF: Identify and handle IN constraints in xBestIndex -** -** This interface may only be used from within an -** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. -** The result of invoking this interface from any other context is -** undefined and probably harmful. -** -** ^(A constraint on a virtual table of the form -** "[IN operator|column IN (...)]" is -** communicated to the xBestIndex method as a -** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use -** this constraint, it must set the corresponding -** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under -** the usual mode of handling IN operators, SQLite generates [bytecode] -** that invokes the [xFilter|xFilter() method] once for each value -** on the right-hand side of the IN operator.)^ Thus the virtual table -** only sees a single value from the right-hand side of the IN operator -** at a time. -** -** In some cases, however, it would be advantageous for the virtual -** table to see all values on the right-hand of the IN operator all at -** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: -** -**

      -**
    1. -** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) -** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint -** is an [IN operator] that can be processed all at once. ^In other words, -** sqlite3_vtab_in() with -1 in the third argument is a mechanism -** by which the virtual table can ask SQLite if all-at-once processing -** of the IN operator is even possible. -** -**

    2. -** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates -** to SQLite that the virtual table does or does not want to process -** the IN operator all-at-once, respectively. ^Thus when the third -** parameter (F) is non-negative, this interface is the mechanism by -** which the virtual table tells SQLite how it wants to process the -** IN operator. -**

    -** -** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times -** within the same xBestIndex method call. ^For any given P,N pair, -** the return value from sqlite3_vtab_in(P,N,F) will always be the same -** within the same xBestIndex call. ^If the interface returns true -** (non-zero), that means that the constraint is an IN operator -** that can be processed all-at-once. ^If the constraint is not an IN -** operator or cannot be processed all-at-once, then the interface returns -** false. -** -** ^(All-at-once processing of the IN operator is selected if both of the -** following conditions are met: -** -**
      -**
    1. The P->aConstraintUsage[N].argvIndex value is set to a positive -** integer. This is how the virtual table tells SQLite that it wants to -** use the N-th constraint. -** -**

    2. The last call to sqlite3_vtab_in(P,N,F) for which F was -** non-negative had F>=1. -**

    )^ -** -** ^If either or both of the conditions above are false, then SQLite uses -** the traditional one-at-a-time processing strategy for the IN constraint. -** ^If both conditions are true, then the argvIndex-th parameter to the -** xFilter method will be an [sqlite3_value] that appears to be NULL, -** but which can be passed to [sqlite3_vtab_in_first()] and -** [sqlite3_vtab_in_next()] to find all values on the right-hand side -** of the IN constraint. -*/ -SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); - -/* -** CAPI3REF: Find all elements on the right-hand side of an IN constraint. -** -** These interfaces are only useful from within the -** [xFilter|xFilter() method] of a [virtual table] implementation. -** The result of invoking these interfaces from any other context -** is undefined and probably harmful. -** -** The X parameter in a call to sqlite3_vtab_in_first(X,P) or -** sqlite3_vtab_in_next(X,P) should be one of the parameters to the -** xFilter method which invokes these routines, and specifically -** a parameter that was previously selected for all-at-once IN constraint -** processing use the [sqlite3_vtab_in()] interface in the -** [xBestIndex|xBestIndex method]. ^(If the X parameter is not -** an xFilter argument that was selected for all-at-once IN constraint -** processing, then these routines return [SQLITE_ERROR].)^ -** -** ^(Use these routines to access all values on the right-hand side -** of the IN constraint using code like the following: -** -**
    -**    for(rc=sqlite3_vtab_in_first(pList, &pVal);
    -**        rc==SQLITE_OK && pVal;
    -**        rc=sqlite3_vtab_in_next(pList, &pVal)
    -**    ){
    -**      // do something with pVal
    -**    }
    -**    if( rc!=SQLITE_OK ){
    -**      // an error has occurred
    -**    }
    -** 
    )^ -** -** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) -** routines return SQLITE_OK and set *P to point to the first or next value -** on the RHS of the IN constraint. ^If there are no more values on the -** right hand side of the IN constraint, then *P is set to NULL and these -** routines return [SQLITE_DONE]. ^The return value might be -** some other value, such as SQLITE_NOMEM, in the event of a malfunction. -** -** The *ppOut values returned by these routines are only valid until the -** next call to either of these routines or until the end of the xFilter -** method from which these routines were called. If the virtual table -** implementation needs to retain the *ppOut values for longer, it must make -** copies. The *ppOut values are [protected sqlite3_value|protected]. -*/ -SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); -SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); - -/* -** CAPI3REF: Constraint values in xBestIndex() -** METHOD: sqlite3_index_info -** -** This API may only be used from within the [xBestIndex|xBestIndex method] -** of a [virtual table] implementation. The result of calling this interface -** from outside of an xBestIndex method are undefined and probably harmful. -** -** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within -** the [xBestIndex] method of a [virtual table] implementation, with P being -** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and -** J being a 0-based index into P->aConstraint[], then this routine -** attempts to set *V to the value of the right-hand operand of -** that constraint if the right-hand operand is known. ^If the -** right-hand operand is not known, then *V is set to a NULL pointer. -** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if -** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) -** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th -** constraint is not available. ^The sqlite3_vtab_rhs_value() interface -** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if -** something goes wrong. -** -** The sqlite3_vtab_rhs_value() interface is usually only successful if -** the right-hand operand of a constraint is a literal value in the original -** SQL statement. If the right-hand operand is an expression or a reference -** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() -** will probably return [SQLITE_NOTFOUND]. -** -** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and -** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such -** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ -** -** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value -** and remains valid for the duration of the xBestIndex method call. -** ^When xBestIndex returns, the sqlite3_value object returned by -** sqlite3_vtab_rhs_value() is automatically deallocated. -** -** The "_rhs_" in the name of this routine is an abbreviation for -** "Right-Hand Side". -*/ -SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); - /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} ** ** These constants are returned by [sqlite3_vtab_on_conflict()] to @@ -10653,75 +9295,57 @@ ** ** When the value returned to V is a string, space to hold that string is ** managed by the prepared statement S and will be automatically freed when ** S is finalized. ** -** Not all values are available for all query elements. When a value is -** not available, the output variable is set to -1 if the value is numeric, -** or to NULL if it is a string (SQLITE_SCANSTAT_NAME). -** **
    ** [[SQLITE_SCANSTAT_NLOOP]]
    SQLITE_SCANSTAT_NLOOP
    -**
    ^The [sqlite3_int64] variable pointed to by the V parameter will be +**
    ^The [sqlite3_int64] variable pointed to by the T parameter will be ** set to the total number of times that the X-th loop has run.
    ** ** [[SQLITE_SCANSTAT_NVISIT]]
    SQLITE_SCANSTAT_NVISIT
    -**
    ^The [sqlite3_int64] variable pointed to by the V parameter will be set +**
    ^The [sqlite3_int64] variable pointed to by the T parameter will be set ** to the total number of rows examined by all iterations of the X-th loop.
    ** ** [[SQLITE_SCANSTAT_EST]]
    SQLITE_SCANSTAT_EST
    -**
    ^The "double" variable pointed to by the V parameter will be set to the +**
    ^The "double" variable pointed to by the T parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]]
    SQLITE_SCANSTAT_NAME
    -**
    ^The "const char *" variable pointed to by the V parameter will be set +**
    ^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the name of the index or table ** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]]
    SQLITE_SCANSTAT_EXPLAIN
    -**
    ^The "const char *" variable pointed to by the V parameter will be set +**
    ^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. ** -** [[SQLITE_SCANSTAT_SELECTID]]
    SQLITE_SCANSTAT_SELECTID
    -**
    ^The "int" variable pointed to by the V parameter will be set to the -** id for the X-th query plan element. The id value is unique within the -** statement. The select-id is the same value as is output in the first -** column of an [EXPLAIN QUERY PLAN] query. -** -** [[SQLITE_SCANSTAT_PARENTID]]
    SQLITE_SCANSTAT_PARENTID
    -**
    The "int" variable pointed to by the V parameter will be set to the -** the id of the parent of the current query element, if applicable, or -** to zero if the query element has no parent. This is the same value as -** returned in the second column of an [EXPLAIN QUERY PLAN] query. -** -** [[SQLITE_SCANSTAT_NCYCLE]]
    SQLITE_SCANSTAT_NCYCLE
    -**
    The sqlite3_int64 output value is set to the number of cycles, -** according to the processor time-stamp counter, that elapsed while the -** query element was being processed. This value is not available for -** all query elements - if it is unavailable the output variable is -** set to -1. +** [[SQLITE_SCANSTAT_SELECTID]]
    SQLITE_SCANSTAT_SELECT
    +**
    ^The "int" variable pointed to by the T parameter will be set to the +** "select-id" for the X-th loop. The select-id identifies which query or +** subquery the loop is part of. The main query has a select-id of zero. +** The select-id is the same value as is output in the first column +** of an [EXPLAIN QUERY PLAN] query. **
    */ #define SQLITE_SCANSTAT_NLOOP 0 #define SQLITE_SCANSTAT_NVISIT 1 #define SQLITE_SCANSTAT_EST 2 #define SQLITE_SCANSTAT_NAME 3 #define SQLITE_SCANSTAT_EXPLAIN 4 #define SQLITE_SCANSTAT_SELECTID 5 -#define SQLITE_SCANSTAT_PARENTID 6 -#define SQLITE_SCANSTAT_NCYCLE 7 /* ** CAPI3REF: Prepared Statement Scan Status ** METHOD: sqlite3_stmt ** -** These interfaces return information about the predicted and measured +** This interface returns information about the predicted and measured ** performance for pStmt. Advanced applications can use this ** interface to compare the predicted and the measured performance and ** issue warnings and/or rerun [ANALYZE] if discrepancies are found. ** ** Since this interface is expected to be rarely used, it is only @@ -10728,51 +9352,32 @@ ** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS] ** compile-time option. ** ** The "iScanStatusOp" parameter determines which status information to return. ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior -** of this interface is undefined. ^The requested measurement is written into -** a variable pointed to by the "pOut" parameter. -** -** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX -** is specified, then status information is available for all elements -** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If -** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements -** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of -** the EXPLAIN QUERY PLAN output) are available. Invoking API -** sqlite3_stmt_scanstatus() is equivalent to calling -** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter. -** -** Parameter "idx" identifies the specific query element to retrieve statistics -** for. Query elements are numbered starting from zero. A value of -1 may be -** to query for statistics regarding the entire query. ^If idx is out of range -** - less than -1 or greater than or equal to the total number of query -** elements used to implement the statement - a non-zero value is returned and -** the variable that pOut points to is unchanged. +** of this interface is undefined. +** ^The requested measurement is written into a variable pointed to by +** the "pOut" parameter. +** Parameter "idx" identifies the specific loop to retrieve statistics for. +** Loops are numbered starting from zero. ^If idx is out of range - less than +** zero or greater than or equal to the total number of loops used to implement +** the statement - a non-zero value is returned and the variable that pOut +** points to is unchanged. +** +** ^Statistics might not be available for all loops in all statements. ^In cases +** where there exist loops with no available statistics, this function behaves +** as if the loop did not exist - it returns non-zero and leave the variable +** that pOut points to unchanged. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ -); -SQLITE_API int sqlite3_stmt_scanstatus_v2( - sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ - int flags, /* Mask of flags defined below */ - void *pOut /* Result written here */ -); - -/* -** CAPI3REF: Prepared Statement Scan Status -** KEYWORDS: {scan status flags} -*/ -#define SQLITE_SCANSTAT_COMPLEX 0x0001 +); /* ** CAPI3REF: Zero Scan-Status Counters ** METHOD: sqlite3_stmt ** @@ -10783,23 +9388,22 @@ */ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction -** METHOD: sqlite3 ** ** ^If a write-transaction is open on [database connection] D when the ** [sqlite3_db_cacheflush(D)] interface invoked, any dirty -** pages in the pager-cache that are not currently in use are written out +** pages in the pager-cache that are not currently in use are written out ** to disk. A dirty page may be in use if a database cursor created by an ** active SQL statement is reading from it, or if it is page 1 of a database ** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)] ** interface flushes caches for all schemas - "main", "temp", and ** any [attached] databases. ** -** ^If this function needs to obtain extra database locks before dirty pages -** can be flushed to disk, it does so. ^If those locks cannot be obtained +** ^If this function needs to obtain extra database locks before dirty pages +** can be flushed to disk, it does so. ^If those locks cannot be obtained ** immediately and there is a busy-handler callback configured, it is invoked ** in the usual manner. ^If the required lock still cannot be obtained, then ** the database is skipped and an attempt made to flush any dirty pages ** belonging to the next (if any) database. ^If any databases are skipped ** because locks cannot be obtained, but no other error occurs, this @@ -10816,11 +9420,10 @@ */ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); /* ** CAPI3REF: The pre-update hook. -** METHOD: sqlite3 ** ** ^These interfaces are only available if SQLite is compiled using the ** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. ** ** ^The [sqlite3_preupdate_hook()] interface registers a callback function @@ -10834,38 +9437,34 @@ ** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as ** the first parameter to callbacks. ** ** ^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_sequence or sqlite_stat1. +** 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. ** ^The third parameter to the preupdate callback is one of the constants ** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the ** kind of update operation that is about to occur. ** ^(The fourth parameter to the preupdate callback is the name of the ** database within the database connection that is being modified. This -** will be "main" for the main database or "temp" for TEMP tables or +** will be "main" for the main database or "temp" for TEMP tables or ** the name given after the AS keyword in the [ATTACH] statement for attached ** databases.)^ ** ^The fifth parameter to the preupdate callback is the name of the ** table that is being modified. ** ** For an UPDATE or DELETE operation on a [rowid table], the sixth -** parameter passed to the preupdate callback is the initial [rowid] of the +** parameter passed to the preupdate callback is the initial [rowid] of the ** row being modified or deleted. For an INSERT operation on a rowid table, -** or any operation on a WITHOUT ROWID table, the value of the sixth +** or any operation on a WITHOUT ROWID table, the value of the sixth ** parameter is undefined. For an INSERT or UPDATE on a rowid table the ** seventh parameter is the final rowid value of the row being inserted ** or updated. The value of the seventh parameter passed to the callback ** function is not defined for operations on WITHOUT ROWID tables, or for -** DELETE operations on rowid tables. -** -** ^The sqlite3_preupdate_hook(D,C,P) function returns the P argument from -** the previous call on the same [database connection] D, or NULL for -** the first call on D. +** INSERT operations on rowid tables. ** ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces ** provide additional information about a preupdate event. These routines ** may only be called from within a preupdate callback. Invoking any of @@ -10895,23 +9494,14 @@ ** behavior is undefined. The [sqlite3_value] that P points to ** will be destroyed when the preupdate callback returns. ** ** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate ** callback was invoked as a result of a direct insert, update, or delete -** operation; or 1 for inserts, updates, or deletes invoked by top-level +** operation; or 1 for inserts, updates, or deletes invoked by top-level ** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; and so forth. ** -** When the [sqlite3_blob_write()] API is used to update a blob column, -** the pre-update hook is invoked with SQLITE_DELETE. This is because the -** in this case the new values are not available. In this case, when a -** callback made with op==SQLITE_DELETE is actually a write using the -** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns -** the index of the column being written. In other cases, where the -** pre-update hook is being invoked for some other reason, including a -** regular DELETE, sqlite3_preupdate_blobwrite() returns -1. -** ** See also: [sqlite3_update_hook()] */ #if defined(SQLITE_ENABLE_PREUPDATE_HOOK) SQLITE_API void *sqlite3_preupdate_hook( sqlite3 *db, @@ -10928,29 +9518,28 @@ ); SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); SQLITE_API int sqlite3_preupdate_count(sqlite3 *); SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); -SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *); #endif /* ** CAPI3REF: Low-level system error code -** METHOD: sqlite3 ** ** ^Attempt to return the underlying operating system error code or error ** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be ** called to get back the underlying "errno" that caused the problem, such -** as ENOSPC, EAUTH, EISDIR, and so forth. +** as ENOSPC, EAUTH, EISDIR, and so forth. */ SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot ** KEYWORDS: {snapshot} {sqlite3_snapshot} +** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] ** database for some specific point in history. ** ** In [WAL mode], multiple [database connections] that are open on the @@ -10963,356 +9552,181 @@ ** ** The sqlite3_snapshot object records state information about an historical ** version of the database file so that it is possible to later open a new read ** transaction that sees that historical version of the database rather than ** the most recent version. +** +** The constructor for this object is [sqlite3_snapshot_get()]. The +** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer +** to an historical snapshot (if possible). The destructor for +** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ typedef struct sqlite3_snapshot { unsigned char hidden[48]; } sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot -** CONSTRUCTOR: sqlite3_snapshot +** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a ** new [sqlite3_snapshot] object that records the current state of ** 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 there is not already a read-transaction open on schema S when -** this function is called, one is opened automatically. -** -** If a read-transaction is opened by this function, then it is guaranteed -** that the returned snapshot object may not be invalidated by a database -** writer or checkpointer until after the read-transaction is closed. This -** is not guaranteed if a read-transaction is already open when this -** function is called. In that case, any subsequent write or checkpoint -** operation on the database may invalidate the returned snapshot handle, -** even while the read-transaction remains open. +** this function is called, one is opened automatically. ** ** The following must be true for this function to succeed. If any of ** the following statements are false when sqlite3_snapshot_get() is ** called, SQLITE_ERROR is returned. The final value of *P is undefined -** in this case. +** in this case. ** **
      -**
    • The database handle must not be in [autocommit mode]. +**
    • 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 +** that a snapshot cannot be taken on a wal mode database with no wal ** file immediately after it is first opened. At least one transaction ** must be written to it first. **
    ** ** This function may also return SQLITE_NOMEM. If it is called with the -** database handle in autocommit mode but fails for some other reason, +** database handle in autocommit mode but fails for some other reason, ** whether or not a read transaction is opened on schema S is undefined. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** ** The [sqlite3_snapshot_get()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot ); /* ** CAPI3REF: Start a read transaction on an historical snapshot -** METHOD: sqlite3_snapshot -** -** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read -** transaction or upgrades an existing one for schema S of -** [database connection] D such that the read transaction refers to -** historical [snapshot] P, rather than the most recent change to the -** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK -** on success or an appropriate [error code] if it fails. -** -** ^In order to succeed, the database connection must not be in -** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there -** is already a read transaction open on schema S, then the database handle -** must have no active statements (SELECT statements that have been passed -** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). -** SQLITE_ERROR is returned if either of these conditions is violated, or -** if schema S does not exist, or if the snapshot object is invalid. -** -** ^A call to sqlite3_snapshot_open() will fail to open if the specified -** snapshot has been overwritten by a [checkpoint]. In this case -** SQLITE_ERROR_SNAPSHOT is returned. -** -** If there is already a read transaction open when this function is -** invoked, then the same read transaction remains open (on the same -** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT -** is returned. If another error code - for example SQLITE_PROTOCOL or an -** SQLITE_IOERR error code - is returned, then the final state of the -** read transaction is undefined. If SQLITE_OK is returned, then the -** read transaction is now open on database snapshot P. -** +** EXPERIMENTAL +** +** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +** read transaction for schema S of +** [database connection] D such that the read transaction +** refers to historical [snapshot] P, rather than the most +** recent change to the database. +** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success +** or an appropriate [error code] if it fails. +** +** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be +** the first operation following the [BEGIN] that takes the schema S +** out of [autocommit mode]. +** ^In other words, schema S must not currently be in +** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +** database connection D must be out of [autocommit mode]. +** ^A [snapshot] will fail to open if it has been overwritten by a +** [checkpoint]. ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the ** database connection D does not know that the database file for ** schema S is in [WAL mode]. A database connection might not know ** that the database file is in [WAL mode] if there has been no prior -** I/O on that database connection, or if the database entered [WAL mode] +** I/O on that database connection, or if the database entered [WAL mode] ** after the most recent I/O on the database connection.)^ ** (Hint: Run "[PRAGMA application_id]" against a newly opened ** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot ); /* ** CAPI3REF: Destroy a snapshot -** DESTRUCTOR: sqlite3_snapshot +** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. ** The application must eventually free every [sqlite3_snapshot] object ** using this routine to avoid a memory leak. ** ** The [sqlite3_snapshot_free()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. -** METHOD: sqlite3_snapshot +** EXPERIMENTAL ** ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages -** of two valid snapshot handles. +** of two valid snapshot handles. ** -** If the two snapshot handles are not associated with the same database -** file, the result of the comparison is undefined. +** If the two snapshot handles are not associated with the same database +** file, the result of the comparison is undefined. ** ** Additionally, the result of the comparison is only valid if both of the ** snapshot handles were obtained by calling sqlite3_snapshot_get() since the ** last time the wal file was deleted. The wal file is deleted when the ** database is changed back to rollback mode or when the number of database -** clients drops to zero. If either snapshot handle was obtained before the -** wal file was last deleted, the value returned by this function +** clients drops to zero. If either snapshot handle was obtained before the +** wal file was last deleted, the value returned by this function ** is undefined. ** ** Otherwise, this API returns a negative value if P1 refers to an older ** snapshot than P2, zero if the two handles refer to the same database ** snapshot, and a positive value if P1 is a newer snapshot than P2. -** -** This interface is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); /* ** CAPI3REF: Recover snapshots from a wal file -** METHOD: sqlite3_snapshot -** -** If a [WAL file] remains on disk after all database connections close -** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] -** or because the last process to have the database opened exited without -** calling [sqlite3_close()]) and a new connection is subsequently opened -** on that database and [WAL file], the [sqlite3_snapshot_open()] interface -** will only be able to open the last transaction added to the WAL file -** even though the WAL file contains other valid transactions. -** -** This function attempts to scan the WAL file associated with database zDb +** 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 +** 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. -** -** This interface is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); -/* -** CAPI3REF: Serialize a database -** -** The sqlite3_serialize(D,S,P,F) interface returns a pointer to -** memory that is a serialization of the S database on -** [database connection] D. If S is a NULL pointer, the main database is used. -** If P is not a NULL pointer, then the size of the database in bytes -** is written into *P. -** -** For an ordinary on-disk database file, the serialization is just a -** copy of the disk file. For an in-memory database or a "TEMP" database, -** the serialization is the same sequence of bytes which would be written -** to disk if that database where backed up to disk. -** -** The usual case is that sqlite3_serialize() copies the serialization of -** the database into memory obtained from [sqlite3_malloc64()] and returns -** a pointer to that memory. The caller is responsible for freeing the -** returned value to avoid a memory leak. However, if the F argument -** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations -** are made, and the sqlite3_serialize() function will return a pointer -** to the contiguous memory representation of the database that SQLite -** is currently using for that database, or NULL if the no such contiguous -** memory representation of the database exists. A contiguous memory -** representation of the database will usually only exist if there has -** been a prior call to [sqlite3_deserialize(D,S,...)] with the same -** values of D and S. -** The size of the database is written into *P even if the -** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy -** of the database exists. -** -** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set, -** the returned buffer content will remain accessible and unchanged -** until either the next write operation on the connection or when -** the connection is closed, and applications must not modify the -** buffer. If the bit had been clear, the returned buffer will not -** be accessed by SQLite after the call. -** -** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the -** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory -** allocation error occurs. -** -** This interface is omitted if SQLite is compiled with the -** [SQLITE_OMIT_DESERIALIZE] option. -*/ -SQLITE_API unsigned char *sqlite3_serialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ - sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ - unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3_serialize -** -** Zero or more of the following constants can be OR-ed together for -** the F argument to [sqlite3_serialize(D,S,P,F)]. -** -** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return -** a pointer to contiguous in-memory database that it is currently using, -** without making a copy of the database. If SQLite is not currently using -** a contiguous in-memory database, then this option causes -** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be -** using a contiguous in-memory database if it has been initialized by a -** prior call to [sqlite3_deserialize()]. -*/ -#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ - -/* -** CAPI3REF: Deserialize a database -** -** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the -** [database connection] D to disconnect from database S and then -** reopen S as an in-memory database based on the serialization contained -** in P. The serialized database P is N bytes in size. M is the size of -** the buffer P, which might be larger than N. If M is larger than N, and -** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is -** permitted to add content to the in-memory database as long as the total -** size does not exceed M bytes. -** -** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will -** invoke sqlite3_free() on the serialization buffer when the database -** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then -** SQLite will try to increase the buffer size using sqlite3_realloc64() -** if writes on the database cause it to grow larger than M bytes. -** -** Applications must not modify the buffer P or invalidate it before -** the database connection D is closed. -** -** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the -** database is currently in a read transaction or is involved in a backup -** operation. -** -** It is not possible to deserialized into the TEMP database. If the -** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the -** function returns SQLITE_ERROR. -** -** The deserialized database should not be in [WAL mode]. If the database -** is in WAL mode, then any attempt to use the database file will result -** in an [SQLITE_CANTOPEN] error. The application can set the -** [file format version numbers] (bytes 18 and 19) of the input database P -** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the -** database file into rollback mode and work around this limitation. -** -** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the -** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then -** [sqlite3_free()] is invoked on argument P prior to returning. -** -** This interface is omitted if SQLite is compiled with the -** [SQLITE_OMIT_DESERIALIZE] option. -*/ -SQLITE_API int sqlite3_deserialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to reopen with the deserialization */ - unsigned char *pData, /* The serialized database content */ - sqlite3_int64 szDb, /* Number bytes in the deserialization */ - sqlite3_int64 szBuf, /* Total size of buffer pData[] */ - unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3_deserialize() -** -** The following are allowed values for 6th argument (the F argument) to -** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. -** -** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization -** in the P argument is held in memory obtained from [sqlite3_malloc64()] -** and that SQLite should take ownership of this memory and automatically -** free it when it has finished using it. Without this flag, the caller -** is responsible for freeing any dynamically allocated memory. -** -** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to -** grow the size of the database using calls to [sqlite3_realloc64()]. This -** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. -** Without this flag, the deserialized database cannot increase in size beyond -** the number of bytes specified by the M parameter. -** -** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database -** should be treated as read-only. -*/ -#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ -#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ -#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ - /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif -#if defined(__wasi__) -# undef SQLITE_WASI -# define SQLITE_WASI 1 -# ifndef SQLITE_OMIT_LOAD_EXTENSION -# define SQLITE_OMIT_LOAD_EXTENSION -# endif -# ifndef SQLITE_THREADSAFE -# define SQLITE_THREADSAFE 0 -# endif -#endif - #if 0 } /* End of the 'extern "C"' block */ #endif -/* #endif for SQLITE3_H will be added by mksqlite3.tcl */ +#endif /* SQLITE3_H */ /******** Begin file sqlite3rtree.h *********/ /* ** 2010 August 30 ** @@ -11371,11 +9785,11 @@ void *pUser; /* Callback implementation user data */ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ }; /* -** Register a 2nd-generation geometry callback named zScore that can be +** Register a 2nd-generation geometry callback named zScore that can be ** used as part of an R-Tree geometry query as follows: ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ SQLITE_API int sqlite3_rtree_query_callback( @@ -11386,11 +9800,11 @@ void (*xDestructor)(void*) ); /* -** A pointer to a structure of the following type is passed as the +** A pointer to a structure of the following type is passed as the ** argument to scored geometry callback registered using ** sqlite3_rtree_query_callback(). ** ** Note that the first 5 fields of this structure are identical to ** sqlite3_rtree_geometry. This structure is a subclass of @@ -11408,11 +9822,11 @@ int iLevel; /* Level of current node or entry */ int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visibility */ + int eWithin; /* OUT: Visiblity */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ }; @@ -11444,27 +9858,20 @@ #endif /* ** CAPI3REF: Session Object Handle -** -** An instance of this object is a [session] that can be used to -** record changes to a database. */ typedef struct sqlite3_session sqlite3_session; /* ** CAPI3REF: Changeset Iterator Handle -** -** An instance of this object acts as a cursor for iterating -** over the elements of a [changeset] or [patchset]. */ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* ** CAPI3REF: Create A New Session Object -** CONSTRUCTOR: sqlite3_session ** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is ** returned. If an error occurs, *ppSession is set to NULL and an SQLite ** error code (e.g. SQLITE_NOMEM) is returned. @@ -11481,11 +9888,11 @@ ** ** Because the session module uses the [sqlite3_preupdate_hook()] API, it ** is not possible for an application to register a pre-update hook on a ** database handle that has one or more session objects attached. Nor is ** it possible to create a session object attached to a database handle for -** which a pre-update hook is already defined. The results of attempting +** which a pre-update hook is already defined. The results of attempting ** either of these things are undefined. ** ** The session object will be used to create changesets for tables in ** database zDb, where zDb is either "main", or "temp", or the name of an ** attached database. It is not an error if database zDb is not attached @@ -11497,100 +9904,52 @@ sqlite3_session **ppSession /* OUT: New session object */ ); /* ** CAPI3REF: Delete A Session Object -** DESTRUCTOR: sqlite3_session ** -** Delete a session object previously allocated using +** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the ** results of attempting to use pSession with any other session module ** function are undefined. ** ** Session objects must be deleted before the database handle to which they -** are attached is closed. Refer to the documentation for +** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); -/* -** CAPI3REF: Configure a Session Object -** METHOD: sqlite3_session -** -** This method is used to configure a session object after it has been -** created. At present the only valid values for the second parameter are -** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. -** -*/ -SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); - -/* -** CAPI3REF: Options for sqlite3session_object_config -** -** The following values may passed as the the 2nd parameter to -** sqlite3session_object_config(). -** -**
    SQLITE_SESSION_OBJCONFIG_SIZE
    -** This option is used to set, clear or query the flag that enables -** the [sqlite3session_changeset_size()] API. Because it imposes some -** computational overhead, this API is disabled by default. Argument -** pArg must point to a value of type (int). If the value is initially -** 0, then the sqlite3session_changeset_size() API is disabled. If it -** is greater than 0, then the same API is enabled. Or, if the initial -** value is less than zero, no change is made. In all cases the (int) -** variable is set to 1 if the sqlite3session_changeset_size() API is -** enabled following the current call, or 0 otherwise. -** -** It is an error (SQLITE_MISUSE) to attempt to modify this setting after -** the first table has been attached to the session object. -** -**
    SQLITE_SESSION_OBJCONFIG_ROWID
    -** This option is used to set, clear or query the flag that enables -** collection of data for tables with no explicit PRIMARY KEY. -** -** Normally, tables with no explicit PRIMARY KEY are simply ignored -** by the sessions module. However, if this flag is set, it behaves -** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted -** as their leftmost columns. -** -** It is an error (SQLITE_MISUSE) to attempt to modify this setting after -** the first table has been attached to the session object. -*/ -#define SQLITE_SESSION_OBJCONFIG_SIZE 1 -#define SQLITE_SESSION_OBJCONFIG_ROWID 2 /* ** CAPI3REF: Enable Or Disable A Session Object -** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When ** disabled - it does not. A newly created session object is enabled. ** Refer to the documentation for [sqlite3session_changeset()] for further ** details regarding how enabling and disabling a session object affects ** the eventual changesets. ** ** Passing zero to this function disables the session. Passing a value -** greater than zero enables it. Passing a value less than zero is a +** greater than zero enables it. Passing a value less than zero is a ** no-op, and may be used to query the current state of the session. ** -** The return value indicates the final state of the session object: 0 if +** The return value indicates the final state of the session object: 0 if ** the session is disabled, or 1 if it is enabled. */ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag -** METHOD: sqlite3_session ** ** Each change recorded by a session object is marked as either direct or ** indirect. A change is marked as indirect if either: ** **
      **
    • The session object "indirect" flag is set when the change is ** made, or -**
    • The change is made by an SQL trigger or foreign key action +**
    • The change is made by an SQL trigger or foreign key action ** instead of directly as a result of a users SQL statement. **
    ** ** If a single row is affected by more than one operation within a session, ** then the change is considered indirect if all operations meet the criteria @@ -11598,89 +9957,58 @@ ** ** This function is used to set, clear or query the session object indirect ** flag. If the second argument passed to this function is zero, then the ** indirect flag is cleared. If it is greater than zero, the indirect flag ** is set. Passing a value less than zero does not modify the current value -** of the indirect flag, and may be used to query the current state of the +** of the indirect flag, and may be used to query the current state of the ** indirect flag for the specified session object. ** -** The return value indicates the final state of the indirect flag: 0 if +** The return value indicates the final state of the indirect flag: 0 if ** it is clear, or 1 if it is set. */ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); /* ** CAPI3REF: Attach A Table To A Session Object -** METHOD: sqlite3_session ** ** If argument zTab is not NULL, then it is the name of a table to attach -** to the session object passed as the first argument. All subsequent changes -** made to the table while the session object is enabled will be recorded. See +** to the session object passed as the first argument. All subsequent changes +** made to the table while the session object is enabled will be recorded. See ** documentation for [sqlite3session_changeset()] for further details. ** ** Or, if argument zTab is NULL, then changes are recorded for all tables -** in the database. If additional tables are added to the database (by -** executing "CREATE TABLE" statements) after this call is made, changes for +** in the database. If additional tables are added to the database (by +** executing "CREATE TABLE" statements) after this call is made, changes for ** the new tables are also recorded. ** ** Changes can only be recorded for tables that have a PRIMARY KEY explicitly -** defined as part of their CREATE TABLE statement. It does not matter if the +** defined as part of their CREATE TABLE statement. It does not matter if the ** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY ** KEY may consist of a single column, or may be a composite key. -** +** ** It is not an error if the named table does not exist in the database. Nor ** is it an error if the named table does not have a PRIMARY KEY. However, ** no changes will be recorded in either of these scenarios. ** ** Changes are not recorded for individual rows that have NULL values stored ** in one or more of their PRIMARY KEY columns. ** -** SQLITE_OK is returned if the call completes without error. Or, if an error +** SQLITE_OK is returned if the call completes without error. Or, if an error ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. -** -**

    Special sqlite_stat1 Handling

    -** -** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to -** 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. */ SQLITE_API int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zTab /* Table name */ ); /* ** CAPI3REF: Set a table filter on a Session Object. -** METHOD: sqlite3_session ** -** The second argument (xFilter) is the "filter callback". For changes to rows +** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called -** to determine whether changes to the table's rows should be tracked or not. -** If xFilter returns 0, changes are not tracked. Note that once a table is +** to determine whether changes to the table's rows should be tracked or not. +** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. */ SQLITE_API void sqlite3session_table_filter( sqlite3_session *pSession, /* Session object */ int(*xFilter)( @@ -11690,15 +10018,14 @@ void *pCtx /* First argument passed to xFilter */ ); /* ** CAPI3REF: Generate A Changeset From A Session Object -** METHOD: sqlite3_session ** -** Obtain a changeset containing changes to the tables attached to the -** session object passed as the first argument. If successful, -** set *ppChangeset to point to a buffer containing the changeset +** Obtain a changeset containing changes to the tables attached to the +** session object passed as the first argument. If successful, +** set *ppChangeset to point to a buffer containing the changeset ** and *pnChangeset to the size of the changeset in bytes before returning ** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to ** zero and return an SQLite error code. ** ** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, @@ -11709,11 +10036,11 @@ ** database row along with the updated values for each updated non-primary-key ** column. It is not possible for an UPDATE change to represent a change that ** modifies the values of primary key columns. If such a change is made, it ** is represented in a changeset as a DELETE followed by an INSERT. ** -** Changes are not recorded for rows that have NULL values stored in one or +** Changes are not recorded for rows that have NULL values stored in one or ** more of their PRIMARY KEY columns. If such a row is inserted or deleted, ** no corresponding change is present in the changesets returned by this ** function. If an existing row with one or more NULL values stored in ** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, ** only an INSERT is appears in the changeset. Similarly, if an existing row @@ -11762,38 +10089,38 @@ ** file. Specifically: ** **
      **
    • For each record generated by an insert, the database is queried ** for a row with a matching primary key. If one is found, an INSERT -** change is added to the changeset. If no such row is found, no change +** change is added to the changeset. If no such row is found, no change ** is added to the changeset. ** -**
    • For each record generated by an update or delete, the database is +**
    • For each record generated by an update or delete, the database is ** queried for a row with a matching primary key. If such a row is ** found and one or more of the non-primary key fields have been -** modified from their original values, an UPDATE change is added to -** the changeset. Or, if no such row is found in the table, a DELETE +** modified from their original values, an UPDATE change is added to +** the changeset. Or, if no such row is found in the table, a DELETE ** change is added to the changeset. If there is a row with a matching ** primary key in the database, but all fields contain their original ** values, no change is added to the changeset. **
    ** ** This means, amongst other things, that if a row is inserted and then later ** deleted while a session object is active, neither the insert nor the delete -** will be present in the changeset. Or if a row is deleted and then later a +** will be present in the changeset. Or if a row is deleted and then later a ** row with the same primary key values inserted while a session object is ** active, the resulting changeset will contain an UPDATE change instead of ** a DELETE and an INSERT. ** ** When a session object is disabled (see the [sqlite3session_enable()] API), ** it does not accumulate records when rows are inserted, updated or deleted. ** This may appear to have some counter-intuitive effects if a single row ** is written to more than once during a session. For example, if a row -** is inserted while a session object is enabled, then later deleted while +** is inserted while a session object is enabled, then later deleted while ** the same session object is disabled, no INSERT record will appear in the ** changeset, even though the delete took place while the session was disabled. -** Or, if one field of a row is updated while a session is disabled, and +** Or, if one field of a row is updated while a session is disabled, and ** another field of the same row is updated while the session is enabled, the ** resulting changeset will contain an UPDATE change that updates both fields. */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ @@ -11800,37 +10127,20 @@ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* -** CAPI3REF: Return An Upper-limit For The Size Of The Changeset -** METHOD: sqlite3_session -** -** By default, this function always returns 0. For it to return -** a useful result, the sqlite3_session object must have been configured -** to enable this API using sqlite3session_object_config() with the -** SQLITE_SESSION_OBJCONFIG_SIZE verb. -** -** When enabled, this function returns an upper limit, in bytes, for the size -** of the changeset that might be produced if sqlite3session_changeset() were -** called. The final changeset size might be equal to or smaller than the -** size in bytes returned by this function. -*/ -SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession); - -/* -** CAPI3REF: Load The Difference Between Tables Into A Session -** METHOD: sqlite3_session +** CAPI3REF: Load The Difference Between Tables Into A Session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the ** [sqlite3session_attach()] function. If zTbl does not exist, or if it ** does not have a primary key, this function is a no-op (but does not return ** an error). ** ** Argument zFromDb must be the name of a database ("main", "temp" etc.) -** attached to the same database handle as the session object that contains +** attached to the same database handle as the session object that contains ** a table compatible with the table attached to the session by this function. ** A table is considered compatible if it: ** **
      **
    • Has the same name, @@ -11842,37 +10152,37 @@ ** are compatible but do not have any PRIMARY KEY columns, it is not an error ** but no changes are added to the session object. As with other session ** APIs, tables without PRIMARY KEYs are simply ignored. ** ** This function adds a set of changes to the session object that could be -** used to update the table in database zFrom (call this the "from-table") -** so that its content is the same as the table attached to the session +** used to update the table in database zFrom (call this the "from-table") +** so that its content is the same as the table attached to the session ** object (call this the "to-table"). Specifically: ** **
        -**
      • For each row (primary key) that exists in the to-table but not in +**
      • For each row (primary key) that exists in the to-table but not in ** the from-table, an INSERT record is added to the session object. ** -**
      • For each row (primary key) that exists in the to-table but not in +**
      • For each row (primary key) that exists in the to-table but not in ** the from-table, a DELETE record is added to the session object. ** -**
      • For each row (primary key) that exists in both tables, but features +**
      • For each row (primary key) that exists in both tables, but features ** different non-PK values in each, an UPDATE record is added to the -** session. +** session. **
      ** ** To clarify, if this function is called and then a changeset constructed -** using [sqlite3session_changeset()], then after applying that changeset to -** database zFrom the contents of the two compatible tables would be +** using [sqlite3session_changeset()], then after applying that changeset to +** database zFrom the contents of the two compatible tables would be ** identical. ** ** It an error if database zFrom does not exist or does not contain the ** required compatible table. ** -** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite +** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite ** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg -** may be set to point to a buffer containing an English language error +** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to free this buffer using ** sqlite3_free(). */ SQLITE_API int sqlite3session_diff( sqlite3_session *pSession, @@ -11882,28 +10192,27 @@ ); /* ** CAPI3REF: Generate A Patchset From A Session Object -** METHOD: sqlite3_session ** ** The differences between a patchset and a changeset are that: ** **
        -**
      • DELETE records consist of the primary key fields only. The +**
      • DELETE records consist of the primary key fields only. The ** original values of other fields are omitted. -**
      • The original values of any modified fields are omitted from +**
      • The original values of any modified fields are omitted from ** UPDATE records. **
      ** -** A patchset blob may be used with up to date versions of all -** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), +** A patchset blob may be used with up to date versions of all +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), ** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, ** attempting to use a patchset blob with old versions of the -** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. ** -** Because the non-primary key "old.*" fields are omitted, no +** Because the non-primary key "old.*" fields are omitted, no ** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset ** is passed to the sqlite3changeset_apply() API. Other conflict types work ** in the same way as for changesets. ** ** Changes within a patchset are ordered in the same way as for changesets @@ -11911,49 +10220,40 @@ ** a single table are grouped together, tables appear in the order in which ** they were attached to the session object). */ SQLITE_API int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ - int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ - void **ppPatchset /* OUT: Buffer containing patchset */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Test if a changeset has recorded any changes. ** -** Return non-zero if no changes to attached tables have been recorded by -** the session object passed as the first argument. Otherwise, if one or +** Return non-zero if no changes to attached tables have been recorded by +** the session object passed as the first argument. Otherwise, if one or ** more changes have been recorded, return zero. ** ** Even if this function returns zero, it is possible that calling ** [sqlite3session_changeset()] on the session handle may still return a -** changeset that contains no changes. This can happen when a row in -** an attached table is modified and then later on the original values +** changeset that contains no changes. This can happen when a row in +** an attached table is modified and then later on the original values ** are restored. However, if this function returns non-zero, then it is -** guaranteed that a call to sqlite3session_changeset() will return a +** guaranteed that a call to sqlite3session_changeset() will return a ** changeset containing zero changes. */ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); /* -** CAPI3REF: Query for the amount of heap memory used by a session object. -** -** This API returns the total amount of heap memory in bytes currently -** used by the session object passed as the only argument. -*/ -SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession); - -/* -** CAPI3REF: Create An Iterator To Traverse A Changeset -** CONSTRUCTOR: sqlite3_changeset_iter +** CAPI3REF: Create An Iterator To Traverse A Changeset ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK ** is returned. Otherwise, if an error occurs, *pp is set to zero and an ** SQLite error code is returned. ** -** The following functions can be used to advance and query a changeset +** The following functions can be used to advance and query a changeset ** iterator created by this function: ** **
        **
      • [sqlite3changeset_next()] **
      • [sqlite3changeset_op()] @@ -11966,56 +10266,29 @@ ** changeset (pChangeset) must remain valid until after the iterator is ** destroyed. ** ** Assuming the changeset blob was created by one of the ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or -** [sqlite3changeset_invert()] functions, all changes within the changeset -** that apply to a single table are grouped together. This means that when -** an application iterates through a changeset using an iterator created by -** this function, all changes that relate to a single table are visited -** consecutively. There is no chance that the iterator will visit a change -** the applies to table X, then one for table Y, and then later on visit +** [sqlite3changeset_invert()] functions, all changes within the changeset +** that apply to a single table are grouped together. This means that when +** an application iterates through a changeset using an iterator created by +** this function, all changes that relate to a single table are visited +** consecutively. There is no chance that the iterator will visit a change +** the applies to table X, then one for table Y, and then later on visit ** another change for table X. -** -** The behavior of sqlite3changeset_start_v2() and its streaming equivalent -** may be modified by passing a combination of -** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. -** -** Note that the sqlite3changeset_start_v2() API is still experimental -** and therefore subject to change. */ SQLITE_API int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); -SQLITE_API int sqlite3changeset_start_v2( - sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ - int nChangeset, /* Size of changeset blob in bytes */ - void *pChangeset, /* Pointer to blob containing changeset */ - int flags /* SESSION_CHANGESETSTART_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3changeset_start_v2 -** -** The following flags may passed via the 4th parameter to -** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: -** -**
        SQLITE_CHANGESETAPPLY_INVERT
        -** Invert the changeset while iterating through it. This is equivalent to -** inverting a changeset using sqlite3changeset_invert() before applying it. -** It is an error to specify this flag with a patchset. -*/ -#define SQLITE_CHANGESETSTART_INVERT 0x0002 /* ** CAPI3REF: Advance A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** -** This function may only be used with iterators created by the function +** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to ** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE ** is returned and the call has no effect. ** ** Immediately after an iterator is created by sqlite3changeset_start(), it @@ -12022,47 +10295,41 @@ ** does not point to any change in the changeset. Assuming the changeset ** is not empty, the first call to this function advances the iterator to ** point to the first change in the changeset. Each subsequent call advances ** the iterator to point to the next change in the changeset (if any). If ** no error occurs and the iterator points to a valid change after a call -** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. ** Otherwise, if all changes in the changeset have already been visited, ** SQLITE_DONE is returned. ** -** If an error occurs, an SQLite error code is returned. Possible error -** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or +** If an error occurs, an SQLite error code is returned. Possible error +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or ** SQLITE_NOMEM. */ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent ** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this ** is not the case, this function returns [SQLITE_MISUSE]. ** -** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three -** outputs are set through these pointers: -** -** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the type of change that the iterator currently points to; -** -** *pnCol is set to the number of columns in the table affected by the change; and -** -** *pzTab is set to point to a nul-terminated utf-8 encoded string containing -** the name of the table affected by the current change. The buffer remains -** valid until either sqlite3changeset_next() is called on the iterator -** or until the conflict-handler function returns. -** -** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change +** If argument pzTab is not NULL, then *pzTab is set to point to a +** nul-terminated utf-8 encoded string containing the name of the table +** affected by the current change. The buffer remains valid until either +** sqlite3changeset_next() is called on the iterator or until the +** conflict-handler function returns. If pnCol is not NULL, then *pnCol is +** set to the number of columns in the table affected by the change. If +** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change ** is an indirect change, or false (0) otherwise. See the documentation for ** [sqlite3session_indirect()] for a description of direct and indirect -** changes. +** changes. Finally, if pOp is not NULL, then *pOp is set to one of +** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the +** type of change that the iterator currently points to. ** ** If no error occurs, SQLITE_OK is returned. If an error does occur, an ** SQLite error code is returned. The values of the output variables may not ** be trusted in this case. */ @@ -12074,11 +10341,10 @@ int *pbIndirect /* OUT: True for an 'indirect' change */ ); /* ** CAPI3REF: Obtain The Primary Key Definition Of A Table -** METHOD: sqlite3_changeset_iter ** ** For each modified table, a changeset includes the following: ** **
          **
        • The number of columns in the table, and @@ -12106,28 +10372,27 @@ int *pnCol /* OUT: Number of entries in output array */ ); /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. ** Furthermore, it may only be called if the type of change that the iterator ** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, ** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, ** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the vector of +** sqlite3_value object containing the iVal'th value from the vector of ** original row values stored as part of the UPDATE or DELETE change and -** returns SQLITE_OK. The name of the function comes from the fact that this +** returns SQLITE_OK. The name of the function comes from the fact that this ** is similar to the "old.*" columns available to update or delete triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ @@ -12137,31 +10402,30 @@ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ); /* ** CAPI3REF: Obtain new.* Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. ** Furthermore, it may only be called if the type of change that the iterator ** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, ** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, ** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the vector of +** sqlite3_value object containing the iVal'th value from the vector of ** new row values stored as part of the UPDATE or INSERT change and ** returns SQLITE_OK. If the change is an UPDATE and does not include -** a new value for the requested column, *ppValue is set to NULL and -** SQLITE_OK returned. The name of the function comes from the fact that -** this is similar to the "new.*" columns available to update or delete +** a new value for the requested column, *ppValue is set to NULL and +** SQLITE_OK returned. The name of the function comes from the fact that +** this is similar to the "new.*" columns available to update or delete ** triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ @@ -12171,11 +10435,10 @@ sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); /* ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either ** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function ** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue @@ -12184,11 +10447,11 @@ ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, ** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the +** sqlite3_value object containing the iVal'th value from the ** "conflicting row" associated with the current conflict-handler callback ** and returns SQLITE_OK. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. @@ -12199,11 +10462,10 @@ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); /* ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations -** METHOD: sqlite3_changeset_iter ** ** This function may only be called with an iterator passed to an ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case ** it sets the output variable to the total number of known foreign key ** violations in the destination database and returns SQLITE_OK. @@ -12216,11 +10478,10 @@ ); /* ** CAPI3REF: Finalize A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. ** ** This function should only be called on iterators created using the @@ -12228,25 +10489,23 @@ ** function with an iterator passed to a conflict-handler by ** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the ** call has no effect. ** ** If an error was encountered within a call to an sqlite3changeset_xxx() -** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an ** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** -**
           **   sqlite3changeset_start();
           **   while( SQLITE_ROW==sqlite3changeset_next() ){
           **     // Do something with change.
           **   }
           **   rc = sqlite3changeset_finalize();
           **   if( rc!=SQLITE_OK ){
          -**     // An error has occurred
          +**     // An error has occurred 
           **   }
          -** 
          */ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Invert A Changeset @@ -12268,11 +10527,11 @@ ** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and ** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are ** zeroed and an SQLite error code returned. ** ** It is the responsibility of the caller to eventually call sqlite3_free() -** on the *ppOut pointer to free the buffer allocation following a successful +** on the *ppOut pointer to free the buffer allocation following a successful ** call to this function. ** ** WARNING/TODO: This function currently assumes that the input is a valid ** changeset. If it is not, the results are undefined. */ @@ -12282,19 +10541,18 @@ ); /* ** CAPI3REF: Concatenate Two Changeset Objects ** -** This function is used to concatenate two changesets, A and B, into a +** This function is used to concatenate two changesets, A and B, into a ** single changeset. The result is a changeset equivalent to applying -** changeset A followed by changeset B. +** changeset A followed by changeset B. ** -** This function combines the two input changesets using an +** This function combines the two input changesets using an ** sqlite3_changegroup object. Calling it produces similar results as the ** following code fragment: ** -**
           **   sqlite3_changegroup *pGrp;
           **   rc = sqlite3_changegroup_new(&pGrp);
           **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
           **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
           **   if( rc==SQLITE_OK ){
          @@ -12301,11 +10559,10 @@
           **     rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
           **   }else{
           **     *ppOut = 0;
           **     *pnOut = 0;
           **   }
          -** 
          ** ** Refer to the sqlite3_changegroup documentation below for details. */ SQLITE_API int sqlite3changeset_concat( int nA, /* Number of bytes in buffer pA */ @@ -12314,43 +10571,27 @@ void *pB, /* Pointer to buffer containing changeset B */ int *pnOut, /* OUT: Number of bytes in output changeset */ void **ppOut /* OUT: Buffer containing output changeset */ ); - -/* -** CAPI3REF: Upgrade the Schema of a Changeset/Patchset -*/ -SQLITE_API int sqlite3changeset_upgrade( - sqlite3 *db, - const char *zDb, - int nIn, const void *pIn, /* Input changeset */ - int *pnOut, void **ppOut /* OUT: Inverse of input */ -); - - /* ** CAPI3REF: Changegroup Handle -** -** A changegroup is an object used to combine two or more -** [changesets] or [patchsets] */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* ** CAPI3REF: Create A New Changegroup Object -** CONSTRUCTOR: sqlite3_changegroup ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup ** object may combine changesets or patchsets, but not both. The output is ** always in the same format as the input. ** ** If successful, this function returns SQLITE_OK and populates (*pp) with ** a pointer to a new sqlite3_changegroup object before returning. The caller -** should eventually free the returned object using a call to +** should eventually free the returned object using a call to ** sqlite3changegroup_delete(). If an error occurs, an SQLite error code ** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. ** ** The usual usage pattern for an sqlite3_changegroup object is as follows: ** @@ -12358,63 +10599,30 @@ **
        • It is created using a call to sqlite3changegroup_new(). ** **
        • Zero or more changesets (or patchsets) are added to the object ** by calling sqlite3changegroup_add(). ** -**
        • The result of combining all input changesets together is obtained +**
        • The result of combining all input changesets together is obtained ** by the application via a call to sqlite3changegroup_output(). ** **
        • The object is deleted using a call to sqlite3changegroup_delete(). **
        ** ** Any number of calls to add() and output() may be made between the calls to ** new() and delete(), and in any order. ** -** As well as the regular sqlite3changegroup_add() and +** As well as the regular sqlite3changegroup_add() and ** sqlite3changegroup_output() functions, also available are the streaming ** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). */ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); -/* -** CAPI3REF: Add a Schema to a Changegroup -** METHOD: sqlite3_changegroup_schema -** -** This method may be used to optionally enforce the rule that the changesets -** added to the changegroup handle must match the schema of database zDb -** ("main", "temp", or the name of an attached database). If -** sqlite3changegroup_add() is called to add a changeset that is not compatible -** with the configured schema, SQLITE_SCHEMA is returned and the changegroup -** object is left in an undefined state. -** -** A changeset schema is considered compatible with the database schema in -** the same way as for sqlite3changeset_apply(). Specifically, for each -** table in the changeset, there exists a database table with: -** -**
          -**
        • The name identified by the changeset, and -**
        • at least as many columns as recorded in the changeset, and -**
        • the primary key columns in the same position as recorded in -** the changeset. -**
        -** -** The output of the changegroup object always has the same schema as the -** database nominated using this function. In cases where changesets passed -** to sqlite3changegroup_add() have fewer columns than the corresponding table -** in the database schema, these are filled in using the default column -** values from the database schema. This makes it possible to combined -** changesets that have different numbers of columns for a single table -** within a changegroup, provided that they are otherwise compatible. -*/ -SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb); - /* ** CAPI3REF: Add A Changeset To A Changegroup -** METHOD: sqlite3_changegroup ** ** Add all changes within the changeset (or patchset) in buffer pData (size -** nData bytes) to the changegroup. +** nData bytes) to the changegroup. ** ** If the buffer contains a patchset, then all prior calls to this function ** on the same changegroup object must also have specified patchsets. Or, if ** the buffer contains a changeset, so must have the earlier calls to this ** function. Otherwise, SQLITE_ERROR is returned and no changes are added @@ -12437,11 +10645,11 @@ ** INSERT INSERT ** The new change is ignored. This case does not occur if the new ** changeset was recorded immediately after the changesets already ** added to the changegroup. ** INSERT UPDATE -** The INSERT change remains in the changegroup. The values in the +** The INSERT change remains in the changegroup. The values in the ** INSERT change are modified as if the row was inserted by the ** existing change and then updated according to the new change. ** INSERT DELETE ** The existing INSERT is removed from the changegroup. The DELETE is ** not added. @@ -12448,21 +10656,21 @@ ** UPDATE INSERT ** The new change is ignored. This case does not occur if the new ** changeset was recorded immediately after the changesets already ** added to the changegroup. ** UPDATE UPDATE -** The existing UPDATE remains within the changegroup. It is amended -** so that the accompanying values are as if the row was updated once +** The existing UPDATE remains within the changegroup. It is amended +** so that the accompanying values are as if the row was updated once ** by the existing change and then again by the new change. ** UPDATE DELETE ** The existing UPDATE is replaced by the new DELETE within the ** changegroup. ** DELETE INSERT ** If one or more of the column values in the row inserted by the -** new change differ from those in the row deleted by the existing +** new change differ from those in the row deleted by the existing ** change, the existing DELETE is replaced by an UPDATE within the -** changegroup. Otherwise, if the inserted row is exactly the same +** changegroup. Otherwise, if the inserted row is exactly the same ** as the deleted row, the existing DELETE is simply discarded. ** DELETE UPDATE ** The new change is ignored. This case does not occur if the new ** changeset was recorded immediately after the changesets already ** added to the changegroup. @@ -12473,52 +10681,22 @@ ** ** ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup -** object has been configured with a database schema using the -** sqlite3changegroup_schema() API, then it is possible to combine changesets -** with different numbers of columns for a single table, provided that -** they are otherwise compatible. -** -** If the input changeset appears to be corrupt and the corruption is -** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition -** occurs during processing, this function returns SQLITE_NOMEM. -** -** In all cases, if an error occurs the state of the final contents of the -** changegroup is undefined. If no error occurs, SQLITE_OK is returned. +** case, this function fails with SQLITE_SCHEMA. If the input changeset +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is +** returned. Or, if an out-of-memory condition occurs during processing, this +** function returns SQLITE_NOMEM. In all cases, if an error occurs the +** final contents of the changegroup is undefined. +** +** If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); - -/* -** CAPI3REF: Add A Single Change To A Changegroup -** METHOD: sqlite3_changegroup -** -** This function adds the single change currently indicated by the iterator -** passed as the second argument to the changegroup object. The rules for -** adding the change are just as described for [sqlite3changegroup_add()]. -** -** If the change is successfully added to the changegroup, SQLITE_OK is -** returned. Otherwise, an SQLite error code is returned. -** -** The iterator must point to a valid entry when this function is called. -** If it does not, SQLITE_ERROR is returned and no change is added to the -** changegroup. Additionally, the iterator must not have been opened with -** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also -** returned. -*/ -SQLITE_API int sqlite3changegroup_add_change( - sqlite3_changegroup*, - sqlite3_changeset_iter* -); - - /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup -** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup ** were themselves changesets, the output is a changeset. Or, if the ** inputs were patchsets, the output is also a patchset. @@ -12532,11 +10710,11 @@ ** appended onto the end of the output changeset, again in the order in ** which they are first encountered. ** ** If an error occurs, an SQLite error code is returned and the output ** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK -** is returned and the output variables are set to the size of and a +** is returned and the output variables are set to the size of and a ** pointer to the output buffer, respectively. In this case it is the ** responsibility of the caller to eventually free the buffer using a ** call to sqlite3_free(). */ SQLITE_API int sqlite3changegroup_output( @@ -12545,77 +10723,77 @@ void **ppData /* OUT: Pointer to output buffer */ ); /* ** CAPI3REF: Delete A Changegroup Object -** DESTRUCTOR: sqlite3_changegroup */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** -** Apply a changeset or patchset to a database. These functions attempt to -** update the "main" database attached to handle db with the changes found in -** the changeset passed via the second and third arguments. +** Apply a changeset to a database. This function attempts to update the +** "main" database attached to handle db with the changes found in the +** changeset passed via the second and third arguments. ** -** The fourth argument (xFilter) passed to these functions is the "filter +** The fourth argument (xFilter) passed to this function is the "filter ** callback". If it is not NULL, then for each table affected by at least one ** change in the changeset, the filter callback is invoked with ** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument as the first. If the "filter callback" -** returns zero, then no attempt is made to apply any changes to the table. -** Otherwise, if the return value is non-zero or the xFilter argument to -** is NULL, all changes related to the table are attempted. +** passed as the sixth argument to this function as the first. If the "filter +** callback" returns zero, then no attempt is made to apply any changes to +** the table. Otherwise, if the return value is non-zero or the xFilter +** argument to this function is NULL, all changes related to the table are +** attempted. ** -** For each table that is not excluded by the filter callback, this function -** tests that the target database contains a compatible table. A table is +** For each table that is not excluded by the filter callback, this function +** tests that the target database contains a compatible table. A table is ** considered compatible if all of the following are true: ** **
          -**
        • The table has the same name as the name recorded in the +**
        • The table has the same name as the name recorded in the ** changeset, and -**
        • The table has at least as many columns as recorded in the +**
        • The table has at least as many columns as recorded in the ** changeset, and -**
        • The table has primary key columns in the same position as +**
        • The table has primary key columns in the same position as ** recorded in the changeset. **
        ** ** If there is no compatible table, it is not an error, but none of the ** changes associated with the table are applied. A warning message is issued ** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most ** one such warning is issued for each table in the changeset. ** -** For each change for which there is a compatible table, an attempt is made -** to modify the table contents according to the UPDATE, INSERT or DELETE -** change. If a change cannot be applied cleanly, the conflict handler -** function passed as the fifth argument to sqlite3changeset_apply() may be -** invoked. A description of exactly when the conflict handler is invoked for +** For each change for which there is a compatible table, an attempt is made +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for ** each type of change is below. ** ** Unlike the xFilter argument, xConflict may not be passed NULL. The results ** of passing anything other than a valid function pointer as the xConflict ** argument are undefined. ** ** Each time the conflict handler function is invoked, it must return one -** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or ** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned ** if the second argument passed to the conflict handler is either ** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler ** returns an illegal value, any changes already made are rolled back and -** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different ** actions are taken by sqlite3changeset_apply() depending on the value ** returned by each invocation of the conflict-handler function. Refer to -** the documentation for the three +** the documentation for the three ** [SQLITE_CHANGESET_OMIT|available return values] for details. ** **
        **
        DELETE Changes
        -** For each DELETE change, the function checks if the target database -** contains a row with the same primary key value (or values) as the -** original row values stored in the changeset. If it does, and the values -** stored in all non-primary key columns also match the values stored in +** For each DELETE change, 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 deleted from 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 the original ** row value stored in the changeset, the conflict-handler function is @@ -12640,26 +10818,26 @@ ** For each INSERT change, an attempt is made to insert the new row into ** 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 +** If the attempt to insert the row fails because the database already ** contains a row with the same primary key values, the conflict handler -** function is invoked with the second argument set to +** function is invoked with the second argument set to ** [SQLITE_CHANGESET_CONFLICT]. ** ** If the attempt to insert the row fails because of some other constraint -** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is ** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. -** This includes the case where the INSERT operation is re-attempted because -** an earlier call to the conflict handler function returned +** This includes the case where the INSERT operation is re-attempted because +** an earlier call to the conflict handler function returned ** [SQLITE_CHANGESET_REPLACE]. ** **
        UPDATE Changes
        -** For each UPDATE change, the function checks if the target database -** contains a row with the same primary key value (or values) as the -** original row values stored in the changeset. If it does, and the values +** For each UPDATE change, 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 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 modified non-primary key fields contains a value different from an @@ -12671,45 +10849,28 @@ ** ** If no row with matching primary key values is found in the database, ** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] ** passed as the second argument. ** -** If the UPDATE operation is attempted, but SQLite returns -** SQLITE_CONSTRAINT, the conflict-handler function is invoked with +** If the UPDATE operation is attempted, but SQLite returns +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with ** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. -** This includes the case where the UPDATE operation is attempted after +** This includes the case where the UPDATE operation is attempted after ** an earlier call to the conflict handler function returned -** [SQLITE_CHANGESET_REPLACE]. +** [SQLITE_CHANGESET_REPLACE]. **
        ** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. -** This can be used to further customize the application's conflict +** This can be used to further customize the applications conflict ** resolution strategy. ** -** All changes made by these functions are enclosed in a savepoint transaction. +** All changes made by this function are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is -** rolled back, restoring the target database to its original state, and an +** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. -** -** If the output parameters (ppRebase) and (pnRebase) are non-NULL and -** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() -** may set (*ppRebase) to point to a "rebase" that may be used with the -** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) -** is set to the size of the buffer in bytes. It is the responsibility of the -** caller to eventually free any such buffer using sqlite3_free(). The buffer -** is only allocated and populated if one or more conflicts were encountered -** while applying the patchset. See comments surrounding the sqlite3_rebaser -** APIs for further details. -** -** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent -** may be modified by passing a combination of -** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. -** -** Note that the sqlite3changeset_apply_v2() API is still experimental -** and therefore subject to change. */ 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 */ @@ -12722,123 +10883,61 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); -SQLITE_API int sqlite3changeset_apply_v2( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* SESSION_CHANGESETAPPLY_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3changeset_apply_v2 -** -** The following flags may passed via the 9th parameter to -** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: -** -**
        -**
        SQLITE_CHANGESETAPPLY_NOSAVEPOINT
        -** Usually, the sessions module encloses all operations performed by -** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The -** SAVEPOINT is committed if the changeset or patchset is successfully -** applied, or rolled back if an error occurs. Specifying this flag -** causes the sessions module to omit this savepoint. In this case, if the -** caller has an open transaction or savepoint when apply_v2() is called, -** it may revert the partially applied changeset by rolling it back. -** -**
        SQLITE_CHANGESETAPPLY_INVERT
        -** Invert the changeset before applying it. This is equivalent to inverting -** a changeset using sqlite3changeset_invert() before applying it. It is -** an error to specify this flag with a patchset. -** -**
        SQLITE_CHANGESETAPPLY_IGNORENOOP
        -** Do not invoke the conflict handler callback for any changes that -** would not actually modify the database even if they were applied. -** Specifically, this means that the conflict handler is not invoked -** for: -**
          -**
        • a delete change if the row being deleted cannot be found, -**
        • an update change if the modified fields are already set to -** their new values in the conflicting row, or -**
        • an insert change if all fields of the conflicting row match -** the row being inserted. -**
        -** -**
        SQLITE_CHANGESETAPPLY_FKNOACTION
        -** If this flag it set, then all foreign key constraints in the target -** database behave as if they were declared with "ON UPDATE NO ACTION ON -** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL -** or SET DEFAULT. -*/ -#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 -#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 -#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004 -#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 - -/* + +/* ** CAPI3REF: Constants Passed To The Conflict Handler ** ** Values that may be passed as the second argument to a conflict-handler. ** **
        **
        SQLITE_CHANGESET_DATA
        ** The conflict handler is invoked with CHANGESET_DATA as the second argument ** when processing a DELETE or UPDATE change if a row with the required -** PRIMARY KEY fields is present in the database, but one or more other -** (non primary-key) fields modified by the update do not contain the +** PRIMARY KEY fields is present in the database, but one or more other +** (non primary-key) fields modified by the update do not contain the ** expected "before" values. -** +** ** The conflicting row, in this case, is the database row with the matching ** primary key. -** +** **
        SQLITE_CHANGESET_NOTFOUND
        ** The conflict handler is invoked with CHANGESET_NOTFOUND as the second ** argument when processing a DELETE or UPDATE change if a row with the ** required PRIMARY KEY fields is not present in the database. -** +** ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. -** +** **
        SQLITE_CHANGESET_CONFLICT
        ** CHANGESET_CONFLICT is passed as the second argument to the conflict -** handler while processing an INSERT change if the operation would result +** handler while processing an INSERT change if the operation would result ** in duplicate primary key values. -** +** ** The conflicting row in this case is the database row with the matching ** primary key. ** **
        SQLITE_CHANGESET_FOREIGN_KEY
        ** If foreign key handling is enabled, and applying a changeset leaves the -** database in a state containing foreign key violations, the conflict +** database in a state containing foreign key violations, the conflict ** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument ** exactly once before the changeset is committed. If the conflict handler ** returns CHANGESET_OMIT, the changes, including those that caused the ** foreign key constraint violation, are committed. Or, if it returns ** CHANGESET_ABORT, the changeset is rolled back. ** ** No current or conflicting row information is provided. The only function ** it is possible to call on the supplied sqlite3_changeset_iter handle ** is sqlite3changeset_fk_conflicts(). -** +** **
        SQLITE_CHANGESET_CONSTRAINT
        -** If any other constraint violation occurs while applying a change (i.e. -** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is +** If any other constraint violation occurs while applying a change (i.e. +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is ** invoked with CHANGESET_CONSTRAINT as the second argument. -** +** ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. ** **
        */ @@ -12846,25 +10945,25 @@ #define SQLITE_CHANGESET_NOTFOUND 2 #define SQLITE_CHANGESET_CONFLICT 3 #define SQLITE_CHANGESET_CONSTRAINT 4 #define SQLITE_CHANGESET_FOREIGN_KEY 5 -/* +/* ** CAPI3REF: Constants Returned By The Conflict Handler ** ** A conflict handler callback must return one of the following three values. ** **
        **
        SQLITE_CHANGESET_OMIT
        ** If a conflict handler returns this value no special action is taken. The -** change that caused the conflict is not applied. The session module +** change that caused the conflict is not applied. The session module ** continues to the next change in the changeset. ** **
        SQLITE_CHANGESET_REPLACE
        ** This value may only be returned if the second argument to the conflict ** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this -** is not the case, any changes applied so far are rolled back and the +** is not the case, any changes applied so far are rolled back and the ** call to sqlite3changeset_apply() returns SQLITE_MISUSE. ** ** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict ** handler, then the conflicting row is either updated or deleted, depending ** on the type of change. @@ -12873,195 +10972,39 @@ ** handler, then the conflicting row is removed from the database and a ** second attempt to apply the change is made. If this second attempt fails, ** the original row is restored to the database before continuing. ** **
        SQLITE_CHANGESET_ABORT
        -** If this value is returned, any changes applied so far are rolled back +** If this value is returned, any changes applied so far are rolled back ** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. **
        */ #define SQLITE_CHANGESET_OMIT 0 #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 -/* -** CAPI3REF: Rebasing changesets -** EXPERIMENTAL -** -** Suppose there is a site hosting a database in state S0. And that -** modifications are made that move that database to state S1 and a -** changeset recorded (the "local" changeset). Then, a changeset based -** on S0 is received from another site (the "remote" changeset) and -** applied to the database. The database is then in state -** (S1+"remote"), where the exact state depends on any conflict -** resolution decisions (OMIT or REPLACE) made while applying "remote". -** Rebasing a changeset is to update it to take those conflict -** resolution decisions into account, so that the same conflicts -** do not have to be resolved elsewhere in the network. -** -** For example, if both the local and remote changesets contain an -** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": -** -** local: INSERT INTO t1 VALUES(1, 'v1'); -** remote: INSERT INTO t1 VALUES(1, 'v2'); -** -** and the conflict resolution is REPLACE, then the INSERT change is -** removed from the local changeset (it was overridden). Or, if the -** conflict resolution was "OMIT", then the local changeset is modified -** to instead contain: -** -** UPDATE t1 SET b = 'v2' WHERE a=1; -** -** Changes within the local changeset are rebased as follows: -** -**
        -**
        Local INSERT
        -** This may only conflict with a remote INSERT. If the conflict -** resolution was OMIT, then add an UPDATE change to the rebased -** changeset. Or, if the conflict resolution was REPLACE, add -** nothing to the rebased changeset. -** -**
        Local DELETE
        -** This may conflict with a remote UPDATE or DELETE. In both cases the -** only possible resolution is OMIT. If the remote operation was a -** DELETE, then add no change to the rebased changeset. If the remote -** operation was an UPDATE, then the old.* fields of change are updated -** to reflect the new.* values in the UPDATE. -** -**
        Local UPDATE
        -** This may conflict with a remote UPDATE or DELETE. If it conflicts -** with a DELETE, and the conflict resolution was OMIT, then the update -** is changed into an INSERT. Any undefined values in the new.* record -** from the update change are filled in using the old.* values from -** the conflicting DELETE. Or, if the conflict resolution was REPLACE, -** the UPDATE change is simply omitted from the rebased changeset. -** -** If conflict is with a remote UPDATE and the resolution is OMIT, then -** the old.* values are rebased using the new.* values in the remote -** change. Or, if the resolution is REPLACE, then the change is copied -** into the rebased changeset with updates to columns also updated by -** the conflicting remote UPDATE removed. If this means no columns would -** be updated, the change is omitted. -**
        -** -** A local change may be rebased against multiple remote changes -** simultaneously. If a single key is modified by multiple remote -** changesets, they are combined as follows before the local changeset -** is rebased: -** -**
          -**
        • If there has been one or more REPLACE resolutions on a -** key, it is rebased according to a REPLACE. -** -**
        • If there have been no REPLACE resolutions on a key, then -** the local changeset is rebased according to the most recent -** of the OMIT resolutions. -**
        -** -** Note that conflict resolutions from multiple remote changesets are -** combined on a per-field basis, not per-row. This means that in the -** case of multiple remote UPDATE operations, some fields of a single -** local change may be rebased for REPLACE while others are rebased for -** OMIT. -** -** In order to rebase a local changeset, the remote changeset must first -** be applied to the local database using sqlite3changeset_apply_v2() and -** the buffer of rebase information captured. Then: -** -**
          -**
        1. An sqlite3_rebaser object is created by calling -** sqlite3rebaser_create(). -**
        2. The new object is configured with the rebase buffer obtained from -** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). -** If the local changeset is to be rebased against multiple remote -** changesets, then sqlite3rebaser_configure() should be called -** multiple times, in the same order that the multiple -** sqlite3changeset_apply_v2() calls were made. -**
        3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). -**
        4. The sqlite3_rebaser object is deleted by calling -** sqlite3rebaser_delete(). -**
        -*/ -typedef struct sqlite3_rebaser sqlite3_rebaser; - -/* -** CAPI3REF: Create a changeset rebaser object. -** EXPERIMENTAL -** -** Allocate a new changeset rebaser object. If successful, set (*ppNew) to -** point to the new object and return SQLITE_OK. Otherwise, if an error -** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) -** to NULL. -*/ -SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); - -/* -** CAPI3REF: Configure a changeset rebaser object. -** EXPERIMENTAL -** -** Configure the changeset rebaser object to rebase changesets according -** to the conflict resolutions described by buffer pRebase (size nRebase -** bytes), which must have been obtained from a previous call to -** sqlite3changeset_apply_v2(). -*/ -SQLITE_API int sqlite3rebaser_configure( - sqlite3_rebaser*, - int nRebase, const void *pRebase -); - -/* -** CAPI3REF: Rebase a changeset -** EXPERIMENTAL -** -** Argument pIn must point to a buffer containing a changeset nIn bytes -** in size. This function allocates and populates a buffer with a copy -** of the changeset rebased according to the configuration of the -** rebaser object passed as the first argument. If successful, (*ppOut) -** is set to point to the new buffer containing the rebased changeset and -** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the -** responsibility of the caller to eventually free the new buffer using -** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) -** are set to zero and an SQLite error code returned. -*/ -SQLITE_API int sqlite3rebaser_rebase( - sqlite3_rebaser*, - int nIn, const void *pIn, - int *pnOut, void **ppOut -); - -/* -** CAPI3REF: Delete a changeset rebaser object. -** EXPERIMENTAL -** -** Delete the changeset rebaser object and all associated resources. There -** should be one call to this function for each successful invocation -** of sqlite3rebaser_create(). -*/ -SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); - /* ** CAPI3REF: Streaming Versions of API functions. ** -** The six streaming API xxx_strm() functions serve similar purposes to the +** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** ** -**
        Streaming functionNon-streaming equivalent
        sqlite3changeset_apply_strm[sqlite3changeset_apply] -**
        sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] -**
        sqlite3changeset_concat_strm[sqlite3changeset_concat] -**
        sqlite3changeset_invert_strm[sqlite3changeset_invert] -**
        sqlite3changeset_start_strm[sqlite3changeset_start] -**
        sqlite3session_changeset_strm[sqlite3session_changeset] -**
        sqlite3session_patchset_strm[sqlite3session_patchset] +**
        sqlite3changeset_apply_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] **
        ** ** Non-streaming functions that accept changesets (or patchsets) as input -** require that the entire changeset be stored in a single buffer in memory. -** Similarly, those that return a changeset or patchset do so by returning -** a pointer to a single large buffer allocated using sqlite3_malloc(). -** Normally this is convenient. However, if an application running in a +** require that the entire changeset be stored in a single buffer in memory. +** Similarly, those that return a changeset or patchset do so by returning +** a pointer to a single large buffer allocated using sqlite3_malloc(). +** Normally this is convenient. However, if an application running in a ** low-memory environment is required to handle very large changesets, the ** large contiguous memory allocations required can become onerous. ** ** In order to avoid this problem, instead of a single large buffer, input ** is passed to a streaming API functions by way of a callback function that @@ -13079,24 +11022,24 @@ **   int (*xInput)(void *pIn, void *pData, int *pnData), **   void *pIn, ** ** ** Each time the xInput callback is invoked by the sessions module, the first -** argument passed is a copy of the supplied pIn context pointer. The second -** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no -** error occurs the xInput method should copy up to (*pnData) bytes of data -** into the buffer and set (*pnData) to the actual number of bytes copied -** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) -** should be set to zero to indicate this. Or, if an error occurs, an SQLite +** argument passed is a copy of the supplied pIn context pointer. The second +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no +** error occurs the xInput method should copy up to (*pnData) bytes of data +** into the buffer and set (*pnData) to the actual number of bytes copied +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) +** should be set to zero to indicate this. Or, if an error occurs, an SQLite ** error code should be returned. In all cases, if an xInput callback returns ** an error, all processing is abandoned and the streaming API function ** returns a copy of the error code to the caller. ** ** In the case of sqlite3changeset_start_strm(), the xInput callback may be ** invoked by the sessions module at any point during the lifetime of the ** iterator. If such an xInput callback returns an error, the iterator enters -** an error state, whereby all subsequent calls to iterator functions +** an error state, whereby all subsequent calls to iterator functions ** immediately fail with the same error code as returned by xInput. ** ** Similarly, streaming API functions that return changesets (or patchsets) ** return them in chunks by way of a callback function instead of via a ** pointer to a single large buffer. In this case, a pair of parameters such @@ -13122,11 +11065,11 @@ ** supplied data, it should return SQLITE_OK to indicate success. Otherwise, ** it should return some other SQLite error code. In this case processing ** is immediately abandoned and the streaming API function returns a copy ** of the xOutput error code to the application. ** -** The sessions module never invokes an xOutput callback with the third +** The sessions module never invokes an xOutput callback with the third ** parameter set to a value less than or equal to zero. Other than this, ** no guarantees are made as to the size of the chunks of data returned. */ SQLITE_API int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -13141,27 +11084,10 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); -SQLITE_API int sqlite3changeset_apply_v2_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, @@ -13177,16 +11103,10 @@ SQLITE_API int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); -SQLITE_API int sqlite3changeset_start_v2_strm( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int flags -); SQLITE_API int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); @@ -13193,65 +11113,19 @@ SQLITE_API int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, +SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3rebaser_rebase_strm( - sqlite3_rebaser *pRebaser, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - -/* -** CAPI3REF: Configure global parameters -** -** The sqlite3session_config() interface is used to make global configuration -** changes to the sessions module in order to tune it to the specific needs -** of the application. -** -** The sqlite3session_config() interface is not threadsafe. If it is invoked -** while any other thread is inside any other sessions method then the -** results are undefined. Furthermore, if it is invoked after any sessions -** related objects have been created, the results are also undefined. -** -** The first argument to the sqlite3session_config() function must be one -** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The -** interpretation of the (void*) value passed as the second parameter and -** the effect of calling this function depends on the value of the first -** parameter. -** -**
        -**
        SQLITE_SESSION_CONFIG_STRMSIZE
        -** By default, the sessions module streaming interfaces attempt to input -** and output data in approximately 1 KiB chunks. This operand may be used -** to set and query the value of this configuration setting. The pointer -** passed as the second argument must point to a value of type (int). -** If this value is greater than 0, it is used as the new streaming data -** chunk size for both input and output. Before returning, the (int) value -** pointed to by pArg is set to the final value of the streaming interface -** chunk size. -**
        -** -** This function returns SQLITE_OK if successful, or an SQLite error code -** otherwise. -*/ -SQLITE_API int sqlite3session_config(int op, void *pArg); - -/* -** CAPI3REF: Values for sqlite3session_config(). -*/ -#define SQLITE_SESSION_CONFIG_STRMSIZE 1 + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + /* ** Make sure we can call this stuff from C++. */ #if 0 @@ -13272,11 +11146,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** -** Interfaces to extend FTS5. Using the interfaces defined in this file, +** Interfaces to extend FTS5. Using the interfaces defined in this file, ** FTS5 may be extended with: ** ** * custom tokenizers, and ** * custom auxiliary functions. */ @@ -13316,23 +11190,23 @@ /* ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): -** Return a copy of the pUserData pointer passed to the xCreateFunction() -** API when the extension function was registered. +** Return a copy of the context pointer the extension function was +** registered with. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken ** to the total number of tokens in the FTS5 table. Or, if iCol is ** non-negative but less than the number of columns in the table, return -** the total number of tokens in column iCol, considering all rows in +** the total number of tokens in column iCol, considering all rows in ** the FTS5 table. ** ** If parameter iCol is greater than or equal to the number of columns ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is +** an OOM condition or IO error), an appropriate SQLite error code is ** returned. ** ** xColumnCount(pFts): ** Return the number of columns in the table. ** @@ -13342,60 +11216,58 @@ ** non-negative but less than the number of columns in the table, set ** *pnToken to the number of tokens in column iCol of the current row. ** ** If parameter iCol is greater than or equal to the number of columns ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is +** an OOM condition or IO error), an appropriate SQLite error code is ** returned. ** ** This function may be quite inefficient if used with an FTS5 table ** created with the "columnsize=0" option. ** ** xColumnText: -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the text of column iCol of -** the current document. If successful, (*pz) is set to point to a buffer +** This function attempts to retrieve the text of column iCol of the +** current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values ** of (*pz) and (*pn) are undefined. ** ** xPhraseCount: ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: -** If parameter iCol is less than zero, or greater than or equal to the -** number of phrases in the current query, as returned by xPhraseCount, -** 0 is returned. Otherwise, this function returns the number of tokens in -** phrase iPhrase of the query. Phrases are numbered starting from zero. +** Returns the number of tokens in phrase iPhrase of the query. Phrases +** are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within ** the query within the current row. Return SQLITE_OK if successful, or ** an error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option ** (i.e. if it is a contentless table), then this API always returns 0. ** ** xInst: ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). If iIdx is less than zero or greater than -** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. +** output by xInstCount(). ** -** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol +** Usually, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. SQLITE_OK is returned if successful, or an -** error code (i.e. SQLITE_NOMEM) if an error occurs. +** first token of the phrase. The exception is if the table was created +** with the offsets=0 option specified. In this case *piOff is always +** set to -1. +** +** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM) +** if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. +** "detail=none" or "detail=column" option. ** ** xRowid: ** Returns the rowid of the current row. ** ** xTokenize: @@ -13407,21 +11279,17 @@ ** ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the ** current query is executed. Any column filter that applies to -** phrase iPhrase of the current query is included in $p. For each -** row visited, the callback function passed as the fourth argument -** is invoked. The context and API objects passed to the callback +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback ** function may be used to access the properties of each matched row. -** Invoking Api.xUserData() returns a copy of the pointer passed as +** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** -** If parameter iPhrase is less than zero, or greater than or equal to -** the number of phrases in the query, as returned by xPhraseCount(), -** this function returns SQLITE_RANGE. -** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. ** Otherwise, the error code is propagated upwards. ** @@ -13430,18 +11298,18 @@ ** the callback, an SQLite error code is returned. ** ** ** xSetAuxdata(pFts5, pAux, xDelete) ** -** Save the pointer passed as the second argument as the extension function's +** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of -** the same MATCH query using the xGetAuxdata() API. +** of the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for -** each FTS query (MATCH expression). If the extension function is invoked -** more than once for a single FTS query, then all invocations share a +** each FTS query (MATCH expression). If the extension function is invoked +** more than once for a single FTS query, then all invocations share a ** single auxiliary data context. ** ** If there is already an auxiliary data pointer when this function is ** invoked, then it is replaced by the new pointer. If an xDelete callback ** was specified along with the original pointer, it is invoked at this @@ -13448,19 +11316,19 @@ ** point. ** ** The xDelete callback, if one is specified, is also invoked on the ** auxiliary data pointer after the FTS5 query has finished. ** -** If an error (e.g. an OOM condition) occurs within this function, +** If an error (e.g. an OOM condition) occurs within this function, an ** the auxiliary data is set to NULL and an error code returned. If the ** xDelete parameter was not NULL, it is invoked on the auxiliary data ** pointer before returning. ** ** ** xGetAuxdata(pFts5, bClear) ** -** Returns the current auxiliary data pointer for the fts5 extension +** Returns the current auxiliary data pointer for the fts5 extension ** function. See the xSetAuxdata() method for details. ** ** If the bClear argument is non-zero, then the auxiliary data is cleared ** (set to NULL) before this function returns. In this case the xDelete, ** if any, is not invoked. @@ -13476,11 +11344,11 @@ ** xPhraseFirst() ** This function is used, along with type Fts5PhraseIter and the xPhraseNext ** method, to iterate through all instances of a single query phrase within ** the current row. This is the same information as is accessible via the ** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient -** to use, this API may be faster under some circumstances. To iterate +** to use, this API may be faster under some circumstances. To iterate ** through instances of phrase iPhrase, use the following code: ** ** Fts5PhraseIter iter; ** int iCol, iOff; ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); @@ -13494,19 +11362,15 @@ ** modify this structure directly - it should only be used as shown above ** with the xPhraseFirst() and xPhraseNext() API methods (and by ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option ** (i.e. if it is a contentless table), then this API always iterates ** through an empty set (all calls to xPhraseFirst() set iCol to -1). ** -** In all cases, matches are visited in (column ASC, offset ASC) order. -** i.e. all those in column 0, sorted by offset, followed by those in -** column 1, etc. -** ** xPhraseNext() ** See xPhraseFirst above. ** ** xPhraseFirstColumn() ** This function and xPhraseNextColumn() are similar to the xPhraseFirst() @@ -13523,105 +11387,34 @@ ** ){ ** // Column iCol contains at least one instance of phrase iPhrase ** } ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" option. If the FTS5 table is created with either -** "detail=none" "content=" option (i.e. if it is a contentless table), -** then this API always iterates through an empty set (all calls to +** "detail=none" option. If the FTS5 table is created with either +** "detail=none" "content=" option (i.e. if it is a contentless table), +** then this API always iterates through an empty set (all calls to ** xPhraseFirstColumn() set iCol to -1). ** ** The information accessed using this API and its companion ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext ** (or xInst/xInstCount). The chief advantage of this API is that it is ** significantly more efficient than those alternatives when used with -** "detail=column" tables. +** "detail=column" tables. ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above. -** -** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase iPhrase of the current -** query. Before returning, output parameter *ppToken is set to point -** to a buffer containing the requested token, and *pnToken to the -** size of this buffer in bytes. -** -** If iPhrase or iToken are less than zero, or if iPhrase is greater than -** or equal to the number of phrases in the query as reported by -** xPhraseCount(), or if iToken is equal to or greater than the number of -** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken - are both zeroed. -** -** The output text is not a copy of the query text that specified the -** token. It is the output of the tokenizer module. For tokendata=1 -** tables, this includes any embedded 0x00 and trailing data. -** -** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase hit iIdx within the -** current row. If iIdx is less than zero or greater than or equal to the -** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, -** output variable (*ppToken) is set to point to a buffer containing the -** matching document token, and (*pnToken) to the size of that buffer in -** bytes. -** -** The output text is not a copy of the document text that was tokenized. -** It is the output of the tokenizer module. For tokendata=1 tables, this -** includes any embedded 0x00 and trailing data. -** -** This API may be slow in some cases if the token identified by parameters -** iIdx and iToken matched a prefix token in the query. In most cases, the -** first call to this API for each prefix token in the query is forced -** to scan the portion of the full-text index that matches the prefix -** token to collect the extra data required by this API. If the prefix -** token matches a large number of token instances in the document set, -** this may be a performance problem. -** -** If the user knows in advance that a query may use this API for a -** prefix token, FTS5 may be configured to collect all required data as part -** of the initial querying of the full-text index, avoiding the second scan -** entirely. This also causes prefix queries that do not use this API to -** run more slowly and use more memory. FTS5 may be configured in this way -** either on a per-table basis using the [FTS5 insttoken | 'insttoken'] -** option, or on a per-query basis using the -** [fts5_insttoken | fts5_insttoken()] user function. -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. -** -** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale) -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the locale associated -** with column iCol of the current row. Usually, there is no associated -** locale, and output parameters (*pzLocale) and (*pnLocale) are set -** to NULL and 0, respectively. However, if the fts5_locale() function -** was used to associate a locale with the value when it was inserted -** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated -** buffer containing the name of the locale in utf-8 encoding. (*pnLocale) -** is set to the size in bytes of the buffer, not including the -** nul-terminator. -** -** If successful, SQLITE_OK is returned. Or, if an error occurs, an -** SQLite error code is returned. The final value of the output parameters -** is undefined in this case. -** -** xTokenize_v2: -** Tokenize text using the tokenizer belonging to the FTS5 table. This -** API is the same as the xTokenize() API, except that it allows a tokenizer -** locale to be specified. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 4 */ + int iVersion; /* Currently always set to 3 */ void *(*xUserData)(Fts5Context*); int (*xColumnCount)(Fts5Context*); int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); - int (*xTokenize)(Fts5Context*, + int (*xTokenize)(Fts5Context*, const char *pText, int nText, /* Text to tokenize */ void *pCtx, /* Context passed to xToken() */ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ ); @@ -13644,114 +11437,91 @@ int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); - - /* Below this point are iVersion>=3 only */ - int (*xQueryToken)(Fts5Context*, - int iPhrase, int iToken, - const char **ppToken, int *pnToken - ); - int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); - - /* Below this point are iVersion>=4 only */ - int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xTokenize_v2)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - const char *pLocale, int nLocale, /* Locale to pass to tokenizer */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); }; -/* +/* ** CUSTOM AUXILIARY FUNCTIONS *************************************************************************/ /************************************************************************* ** CUSTOM TOKENIZERS ** -** Applications may also register custom tokenizer types. A tokenizer -** is registered by providing fts5 with a populated instance of the +** Applications may also register custom tokenizer types. A tokenizer +** is registered by providing fts5 with a populated instance of the ** following structure. All structure methods must be defined, setting ** any member of the fts5_tokenizer struct to NULL leads to undefined ** behaviour. The structure methods are expected to function as follows: ** ** xCreate: ** This function is used to allocate and initialize a tokenizer instance. ** A tokenizer instance is required to actually tokenize text. ** ** The first argument passed to this function is a copy of the (void*) -** pointer provided by the application when the fts5_tokenizer_v2 object -** was registered with FTS5 (the third argument to xCreateTokenizer()). +** pointer provided by the application when the fts5_tokenizer object +** was registered with FTS5 (the third argument to xCreateTokenizer()). ** The second and third arguments are an array of nul-terminated strings ** containing the tokenizer arguments, if any, specified following the ** tokenizer name as part of the CREATE VIRTUAL TABLE statement used ** to create the FTS5 table. ** -** The final argument is an output variable. If successful, (*ppOut) +** The final argument is an output variable. If successful, (*ppOut) ** should be set to point to the new tokenizer handle and SQLITE_OK ** returned. If an error occurs, some value other than SQLITE_OK should -** be returned. In this case, fts5 assumes that the final value of *ppOut +** be returned. In this case, fts5 assumes that the final value of *ppOut ** is undefined. ** ** xDelete: ** This function is invoked to delete a tokenizer handle previously ** allocated using xCreate(). Fts5 guarantees that this function will ** be invoked exactly once for each successful call to xCreate(). ** ** xTokenize: -** This function is expected to tokenize the nText byte string indicated +** This function is expected to tokenize the nText byte string indicated ** by argument pText. pText may or may not be nul-terminated. The first ** argument passed to this function is a pointer to an Fts5Tokenizer object ** returned by an earlier call to xCreate(). ** -** The third argument indicates the reason that FTS5 is requesting +** The second argument indicates the reason that FTS5 is requesting ** tokenization of the supplied text. This is always one of the following ** four values: ** **
        • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into ** or removed from the FTS table. The tokenizer is being invoked to ** determine the set of tokens to add to (or delete from) the ** FTS index. ** -**
        • FTS5_TOKENIZE_QUERY - A MATCH query is being executed -** against the FTS index. The tokenizer is being called to tokenize +**
        • FTS5_TOKENIZE_QUERY - A MATCH query is being executed +** against the FTS index. The tokenizer is being called to tokenize ** a bareword or quoted string specified as part of the query. ** **
        • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as ** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is ** followed by a "*" character, indicating that the last token ** returned by the tokenizer will be treated as a token prefix. ** -**
        • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to +**
        • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to ** satisfy an fts5_api.xTokenize() request made by an auxiliary ** function. Or an fts5_api.xColumnSize() request made by the same -** on a columnsize=0 database. +** on a columnsize=0 database. **
        ** -** The sixth and seventh arguments passed to xTokenize() - pLocale and -** nLocale - are a pointer to a buffer containing the locale to use for -** tokenization (e.g. "en_US") and its size in bytes, respectively. The -** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in -** which case nLocale is always 0) to indicate that the tokenizer should -** use its default locale. -** ** For each token in the input string, the supplied callback xToken() must ** be invoked. The first argument to it should be a copy of the pointer ** passed as the second argument to xTokenize(). The third and fourth ** arguments are a pointer to a buffer containing the token text, and the ** size of the token in bytes. The 4th and 5th arguments are the byte offsets ** of the first byte of and first byte immediately following the text from ** which the token is derived within the input. ** ** The second argument passed to the xToken() callback ("tflags") should -** normally be set to 0. The exception is if the tokenizer supports +** normally be set to 0. The exception is if the tokenizer supports ** synonyms. In this case see the discussion below for details. ** -** FTS5 assumes the xToken() callback is invoked for each token in the +** FTS5 assumes the xToken() callback is invoked for each token in the ** order that they occur within the input text. ** ** If an xToken() callback returns any value other than SQLITE_OK, then ** the tokenization should be abandoned and the xTokenize() method should ** immediately return a copy of the xToken() return value. Or, if the @@ -13758,86 +11528,62 @@ ** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, ** if an error occurs with the xTokenize() implementation itself, it ** may abandon the tokenization and return any error code other than ** SQLITE_OK or SQLITE_DONE. ** -** If the tokenizer is registered using an fts5_tokenizer_v2 object, -** then the xTokenize() method has two additional arguments - pLocale -** and nLocale. These specify the locale that the tokenizer should use -** for the current request. If pLocale and nLocale are both 0, then the -** tokenizer should use its default locale. Otherwise, pLocale points to -** an nLocale byte buffer containing the name of the locale to use as utf-8 -** text. pLocale is not nul-terminated. -** -** FTS5_TOKENIZER -** -** There is also an fts5_tokenizer object. This is an older, deprecated, -** version of fts5_tokenizer_v2. It is similar except that: -** -**
          -**
        • There is no "iVersion" field, and -**
        • The xTokenize() method does not take a locale argument. -**
        -** -** Legacy fts5_tokenizer tokenizers must be registered using the -** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2(). -** -** Tokenizer implementations registered using either API may be retrieved -** using both xFindTokenizer() and xFindTokenizer_v2(). -** ** SYNONYM SUPPORT ** ** Custom tokenizers may also support synonyms. Consider a case in which a -** user wishes to query for a phrase such as "first place". Using the +** user wishes to query for a phrase such as "first place". Using the ** built-in tokenizers, the FTS5 query 'first + place' will match instances ** of "first place" within the document set, but not alternative forms ** such as "1st place". In some applications, it would be better to match ** all instances of "first place" or "1st place" regardless of which form ** the user specified in the MATCH query text. ** ** There are several ways to approach this in FTS5: ** -**
        1. By mapping all synonyms to a single token. In this case, using -** the above example, this means that the tokenizer returns the +**
          1. By mapping all synonyms to a single token. In this case, the +** In the above example, this means that the tokenizer returns the ** same token for inputs "first" and "1st". Say that token is in ** fact "first", so that when the user inserts the document "I won ** 1st place" entries are added to the index for tokens "i", "won", ** "first" and "place". If the user then queries for '1st + place', ** the tokenizer substitutes "first" for "1st" and the query works ** as expected. ** -**
          2. By querying the index for all synonyms of each query term -** separately. In this case, when tokenizing query text, the -** tokenizer may provide multiple synonyms for a single term -** within the document. FTS5 then queries the index for each -** synonym individually. For example, faced with the query: +**
          3. By adding multiple synonyms for a single term to the FTS index. +** In this case, when tokenizing query text, the tokenizer may +** provide multiple synonyms for a single term within the document. +** FTS5 then queries the index for each synonym individually. For +** example, faced with the query: ** ** ** ... MATCH 'first place' ** ** the tokenizer offers both "1st" and "first" as synonyms for the -** first token in the MATCH query and FTS5 effectively runs a query +** first token in the MATCH query and FTS5 effectively runs a query ** similar to: ** ** ** ... MATCH '(first OR 1st) place' ** ** except that, for the purposes of auxiliary functions, the query -** still appears to contain just two phrases - "(first OR 1st)" +** still appears to contain just two phrases - "(first OR 1st)" ** being treated as a single phrase. ** **
          4. By adding multiple synonyms for a single term to the FTS index. ** Using this method, when tokenizing document text, the tokenizer -** provides multiple synonyms for each token. So that when a +** provides multiple synonyms for each token. So that when a ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms -** when tokenizing query text (it should not - to do so would be -** inefficient), it doesn't matter if the user queries for -** 'first + place' or '1st + place', as there are entries in the +** when tokenizing query text (it should not - to do would be +** inefficient), it doesn't matter if the user queries for +** 'first + place' or '1st + place', as there are entires in the ** FTS index corresponding to both forms of the first token. **
          ** ** Whether it is parsing document or query text, any call to xToken that ** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit @@ -13853,58 +11599,55 @@ ** xToken(pCtx, 0, "place", 5, 12, 17); ** ** ** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time ** xToken() is called. Multiple synonyms may be specified for a single token -** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. +** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. ** There is no limit to the number of synonyms that may be provided for a ** single token. ** -** In many cases, method (1) above is the best approach. It does not add +** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the -** token "first" is substituted for "1st" by the tokenizer, then the query: +** token "first" is subsituted for "1st" by the tokenizer, then the query: ** ** ** ... MATCH '1s*' ** ** will not match documents that contain the token "1st" (as the tokenizer ** will probably not map "1s" to any prefix of "first"). ** -** For full prefix support, method (3) may be preferred. In this case, +** For full prefix support, method (3) may be preferred. In this case, ** because the index contains entries for both "first" and "1st", prefix ** queries such as 'fi*' or '1s*' will match correctly. However, because ** extra entries are added to the FTS index, this method uses more space ** within the database. ** ** Method (2) offers a midpoint between (1) and (3). Using this method, -** a query such as '1s*' will match documents that contain the literal +** a query such as '1s*' will match documents that contain the literal ** token "1st", but not "first" (assuming the tokenizer is not able to ** provide synonyms for prefixes). However, a non-prefix query like '1st' ** will match against "1st" and "first". This method does not require -** extra disk space, as no extra entries are added to the FTS index. +** extra disk space, as no extra entries are added to the FTS index. ** On the other hand, it may require more CPU cycles to run MATCH queries, ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (3)) or query -** text (method (2)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (2)) or query +** text (method (3)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; -typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2; -struct fts5_tokenizer_v2 { - int iVersion; /* Currently always 2 */ - +typedef struct fts5_tokenizer fts5_tokenizer; +struct fts5_tokenizer { int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, + int (*xTokenize)(Fts5Tokenizer*, void *pCtx, int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - const char *pLocale, int nLocale, + const char *pText, int nText, int (*xToken)( void *pCtx, /* Copy of 2nd argument to xTokenize() */ int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Pointer to buffer containing token */ int nToken, /* Size of token in bytes */ @@ -13911,35 +11654,10 @@ int iStart, /* Byte offset of token within input text */ int iEnd /* Byte offset of end of token within input text */ ) ); }; - -/* -** New code should use the fts5_tokenizer_v2 type to define tokenizer -** implementations. The following type is included for legacy applications -** that still use it. -*/ -typedef struct fts5_tokenizer fts5_tokenizer; -struct fts5_tokenizer { - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); -}; - /* Flags that may be passed as the third argument to xTokenize() */ #define FTS5_TOKENIZE_QUERY 0x0001 #define FTS5_TOKENIZE_PREFIX 0x0002 #define FTS5_TOKENIZE_DOCUMENT 0x0004 @@ -13956,56 +11674,37 @@ /************************************************************************* ** FTS5 EXTENSION REGISTRATION API */ typedef struct fts5_api fts5_api; struct fts5_api { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ /* Create a new tokenizer */ int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pUserData, + void *pContext, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); /* Find an existing tokenizer */ int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppUserData, + void **ppContext, fts5_tokenizer *pTokenizer ); /* Create a new auxiliary function */ int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pUserData, + void *pContext, fts5_extension_function xFunction, void (*xDestroy)(void*) ); - - /* APIs below this point are only available if iVersion>=3 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void *pUserData, - fts5_tokenizer_v2 *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void **ppUserData, - fts5_tokenizer_v2 **ppTokenizer - ); }; /* ** END OF REGISTRATION API *************************************************************************/ @@ -14015,26 +11714,20 @@ #endif #endif /* _FTS5_H */ /******** End of fts5.h *********/ -#endif /* SQLITE3_H */ /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ -/* -** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory. -*/ -#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1 - /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) -#include "sqlite_cfg.h" +/* #include "config.h" */ #define SQLITECONFIG_H 1 #endif /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ /************** Begin file sqliteLimit.h *************************************/ @@ -14047,11 +11740,11 @@ ** 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 defines various limits of what SQLite can process. */ /* ** The maximum length of a TEXT or BLOB in bytes. This also @@ -14061,11 +11754,10 @@ ** to count the size: 2^31-1 or 2147483647. */ #ifndef SQLITE_MAX_LENGTH # define SQLITE_MAX_LENGTH 1000000000 #endif -#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */ /* ** This is the maximum number of ** ** * Columns in a table @@ -14096,14 +11788,18 @@ #ifndef SQLITE_MAX_SQL_LENGTH # define SQLITE_MAX_SQL_LENGTH 1000000000 #endif /* -** The maximum depth of an expression tree. This is limited to -** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might -** want to place more severe limits on the complexity of an -** expression. A value of 0 means that there is no limit. +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. */ #ifndef SQLITE_MAX_EXPR_DEPTH # define SQLITE_MAX_EXPR_DEPTH 1000 #endif @@ -14111,11 +11807,11 @@ ** The maximum number of terms in a compound SELECT statement. ** The code generator for compound SELECT statements does one ** level of recursion for each term. A stack overflow can result ** if the number of terms is too large. In practice, most SQL ** never has more than 3 or 4 terms. Use a value of 0 to disable -** any limit on the number of terms in a compound SELECT. +** any limit on the number of terms in a compount SELECT. */ #ifndef SQLITE_MAX_COMPOUND_SELECT # define SQLITE_MAX_COMPOUND_SELECT 500 #endif @@ -14127,17 +11823,13 @@ # define SQLITE_MAX_VDBE_OP 250000000 #endif /* ** The maximum number of arguments to an SQL function. -** -** This value has a hard upper limit of 32767 due to storage -** constraints (it needs to fit inside a i16). We keep it -** lower than that to prevent abuse. */ #ifndef SQLITE_MAX_FUNCTION_ARG -# define SQLITE_MAX_FUNCTION_ARG 1000 +# define SQLITE_MAX_FUNCTION_ARG 127 #endif /* ** The suggested maximum number of in-memory pages to use for ** the main database table and for temporary tables. @@ -14170,27 +11862,24 @@ #endif /* ** The maximum value of a ?nnn wildcard that the parser will accept. -** If the value exceeds 32767 then extra space is required for the Expr -** structure. But otherwise, we believe that the number can be as large -** as a signed 32-bit integer can hold. */ #ifndef SQLITE_MAX_VARIABLE_NUMBER -# define SQLITE_MAX_VARIABLE_NUMBER 32766 +# define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 65536. This a limit ** imposed by the use of 16-bit offsets within each page. ** ** Earlier versions of SQLite allowed the user to change this value at ** compile time. This is no longer permitted, on the grounds that it creates -** a library that is technically incompatible with an SQLite library -** compiled with a different limit. If a process operating on a database -** with a page-size of 65536 bytes crashes, then an instance of SQLite -** compiled with the default page-size limit will not be able to rollback +** a library that is technically incompatible with an SQLite library +** compiled with a different limit. If a process operating on a database +** with a page-size of 65536 bytes crashes, then an instance of SQLite +** compiled with the default page-size limit will not be able to rollback ** the aborted transaction. This could lead to database corruption. */ #ifdef SQLITE_MAX_PAGE_SIZE # undef SQLITE_MAX_PAGE_SIZE #endif @@ -14230,11 +11919,11 @@ ** This is really just the default value for the max_page_count pragma. ** This value can be lowered (or raised) at run-time using that the ** max_page_count macro. */ #ifndef SQLITE_MAX_PAGE_COUNT -# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */ +# define SQLITE_MAX_PAGE_COUNT 1073741823 #endif /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. @@ -14245,11 +11934,11 @@ /* ** Maximum depth of recursion for triggers. ** ** A value of 1 means that a trigger program will not be able to itself -** fire any triggers. A value of 0 means that no trigger programs at all +** fire any triggers. A value of 0 means that no trigger programs at all ** may be executed. */ #ifndef SQLITE_MAX_TRIGGER_DEPTH # define SQLITE_MAX_TRIGGER_DEPTH 1000 #endif @@ -14264,27 +11953,10 @@ #pragma warn -aus /* Assigned value is never used */ #pragma warn -csu /* Comparing signed and unsigned */ #pragma warn -spa /* Suspicious pointer arithmetic */ #endif -/* -** A few places in the code require atomic load/store of aligned -** integer values. -*/ -#ifndef __has_extension -# define __has_extension(x) 0 /* compatibility with non-clang compilers */ -#endif -#if GCC_VERSION>=4007000 || __has_extension(c_atomic) -# define SQLITE_ATOMIC_INTRINSICS 1 -# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED) -# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED) -#else -# define SQLITE_ATOMIC_INTRINSICS 0 -# define AtomicLoad(PTR) (*(PTR)) -# define AtomicStore(PTR,VAL) (*(PTR) = (VAL)) -#endif - /* ** Include standard header files as necessary */ #ifdef HAVE_STDINT_H #include @@ -14307,41 +11979,34 @@ ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). ** So we have to define the macros in different ways depending on the ** compiler. */ -#if defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ -# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) -# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) -#elif defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) #elif !defined(__GNUC__) /* Works for compilers other than LLVM */ # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) +#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif /* -** Macros to hint to the compiler that a function should or should not be +** A macro to hint to the compiler that a function should not be ** inlined. */ #if defined(__GNUC__) # define SQLITE_NOINLINE __attribute__((noinline)) -# define SQLITE_INLINE __attribute__((always_inline)) inline #elif defined(_MSC_VER) && _MSC_VER>=1310 # define SQLITE_NOINLINE __declspec(noinline) -# define SQLITE_INLINE __forceinline #else # define SQLITE_NOINLINE -# define SQLITE_INLINE -#endif -#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__) -# undef SQLITE_INLINE -# define SQLITE_INLINE #endif /* ** Make sure that the compiler intrinsics we desire are enabled when ** compiling with an appropriate version of MSVC unless prevented by @@ -14358,33 +12023,10 @@ # else # include # endif # endif #endif - -/* -** Enable SQLITE_USE_SEH by default on MSVC builds. Only omit -** SEH support if the -DSQLITE_OMIT_SEH option is given. -*/ -#if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH) -# define SQLITE_USE_SEH 1 -#else -# undef SQLITE_USE_SEH -#endif - -/* -** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly -** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0 -*/ -#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1 - /* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */ -# undef SQLITE_DIRECT_OVERFLOW_READ -#else - /* In all other cases, enable */ -# define SQLITE_DIRECT_OVERFLOW_READ 1 -#endif - /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never ** threadsafe. 1 means the library is serialized which is the highest @@ -14511,16 +12153,15 @@ ** can be used to make sure boundary values are tested. For ** bitmask tests, testcase() can be used to make sure each bit ** is significant and used at least once. On switch statements ** where multiple cases go to the same block of code, testcase() ** can insure that all cases are evaluated. +** */ -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) -# ifndef SQLITE_AMALGAMATION - extern unsigned int sqlite3CoverageCounter; -# endif -# define testcase(X) if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; } +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } #else # define testcase(X) #endif /* @@ -14546,18 +12187,10 @@ # define VVA_ONLY(X) X #else # define VVA_ONLY(X) #endif -/* -** Disable ALWAYS() and NEVER() (make them pass-throughs) for coverage -** and mutation testing -*/ -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) -# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 -#endif - /* ** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience @@ -14569,11 +12202,11 @@ ** ** When doing coverage testing ALWAYS and NEVER are hard-coded to ** be true and false so that the unreachable code they specify will ** not be counted as untested code. */ -#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) +#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) @@ -14580,25 +12213,10 @@ #else # define ALWAYS(X) (X) # 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 ** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches ** during a normal build. The following macro can be used to disable tests @@ -14643,19 +12261,10 @@ */ #ifdef SQLITE_OMIT_EXPLAIN # undef SQLITE_ENABLE_EXPLAIN_COMMENTS #endif -/* -** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE -*/ -#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE) -# define SQLITE_OMIT_ALTERTABLE -#endif - -#define SQLITE_DIGIT_SEPARATOR '_' - /* ** Return true (non-zero) if the input is an integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() ** macros to verify that we have tested SQLite for large-file support. */ @@ -14708,26 +12317,26 @@ ** There are Hash.htsize buckets. Each bucket points to a spot in ** the global doubly-linked list. The contents of the bucket are the ** element pointed to plus the next _ht.count-1 elements in the list. ** ** Hash.htsize and Hash.ht may be zero. In that case lookup is done -** by a linear search of the global list. For small tables, the +** by a linear search of the global list. For small tables, the ** Hash.ht table is never allocated because if there are few elements ** in the table, it is faster to do a linear search than to manage ** the hash table. */ struct Hash { unsigned int htsize; /* Number of buckets in the hash table */ unsigned int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ struct _ht { /* the hash table */ - unsigned int count; /* Number of entries with this hash */ + int count; /* Number of entries with this hash */ HashElem *chain; /* Pointer to first entry with this hash */ } *ht; }; -/* Each element in the hash table is an instance of the following +/* Each element in the hash table is an instance of the following ** structure. All elements are stored on a single doubly-linked list. ** ** Again, this structure is intended to be opaque, but it can't really ** be opaque because it is used by macros. */ @@ -14764,11 +12373,11 @@ /* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ -#define sqliteHashCount(H) ((H)->count) +/* #define sqliteHashCount(H) ((H)->count) // NOT USED */ #endif /* SQLITE_HASH_H */ /************** End of hash.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -14796,181 +12405,165 @@ #define TK_EXISTS 20 #define TK_TEMP 21 #define TK_LP 22 #define TK_RP 23 #define TK_AS 24 -#define TK_COMMA 25 -#define TK_WITHOUT 26 -#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_ISNOT 46 -#define TK_MATCH 47 -#define TK_LIKE_KW 48 -#define TK_BETWEEN 49 -#define TK_IN 50 -#define TK_ISNULL 51 -#define TK_NOTNULL 52 -#define TK_NE 53 -#define TK_EQ 54 -#define TK_GT 55 -#define TK_LE 56 -#define TK_LT 57 -#define TK_GE 58 -#define TK_ESCAPE 59 -#define TK_ID 60 -#define TK_COLUMNKW 61 -#define TK_DO 62 -#define TK_FOR 63 -#define TK_IGNORE 64 -#define TK_INITIALLY 65 -#define TK_INSTEAD 66 -#define TK_NO 67 -#define TK_KEY 68 -#define TK_OF 69 -#define TK_OFFSET 70 -#define TK_PRAGMA 71 -#define TK_RAISE 72 -#define TK_RECURSIVE 73 -#define TK_REPLACE 74 -#define TK_RESTRICT 75 -#define TK_ROW 76 -#define TK_ROWS 77 -#define TK_TRIGGER 78 -#define TK_VACUUM 79 -#define TK_VIEW 80 -#define TK_VIRTUAL 81 -#define TK_WITH 82 -#define TK_NULLS 83 -#define TK_FIRST 84 -#define TK_LAST 85 -#define TK_CURRENT 86 -#define TK_FOLLOWING 87 -#define TK_PARTITION 88 -#define TK_PRECEDING 89 -#define TK_RANGE 90 -#define TK_UNBOUNDED 91 -#define TK_EXCLUDE 92 -#define TK_GROUPS 93 -#define TK_OTHERS 94 -#define TK_TIES 95 -#define TK_GENERATED 96 -#define TK_ALWAYS 97 -#define TK_MATERIALIZED 98 -#define TK_REINDEX 99 -#define TK_RENAME 100 -#define TK_CTIME_KW 101 -#define TK_ANY 102 -#define TK_BITAND 103 -#define TK_BITOR 104 -#define TK_LSHIFT 105 -#define TK_RSHIFT 106 -#define TK_PLUS 107 -#define TK_MINUS 108 -#define TK_STAR 109 -#define TK_SLASH 110 -#define TK_REM 111 -#define TK_CONCAT 112 -#define TK_PTR 113 -#define TK_COLLATE 114 -#define TK_BITNOT 115 -#define TK_ON 116 -#define TK_INDEXED 117 -#define TK_STRING 118 -#define TK_JOIN_KW 119 -#define TK_CONSTRAINT 120 -#define TK_DEFAULT 121 -#define TK_NULL 122 -#define TK_PRIMARY 123 -#define TK_UNIQUE 124 -#define TK_CHECK 125 -#define TK_REFERENCES 126 -#define TK_AUTOINCR 127 -#define TK_INSERT 128 -#define TK_DELETE 129 -#define TK_UPDATE 130 -#define TK_SET 131 -#define TK_DEFERRABLE 132 -#define TK_FOREIGN 133 -#define TK_DROP 134 -#define TK_UNION 135 -#define TK_ALL 136 -#define TK_EXCEPT 137 -#define TK_INTERSECT 138 -#define TK_SELECT 139 -#define TK_VALUES 140 -#define TK_DISTINCT 141 -#define TK_DOT 142 -#define TK_FROM 143 -#define TK_JOIN 144 -#define TK_USING 145 -#define TK_ORDER 146 -#define TK_GROUP 147 -#define TK_HAVING 148 -#define TK_LIMIT 149 -#define TK_WHERE 150 -#define TK_RETURNING 151 -#define TK_INTO 152 -#define TK_NOTHING 153 -#define TK_FLOAT 154 -#define TK_BLOB 155 -#define TK_INTEGER 156 -#define TK_VARIABLE 157 -#define TK_CASE 158 -#define TK_WHEN 159 -#define TK_THEN 160 -#define TK_ELSE 161 -#define TK_INDEX 162 -#define TK_ALTER 163 -#define TK_ADD 164 -#define TK_WINDOW 165 -#define TK_OVER 166 -#define TK_FILTER 167 -#define TK_COLUMN 168 -#define TK_AGG_FUNCTION 169 -#define TK_AGG_COLUMN 170 -#define TK_TRUEFALSE 171 -#define TK_FUNCTION 172 -#define TK_UPLUS 173 -#define TK_UMINUS 174 -#define TK_TRUTH 175 -#define TK_REGISTER 176 -#define TK_VECTOR 177 -#define TK_SELECT_COLUMN 178 -#define TK_IF_NULL_ROW 179 -#define TK_ASTERISK 180 -#define TK_SPAN 181 -#define TK_ERROR 182 -#define TK_QNUMBER 183 -#define TK_SPACE 184 -#define TK_COMMENT 185 -#define TK_ILLEGAL 186 +#define TK_WITHOUT 25 +#define TK_COMMA 26 +#define TK_ID 27 +#define TK_ABORT 28 +#define TK_ACTION 29 +#define TK_AFTER 30 +#define TK_ANALYZE 31 +#define TK_ASC 32 +#define TK_ATTACH 33 +#define TK_BEFORE 34 +#define TK_BY 35 +#define TK_CASCADE 36 +#define TK_CAST 37 +#define TK_COLUMNKW 38 +#define TK_CONFLICT 39 +#define TK_DATABASE 40 +#define TK_DESC 41 +#define TK_DETACH 42 +#define TK_EACH 43 +#define TK_FAIL 44 +#define TK_FOR 45 +#define TK_IGNORE 46 +#define TK_INITIALLY 47 +#define TK_INSTEAD 48 +#define TK_LIKE_KW 49 +#define TK_MATCH 50 +#define TK_NO 51 +#define TK_KEY 52 +#define TK_OF 53 +#define TK_OFFSET 54 +#define TK_PRAGMA 55 +#define TK_RAISE 56 +#define TK_RECURSIVE 57 +#define TK_REPLACE 58 +#define TK_RESTRICT 59 +#define TK_ROW 60 +#define TK_TRIGGER 61 +#define TK_VACUUM 62 +#define TK_VIEW 63 +#define TK_VIRTUAL 64 +#define TK_WITH 65 +#define TK_REINDEX 66 +#define TK_RENAME 67 +#define TK_CTIME_KW 68 +#define TK_ANY 69 +#define TK_OR 70 +#define TK_AND 71 +#define TK_IS 72 +#define TK_BETWEEN 73 +#define TK_IN 74 +#define TK_ISNULL 75 +#define TK_NOTNULL 76 +#define TK_NE 77 +#define TK_EQ 78 +#define TK_GT 79 +#define TK_LE 80 +#define TK_LT 81 +#define TK_GE 82 +#define TK_ESCAPE 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 +#define TK_DEFAULT 100 +#define TK_NULL 101 +#define TK_PRIMARY 102 +#define TK_UNIQUE 103 +#define TK_CHECK 104 +#define TK_REFERENCES 105 +#define TK_AUTOINCR 106 +#define TK_ON 107 +#define TK_INSERT 108 +#define TK_DELETE 109 +#define TK_UPDATE 110 +#define TK_SET 111 +#define TK_DEFERRABLE 112 +#define TK_FOREIGN 113 +#define TK_DROP 114 +#define TK_UNION 115 +#define TK_ALL 116 +#define TK_EXCEPT 117 +#define TK_INTERSECT 118 +#define TK_SELECT 119 +#define TK_VALUES 120 +#define TK_DISTINCT 121 +#define TK_DOT 122 +#define TK_FROM 123 +#define TK_JOIN 124 +#define TK_USING 125 +#define TK_ORDER 126 +#define TK_GROUP 127 +#define TK_HAVING 128 +#define TK_LIMIT 129 +#define TK_WHERE 130 +#define TK_INTO 131 +#define TK_FLOAT 132 +#define TK_BLOB 133 +#define TK_INTEGER 134 +#define TK_VARIABLE 135 +#define TK_CASE 136 +#define TK_WHEN 137 +#define TK_THEN 138 +#define TK_ELSE 139 +#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_IF_NULL_ROW 160 +#define TK_ASTERISK 161 +#define TK_SPAN 162 +#define TK_SPACE 163 +#define TK_ILLEGAL 164 + +/* The token codes above must all fit in 8 bits */ +#define TKFLG_MASK 0xff + +/* Flags that can be added to a token code when it is not +** being stored in a u8: */ +#define TKFLG_DONTFOLD 0x100 /* Omit constant folding optimizations */ /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ #include #include #include #include #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 @@ -14987,12 +12580,11 @@ ** substitute integer for floating-point */ #ifdef SQLITE_OMIT_FLOATING_POINT # define double sqlite_int64 # define float sqlite_int64 -# define fabs(X) ((X)<0?-(X):(X)) -# define sqlite3IsOverflow(X) 0 +# define LONGDOUBLE_TYPE sqlite_int64 # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif # define SQLITE_OMIT_DATETIME_FUNCS 1 # define SQLITE_OMIT_TRACE 1 @@ -15065,33 +12657,17 @@ ** The default initial allocation for the pagecache when using separate ** 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 chosen to minimize the run-time of the +** 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 20 #endif -/* -** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option. -*/ -#ifndef SQLITE_DEFAULT_SORTERREF_SIZE -# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff -#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 - /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof @@ -15163,10 +12739,13 @@ # define INT8_TYPE int8_t # else # define INT8_TYPE signed char # endif #endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif typedef sqlite_int64 i64; /* 8-byte signed integer */ typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef INT16_TYPE i16; /* 2-byte signed integer */ @@ -15181,13 +12760,19 @@ */ #define SQLITE_MAX_U32 ((((u64)1)<<32)-1) /* ** The datatype used to store estimates of the number of rows in a -** table or index. +** table or index. This is an unsigned integer type. For 99.9% of +** the world, a 32-bit integer is sufficient. But a 64-bit integer +** can be used at compile-time if desired. */ -typedef u64 tRowcnt; +#ifdef SQLITE_64BIT_STATS + typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ +#else + typedef u32 tRowcnt; /* 32-bit is the default */ +#endif /* ** Estimated quantities used for query planning are stored as 16-bit ** logarithms. For quantity X, the value stored is 10*log2(X). This ** gives a possible range of values of approximately 1.0e986 to 1e-986. @@ -15209,23 +12794,19 @@ ** Examples: ** ** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 */ typedef INT16_TYPE LogEst; -#define LOGEST_MIN (-32768) -#define LOGEST_MAX (32767) /* ** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer */ #ifndef SQLITE_PTRSIZE # if defined(__SIZEOF_POINTER__) # define SQLITE_PTRSIZE __SIZEOF_POINTER__ # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ - (defined(__APPLE__) && defined(__ppc__)) || \ - (defined(__TOS_AIX__) && !defined(__64BIT__)) + defined(_M_ARM) || defined(__arm__) || defined(__x86) # define SQLITE_PTRSIZE 4 # else # define SQLITE_PTRSIZE 8 # endif #endif @@ -15246,71 +12827,30 @@ ** ** In other words, S is a buffer and E is a pointer to the first byte after ** the end of buffer S. This macro returns true if P points to something ** contained within the buffer S. */ -#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) - -/* -** P is one byte past the end of a large buffer. Return true if a span of bytes -** between S..E crosses the end of that buffer. In other words, return true -** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. -** -** S is the start of the span. E is one byte past the end of end of span. -** -** P -** |-----------------| FALSE -** |-------| -** S E -** -** P -** |-----------------| -** |-------| TRUE -** S E -** -** P -** |-----------------| -** |-------| FALSE -** S E -*/ -#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P))) +#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) + /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. ** ** For best performance, an attempt is made to guess at the byte-order ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined ** at run-time. -** -** If you are building SQLite on some obscure platform for which the -** following ifdef magic does not work, you can always include either: -** -** -DSQLITE_BYTEORDER=1234 -** -** or -** -** -DSQLITE_BYTEORDER=4321 -** -** to cause the build to work for little-endian or big-endian processors, -** respectively. */ -#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */ -# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ -# define SQLITE_BYTEORDER 4321 -# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ -# define SQLITE_BYTEORDER 1234 -# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 -# define SQLITE_BYTEORDER 4321 -# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 +#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__) +# define SQLITE_BYTEORDER 1234 +# elif defined(sparc) || defined(__ppc__) +# define SQLITE_BYTEORDER 4321 # else # define SQLITE_BYTEORDER 0 # endif #endif #if SQLITE_BYTEORDER==4321 @@ -15336,29 +12876,17 @@ ** Constants for the largest and smallest possible 64-bit signed integers. ** These macros are designed to work correctly on both 32-bit and 64-bit ** compilers. */ #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) -#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32)) #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) /* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. -** -** ROUND8() always does the rounding, for any argument. -** -** ROUND8P() assumes that the argument is already an integer number of -** pointers in size, and so it is a no-op on systems where the pointer -** size is 8. */ #define ROUND8(x) (((x)+7)&~7) -#if SQLITE_PTRSIZE==8 -# define ROUND8P(x) (x) -#else -# define ROUND8P(x) (((x)+7)&~7) -#endif /* ** Round down to the nearest multiple of 8 */ #define ROUNDDOWN8(x) ((x)&~7) @@ -15371,13 +12899,13 @@ ** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the ** underlying malloc() implementation might return us 4-byte aligned ** pointers. In that case, only verify 4-byte alignment. */ #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) #else -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) #endif /* ** Disable MMAP on platforms where it is known to not work */ @@ -15417,97 +12945,32 @@ # undef SQLITE_DEFAULT_MMAP_SIZE # define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE #endif /* -** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not -** the Abstract Syntax Tree tracing logic is turned on. -*/ -#if !defined(SQLITE_AMALGAMATION) -SQLITE_PRIVATE u32 sqlite3TreeTrace; -#endif -#if defined(SQLITE_DEBUG) \ - && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \ - || defined(SQLITE_ENABLE_TREETRACE)) -# define TREETRACE_ENABLED 1 -# define TREETRACE(K,P,S,X) \ - if(sqlite3TreeTrace&(K)) \ - sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\ - sqlite3DebugPrintf X -#else -# define TREETRACE(K,P,S,X) -# define TREETRACE_ENABLED 0 -#endif - -/* TREETRACE flag meanings: -** -** 0x00000001 Beginning and end of SELECT processing -** 0x00000002 WHERE clause processing -** 0x00000004 Query flattener -** 0x00000008 Result-set wildcard expansion -** 0x00000010 Query name resolution -** 0x00000020 Aggregate analysis -** 0x00000040 Window functions -** 0x00000080 Generated column names -** 0x00000100 Move HAVING terms into WHERE -** 0x00000200 Count-of-view optimization -** 0x00000400 Compound SELECT processing -** 0x00000800 Drop superfluous ORDER BY -** 0x00001000 LEFT JOIN simplifies to JOIN -** 0x00002000 Constant propagation -** 0x00004000 Push-down optimization -** 0x00008000 After all FROM-clause analysis -** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing -** 0x00020000 Transform DISTINCT into GROUP BY -** 0x00040000 SELECT tree dump after all code has been generated -** 0x00080000 NOT NULL strength reduction -*/ - -/* -** Macros for "wheretrace" -*/ -SQLITE_PRIVATE u32 sqlite3WhereTrace; -#if defined(SQLITE_DEBUG) \ - && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) -# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X -# define WHERETRACE_ENABLED 1 -#else -# define WHERETRACE(K,X) -#endif - -/* -** Bits for the sqlite3WhereTrace mask: -** -** (---any--) Top-level block structure -** 0x-------F High-level debug messages -** 0x----FFF- More detail -** 0xFFFF---- Low-level debug messages -** -** 0x00000001 Code generation -** 0x00000002 Solver (Use 0x40000 for less detail) -** 0x00000004 Solver costs -** 0x00000008 WhereLoop inserts -** -** 0x00000010 Display sqlite3_index_info xBestIndex calls -** 0x00000020 Range an equality scan metrics -** 0x00000040 IN operator decisions -** 0x00000080 WhereLoop cost adjustments -** 0x00000100 -** 0x00000200 Covering index decisions -** 0x00000400 OR optimization -** 0x00000800 Index scanner -** 0x00001000 More details associated with code generation -** 0x00002000 -** 0x00004000 Show all WHERE terms at key points -** 0x00008000 Show the full SELECT statement at key places -** -** 0x00010000 Show more detail when printing WHERE terms -** 0x00020000 Show WHERE terms returned from whereScanNext() -** 0x00040000 Solver overview messages -** 0x00080000 Star-query heuristic -*/ - +** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined. +** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also +** define SQLITE_ENABLE_STAT3_OR_STAT4 +*/ +#ifdef SQLITE_ENABLE_STAT4 +# undef SQLITE_ENABLE_STAT3 +# define SQLITE_ENABLE_STAT3_OR_STAT4 1 +#elif SQLITE_ENABLE_STAT3 +# define SQLITE_ENABLE_STAT3_OR_STAT4 1 +#elif SQLITE_ENABLE_STAT3_OR_STAT4 +# undef SQLITE_ENABLE_STAT3_OR_STAT4 +#endif + +/* +** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not +** the Select query generator tracing logic is turned on. +*/ +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE) +# define SELECTTRACE_ENABLED 1 +#else +# define SELECTTRACE_ENABLED 0 +#endif /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** @@ -15516,48 +12979,32 @@ ** handle is passed a pointer to sqlite.busyHandler. The busy-handler ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { - int (*xBusyHandler)(void *,int); /* The busy callback */ - void *pBusyArg; /* First arg to busy callback */ - int nBusy; /* Incremented with each busy call */ + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ }; /* -** Name of table that holds the database schema. -** -** The PREFERRED names are used wherever possible. But LEGACY is also -** used for backwards compatibility. -** -** 1. Queries can use either the PREFERRED or the LEGACY names -** 2. The sqlite3_set_authorizer() callback uses the LEGACY name -** 3. The PRAGMA table_list statement uses the PREFERRED name -** -** The LEGACY names are stored in the internal symbol hash table -** in support of (2). Names are translated using sqlite3PreferredTableName() -** for (3). The sqlite3FindTable() function takes care of translating -** names for (1). -** -** Note that "sqlite_temp_schema" can also be called "temp.sqlite_schema". -*/ -#define LEGACY_SCHEMA_TABLE "sqlite_master" -#define LEGACY_TEMP_SCHEMA_TABLE "sqlite_temp_master" -#define PREFERRED_SCHEMA_TABLE "sqlite_schema" -#define PREFERRED_TEMP_SCHEMA_TABLE "sqlite_temp_schema" - - -/* -** The root-page of the schema table. -*/ -#define SCHEMA_ROOT 1 - -/* -** The name of the schema table. The name is different for TEMP. -*/ -#define SCHEMA_TABLE(x) \ - ((!OMIT_TEMPDB)&&(x==1)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE) +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) /* ** A convenience macro that returns the number of elements in ** an array. */ @@ -15574,11 +13021,11 @@ ** one parameter that destructors normally want. So we have to introduce ** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. */ -#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear) +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize) /* ** When SQLITE_OMIT_WSD is defined, it means that the target platform does ** not support Writable Static Data (WSD) such as global and static variables. ** All variables must either be on the stack or dynamically allocated from @@ -15630,95 +13077,52 @@ typedef struct AuthContext AuthContext; typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; typedef struct CollSeq CollSeq; typedef struct Column Column; -typedef struct Cte Cte; -typedef struct CteUse CteUse; typedef struct Db Db; -typedef struct DbClientData DbClientData; -typedef struct DbFixer DbFixer; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; +typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; -typedef struct FpDecode FpDecode; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; -typedef struct IndexedExpr IndexedExpr; typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; -typedef struct OnOrUsing OnOrUsing; typedef struct Parse Parse; -typedef struct ParseCleanup ParseCleanup; typedef struct PreUpdate PreUpdate; typedef struct PrintfArguments PrintfArguments; -typedef struct RCStr RCStr; -typedef struct RenameToken RenameToken; -typedef struct Returning Returning; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; typedef struct SQLiteThread SQLiteThread; typedef struct SelectDest SelectDest; -typedef struct Subquery Subquery; -typedef struct SrcItem SrcItem; typedef struct SrcList SrcList; -typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */ +typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TreeView TreeView; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; -typedef struct Upsert Upsert; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; -typedef struct Window Window; typedef struct With With; - -/* -** The bitmask datatype defined below is used for various optimizations. -** -** Changing this from a 64-bit to a 32-bit type limits the number of -** tables in a join to 32 instead of 64. But it also reduces the size -** of the library by 738 bytes on ix86. -*/ -#ifdef SQLITE_BITMASK_TYPE - typedef SQLITE_BITMASK_TYPE Bitmask; -#else - typedef u64 Bitmask; -#endif - -/* -** The number of bits in a Bitmask. "BMS" means "BitMask Size". -*/ -#define BMS ((int)(sizeof(Bitmask)*8)) - -/* -** A bit in a Bitmask -*/ -#define MASKBIT(n) (((Bitmask)1)<<(n)) -#define MASKBIT64(n) (((u64)1)<<(n)) -#define MASKBIT32(n) (((unsigned int)1)<<(n)) -#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0) -#define ALLBITS ((Bitmask)-1) -#define TOPBIT (((Bitmask)1)<<(BMS-1)) - /* A VList object records a mapping between parameters/variables/wildcards ** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer ** 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. @@ -15728,603 +13132,10 @@ /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque ** pointer types (i.e. FuncDef) defined above. */ -/************** Include os.h in the middle of sqliteInt.h ********************/ -/************** Begin file os.h **********************************************/ -/* -** 2001 September 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file (together with is companion C source-code file -** "os.c") attempt to abstract the underlying operating system so that -** the SQLite library will work on both POSIX and windows systems. -** -** This header file is #include-ed by sqliteInt.h and thus ends up -** being included by every source file. -*/ -#ifndef _SQLITE_OS_H_ -#define _SQLITE_OS_H_ - -/* -** Attempt to automatically detect the operating system and setup the -** necessary pre-processor macros for it. -*/ -/************** Include os_setup.h in the middle of os.h *********************/ -/************** Begin file os_setup.h ****************************************/ -/* -** 2013 November 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains pre-processor directives related to operating system -** detection and/or setup. -*/ -#ifndef SQLITE_OS_SETUP_H -#define SQLITE_OS_SETUP_H - -/* -** Figure out if we are dealing with Unix, Windows, or some other operating -** system. -** -** After the following block of preprocess macros, all of -** -** SQLITE_OS_KV -** SQLITE_OS_OTHER -** SQLITE_OS_UNIX -** SQLITE_OS_WIN -** -** will defined to either 1 or 0. One of them will be 1. The others will be 0. -** If none of the macros are initially defined, then select either -** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform. -** -** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application -** must provide its own VFS implementation together with sqlite3_os_init() -** and sqlite3_os_end() routines. -*/ -#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \ - !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN) -# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ - defined(__MINGW32__) || defined(__BORLANDC__) -# define SQLITE_OS_WIN 1 -# define SQLITE_OS_UNIX 0 -# else -# define SQLITE_OS_WIN 0 -# define SQLITE_OS_UNIX 1 -# endif -#endif -#if SQLITE_OS_OTHER+1>1 -# undef SQLITE_OS_KV -# define SQLITE_OS_KV 0 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -#endif -#if SQLITE_OS_KV+1>1 -# undef SQLITE_OS_OTHER -# define SQLITE_OS_OTHER 0 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -# define SQLITE_OMIT_LOAD_EXTENSION 1 -# define SQLITE_OMIT_WAL 1 -# define SQLITE_OMIT_DEPRECATED 1 -# undef SQLITE_TEMP_STORE -# define SQLITE_TEMP_STORE 3 /* Always use memory for temporary storage */ -# define SQLITE_DQS 0 -# define SQLITE_OMIT_SHARED_CACHE 1 -# define SQLITE_OMIT_AUTOINIT 1 -#endif -#if SQLITE_OS_UNIX+1>1 -# undef SQLITE_OS_KV -# define SQLITE_OS_KV 0 -# undef SQLITE_OS_OTHER -# define SQLITE_OS_OTHER 0 -# undef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -#endif -#if SQLITE_OS_WIN+1>1 -# undef SQLITE_OS_KV -# define SQLITE_OS_KV 0 -# undef SQLITE_OS_OTHER -# define SQLITE_OS_OTHER 0 -# undef SQLITE_OS_UNIX -# define SQLITE_OS_UNIX 0 -#endif - - -#endif /* SQLITE_OS_SETUP_H */ - -/************** End of os_setup.h ********************************************/ -/************** Continuing where we left off in os.h *************************/ - -/* If the SET_FULLSYNC macro is not defined above, then make it -** a no-op -*/ -#ifndef SET_FULLSYNC -# define SET_FULLSYNC(x,y) -#endif - -/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h -*/ -#ifndef SQLITE_MAX_PATHLEN -# define SQLITE_MAX_PATHLEN FILENAME_MAX -#endif - -/* Maximum number of symlinks that will be resolved while trying to -** expand a filename in xFullPathname() in the VFS. -*/ -#ifndef SQLITE_MAX_SYMLINK -# define SQLITE_MAX_SYMLINK 200 -#endif - -/* -** The default size of a disk sector -*/ -#ifndef SQLITE_DEFAULT_SECTOR_SIZE -# define SQLITE_DEFAULT_SECTOR_SIZE 4096 -#endif - -/* -** Temporary files are named starting with this prefix followed by 16 random -** alphanumeric characters, and no file extension. They are stored in the -** OS's standard temporary file directory, and are deleted prior to exit. -** If sqlite is being embedded in another program, you may wish to change the -** prefix to reflect your program's name, so that if your program exits -** prematurely, old temporary files can be easily identified. This can be done -** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. -** -** 2006-10-31: The default prefix used to be "sqlite_". But then -** Mcafee started using SQLite in their anti-virus product and it -** started putting files with the "sqlite" name in the c:/temp folder. -** This annoyed many windows users. Those users would then do a -** Google search for "sqlite", find the telephone numbers of the -** developers and call to wake them up at night and complain. -** For this reason, the default name prefix is changed to be "sqlite" -** spelled backwards. So the temp files are still identified, but -** anybody smart enough to figure out the code is also likely smart -** enough to know that calling the developer will not help get rid -** of the file. -*/ -#ifndef SQLITE_TEMP_FILE_PREFIX -# define SQLITE_TEMP_FILE_PREFIX "etilqs_" -#endif - -/* -** The following values may be passed as the second argument to -** sqlite3OsLock(). The various locks exhibit the following semantics: -** -** SHARED: Any number of processes may hold a SHARED lock simultaneously. -** RESERVED: A single process may hold a RESERVED lock on a file at -** any time. Other processes may hold and obtain new SHARED locks. -** PENDING: A single process may hold a PENDING lock on a file at -** any one time. Existing SHARED locks may persist, but no new -** SHARED locks may be obtained by other processes. -** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. -** -** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a -** process that requests an EXCLUSIVE lock may actually obtain a PENDING -** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to -** sqlite3OsLock(). -*/ -#define NO_LOCK 0 -#define SHARED_LOCK 1 -#define RESERVED_LOCK 2 -#define PENDING_LOCK 3 -#define EXCLUSIVE_LOCK 4 - -/* -** File Locking Notes: (Mostly about windows but also some info for Unix) -** -** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because -** those functions are not available. So we use only LockFile() and -** UnlockFile(). -** -** LockFile() prevents not just writing but also reading by other processes. -** A SHARED_LOCK is obtained by locking a single randomly-chosen -** byte out of a specific range of bytes. The lock byte is obtained at -** random so two separate readers can probably access the file at the -** same time, unless they are unlucky and choose the same lock byte. -** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. -** There can only be one writer. A RESERVED_LOCK is obtained by locking -** a single byte of the file that is designated as the reserved lock byte. -** A PENDING_LOCK is obtained by locking a designated byte different from -** the RESERVED_LOCK byte. -** -** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, -** which means we can use reader/writer locks. When reader/writer locks -** are used, the lock is placed on the same range of bytes that is used -** for probabilistic locking in Win95/98/ME. Hence, the locking scheme -** will support two or more Win95 readers or two or more WinNT readers. -** But a single Win95 reader will lock out all WinNT readers and a single -** WinNT reader will lock out all other Win95 readers. -** -** The following #defines specify the range of bytes used for locking. -** SHARED_SIZE is the number of bytes available in the pool from which -** a random byte is selected for a shared lock. The pool of bytes for -** shared locks begins at SHARED_FIRST. -** -** The same locking strategy and -** byte ranges are used for Unix. This leaves open the possibility of having -** clients on win95, winNT, and unix all talking to the same shared file -** and all locking correctly. To do so would require that samba (or whatever -** tool is being used for file sharing) implements locks correctly between -** windows and unix. I'm guessing that isn't likely to happen, but by -** using the same locking range we are at least open to the possibility. -** -** Locking in windows is manditory. For this reason, we cannot store -** actual data in the bytes used for locking. The pager never allocates -** the pages involved in locking therefore. SHARED_SIZE is selected so -** that all locks will fit on a single page even at the minimum page size. -** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE -** is set high so that we don't have to allocate an unused page except -** for very large databases. But one should test the page skipping logic -** by setting PENDING_BYTE low and running the entire regression suite. -** -** Changing the value of PENDING_BYTE results in a subtly incompatible -** file format. Depending on how it is changed, you might not notice -** the incompatibility right away, even running a full regression test. -** The default location of PENDING_BYTE is the first byte past the -** 1GB boundary. -** -*/ -#ifdef SQLITE_OMIT_WSD -# define PENDING_BYTE (0x40000000) -#else -# define PENDING_BYTE sqlite3PendingByte -#endif -#define RESERVED_BYTE (PENDING_BYTE+1) -#define SHARED_FIRST (PENDING_BYTE+2) -#define SHARED_SIZE 510 - -/* -** Wrapper around OS specific sqlite3_os_init() function. -*/ -SQLITE_PRIVATE int sqlite3OsInit(void); - -/* -** Functions for accessing sqlite3_file methods -*/ -SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*); -SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); -SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); -SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); -SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); -SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); -SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); -SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); -SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); -SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); -SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*); -#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 -SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); -SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); -SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); -SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); -SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); -#endif /* SQLITE_OMIT_WAL */ -SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); -SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); - - -/* -** Functions for accessing sqlite3_vfs methods -*/ -SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); -SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); -SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); -SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); -#ifndef SQLITE_OMIT_LOAD_EXTENSION -SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); -SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); -SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); -SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ -SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); -SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); -SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*); -SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); - -/* -** Convenience functions for opening and closing files using -** sqlite3_malloc() to obtain space for the file-handle structure. -*/ -SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); -SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *); - -#endif /* _SQLITE_OS_H_ */ - -/************** End of os.h **************************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ -/************** Include pager.h in the middle of sqliteInt.h *****************/ -/************** Begin file pager.h *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the sqlite page cache -** subsystem. The page cache subsystem reads and writes a file a page -** at a time and provides a journal for rollback. -*/ - -#ifndef SQLITE_PAGER_H -#define SQLITE_PAGER_H - -/* -** Default maximum size for persistent journal files. A negative -** value means no limit. This value may be overridden using the -** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". -*/ -#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT - #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 -#endif - -/* -** The type used to represent a page number. The first page in a file -** is called page 1. 0 is used to represent "not a page". -*/ -typedef u32 Pgno; - -/* -** Each open file is managed by a separate instance of the "Pager" structure. -*/ -typedef struct Pager Pager; - -/* -** Handle type for pages. -*/ -typedef struct PgHdr DbPage; - -/* -** Page number PAGER_SJ_PGNO is never used in an SQLite database (it is -** reserved for working around a windows/posix incompatibility). It is -** used in the journal to signify that the remainder of the journal file -** is devoted to storing a super-journal name - there are no more pages to -** roll back. See comments for function writeSuperJournal() in pager.c -** for details. -*/ -#define PAGER_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) -#define PAGER_SJ_PGNO(x) ((x)->lckPgno) - -/* -** Allowed values for the flags parameter to sqlite3PagerOpen(). -** -** NOTE: These values must match the corresponding BTREE_ values in btree.h. -*/ -#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ -#define PAGER_MEMORY 0x0002 /* In-memory database */ - -/* -** Valid values for the second argument to sqlite3PagerLockingMode(). -*/ -#define PAGER_LOCKINGMODE_QUERY -1 -#define PAGER_LOCKINGMODE_NORMAL 0 -#define PAGER_LOCKINGMODE_EXCLUSIVE 1 - -/* -** Numeric constants that encode the journalmode. -** -** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY) -** are exposed in the API via the "PRAGMA journal_mode" command and -** therefore cannot be changed without a compatibility break. -*/ -#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ -#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ -#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ -#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ -#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ -#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ -#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ - -#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL) - -/* -** The argument to this macro is a file descriptor (type sqlite3_file*). -** Return 0 if it is not open, or non-zero (but not 1) if it is. -** -** This is so that expressions can be written as: -** -** if( isOpen(pPager->jfd) ){ ... -** -** instead of -** -** if( pPager->jfd->pMethods ){ ... -*/ -#define isOpen(pFd) ((pFd)->pMethods!=0) - -/* -** Flags that make up the mask passed to sqlite3PagerGet(). -*/ -#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ -#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ - -/* -** Flags for sqlite3PagerSetFlags() -** -** Value constraints (enforced via assert()): -** PAGER_FULLFSYNC == SQLITE_FullFSync -** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync -** PAGER_CACHE_SPILL == SQLITE_CacheSpill -*/ -#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ -#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ -#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ -#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */ -#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */ -#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */ -#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */ -#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */ -#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */ - -/* -** The remainder of this file contains the declarations of the functions -** that make up the Pager sub-system API. See source code comments for -** a detailed description of each routine. -*/ - -/* Open and close a Pager connection. */ -SQLITE_PRIVATE int sqlite3PagerOpen( - sqlite3_vfs*, - Pager **ppPager, - const char*, - int, - int, - int, - void(*)(DbPage*) -); -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); -SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); - -/* Functions used to configure a Pager object. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); -SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager*, Pgno); -SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); -SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int); -SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); -SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); -SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned); -SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); -SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); -SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); -SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); -SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); -SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); -SQLITE_PRIVATE int sqlite3PagerFlush(Pager*); - -/* Functions used to obtain and release page references. */ -SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); -SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); -SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); -SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); -SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); -SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*); - -/* Operations on page references. */ -SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); -SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); -SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); -SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); -SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); -SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); - -/* Functions used to manage pager transactions and savepoints. */ -SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); -SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); -SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zSuper, int); -SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper); -SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); -SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); -SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); -SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); -SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); - -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); -SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); -SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); -SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); -# ifdef SQLITE_ENABLE_SNAPSHOT -SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot); -SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); -SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager); -# endif -#endif - -#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT) -SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int); -SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*); -#else -# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK -# define sqlite3PagerWalDb(x,y) -#endif - -#ifdef SQLITE_DIRECT_OVERFLOW_READ -SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); -#endif - -#ifdef SQLITE_ENABLE_ZIPVFS -SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); -#endif - -/* Functions used to query pager state and configuration. */ -SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); -SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); -#endif -SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); -SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager*, int); -SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*); -SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); -SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*); -SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); -SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); -SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*); -SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); -SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); - -/* Functions used to truncate the database file. */ -SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); - -SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16); - -/* Functions to support testing and debugging. */ -#if !defined(NDEBUG) || defined(SQLITE_TEST) -SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); -SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); -#endif -#ifdef SQLITE_TEST -SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); -SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); - void disable_simulated_io_errors(void); - void enable_simulated_io_errors(void); -#else -# define disable_simulated_io_errors() -# define enable_simulated_io_errors() -#endif - -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) -SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*); -#endif - -#endif /* SQLITE_PAGER_H */ - -/************** End of pager.h ***********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ /************** Include btree.h in the middle of sqliteInt.h *****************/ /************** Begin file btree.h *******************************************/ /* ** 2001 September 15 ** @@ -16396,42 +13207,34 @@ SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); #endif SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); -SQLITE_PRIVATE Pgno sqlite3BtreeMaxPageCount(Btree*,Pgno); -SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree*); +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); +SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree*); +SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*); SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*); -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char*); +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int); SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags); -SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*); +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); - SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); #ifndef SQLITE_OMIT_SHARED_CACHE SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); #endif - -/* Savepoints are named, nestable SQL transactions mostly implemented */ -/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); -/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */ -#ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); -#endif - SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); @@ -16448,11 +13251,11 @@ */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ #define BTREE_BLOBKEY 2 /* Table has keys only - no data */ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); -SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*); +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); @@ -16459,11 +13262,11 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta -** should be one of the following values. The integer values are assigned +** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** ** offset = 36 + (idx * 4) ** @@ -16508,11 +13311,11 @@ ** to prefetch content from remote machines - to provide those ** implementations with limits on what needs to be prefetched and thereby ** reduce network bandwidth. ** ** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by -** standard SQLite. The other hints are provided for extensions that use +** standard SQLite. The other hints are provided for extentions that use ** the SQLite parser and code generator but substitute their own storage ** engine. */ #define BTREE_HINT_RANGE 0 /* Range constraints on queries */ @@ -16530,11 +13333,11 @@ ** */ #define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */ #define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */ -/* +/* ** Flags passed as the third argument to sqlite3BtreeCursor(). ** ** For read-only cursors the wrFlag argument is always zero. For read-write ** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just ** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will @@ -16558,85 +13361,61 @@ #define BTREE_WRCSR 0x00000004 /* read-write cursor */ #define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */ SQLITE_PRIVATE int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ - Pgno iTable, /* Index of root page */ + int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); -SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void); SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*); -#endif SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...); #endif SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeTableMoveto( +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( BtCursor*, + UnpackedRecord *pUnKey, i64 intKey, int bias, int *pRes ); -SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( - BtCursor*, - UnpackedRecord *pUnKey, - int *pRes -); SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); /* 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 */ -#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */ /* An instance of the BtreePayload object describes the content of a single ** entry in either an index or table btree. ** ** Index btrees (used for indexes and also WITHOUT ROWID tables) contain -** an arbitrary key and no data. These btrees have pKey,nKey set to the -** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem -** fields give an array of Mem objects that are a decomposition of the key. -** The nMem field might be zero, indicating that no decomposition is available. +** an arbitrary key and no data. These btrees have pKey,nKey set to their +** key and pData,nData,nZero set to zero. ** ** Table btrees (used for rowid tables) contain an integer rowid used as -** the key and passed in the nKey field. The pKey field is zero. +** the key and passed in the nKey field. The pKey field is zero. ** pData,nData hold the content of the new entry. nZero extra zero bytes ** are appended to the end of the content when constructing the entry. -** The aMem,nMem fields are uninitialized for table btrees. -** -** Field usage summary: -** -** Table BTrees Index Btrees -** -** pKey always NULL encoded key -** nKey the ROWID length of pKey -** pData data not used -** aMem not used decomposed key value -** nMem not used entries in aMem -** nData length of pData not used -** nZero extra zeros after pData not used ** ** This object is used to pass information into sqlite3BtreeInsert(). The ** same information used to be passed as five separate parameters. But placing -** the information into this object helps to keep the interface more +** the information into this object helps to keep the interface more ** organized and understandable, and it also helps the resulting code to ** run a little faster by using fewer registers for parameter passing. */ 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. */ + 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 */ }; @@ -16647,28 +13426,15 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*); -SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*); - -SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( - sqlite3 *db, /* Database connection that is running the check */ - Btree *p, /* The btree to be checked */ - Pgno *aRoot, /* An array of root pages numbers for individual trees */ - sqlite3_value *aCnt, /* OUT: entry counts for each btree in aRoot[] */ - int nRoot, /* Number of entries in aRoot[] */ - int mxErr, /* Stop reporting errors after this many */ - int *pnErr, /* OUT: Write number of errors seen to this variable */ - char **pzOut /* OUT: Write the error message string here */ -); + +SQLITE_PRIVATE 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*); @@ -16679,22 +13445,18 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt); SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree*); -#else -# define sqlite3BtreeSeekCount(X) 0 -#endif - #ifndef NDEBUG SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); #endif SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*); +#ifndef SQLITE_OMIT_BTREECOUNT +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); +#endif #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); #endif @@ -16701,14 +13463,10 @@ #ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); #endif -SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64); - -SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree*); - /* ** If we are not using shared cache, then there is no need to ** use mutexes to access the BtShared structures. So make the ** Enter and Leave procedures no-ops. */ @@ -16717,11 +13475,11 @@ SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree*); #else -# define sqlite3BtreeEnter(X) +# define sqlite3BtreeEnter(X) # define sqlite3BtreeEnterAll(X) # define sqlite3BtreeSharable(X) 0 # define sqlite3BtreeEnterCursor(X) # define sqlite3BtreeConnectionCount(X) 1 #endif @@ -16786,24 +13544,10 @@ ** The names of the following types declared in vdbeInt.h are required ** for the VdbeOp definition. */ typedef struct sqlite3_value Mem; typedef struct SubProgram SubProgram; -typedef struct SubrtnSig SubrtnSig; - -/* -** A signature for a reusable subroutine that materializes the RHS of -** an IN operator. -*/ -struct SubrtnSig { - int selId; /* SELECT-id for the SELECT statement on the RHS */ - u8 bComplete; /* True if fully coded and available for reusable */ - char *zAff; /* Affinity of the overall IN expression */ - int iTable; /* Ephemeral table generated by the subroutine */ - int iAddr; /* Subroutine entry address */ - int regReturn; /* Register used to hold return address */ -}; /* ** A single instruction of the virtual machine has an opcode ** and as many as three operands. The instruction is recorded ** as an instance of the following structure: @@ -16825,28 +13569,27 @@ sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ - u32 *ai; /* Used when p4type is P4_INTARRAY */ + int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ Table *pTab; /* Used when p4type is P4_TABLE */ - SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */ #ifdef SQLITE_ENABLE_CURSOR_HINTS Expr *pExpr; /* Used when p4type is P4_EXPR */ #endif + int (*xAdvance)(BtCursor *, int); } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS char *zComment; /* Comment to improve readability */ #endif +#ifdef VDBE_PROFILE + u32 cnt; /* Number of times this instruction was executed */ + u64 cycles; /* Total time spent executing this instruction */ +#endif #ifdef SQLITE_VDBE_COVERAGE - u32 iSrcLine; /* Source-code line that generated this opcode - ** with flags in the upper 8 bits */ -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - u64 nExec; - u64 nCycle; + int iSrcLine; /* Source-code line that generated this opcode */ #endif }; typedef struct VdbeOp VdbeOp; @@ -16882,34 +13625,33 @@ #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_TABLE (-5) /* P4 is a pointer to a Table 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 (-6) -#define P4_DYNAMIC (-6) /* Pointer to memory from sqliteMalloc() */ -#define P4_FUNCDEF (-7) /* P4 is a pointer to a FuncDef structure */ -#define P4_KEYINFO (-8) /* P4 is a pointer to a KeyInfo structure */ -#define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */ -#define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */ -#define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */ -#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_INTARRAY (-14) /* P4 is a vector of 32-bit integers */ -#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */ -#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */ -#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */ +#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 */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 #define P5_ConstraintUnique 2 #define P5_ConstraintCheck 3 #define P5_ConstraintFK 4 /* -** The Vdbe.aColName array contains 5n Mem structures, where n is the +** The Vdbe.aColName array contains 5n Mem structures, where n is the ** number of columns of data returned by the statement. */ #define COLNAME_NAME 0 #define COLNAME_DECLTYPE 1 #define COLNAME_DATABASE 2 @@ -16924,15 +13666,16 @@ # define COLNAME_N 2 /* Store the name and decltype */ # endif #endif /* -** The following macro converts a label returned by sqlite3VdbeMakeLabel() -** into an index into the Parse.aLabel[] array that contains the resolved -** address of that label. +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that +** sqlite3VdbeAddOpList() knows that the address is relative. Calling +** the macro again restores the address. */ -#define ADDR(X) (~(X)) +#define ADDR(X) (-1-(X)) /* ** The makefile scans the vdbe.c source file and creates the "opcodes.h" ** header file that defines a number for each opcode used by the VDBE. */ @@ -16941,197 +13684,173 @@ /* Automatically generated. Do not edit */ /* See the tool/mkopcodeh.tcl script for details */ #define OP_Savepoint 0 #define OP_AutoCommit 1 #define OP_Transaction 2 -#define OP_Checkpoint 3 -#define OP_JournalMode 4 -#define OP_Vacuum 5 -#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */ -#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */ -#define OP_Init 8 /* jump0, synopsis: Start at P2 */ -#define OP_Goto 9 /* jump */ -#define OP_Gosub 10 /* jump */ -#define OP_InitCoroutine 11 /* jump0 */ -#define OP_Yield 12 /* jump0 */ -#define OP_MustBeInt 13 /* jump0 */ -#define OP_Jump 14 /* jump */ -#define OP_Once 15 /* jump */ -#define OP_If 16 /* jump */ -#define OP_IfNot 17 /* jump */ -#define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */ +#define OP_SorterNext 3 +#define OP_PrevIfOpen 4 +#define OP_NextIfOpen 5 +#define OP_Prev 6 +#define OP_Next 7 +#define OP_Checkpoint 8 +#define OP_JournalMode 9 +#define OP_Vacuum 10 +#define OP_VFilter 11 /* 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_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ -#define OP_SeekLT 21 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_SeekLE 22 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_SeekGE 23 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_SeekGT 24 /* jump0, synopsis: key=r[P3@P4] */ -#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */ -#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */ -#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */ -#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */ -#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekRowid 30 /* jump0, synopsis: intkey=r[P3] */ -#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */ -#define OP_Last 32 /* jump0 */ -#define OP_IfSizeBetween 33 /* jump */ -#define OP_SorterSort 34 /* jump */ -#define OP_Sort 35 /* jump */ -#define OP_Rewind 36 /* jump0 */ -#define OP_SorterNext 37 /* jump */ -#define OP_Prev 38 /* jump */ -#define OP_Next 39 /* jump */ -#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IdxLT 42 /* jump, synopsis: key=r[P3@P4] */ -#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ -#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */ -#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 48 /* jump0 */ -#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ -#define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ -#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ -#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ -#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ -#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ -#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ -#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */ -#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */ -#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ -#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IncrVacuum 62 /* jump */ -#define OP_VNext 63 /* jump */ -#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */ -#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */ -#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */ -#define OP_Return 67 -#define OP_EndCoroutine 68 -#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 70 -#define OP_Integer 71 /* synopsis: r[P2]=P1 */ -#define OP_Int64 72 /* synopsis: r[P2]=P4 */ -#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */ -#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */ -#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1) */ -#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */ -#define OP_FkCheck 83 -#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 85 -#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_RealAffinity 87 -#define OP_Cast 88 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 89 -#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ -#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */ -#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */ -#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */ -#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */ -#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 98 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 99 -#define OP_SetCookie 100 -#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */ -#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenDup 114 -#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ -#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */ -#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_SorterOpen 119 -#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 122 -#define OP_ColumnsUsed 123 -#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */ -#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */ -#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */ -#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_RowCell 129 -#define OP_Delete 130 -#define OP_ResetCount 131 -#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 133 /* synopsis: r[P2]=data */ -#define OP_RowData 134 /* synopsis: r[P2]=data */ -#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */ -#define OP_NullRow 136 -#define OP_SeekEnd 137 -#define OP_IdxInsert 138 /* synopsis: key=r[P2] */ -#define OP_SorterInsert 139 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */ -#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */ -#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */ -#define OP_FinishSeek 143 -#define OP_Destroy 144 -#define OP_Clear 145 -#define OP_ResetSorter 146 -#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ -#define OP_SqlExec 148 -#define OP_ParseSchema 149 -#define OP_LoadAnalysis 150 -#define OP_DropTable 151 -#define OP_DropIndex 152 -#define OP_DropTrigger 153 -#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_IntegrityCk 155 -#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */ -#define OP_Param 157 -#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */ -#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ -#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */ -#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 166 -#define OP_CursorLock 167 -#define OP_CursorUnlock 168 -#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 170 -#define OP_VCreate 171 -#define OP_VDestroy 172 -#define OP_VOpen 173 -#define OP_VCheck 174 -#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */ -#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 177 -#define OP_Pagecount 178 -#define OP_MaxPgcnt 179 -#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */ -#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */ -#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */ -#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */ -#define OP_Trace 184 -#define OP_CursorHint 185 -#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */ -#define OP_Noop 187 -#define OP_Explain 188 -#define OP_Abortable 189 +#define OP_Once 20 +#define OP_If 21 +#define OP_IfNot 22 +#define OP_IfNullRow 23 /* synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ +#define OP_SeekLT 24 /* synopsis: key=r[P3@P4] */ +#define OP_SeekLE 25 /* synopsis: key=r[P3@P4] */ +#define OP_SeekGE 26 /* synopsis: key=r[P3@P4] */ +#define OP_SeekGT 27 /* synopsis: key=r[P3@P4] */ +#define OP_NoConflict 28 /* synopsis: key=r[P3@P4] */ +#define OP_NotFound 29 /* synopsis: key=r[P3@P4] */ +#define OP_Found 30 /* synopsis: key=r[P3@P4] */ +#define OP_SeekRowid 31 /* synopsis: intkey=r[P3] */ +#define OP_NotExists 32 /* synopsis: intkey=r[P3] */ +#define OP_Last 33 +#define OP_IfSmaller 34 +#define OP_SorterSort 35 +#define OP_Sort 36 +#define OP_Rewind 37 +#define OP_IdxLE 38 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGT 39 /* synopsis: key=r[P3@P4] */ +#define OP_IdxLT 40 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGE 41 /* synopsis: key=r[P3@P4] */ +#define OP_RowSetRead 42 /* synopsis: r[P3]=rowset(P1) */ +#define OP_RowSetTest 43 /* synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 44 +#define OP_FkIfZero 45 /* synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_IfPos 46 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ +#define OP_IfNotZero 47 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ +#define OP_DecrJumpZero 48 /* synopsis: if (--r[P1])==0 goto P2 */ +#define OP_IncrVacuum 49 +#define OP_VNext 50 +#define OP_Init 51 /* synopsis: Start at P2 */ +#define OP_Return 52 +#define OP_EndCoroutine 53 +#define OP_HaltIfNull 54 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 55 +#define OP_Integer 56 /* synopsis: r[P2]=P1 */ +#define OP_Int64 57 /* synopsis: r[P2]=P4 */ +#define OP_String 58 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 59 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 60 /* synopsis: r[P1]=NULL */ +#define OP_Blob 61 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 62 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 63 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 64 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 65 /* synopsis: r[P2]=r[P1] */ +#define OP_IntCopy 66 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 67 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 68 +#define OP_Function0 69 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Or 70 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ +#define OP_And 71 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ +#define OP_Function 72 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_AddImm 73 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_RealAffinity 74 +#define OP_IsNull 75 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ +#define OP_NotNull 76 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ +#define OP_Ne 77 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */ +#define OP_Eq 78 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */ +#define OP_Gt 79 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */ +#define OP_Le 80 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */ +#define OP_Lt 81 /* same as TK_LT, synopsis: IF r[P3]=r[P1] */ +#define OP_ElseNotEq 83 /* same as TK_ESCAPE */ +#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_Cast 94 /* synopsis: affinity(r[P1]) */ +#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +#define OP_Permutation 96 +#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ +#define OP_Compare 98 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_Column 99 /* synopsis: r[P3]=PX */ +#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 102 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 103 +#define OP_SetCookie 104 +#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenDup 108 +#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 111 +#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 114 +#define OP_ColumnsUsed 115 +#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */ +#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 120 +#define OP_ResetCount 121 +#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 123 /* synopsis: r[P2]=data */ +#define OP_RowData 124 /* synopsis: r[P2]=data */ +#define OP_Rowid 125 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 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_Destroy 133 +#define OP_Clear 134 +#define OP_ResetSorter 135 +#define OP_CreateIndex 136 /* synopsis: r[P2]=root iDb=P1 */ +#define OP_CreateTable 137 /* synopsis: r[P2]=root iDb=P1 */ +#define OP_SqlExec 138 +#define OP_ParseSchema 139 +#define OP_LoadAnalysis 140 +#define OP_DropTable 141 +#define OP_DropIndex 142 +#define OP_DropTrigger 143 +#define OP_IntegrityCk 144 +#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 146 +#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 153 +#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 155 +#define OP_VCreate 156 +#define OP_VDestroy 157 +#define OP_VOpen 158 +#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 160 +#define OP_Pagecount 161 +#define OP_MaxPgcnt 162 +#define OP_CursorHint 163 +#define OP_Noop 164 +#define OP_Explain 165 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c ** are encoded into bitvectors as follows: */ @@ -17139,61 +13858,55 @@ #define OPFLG_IN1 0x02 /* in1: P1 is an input */ #define OPFLG_IN2 0x04 /* in2: P2 is an input */ #define OPFLG_IN3 0x08 /* in3: P3 is an input */ #define OPFLG_OUT2 0x10 /* out2: P2 is an output */ #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ -#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */ -#define OPFLG_JUMP0 0x80 /* jump0: P2 might be zero */ #define OPFLG_INITIALIZER {\ -/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\ -/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\ -/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\ -/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\ -/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\ -/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\ -/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ -/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\ -/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\ -/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\ -/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\ -/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\ -/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\ -/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ -/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\ -/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\ -/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\ -/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\ -/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\ -/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\ -/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\ -/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} - -/* The resolve3P2Values() routine is able to run faster if it knows +/* 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, 0x01,\ +/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\ +/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ +/* 40 */ 0x01, 0x01, 0x23, 0x0b, 0x01, 0x01, 0x03, 0x03,\ +/* 48 */ 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x00,\ +/* 56 */ 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00,\ +/* 64 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x26, 0x26,\ +/* 72 */ 0x00, 0x02, 0x02, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ +/* 80 */ 0x0b, 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26,\ +/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x02, 0x12,\ +/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ +/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04,\ +/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\ +/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\ +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,} + +/* The sqlite3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum ** JUMP opcode the better, so the mkopcodeh.tcl script that ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ -#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */ +#define SQLITE_MX_JUMP_OPCODE 83 /* 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 0x1f /* Mask of public flags */ +#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. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*); -SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe*,int,const char*); @@ -17200,77 +13913,38 @@ SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...); SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); -SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int); SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int); #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); #else # define sqlite3VdbeVerifyNoMallocRequired(A,B) # define sqlite3VdbeVerifyNoResultRow(A) #endif -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); -SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int); -#else -# define sqlite3VdbeVerifyAbortable(A,B) -# define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D) -#endif -SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); -#ifndef SQLITE_OMIT_EXPLAIN -SQLITE_PRIVATE int sqlite3VdbeExplain(Parse*,u8,const char*,...); -SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); -SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); -# define ExplainQueryPlan(P) sqlite3VdbeExplain P -# ifdef SQLITE_ENABLE_STMT_SCANSTATUS -# define ExplainQueryPlan2(V,P) (V = sqlite3VdbeExplain P) -# else -# define ExplainQueryPlan2(V,P) ExplainQueryPlan(P) -# endif -# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) -# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) -#else -# define ExplainQueryPlan(P) -# define ExplainQueryPlan2(V,P) -# define ExplainQueryPlanPop(P) -# define ExplainQueryPlanParent(P) 0 -# define sqlite3ExplainBreakpoint(A,B) /*no-op*/ -#endif -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) -SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*); -#else -# define sqlite3ExplainBreakpoint(A,B) /*no-op*/ -#endif -SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16); -SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8); -SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); -SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); -SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); +SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5); -SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe*, int); SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); -SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr); SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr); SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int); -#else -# define sqlite3VdbeReleaseRegisters(P,A,N,M,F) -#endif SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type); SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); -SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*); +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG @@ -17283,40 +13957,29 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*); -SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*); -#endif SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8); SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); -SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*); 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*); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); +#ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); -SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*); - -SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val); - -SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*); -#ifdef SQLITE_ENABLE_BYTECODE_VTAB -SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*); #endif /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on ** each VDBE opcode. ** @@ -17342,11 +14005,11 @@ /* ** The VdbeCoverage macros are used to set a coverage testing point ** for VDBE branch instructions. The coverage testing points are line ** numbers in the sqlite3.c source file. VDBE branch coverage testing -** only works with an amalgamation build. That's ok since a VDBE branch +** only works with an amalagmation build. That's ok since a VDBE branch ** coverage build designed for testing the test suite only. No application ** should ever ship with VDBE branch coverage measuring turned on. ** ** VdbeCoverage(v) // Mark the previously coded instruction ** // as a branch @@ -17355,80 +14018,283 @@ ** ** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken ** ** VdbeCoverageNeverTaken(v) // Previous branch is never taken ** -** VdbeCoverageNeverNull(v) // Previous three-way branch is only -** // taken on the first two ways. The -** // NULL option is not possible -** -** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested -** // in distinguishing equal and not-equal. -** ** Every VDBE branch operation must be tagged with one of the macros above. ** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and ** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() ** routine in vdbe.c, alerting the developer to the missed tag. -** -** During testing, the test application will invoke -** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback -** routine that is invoked as each bytecode branch is taken. The callback -** contains the sqlite3.c source line number of the VdbeCoverage macro and -** flags to indicate whether or not the branch was taken. The test application -** is responsible for keeping track of this and reporting byte-code branches -** that are never taken. -** -** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the -** vdbe.c source file for additional information. */ #ifdef SQLITE_VDBE_COVERAGE SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); # define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) -# define VdbeCoverageAlwaysTaken(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000); -# define VdbeCoverageNeverTaken(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000); -# define VdbeCoverageNeverNull(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); -# define VdbeCoverageNeverNullIf(v,x) \ - if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); -# define VdbeCoverageEqNe(v) \ - sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000); +# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); # define VDBE_OFFSET_LINENO(x) (__LINE__+x) #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) -# define VdbeCoverageNeverNull(v) -# define VdbeCoverageNeverNullIf(v,x) -# define VdbeCoverageEqNe(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); -SQLITE_PRIVATE void sqlite3VdbeScanStatusRange(Vdbe*, int, int, int); -SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters(Vdbe*, int, int, int); #else -# define sqlite3VdbeScanStatus(a,b,c,d,e,f) -# define sqlite3VdbeScanStatusRange(a,b,c,d) -# define sqlite3VdbeScanStatusCounters(a,b,c,d) -#endif - -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) -SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*); -#endif - -#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr); +# define sqlite3VdbeScanStatus(a,b,c,d,e) #endif #endif /* SQLITE_VDBE_H */ /************** End of vdbe.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pager.h in the middle of sqliteInt.h *****************/ +/************** Begin file pager.h *******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** subsystem. The page cache subsystem reads and writes a file a page +** at a time and provides a journal for rollback. +*/ + +#ifndef SQLITE_PAGER_H +#define SQLITE_PAGER_H + +/* +** Default maximum size for persistent journal files. A negative +** value means no limit. This value may be overridden using the +** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef u32 Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() in pager.c +** for details. +*/ +#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: These values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_MEMORY 0x0002 /* In-memory database */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** Numeric constants that encode the journalmode. +** +** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY) +** are exposed in the API via the "PRAGMA journal_mode" command and +** therefore cannot be changed without a compatibility break. +*/ +#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ +#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ +#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ +#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ + +/* +** Flags that make up the mask passed to sqlite3PagerGet(). +*/ +#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ +#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ + +/* +** Flags for sqlite3PagerSetFlags() +** +** Value constraints (enforced via assert()): +** PAGER_FULLFSYNC == SQLITE_FullFSync +** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync +** PAGER_CACHE_SPILL == SQLITE_CacheSpill +*/ +#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ +#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ +#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ +#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */ +#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */ +#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */ +#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */ +#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */ +#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */ + +/* +** The remainder of this file contains the declarations of the functions +** that make up the Pager sub-system API. See source code comments for +** a detailed description of each routine. +*/ + +/* Open and close a Pager connection. */ +SQLITE_PRIVATE int sqlite3PagerOpen( + sqlite3_vfs*, + Pager **ppPager, + const char*, + int, + int, + int, + void(*)(DbPage*) +); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); +SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); + +/* Functions used to configure a Pager object. */ +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); +#ifdef SQLITE_HAS_CODEC +SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); +#endif +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); +SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); +SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); +SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned); +SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); +SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); +SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); +SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); +SQLITE_PRIVATE int sqlite3PagerFlush(Pager*); + +/* Functions used to obtain and release page references. */ +SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); + +/* Operations on page references. */ +SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); +SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); +SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); +SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); +SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); +SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); + +/* Functions used to manage pager transactions and savepoints. */ +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); +SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); +SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); +SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); +SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); + +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); +SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); +# ifdef SQLITE_DIRECT_OVERFLOW_READ +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno); +# endif +# ifdef SQLITE_ENABLE_SNAPSHOT +SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); +SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); +SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); +# endif +#else +# define sqlite3PagerUseWal(x,y) 0 +#endif + +#ifdef SQLITE_ENABLE_ZIPVFS +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); +#endif + +/* Functions used to query pager state and configuration. */ +SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); +#endif +SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); +SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*); +SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); +SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); +SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); +SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); +SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); +SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); + +/* Functions used to truncate the database file. */ +SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); + +SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16); + +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) +SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *); +#endif + +/* Functions to support testing and debugging. */ +#if !defined(NDEBUG) || defined(SQLITE_TEST) +SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); +SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); +#endif +#ifdef SQLITE_TEST +SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); +SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); + void disable_simulated_io_errors(void); + void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* SQLITE_PAGER_H */ + +/************** End of pager.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include pcache.h in the middle of sqliteInt.h ****************/ /************** Begin file pcache.h ******************************************/ /* ** 2008 August 05 @@ -17440,11 +14306,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache -** subsystem. +** subsystem. */ #ifndef _PCACHE_H_ typedef struct PgHdr PgHdr; @@ -17466,19 +14332,17 @@ u32 pageHash; /* Hash of page content */ #endif u16 flags; /* PGHDR flags defined below */ /********************************************************************** - ** Elements above, except pCache, are public. All that follow are + ** Elements above, except pCache, are public. All that follow are ** private to pcache.c and should not be accessed by other modules. ** pCache is grouped with the public elements for efficiency. */ - i64 nRef; /* Number of users of this page */ + i16 nRef; /* Number of users of this page */ PgHdr *pDirtyNext; /* Next element in list of dirty pages */ PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ - /* NB: pDirtyNext and pDirtyPrev are undefined if the - ** PgHdr object is not dirty */ }; /* Bit values for PgHdr.flags */ #define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */ #define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */ @@ -17519,11 +14383,11 @@ ** storage space. */ SQLITE_PRIVATE int sqlite3PcacheSize(void); /* One release per successful fetch. Page is pinned until released. -** Reference counted. +** Reference counted. */ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag); SQLITE_PRIVATE int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**); SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage); SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); @@ -17551,23 +14415,23 @@ /* Discard the contents of the cache */ SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); /* Return the total number of outstanding page references */ -SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache*); +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); /* Increment the reference count of an existing page */ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); -SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr*); +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); /* Return the total number of pages stored in the cache */ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* Iterate through all dirty pages currently stored in the cache. This -** interface is only available if SQLITE_CHECK_PAGES is defined when the +** interface is only available if SQLITE_CHECK_PAGES is defined when the ** library is built. */ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); #endif @@ -17613,17 +14477,289 @@ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); /* Number of dirty pages as a percentage of the configured cache size */ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*); -#ifdef SQLITE_DIRECT_OVERFLOW_READ -SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); -#endif - #endif /* _PCACHE_H_ */ /************** End of pcache.h **********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include os.h in the middle of sqliteInt.h ********************/ +/************** Begin file os.h **********************************************/ +/* +** 2001 September 16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This header file (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Attempt to automatically detect the operating system and setup the +** necessary pre-processor macros for it. +*/ +/************** Include os_setup.h in the middle of os.h *********************/ +/************** Begin file os_setup.h ****************************************/ +/* +** 2013 November 25 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains pre-processor directives related to operating system +** detection and/or setup. +*/ +#ifndef SQLITE_OS_SETUP_H +#define SQLITE_OS_SETUP_H + +/* +** Figure out if we are dealing with Unix, Windows, or some other operating +** system. +** +** After the following block of preprocess macros, all of SQLITE_OS_UNIX, +** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of +** the three will be 1. The other two will be 0. +*/ +#if defined(SQLITE_OS_OTHER) +# if SQLITE_OS_OTHER==1 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# else +# undef SQLITE_OS_OTHER +# endif +#endif +#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +# define SQLITE_OS_OTHER 0 +# ifndef SQLITE_OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ + defined(__MINGW32__) || defined(__BORLANDC__) +# define SQLITE_OS_WIN 1 +# define SQLITE_OS_UNIX 0 +# else +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 1 +# endif +# else +# define SQLITE_OS_UNIX 0 +# endif +#else +# ifndef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# endif +#endif + +#endif /* SQLITE_OS_SETUP_H */ + +/************** End of os_setup.h ********************************************/ +/************** Continuing where we left off in os.h *************************/ + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 4096 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** a random byte is selected for a shared lock. The pool of bytes for +** shared locks begins at SHARED_FIRST. +** +** The same locking strategy and +** byte ranges are used for Unix. This leaves open the possibility of having +** clients on win95, winNT, and unix all talking to the same shared file +** and all locking correctly. To do so would require that samba (or whatever +** tool is being used for file sharing) implements locks correctly between +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#ifdef SQLITE_OMIT_WSD +# define PENDING_BYTE (0x40000000) +#else +# define PENDING_BYTE sqlite3PendingByte +#endif +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Wrapper around OS specific sqlite3_os_init() function. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void); + +/* +** Functions for accessing sqlite3_file methods +*/ +SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*); +SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); +SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); +SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*); +#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 +SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); +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); +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); + + +/* +** Functions for accessing sqlite3_vfs methods +*/ +SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); +SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); +SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*); +SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *); + +#endif /* _SQLITE_OS_H_ */ + +/************** End of os.h **************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include mutex.h in the middle of sqliteInt.h *****************/ /************** Begin file mutex.h *******************************************/ /* ** 2007 August 28 @@ -17681,22 +14817,21 @@ /* ** If this is a no-op implementation, implement everything as macros. */ #define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) #define sqlite3_mutex_free(X) -#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_enter(X) #define sqlite3_mutex_try(X) SQLITE_OK -#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_leave(X) #define sqlite3_mutex_held(X) ((void)(X),1) #define sqlite3_mutex_notheld(X) ((void)(X),1) #define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) #define sqlite3MutexInit() SQLITE_OK #define sqlite3MutexEnd() #define MUTEX_LOGIC(X) #else #define MUTEX_LOGIC(X) X -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); #endif /* defined(SQLITE_MUTEX_OMIT) */ /************** End of mutex.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -17709,11 +14844,11 @@ #endif /* ** Default synchronous levels. ** -** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ +** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ ** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1. ** ** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS ** OFF 1 0 ** NORMAL 2 1 @@ -17748,11 +14883,11 @@ /* ** An instance of the following structure stores a database schema. ** ** Most Schema objects are associated with a Btree. The exception is -** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing. +** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. ** In shared cache mode, a single Schema object can be shared by multiple ** Btrees that refer to the same underlying BtShared object. ** ** Schema objects are automatically deallocated when the last Btree that ** references them is destroyed. The TEMP Schema is manually freed by @@ -17796,11 +14931,11 @@ ** have been filled out. If the schema changes, these column names might ** changes and so the view will need to be reset. */ #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ #define DB_UnresetViews 0x0002 /* Some views have defined column names */ -#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ /* ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ @@ -17823,129 +14958,104 @@ ** with a particular database connection. Hence, schema information cannot ** be stored in lookaside because in shared cache mode the schema information ** is shared by multiple database connections. Therefore, while parsing ** schema information, the Lookaside.bEnabled flag is cleared so that ** lookaside allocations are not used to construct the schema objects. -** -** New lookaside allocations are only allowed if bDisable==0. When -** bDisable is greater than zero, sz is set to zero which effectively -** disables lookaside without adding a new test for the bDisable flag -** in a performance-critical path. sz should be set by to szTrue whenever -** bDisable changes back to zero. -** -** Lookaside buffers are initially held on the pInit list. As they are -** used and freed, they are added back to the pFree list. New allocations -** come off of pFree first, then pInit as a fallback. This dual-list -** allows use to compute a high-water mark - the maximum number of allocations -** outstanding at any point in the past - by subtracting the number of -** allocations on the pInit list from the total number of allocations. -** -** Enhancement on 2019-12-12: Two-size-lookaside -** The default lookaside configuration is 100 slots of 1200 bytes each. -** The larger slot sizes are important for performance, but they waste -** a lot of space, as most lookaside allocations are less than 128 bytes. -** The two-size-lookaside enhancement breaks up the lookaside allocation -** into two pools: One of 128-byte slots and the other of the default size -** (1200-byte) slots. Allocations are filled from the small-pool first, -** failing over to the full-size pool if that does not work. Thus more -** lookaside slots are available while also using less memory. -** This enhancement can be omitted by compiling with -** SQLITE_OMIT_TWOSIZE_LOOKASIDE. */ struct Lookaside { u32 bDisable; /* Only operate the lookaside when zero */ u16 sz; /* Size of each buffer in bytes */ - u16 szTrue; /* True value of sz, even if disabled */ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ - u32 nSlot; /* Number of lookaside slots allocated */ - u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ - LookasideSlot *pInit; /* List of buffers not previously used */ + 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 */ LookasideSlot *pFree; /* List of available buffers */ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - LookasideSlot *pSmallInit; /* List of small buffers not previously used */ - LookasideSlot *pSmallFree; /* List of available small buffers */ - void *pMiddle; /* First byte past end of full-size buffers and - ** the first byte of LOOKASIDE_SMALL buffers */ -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ void *pStart; /* First byte of available memory space */ void *pEnd; /* First byte past end of available space */ - void *pTrueEnd; /* True value of pEnd, when db->pnBytesFreed!=0 */ }; struct LookasideSlot { LookasideSlot *pNext; /* Next buffer in the list of free buffers */ }; -#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0 -#define EnableLookaside db->lookaside.bDisable--;\ - db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue - -/* Size of the smaller allocations in two-size lookaside */ -#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE -# define LOOKASIDE_SMALL 0 -#else -# define LOOKASIDE_SMALL 128 -#endif - /* ** A hash table for built-in function definitions. (Application-defined ** functions use a regular table table from hash.h.) ** ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. -** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH() -** macro to compute a hash on the function name. +** Collisions are on the FuncDef.u.pHash chain. */ #define SQLITE_FUNC_HASH_SZ 23 struct FuncDefHash { FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ }; -#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) + +#ifdef SQLITE_USER_AUTHENTICATION +/* +** Information held in the "sqlite3" database connection object and used +** to manage user authentication. +*/ +typedef struct sqlite3_userauth sqlite3_userauth; +struct sqlite3_userauth { + u8 authLevel; /* Current authentication level */ + int nAuthPW; /* Size of the zAuthPW in bytes */ + char *zAuthPW; /* Password used to authenticate */ + char *zAuthUser; /* User name used to authenticate */ +}; + +/* Allowed values for sqlite3_userauth.authLevel */ +#define UAUTH_Unknown 0 /* Authentication not yet checked */ +#define UAUTH_Fail 1 /* User authentication failed */ +#define UAUTH_User 2 /* Authenticated as a normal user */ +#define UAUTH_Admin 3 /* Authenticated as an administrator */ + +/* Functions used only by user authorization logic */ +SQLITE_PRIVATE int sqlite3UserAuthTable(const char*); +SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*); +SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*); +SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); + +#endif /* SQLITE_USER_AUTHENTICATION */ /* ** typedef for the authorization callback function. */ -typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*, - const char*); +#ifdef SQLITE_USER_AUTHENTICATION + typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*, + const char*, const char*); +#else + typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*, + const char*); +#endif #ifndef SQLITE_OMIT_DEPRECATED /* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing ** in the style of sqlite3_trace() */ -#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */ -#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */ +#define SQLITE_TRACE_LEGACY 0x80 #else -#define SQLITE_TRACE_LEGACY 0 -#define SQLITE_TRACE_XPROFILE 0 +#define SQLITE_TRACE_LEGACY 0 #endif /* SQLITE_OMIT_DEPRECATED */ -#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */ -/* -** Maximum number of sqlite3.aDb[] entries. This is the number of attached -** databases plus 2 for "main" and "temp". -*/ -#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2) /* ** Each database connection is an instance of the following structure. */ struct sqlite3 { sqlite3_vfs *pVfs; /* OS Interface */ struct Vdbe *pVdbe; /* List of active virtual machines */ - CollSeq *pDfltColl; /* BINARY collseq for the database encoding */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ sqlite3_mutex *mutex; /* Connection mutex */ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ - u32 mDbFlags; /* flags recording internal state */ - u64 flags; /* flags settable by pragmas. See below */ + int flags; /* Miscellaneous flags. 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 errByteOffset; /* Byte offset of error in SQL statement */ int errMask; /* & result codes with this before returning */ int iSysErrno; /* Errno value from last system error */ - u32 dbOptFlags; /* Flags to enable/disable optimizations */ + u16 dbOptFlags; /* Flags to enable/disable optimizations */ u8 enc; /* Text encoding */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 bBenignMalloc; /* Do not require OOMs if true */ @@ -17953,53 +15063,42 @@ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ 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 noSharedCache; /* True if no shared-cache backends */ + u8 skipBtreeMutex; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ - u8 eOpenState; /* Current condition of the connection */ int nextPagesize; /* Pagesize after VACUUM if >0 */ - i64 nChange; /* Value returned by sqlite3_changes() */ - i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ + u32 magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ struct sqlite3InitInfo { /* Information used during initialization */ - Pgno newTnum; /* Rootpage of table being initialized */ + int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ - unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ - unsigned imposterTable : 1; /* Building an imposter table */ - unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ - const char **azInit; /* "type", "name", and "tbl_name" columns */ + u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ + u8 imposterTable; /* Building an imposter table */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ int nVdbeWrite; /* Number of active VDBEs that read and write */ int nVdbeExec; /* Number of nested calls to VdbeExec() */ int nVDestroy; /* Number of active OP_VDestroy operations */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ - union { - void (*xLegacy)(void*,const char*); /* mTrace==SQLITE_TRACE_LEGACY */ - int (*xV2)(u32,void*,void*,void*); /* All other mTrace values */ - } trace; - void *pTraceArg; /* Argument to the trace function */ -#ifndef SQLITE_OMIT_DEPRECATED + int (*xTrace)(u32,void*,void*,void*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ -#endif void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*); /* Invoked at every commit. */ void *pRollbackArg; /* Argument to xRollbackCallback() */ void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); - void *pAutovacPagesArg; /* Client argument to autovac_pages */ - void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */ - unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32); - Parse *pParse; /* Current parse */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK void *pPreUpdateArg; /* First argument to xPreUpdateCallback */ void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 ); @@ -18030,27 +15129,25 @@ #ifndef SQLITE_OMIT_VIRTUALTABLE int nVTrans; /* Allocated size of aVTrans */ 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 */ BusyHandler busyHandler; /* Busy callback */ Db aDbStatic[2]; /* Static space for the 2 default backends */ Savepoint *pSavepoint; /* List of active savepoints */ - int nAnalysisLimit; /* Number of index rows to ANALYZE */ int busyTimeout; /* Busy handler timeout, in msec */ int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ - DbClientData *pDbData; /* sqlite3_set_clientdata() content */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - /* The following variables are all protected by the STATIC_MAIN + /* The following variables are all protected by the STATIC_MASTER ** mutex, not by sqlite3.mutex. They are used by code in notify.c. ** ** When X.pUnlockConnection==Y, that means that X is waiting for Y to ** unlock so that it can proceed. ** @@ -18062,137 +15159,91 @@ sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ void *pUnlockArg; /* Argument to xUnlockNotify */ void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ #endif +#ifdef SQLITE_USER_AUTHENTICATION + sqlite3_userauth auth; /* User authentication information */ +#endif }; /* ** A macro to discover the encoding of a database. */ #define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) #define ENC(db) ((db)->enc) -/* -** A u64 constant where the lower 32 bits are all zeros. Only the -** upper 32 bits are included in the argument. Necessary because some -** C-compilers still do not accept LL integer literals. -*/ -#define HI(X) ((u64)(X)<<32) - /* ** Possible values for the sqlite3.flags. ** ** Value constraints (enforced via assert()): ** SQLITE_FullFSync == PAGER_FULLFSYNC ** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC ** SQLITE_CacheSpill == PAGER_CACHE_SPILL */ -#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_SCHEMA */ +#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 */ #define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */ #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ -#define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and - ** vtabs in the schema definition */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */ -#define SQLITE_StmtScanStatus 0x00000400 /* Enable stmt_scanstats() counters */ +#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 */ -#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ -#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ -#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ -#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ -#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ -#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ -#define SQLITE_EnableView 0x80000000 /* Enable the use of views */ -#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */ - /* DELETE, or UPDATE and return */ - /* the count using a callback. */ -#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */ -#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */ -#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */ -#define SQLITE_AttachCreate HI(0x00010) /* ATTACH allowed to create new dbs */ -#define SQLITE_AttachWrite HI(0x00020) /* ATTACH allowed to open for write */ -#define SQLITE_Comments HI(0x00040) /* Enable SQL comments */ - +#define SQLITE_EnableTrigger 0x00020000 /* True to enable triggers */ +#define SQLITE_DeferFKs 0x00040000 /* Defer all FK constraints */ +#define SQLITE_QueryOnly 0x00080000 /* Disable database changes */ +#define SQLITE_CellSizeCk 0x00100000 /* Check btree cell sizes on load */ +#define SQLITE_Fts3Tokenizer 0x00200000 /* Enable fts3_tokenizer(2) */ +#define SQLITE_EnableQPSG 0x00400000 /* Query Planner Stability Guarantee */ +/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and +** could be factored out into a separate bit vector of the sqlite3 object. */ +#define SQLITE_InternChanges 0x00800000 /* Uncommitted Hash table changes */ +#define SQLITE_LoadExtFunc 0x01000000 /* Enable load_extension() SQL func */ +#define SQLITE_PreferBuiltin 0x02000000 /* Preference to built-in funcs */ +#define SQLITE_Vacuum 0x04000000 /* Currently in a VACUUM */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG -#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */ -#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */ -#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */ +#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 */ -#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */ -#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */ -#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */ -#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ -#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */ -#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */ -#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */ -#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */ -#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */ -#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */ -#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */ -#define SQLITE_Transitive 0x00000080 /* Transitive constraints */ -#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */ -#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */ -#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */ -#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ - /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ -#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */ -#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ -#define SQLITE_SkipScan 0x00004000 /* Skip-scans */ -#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ -#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ -#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ -#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ - /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ -#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ -#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ -#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ -#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */ -#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ - /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */ -#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ -#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ -#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */ -#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */ -#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */ -#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */ -#define SQLITE_AllOpts 0xffffffff /* All optimizations */ +#define SQLITE_QueryFlattener 0x0001 /* Query flattening */ +#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_Stat34 0x0800 /* Use STAT3 or STAT4 data */ +#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */ +#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */ +#define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) @@ -18202,20 +15253,21 @@ ** Return true if it OK to factor constant expressions into the initialization ** code. The argument is a Parse object for the code generator. */ #define ConstFactorOk(P) ((P)->okConstFactor) -/* Possible values for the sqlite3.eOpenState field. -** The numbers are randomly selected such that a minimum of three bits must -** change to convert any number to another or to zero +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. */ -#define SQLITE_STATE_OPEN 0x76 /* Database is open */ -#define SQLITE_STATE_CLOSED 0xce /* Database is closed */ -#define SQLITE_STATE_SICK 0xba /* Error and awaiting close */ -#define SQLITE_STATE_BUSY 0x6d /* Database currently in use */ -#define SQLITE_STATE_ERROR 0xd5 /* An SQLITE_MISUSE error occurred */ -#define SQLITE_STATE_ZOMBIE 0xa7 /* Close with last statement close */ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ +#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */ /* ** Each SQL function is defined by an instance of the following ** structure. For global built-in functions (ex: substr(), max(), count()) ** a pointer to this structure is held in the sqlite3BuiltinFunctions object. @@ -18224,23 +15276,21 @@ ** ** The u.pHash field is used by the global built-ins. The u.pDestructor ** field is used by per-connection app-def functions. */ struct FuncDef { - i16 nArg; /* Number of arguments. -1 means unlimited */ - u32 funcFlags; /* Some combination of SQLITE_FUNC_* */ + i8 nArg; /* Number of arguments. -1 means unlimited */ + u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ - void (*xValue)(sqlite3_context*); /* Current agg value */ - void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */ const char *zName; /* SQL name of the function. */ union { FuncDef *pHash; /* Next with a different name but the same hash */ FuncDestructor *pDestructor; /* Reference counted destructor function */ - } u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */ + } u; }; /* ** This structure encapsulates a user-function destructor callback (as ** configured using create_function_v2()) and a reference counter. When @@ -18266,62 +15316,31 @@ ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And ** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There ** are assert() statements in the code to verify this. ** ** Value constraints (enforced via assert()): -** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg -** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd -** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG -** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG -** SQLITE_FUNC_BYTELEN == OPFLAG_BYTELENARG -** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API -** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API -** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!! +** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg +** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG +** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG +** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API ** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API -** -** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the -** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is -** used internally and if set means that the function has side effects. -** SQLITE_INNOCUOUS is used by application code and means "not unsafe". -** See multiple instances of tag-20230109-1. */ #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ #define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */ #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */ #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/ #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */ #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */ -#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */ #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */ -/* 0x0200 -- available for reuse */ +#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */ #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ -#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ -#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */ -#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ -#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ -#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ -/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */ -#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ -#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ -#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */ -/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */ -#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ - -/* Identifier numbers for each in-line function */ -#define INLINEFUNC_coalesce 0 -#define INLINEFUNC_implies_nonnull_row 1 -#define INLINEFUNC_expr_implies_expr 2 -#define INLINEFUNC_expr_compare 3 -#define INLINEFUNC_affinity 4 -#define INLINEFUNC_iif 5 -#define INLINEFUNC_sqlite_offset 6 -#define INLINEFUNC_unlikely 99 /* Default case */ +#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** @@ -18333,49 +15352,17 @@ ** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. ** ** VFUNCTION(zName, nArg, iArg, bNC, xFunc) ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag. ** -** SFUNCTION(zName, nArg, iArg, bNC, xFunc) -** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and -** adds the SQLITE_DIRECTONLY flag. -** -** INLINE_FUNC(zName, nArg, iFuncId, mFlags) -** zName is the name of a function that is implemented by in-line -** byte code rather than by the usual callbacks. The iFuncId -** parameter determines the function id. The mFlags parameter is -** optional SQLITE_FUNC_ flags for this function. -** -** TEST_FUNC(zName, nArg, iFuncId, mFlags) -** zName is the name of a test-only function implemented by in-line -** byte code rather than by the usual callbacks. The iFuncId -** parameter determines the function id. The mFlags parameter is -** optional SQLITE_FUNC_ flags for this function. -** ** DFUNCTION(zName, nArg, iArg, bNC, xFunc) ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and ** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions ** and functions like sqlite_version() that can change, but not during -** a single query. The iArg is ignored. The user-data is always set -** to a NULL pointer. The bNC parameter is not used. -** -** MFUNCTION(zName, nArg, xPtr, xFunc) -** For math-library functions. xPtr is an arbitrary pointer. -** -** PURE_DATE(zName, nArg, iArg, bNC, xFunc) -** Used for "pure" date/time functions, this macro is like DFUNCTION -** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is -** ignored and the user-data for these functions is set to an -** arbitrary non-NULL pointer. The bNC parameter is not used. +** a single query. ** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) -** Used to create an aggregate function definition implemented by -** the C functions xStep and xFinal. The first four parameters -** are interpreted in the same way as the first 4 parameters to -** FUNCTION(). -** -** WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to ** FUNCTION(). ** @@ -18386,62 +15373,33 @@ ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } -#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } -#define MFUNCTION(zName, nArg, xPtr, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ - xPtr, 0, xFunc, 0, 0, 0, #zName, {0} } -#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\ - SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\ - ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \ - SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} } -#define INLINE_FUNC(zName, nArg, iArg, mFlags) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ - SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} } -#define TEST_FUNC(zName, nArg, iArg, mFlags) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \ - SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ - SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} } + {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_BUILTIN|SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \ - 0, 0, xFunc, 0, 0, 0, #zName, {0} } -#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ - (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} } + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - pArg, 0, xFunc, 0, 0, 0, #zName, } + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + pArg, 0, xFunc, 0, #zName, } #define LIKEFUNC(zName, nArg, arg, flags) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ - (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} } -#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ - {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ - SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} -#define INTERNAL_FUNCTION(zName, nArg, xFunc) \ - {nArg, SQLITE_FUNC_BUILTIN|\ - SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ - 0, 0, xFunc, 0, 0, 0, #zName, {0} } - + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ + (void *)arg, 0, likeFunc, 0, #zName, {0} } +#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} +#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ + SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} /* ** All current savepoints are stored in a linked list starting at ** sqlite3.pSavepoint. The first element in the list is the most recently ** opened savepoint. Savepoints are added to the list by the vdbe @@ -18469,88 +15427,34 @@ ** hash table. */ struct Module { const sqlite3_module *pModule; /* Callback pointers */ const char *zName; /* Name passed to create_module() */ - int nRefModule; /* Number of pointers to this object */ void *pAux; /* pAux passed to create_module() */ void (*xDestroy)(void *); /* Module destructor function */ Table *pEpoTab; /* Eponymous table for this module */ }; /* -** Information about each column of an SQL table is held in an instance -** of the Column structure, in the Table.aCol[] array. -** -** Definitions: -** -** "table column index" This is the index of the column in the -** Table.aCol[] array, and also the index of -** the column in the original CREATE TABLE stmt. -** -** "storage column index" This is the index of the column in the -** record BLOB generated by the OP_MakeRecord -** opcode. The storage column index is less than -** or equal to the table column index. It is -** equal if and only if there are no VIRTUAL -** columns to the left. -** -** Notes on zCnName: -** The zCnName field stores the name of the column, the datatype of the -** column, and the collating sequence for the column, in that order, all in -** a single allocation. Each string is 0x00 terminated. The datatype -** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the -** collating sequence name is only included if the COLFLAG_HASCOLL bit is -** set. +** information about each column of an SQL table is held in an instance +** of this structure. */ struct Column { - char *zCnName; /* Name of this column */ - unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */ - unsigned eCType :4; /* One of the standard types */ - char affinity; /* One of the SQLITE_AFF_... values */ - u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */ - u8 hName; /* Column name hash for faster lookup */ - u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */ - u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ + char *zName; /* Name of this column, \000, then the type */ + Expr *pDflt; /* Default value of this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ + char affinity; /* One of the SQLITE_AFF_... values */ + u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ + u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; -/* Allowed values for Column.eCType. -** -** Values must match entries in the global constant arrays -** sqlite3StdTypeLen[] and sqlite3StdType[]. Each value is one more -** than the offset into these arrays for the corresponding name. -** Adjust the SQLITE_N_STDTYPE value if adding or removing entries. -*/ -#define COLTYPE_CUSTOM 0 /* Type appended to zName */ -#define COLTYPE_ANY 1 -#define COLTYPE_BLOB 2 -#define COLTYPE_INT 3 -#define COLTYPE_INTEGER 4 -#define COLTYPE_REAL 5 -#define COLTYPE_TEXT 6 -#define SQLITE_N_STDTYPE 6 /* Number of standard types */ - -/* Allowed values for Column.colFlags. -** -** Constraints: -** TF_HasVirtual == COLFLAG_VIRTUAL -** TF_HasStored == COLFLAG_STORED -** TF_HasHidden == COLFLAG_HIDDEN -*/ -#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ -#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ -#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ -#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ -#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ -#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ -#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */ -#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */ -#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */ -#define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */ -#define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */ -#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */ -#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */ +/* Allowed values for Column.colFlags: +*/ +#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ +#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ +#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. @@ -18586,17 +15490,15 @@ ** used as the P4 operand, they will be more readable. ** ** Note also that the numeric types are grouped together so that testing ** for a numeric type is a single comparison. And the BLOB type is first. */ -#define SQLITE_AFF_NONE 0x40 /* '@' */ -#define SQLITE_AFF_BLOB 0x41 /* 'A' */ -#define SQLITE_AFF_TEXT 0x42 /* 'B' */ -#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */ -#define SQLITE_AFF_INTEGER 0x44 /* 'D' */ -#define SQLITE_AFF_REAL 0x45 /* 'E' */ -#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */ +#define SQLITE_AFF_BLOB 'A' +#define SQLITE_AFF_TEXT 'B' +#define SQLITE_AFF_NUMERIC 'C' +#define SQLITE_AFF_INTEGER 'D' +#define SQLITE_AFF_REAL 'E' #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) /* ** The SQLITE_AFF_MASK values masks off the significant bits of an @@ -18611,11 +15513,13 @@ ** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. ** It causes an assert() to fire if either operand to a comparison ** operator is NULL. It is added to certain comparison operators to ** prove that the operands are always NOT NULL. */ +#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */ #define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ #define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */ /* ** An object of this type is created for each virtual table present in @@ -18663,122 +15567,81 @@ sqlite3 *db; /* Database connection associated with this table */ Module *pMod; /* Pointer to module implementation */ sqlite3_vtab *pVtab; /* Pointer to vtab instance */ int nRef; /* Number of pointers to this structure */ u8 bConstraint; /* True if constraints are supported */ - u8 bAllSchemas; /* True if might use any attached schema */ - u8 eVtabRisk; /* Riskiness of allowing hacker access */ int iSavepoint; /* Depth of the SAVEPOINT stack */ VTable *pNext; /* Next in linked list (see above) */ }; -/* Allowed values for VTable.eVtabRisk -*/ -#define SQLITE_VTABRISK_Low 0 -#define SQLITE_VTABRISK_Normal 1 -#define SQLITE_VTABRISK_High 2 - /* -** The schema for each SQL table, virtual table, and view is represented -** in memory by an instance of the following structure. +** The schema for each SQL table and view is represented in memory +** by an instance of the following structure. */ struct Table { char *zName; /* Name of the table or view */ Column *aCol; /* Information about each column */ Index *pIndex; /* List of SQL indexes on this table. */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ ExprList *pCheck; /* All CHECK constraints */ /* ... also used as column name list in a VIEW */ - Pgno tnum; /* Root BTree page for this table */ + 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 */ - i16 nNVCol; /* Number of columns that are not VIRTUAL */ LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ #ifdef SQLITE_ENABLE_COSTMULT LogEst costMult; /* Cost multiplier for using this table */ #endif u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ - u8 eTabType; /* 0: normal, 1: virtual, 2: view */ - union { - struct { /* Used by ordinary tables: */ - int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ - FKey *pFKey; /* Linked list of all foreign keys in this table */ - ExprList *pDfltList; /* DEFAULT clauses on various columns. - ** Or the AS clause for generated columns. */ - } tab; - struct { /* Used by views: */ - Select *pSelect; /* View definition */ - } view; - struct { /* Used by virtual tables only: */ - int nArg; /* Number of arguments to the module */ - char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */ - VTable *p; /* List of VTable objects. */ - } vtab; - } u; - Trigger *pTrigger; /* List of triggers on this object */ +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */ + VTable *pVTable; /* List of VTable objects. */ +#endif + Trigger *pTrigger; /* List of triggers stored in pSchema */ Schema *pSchema; /* Schema that contains this table */ + Table *pNextZombie; /* Next on the Parse.pZombieTab list */ }; /* ** Allowed values for Table.tabFlags. ** ** TF_OOOHidden applies to tables or view that have hidden columns that are ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, ** the TF_OOOHidden attribute would apply in this case. Such tables require -** special handling during INSERT processing. The "OOO" means "Out Of Order". -** -** Constraints: -** -** TF_HasVirtual == COLFLAG_VIRTUAL -** TF_HasStored == COLFLAG_STORED -** TF_HasHidden == COLFLAG_HIDDEN -*/ -#define TF_Readonly 0x00000001 /* Read-only system table */ -#define TF_HasHidden 0x00000002 /* Has one or more hidden columns */ -#define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */ -#define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */ -#define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */ -#define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */ -#define TF_HasStored 0x00000040 /* Has one or more STORED columns */ -#define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */ -#define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */ -#define TF_MaybeReanalyze 0x00000100 /* Maybe run ANALYZE on this table */ -#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */ -#define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */ -#define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */ -#define TF_Shadow 0x00001000 /* True for a shadow table */ -#define TF_HasStat4 0x00002000 /* STAT4 info available for this table */ -#define TF_Ephemeral 0x00004000 /* An ephemeral table */ -#define TF_Eponymous 0x00008000 /* An eponymous virtual table */ -#define TF_Strict 0x00010000 /* STRICT mode */ - -/* -** Allowed values for Table.eTabType -*/ -#define TABTYP_NORM 0 /* Ordinary table */ -#define TABTYP_VTAB 1 /* Virtual table */ -#define TABTYP_VIEW 2 /* A view */ - -#define IsView(X) ((X)->eTabType==TABTYP_VIEW) -#define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM) +** special handling during INSERT processing. +*/ +#define TF_Readonly 0x0001 /* Read-only system table */ +#define TF_Ephemeral 0x0002 /* An ephemeral table */ +#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */ +#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */ +#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ +#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */ +#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */ +#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */ +#define TF_StatsUsed 0x0100 /* Query planner decisions affected by + ** Index.aiRowLogEst[] values */ +#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE -# define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB) -# define ExprIsVtab(X) \ - ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB) +# define IsVirtual(X) ((X)->nModuleArg) #else # define IsVirtual(X) 0 -# define ExprIsVtab(X) 0 #endif /* ** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn() ** only works for non-virtual tables (ordinary tables and views) and is @@ -18799,19 +15662,10 @@ /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) -/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is -** available. By default, this macro is false -*/ -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW -# define ViewCanHaveRowid 0 -#else -# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0) -#endif - /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign @@ -18867,39 +15721,34 @@ ** occurs. IGNORE means that the particular row that caused the constraint ** error is not inserted or updated. Processing continues and no error ** is returned. REPLACE means that preexisting database rows that caused ** a UNIQUE constraint violation are removed so that the new insert or ** update can proceed. Processing continues and no error is reported. -** UPDATE applies to insert operations only and means that the insert -** is omitted and the DO UPDATE clause of an upsert is run instead. ** -** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys. +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. ** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the ** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign -** key is set to NULL. SETDFLT means that the foreign key is set -** to its default value. CASCADE means that a DELETE or UPDATE of the +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the ** referenced table row is propagated into the row that holds the ** foreign key. ** -** The OE_Default value is a place holder that means to use whatever -** conflict resolution algorithm is required from context. -** ** The following symbolic values are used to record which type -** of conflict resolution action to take. +** of action to take. */ #define OE_None 0 /* There is no constraint to check */ #define OE_Rollback 1 /* Fail the operation and rollback the transaction */ #define OE_Abort 2 /* Back out changes but do no rollback transaction */ #define OE_Fail 3 /* Stop the operation but leave all prior changes */ #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ -#define OE_Update 6 /* Process as a DO UPDATE in an upsert */ -#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ -#define OE_SetNull 8 /* Set the foreign key value to NULL */ -#define OE_SetDflt 9 /* Set the foreign key value to its default */ -#define OE_Cascade 10 /* Cascade the changes */ -#define OE_Default 11 /* Do whatever the default action is */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 10 /* Do whatever the default action is */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the @@ -18910,23 +15759,17 @@ ** for the rowid at the end. */ struct KeyInfo { u32 nRef; /* Number of references to this KeyInfo object */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ - u16 nKeyField; /* Number of key columns in the index */ - u16 nAllField; /* Total columns, including key plus others */ + u16 nField; /* Number of key columns in the index */ + u16 nXField; /* Number of columns beyond the key columns */ sqlite3 *db; /* The database connection */ - u8 *aSortFlags; /* Sort order for each column. */ + u8 *aSortOrder; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; -/* -** Allowed bit values for entries in the KeyInfo.aSortFlags[] array. -*/ -#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */ -#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */ - /* ** This object holds a record which has been parsed out into individual ** fields, for the purposes of doing a comparison. ** ** A record is an object that contains one or more fields of data. @@ -18961,20 +15804,15 @@ ** b-tree. */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ Mem *aMem; /* Values */ - union { - char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */ - i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */ - } u; - int n; /* Cache of aMem[0].n used by vdbeRecordCompareString() */ u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ - i8 r1; /* Value to return if (lhs < rhs) */ - i8 r2; /* Value to return if (lhs > rhs) */ + i8 r1; /* Value to return if (lhs > rhs) */ + i8 r2; /* Value to return if (rhs < lhs) */ u8 eqSeen; /* True if an equality comparison has been seen */ }; /* @@ -18997,28 +15835,16 @@ ** Ex1.aCol[], hence Ex2.aiColumn[1]==0. ** ** The Index.onError field determines whether or not the indexed columns ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index -** and the value of Index.onError indicates which conflict resolution -** algorithm to employ when an attempt is made to insert a non-unique +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique ** element. ** -** The colNotIdxed bitmask is used in combination with SrcItem.colUsed -** for a fast test to see if an index can serve as a covering index. -** colNotIdxed has a 1 bit for every column of the original table that -** is *not* available in the index. Thus the expression -** "colUsed & colNotIdxed" will be non-zero if the index is not a -** covering index. The most significant bit of of colNotIdxed will always -** be true (note-20221022-a). If a column beyond the 63rd column of the -** table is used, the "colUsed & colNotIdxed" test will always be non-zero -** and we have to assume either that the index is not covering, or use -** an alternative (slower) algorithm to determine whether or not -** the index is covering. -** ** While parsing a CREATE TABLE or CREATE INDEX statement in order to -** generate VDBE code (as opposed to parsing one read from an sqlite_schema +** generate VDBE code (as opposed to parsing one read from an sqlite_master ** table as part of parsing an existing database schema), transient instances ** of this structure may be created. In this case the Index.tnum variable is ** used to store the address of a VDBE instruction, not a database page ** number (it cannot - the database page is not allocated until the VDBE ** program is executed). See convertToWithoutRowidTable() for details. @@ -19033,47 +15859,38 @@ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ const char **azColl; /* Array of collation sequence names for index */ Expr *pPartIdxWhere; /* WHERE clause for partial indices */ ExprList *aColExpr; /* Column expressions */ - Pgno tnum; /* DB Page containing root of this index */ + int tnum; /* DB Page containing root of this index */ LogEst szIdxRow; /* Estimated average row size in bytes */ u16 nKeyCol; /* Number of columns forming the key */ u16 nColumn; /* Number of columns stored in the index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ - unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */ + unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ 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 bLowQual:1; /* sqlite_stat1 says this is a low-quality index */ - unsigned bNoQuery:1; /* Do not use this index to optimize queries */ - unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ - unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ - unsigned bHasExpr:1; /* Index contains an expression, either a literal - ** expression, or a reference to a VIRTUAL column */ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ - int mxSample; /* Number of slots allocated to aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ #endif - Bitmask colNotIdxed; /* Unindexed columns in pTab */ }; /* ** Allowed values for Index.idxType */ #define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */ #define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */ #define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */ -#define SQLITE_IDXTYPE_IPK 3 /* INTEGER PRIMARY KEY index */ /* Return true if index X is a PRIMARY KEY index */ #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) /* Return true if index X is a UNIQUE index */ @@ -19084,11 +15901,11 @@ */ #define XN_ROWID (-1) /* Indexed column is the rowid */ #define XN_EXPR (-2) /* Indexed column is an expression */ /* -** Each sample stored in the sqlite_stat4 table is represented in memory +** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the ** analyze.c source file for additional information. */ struct IndexSample { void *p; /* Pointer to sampled record */ @@ -19096,25 +15913,17 @@ tRowcnt *anEq; /* Est. number of rows where the key equals this sample */ tRowcnt *anLt; /* Est. number of rows where key is less than this sample */ tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ }; -/* -** Possible values to use within the flags argument to sqlite3GetToken(). -*/ -#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */ -#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */ - /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** -** The memory that "z" points to is owned by other objects. Take care -** that the owner of the "z" string does not deallocate the string before -** the Token goes out of scope! Very often, the "z" points to some place -** in the middle of the Parse.zSql text. But it might also point to a -** static string. +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assumptions about Token.dyn +** and Token.n when Token.z==0. */ struct Token { const char *z; /* Text of the token. Not NULL-terminated! */ unsigned int n; /* Number of characters in this token */ }; @@ -19122,11 +15931,11 @@ /* ** An instance of this structure contains information needed to generate ** code for a SELECT that contains aggregate functions. ** ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a -** pointer to this structure. The Expr.iAgg field is the index in +** pointer to this structure. The Expr.iColumn field is the index in ** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate ** code for that node. ** ** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the ** original Select structure that describes the SELECT statement. These @@ -19135,71 +15944,47 @@ struct AggInfo { u8 directMode; /* Direct rendering mode means take data directly ** from source tables rather than from accumulators */ u8 useSortingIdx; /* In direct mode, reference the sorting index rather ** than the source table */ - u16 nSortingColumn; /* Number of columns in the sorting index */ int sortingIdx; /* Cursor number of the sorting index */ int sortingIdxPTab; /* Cursor number of pseudo-table */ - int iFirstReg; /* First register in range for aCol[] and aFunc[] */ + int nSortingColumn; /* Number of columns in the sorting index */ + int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */ ExprList *pGroupBy; /* The group by clause */ struct AggInfo_col { /* For each column used in source tables */ Table *pTab; /* Source table */ - Expr *pCExpr; /* The original expression */ int iTable; /* Cursor number of the source table */ - i16 iColumn; /* Column number within the source table */ - i16 iSorterColumn; /* Column number in the sorting index */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ } *aCol; int nColumn; /* Number of used entries in aCol[] */ int nAccumulator; /* Number of columns that show through to the output. ** Additional columns are used only as parameters to ** aggregate functions */ struct AggInfo_func { /* For each aggregate function */ - Expr *pFExpr; /* Expression encoding the function */ + Expr *pExpr; /* Expression encoding the function */ FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ int iDistinct; /* Ephemeral table used to enforce DISTINCT */ - int iDistAddr; /* Address of OP_OpenEphemeral */ - int iOBTab; /* Ephemeral table to implement ORDER BY */ - u8 bOBPayload; /* iOBTab has payload columns separate from key */ - u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */ - u8 bUseSubtype; /* Transfer subtype info through sorter */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ - u32 selId; /* Select to which this AggInfo belongs */ -#ifdef SQLITE_DEBUG - Select *pSelect; /* SELECT statement that this AggInfo supports */ -#endif }; -/* -** Macros to compute aCol[] and aFunc[] register numbers. -** -** These macros should not be used prior to the call to -** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg. -** The assert()s that are part of this macro verify that constraint. -*/ -#ifndef NDEBUG -#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I)) -#define AggInfoFuncReg(A,I) \ - (assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I)) -#else -#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I)) -#define AggInfoFuncReg(A,I) \ - ((A)->iFirstReg+(A)->nColumn+(I)) -#endif - /* ** The datatype ynVar is a signed integer, either 16-bit or 32-bit. ** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater ** than 32767 we have to make it 32-bit. 16-bit is preferred because ** it uses less memory in the Expr object, which is a big memory user ** in systems with lots of prepared statements. And few applications ** need more than about 10 or 20 variables. But some extreme users want -** to have prepared statements with over 32766 variables, and for them +** to have prepared statements with over 32767 variables, and for them ** the option is available (at compile-time). */ -#if SQLITE_MAX_VARIABLE_NUMBER<32767 +#if SQLITE_MAX_VARIABLE_NUMBER<=32767 typedef i16 ynVar; #else typedef int ynVar; #endif @@ -19212,14 +15997,14 @@ ** code representing the ">=" operator. This same integer code is reused ** to represent the greater-than-or-equal-to operator in the expression ** tree. ** ** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, -** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If -** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the +** or TK_STRING), then Expr.token contains the text of the SQL literal. If +** the expression is a variable (TK_VARIABLE), then Expr.token contains the ** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), -** then Expr.u.zToken contains the name of the function. +** then Expr.token contains the name of the function. ** ** Expr.pRight and Expr.pLeft are the left and right subexpressions of a ** binary operator. Either or both may be NULL. ** ** Expr.x.pList is a list of arguments if the expression is an SQL function, @@ -19255,11 +16040,11 @@ ** ** Expr objects can use a lot of memory space in database schema. To ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, -** together with Expr.u.zToken strings. +** together with Expr.zToken strings. ** ** If the EP_Reduced and EP_TokenOnly flags are set when ** an Expr object is truncated. When EP_Reduced is set, then all ** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees ** are contained within the same memory allocation. Note, however, that @@ -19266,18 +16051,11 @@ ** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately ** allocated, regardless of whether or not EP_Reduced is set. */ struct Expr { u8 op; /* Operation performed by this node */ - char affExpr; /* affinity, or RAISE type */ - u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op - ** TK_COLUMN: the value of p5 for OP_Column - ** TK_AGG_FUNCTION: nesting depth - ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */ -#ifdef SQLITE_DEBUG - u8 vvaFlags; /* Verification flags. */ -#endif + char affinity; /* The affinity of the column or 0 if not a column */ u32 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ int iValue; /* Non-negative integer value if EP_IntValue */ } u; @@ -19304,118 +16082,73 @@ #endif int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 134217728 times likelihood - ** TK_IN: ephemeral table holding RHS - ** TK_SELECT_COLUMN: Number of columns on the LHS ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). ** TK_SELECT_COLUMN: column of the result vector */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ - union { - int iJoin; /* If EP_OuterON or EP_InnerON, the right table */ - int iOfst; /* else: start of token from start of statement */ - } w; + i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + u8 op2; /* TK_REGISTER: original value of Expr.op + ** TK_COLUMN: the value of p5 for OP_Column + ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - union { - Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL - ** for a column of an index on an expression */ - Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */ - struct { /* TK_IN, TK_SELECT, and TK_EXISTS */ - int iAddr; /* Subroutine entry address */ - int regReturn; /* Register used to hold return address */ - } sub; - } y; + Table *pTab; /* Table for TK_COLUMN expressions. */ }; -/* The following are the meanings of bits in the Expr.flags field. -** Value restrictions: -** -** EP_Agg == NC_HasAgg == SF_HasAgg -** EP_Win == NC_HasWin -*/ -#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */ -#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */ -#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */ -#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */ -#define EP_Agg 0x000010 /* Contains one or more aggregate functions */ -#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */ -#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */ -#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */ -#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */ -#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */ -#define EP_Commuted 0x000400 /* Comparison operator has been commuted */ -#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */ -#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */ -#define EP_Skip 0x002000 /* Operator does not contribute to affinity */ -#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ -#define EP_Win 0x008000 /* Contains window functions */ -#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ -#define EP_FullSize 0x020000 /* Expr structure must remain full sized */ -#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */ -#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */ -#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ -#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */ -#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */ -#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ -#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ -#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ -#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ -#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ -#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ -#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ -#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */ -#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */ - -/* The EP_Propagate mask is a set of properties that automatically propagate -** upwards into parent nodes. -*/ -#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc) - -/* Macros can be used to test, set, or clear bits in the +/* +** The following are the meanings of bits in the Expr.flags field. +*/ +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ +#define EP_Agg 0x000002 /* Contains one or more aggregate functions */ + /* 0x000004 // available for use */ + /* 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 "..." */ +#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ +#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ +#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ +#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ +#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */ +#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ +#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ +#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ +#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ +#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ +#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ +#define EP_Alias 0x400000 /* Is an alias for a result set column */ +#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ + +/* +** Combinations of two or more EP_* flags +*/ +#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ + +/* +** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))!=0) #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) #define ExprSetProperty(E,P) (E)->flags|=(P) #define ExprClearProperty(E,P) (E)->flags&=~(P) -#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue) -#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse) -#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0) - -/* Macros used to ensure that the correct members of unions are accessed -** in Expr. -*/ -#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0) -#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0) -#define ExprUseWOfst(E) (((E)->flags&(EP_InnerON|EP_OuterON))==0) -#define ExprUseWJoin(E) (((E)->flags&(EP_InnerON|EP_OuterON))!=0) -#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0) -#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0) -#define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0) -#define ExprUseYWin(E) (((E)->flags&EP_WinFunc)!=0) -#define ExprUseYSub(E) (((E)->flags&EP_Subrtn)!=0) - -/* Flags for use with Expr.vvaFlags -*/ -#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */ -#define EP_Immutable 0x02 /* Do not change this Expr node */ /* The ExprSetVVAProperty() macro is used for Verification, Validation, ** and Accreditation only. It works like ExprSetProperty() during VVA ** processes but is a no-op for delivery. */ #ifdef SQLITE_DEBUG -# define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P) -# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0) -# define ExprClearVVAProperties(E) (E)->vvaFlags = 0 +# define ExprSetVVAProperty(E,P) (E)->flags|=(P) #else # define ExprSetVVAProperty(E,P) -# define ExprHasVVAProperty(E,P) 0 -# define ExprClearVVAProperties(E) #endif /* ** Macros to determine the number of bytes required by a normal Expr ** struct, an Expr struct with the EP_Reduced flag set in Expr.flags @@ -19429,80 +16162,57 @@ ** Flags passed to the sqlite3ExprDup() function. See the header comment ** above sqlite3ExprDup() for details. */ #define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */ -/* -** True if the expression passed as an argument was a function with -** an OVER() clause (a window function). -*/ -#ifdef SQLITE_OMIT_WINDOWFUNC -# define IsWindowFunc(p) 0 -#else -# define IsWindowFunc(p) ( \ - ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \ - ) -#endif - /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the ** list of "ID = expr" items in an UPDATE. A list of expressions can ** also be used as the argument to a function, in which case the a.zName ** field is not used. ** -** In order to try to keep memory usage down, the Expr.a.zEName field -** is used for multiple purposes: -** -** eEName Usage -** ---------- ------------------------- -** ENAME_NAME (1) the AS of result set column -** (2) COLUMN= of an UPDATE -** -** ENAME_TAB DB.TABLE.NAME used to resolve names -** of subqueries -** -** ENAME_SPAN Text of the original result set -** expression. +** By default the Expr.zSpan field holds a human-readable description of +** the expression that is used in the generation of error messages and +** column labels. In this case, Expr.zSpan is typically the text of a +** column expression as it exists in a SELECT statement. However, if +** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name +** of the result column in the form: DATABASE.TABLE.COLUMN. This later +** form is used for name resolution with nested FROM clauses. */ struct ExprList { int nExpr; /* Number of expressions on the list */ int nAlloc; /* Number of a[] slots allocated */ struct ExprList_item { /* For each expression in the list */ Expr *pExpr; /* The parse tree for this expression */ - char *zEName; /* Token associated with this expression */ - struct { - u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */ - unsigned eEName :2; /* Meaning of zEName */ - unsigned done :1; /* Indicates when processing is finished */ - unsigned reusable :1; /* Constant expression is reusable */ - unsigned bSorterRef :1; /* Defer evaluation until after sorting */ - unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */ - unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */ - unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */ - unsigned bNoExpand: 1; /* Term is an auxiliary in NestedFrom and should - ** not be expanded by "*" in parent queries */ - } fg; + char *zName; /* Token associated with this expression */ + char *zSpan; /* Original text of the expression */ + u8 sortOrder; /* 1 for DESC or 0 for ASC */ + unsigned done :1; /* A flag to indicate when processing is finished */ + unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ + unsigned reusable :1; /* Constant expression is reusable */ union { - struct { /* Used by any ExprList other than Parse.pConsExpr */ + struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } x; - int iConstExprReg; /* Register in which Expr value is cached. Used only - ** by Parse.pConstExpr */ + int iConstExprReg; /* Register in which Expr value is cached */ } u; } a[1]; /* One slot for each expression in the list */ }; /* -** Allowed values for Expr.a.eEName +** 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. */ -#define ENAME_NAME 0 /* The AS clause of a result set */ -#define ENAME_SPAN 1 /* Complete text of the result set expression */ -#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */ -#define ENAME_ROWID 3 /* "DB.TABLE._rowid_" for * expansion of rowid */ +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 */ +}; /* ** An instance of this structure can hold a simple list of identifiers, ** such as the list "a,b,c" in the following statements: ** @@ -19516,152 +16226,109 @@ ** INSERT INTO t(a,b,c) ... ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { - int nId; /* Number of identifiers on the list */ struct IdList_item { char *zName; /* Name of the identifier */ - } a[1]; -}; - -/* -** Allowed values for IdList.eType, which determines which value of the a.u4 -** is valid. -*/ -#define EU4_NONE 0 /* Does not use IdList.a.u4 */ -#define EU4_IDX 1 /* Uses IdList.a.u4.idx */ -#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */ - -/* -** Details of the implementation of a subquery. -*/ -struct Subquery { - Select *pSelect; /* A SELECT statement used in place of a table name */ - int addrFillSub; /* Address of subroutine to initialize a subquery */ - int regReturn; /* Register holding return address of addrFillSub */ - int regResult; /* Registers holding results of a co-routine */ -}; - -/* -** The SrcItem object represents a single term in the FROM clause of a query. -** The SrcList object is mostly an array of SrcItems. + int idx; /* Index in some Table.aCol[] of a column named zName */ + } *a; + int nId; /* Number of identifiers on the list */ +}; + +/* +** The bitmask datatype defined below is used for various optimizations. +** +** Changing this from a 64-bit to a 32-bit type limits the number of +** tables in a join to 32 instead of 64. But it also reduces the size +** of the library by 738 bytes on ix86. +*/ +#ifdef SQLITE_BITMASK_TYPE + typedef SQLITE_BITMASK_TYPE Bitmask; +#else + typedef u64 Bitmask; +#endif + +/* +** The number of bits in a Bitmask. "BMS" means "BitMask Size". +*/ +#define BMS ((int)(sizeof(Bitmask)*8)) + +/* +** A bit in a Bitmask +*/ +#define MASKBIT(n) (((Bitmask)1)<<(n)) +#define MASKBIT32(n) (((unsigned int)1)<<(n)) +#define ALLBITS ((Bitmask)-1) + +/* +** The following structure describes the FROM clause of a SELECT statement. +** Each table or subquery in the FROM clause is a separate element of +** the SrcList.a[] array. +** +** With the addition of multiple database support, the following structure +** can also be used to describe a particular table such as the table that +** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL, +** such a table must be a simple name: ID. But in SQLite, the table can +** now be identified by a database name, a dot, then the table name: ID.ID. ** ** The jointype starts out showing the join type between the current table ** and the next table on the list. The parser builds the list this way. ** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each ** jointype expresses the join between the table and the previous table. ** ** In the colUsed field, the high-order bit (bit 63) is set if the table ** contains more than 63 columns and the 64-th or later column is used. -** -** Aggressive use of "union" helps keep the size of the object small. This -** has been shown to boost performance, in addition to saving memory. -** Access to union elements is gated by the following rules which should -** always be checked, either by an if-statement or by an assert(). -** -** Field Only access if this is true -** --------------- ----------------------------------- -** u1.zIndexedBy fg.isIndexedBy -** u1.pFuncArg fg.isTabFunc -** u1.nRow !fg.isTabFunc && !fg.isIndexedBy -** -** u2.pIBIndex fg.isIndexedBy -** u2.pCteUse fg.isCte -** -** u3.pOn !fg.isUsing -** u3.pUsing fg.isUsing -** -** u4.zDatabase !fg.fixedSchema && !fg.isSubquery -** u4.pSchema fg.fixedSchema -** u4.pSubq fg.isSubquery -** -** See also the sqlite3SrcListDelete() routine for assert() statements that -** check invariants on the fields of this object, especially the flags -** inside the fg struct. -*/ -struct SrcItem { - char *zName; /* Name of the table */ - char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ - Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */ - struct { - u8 jointype; /* Type of join between this table and the previous */ - unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ - unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ - unsigned isSubquery :1; /* True if this term is a subquery */ - unsigned isTabFunc :1; /* True if table-valued-function syntax */ - unsigned isCorrelated :1; /* True if sub-query is correlated */ - unsigned isMaterialized:1; /* This is a materialized view */ - unsigned viaCoroutine :1; /* Implemented as a co-routine */ - unsigned isRecursive :1; /* True for recursive reference in WITH */ - unsigned fromDDL :1; /* Comes from sqlite_schema */ - unsigned isCte :1; /* This is a CTE */ - unsigned notCte :1; /* This item may not match a CTE */ - unsigned isUsing :1; /* u3.pUsing is valid */ - unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ - unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ - unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ - unsigned rowidUsed :1; /* The ROWID of this table is referenced */ - unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */ - unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */ - } fg; - int iCursor; /* The VDBE cursor number used to access this table */ - Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */ - union { - char *zIndexedBy; /* Identifier from "INDEXED BY " clause */ - ExprList *pFuncArg; /* Arguments to table-valued-function */ - u32 nRow; /* Number of rows in a VALUES clause */ - } u1; - union { - Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ - CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */ - } u2; - union { - Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */ - IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */ - } u3; - union { - Schema *pSchema; /* Schema to which this item is fixed */ - char *zDatabase; /* Name of database holding this table */ - Subquery *pSubq; /* Description of a subquery */ - } u4; -}; - -/* -** The OnOrUsing object represents either an ON clause or a USING clause. -** It can never be both at the same time, but it can be neither. -*/ -struct OnOrUsing { - Expr *pOn; /* The ON clause of a join */ - IdList *pUsing; /* The USING clause of a join */ -}; - -/* -** This object represents one or more tables that are the source of -** content for an SQL statement. For example, a single SrcList object -** is used to hold the FROM clause of a SELECT statement. SrcList also -** represents the target tables for DELETE, INSERT, and UPDATE statements. -** */ struct SrcList { int nSrc; /* Number of tables or subqueries in the FROM clause */ u32 nAlloc; /* Number of entries allocated in a[] below */ - SrcItem a[1]; /* One entry for each identifier on the list */ + struct SrcList_item { + Schema *pSchema; /* Schema to which this item is fixed */ + char *zDatabase; /* Name of database holding this table */ + char *zName; /* Name of the table */ + char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ + Table *pTab; /* An SQL table corresponding to zName */ + Select *pSelect; /* A SELECT statement used in place of a table name */ + int addrFillSub; /* Address of subroutine to manifest a subquery */ + int regReturn; /* Register holding return address of addrFillSub */ + int regResult; /* Registers holding results of a co-routine */ + struct { + u8 jointype; /* Type of join between this table and the previous */ + unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ + unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ + unsigned isTabFunc :1; /* True if table-valued-function syntax */ + unsigned isCorrelated :1; /* True if sub-query is correlated */ + unsigned viaCoroutine :1; /* Implemented as a co-routine */ + unsigned isRecursive :1; /* True for recursive reference in WITH */ + } fg; +#ifndef SQLITE_OMIT_EXPLAIN + u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ +#endif + int iCursor; /* The VDBE cursor number used to access this table */ + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ + Bitmask colUsed; /* Bit N (1<" clause */ + ExprList *pFuncArg; /* Arguments to table-valued-function */ + } u1; + Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ + } a[1]; /* One entry for each identifier on the list */ }; /* ** Permitted values of the SrcList.a.jointype field */ -#define JT_INNER 0x01 /* Any kind of inner or cross join */ -#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */ -#define JT_NATURAL 0x04 /* True for a "natural" join */ -#define JT_LEFT 0x08 /* Left outer join */ -#define JT_RIGHT 0x10 /* Right outer join */ -#define JT_OUTER 0x20 /* The "OUTER" keyword is present */ -#define JT_LTORJ 0x40 /* One of the LEFT operands of a RIGHT JOIN - ** Mnemonic: Left Table Of Right Join */ -#define JT_ERROR 0x80 /* unknown or unsupported join type */ +#define JT_INNER 0x0001 /* Any kind of inner or cross join */ +#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */ +#define JT_NATURAL 0x0004 /* True for a "natural" join */ +#define JT_LEFT 0x0008 /* Left outer join */ +#define JT_RIGHT 0x0010 /* Right outer join */ +#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */ +#define JT_ERROR 0x0040 /* unknown or unsupported join type */ + /* ** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() ** and the WhereInfo.wctrlFlags member. ** @@ -19678,14 +16345,14 @@ ** the OR optimization */ #define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */ #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */ -#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */ +#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */ #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */ -#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */ -#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */ +#define WHERE_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 */ /* Allowed return values from sqlite3WhereIsDistinct() */ @@ -19716,100 +16383,44 @@ ** subqueries looking for a match. */ struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ - union { - ExprList *pEList; /* Optional list of result-set columns */ - AggInfo *pAggInfo; /* Information about aggregates at this level */ - Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */ - int iBaseReg; /* For TK_REGISTER when parsing RETURNING */ - } uNC; + ExprList *pEList; /* Optional list of result-set columns */ + AggInfo *pAggInfo; /* Information about aggregates at this level */ NameContext *pNext; /* Next outer name context. NULL for outermost */ int nRef; /* Number of names resolved by this context */ - int nNcErr; /* Number of errors encountered while resolving names */ - int ncFlags; /* Zero or more NC_* flags defined below */ - u32 nNestedSelect; /* Number of nested selects using this NC */ - Select *pWinSelect; /* SELECT statement for any window functions */ + int nErr; /* Number of errors encountered while resolving names */ + u16 ncFlags; /* Zero or more NC_* flags defined below */ }; /* ** Allowed values for the NameContext, ncFlags field. ** ** Value constraints (all checked via assert()): -** NC_HasAgg == SF_HasAgg == EP_Agg -** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX -** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER -** NC_HasWin == EP_Win -** -*/ -#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */ -#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */ -#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */ -#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */ -#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */ -#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */ -#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */ -#define NC_Subquery 0x000040 /* A subquery has been seen */ -#define NC_UEList 0x000080 /* True if uNC.pEList is used */ -#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */ -#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */ -#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */ -#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */ -/* 0x002000 // available for reuse */ -#define NC_AllowWin 0x004000 /* Window functions are allowed here */ -#define NC_HasWin 0x008000 /* One or more window functions seen */ -#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */ -#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */ -#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */ -#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */ -#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */ -#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */ - -/* -** An instance of the following object describes a single ON CONFLICT -** clause in an upsert. -** -** The pUpsertTarget field is only set if the ON CONFLICT clause includes -** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the -** conflict-target clause.) The pUpsertTargetWhere is the optional -** WHERE clause used to identify partial unique indexes. -** -** pUpsertSet is the list of column=expr terms of the UPDATE statement. -** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The -** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the -** WHERE clause is omitted. -*/ -struct Upsert { - ExprList *pUpsertTarget; /* Optional description of conflict target */ - Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */ - ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */ - Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */ - Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */ - u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */ - u8 isDup; /* True if 2nd or later with same pUpsertIdx */ - /* Above this point is the parse tree for the ON CONFLICT clauses. - ** The next group of fields stores intermediate data. */ - void *pToFree; /* Free memory when deleting the Upsert object */ - /* All fields above are owned by the Upsert object and must be freed - ** when the Upsert is destroyed. The fields below are used to transfer - ** information from the INSERT processing down into the UPDATE processing - ** while generating code. The fields below are owned by the INSERT - ** statement and will be freed by INSERT processing. */ - Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */ - SrcList *pUpsertSrc; /* Table to be updated */ - int regData; /* First register holding array of VALUES */ - int iDataCur; /* Index of the data cursor */ - int iIdxCur; /* Index of the first index cursor */ -}; +** NC_HasAgg == SF_HasAgg +** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX +** +*/ +#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ +#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */ +#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */ +#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */ +#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */ +#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ +#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ +#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** -** See the header comment on the computeLimitRegisters() routine for a -** detailed description of the meaning of the iLimit and iOffset fields. +** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. +** If there is a LIMIT clause, the parser sets nLimit to the value of the +** limit and nOffset to the value of the offset (or 0 if there is not +** offset). But later on, nLimit and nOffset become the memory locations +** in the VDBE that record the limit and offset counters. ** ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. ** These addresses must be stored so that we can go back and fill in ** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor ** the number of columns in P2 can be computed at the same time @@ -19818,77 +16429,59 @@ ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences ** for the result set. The KeyInfo for addrOpenEphm[2] contains collating ** sequences for the ORDER BY clause. */ struct Select { + ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ LogEst nSelectRow; /* Estimated number of result rows */ u32 selFlags; /* Various SF_* values */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ - u32 selId; /* Unique identifier number for this SELECT */ +#if SELECTTRACE_ENABLED + char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ +#endif int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ - ExprList *pEList; /* The fields of the result */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ 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. */ -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin; /* List of window functions */ - Window *pWinDefn; /* List of named window definitions */ -#endif }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". ** ** Value constraints (all checked via assert()) -** SF_HasAgg == NC_HasAgg -** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX -** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER -** SF_FixedLimit == WHERE_USE_LIMIT +** SF_HasAgg == NC_HasAgg +** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX +** SF_FixedLimit == WHERE_USE_LIMIT */ -#define SF_Distinct 0x0000001 /* Output should be DISTINCT */ -#define SF_All 0x0000002 /* Includes the ALL keyword */ -#define SF_Resolved 0x0000004 /* Identifiers have been resolved */ -#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */ -#define SF_HasAgg 0x0000010 /* Contains aggregate functions */ -#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */ -#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */ -#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */ -#define SF_Compound 0x0000100 /* Part of a compound query */ -#define SF_Values 0x0000200 /* Synthesized from VALUES clause */ -#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */ -#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */ -#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */ -#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */ -#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */ -#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */ -#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ -#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ -#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ -#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ -#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ -#define SF_View 0x0200000 /* SELECT statement is a view */ -#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ -#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ -#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */ -#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ -#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ -#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ -#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ -#define SF_Correlated 0x20000000 /* True if references the outer context */ - -/* True if SrcItem X is a subquery that has SF_NestedFrom */ -#define IsNestedFrom(X) \ - ((X)->fg.isSubquery && \ - ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0) +#define SF_Distinct 0x00001 /* Output should be DISTINCT */ +#define SF_All 0x00002 /* Includes the ALL keyword */ +#define SF_Resolved 0x00004 /* Identifiers have been resolved */ +#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */ +#define SF_HasAgg 0x00010 /* Contains aggregate functions */ +#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */ +#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */ +#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */ +#define SF_Compound 0x00100 /* Part of a compound query */ +#define SF_Values 0x00200 /* Synthesized from VALUES clause */ +#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */ +#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */ +#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */ +#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */ +#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */ +#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */ +#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ +#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ + /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". @@ -19902,10 +16495,13 @@ ** set is not empty. ** ** SRT_Discard Throw the results away. This is used by SELECT ** statements within triggers whose only purpose is ** the side-effects of functions. +** +** All of the above are free to ignore their ORDER BY clause. Those that +** follow must honor the ORDER BY clause. ** ** SRT_Output Generate a row of output (using the OP_ResultRow ** opcode) for each row in the result set. ** ** SRT_Mem Only valid if the result is a single column. @@ -19914,15 +16510,11 @@ ** of the query. This destination implies "LIMIT 1". ** ** SRT_Set The result must be a single column. Store each ** row of result as the key in table pDest->iSDParm. ** Apply the affinity pDest->affSdst before storing -** results. if pDest->iSDParm2 is positive, then it is -** a register holding a Bloom filter for the IN operator -** that should be populated in addition to the -** pDest->iSDParm table. This SRT is used to -** implement "IN (SELECT ...)". +** results. Used to implement "IN (SELECT ...)". ** ** SRT_EphemTab Create an temporary table pDest->iSDParm and store ** the result there. The cursor is left open after ** returning. This is like SRT_Table except that ** this destination uses OP_OpenEphemeral to create @@ -19950,55 +16542,40 @@ ** are distinct. ** ** SRT_DistQueue Store results in priority queue pDest->iSDParm only if ** the same record has never been stored before. The ** index at pDest->iSDParm+1 hold all prior stores. -** -** SRT_Upfrom Store results in the temporary table already opened by -** pDest->iSDParm. If (pDest->iSDParm<0), then the temp -** table is an intkey table - in this case the first -** column returned by the SELECT is used as the integer -** key. If (pDest->iSDParm>0), then the table is an index -** table. (pDest->iSDParm) is the number of key columns in -** each index record in this case. */ #define SRT_Union 1 /* Store result as keys in an index */ #define SRT_Except 2 /* Remove result from a UNION index */ #define SRT_Exists 3 /* Store 1 if the result is not empty */ #define SRT_Discard 4 /* Do not save the results anywhere */ -#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */ -#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */ - -/* The DISTINCT clause is ignored for all of the above. Not that -** IgnorableDistinct() implies IgnorableOrderby() */ -#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue) - +#define SRT_Fifo 5 /* Store result as data with an automatic rowid */ +#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */ #define SRT_Queue 7 /* Store result in an queue */ -#define SRT_Fifo 8 /* Store result as data with an automatic rowid */ +#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */ /* The ORDER BY clause is ignored for all of the above */ -#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo) +#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue) #define SRT_Output 9 /* Output each row of result */ #define SRT_Mem 10 /* Store result in a memory cell */ #define SRT_Set 11 /* Store results as keys in an index */ #define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ #define SRT_Coroutine 13 /* Generate a single row of result */ #define SRT_Table 14 /* Store result as data with an automatic rowid */ -#define SRT_Upfrom 15 /* Store result as data with rowid */ /* ** An instance of this object describes where to put of the results of ** a SELECT statement. */ struct SelectDest { - u8 eDest; /* How to dispose of the results. One of SRT_* above. */ + u8 eDest; /* How to dispose of the results. On of SRT_* above. */ int iSDParm; /* A parameter used by the eDest disposal method */ - int iSDParm2; /* A second parameter for the eDest disposal method */ int iSdst; /* Base register where results are written */ int nSdst; /* Number of registers allocated */ - char *zAffSdst; /* Affinity used for SRT_Set */ + char *zAffSdst; /* Affinity used when eDest==SRT_Set */ ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ }; /* ** During code generation of statements that do inserts into AUTOINCREMENT @@ -20014,10 +16591,17 @@ Table *pTab; /* Table this info block refers to */ int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ int regCtr; /* Memory register holding the rowid counter */ }; +/* +** Size of the column cache +*/ +#ifndef SQLITE_N_COLCACHE +# define SQLITE_N_COLCACHE 10 +#endif + /* ** At least one instance of the following structure is created for each ** trigger that may be fired while parsing an INSERT, UPDATE or DELETE ** statement. All such objects are stored in the linked list headed at ** Parse.pTriggerPrg and deleted once statement compilation has been @@ -20053,49 +16637,15 @@ # define DbMaskAllZero(M) sqlite3DbMaskAllZero(M) # define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0) #else typedef unsigned int yDbMask; # define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0) -# define DbMaskZero(M) ((M)=0) -# define DbMaskSet(M,I) ((M)|=(((yDbMask)1)<<(I))) -# define DbMaskAllZero(M) ((M)==0) -# define DbMaskNonZero(M) ((M)!=0) -#endif - -/* -** For each index X that has as one of its arguments either an expression -** or the name of a virtual generated column, and if X is in scope such that -** the value of the expression can simply be read from the index, then -** there is an instance of this object on the Parse.pIdxExpr list. -** -** During code generation, while generating code to evaluate expressions, -** this list is consulted and if a matching expression is found, the value -** is read from the index rather than being recomputed. -*/ -struct IndexedExpr { - Expr *pExpr; /* The expression contained in the index */ - int iDataCur; /* The data cursor associated with the index */ - int iIdxCur; /* The index cursor */ - int iIdxCol; /* The index column that contains value of pExpr */ - u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ - u8 aff; /* Affinity of the pExpr expression */ - IndexedExpr *pIENext; /* Next in a list of all indexed expressions */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - const char *zIdxName; /* Name of index, used only for bytecode comments */ -#endif -}; - -/* -** An instance of the ParseCleanup object specifies an operation that -** should be performed after parsing to deallocation resources obtained -** during the parse and which are no longer needed. -*/ -struct ParseCleanup { - ParseCleanup *pNext; /* Next cleanup task */ - void *pPtr; /* Pointer to object to deallocate */ - void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */ -}; +# define DbMaskZero(M) (M)=0 +# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I)) +# define DbMaskAllZero(M) (M)==0 +# define DbMaskNonZero(M) (M)!=0 +#endif /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. @@ -20123,74 +16673,66 @@ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ - u8 prepFlags; /* SQLITE_PREPARE_* flags */ - u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ - u8 bHasWith; /* True if statement contains WITH */ - u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) - u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ -#endif -#ifdef SQLITE_DEBUG - u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */ -#endif + u8 nColCache; /* Number of entries in aColCache[] */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ + int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ - int iSelfTab; /* Table associated with an index on expr, or negative - ** of the base register during check-constraint eval */ - int nLabel; /* The *negative* of the number of labels used */ - int nLabelAlloc; /* Number of slots in aLabel */ + int ckBase; /* Base register of data during check constraints */ + int iSelfTab; /* Table of an index whose exprs are being coded */ + int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ + int iCacheCnt; /* Counter used to generate aColCache[].lru values */ + int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ ExprList *pConstExpr;/* Constant expressions */ - IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */ - IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ - int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ +#if SELECTTRACE_ENABLED + int nSelect; /* Number of SELECT statements seen */ + int nSelectIndent; /* How far to indent SELECTTRACE() output */ #endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ - TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ - ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ - union { - int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ - Returning *pReturning; /* The RETURNING clause */ - } u1; + int addrCrTab; /* Address of OP_CreateTable 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 */ - LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ - u8 bReturning; /* Coding a RETURNING trigger */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ /************************************************************************** ** Fields above must be initialized to zero. The fields that follow, ** down to the beginning of the recursive section, do not need to be ** initialized as they will be set before being used. The boundary is - ** determined by offsetof(Parse,aTempReg). + ** determined by offsetof(Parse,aColCache). **************************************************************************/ + struct yColCache { + int iTable; /* Table cursor number */ + i16 iColumn; /* Table column number */ + u8 tempReg; /* iReg is a temp register that needs to be freed */ + int iLevel; /* Nesting level */ + int iReg; /* Reg with value of this column. 0 means none. */ + int lru; /* Least recently used entry has the smallest value */ + } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ int aTempReg[8]; /* Holding area for temporary registers */ - Parse *pOuterParse; /* Outer Parse object when nested */ Token sNameToken; /* Token with unqualified schema object name */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined @@ -20200,49 +16742,39 @@ Token sLastToken; /* The last token parsed */ ynVar nVar; /* Number of '?' variables seen in the SQL so far */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ u8 explain; /* True if the EXPLAIN flag is found on the query */ - u8 eParseMode; /* PARSE_MODE_XXX constant */ #ifndef SQLITE_OMIT_VIRTUALTABLE + u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ #endif int nHeight; /* Expression tree height of current sub-select */ #ifndef SQLITE_OMIT_EXPLAIN - int addrExplain; /* Address of current OP_Explain opcode */ + int iSelectId; /* ID of current select for EXPLAIN output */ + int iNextSelectId; /* Next available select ID for EXPLAIN output */ #endif VList *pVList; /* Mapping between variable names and numbers */ Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ - Index *pNewIndex; /* An index being constructed by CREATE INDEX. - ** Also used to hold redundant UNIQUE constraints - ** during a RENAME COLUMN */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif + Table *pZombieTab; /* List of Table objects to delete after code gen */ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ -#ifndef SQLITE_OMIT_ALTERTABLE - RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ -#endif + With *pWithToFree; /* Free this WITH object at the end of the parse */ }; -/* Allowed values for Parse.eParseMode -*/ -#define PARSE_MODE_NORMAL 0 -#define PARSE_MODE_DECLARE_VTAB 1 -#define PARSE_MODE_RENAME 2 -#define PARSE_MODE_UNMAP 3 - /* ** Sizes and pointers of various parts of the Parse object. */ -#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg)) -#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/ +#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ /* @@ -20249,23 +16781,11 @@ ** Return true if currently inside an sqlite3_declare_vtab() call. */ #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 #else - #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB) -#endif - -#if defined(SQLITE_OMIT_ALTERTABLE) - #define IN_RENAME_OBJECT 0 -#else - #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME) -#endif - -#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE) - #define IN_SPECIAL_PARSE 0 -#else - #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL) + #define IN_DECLARE_VTAB (pParse->declareVtab) #endif /* ** An instance of the following structure can be declared on a stack and used ** to save the Parse.zAuthContext value so that it can be restored later. @@ -20287,51 +16807,46 @@ ** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION ** OPFLAG_AUXDELETE == BTREE_AUXDELETE */ #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ /* Also used in P2 (not P5) of OP_Delete */ -#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */ #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ #define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ -#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ #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/Insert: save cursor pos */ #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ -#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */ -#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */ /* -** Each trigger present in the database schema is stored as an instance of -** struct Trigger. -** -** Pointers to instances of struct Trigger are stored in two ways. -** 1. In the "trigHash" hash table (part of the sqlite3* that represents the -** database). This allows Trigger structures to be retrieved by name. -** 2. All triggers associated with a single table form a linked list, using the -** pNext member of struct Trigger. A pointer to the first element of the -** linked list is stored as the "pTrigger" member of the associated -** struct Table. -** -** The "step_list" member points to the first element of a linked list -** containing the SQL statements specified as the trigger program. -*/ + * Each trigger present in the database schema is stored as an instance of + * struct Trigger. + * + * Pointers to instances of struct Trigger are stored in two ways. + * 1. In the "trigHash" hash table (part of the sqlite3* that represents the + * database). This allows Trigger structures to be retrieved by name. + * 2. All triggers associated with a single table form a linked list, using the + * pNext member of struct Trigger. A pointer to the first element of the + * linked list is stored as the "pTrigger" member of the associated + * struct Table. + * + * The "step_list" member points to the first element of a linked list + * containing the SQL statements specified as the trigger program. + */ struct Trigger { char *zName; /* The name of the trigger */ char *table; /* The table or view to which the trigger applies */ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ - u8 bReturning; /* This trigger implements a RETURNING clause */ Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF trigger, the is stored here */ Schema *pSchema; /* Schema containing the trigger */ Schema *pTabSchema; /* Schema containing the table */ @@ -20348,124 +16863,97 @@ */ #define TRIGGER_BEFORE 1 #define TRIGGER_AFTER 2 /* -** An instance of struct TriggerStep is used to store a single SQL statement -** that is a part of a trigger-program. -** -** Instances of struct TriggerStep are stored in a singly linked list (linked -** using the "pNext" member) referenced by the "step_list" member of the -** associated struct Trigger instance. The first element of the linked list is -** the first step of the trigger-program. -** -** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or -** "SELECT" statement. The meanings of the other members is determined by the -** value of "op" as follows: -** -** (op == TK_INSERT) -** orconf -> stores the ON CONFLICT algorithm -** pSelect -> The content to be inserted - either a SELECT statement or -** a VALUES clause. -** zTarget -> Dequoted name of the table to insert into. -** pIdList -> If this is an INSERT INTO ... () VALUES ... -** statement, then this stores the column-names to be -** inserted into. -** pUpsert -> The ON CONFLICT clauses for an Upsert -** -** (op == TK_DELETE) -** zTarget -> Dequoted name of the table to delete from. -** pWhere -> The WHERE clause of the DELETE statement if one is specified. -** Otherwise NULL. -** -** (op == TK_UPDATE) -** zTarget -> Dequoted name of the table to update. -** pWhere -> The WHERE clause of the UPDATE statement if one is specified. -** Otherwise NULL. -** pExprList -> A list of the columns to update and the expressions to update -** them to. See sqlite3Update() documentation of "pChanges" -** argument. -** -** (op == TK_SELECT) -** pSelect -> The SELECT statement -** -** (op == TK_RETURNING) -** pExprList -> The list of expressions that follow the RETURNING keyword. -** -*/ + * An instance of struct TriggerStep is used to store a single SQL statement + * that is a part of a trigger-program. + * + * Instances of struct TriggerStep are stored in a singly linked list (linked + * using the "pNext" member) referenced by the "step_list" member of the + * associated struct Trigger instance. The first element of the linked list is + * the first step of the trigger-program. + * + * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or + * "SELECT" statement. The meanings of the other members is determined by the + * value of "op" as follows: + * + * (op == TK_INSERT) + * orconf -> stores the ON CONFLICT algorithm + * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then + * this stores a pointer to the SELECT statement. Otherwise NULL. + * zTarget -> Dequoted name of the table to insert into. + * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then + * this stores values to be inserted. Otherwise NULL. + * pIdList -> If this is an INSERT INTO ... () VALUES ... + * statement, then this stores the column-names to be + * inserted into. + * + * (op == TK_DELETE) + * zTarget -> Dequoted name of the table to delete from. + * pWhere -> The WHERE clause of the DELETE statement if one is specified. + * Otherwise NULL. + * + * (op == TK_UPDATE) + * zTarget -> Dequoted name of the table to update. + * pWhere -> The WHERE clause of the UPDATE statement if one is specified. + * Otherwise NULL. + * pExprList -> A list of the columns to update and the expressions to update + * them to. See sqlite3Update() documentation of "pChanges" + * argument. + * + */ struct TriggerStep { - u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT, - ** or TK_RETURNING */ + u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ - SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ - ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */ + ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ - Upsert *pUpsert; /* Upsert clauses on an 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 */ }; /* -** Information about a RETURNING clause +** The following structure contains information used by the sqliteFix... +** routines as they walk the parse tree to make database references +** explicit. */ -struct Returning { - Parse *pParse; /* The parse that includes the RETURNING clause */ - ExprList *pReturnEL; /* List of expressions to return */ - Trigger retTrig; /* The transient trigger that implements RETURNING */ - TriggerStep retTStep; /* The trigger step */ - int iRetCur; /* Transient table holding RETURNING results */ - int nRetCol; /* Number of in pReturnEL after expansion */ - int iRetReg; /* Register array for holding a row of RETURNING */ - char zName[40]; /* Name of trigger: "sqlite_returning_%p" */ +typedef struct DbFixer DbFixer; +struct DbFixer { + Parse *pParse; /* The parsing context. Error messages written here */ + Schema *pSchema; /* Fix items to this schema */ + int bVarOnly; /* Check for variable references only */ + const char *zDb; /* Make sure all objects are contained in this database */ + const char *zType; /* Type of the container - used for error messages */ + const Token *pName; /* Name of the container - used for error messages */ }; /* -** An object used to accumulate the text of a string where we +** An objected used to accumulate the text of a string where we ** do not necessarily know how big the string will be in the end. */ -struct sqlite3_str { +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; /* SQLITE_NOMEM or SQLITE_TOOBIG */ + u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ u8 printfFlags; /* SQLITE_PRINTF flags below */ }; +#define STRACCUM_NOMEM 1 +#define STRACCUM_TOOBIG 2 #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ -#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */ +#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) -/* -** The following object is the header for an "RCStr" or "reference-counted -** string". An RCStr is passed around and used like any other char* -** that has been dynamically allocated. The important interface -** differences: -** -** 1. RCStr strings are reference counted. They are deallocated -** when the reference count reaches zero. -** -** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than -** sqlite3_free() -** -** 3. Make a (read-only) copy of a read-only RCStr string using -** sqlite3RCStrRef(). -** -** "String" is in the name, but an RCStr object can also be used to hold -** binary data. -*/ -struct RCStr { - u64 nRCRef; /* Number of references */ - /* Total structure size should be a multiple of 8 bytes for alignment */ -}; /* ** A pointer to this structure is used to communicate information ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. */ @@ -20472,55 +16960,23 @@ typedef struct { sqlite3 *db; /* The database being initialized */ char **pzErrMsg; /* Error message stored here */ int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ int rc; /* Result code stored here */ - u32 mInitFlags; /* Flags controlling error messages */ - u32 nInitRow; /* Number of rows processed */ - Pgno mxPage; /* Maximum page number. 0 for no limit. */ } InitData; -/* -** Allowed values for mInitFlags -*/ -#define INITFLAG_AlterMask 0x0003 /* Types of ALTER */ -#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */ -#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */ -#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */ - -/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled -** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning -** parameters are for temporary use during development, to help find -** optimal values for parameters in the query planner. The should not -** be used on trunk check-ins. They are a temporary mechanism available -** for transient development builds only. -** -** Tuning parameters are numbered starting with 1. -*/ -#define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */ -#ifdef SQLITE_DEBUG -# define Tuning(X) (sqlite3Config.aTune[(X)-1]) -#else -# define Tuning(X) 0 -#endif - /* ** Structure containing global configuration data for the SQLite library. ** ** This structure also contains some state information. */ struct Sqlite3Config { int bMemstat; /* True to enable memory status */ - u8 bCoreMutex; /* True to enable core mutexing */ - u8 bFullMutex; /* True to enable full mutexing */ - u8 bOpenUri; /* True to interpret filenames as URIs */ - u8 bUseCis; /* Use covering indices for full-scans */ - u8 bSmallMalloc; /* Avoid large memory allocations if true */ - u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ -#ifdef SQLITE_DEBUG - u8 bJsonSelfcheck; /* Double-check JSON parsing */ -#endif + int bCoreMutex; /* True to enable core mutexing */ + int bFullMutex; /* True to enable full mutexing */ + int bOpenUri; /* True to interpret filenames as URIs */ + int bUseCis; /* Use covering indices for full-scans */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ int nStmtSpill; /* Stmt-journal spill-to-disk threshold */ @@ -20530,10 +16986,13 @@ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ 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[] */ int mxParserStack; /* maximum depth of the parser stack */ int sharedCacheEnabled; /* true if shared-cache mode enabled */ @@ -20555,33 +17014,18 @@ #endif #ifdef SQLITE_VDBE_COVERAGE /* The following callback (if not NULL) is invoked on every VDBE branch ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. */ - void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */ + void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ void *pVdbeBranchArg; /* 1st argument */ #endif -#ifndef SQLITE_OMIT_DESERIALIZE - sqlite3_int64 mxMemdbSize; /* Default max memdb size */ -#endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW - ** feature is disabled. 0 if rowids can - ** occur in views. */ -#endif int bLocaltimeFault; /* True to fail localtime() calls */ - int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ int iOnceResetThreshold; /* When to reset OP_Once counters */ - u32 szSorterRef; /* Min size in bytes to use sorter-refs */ - unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ - /* vvvv--- must be last ---vvv */ -#ifdef SQLITE_DEBUG - sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ -#endif }; /* ** This macro is used inside of assert() statements to indicate that ** the assert is only valid on a well-formed database. Instead of: @@ -20607,140 +17051,59 @@ Parse *pParse; /* Parser context. */ int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ int walkerDepth; /* Number of subqueries */ - u16 eCode; /* A small processing code */ - u16 mWFlags; /* Use-dependent flags */ + 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() */ - struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */ 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 */ - Select *pSelect; /* HAVING to WHERE clause ctx */ - struct WindowRewrite *pRewrite; /* Window rewrite context */ - struct WhereConst *pConst; /* WHERE clause constants */ - struct RenameCtx *pRename; /* RENAME COLUMN context */ - struct Table *pTab; /* Table of generated column */ - struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */ - SrcItem *pSrcItem; /* A single FROM clause item */ - DbFixer *pFix; /* See sqlite3FixSelect() */ - Mem *aMem; /* See sqlite3BtreeCursorHint() */ + struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */ } u; }; -/* -** The following structure contains information used by the sqliteFix... -** routines as they walk the parse tree to make database references -** explicit. -*/ -struct DbFixer { - Parse *pParse; /* The parsing context. Error messages written here */ - Walker w; /* Walker object */ - Schema *pSchema; /* Fix items to this schema */ - u8 bTemp; /* True for TEMP schema entries */ - const char *zDb; /* Make sure all objects are contained in this database */ - const char *zType; /* Type of the container - used for error messages */ - const Token *pName; /* Name of the container - used for error messages */ -}; - /* Forward declarations */ SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*); -SQLITE_PRIVATE int sqlite3WalkExprNN(Walker*, Expr*); SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); -SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); -SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*); -SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*); -SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker*,Select*); - #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); #endif -#ifndef SQLITE_OMIT_CTE -SQLITE_PRIVATE void sqlite3SelectPopWith(Walker*, Select*); -#else -# define sqlite3SelectPopWith 0 -#endif - /* ** Return code from the parse-tree walking primitives and their ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ #define WRC_Abort 2 /* Abandon the tree walk */ /* -** A single common table expression -*/ -struct Cte { - char *zName; /* Name of this CTE */ - ExprList *pCols; /* List of explicit column names, or NULL */ - Select *pSelect; /* The definition of this CTE */ - const char *zCteErr; /* Error message for circular references */ - CteUse *pUse; /* Usage information for this CTE */ - u8 eM10d; /* The MATERIALIZED flag */ -}; - -/* -** Allowed values for the materialized flag (eM10d): -*/ -#define M10d_Yes 0 /* AS MATERIALIZED */ -#define M10d_Any 1 /* Not specified. Query planner's choice */ -#define M10d_No 2 /* AS NOT MATERIALIZED */ - -/* -** An instance of the With object represents a WITH clause containing -** one or more CTEs (common table expressions). +** An instance of this structure represents a set of one or more CTEs +** (common table expressions) created by a single WITH clause. */ struct With { - int nCte; /* Number of CTEs in the WITH clause */ - int bView; /* Belongs to the outermost Select of a view */ - With *pOuter; /* Containing WITH clause, or NULL */ - Cte a[1]; /* For each CTE in the WITH clause.... */ -}; - -/* -** The Cte object is not guaranteed to persist for the entire duration -** of code generation. (The query flattener or other parser tree -** edits might delete it.) The following object records information -** about each Common Table Expression that must be preserved for the -** duration of the parse. -** -** The CteUse objects are freed using sqlite3ParserAddCleanup() rather -** than sqlite3SelectDelete(), which is what enables them to persist -** until the end of code generation. -*/ -struct CteUse { - int nUse; /* Number of users of this CTE */ - int addrM9e; /* Start of subroutine to compute materialization */ - int regRtn; /* Return address register for addrM9e subroutine */ - int iCur; /* Ephemeral table holding the materialization */ - LogEst nRowEst; /* Estimated number of rows in the table */ - u8 eM10d; /* The MATERIALIZED flag */ -}; - - -/* Client data associated with sqlite3_set_clientdata() and -** sqlite3_get_clientdata(). -*/ -struct DbClientData { - DbClientData *pNext; /* Next in a linked list */ - void *pData; /* The data */ - void (*xDestructor)(void*); /* Destructor. Might be NULL */ - char zName[1]; /* Name of this client data. MUST BE LAST */ + int nCte; /* Number of CTEs in the WITH clause */ + With *pOuter; /* Containing WITH clause, or NULL */ + struct Cte { /* For each CTE in the WITH clause.... */ + char *zName; /* Name of this CTE */ + ExprList *pCols; /* List of explicit column names, or NULL */ + Select *pSelect; /* The definition of this CTE */ + const char *zCteErr; /* Error message for circular references */ + } a[1]; }; #ifdef SQLITE_DEBUG /* ** An instance of the TreeView object is used for printing the content of @@ -20750,91 +17113,10 @@ int iLevel; /* Which level of the tree we are on */ u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */ }; #endif /* SQLITE_DEBUG */ -/* -** This object is used in various ways, most (but not all) related to window -** functions. -** -** (1) A single instance of this structure is attached to the -** the Expr.y.pWin field for each window function in an expression tree. -** This object holds the information contained in the OVER clause, -** plus additional fields used during code generation. -** -** (2) All window functions in a single SELECT form a linked-list -** attached to Select.pWin. The Window.pFunc and Window.pExpr -** fields point back to the expression that is the window function. -** -** (3) The terms of the WINDOW clause of a SELECT are instances of this -** object on a linked list attached to Select.pWinDefn. -** -** (4) For an aggregate function with a FILTER clause, an instance -** of this object is stored in Expr.y.pWin with eFrmType set to -** TK_FILTER. In this case the only field used is Window.pFilter. -** -** The uses (1) and (2) are really the same Window object that just happens -** to be accessible in two different ways. Use case (3) are separate objects. -*/ -struct Window { - char *zName; /* Name of window (may be NULL) */ - char *zBase; /* Name of base window for chaining (may be NULL) */ - ExprList *pPartition; /* PARTITION BY clause */ - ExprList *pOrderBy; /* ORDER BY clause */ - u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */ - u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ - u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ - u8 bImplicitFrame; /* True if frame was implicitly specified */ - u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */ - Expr *pStart; /* Expression for " PRECEDING" */ - Expr *pEnd; /* Expression for " FOLLOWING" */ - Window **ppThis; /* Pointer to this object in Select.pWin list */ - Window *pNextWin; /* Next window function belonging to this SELECT */ - Expr *pFilter; /* The FILTER expression */ - FuncDef *pWFunc; /* The function */ - int iEphCsr; /* Partition buffer or Peer buffer */ - int regAccum; /* Accumulator */ - int regResult; /* Interim result */ - int csrApp; /* Function cursor (used by min/max) */ - int regApp; /* Function register (also used by min/max) */ - int regPart; /* Array of registers for PARTITION BY values */ - Expr *pOwner; /* Expression object this window is attached to */ - int nBufferCol; /* Number of columns in buffer table */ - int iArgCol; /* Offset of first argument for this function */ - int regOne; /* Register containing constant value 1 */ - int regStartRowid; - int regEndRowid; - u8 bExprArgs; /* Defer evaluation of window function arguments - ** due to the SQLITE_SUBTYPE flag */ -}; - -SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow); -SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal); - -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*); -SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*); -SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p); -SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); -SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*); -SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin); -SQLITE_PRIVATE int sqlite3WindowCompare(const Parse*, const Window*, const Window*, int); -SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*); -SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); -SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*); -SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); -SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); -SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p); -SQLITE_PRIVATE void sqlite3WindowFunctions(void); -SQLITE_PRIVATE void sqlite3WindowChain(Parse*, Window*, Window*); -SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*); -#else -# define sqlite3WindowDelete(a,b) -# define sqlite3WindowFunctions() -# define sqlite3WindowAttach(a,b,c) -#endif - /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. */ #define SQLITE_SKIP_UTF8(zIn) { \ @@ -20848,30 +17130,26 @@ ** the same name but without the _BKPT suffix. These macros invoke ** routines that report the line-number on which the error originated ** 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); #define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3NomemError(int); SQLITE_PRIVATE int sqlite3IoerrnomemError(int); +SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); # define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__) # define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__) +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) #else # define SQLITE_NOMEM_BKPT SQLITE_NOMEM # define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM -#endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO) -SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); -# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) -#else # define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__) #endif /* ** FTS3 and FTS4 both require virtual table support @@ -20888,10 +17166,19 @@ */ #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) # define SQLITE_ENABLE_FTS3 1 #endif +/* +** The ctype.h header is needed for non-ASCII systems. It is also +** needed by FTS3 when FTS3 is included in the amalgamation. +*/ +#if !defined(SQLITE_ASCII) || \ + (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION)) +# include +#endif + /* ** The following macros mimic the standard library functions toupper(), ** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The ** sqlite versions only work for ASCII characters, regardless of locale. */ @@ -20902,32 +17189,29 @@ # define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02) # define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) # define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) # define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) # define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) -# define sqlite3JsonId1(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x42) -# define sqlite3JsonId2(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x46) #else # define sqlite3Toupper(x) toupper((unsigned char)(x)) # define sqlite3Isspace(x) isspace((unsigned char)(x)) # define sqlite3Isalnum(x) isalnum((unsigned char)(x)) # define sqlite3Isalpha(x) isalpha((unsigned char)(x)) # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) # define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') -# define sqlite3JsonId1(x) (sqlite3IsIdChar(x)&&(x)<'0') -# define sqlite3JsonId2(x) sqlite3IsIdChar(x) #endif +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_PRIVATE int sqlite3IsIdChar(u8); +#endif /* ** Internal function prototypes */ SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*); SQLITE_PRIVATE int sqlite3Strlen30(const char*); -#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff) SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*); #define sqlite3StrNICmp sqlite3_strnicmp SQLITE_PRIVATE int sqlite3MallocInit(void); SQLITE_PRIVATE void sqlite3MallocEnd(void); @@ -20936,19 +17220,19 @@ SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); 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 void sqlite3DbNNFreeNN(sqlite3*, void*); -SQLITE_PRIVATE int sqlite3MallocSize(const void*); -SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, const 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_UNTESTABLE SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); @@ -20963,18 +17247,16 @@ ** The alloca() routine never returns NULL. This will cause code paths ** that deal with sqlite3StackAlloc() failures to be unreachable. */ #ifdef SQLITE_USE_ALLOCA # define sqlite3StackAllocRaw(D,N) alloca(N) -# define sqlite3StackAllocRawNN(D,N) alloca(N) +# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N) # define sqlite3StackFree(D,P) -# define sqlite3StackFreeNN(D,P) #else # define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) -# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N) +# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N) # define sqlite3StackFree(D,P) sqlite3DbFree(D,P) -# define sqlite3StackFreeNN(D,P) sqlite3DbFreeNN(D,P) #endif /* Do not allow both MEMSYS5 and MEMSYS3 to be defined together. If they ** are, disable MEMSYS3 */ @@ -21002,33 +17284,19 @@ 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 -# define EXP754 (((u64)0x7ff)<<52) -# define MAN754 ((((u64)1)<<52)-1) -# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) -# define IsOvfl(X) (((X)&EXP754)==EXP754) SQLITE_PRIVATE int sqlite3IsNaN(double); -SQLITE_PRIVATE int sqlite3IsOverflow(double); #else -# define IsNaN(X) 0 -# define sqlite3IsNaN(X) 0 -# define sqlite3IsOVerflow(X) 0 +# define sqlite3IsNaN(X) 0 #endif /* ** An instance of the following structure holds information about SQL ** functions arguments that are the parameters to the printf() function. @@ -21037,24 +17305,12 @@ int nArg; /* Total number of arguments */ int nUsed; /* Number of arguments used so far */ sqlite3_value **apArg; /* The argument values */ }; -/* -** An instance of this object receives the decoding of a floating point -** value into an approximate decimal representation. -*/ -struct FpDecode { - char sign; /* '+' or '-' */ - char isSpecial; /* 1: Infinity 2: NaN */ - int n; /* Significant digits in the decode */ - int iDP; /* Location of the decimal point */ - char *z; /* Start of significant digits */ - char zBuf[24]; /* Storage for significant digits */ -}; - -SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int); +SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif @@ -21061,156 +17317,81 @@ #if defined(SQLITE_TEST) SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif #if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...); SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); -SQLITE_PRIVATE void sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*); -SQLITE_PRIVATE void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*); -SQLITE_PRIVATE void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8); -SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); -SQLITE_PRIVATE void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8); -#if TREETRACE_ENABLED -SQLITE_PRIVATE void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*, - const ExprList*,const Expr*, const Trigger*); -SQLITE_PRIVATE void sqlite3TreeViewInsert(const With*, const SrcList*, - const IdList*, const Select*, const ExprList*, - int, const Upsert*, const Trigger*); -SQLITE_PRIVATE void sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*, - const Expr*, int, const ExprList*, const Expr*, - const Upsert*, const Trigger*); -#endif -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8); -SQLITE_PRIVATE void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8); -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8); -SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); -#endif -SQLITE_PRIVATE void sqlite3ShowExpr(const Expr*); -SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList*); -SQLITE_PRIVATE void sqlite3ShowIdList(const IdList*); -SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList*); -SQLITE_PRIVATE void sqlite3ShowSelect(const Select*); -SQLITE_PRIVATE void sqlite3ShowWith(const With*); -SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert*); -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep*); -SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep*); -SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger*); -SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*); -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3ShowWindow(const Window*); -SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*); -#endif -#endif +#endif + SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); -SQLITE_PRIVATE void sqlite3ProgressCheck(Parse*); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); -SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); SQLITE_PRIVATE void sqlite3Dequote(char*); -SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); -SQLITE_PRIVATE void sqlite3DequoteToken(Token*); -SQLITE_PRIVATE void sqlite3DequoteNumber(Parse*, Expr*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); -SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*); +SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int); SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse*); -SQLITE_PRIVATE void sqlite3TouchRegister(Parse*,int); -#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3FirstAvailableRegister(Parse*,int); -#endif #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int); #endif SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); -SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); -SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); -SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*); -SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); +SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); +SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); -SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); -SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*); -SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); -SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int); -SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); +SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); +SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); +SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); -SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); -SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); -SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); 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*); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); -SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*); -SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*); -SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl); -SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*); SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); -SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect); SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); -SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char); -SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); -SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); +SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*); +SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*); +SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int); SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); -SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16); -#ifdef SQLITE_OMIT_GENERATED_COLUMNS -# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */ -# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */ -#else -SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16); -SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table*, i16); -#endif +SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16); SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); #if SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*); #else # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ #endif -SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token,Token); +SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*); SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); -SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*); -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); +SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); -SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*); -SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u32,Select*); -SQLITE_PRIVATE void sqlite3AddReturning(Parse*,ExprList*); +SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); -#define sqlite3CodecQueryParameters(A,B,C) 0 SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); #ifdef SQLITE_UNTESTABLE # define sqlite3FaultSim(X) SQLITE_OK #else @@ -21226,13 +17407,12 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); #ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); #endif -SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*); -SQLITE_PRIVATE void sqlite3RowSetDelete(void*); -SQLITE_PRIVATE void sqlite3RowSetClear(void*); +SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); +SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64); SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int); @@ -21247,91 +17427,79 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); #endif SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); -SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*); -SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); #ifndef SQLITE_OMIT_AUTOINCREMENT SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif -SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(Parse*, int, Table*); -#endif +SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); -SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*); +SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); -SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int); -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2); -SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*); -SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*); -SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*); -SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int); +SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); +SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, - Token*, Select*, OnOrUsing*); + Token*, Select*, Expr*, IdList*); SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *); SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*); -SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *); -SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*); +SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *); +SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*); SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); -SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*); SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**); SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Expr*, int, int, u8); 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*,ExprList*,u32,Expr*,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); -SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); -SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*); +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*,char*); +SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); #endif -SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*); -SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); -SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, - Upsert*); -SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*, - ExprList*,Select*,u16,int); +SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); +SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); +SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); -SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); -SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*); +SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*); #define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ #define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ -SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*); SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); +SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); -SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg); +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*); +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*); +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int); -#endif SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int); +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); 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 */ @@ -21340,28 +17508,25 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); #define LOCATE_VIEW 0x01 #define LOCATE_NOERR 0x02 SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); -SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char*); -SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *); +SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *); SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*); -SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*); -SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, const Token*); -SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int); -SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int); -SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int); -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,int); -SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); +SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); +SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); +SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); +SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); +SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); -SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*); +SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); #ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); #endif @@ -21371,33 +17536,29 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int); SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); -SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*); -SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); -SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); -SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*); +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 sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int); +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); #endif -SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*); +SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); -SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab); SQLITE_PRIVATE void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); -SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, - u8,u8,int,int*,int*,Upsert*); + u8,u8,int,int*,int*); #ifdef SQLITE_ENABLE_NULL_TRIM SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*); #else # define sqlite3SetMakeRecordP5(A,B) #endif @@ -21407,33 +17568,31 @@ SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); SQLITE_PRIVATE void sqlite3MayAbort(Parse*); SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8); SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*); SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*); -SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,const Expr*,int); -SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,const ExprList*,int); -SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,const SrcList*,int); -SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,const IdList*); -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int); -SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*); +SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); +SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); +SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); +SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); +#if SELECTTRACE_ENABLED +SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*); +#else +# define sqlite3SelectSetName(A,B) +#endif SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); -SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); -SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) -SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3*); -#endif SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); -SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) -SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); +SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int); #endif #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, Expr*,int, int); @@ -21445,23 +17604,18 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *, int, int, int); 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*, - const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, - Select*,u8,Upsert*, - const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*, - Expr*, u8, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, - const char*,const char*); +SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); +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*); SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); -SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*); # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) # define sqlite3IsToplevel(p) ((p)->pToplevel==0) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) @@ -21471,17 +17625,13 @@ # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) # define sqlite3TriggerList(X, Y) 0 # define sqlite3ParseToplevel(p) p # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 -# define sqlite3TriggerStepSrc(A,B) 0 #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); -SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol); -SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int); -SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int,u32); SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION SQLITE_PRIVATE void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); SQLITE_PRIVATE int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); @@ -21492,36 +17642,36 @@ # define sqlite3AuthRead(a,b,c,d) # define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK # define sqlite3AuthContextPush(a,b,c) # define sqlite3AuthContextPop(a) ((void)(a)) #endif -SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName); SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*); SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); +SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); - -SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64); -SQLITE_PRIVATE i64 sqlite3RealToI64(double); -SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*); SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); -SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*); SQLITE_PRIVATE int sqlite3Atoi(const char*); #ifndef SQLITE_OMIT_UTF16 -SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar); +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 int sqlite3Utf8ReadLimited(const u8*, int, u32*); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); +#ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); +#endif +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ + defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ + defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); +#endif SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); /* @@ -21539,67 +17689,47 @@ ** macros handle the common case without a procedure call, but then call ** the procedure for larger varints. */ #define getVarint32(A,B) \ (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B))) -#define getVarint32NR(A,B) \ - B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B)) #define putVarint32(A,B) \ (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\ sqlite3PutVarint((A),(B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*); -SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3*,const Table*); SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); -SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2); -SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity); -SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table*,int); -SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr); -SQLITE_PRIVATE int sqlite3ExprDataType(const Expr *pExpr); +SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); +SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); +SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table*,int); +SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*); SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); SQLITE_PRIVATE void sqlite3Error(sqlite3*,int); -SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*); SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int); -#if !defined(SQLITE_OMIT_BLOB_LITERAL) SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); -#endif SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); #if defined(SQLITE_NEED_ERR_NAME) SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif -#ifndef SQLITE_OMIT_DESERIALIZE -SQLITE_PRIVATE int sqlite3MemdbInit(void); -SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs*); -#else -# define sqlite3IsMemdb(X) 0 -#endif - SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); -SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*); SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); -SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8); -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr); -SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr); -SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(const Parse *pParse, Expr*, const Token*, int); -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(const Parse*,Expr*,const char*); +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); -SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); -SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*); -SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64); +SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); +SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64); SQLITE_PRIVATE int sqlite3AbsInt32(int); #ifdef SQLITE_ENABLE_8_3_NAMES @@ -21608,82 +17738,54 @@ # define sqlite3FileSuffix3(X,Y) #endif SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8); SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); -SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*)); SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*); SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*); -#ifndef SQLITE_UNTESTABLE -SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context*); -#endif SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *); #ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); #endif -SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, const Expr *, u8, u8, sqlite3_value **); +SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; SQLITE_PRIVATE const char sqlite3StrBINARY[]; -SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[]; -SQLITE_PRIVATE const char sqlite3StdTypeAffinity[]; -SQLITE_PRIVATE const char *sqlite3StdType[]; SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; -SQLITE_PRIVATE const unsigned char *sqlite3aLTb; -SQLITE_PRIVATE const unsigned char *sqlite3aEQb; -SQLITE_PRIVATE const unsigned char *sqlite3aGTb; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; +SQLITE_PRIVATE const Token sqlite3IntTokens[]; SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte; #endif -#endif /* SQLITE_AMALGAMATION */ -#ifdef VDBE_PROFILE -SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt; #endif -SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno); +SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int); SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); -SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); -SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); -SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); +SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); +SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); -SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*); SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); -SQLITE_PRIVATE int sqlite3MatchEName( - const struct ExprList_item*, - const char*, - const char*, - const char*, - int* -); -SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*); -SQLITE_PRIVATE u8 sqlite3StrIHash(const char*); +SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); -SQLITE_PRIVATE int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); +SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); -SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse*, SrcList*, const Token*); -SQLITE_PRIVATE const void *sqlite3RenameTokenMap(Parse*, const void*, const Token*); -SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, const void *pTo, const void *pFrom); -SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*); -SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); -SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); +SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); @@ -21696,45 +17798,31 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *); SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*); SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*); SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); -SQLITE_PRIVATE const char *sqlite3SelectOpName(int); -SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse*, ExprList*); - #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*); #endif SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), - void (*)(sqlite3_context*,int,sqlite3_value **), - void (*)(sqlite3_context*), - void (*)(sqlite3_context*), - void (*)(sqlite3_context*,int,sqlite3_value **), + void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), FuncDestructor *pDestructor ); -SQLITE_PRIVATE void sqlite3NoopDestructor(void*); -SQLITE_PRIVATE void *sqlite3OomFault(sqlite3*); +SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); -SQLITE_PRIVATE char *sqlite3RCStrRef(char*); -SQLITE_PRIVATE void sqlite3RCStrUnref(void*); -SQLITE_PRIVATE char *sqlite3RCStrNew(u64); -SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64); - SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); -SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64); +SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); +SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); +SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); -SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8); -SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); +SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); -SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*); -SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*); SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *); SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); #ifndef SQLITE_OMIT_SUBQUERY @@ -21741,11 +17829,12 @@ SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse*, Expr*); #else # define sqlite3ExprCheckIN(x,y) SQLITE_OK #endif -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void); SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*); SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*); SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**); @@ -21754,15 +17843,14 @@ /* ** The interface to the LEMON-generated parser */ #ifndef SQLITE_AMALGAMATION -SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*); +SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); #endif -SQLITE_PRIVATE void sqlite3Parser(void*, int, Token); -SQLITE_PRIVATE int sqlite3ParserFallback(int); +SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); #ifdef YYTRACKMAXSTACKDEPTH SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); #endif SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3*); @@ -21771,28 +17859,27 @@ #else # define sqlite3CloseExtensions(X) #endif #ifndef SQLITE_OMIT_SHARED_CACHE -SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, Pgno, u8, const char *); +SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, int, u8, const char *); #else #define sqlite3TableLock(v,w,x,y,z) #endif #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*); #endif #ifdef SQLITE_OMIT_VIRTUALTABLE -# define sqlite3VtabClear(D,T) +# define sqlite3VtabClear(Y) # define sqlite3VtabSync(X,Y) SQLITE_OK # define sqlite3VtabRollback(X) # define sqlite3VtabCommit(X) # define sqlite3VtabInSync(db) 0 # define sqlite3VtabLock(X) # define sqlite3VtabUnlock(X) -# define sqlite3VtabModuleUnref(D,X) # define sqlite3VtabUnlockList(X) # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK # define sqlite3GetVTable(X,Y) ((VTable*)0) #else SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*); @@ -21800,11 +17887,10 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe*); SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db); SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db); SQLITE_PRIVATE void sqlite3VtabLock(VTable *); SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *); -SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3*,Module*); SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*); SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int); SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); SQLITE_PRIVATE Module *sqlite3VtabCreateModule( @@ -21814,20 +17900,10 @@ void*, void(*)(void*) ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif -SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db); -#ifndef SQLITE_OMIT_VIRTUALTABLE -SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName); -SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*); -SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*); -#else -# define sqlite3ShadowTableName(A,B) 0 -# define sqlite3IsShadowTableOf(A,B,C) 0 -# define sqlite3MarkAllShadowTablesOf(A,B) -#endif SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*); SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); @@ -21835,62 +17911,33 @@ SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*); SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); - SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); -SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse*); +SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); -SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse*,sqlite3*); -SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse*); -SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*); -#endif +SQLITE_PRIVATE void sqlite3ParserReset(Parse*); SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); -SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*); -SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*); +SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); SQLITE_PRIVATE const char *sqlite3JournalModename(int); #ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE -SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); -SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); -SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); +SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); -SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3*,void*); -SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); -#else -# define sqlite3CteNew(P,T,E,S) ((void*)0) -# define sqlite3CteDelete(D,C) -# define sqlite3CteWithAdd(P,W,C) ((void*)0) -# define sqlite3WithDelete(x,y) -# define sqlite3WithPush(x,y,z) ((void*)0) -#endif -#ifndef SQLITE_OMIT_UPSERT -SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); -SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); -SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); -SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*); -SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); -SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*); -SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*); -#else -#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0) -#define sqlite3UpsertDelete(x,y) -#define sqlite3UpsertDup(x,y) ((Upsert*)0) -#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0) -#define sqlite3UpsertNextIsIPK(x) 0 -#endif - +SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8); +#else +#define sqlite3WithPush(x,y,z) +#define sqlite3WithDelete(x,y) +#endif /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In @@ -21902,19 +17949,17 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*); SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int); SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); -SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3*,int); #else #define sqlite3FkActions(a,b,c,d,e,f) #define sqlite3FkCheck(a,b,c,d,e,f) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #define sqlite3FkReferences(a) 0 - #define sqlite3FkClearTriggerCache(a,b) #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); #else @@ -21954,31 +17999,29 @@ ** Allowed flags for the 3rd parameter to sqlite3FindInIndex(). */ #define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */ #define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */ #define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*); +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 *); -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) +#ifdef SQLITE_ENABLE_ATOMIC_WRITE SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); #endif SQLITE_PRIVATE int sqlite3JournalIsInMemory(sqlite3_file *p); SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *); SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 -SQLITE_PRIVATE int sqlite3SelectExprHeight(const Select *); +SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *); SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); #else #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif -SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int); SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*); SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32); #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY @@ -21992,13 +18035,10 @@ #endif #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 ** sqlite3IoTrace is a pointer to a printf-like routine used to ** print I/O tracing messages. @@ -22040,966 +18080,47 @@ ** All of this is no-op for a production build. It only comes into ** play when the SQLITE_MEMDEBUG compile-time option is used. */ #ifdef SQLITE_MEMDEBUG SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8); -SQLITE_PRIVATE int sqlite3MemdebugHasType(const void*,u8); -SQLITE_PRIVATE int sqlite3MemdebugNoType(const void*,u8); +SQLITE_PRIVATE int sqlite3MemdebugHasType(void*,u8); +SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8); #else # define sqlite3MemdebugSetType(X,Y) /* no-op */ # define sqlite3MemdebugHasType(X,Y) 1 # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ -#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */ +#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ +#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ /* ** Threading interface */ #if SQLITE_MAX_WORKER_THREADS>0 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 -SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr); -SQLITE_PRIVATE int sqlite3ExprIsVector(const Expr *pExpr); +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,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 -#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) -SQLITE_PRIVATE int sqlite3KvvfsInit(void); -#endif - -#if defined(VDBE_PROFILE) \ - || defined(SQLITE_PERFORMANCE_TRACE) \ - || defined(SQLITE_ENABLE_STMT_SCANSTATUS) -SQLITE_PRIVATE sqlite3_uint64 sqlite3Hwtime(void); -#endif - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -# define IS_STMT_SCANSTATUS(db) (db->flags & SQLITE_StmtScanStatus) -#else -# define IS_STMT_SCANSTATUS(db) 0 -#endif - #endif /* SQLITEINT_H */ /************** End of sqliteInt.h *******************************************/ -/************** Begin file os_common.h ***************************************/ -/* -** 2004 May 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains macros and a little bit of code that is common to -** all of the platform-specific files (os_*.c) and is #included into those -** files. -** -** This file should be #included by the os_*.c files only. It is not a -** general purpose header file. -*/ -#ifndef _OS_COMMON_H_ -#define _OS_COMMON_H_ - -/* -** At least two bugs have slipped in because we changed the MEMORY_DEBUG -** macro to SQLITE_DEBUG and some older makefiles have not yet made the -** switch. The following code should catch this problem at compile-time. -*/ -#ifdef MEMORY_DEBUG -# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." -#endif - -/* -** Macros for performance tracing. Normally turned off. Only works -** on i486 hardware. -*/ -#ifdef SQLITE_PERFORMANCE_TRACE - -static sqlite_uint64 g_start; -static sqlite_uint64 g_elapsed; -#define TIMER_START g_start=sqlite3Hwtime() -#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start -#define TIMER_ELAPSED g_elapsed -#else -#define TIMER_START -#define TIMER_END -#define TIMER_ELAPSED ((sqlite_uint64)0) -#endif - -/* -** If we compile with the SQLITE_TEST macro set, then the following block -** of code will give us the ability to simulate a disk I/O error. This -** is used for testing the I/O recovery logic. -*/ -#if defined(SQLITE_TEST) -SQLITE_API extern int sqlite3_io_error_hit; -SQLITE_API extern int sqlite3_io_error_hardhit; -SQLITE_API extern int sqlite3_io_error_pending; -SQLITE_API extern int sqlite3_io_error_persist; -SQLITE_API extern int sqlite3_io_error_benign; -SQLITE_API extern int sqlite3_diskfull_pending; -SQLITE_API extern int sqlite3_diskfull; -#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) -#define SimulateIOError(CODE) \ - if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ - || sqlite3_io_error_pending-- == 1 ) \ - { local_ioerr(); CODE; } -static void local_ioerr(){ - IOTRACE(("IOERR\n")); - sqlite3_io_error_hit++; - if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; -} -#define SimulateDiskfullError(CODE) \ - if( sqlite3_diskfull_pending ){ \ - if( sqlite3_diskfull_pending == 1 ){ \ - local_ioerr(); \ - sqlite3_diskfull = 1; \ - sqlite3_io_error_hit = 1; \ - CODE; \ - }else{ \ - sqlite3_diskfull_pending--; \ - } \ - } -#else -#define SimulateIOErrorBenign(X) -#define SimulateIOError(A) -#define SimulateDiskfullError(A) -#endif /* defined(SQLITE_TEST) */ - -/* -** When testing, keep a count of the number of open files. -*/ -#if defined(SQLITE_TEST) -SQLITE_API extern int sqlite3_open_file_count; -#define OpenCounter(X) sqlite3_open_file_count+=(X) -#else -#define OpenCounter(X) -#endif /* defined(SQLITE_TEST) */ - -#endif /* !defined(_OS_COMMON_H_) */ - -/************** End of os_common.h *******************************************/ -/************** Begin file ctime.c *******************************************/ -/* DO NOT EDIT! -** This file is automatically generated by the script in the canonical -** SQLite source tree at tool/mkctimec.tcl. -** -** To modify this header, edit any of the various lists in that script -** which specify categories of generated conditionals in this file. -*/ - -/* -** 2010 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements routines used to report what compile-time options -** SQLite was built with. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */ - -/* -** Include the configuration header output by 'configure' if we're using the -** autoconf-based build -*/ -#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) -/* #include "sqlite_cfg.h" */ -#define SQLITECONFIG_H 1 -#endif - -/* These macros are provided to "stringify" the value of the define -** for those options in which the value is meaningful. */ -#define CTIMEOPT_VAL_(opt) #opt -#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) - -/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This -** option requires a separate macro because legal values contain a single -** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */ -#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2 -#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt) -/* #include "sqliteInt.h" */ - -/* -** An array of names of all compile-time options. This array should -** be sorted A-Z. -** -** This array looks large, but in a typical installation actually uses -** only a handful of compile-time options, so most times this array is usually -** rather short and uses little memory space. -*/ -static const char * const sqlite3azCompileOpt[] = { - -#ifdef SQLITE_32BIT_ROWID - "32BIT_ROWID", -#endif -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC - "4_BYTE_ALIGNED_MALLOC", -#endif -#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN -# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 - "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), -# endif -#endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - "ALLOW_ROWID_IN_VIEW", -#endif -#ifdef SQLITE_ALLOW_URI_AUTHORITY - "ALLOW_URI_AUTHORITY", -#endif -#ifdef SQLITE_ATOMIC_INTRINSICS - "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS), -#endif -#ifdef SQLITE_BITMASK_TYPE - "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE), -#endif -#ifdef SQLITE_BUG_COMPATIBLE_20160819 - "BUG_COMPATIBLE_20160819", -#endif -#ifdef SQLITE_CASE_SENSITIVE_LIKE - "CASE_SENSITIVE_LIKE", -#endif -#ifdef SQLITE_CHECK_PAGES - "CHECK_PAGES", -#endif -#if defined(__clang__) && defined(__clang_major__) - "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "." - CTIMEOPT_VAL(__clang_minor__) "." - CTIMEOPT_VAL(__clang_patchlevel__), -#elif defined(_MSC_VER) - "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER), -#elif defined(__GNUC__) && defined(__VERSION__) - "COMPILER=gcc-" __VERSION__, -#endif -#ifdef SQLITE_COVERAGE_TEST - "COVERAGE_TEST", -#endif -#ifdef SQLITE_DEBUG - "DEBUG", -#endif -#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX - "DEFAULT_AUTOMATIC_INDEX", -#endif -#ifdef SQLITE_DEFAULT_AUTOVACUUM - "DEFAULT_AUTOVACUUM", -#endif -#ifdef SQLITE_DEFAULT_CACHE_SIZE - "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE), -#endif -#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC - "DEFAULT_CKPTFULLFSYNC", -#endif -#ifdef SQLITE_DEFAULT_FILE_FORMAT - "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT), -#endif -#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS - "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS), -#endif -#ifdef SQLITE_DEFAULT_FOREIGN_KEYS - "DEFAULT_FOREIGN_KEYS", -#endif -#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT - "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT), -#endif -#ifdef SQLITE_DEFAULT_LOCKING_MODE - "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), -#endif -#ifdef SQLITE_DEFAULT_LOOKASIDE - "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), -#endif -#ifdef SQLITE_DEFAULT_MEMSTATUS -# if SQLITE_DEFAULT_MEMSTATUS != 1 - "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS), -# endif -#endif -#ifdef SQLITE_DEFAULT_MMAP_SIZE - "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), -#endif -#ifdef SQLITE_DEFAULT_PAGE_SIZE - "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE), -#endif -#ifdef SQLITE_DEFAULT_PCACHE_INITSZ - "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ), -#endif -#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS - "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS), -#endif -#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS - "DEFAULT_RECURSIVE_TRIGGERS", -#endif -#ifdef SQLITE_DEFAULT_ROWEST - "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST), -#endif -#ifdef SQLITE_DEFAULT_SECTOR_SIZE - "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE), -#endif -#ifdef SQLITE_DEFAULT_SYNCHRONOUS - "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS), -#endif -#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT - "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT), -#endif -#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS - "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS), -#endif -#ifdef SQLITE_DEFAULT_WORKER_THREADS - "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS), -#endif -#ifdef SQLITE_DIRECT_OVERFLOW_READ - "DIRECT_OVERFLOW_READ", -#endif -#ifdef SQLITE_DISABLE_DIRSYNC - "DISABLE_DIRSYNC", -#endif -#ifdef SQLITE_DISABLE_FTS3_UNICODE - "DISABLE_FTS3_UNICODE", -#endif -#ifdef SQLITE_DISABLE_FTS4_DEFERRED - "DISABLE_FTS4_DEFERRED", -#endif -#ifdef SQLITE_DISABLE_INTRINSIC - "DISABLE_INTRINSIC", -#endif -#ifdef SQLITE_DISABLE_LFS - "DISABLE_LFS", -#endif -#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS - "DISABLE_PAGECACHE_OVERFLOW_STATS", -#endif -#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT - "DISABLE_SKIPAHEAD_DISTINCT", -#endif -#ifdef SQLITE_DQS - "DQS=" CTIMEOPT_VAL(SQLITE_DQS), -#endif -#ifdef SQLITE_ENABLE_8_3_NAMES - "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), -#endif -#ifdef SQLITE_ENABLE_API_ARMOR - "ENABLE_API_ARMOR", -#endif -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - "ENABLE_ATOMIC_WRITE", -#endif -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - "ENABLE_BATCH_ATOMIC_WRITE", -#endif -#ifdef SQLITE_ENABLE_BYTECODE_VTAB - "ENABLE_BYTECODE_VTAB", -#endif -#ifdef SQLITE_ENABLE_CEROD - "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), -#endif -#ifdef SQLITE_ENABLE_COLUMN_METADATA - "ENABLE_COLUMN_METADATA", -#endif -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - "ENABLE_COLUMN_USED_MASK", -#endif -#ifdef SQLITE_ENABLE_COSTMULT - "ENABLE_COSTMULT", -#endif -#ifdef SQLITE_ENABLE_CURSOR_HINTS - "ENABLE_CURSOR_HINTS", -#endif -#ifdef SQLITE_ENABLE_DBPAGE_VTAB - "ENABLE_DBPAGE_VTAB", -#endif -#ifdef SQLITE_ENABLE_DBSTAT_VTAB - "ENABLE_DBSTAT_VTAB", -#endif -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - "ENABLE_EXPENSIVE_ASSERT", -#endif -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - "ENABLE_EXPLAIN_COMMENTS", -#endif -#ifdef SQLITE_ENABLE_FTS3 - "ENABLE_FTS3", -#endif -#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS - "ENABLE_FTS3_PARENTHESIS", -#endif -#ifdef SQLITE_ENABLE_FTS3_TOKENIZER - "ENABLE_FTS3_TOKENIZER", -#endif -#ifdef SQLITE_ENABLE_FTS4 - "ENABLE_FTS4", -#endif -#ifdef SQLITE_ENABLE_FTS5 - "ENABLE_FTS5", -#endif -#ifdef SQLITE_ENABLE_GEOPOLY - "ENABLE_GEOPOLY", -#endif -#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS - "ENABLE_HIDDEN_COLUMNS", -#endif -#ifdef SQLITE_ENABLE_ICU - "ENABLE_ICU", -#endif -#ifdef SQLITE_ENABLE_IOTRACE - "ENABLE_IOTRACE", -#endif -#ifdef SQLITE_ENABLE_LOAD_EXTENSION - "ENABLE_LOAD_EXTENSION", -#endif -#ifdef SQLITE_ENABLE_LOCKING_STYLE - "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), -#endif -#ifdef SQLITE_ENABLE_MATH_FUNCTIONS - "ENABLE_MATH_FUNCTIONS", -#endif -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - "ENABLE_MEMORY_MANAGEMENT", -#endif -#ifdef SQLITE_ENABLE_MEMSYS3 - "ENABLE_MEMSYS3", -#endif -#ifdef SQLITE_ENABLE_MEMSYS5 - "ENABLE_MEMSYS5", -#endif -#ifdef SQLITE_ENABLE_MULTIPLEX - "ENABLE_MULTIPLEX", -#endif -#ifdef SQLITE_ENABLE_NORMALIZE - "ENABLE_NORMALIZE", -#endif -#ifdef SQLITE_ENABLE_NULL_TRIM - "ENABLE_NULL_TRIM", -#endif -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - "ENABLE_OFFSET_SQL_FUNC", -#endif -#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES - "ENABLE_ORDERED_SET_AGGREGATES", -#endif -#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK - "ENABLE_OVERSIZE_CELL_CHECK", -#endif -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - "ENABLE_PREUPDATE_HOOK", -#endif -#ifdef SQLITE_ENABLE_QPSG - "ENABLE_QPSG", -#endif -#ifdef SQLITE_ENABLE_RBU - "ENABLE_RBU", -#endif -#ifdef SQLITE_ENABLE_RTREE - "ENABLE_RTREE", -#endif -#ifdef SQLITE_ENABLE_SESSION - "ENABLE_SESSION", -#endif -#ifdef SQLITE_ENABLE_SNAPSHOT - "ENABLE_SNAPSHOT", -#endif -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - "ENABLE_SORTER_REFERENCES", -#endif -#ifdef SQLITE_ENABLE_SQLLOG - "ENABLE_SQLLOG", -#endif -#ifdef SQLITE_ENABLE_STAT4 - "ENABLE_STAT4", -#endif -#ifdef SQLITE_ENABLE_STMTVTAB - "ENABLE_STMTVTAB", -#endif -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - "ENABLE_STMT_SCANSTATUS", -#endif -#ifdef SQLITE_ENABLE_TREETRACE - "ENABLE_TREETRACE", -#endif -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - "ENABLE_UNKNOWN_SQL_FUNCTION", -#endif -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - "ENABLE_UNLOCK_NOTIFY", -#endif -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - "ENABLE_UPDATE_DELETE_LIMIT", -#endif -#ifdef SQLITE_ENABLE_URI_00_ERROR - "ENABLE_URI_00_ERROR", -#endif -#ifdef SQLITE_ENABLE_VFSTRACE - "ENABLE_VFSTRACE", -#endif -#ifdef SQLITE_ENABLE_WHERETRACE - "ENABLE_WHERETRACE", -#endif -#ifdef SQLITE_ENABLE_ZIPVFS - "ENABLE_ZIPVFS", -#endif -#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS - "EXPLAIN_ESTIMATED_ROWS", -#endif -#ifdef SQLITE_EXTRA_AUTOEXT - "EXTRA_AUTOEXT=" CTIMEOPT_VAL(SQLITE_EXTRA_AUTOEXT), -#endif -#ifdef SQLITE_EXTRA_IFNULLROW - "EXTRA_IFNULLROW", -#endif -#ifdef SQLITE_EXTRA_INIT - "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT), -#endif -#ifdef SQLITE_EXTRA_SHUTDOWN - "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN), -#endif -#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH - "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH), -#endif -#ifdef SQLITE_FTS5_ENABLE_TEST_MI - "FTS5_ENABLE_TEST_MI", -#endif -#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID - "FTS5_NO_WITHOUT_ROWID", -#endif -#if HAVE_ISNAN || SQLITE_HAVE_ISNAN - "HAVE_ISNAN", -#endif -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX -# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1 - "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX), -# endif -#endif -#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS - "IGNORE_AFP_LOCK_ERRORS", -#endif -#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - "IGNORE_FLOCK_LOCK_ERRORS", -#endif -#ifdef SQLITE_INLINE_MEMCPY - "INLINE_MEMCPY", -#endif -#ifdef SQLITE_INT64_TYPE - "INT64_TYPE", -#endif -#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX - "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), -#endif -#ifdef SQLITE_LEGACY_JSON_VALID - "LEGACY_JSON_VALID", -#endif -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - "LIKE_DOESNT_MATCH_BLOBS", -#endif -#ifdef SQLITE_LOCK_TRACE - "LOCK_TRACE", -#endif -#ifdef SQLITE_LOG_CACHE_SPILL - "LOG_CACHE_SPILL", -#endif -#ifdef SQLITE_MALLOC_SOFT_LIMIT - "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT), -#endif -#ifdef SQLITE_MAX_ATTACHED - "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED), -#endif -#ifdef SQLITE_MAX_COLUMN - "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN), -#endif -#ifdef SQLITE_MAX_COMPOUND_SELECT - "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT), -#endif -#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE - "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE), -#endif -#ifdef SQLITE_MAX_EXPR_DEPTH - "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH), -#endif -#ifdef SQLITE_MAX_FUNCTION_ARG - "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG), -#endif -#ifdef SQLITE_MAX_LENGTH - "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH), -#endif -#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH - "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH), -#endif -#ifdef SQLITE_MAX_MEMORY - "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY), -#endif -#ifdef SQLITE_MAX_MMAP_SIZE - "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), -#endif -#ifdef SQLITE_MAX_MMAP_SIZE_ - "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_), -#endif -#ifdef SQLITE_MAX_PAGE_COUNT - "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT), -#endif -#ifdef SQLITE_MAX_PAGE_SIZE - "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE), -#endif -#ifdef SQLITE_MAX_SCHEMA_RETRY - "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), -#endif -#ifdef SQLITE_MAX_SQL_LENGTH - "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH), -#endif -#ifdef SQLITE_MAX_TRIGGER_DEPTH - "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH), -#endif -#ifdef SQLITE_MAX_VARIABLE_NUMBER - "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER), -#endif -#ifdef SQLITE_MAX_VDBE_OP - "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP), -#endif -#ifdef SQLITE_MAX_WORKER_THREADS - "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS), -#endif -#ifdef SQLITE_MEMDEBUG - "MEMDEBUG", -#endif -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT - "MIXED_ENDIAN_64BIT_FLOAT", -#endif -#ifdef SQLITE_MMAP_READWRITE - "MMAP_READWRITE", -#endif -#ifdef SQLITE_MUTEX_NOOP - "MUTEX_NOOP", -#endif -#ifdef SQLITE_MUTEX_OMIT - "MUTEX_OMIT", -#endif -#ifdef SQLITE_MUTEX_PTHREADS - "MUTEX_PTHREADS", -#endif -#ifdef SQLITE_MUTEX_W32 - "MUTEX_W32", -#endif -#ifdef SQLITE_NEED_ERR_NAME - "NEED_ERR_NAME", -#endif -#ifdef SQLITE_NO_SYNC - "NO_SYNC", -#endif -#ifdef SQLITE_OMIT_ALTERTABLE - "OMIT_ALTERTABLE", -#endif -#ifdef SQLITE_OMIT_ANALYZE - "OMIT_ANALYZE", -#endif -#ifdef SQLITE_OMIT_ATTACH - "OMIT_ATTACH", -#endif -#ifdef SQLITE_OMIT_AUTHORIZATION - "OMIT_AUTHORIZATION", -#endif -#ifdef SQLITE_OMIT_AUTOINCREMENT - "OMIT_AUTOINCREMENT", -#endif -#ifdef SQLITE_OMIT_AUTOINIT - "OMIT_AUTOINIT", -#endif -#ifdef SQLITE_OMIT_AUTOMATIC_INDEX - "OMIT_AUTOMATIC_INDEX", -#endif -#ifdef SQLITE_OMIT_AUTORESET - "OMIT_AUTORESET", -#endif -#ifdef SQLITE_OMIT_AUTOVACUUM - "OMIT_AUTOVACUUM", -#endif -#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION - "OMIT_BETWEEN_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_BLOB_LITERAL - "OMIT_BLOB_LITERAL", -#endif -#ifdef SQLITE_OMIT_CAST - "OMIT_CAST", -#endif -#ifdef SQLITE_OMIT_CHECK - "OMIT_CHECK", -#endif -#ifdef SQLITE_OMIT_COMPLETE - "OMIT_COMPLETE", -#endif -#ifdef SQLITE_OMIT_COMPOUND_SELECT - "OMIT_COMPOUND_SELECT", -#endif -#ifdef SQLITE_OMIT_CONFLICT_CLAUSE - "OMIT_CONFLICT_CLAUSE", -#endif -#ifdef SQLITE_OMIT_CTE - "OMIT_CTE", -#endif -#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT) - "OMIT_DATETIME_FUNCS", -#endif -#ifdef SQLITE_OMIT_DECLTYPE - "OMIT_DECLTYPE", -#endif -#ifdef SQLITE_OMIT_DEPRECATED - "OMIT_DEPRECATED", -#endif -#ifdef SQLITE_OMIT_DESERIALIZE - "OMIT_DESERIALIZE", -#endif -#ifdef SQLITE_OMIT_DISKIO - "OMIT_DISKIO", -#endif -#ifdef SQLITE_OMIT_EXPLAIN - "OMIT_EXPLAIN", -#endif -#ifdef SQLITE_OMIT_FLAG_PRAGMAS - "OMIT_FLAG_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_FLOATING_POINT - "OMIT_FLOATING_POINT", -#endif -#ifdef SQLITE_OMIT_FOREIGN_KEY - "OMIT_FOREIGN_KEY", -#endif -#ifdef SQLITE_OMIT_GET_TABLE - "OMIT_GET_TABLE", -#endif -#ifdef SQLITE_OMIT_HEX_INTEGER - "OMIT_HEX_INTEGER", -#endif -#ifdef SQLITE_OMIT_INCRBLOB - "OMIT_INCRBLOB", -#endif -#ifdef SQLITE_OMIT_INTEGRITY_CHECK - "OMIT_INTEGRITY_CHECK", -#endif -#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS - "OMIT_INTROSPECTION_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_JSON - "OMIT_JSON", -#endif -#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION - "OMIT_LIKE_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_LOAD_EXTENSION - "OMIT_LOAD_EXTENSION", -#endif -#ifdef SQLITE_OMIT_LOCALTIME - "OMIT_LOCALTIME", -#endif -#ifdef SQLITE_OMIT_LOOKASIDE - "OMIT_LOOKASIDE", -#endif -#ifdef SQLITE_OMIT_MEMORYDB - "OMIT_MEMORYDB", -#endif -#ifdef SQLITE_OMIT_OR_OPTIMIZATION - "OMIT_OR_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_PAGER_PRAGMAS - "OMIT_PAGER_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_PARSER_TRACE - "OMIT_PARSER_TRACE", -#endif -#ifdef SQLITE_OMIT_POPEN - "OMIT_POPEN", -#endif -#ifdef SQLITE_OMIT_PRAGMA - "OMIT_PRAGMA", -#endif -#ifdef SQLITE_OMIT_PROGRESS_CALLBACK - "OMIT_PROGRESS_CALLBACK", -#endif -#ifdef SQLITE_OMIT_QUICKBALANCE - "OMIT_QUICKBALANCE", -#endif -#ifdef SQLITE_OMIT_REINDEX - "OMIT_REINDEX", -#endif -#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS - "OMIT_SCHEMA_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - "OMIT_SCHEMA_VERSION_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_SEH - "OMIT_SEH", -#endif -#ifdef SQLITE_OMIT_SHARED_CACHE - "OMIT_SHARED_CACHE", -#endif -#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES - "OMIT_SHUTDOWN_DIRECTORIES", -#endif -#ifdef SQLITE_OMIT_SUBQUERY - "OMIT_SUBQUERY", -#endif -#ifdef SQLITE_OMIT_TCL_VARIABLE - "OMIT_TCL_VARIABLE", -#endif -#ifdef SQLITE_OMIT_TEMPDB - "OMIT_TEMPDB", -#endif -#ifdef SQLITE_OMIT_TEST_CONTROL - "OMIT_TEST_CONTROL", -#endif -#ifdef SQLITE_OMIT_TRACE -# if SQLITE_OMIT_TRACE != 1 - "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE), -# endif -#endif -#ifdef SQLITE_OMIT_TRIGGER - "OMIT_TRIGGER", -#endif -#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION - "OMIT_TRUNCATE_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_UTF16 - "OMIT_UTF16", -#endif -#ifdef SQLITE_OMIT_VACUUM - "OMIT_VACUUM", -#endif -#ifdef SQLITE_OMIT_VIEW - "OMIT_VIEW", -#endif -#ifdef SQLITE_OMIT_VIRTUALTABLE - "OMIT_VIRTUALTABLE", -#endif -#ifdef SQLITE_OMIT_WAL - "OMIT_WAL", -#endif -#ifdef SQLITE_OMIT_WSD - "OMIT_WSD", -#endif -#ifdef SQLITE_OMIT_XFER_OPT - "OMIT_XFER_OPT", -#endif -#ifdef SQLITE_PERFORMANCE_TRACE - "PERFORMANCE_TRACE", -#endif -#ifdef SQLITE_POWERSAFE_OVERWRITE -# if SQLITE_POWERSAFE_OVERWRITE != 1 - "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE), -# endif -#endif -#ifdef SQLITE_PREFER_PROXY_LOCKING - "PREFER_PROXY_LOCKING", -#endif -#ifdef SQLITE_PROXY_DEBUG - "PROXY_DEBUG", -#endif -#ifdef SQLITE_REVERSE_UNORDERED_SELECTS - "REVERSE_UNORDERED_SELECTS", -#endif -#ifdef SQLITE_RTREE_INT_ONLY - "RTREE_INT_ONLY", -#endif -#ifdef SQLITE_SECURE_DELETE - "SECURE_DELETE", -#endif -#ifdef SQLITE_SMALL_STACK - "SMALL_STACK", -#endif -#ifdef SQLITE_SORTER_PMASZ - "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ), -#endif -#ifdef SQLITE_SOUNDEX - "SOUNDEX", -#endif -#ifdef SQLITE_STAT4_SAMPLES - "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES), -#endif -#ifdef SQLITE_STMTJRNL_SPILL - "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL), -#endif -#ifdef SQLITE_SUBSTR_COMPATIBILITY - "SUBSTR_COMPATIBILITY", -#endif -#if (!defined(SQLITE_WIN32_MALLOC) \ - && !defined(SQLITE_ZERO_MALLOC) \ - && !defined(SQLITE_MEMDEBUG) \ - ) || defined(SQLITE_SYSTEM_MALLOC) - "SYSTEM_MALLOC", -#endif -#ifdef SQLITE_TCL - "TCL", -#endif -#ifdef SQLITE_TEMP_STORE - "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), -#endif -#ifdef SQLITE_TEST - "TEST", -#endif -#if defined(SQLITE_THREADSAFE) - "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), -#elif defined(THREADSAFE) - "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE), -#else - "THREADSAFE=1", -#endif -#ifdef SQLITE_UNLINK_AFTER_CLOSE - "UNLINK_AFTER_CLOSE", -#endif -#ifdef SQLITE_UNTESTABLE - "UNTESTABLE", -#endif -#ifdef SQLITE_USE_ALLOCA - "USE_ALLOCA", -#endif -#ifdef SQLITE_USE_FCNTL_TRACE - "USE_FCNTL_TRACE", -#endif -#ifdef SQLITE_USE_URI - "USE_URI", -#endif -#ifdef SQLITE_VDBE_COVERAGE - "VDBE_COVERAGE", -#endif -#ifdef SQLITE_WIN32_MALLOC - "WIN32_MALLOC", -#endif -#ifdef SQLITE_ZERO_MALLOC - "ZERO_MALLOC", -#endif - -} ; - -SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){ - *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); - return (const char**)sqlite3azCompileOpt; -} - -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/************** End of ctime.c ***********************************************/ /************** Begin file global.c ******************************************/ /* ** 2008 June 13 ** ** The author disclaims copyright to this source code. In place of @@ -23014,11 +18135,11 @@ ** This file contains definitions of global variables and constants. */ /* #include "sqliteInt.h" */ /* An array to map all upper-case characters into their corresponding -** lower-case character. +** lower-case character. ** ** SQLite only considers US-ASCII (or EBCDIC) characters. We do not ** handle case conversions for the UTF character set since the tables ** involved are nearly as big or bigger than SQLite itself. */ @@ -23036,11 +18157,11 @@ 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, - 252,253,254,255, + 252,253,254,255 #endif #ifdef SQLITE_EBCDIC 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */ @@ -23056,39 +18177,11 @@ 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */ #endif -/* All of the upper-to-lower conversion data is above. The following -** 18 integers are completely unrelated. They are appended to the -** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is -** going on: -** -** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented -** by invoking sqlite3MemCompare(A,B) which compares values A and B and -** returns negative, zero, or positive if A is less then, equal to, or -** greater than B, respectively. Then the true false results is found by -** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or -** sqlite3aGTb[opcode] depending on whether the result of compare(A,B) -** is negative, zero, or positive, where opcode is the specific opcode. -** The only works because the comparison opcodes are consecutive and in -** this order: NE EQ GT LE LT GE. Various assert()s throughout the code -** ensure that is the case. -** -** These elements must be appended to another array. Otherwise the -** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus -** be undefined behavior. That's goofy, but the C-standards people thought -** it was a good idea, so here we are. -*/ -/* NE EQ GT LE LT GE */ - 1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */ - 0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */ - 1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/ }; -SQLITE_PRIVATE const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne]; -SQLITE_PRIVATE const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne]; -SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne]; /* ** The following 256 byte lookup table is used to support SQLites built-in ** equivalents to the following standard library functions: ** @@ -23096,11 +18189,11 @@ ** isalpha() 0x02 ** isdigit() 0x04 ** isalnum() 0x06 ** isxdigit() 0x08 ** toupper() 0x20 -** SQLite identifier character 0x40 $, _, or non-ascii +** SQLite identifier character 0x40 ** Quote character 0x80 ** ** Bit 0x20 is set if the mapped character requires translation to upper ** case. i.e. if the character is a lower-case ASCII character. ** If x is a lower-case ASCII character, then its upper-case equivalent @@ -23109,15 +18202,16 @@ ** (x & ~(map[x]&0x20)) ** ** The equivalent of tolower() is implemented using the sqlite3UpperToLower[] ** array. tolower() is used more often than toupper() by SQLite. ** -** Bit 0x40 is set if the character is non-alphanumeric and can be used in an +** Bit 0x40 is set if the character is non-alphanumeric and can be used in an ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any ** non-ASCII UTF character. Hence the test for whether or not a character is ** part of an identifier is 0x46. */ +#ifdef SQLITE_ASCII SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */ @@ -23151,10 +18245,11 @@ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */ }; +#endif /* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards ** compatibility for legacy applications, the URI filename capability is ** disabled by default. ** @@ -23162,28 +18257,28 @@ ** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. ** ** 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 ** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if ** that compile-time option is omitted. */ -#if !defined(SQLITE_ALLOW_COVERING_INDEX_SCAN) +#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 -#else -# if !SQLITE_ALLOW_COVERING_INDEX_SCAN -# error "Compile-time disabling of covering index scan using the\ - -DSQLITE_ALLOW_COVERING_INDEX_SCAN=0 option is deprecated.\ - Contact SQLite developers if this is a problem for you, and\ - delete this #error macro to continue with your build." -# endif #endif /* The minimum PMA size is set to this value multiplied by the database ** page size in bytes. */ @@ -23197,11 +18292,11 @@ ** before 3.12.0). -1 means always keep the entire statement journal in ** memory. (The statement journal is also always held entirely in memory ** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this ** setting.) */ -#ifndef SQLITE_STMTJRNL_SPILL +#ifndef SQLITE_STMTJRNL_SPILL # define SQLITE_STMTJRNL_SPILL (64*1024) #endif /* ** The default lookaside-configuration, the format "SZ,N". SZ is the @@ -23208,32 +18303,16 @@ ** 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); -** -** With the two-size-lookaside enhancement, less lookaside is required. -** The default configuration of 1200,40 actually provides 30 1200-byte slots -** and 93 128-byte slots, which is more lookaside than is available -** using the older 1200,100 configuration without two-size-lookaside. */ #ifndef SQLITE_DEFAULT_LOOKASIDE -# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE -# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */ -# else -# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */ -# endif +# define SQLITE_DEFAULT_LOOKASIDE 1200,100 #endif -/* The default maximum size of an in-memory database created using -** sqlite3_deserialize() -*/ -#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE -# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824 -#endif - /* ** The following singleton contains the global configuration for ** the SQLite library. */ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { @@ -23240,15 +18319,10 @@ SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */ 1, /* bCoreMutex */ SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ - 0, /* bSmallMalloc */ - 1, /* bExtraSchemaChecks */ -#ifdef SQLITE_DEBUG - 0, /* bJsonSelfcheck */ -#endif 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ SQLITE_STMTJRNL_SPILL, /* nStmtSpill */ {0,0,0,0,0,0,0,0}, /* m */ @@ -23257,10 +18331,13 @@ (void*)0, /* pHeap */ 0, /* nHeap */ 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 */ 0, /* mxParserStack */ 0, /* sharedCacheEnabled */ @@ -23281,55 +18358,32 @@ #endif #ifdef SQLITE_VDBE_COVERAGE 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif -#ifndef SQLITE_OMIT_DESERIALIZE - SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ -#endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */ -#endif 0, /* bLocaltimeFault */ - 0, /* xAltLocaltime */ - 0x7ffffffe, /* iOnceResetThreshold */ - SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ - 0, /* iPrngSeed */ -#ifdef SQLITE_DEBUG - {0,0,0,0,0,0}, /* aTune */ -#endif + 0x7ffffffe /* iOnceResetThreshold */ }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. */ SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) -/* -** Counter used for coverage testing. Does not come into play for -** release builds. -** -** Access to this global variable is not mutex protected. This might -** result in TSAN warnings. But as the variable does not exist in -** release builds, that should not be a concern. -*/ -SQLITE_PRIVATE unsigned int sqlite3CoverageCounter; -#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */ - -#ifdef VDBE_PROFILE -/* -** The following performance counter can be used in place of -** sqlite3Hwtime() for profiling. This is a no-op on standard builds. -*/ -SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; -#endif +/* +** Constant tokens for values 0 and 1. +*/ +SQLITE_PRIVATE const Token sqlite3IntTokens[] = { + { "0", 1 }, + { "1", 1 } +}; + /* ** The value of the "pending" byte must be 0x40000000 (1 byte past the ** 1-gibabyte boundary) in a compatible database. SQLite never uses ** the database page that contains the pending byte. It never attempts @@ -23349,60 +18403,24 @@ */ #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; #endif -/* -** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS. -*/ -SQLITE_PRIVATE u32 sqlite3TreeTrace = 0; -SQLITE_PRIVATE u32 sqlite3WhereTrace = 0; - /* #include "opcodes.h" */ /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in -** the vdbe.c file. +** the vdbe.c file. */ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; /* ** Name of the default collating sequence */ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; -/* -** Standard typenames. These names must match the COLTYPE_* definitions. -** Adjust the SQLITE_N_STDTYPE value if adding or removing entries. -** -** sqlite3StdType[] The actual names of the datatypes. -** -** sqlite3StdTypeLen[] The length (in bytes) of each entry -** in sqlite3StdType[]. -** -** sqlite3StdTypeAffinity[] The affinity associated with each entry -** in sqlite3StdType[]. -*/ -SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 }; -SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = { - SQLITE_AFF_NUMERIC, - SQLITE_AFF_BLOB, - SQLITE_AFF_INTEGER, - SQLITE_AFF_INTEGER, - SQLITE_AFF_REAL, - SQLITE_AFF_TEXT -}; -SQLITE_PRIVATE const char *sqlite3StdType[] = { - "ANY", - "BLOB", - "INT", - "INTEGER", - "REAL", - "TEXT" -}; - /************** End of global.c **********************************************/ /************** Begin file status.c ******************************************/ /* ** 2008 June 18 ** @@ -23452,12 +18470,11 @@ /* ** VDBE_DISPLAY_P4 is true or false depending on whether or not the ** "explain" P4 display logic is enabled. */ #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ - || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \ - || defined(SQLITE_ENABLE_BYTECODE_VTAB) + || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) # define VDBE_DISPLAY_P4 1 #else # define VDBE_DISPLAY_P4 0 #endif @@ -23477,13 +18494,10 @@ typedef struct VdbeSorter VdbeSorter; /* Elements of the linked list at Vdbe.pAuxData */ typedef struct AuxData AuxData; -/* A cache of large TEXT or BLOB values in a VdbeCursor */ -typedef struct VdbeTxtBlbCache VdbeTxtBlbCache; - /* Types of VDBE cursors */ #define CURTYPE_BTREE 0 #define CURTYPE_SORTER 1 #define CURTYPE_VTAB 2 #define CURTYPE_PSEUDO 3 @@ -23499,11 +18513,11 @@ ** * A one-row "pseudotable" stored in a single register */ typedef struct VdbeCursor VdbeCursor; struct VdbeCursor { u8 eCurType; /* One of the CURTYPE_* values above */ - i8 iDb; /* Index of cursor database in db->aDb[] */ + 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 */ @@ -23510,38 +18524,33 @@ 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 */ - Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */ - Bool colCache:1; /* pCache pointer is initialized and non-NULL */ - u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */ - union { /* pBtx for isEphermeral. pAltMap otherwise */ - Btree *pBtx; /* Separate file holding temporary table */ - u32 *aAltMap; /* Mapping from table to index column numbers */ - } ub; + 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 */ + /* NB: seekResult does not distinguish between "no seeks have ever occurred + ** on this cursor" and "the most recent seek was an exact match". */ /* 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 or _PSEUDO. Btree cursor */ - sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ - VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ + 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 */ } uc; 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 */ @@ -23552,47 +18561,28 @@ 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 */ #endif - VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ u32 aType[1]; /* Type values record decode. MUST BE LAST */ }; -/* Return true if P is a null-only cursor -*/ -#define IsNullCursor(P) \ - ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0) /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. */ #define CACHE_STALE 0 -/* -** Large TEXT or BLOB values can be slow to load, so we want to avoid -** loading them more than once. For that reason, large TEXT and BLOB values -** can be stored in a cache defined by this object, and attached to the -** VdbeCursor using the pCache field. -*/ -struct VdbeTxtBlbCache { - char *pCValue; /* A RCStr buffer to hold the value */ - i64 iOffset; /* File offset of the row being cached */ - int iCol; /* Column for which the cache is valid */ - u32 cacheStatus; /* Vdbe.cacheCtr value */ - u32 colCacheCtr; /* Column cache counter */ -}; - /* ** When a sub-program is executed (OP_Program), a structure of this type ** is allocated to store the current value of the program counter, as ** well as the current memory cell array and various other frame specific -** values stored in the Vdbe struct. When the sub-program is finished, +** values stored in the Vdbe struct. When the sub-program is finished, ** these values are copied back to the Vdbe from the VdbeFrame structure, ** restoring the state of the VM to as it was before the sub-program ** began executing. ** ** The memory for a VdbeFrame object is allocated and managed by a memory @@ -23610,36 +18600,27 @@ typedef struct VdbeFrame VdbeFrame; struct VdbeFrame { Vdbe *v; /* VM this frame belongs to */ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ + i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ u8 *aOnce; /* Bitmask used by OP_Once */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ AuxData *pAuxData; /* Linked list of auxdata allocations */ -#if SQLITE_DEBUG - u32 iFrameMagic; /* magic number for sanity checking */ -#endif int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ - i64 nChange; /* Statement changes (Vdbe.nChange) */ - i64 nDbChange; /* Value of db->nChange */ + int nChange; /* Statement changes (Vdbe.nChange) */ + int nDbChange; /* Value of db->nChange */ }; -/* Magic number for sanity checking on VdbeFrame objects */ -#define SQLITE_FRAME_MAGIC 0x879fb71e - -/* -** Return a pointer to the array of registers allocated for use -** by a VdbeFrame. -*/ #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) /* ** Internally, the vdbe manipulates nearly all SQL values as Mem ** structures. Each Mem struct may cache multiple representations (string, @@ -23647,143 +18628,103 @@ */ 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; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ - const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ + int nZero; /* Used when bit MEM_Zero is set in flags */ + void *pPtr; /* Pointer when flags=MEM_NULL and eSubtype='p' */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ + RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ + VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; - char *z; /* String or BLOB value */ - int n; /* Number of characters in string value, excluding '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ u8 eSubtype; /* Subtype for this value */ + int n; /* Number of characters in string value, excluding '\0' */ + char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ - sqlite3 *db; /* The associated database connection */ + char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ int szMalloc; /* Size of the zMalloc allocation */ u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ - char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ + sqlite3 *db; /* The associated database connection */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ - u16 mScopyFlags; /* flags value immediately after the shallow copy */ - u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */ + void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ #endif }; /* ** Size of struct Mem not including the Mem.zMalloc member or anything that ** follows. */ -#define MEMCELLSIZE offsetof(Mem,db) +#define MEMCELLSIZE offsetof(Mem,zMalloc) -/* One or more of the following flags are set to indicate the +/* One or more of the following flags are set to indicate the validOK ** representations of the value stored in the Mem struct. ** -** * MEM_Null An SQL NULL value -** -** * MEM_Null|MEM_Zero An SQL NULL with the virtual table -** UPDATE no-change flag set -** -** * MEM_Null|MEM_Term| An SQL NULL, but also contains a -** MEM_Subtype pointer accessible using -** sqlite3_value_pointer(). -** -** * MEM_Null|MEM_Cleared Special SQL NULL that compares non-equal -** to other NULLs even using the IS operator. -** -** * MEM_Str A string, stored in Mem.z with -** length Mem.n. Zero-terminated if -** MEM_Term is set. This flag is -** incompatible with MEM_Blob and -** MEM_Null, but can appear with MEM_Int, -** MEM_Real, and MEM_IntReal. -** -** * MEM_Blob A blob, stored in Mem.z length Mem.n. -** Incompatible with MEM_Str, MEM_Null, -** MEM_Int, MEM_Real, and MEM_IntReal. -** -** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus -** MEM.u.i extra 0x00 bytes at the end. -** -** * MEM_Int Integer stored in Mem.u.i. -** -** * MEM_Real Real stored in Mem.u.r. -** -** * MEM_IntReal Real stored as an integer in Mem.u.i. -** ** If the MEM_Null flag is set, then the value is an SQL NULL value. -** For a pointer type created using sqlite3_bind_pointer() or -** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set. +** No other flags may be set in this case. ** ** If the MEM_Str flag is set then Mem.z points at a string representation. ** Usually this is encoded in the same unicode encoding as the main ** database (see below for exceptions). If the MEM_Term flag is also -** set, then the string is nul terminated. The MEM_Int and MEM_Real +** set, then the string is nul terminated. The MEM_Int and MEM_Real ** flags may coexist with the MEM_Str flag. */ -#define MEM_Undefined 0x0000 /* Value is undefined */ -#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */ +#define MEM_Null 0x0001 /* Value is NULL */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ -#define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */ -#define MEM_AffMask 0x003f /* Mask of affinity bits */ - -/* Extra bits that modify the meanings of the core datatypes above -*/ -#define MEM_FromBind 0x0040 /* Value originates from sqlite3_bind() */ - /* 0x0080 // Available */ +#define MEM_AffMask 0x001f /* Mask of affinity bits */ +#define MEM_RowSet 0x0020 /* Value is a RowSet object */ +#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_Term 0x0200 /* String in Mem.z is zero terminated */ -#define MEM_Zero 0x0400 /* Mem.i contains count of 0s appended to blob */ -#define MEM_Subtype 0x0800 /* Mem.eSubtype is valid */ -#define MEM_TypeMask 0x0dbf /* Mask of type bits */ - -/* Bits that determine the storage for Mem.z for a string or blob or -** aggregate accumulator. -*/ -#define MEM_Dyn 0x1000 /* Need to call Mem.xDel() on Mem.z */ -#define MEM_Static 0x2000 /* Mem.z points to a static string */ -#define MEM_Ephem 0x4000 /* Mem.z points to an ephemeral string */ -#define MEM_Agg 0x8000 /* Mem.z points to an agg function context */ +#define MEM_TypeMask 0x81ff /* Mask of type bits */ + + +/* Whenever Mem contains a valid string or blob representation, one of +** the following flags must be set to determine the memory management +** policy for Mem.z. The MEM_Term flag tells us whether or not the +** string is \000 or \u0000 terminated +*/ +#define MEM_Term 0x0200 /* String rep is nul terminated */ +#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ +#define MEM_Static 0x0800 /* Mem.z points to a static string */ +#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ +#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ +#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ +#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ +#ifdef SQLITE_OMIT_INCRBLOB + #undef MEM_Zero + #define MEM_Zero 0x0000 +#endif /* Return TRUE if Mem X contains dynamically allocated content - anything ** that needs to be deallocated to avoid a leak. */ #define VdbeMemDynamic(X) \ - (((X)->flags&(MEM_Agg|MEM_Dyn))!=0) + (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) /* ** Clear any existing type flags from a Mem and replace them with f */ #define MemSetTypeFlag(p, f) \ ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) /* -** True if Mem X is a NULL-nochng type. -*/ -#define MemNullNochng(X) \ - (((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \ - && (X)->n==0 && (X)->u.nZero==0) - -/* -** Return true if a memory cell has been initialized and is valid. +** Return true if a memory cell is not marked as invalid. This macro ** is for use inside assert() statements only. -** -** A Memory cell is initialized if at least one of the -** MEM_Null, MEM_Str, MEM_Int, MEM_Real, MEM_Blob, or MEM_IntReal bits -** is set. It is "undefined" if all those bits are zero. */ #ifdef SQLITE_DEBUG -#define memIsValid(M) ((M)->flags & MEM_AffMask)!=0 +#define memIsValid(M) ((M)->flags & MEM_Undefined)==0 #endif /* -** Each auxiliary data pointer stored by a user defined function +** Each auxiliary data pointer stored by a user defined function ** implementation calling sqlite3_set_auxdata() is stored in an instance ** of this structure. All such structures associated with a single VM ** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed ** when the VM is halted (if not before). */ @@ -23813,145 +18754,116 @@ FuncDef *pFunc; /* Pointer to function information */ Mem *pMem; /* Memory cell used to store aggregate context */ Vdbe *pVdbe; /* The VM that owns this context */ int iOp; /* Instruction number of OP_Function */ int isError; /* Error code returned by the function. */ - u8 enc; /* Encoding to use for results */ u8 skipFlag; /* Skip accumulator loading if true */ - u16 argc; /* Number of arguments */ + u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ + u8 argc; /* Number of arguments */ sqlite3_value *argv[1]; /* Argument set */ }; /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ typedef unsigned bft; /* Bit Field Type */ -/* The ScanStatus object holds a single value for the -** sqlite3_stmt_scanstatus() interface. -** -** aAddrRange[]: -** This array is used by ScanStatus elements associated with EQP -** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is -** an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[] -** values should be summed to calculate the NCYCLE value. Each pair of -** integer addresses is a start and end address (both inclusive) for a range -** instructions. A start value of 0 indicates an empty range. -*/ typedef struct ScanStatus ScanStatus; struct ScanStatus { int addrExplain; /* OP_Explain for loop */ - int aAddrRange[6]; int addrLoop; /* Address of "loops" counter */ int addrVisit; /* Address of "rows visited" counter */ int iSelectID; /* The "Select-ID" for this loop */ LogEst nEst; /* Estimated output rows per loop */ char *zName; /* Name of table or index */ }; -/* The DblquoteStr object holds the text of a double-quoted -** string for a prepared statement. A linked list of these objects -** is constructed during statement parsing and is held on Vdbe.pDblStr. -** When computing a normalized SQL statement for an SQL statement, that -** list is consulted for each double-quoted identifier to see if the -** identifier should really be a string literal. -*/ -typedef struct DblquoteStr DblquoteStr; -struct DblquoteStr { - DblquoteStr *pNextStr; /* Next string literal in the list */ - char z[8]; /* Dequoted value for the string */ -}; - /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. */ struct Vdbe { sqlite3 *db; /* The database connection that owns this statement */ - Vdbe **ppVPrev,*pVNext; /* Linked list of VDBEs with the same Vdbe.db */ + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ Parse *pParse; /* Parsing context used to create this Vdbe */ ynVar nVar; /* Number of entries in aVar[] */ + u32 magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ int nCursor; /* Number of slots in apCsr[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ - i64 nChange; /* Number of db changes made since last reset */ - int iStatement; /* Statement number (or 0 if has no opened stmt) */ + int nChange; /* Number of db changes made since last reset */ + int iStatement; /* Statement number (or 0 if has not opened stmt) */ i64 iCurrentTime; /* Value of julianday('now') for this statement */ i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ - Mem *aMem; /* The memory locations */ - Mem **apArg; /* Arguments to currently executing user function */ - VdbeCursor **apCsr; /* One element of this array for each open cursor */ - Mem *aVar; /* Values for the OP_Variable opcode. */ /* When allocating a new Vdbe object, all of the fields below should be ** initialized to zero or NULL */ Op *aOp; /* Space to hold the virtual machine's program */ - int nOp; /* Number of instructions in the program */ - int nOpAlloc; /* Slots allocated for aOp[] */ + Mem *aMem; /* The memory locations */ + Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ - Mem *pResultRow; /* Current output row */ + Mem *pResultSet; /* Pointer to an array of results */ char *zErrMsg; /* Error message written here */ + VdbeCursor **apCsr; /* One element of this array for each open cursor */ + Mem *aVar; /* Values for the OP_Variable opcode. */ VList *pVList; /* Name of variables */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif + int nOp; /* Number of instructions in the program */ #ifdef SQLITE_DEBUG int rcApp; /* errcode set by sqlite3_result_error_code() */ - u32 nWrite; /* Number of write operations that have occurred */ #endif u16 nResColumn; /* Number of columns in one row of the result set */ - u16 nResAlloc; /* Column slots allocated to aColName[] */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ - u8 eVdbeState; /* On of the VDBE_*_STATE values */ - bft expired:2; /* 1: recompile VM immediately 2: when convenient */ - bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */ + 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 */ bft changeCntOn:1; /* True to update the change-counter */ + bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ - bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - u32 aCounter[9]; /* 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 */ -#ifdef SQLITE_ENABLE_NORMALIZE - char *zNormSql; /* Normalization of the associated SQL statement */ - DblquoteStr *pDblStr; /* List of double-quoted string literals */ -#endif void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ int nFrame; /* Number of frames in pFrame list */ u32 expmask; /* Binding to these vars invalidates VM */ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + i64 *anExec; /* Number of times each op has been executed */ int nScan; /* Entries in aScan[] */ ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ #endif }; /* -** The following are allowed values for Vdbe.eVdbeState +** The following are allowed values for Vdbe.magic */ -#define VDBE_INIT_STATE 0 /* Prepared statement under construction */ -#define VDBE_READY_STATE 1 /* Ready to run but not yet started */ -#define VDBE_RUN_STATE 2 /* Run in progress */ -#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */ +#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */ +#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */ +#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */ +#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */ +#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */ /* -** Structure used to store the context required by the +** Structure used to store the context required by the ** sqlite3_preupdate_*() API functions. */ struct PreUpdate { Vdbe *v; VdbeCursor *pCsr; /* Cursor to read old values from */ @@ -23959,141 +18871,79 @@ u8 *aRecord; /* old.* database record */ KeyInfo keyinfo; UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ - int iBlobWrite; /* Value returned by preupdate_blobwrite() */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ - Mem oldipk; /* Memory cell holding "old" IPK value */ Mem *aNew; /* Array of new.* values */ - Table *pTab; /* Schema object being updated */ + Table *pTab; /* Schema object being upated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ - sqlite3_value **apDflt; /* Array of default values, if required */ -}; - -/* -** An instance of this object is used to pass an vector of values into -** OP_VFilter, the xFilter method of a virtual table. The vector is the -** set of values on the right-hand side of an IN constraint. -** -** The value as passed into xFilter is an sqlite3_value with a "pointer" -** type, such as is generated by sqlite3_result_pointer() and read by -** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null -** and a subtype of 'p'. The sqlite3_vtab_in_first() and _next() interfaces -** know how to use this object to step through all the values in the -** right operand of the IN constraint. -*/ -typedef struct ValueList ValueList; -struct ValueList { - BtCursor *pCsr; /* An ephemeral table holding all values */ - sqlite3_value *pOut; /* Register to hold each decoded output value */ -}; - -/* Size of content associated with serial types that fit into a -** single-byte varint. -*/ -#ifndef SQLITE_AMALGAMATION -SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[]; -#endif +}; /* ** Function prototypes */ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); -SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p); -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*); +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); +#endif SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8); -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in); -# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X) -#else -# define swapMixedEndianFloat(X) -#endif -SQLITE_PRIVATE void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*); +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); +SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); -#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB) -SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**); -SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*); -#endif -#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) -SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*); -#endif -#if !defined(SQLITE_OMIT_EXPLAIN) SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); -#endif SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*)); +SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif -SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); +SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*); SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); -#ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); -#else -SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); -#endif -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); -#endif -SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); -SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); -SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*); +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); -SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8); +SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); -SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem*p); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); -#endif -#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB) SQLITE_PRIVATE const char *sqlite3OpcodeName(int); -#endif SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*); -#endif -SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ -SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */ +SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK -SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( - Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int); +SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); #endif SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *); @@ -24102,21 +18952,11 @@ 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 *); -SQLITE_PRIVATE void sqlite3VdbeValueListFree(void*); - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); -SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*); -#else -# define sqlite3VdbeIncrWriteCounter(V,C) -# define sqlite3VdbeAssertAbortable(V) -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) +#if !defined(SQLITE_OMIT_SHARED_CACHE) SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*); #else # define sqlite3VdbeEnter(X) #endif @@ -24137,11 +18977,11 @@ # define sqlite3VdbeCheckFk(p,i) 0 #endif #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr); +SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); #endif #ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8); SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem); #endif @@ -24263,10 +19103,11 @@ assert( op>=0 && opwsdStat.mxValue[op] ){ wsdStat.mxValue[op] = newValue; } } @@ -24311,36 +19152,10 @@ *pHighwater = (int)iHwtr; } 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); -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - nInit += countLookasideSlots(db->lookaside.pSmallInit); - nFree += countLookasideSlots(db->lookaside.pSmallFree); -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit; - return db->lookaside.nSlot - (nInit+nFree); -} - /* ** Query status information for a single database connection */ SQLITE_API int sqlite3_db_status( sqlite3 *db, /* The database connection whose status is desired */ @@ -24356,28 +19171,14 @@ } #endif sqlite3_mutex_enter(db->mutex); switch( op ){ case SQLITE_DBSTATUS_LOOKASIDE_USED: { - *pCurrent = sqlite3LookasideUsed(db, pHighwater); + *pCurrent = db->lookaside.nOut; + *pHighwater = db->lookaside.mxOut; if( resetFlag ){ - 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; - } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - p = db->lookaside.pSmallFree; - if( p ){ - while( p->pNext ) p = p->pNext; - p->pNext = db->lookaside.pSmallInit; - db->lookaside.pSmallInit = db->lookaside.pSmallFree; - db->lookaside.pSmallFree = 0; - } -#endif + db->lookaside.mxOut = db->lookaside.nOut; } break; } case SQLITE_DBSTATUS_LOOKASIDE_HIT: @@ -24394,11 +19195,11 @@ db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0; } break; } - /* + /* ** Return an approximation for the amount of memory currently used ** by all pagers associated with the given database connection. The ** highwater mark is meaningless and is returned as zero. */ case SQLITE_DBSTATUS_CACHE_USED_SHARED: @@ -24432,19 +19233,17 @@ int i; /* Used to iterate through schemas */ int nByte = 0; /* Used to accumulate return value */ sqlite3BtreeEnterAll(db); db->pnBytesFreed = &nByte; - assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); - db->lookaside.pEnd = db->lookaside.pStart; for(i=0; inDb; i++){ Schema *pSchema = db->aDb[i].pSchema; if( ALWAYS(pSchema!=0) ){ HashElem *p; nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( - pSchema->tblHash.count + pSchema->tblHash.count + pSchema->trigHash.count + pSchema->idxHash.count + pSchema->fkeyHash.count ); nByte += sqlite3_msize(pSchema->tblHash.ht); @@ -24459,11 +19258,10 @@ sqlite3DeleteTable(db, (Table *)sqliteHashData(p)); } } } db->pnBytesFreed = 0; - db->lookaside.pEnd = db->lookaside.pTrueEnd; sqlite3BtreeLeaveAll(db); *pHighwater = 0; *pCurrent = nByte; break; @@ -24477,16 +19275,14 @@ case SQLITE_DBSTATUS_STMT_USED: { struct Vdbe *pVdbe; /* Used to iterate through VMs */ int nByte = 0; /* Used to accumulate return value */ db->pnBytesFreed = &nByte; - assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); - db->lookaside.pEnd = db->lookaside.pStart; - for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pVNext){ - sqlite3VdbeDelete(pVdbe); + for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ + sqlite3VdbeClearObject(db, pVdbe); + sqlite3DbFree(db, pVdbe); } - db->lookaside.pEnd = db->lookaside.pTrueEnd; db->pnBytesFreed = 0; *pHighwater = 0; /* IMP: R-64479-57858 */ *pCurrent = nByte; @@ -24493,21 +19289,18 @@ break; } /* ** Set *pCurrent to the total cache hits or misses encountered by all - ** pagers the database handle is connected to. *pHighwater is always set + ** pagers the database handle is connected to. *pHighwater is always set ** to zero. */ - case SQLITE_DBSTATUS_CACHE_SPILL: - op = SQLITE_DBSTATUS_CACHE_WRITE+1; - /* no break */ deliberate_fall_through case SQLITE_DBSTATUS_CACHE_HIT: case SQLITE_DBSTATUS_CACHE_MISS: case SQLITE_DBSTATUS_CACHE_WRITE:{ int i; - u64 nRet = 0; + int nRet = 0; assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ @@ -24516,11 +19309,11 @@ } } *pHighwater = 0; /* IMP: R-42420-56072 */ /* IMP: R-54100-20147 */ /* IMP: R-29431-39229 */ - *pCurrent = (int)nRet & 0x7fffffff; + *pCurrent = nRet; break; } /* Set *pCurrent to non-zero if there are unresolved deferred foreign ** key constraints. Set *pCurrent to zero if all foreign key constraints @@ -24552,20 +19345,20 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement date and time -** functions for SQLite. +** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** SQLite processes all times and dates as julian day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian -** calendar system. +** calendar system. ** ** 1970-01-01 00:00:00 is JD 2440587.5 ** 2000-01-01 00:00:00 is JD 2451544.5 ** ** This implementation requires years to be expressed as a 4-digit number @@ -24581,11 +19374,11 @@ ** The conversion algorithms are implemented based on descriptions ** in the following text: ** ** Jean Meeus ** Astronomical Algorithms, 2nd Edition, 1998 -** ISBN 0-943396-61-1 +** ISBM 0-943396-61-1 ** Willmann-Bell, Inc ** Richmond, Virginia (USA) */ /* #include "sqliteInt.h" */ /* #include */ @@ -24613,18 +19406,16 @@ 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 nFloor; /* Days to implement "floor" */ - unsigned rawS : 1; /* Raw numeric value stored in s */ - unsigned isError : 1; /* An overflow has occurred */ - unsigned useSubsec : 1; /* Display subsecond precision */ - unsigned isUtc : 1; /* Time is known to be UTC */ - unsigned isLocal : 1; /* Time is known to be localtime */ + char validTZ; /* True (1) if tz is valid */ + char tzSet; /* Timezone was set explicitly */ + char isError; /* An overflow has occurred */ }; /* ** Convert zDate into one or more integers according to the conversion @@ -24653,12 +19444,12 @@ ** ** The function returns the number of successful conversions. */ static int getDigits(const char *zDate, const char *zFormat, ...){ /* The aMx[] array translates the 3rd character of each format - ** spec into a max size: a b c d e f */ - static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 }; + ** spec into a max size: a b c d e f */ + static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 }; va_list ap; int cnt = 0; char nextC; va_start(ap, zFormat); do{ @@ -24718,12 +19509,10 @@ sgn = -1; }else if( c=='+' ){ sgn = +1; }else if( c=='Z' || c=='z' ){ zDate++; - p->isLocal = 0; - p->isUtc = 1; goto zulu_time; }else{ return c!=0; } zDate++; @@ -24732,10 +19521,11 @@ } zDate += 5; p->tz = sgn*(nMn + nHr*60); zulu_time: while( sqlite3Isspace(*zDate) ){ zDate++; } + p->tzSet = 1; return *zDate!=0; } /* ** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. @@ -24764,13 +19554,10 @@ ms = ms*10.0 + *zDate - '0'; rScale *= 10.0; zDate++; } ms /= rScale; - /* Truncate to avoid problems with sub-milliseconds - ** rounding. https://sqlite.org/forum/forumpost/766a2c9231 */ - if( ms>0.999 ) ms = 0.999; } }else{ s = 0; } p->validJD = 0; @@ -24778,10 +19565,11 @@ p->validHMS = 1; p->h = h; p->m = m; p->s = s + ms; if( parseTimezone(zDate, p) ) return 1; + p->validTZ = (p->tz!=0)?1:0; return 0; } /* ** Put the DateTime object into its error state. @@ -24816,49 +19604,24 @@ } if( M<=2 ){ Y--; M += 12; } - A = (Y+4800)/100; - B = 38 - A + (A/4); + A = Y/100; + B = 2 - A + (A/4); X1 = 36525*(Y+4716)/100; X2 = 306001*(M+1)/10000; p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000); p->validJD = 1; if( p->validHMS ){ - p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5); - if( p->tz ){ + p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000); + if( p->validTZ ){ p->iJD -= p->tz*60000; p->validYMD = 0; p->validHMS = 0; - p->tz = 0; - p->isUtc = 1; - p->isLocal = 0; - } - } -} - -/* -** Given the YYYY-MM-DD information current in p, determine if there -** is day-of-month overflow and set nFloor to the number of days that -** would need to be subtracted from the date in order to bring the -** date back to the end of the month. -*/ -static void computeFloor(DateTime *p){ - assert( p->validYMD || p->isError ); - assert( p->D>=0 && p->D<=31 ); - assert( p->M>=0 && p->M<=12 ); - if( p->D<=28 ){ - p->nFloor = 0; - }else if( (1<M) & 0x15aa ){ - p->nFloor = 0; - }else if( p->M!=2 ){ - p->nFloor = (p->D==31); - }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){ - p->nFloor = p->D - 28; - }else{ - p->nFloor = p->D - 29; + p->validTZ = 0; + } } } /* ** Parse dates of the form @@ -24896,32 +19659,25 @@ p->validJD = 0; p->validYMD = 1; p->Y = neg ? -Y : Y; p->M = M; p->D = D; - computeFloor(p); - if( p->tz ){ + if( p->validTZ ){ computeJD(p); } return 0; } - -static void clearYMD_HMS_TZ(DateTime *p); /* Forward declaration */ - /* ** Set the time to the current time reported by the VFS. ** ** Return the number of errors. */ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ p->iJD = sqlite3StmtCurrentTime(context); if( p->iJD>0 ){ p->validJD = 1; - p->isUtc = 1; - p->isLocal = 0; - clearYMD_HMS_TZ(p); return 0; }else{ return 1; } } @@ -24946,48 +19702,43 @@ ** the number of errors. ** ** The following are acceptable forms for the input string: ** ** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM -** DDDD.DD +** DDDD.DD ** now ** ** In the first form, the +/-HH:MM is always optional. The fractional ** seconds extension (the ".FFF") is optional. The seconds portion ** (":SS.FFF") is option. The year and date can be omitted as long ** as there is a time string. The time string can be omitted as long ** as there is a year and date. */ static int parseDateOrTime( - sqlite3_context *context, - const char *zDate, + sqlite3_context *context, + const char *zDate, DateTime *p ){ double r; if( parseYyyyMmDd(zDate,p)==0 ){ return 0; }else if( parseHhMmSs(zDate, p)==0 ){ return 0; - }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ + }else if( sqlite3StrICmp(zDate,"now")==0){ return setDateTimeToCurrent(context, p); - }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ + }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ setRawDateNumber(p, r); return 0; - }else if( (sqlite3StrICmp(zDate,"subsec")==0 - || sqlite3StrICmp(zDate,"subsecond")==0) - && sqlite3NotPureFunc(context) ){ - p->useSubsec = 1; - return setDateTimeToCurrent(context, p); } return 1; } /* 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 +** 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) /* @@ -25001,11 +19752,11 @@ /* ** Compute the Year, Month, and Day from the julian day number. */ static void computeYMD(DateTime *p){ - int Z, alpha, A, B, C, D, E, X1; + int Z, A, B, C, D, E, X1; if( p->validYMD ) return; if( !p->validJD ){ p->Y = 2000; p->M = 1; p->D = 1; @@ -25012,12 +19763,12 @@ }else if( !validJulianDay(p->iJD) ){ datetimeError(p); return; }else{ Z = (int)((p->iJD + 43200000)/86400000); - alpha = (int)((Z + 32044.75)/36524.25) - 52; - A = Z + 1 + alpha - ((alpha+100)/4) + 25; + A = (int)((Z - 1867216.25)/36524.25); + A = Z + 1 + A - (A/4); B = A + 1524; C = (int)((B - 122.1)/365.25); D = (36525*(C&32767))/100; E = (int)((B-D)/30.6001); X1 = (int)(30.6001*E); @@ -25030,18 +19781,21 @@ /* ** Compute the Hour, Minute, and Seconds from the julian day number. */ static void computeHMS(DateTime *p){ - int day_ms, day_min; /* milliseconds, minutes into the day */ + int s; if( p->validHMS ) return; computeJD(p); - day_ms = (int)((p->iJD + 43200000) % 86400000); - p->s = (day_ms % 60000)/1000.0; - day_min = day_ms/60000; - p->m = day_min % 60; - p->h = day_min / 60; + s = (int)((p->iJD + 43200000) % 86400000); + p->s = s/1000.0; + s = (int)p->s; + p->s -= s; + p->h = s/3600; + s -= p->h*3600; + p->m = s/60; + p->s += s - p->m*60; p->rawS = 0; p->validHMS = 1; } /* @@ -25056,24 +19810,24 @@ ** Clear the YMD and HMS and the TZ */ static void clearYMD_HMS_TZ(DateTime *p){ p->validYMD = 0; p->validHMS = 0; - p->tz = 0; + p->validTZ = 0; } #ifndef SQLITE_OMIT_LOCALTIME /* ** On recent Windows platforms, the localtime_s() function is available -** as part of the "Secure CRT". It is essentially equivalent to -** localtime_r() available under most POSIX platforms, except that the +** as part of the "Secure CRT". It is essentially equivalent to +** localtime_r() available under most POSIX platforms, except that the ** order of the parameters is reversed. ** ** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx. ** ** If the user has not indicated to use localtime_r() or localtime_s() -** already, check for an MSVC build environment that provides +** already, check for an MSVC build environment that provides ** localtime_s(). */ #if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \ && defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) #undef HAVE_LOCALTIME_S @@ -25084,14 +19838,12 @@ ** The following routine implements the rough equivalent of localtime_r() ** using whatever operating-system specific localtime facility that ** is available. This routine returns 0 on success and ** non-zero on any kind of error. ** -** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this -** routine will always fail. If bLocaltimeFault is nonzero and -** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is -** invoked in place of the OS-defined localtime() function. +** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this +** routine will always fail. ** ** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C ** library function localtime_r() is used to assist in the calculation of ** local time. */ @@ -25098,39 +19850,23 @@ static int osLocaltime(time_t *t, struct tm *pTm){ int rc; #if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S struct tm *pX; #if SQLITE_THREADSAFE>0 - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); pX = localtime(t); #ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ){ - if( sqlite3GlobalConfig.xAltLocaltime!=0 - && 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm) - ){ - pX = pTm; - }else{ - pX = 0; - } - } + if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; #endif if( pX ) *pTm = *pX; -#if SQLITE_THREADSAFE>0 sqlite3_mutex_leave(mutex); -#endif rc = pX==0; #else #ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ){ - if( sqlite3GlobalConfig.xAltLocaltime!=0 ){ - return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm); - }else{ - return 1; - } - } + if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; #endif #if HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; #else rc = localtime_s(pTm, t); @@ -25141,60 +19877,71 @@ #endif /* SQLITE_OMIT_LOCALTIME */ #ifndef SQLITE_OMIT_LOCALTIME /* -** Assuming the input DateTime is UTC, move it to its localtime equivalent. +** Compute the difference (in milliseconds) between localtime and UTC +** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs, +** return this value and set *pRc to SQLITE_OK. +** +** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value +** is undefined in this case. */ -static int toLocaltime( - DateTime *p, /* Date at which to calculate offset */ - sqlite3_context *pCtx /* Write error here if one occurs */ +static sqlite3_int64 localtimeOffset( + DateTime *p, /* Date at which to calculate offset */ + sqlite3_context *pCtx, /* Write error here if one occurs */ + int *pRc /* OUT: Error code. SQLITE_OK or ERROR */ ){ + DateTime x, y; time_t t; struct tm sLocal; - int iYearDiff; /* Initialize the contents of sLocal to avoid a compiler warning. */ memset(&sLocal, 0, sizeof(sLocal)); - computeJD(p); - if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */ - || p->iJD>2130141456*(i64)100000 /* 2038-01-18 */ - ){ + x = *p; + computeYMD_HMS(&x); + if( x.Y<1971 || x.Y>=2038 ){ /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only ** works for years between 1970 and 2037. For dates outside this range, ** SQLite attempts to map the year into an equivalent year within this ** range, do the calculation, then map the year back. */ - DateTime x = *p; - computeYMD_HMS(&x); - iYearDiff = (2000 + x.Y%4) - x.Y; - x.Y += iYearDiff; - x.validJD = 0; - computeJD(&x); - t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); - }else{ - iYearDiff = 0; - t = (time_t)(p->iJD/1000 - 21086676*(i64)10000); - } + x.Y = 2000; + x.M = 1; + x.D = 1; + x.h = 0; + x.m = 0; + x.s = 0.0; + } else { + int s = (int)(x.s + 0.5); + x.s = s; + } + x.tz = 0; + x.validJD = 0; + computeJD(&x); + t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); if( osLocaltime(&t, &sLocal) ){ sqlite3_result_error(pCtx, "local time unavailable", -1); - return SQLITE_ERROR; - } - p->Y = sLocal.tm_year + 1900 - iYearDiff; - p->M = sLocal.tm_mon + 1; - p->D = sLocal.tm_mday; - p->h = sLocal.tm_hour; - p->m = sLocal.tm_min; - p->s = sLocal.tm_sec + (p->iJD%1000)*0.001; - p->validYMD = 1; - p->validHMS = 1; - p->validJD = 0; - p->rawS = 0; - p->tz = 0; - p->isError = 0; - return SQLITE_OK; + *pRc = SQLITE_ERROR; + return 0; + } + y.Y = sLocal.tm_year + 1900; + y.M = sLocal.tm_mon + 1; + y.D = sLocal.tm_mday; + y.h = sLocal.tm_hour; + y.m = sLocal.tm_min; + y.s = sLocal.tm_sec; + y.validYMD = 1; + y.validHMS = 1; + y.validJD = 0; + y.rawS = 0; + y.validTZ = 0; + y.isError = 0; + computeJD(&y); + *pRc = SQLITE_OK; + return y.iJD - x.iJD; } #endif /* SQLITE_OMIT_LOCALTIME */ /* ** The following table defines various date transformations of the form @@ -25203,42 +19950,24 @@ ** ** Where NNN is an arbitrary floating-point number and "days" can be one ** of several units of time. */ static const struct { - u8 nName; /* Length of the name */ - char zName[7]; /* Name of the transformation */ - float rLimit; /* Maximum NNN value for this transform */ - float rXform; /* Constant used for this transform */ + 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", 4.6427e+14, 1.0 }, - /* 1 */ { 6, "minute", 7.7379e+12, 60.0 }, - /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 }, - /* 3 */ { 3, "day", 5373485.0, 86400.0 }, - /* 4 */ { 5, "month", 176546.0, 2592000.0 }, - /* 5 */ { 4, "year", 14713.0, 31536000.0 }, + { 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 }, }; -/* -** If the DateTime p is raw number, try to figure out if it is -** a julian day number of a unix timestamp. Set the p value -** appropriately. -*/ -static void autoAdjustDate(DateTime *p){ - if( !p->rawS || p->validJD ){ - p->rawS = 0; - }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */ - && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */ - ){ - double r = p->s*1000.0 + 210866760000000.0; - clearYMD_HMS_TZ(p); - p->iJD = (sqlite3_int64)(r + 0.5); - p->validJD = 1; - p->rawS = 0; - } -} - /* ** Process a modifier to a date-time stamp. The modifiers are ** as follows: ** ** NNN days @@ -25245,24 +19974,18 @@ ** NNN hours ** NNN minutes ** NNN.NNNN seconds ** NNN months ** NNN years -** +/-YYYY-MM-DD HH:MM:SS.SSS -** ceiling -** floor ** start of month ** start of year ** start of week ** start of day ** weekday N ** unixepoch -** auto ** localtime ** utc -** subsec -** subsecond ** ** Return 0 on success and 1 if there is any kind of error. If the error ** is in a system call (i.e. localtime()), then an error message is written ** to context pCtx. If the error is an unrecognized modifier, no error is ** written to pCtx. @@ -25269,90 +19992,26 @@ */ 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 idx /* Parameter index of the modifier */ + DateTime *p /* The date/time value to be modified */ ){ int rc = 1; double r; switch(sqlite3UpperToLower[(u8)z[0]] ){ - case 'a': { - /* - ** auto - ** - ** If rawS is available, then interpret as a julian day number, or - ** a unix timestamp, depending on its magnitude. - */ - if( sqlite3_stricmp(z, "auto")==0 ){ - if( idx>1 ) return 1; /* IMP: R-33611-57934 */ - autoAdjustDate(p); - rc = 0; - } - break; - } - case 'c': { - /* - ** ceiling - ** - ** Resolve day-of-month overflow by rolling forward into the next - ** month. As this is the default action, this modifier is really - ** a no-op that is only included for symmetry. See "floor". - */ - if( sqlite3_stricmp(z, "ceiling")==0 ){ - computeJD(p); - clearYMD_HMS_TZ(p); - rc = 0; - p->nFloor = 0; - } - break; - } - case 'f': { - /* - ** floor - ** - ** Resolve day-of-month overflow by rolling back to the end of the - ** previous month. - */ - if( sqlite3_stricmp(z, "floor")==0 ){ - computeJD(p); - p->iJD -= p->nFloor*86400000; - clearYMD_HMS_TZ(p); - rc = 0; - } - break; - } - case 'j': { - /* - ** julianday - ** - ** Always interpret the prior number as a julian-day value. If this - ** is not the first modifier, or if the prior argument is not a numeric - ** value in the allowed range of julian day numbers understood by - ** SQLite (0..5373484.5) then the result will be NULL. - */ - if( sqlite3_stricmp(z, "julianday")==0 ){ - if( idx>1 ) return 1; /* IMP: R-31176-64601 */ - if( p->validJD && p->rawS ){ - rc = 0; - p->rawS = 0; - } - } - break; - } #ifndef SQLITE_OMIT_LOCALTIME case 'l': { /* localtime ** ** Assuming the current time value is UTC (a.k.a. GMT), shift it to ** show local time. */ - if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ - rc = p->isLocal ? SQLITE_OK : toLocaltime(p, pCtx); - p->isUtc = 0; - p->isLocal = 1; + if( sqlite3_stricmp(z, "localtime")==0 ){ + computeJD(p); + p->iJD += localtimeOffset(p, pCtx, &rc); + clearYMD_HMS_TZ(p); } break; } #endif case 'u': { @@ -25361,49 +20020,34 @@ ** ** Treat the current value of p->s as the number of ** seconds since 1970. Convert to a real julian day number. */ if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){ - if( idx>1 ) return 1; /* IMP: R-49255-55373 */ r = p->s*1000.0 + 210866760000000.0; if( r>=0.0 && r<464269060800000.0 ){ clearYMD_HMS_TZ(p); - p->iJD = (sqlite3_int64)(r + 0.5); + p->iJD = (sqlite3_int64)r; p->validJD = 1; p->rawS = 0; rc = 0; } } #ifndef SQLITE_OMIT_LOCALTIME - else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ - if( p->isUtc==0 ){ - i64 iOrigJD; /* Original localtime */ - i64 iGuess; /* Guess at the corresponding utc time */ - int cnt = 0; /* Safety to prevent infinite loop */ - i64 iErr; /* Guess is off by this much */ - + else if( sqlite3_stricmp(z, "utc")==0 ){ + if( p->tzSet==0 ){ + sqlite3_int64 c1; computeJD(p); - iGuess = iOrigJD = p->iJD; - iErr = 0; - do{ - DateTime new; - memset(&new, 0, sizeof(new)); - iGuess -= iErr; - new.iJD = iGuess; - new.validJD = 1; - rc = toLocaltime(&new, pCtx); - if( rc ) return rc; - computeJD(&new); - iErr = new.iJD - iOrigJD; - }while( iErr && cnt++<3 ); - memset(p, 0, sizeof(*p)); - p->iJD = iGuess; - p->validJD = 1; - p->isUtc = 1; - p->isLocal = 0; - } - rc = SQLITE_OK; + c1 = localtimeOffset(p, pCtx, &rc); + if( rc==SQLITE_OK ){ + p->iJD -= c1; + clearYMD_HMS_TZ(p); + p->iJD += c1 - localtimeOffset(p, pCtx, &rc); + } + p->tzSet = 1; + }else{ + rc = SQLITE_OK; + } } #endif break; } case 'w': { @@ -25413,15 +20057,15 @@ ** Move the date to the same time on the next occurrence of ** 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( sqlite3_strnicmp(z, "weekday ", 8)==0 - && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0 - && r>=0.0 && r<7.0 && (n=(int)r)==r ){ + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8) + && (n=(int)r)==r && n>=0 && r<7 ){ sqlite3_int64 Z; computeYMD_HMS(p); - p->tz = 0; + p->validTZ = 0; p->validJD = 0; computeJD(p); Z = ((p->iJD + 129600000)/86400000) % 7; if( Z>n ) Z -= 7; p->iJD += (n - Z)*86400000; @@ -25434,34 +20078,20 @@ /* ** start of TTTTT ** ** Move the date backwards to the beginning of the current day, ** or month or year. - ** - ** subsecond - ** subsec - ** - ** Show subsecond precision in the output of datetime() and - ** unixepoch() and strftime('%s'). */ - if( sqlite3_strnicmp(z, "start of ", 9)!=0 ){ - if( sqlite3_stricmp(z, "subsec")==0 - || sqlite3_stricmp(z, "subsecond")==0 - ){ - p->useSubsec = 1; - rc = 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->tz = 0; + p->validTZ = 0; p->validJD = 0; if( sqlite3_stricmp(z,"month")==0 ){ p->D = 1; rc = 0; }else if( sqlite3_stricmp(z,"year")==0 ){ @@ -25485,88 +20115,32 @@ case '7': case '8': case '9': { double rRounder; int i; - int Y,M,D,h,m,x; - const char *z2 = z; - char z0 = z[0]; - for(n=1; z[n]; n++){ - if( z[n]==':' ) break; - if( sqlite3Isspace(z[n]) ) break; - if( z[n]=='-' ){ - if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break; - if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break; - } - } - if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){ - assert( rc==1 ); - break; - } - if( z[n]=='-' ){ - /* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the - ** specified number of years, months, and days. MM is limited to - ** the range 0-11 and DD is limited to 0-30. - */ - if( z0!='+' && z0!='-' ) break; /* Must start with +/- */ - if( n==5 ){ - if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break; - }else{ - assert( n==6 ); - if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break; - z++; - } - if( M>=12 ) break; /* M range 0..11 */ - if( D>=31 ) break; /* D range 0..30 */ - computeYMD_HMS(p); - p->validJD = 0; - if( z0=='-' ){ - p->Y -= Y; - p->M -= M; - D = -D; - }else{ - p->Y += Y; - p->M += M; - } - x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; - p->Y += x; - p->M -= x*12; - computeFloor(p); - computeJD(p); - p->validHMS = 0; - p->validYMD = 0; - p->iJD += (i64)D*86400000; - if( z[11]==0 ){ - rc = 0; - break; - } - if( sqlite3Isspace(z[11]) - && getDigits(&z[12], "20c:20e", &h, &m)==2 - ){ - z2 = &z[12]; - n = 2; - }else{ - break; - } - } - if( z2[n]==':' ){ + for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} + if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){ + rc = 1; + break; + } + if( z[n]==':' ){ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the ** specified number of hours, minutes, seconds, and fractional seconds ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be ** omitted. */ - + const char *z2 = z; DateTime tx; sqlite3_int64 day; if( !sqlite3Isdigit(*z2) ) z2++; memset(&tx, 0, sizeof(tx)); if( parseHhMmSs(z2, &tx) ) break; computeJD(&tx); tx.iJD -= 43200000; day = tx.iJD/86400000; tx.iJD -= day*86400000; - if( z0=='-' ) tx.iJD = -tx.iJD; + if( z[0]=='-' ) tx.iJD = -tx.iJD; computeJD(p); clearYMD_HMS_TZ(p); p->iJD += tx.iJD; rc = 0; break; @@ -25575,48 +20149,43 @@ /* 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<3 || n>10 ) break; + if( n>10 || n<3 ) break; if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; computeJD(p); - assert( rc==1 ); + rc = 1; rRounder = r<0 ? -0.5 : +0.5; - p->nFloor = 0; for(i=0; i-aXformType[i].rLimit && rM += (int)r; x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; p->Y += x; p->M -= x*12; - computeFloor(p); p->validJD = 0; r -= (int)r; break; } - case 5: { /* Special processing to add years */ + case 2: { /* Special processing to add years */ int y = (int)r; - assert( strcmp(aXformType[5].zName,"year")==0 ); computeYMD_HMS(p); - assert( p->M>=0 && p->M<=12 ); p->Y += y; - computeFloor(p); p->validJD = 0; r -= (int)r; break; } } computeJD(p); - p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder); + p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder); rc = 0; break; } } clearYMD_HMS_TZ(p); @@ -25637,21 +20206,20 @@ ** ** If there are zero parameters (if even argv[0] is undefined) ** then assume a default value of "now" for argv[0]. */ static int isDate( - sqlite3_context *context, - int argc, - sqlite3_value **argv, + sqlite3_context *context, + int argc, + sqlite3_value **argv, DateTime *p ){ int i, n; const unsigned char *z; int eType; memset(p, 0, sizeof(*p)); if( argc==0 ){ - if( !sqlite3NotPureFunc(context) ) return 1; return setDateTimeToCurrent(context, p); } if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT || eType==SQLITE_INTEGER ){ setRawDateNumber(p, sqlite3_value_double(argv[0])); @@ -25662,20 +20230,14 @@ } } for(i=1; iisError || !validJulianDay(p->iJD) ) return 1; - if( argc==1 && p->validYMD && p->D>28 ){ - /* Make sure a YYYY-MM-DD is normalized. - ** Example: 2023-02-31 -> 2023-03-03 */ - assert( p->validJD ); - p->validYMD = 0; - } return 0; } /* @@ -25698,32 +20260,10 @@ computeJD(&x); sqlite3_result_double(context, x.iJD/86400000.0); } } -/* -** unixepoch( TIMESTRING, MOD, MOD, ...) -** -** Return the number of seconds (including fractional seconds) since -** the unix epoch of 1970-01-01 00:00:00 GMT. -*/ -static void unixepochFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - computeJD(&x); - if( x.useSubsec ){ - sqlite3_result_double(context, (x.iJD - 21086676*(i64)10000000)/1000.0); - }else{ - sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000); - } - } -} - /* ** datetime( TIMESTRING, MOD, MOD, ...) ** ** Return YYYY-MM-DD HH:MM:SS */ @@ -25732,55 +20272,15 @@ int argc, sqlite3_value **argv ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - int Y, s, n; - char zBuf[32]; + char zBuf[100]; computeYMD_HMS(&x); - Y = x.Y; - if( Y<0 ) Y = -Y; - zBuf[1] = '0' + (Y/1000)%10; - zBuf[2] = '0' + (Y/100)%10; - zBuf[3] = '0' + (Y/10)%10; - zBuf[4] = '0' + (Y)%10; - zBuf[5] = '-'; - zBuf[6] = '0' + (x.M/10)%10; - zBuf[7] = '0' + (x.M)%10; - zBuf[8] = '-'; - zBuf[9] = '0' + (x.D/10)%10; - zBuf[10] = '0' + (x.D)%10; - zBuf[11] = ' '; - zBuf[12] = '0' + (x.h/10)%10; - zBuf[13] = '0' + (x.h)%10; - zBuf[14] = ':'; - zBuf[15] = '0' + (x.m/10)%10; - zBuf[16] = '0' + (x.m)%10; - zBuf[17] = ':'; - if( x.useSubsec ){ - s = (int)(1000.0*x.s + 0.5); - zBuf[18] = '0' + (s/10000)%10; - zBuf[19] = '0' + (s/1000)%10; - zBuf[20] = '.'; - zBuf[21] = '0' + (s/100)%10; - zBuf[22] = '0' + (s/10)%10; - zBuf[23] = '0' + (s)%10; - zBuf[24] = 0; - n = 24; - }else{ - s = (int)x.s; - zBuf[18] = '0' + (s/10)%10; - zBuf[19] = '0' + (s)%10; - zBuf[20] = 0; - n = 20; - } - if( x.Y<0 ){ - zBuf[0] = '-'; - sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(context, &zBuf[1], n-1, SQLITE_TRANSIENT); - } + sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d", + x.Y, x.M, x.D, x.h, x.m, (int)(x.s)); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); } } /* ** time( TIMESTRING, MOD, MOD, ...) @@ -25792,37 +20292,14 @@ int argc, sqlite3_value **argv ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - int s, n; - char zBuf[16]; + char zBuf[100]; computeHMS(&x); - zBuf[0] = '0' + (x.h/10)%10; - zBuf[1] = '0' + (x.h)%10; - zBuf[2] = ':'; - zBuf[3] = '0' + (x.m/10)%10; - zBuf[4] = '0' + (x.m)%10; - zBuf[5] = ':'; - if( x.useSubsec ){ - s = (int)(1000.0*x.s + 0.5); - zBuf[6] = '0' + (s/10000)%10; - zBuf[7] = '0' + (s/1000)%10; - zBuf[8] = '.'; - zBuf[9] = '0' + (s/100)%10; - zBuf[10] = '0' + (s/10)%10; - zBuf[11] = '0' + (s)%10; - zBuf[12] = 0; - n = 12; - }else{ - s = (int)x.s; - zBuf[6] = '0' + (s/10)%10; - zBuf[7] = '0' + (s)%10; - zBuf[8] = 0; - n = 8; - } - sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); } } /* ** date( TIMESTRING, MOD, MOD, ...) @@ -25834,276 +20311,167 @@ int argc, sqlite3_value **argv ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - int Y; - char zBuf[16]; + char zBuf[100]; computeYMD(&x); - Y = x.Y; - if( Y<0 ) Y = -Y; - zBuf[1] = '0' + (Y/1000)%10; - zBuf[2] = '0' + (Y/100)%10; - zBuf[3] = '0' + (Y/10)%10; - zBuf[4] = '0' + (Y)%10; - zBuf[5] = '-'; - zBuf[6] = '0' + (x.M/10)%10; - zBuf[7] = '0' + (x.M)%10; - zBuf[8] = '-'; - zBuf[9] = '0' + (x.D/10)%10; - zBuf[10] = '0' + (x.D)%10; - zBuf[11] = 0; - if( x.Y<0 ){ - zBuf[0] = '-'; - sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT); - } - } -} - -/* -** Compute the number of days after the most recent January 1. -** -** In other words, compute the zero-based day number for the -** current year: -** -** Jan01 = 0, Jan02 = 1, ..., Jan31 = 30, Feb01 = 31, ... -** Dec31 = 364 or 365. -*/ -static int daysAfterJan01(DateTime *pDate){ - DateTime jan01 = *pDate; - assert( jan01.validYMD ); - assert( jan01.validHMS ); - assert( pDate->validJD ); - jan01.validJD = 0; - jan01.M = 1; - jan01.D = 1; - computeJD(&jan01); - return (int)((pDate->iJD-jan01.iJD+43200000)/86400000); -} - -/* -** Return the number of days after the most recent Monday. -** -** In other words, return the day of the week according -** to this code: -** -** 0=Monday, 1=Tuesday, 2=Wednesday, ..., 6=Sunday. -*/ -static int daysAfterMonday(DateTime *pDate){ - assert( pDate->validJD ); - return (int)((pDate->iJD+43200000)/86400000) % 7; -} - -/* -** Return the number of days after the most recent Sunday. -** -** In other words, return the day of the week according -** to this code: -** -** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday -*/ -static int daysAfterSunday(DateTime *pDate){ - assert( pDate->validJD ); - return (int)((pDate->iJD+129600000)/86400000) % 7; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + } } /* ** strftime( FORMAT, TIMESTRING, MOD, MOD, ...) ** ** Return a string described by FORMAT. Conversions as follows: ** -** %d day of month 01-31 -** %e day of month 1-31 +** %d day of month ** %f ** fractional seconds SS.SSS -** %F ISO date. YYYY-MM-DD -** %G ISO year corresponding to %V 0000-9999. -** %g 2-digit ISO year corresponding to %V 00-99 ** %H hour 00-24 -** %k hour 0-24 (leading zero converted to space) -** %I hour 01-12 -** %j day of year 001-366 +** %j day of year 000-366 ** %J ** julian day number -** %l hour 1-12 (leading zero converted to space) ** %m month 01-12 ** %M minute 00-59 -** %p "am" or "pm" -** %P "AM" or "PM" -** %R time as HH:MM ** %s seconds since 1970-01-01 ** %S seconds 00-59 -** %T time as HH:MM:SS -** %u day of week 1-7 Monday==1, Sunday==7 -** %w day of week 0-6 Sunday==0, Monday==1 -** %U week of year 00-53 (First Sunday is start of week 01) -** %V week of year 01-53 (First week containing Thursday is week 01) -** %W week of year 00-53 (First Monday is start of week 01) +** %w day of week 0-6 sunday==0 +** %W week of year 00-53 ** %Y year 0000-9999 ** %% % */ static void strftimeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ DateTime x; + u64 n; size_t i,j; + char *z; sqlite3 *db; const char *zFmt; - sqlite3_str sRes; - - + char zBuf[100]; if( argc==0 ) return; zFmt = (const char*)sqlite3_value_text(argv[0]); if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return; db = sqlite3_context_db_handle(context); - sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - + for(i=0, n=1; zFmt[i]; i++, n++){ + if( zFmt[i]=='%' ){ + switch( zFmt[i+1] ){ + case 'd': + case 'H': + case 'm': + case 'M': + case 'S': + case 'W': + n++; + /* fall thru */ + case 'w': + case '%': + break; + case 'f': + n += 8; + break; + case 'j': + n += 3; + break; + case 'Y': + n += 8; + break; + case 's': + case 'J': + n += 50; + break; + default: + return; /* ERROR. return a NULL */ + } + i++; + } + } + testcase( n==sizeof(zBuf)-1 ); + testcase( n==sizeof(zBuf) ); + testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); + testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ); + if( n(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + return; + }else{ + z = sqlite3DbMallocRawNN(db, (int)n); + if( z==0 ){ + sqlite3_result_error_nomem(context); + return; + } + } computeJD(&x); computeYMD_HMS(&x); for(i=j=0; zFmt[i]; i++){ - char cf; - if( zFmt[i]!='%' ) continue; - if( j59.999) ) s = 59.999; - sqlite3_str_appendf(&sRes, "%06.3f", s); - break; - } - case 'F': { - sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D); - break; - } - case 'G': /* Fall thru */ - case 'g': { - DateTime y = x; - assert( y.validJD ); - /* Move y so that it is the Thursday in the same week as x */ - y.iJD += (3 - daysAfterMonday(&x))*86400000; - y.validYMD = 0; - computeYMD(&y); - if( cf=='g' ){ - sqlite3_str_appendf(&sRes, "%02d", y.Y%100); - }else{ - sqlite3_str_appendf(&sRes, "%04d", y.Y); - } - break; - } - case 'H': - case 'k': { - sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h); - break; - } - case 'I': /* Fall thru */ - case 'l': { - int h = x.h; - if( h>12 ) h -= 12; - if( h==0 ) h = 12; - sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); - break; - } - case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */ - sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1); - break; - } - case 'J': { /* Julian day number. (Non-standard) */ - sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0); - break; - } - case 'm': { - sqlite3_str_appendf(&sRes,"%02d",x.M); - break; - } - case 'M': { - sqlite3_str_appendf(&sRes,"%02d",x.m); - break; - } - case 'p': /* Fall thru */ - case 'P': { - if( x.h>=12 ){ - sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2); - }else{ - sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2); - } - break; - } - case 'R': { - sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m); - break; - } - case 's': { - if( x.useSubsec ){ - sqlite3_str_appendf(&sRes,"%.3f", - (x.iJD - 21086676*(i64)10000000)/1000.0); - }else{ - i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000); - sqlite3_str_appendf(&sRes,"%lld",iS); - } - break; - } - case 'S': { - sqlite3_str_appendf(&sRes,"%02d",(int)x.s); - break; - } - case 'T': { - sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s); - break; - } - case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */ - case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */ - char c = (char)daysAfterSunday(&x) + '0'; - if( c=='0' && cf=='u' ) c = '7'; - sqlite3_str_appendchar(&sRes, 1, c); - break; - } - case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */ - sqlite3_str_appendf(&sRes,"%02d", - (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7); - break; - } - case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */ - DateTime y = x; - /* Adjust y so that is the Thursday in the same week as x */ - assert( y.validJD ); - y.iJD += (3 - daysAfterMonday(&x))*86400000; - y.validYMD = 0; - computeYMD(&y); - sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1); - break; - } - case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */ - sqlite3_str_appendf(&sRes,"%02d", - (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7); - break; - } - case 'Y': { - sqlite3_str_appendf(&sRes,"%04d",x.Y); - break; - } - case '%': { - sqlite3_str_appendchar(&sRes, 1, '%'); - break; - } - default: { - sqlite3_str_reset(&sRes); - return; - } - } - } - if( j59.999 ) s = 59.999; + sqlite3_snprintf(7, &z[j],"%06.3f", s); + j += sqlite3Strlen30(&z[j]); + break; + } + case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break; + case 'W': /* Fall thru */ + case 'j': { + int nDay; /* Number of days since 1st day of year */ + DateTime y = x; + y.validJD = 0; + y.M = 1; + y.D = 1; + computeJD(&y); + nDay = (int)((x.iJD-y.iJD+43200000)/86400000); + if( zFmt[i]=='W' ){ + int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ + wd = (int)(((x.iJD+43200000)/86400000)%7); + sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7); + j += 2; + }else{ + sqlite3_snprintf(4, &z[j],"%03d",nDay+1); + j += 3; + } + break; + } + case 'J': { + sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0); + j+=sqlite3Strlen30(&z[j]); + break; + } + case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break; + case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break; + case 's': { + sqlite3_snprintf(30,&z[j],"%lld", + (i64)(x.iJD/1000 - 21086676*(i64)10000)); + j += sqlite3Strlen30(&z[j]); + break; + } + case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break; + case 'w': { + z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0'; + break; + } + case 'Y': { + sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]); + break; + } + default: z[j++] = '%'; break; + } + } + } + z[j] = 0; + sqlite3_result_text(context, z, -1, + z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC); } /* ** current_time() ** @@ -26129,119 +20497,10 @@ sqlite3_value **NotUsed2 ){ UNUSED_PARAMETER2(NotUsed, NotUsed2); dateFunc(context, 0, 0); } - -/* -** timediff(DATE1, DATE2) -** -** Return the amount of time that must be added to DATE2 in order to -** convert it into DATE2. The time difference format is: -** -** +YYYY-MM-DD HH:MM:SS.SSS -** -** The initial "+" becomes "-" if DATE1 occurs before DATE2. For -** date/time values A and B, the following invariant should hold: -** -** datetime(A) == (datetime(B, timediff(A,B)) -** -** Both DATE arguments must be either a julian day number, or an -** ISO-8601 string. The unix timestamps are not supported by this -** routine. -*/ -static void timediffFunc( - sqlite3_context *context, - int NotUsed1, - sqlite3_value **argv -){ - char sign; - int Y, M; - DateTime d1, d2; - sqlite3_str sRes; - UNUSED_PARAMETER(NotUsed1); - if( isDate(context, 1, &argv[0], &d1) ) return; - if( isDate(context, 1, &argv[1], &d2) ) return; - computeYMD_HMS(&d1); - computeYMD_HMS(&d2); - if( d1.iJD>=d2.iJD ){ - sign = '+'; - Y = d1.Y - d2.Y; - if( Y ){ - d2.Y = d1.Y; - d2.validJD = 0; - computeJD(&d2); - } - M = d1.M - d2.M; - if( M<0 ){ - Y--; - M += 12; - } - if( M!=0 ){ - d2.M = d1.M; - d2.validJD = 0; - computeJD(&d2); - } - while( d1.iJDd2.iJD ){ - M--; - if( M<0 ){ - M = 11; - Y--; - } - d2.M++; - if( d2.M>12 ){ - d2.M = 1; - d2.Y++; - } - d2.validJD = 0; - computeJD(&d2); - } - d1.iJD = d2.iJD - d1.iJD; - d1.iJD += (u64)1486995408 * (u64)100000; - } - clearYMD_HMS_TZ(&d1); - computeYMD_HMS(&d1); - sqlite3StrAccumInit(&sRes, 0, 0, 0, 100); - sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f", - sign, Y, M, d1.D-1, d1.h, d1.m, d1.s); - sqlite3ResultStrAccum(context, &sRes); -} - /* ** current_timestamp() ** ** This function returns the same value as datetime('now'). @@ -26287,70 +20546,35 @@ if( iT<=0 ) return; t = iT/1000 - 10000*(sqlite3_int64)21086676; #if HAVE_GMTIME_R pTm = gmtime_r(&t, &sNow); #else - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); pTm = gmtime(&t); if( pTm ) memcpy(&sNow, pTm, sizeof(sNow)); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); #endif if( pTm ){ strftime(zBuf, 20, zFormat, &sNow); sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); } } #endif - -#if !defined(SQLITE_OMIT_DATETIME_FUNCS) && defined(SQLITE_DEBUG) -/* -** datedebug(...) -** -** This routine returns JSON that describes the internal DateTime object. -** Used for debugging and testing only. Subject to change. -*/ -static void datedebugFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - DateTime x; - if( isDate(context, argc, argv, &x)==0 ){ - char *zJson; - zJson = sqlite3_mprintf( - "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d," - "s:%.3f,validJD:%d,validYMS:%d,validHMS:%d," - "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d," - "isUtc:%d,isLocal:%d}", - x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz, - x.s, x.validJD, x.validYMD, x.validHMS, - x.nFloor, x.rawS, x.isError, x.useSubsec, - x.isUtc, x.isLocal); - sqlite3_result_text(context, zJson, -1, sqlite3_free); - } -} -#endif /* !SQLITE_OMIT_DATETIME_FUNCS && SQLITE_DEBUG */ - /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. */ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ static FuncDef aDateTimeFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS - PURE_DATE(julianday, -1, 0, 0, juliandayFunc ), - PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ), - PURE_DATE(date, -1, 0, 0, dateFunc ), - PURE_DATE(time, -1, 0, 0, timeFunc ), - PURE_DATE(datetime, -1, 0, 0, datetimeFunc ), - PURE_DATE(strftime, -1, 0, 0, strftimeFunc ), - PURE_DATE(timediff, 2, 0, 0, timediffFunc ), -#ifdef SQLITE_DEBUG - PURE_DATE(datedebug, -1, 0, 0, datedebugFunc ), -#endif + DFUNCTION(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 ), DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), DFUNCTION(current_date, 0, 0, 0, cdateFunc ), #else STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), @@ -26461,23 +20685,21 @@ SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){ return id->pMethods->xTruncate(id, size); } SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){ DO_OS_MALLOC_TEST(id); - return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK; + return id->pMethods->xSync(id, flags); } SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ DO_OS_MALLOC_TEST(id); return id->pMethods->xFileSize(id, pSize); } SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){ DO_OS_MALLOC_TEST(id); - assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE ); return id->pMethods->xLock(id, lockType); } SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){ - assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED ); return id->pMethods->xUnlock(id, lockType); } SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ DO_OS_MALLOC_TEST(id); return id->pMethods->xCheckReservedLock(id, pResOut); @@ -26490,50 +20712,38 @@ ** really care if the VFS receives and understands the information since it ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() ** routine has no return value since the return value would be meaningless. */ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ - if( id->pMethods==0 ) return SQLITE_NOTFOUND; #ifdef SQLITE_TEST - if( op!=SQLITE_FCNTL_COMMIT_PHASETWO - && op!=SQLITE_FCNTL_LOCK_TIMEOUT - && op!=SQLITE_FCNTL_CKPT_DONE - && op!=SQLITE_FCNTL_CKPT_START - ){ + if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite ** is using a regular VFS, it is called after the corresponding ** transaction has been committed. Injecting a fault at this point - ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM + ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM ** but the transaction is committed anyway. ** ** The core must call OsFileControl() though, not OsFileControlHint(), ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably ** means the commit really has failed and an error should be returned - ** to the user. - ** - ** The CKPT_DONE and CKPT_START file-controls are write-only signals - ** to the cksumvfs. Their return code is meaningless and is ignored - ** by the SQLite core, so there is no point in simulating OOMs for them. - */ + ** to the user. */ DO_OS_MALLOC_TEST(id); } #endif return id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ - if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg); + (void)id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); } SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ - if( NEVER(id->pMethods==0) ) return 0; return id->pMethods->xDeviceCharacteristics(id); } -#ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){ return id->pMethods->xShmLock(id, offset, n, flags); } SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){ id->pMethods->xShmBarrier(id); @@ -26549,11 +20759,10 @@ void volatile **pp /* OUT: Pointer to mapping */ ){ 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 */ SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ DO_OS_MALLOC_TEST(id); @@ -26588,19 +20797,18 @@ DO_OS_MALLOC_TEST(0); /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before ** reaching the VFS. */ - assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) ); - rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut); + rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); assert( rc==SQLITE_OK || pFile->pMethods==0 ); return rc; } SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ DO_OS_MALLOC_TEST(0); assert( dirSync==0 || dirSync==1 ); - return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK; + return pVfs->xDelete(pVfs, zPath, dirSync); } SQLITE_PRIVATE int sqlite3OsAccess( sqlite3_vfs *pVfs, const char *zPath, int flags, @@ -26619,12 +20827,10 @@ zPathOut[0] = 0; return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); } #ifndef SQLITE_OMIT_LOAD_EXTENSION SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - assert( zPath!=0 ); - assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */ return pVfs->xDlOpen(pVfs, zPath); } SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ pVfs->xDlError(pVfs, nByte, zBufOut); } @@ -26634,19 +20840,11 @@ SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ pVfs->xDlClose(pVfs, pHandle); } #endif /* SQLITE_OMIT_LOAD_EXTENSION */ SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - if( sqlite3Config.iPrngSeed ){ - memset(zBufOut, 0, nByte); - if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int); - memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte); - return SQLITE_OK; - }else{ - return pVfs->xRandomness(pVfs, nByte, zBufOut); - } - + return pVfs->xRandomness(pVfs, nByte, zBufOut); } SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ return pVfs->xSleep(pVfs, nMicro); } SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs *pVfs){ @@ -26682,19 +20880,16 @@ pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile); if( pFile ){ rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); if( rc!=SQLITE_OK ){ sqlite3_free(pFile); - *ppFile = 0; }else{ *ppFile = pFile; } }else{ - *ppFile = 0; rc = SQLITE_NOMEM_BKPT; } - assert( *ppFile!=0 || rc!=SQLITE_OK ); return rc; } SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *pFile){ assert( pFile ); sqlite3OsClose(pFile); @@ -26732,11 +20927,11 @@ #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return 0; #endif #if SQLITE_THREADSAFE - mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ if( zVfs==0 ) break; if( strcmp(zVfs, pVfs->zName)==0 ) break; @@ -26747,11 +20942,11 @@ /* ** Unlink a VFS from the linked list */ static void vfsUnlink(sqlite3_vfs *pVfs){ - assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) ); + assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) ); if( pVfs==0 ){ /* No-op */ }else if( vfsList==pVfs ){ vfsList = pVfs->pNext; }else if( vfsList ){ @@ -26778,11 +20973,11 @@ #endif #ifdef SQLITE_ENABLE_API_ARMOR if( pVfs==0 ) return SQLITE_MISUSE_BKPT; #endif - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) + MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); if( makeDflt || vfsList==0 ){ pVfs->pNext = vfsList; vfsList = pVfs; @@ -26797,16 +20992,13 @@ /* ** Unregister a VFS so that it is no longer accessible. */ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ - MUTEX_LOGIC(sqlite3_mutex *mutex;) -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return rc; +#if SQLITE_THREADSAFE + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); sqlite3_mutex_leave(mutex); return SQLITE_OK; } @@ -26823,21 +21015,21 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** -** This file contains code to support the concept of "benign" +** This file contains code to support the concept of "benign" ** malloc failures (when the xMalloc() or xRealloc() method of the ** sqlite3_mem_methods structure fails to allocate a block of memory -** and returns 0). +** and returns 0). ** ** Most malloc failures are non-benign. After they occur, SQLite ** abandons the current operation and returns an error code (usually ** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily -** fatal. For example, if a malloc fails while resizing a hash table, this -** is completely recoverable simply by not carrying out the resize. The -** hash table will continue to function normally. So a malloc failure +** fatal. For example, if a malloc fails while resizing a hash table, this +** is completely recoverable simply by not carrying out the resize. The +** hash table will continue to function normally. So a malloc failure ** during a hash table resize is a benign fault. */ /* #include "sqliteInt.h" */ @@ -27035,11 +21227,11 @@ (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x)) #else /* if not __APPLE__ */ /* -** Use standard C library malloc and free on non-Apple systems. +** Use standard C library malloc and free on non-Apple systems. ** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined. */ #define SQLITE_MALLOC(x) malloc(x) #define SQLITE_FREE(x) free(x) #define SQLITE_REALLOC(x,y) realloc((x),(y)) @@ -27121,11 +21313,11 @@ /* ** Like free() but works for allocations obtained from sqlite3MemMalloc() ** or sqlite3MemRealloc(). ** ** For this low-level routine, we already know that pPrior!=0 since -** cases where pPrior==0 will have been intercepted and dealt with +** cases where pPrior==0 will have been intecepted and dealt with ** by higher-level routines. */ static void sqlite3MemFree(void *pPrior){ #ifdef SQLITE_MALLOCSIZE SQLITE_FREE(pPrior); @@ -27209,17 +21401,17 @@ size_t len; if( _sqliteZone_ ){ return SQLITE_OK; } len = sizeof(cpuCount); - /* One usually wants to use hw.activecpu for MT decisions, but not here */ + /* One usually wants to use hw.acctivecpu for MT decisions, but not here */ sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0); if( cpuCount>1 ){ /* defer MT decisions to system malloc */ _sqliteZone_ = malloc_default_zone(); }else{ - /* only 1 core, use our own zone to contention over global locks, + /* only 1 core, use our own zone to contention over global locks, ** e.g. we have our own dedicated locks */ _sqliteZone_ = malloc_create_zone(4096, 0); malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap"); } #endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */ @@ -27339,11 +21531,11 @@ ** into a single structure named "mem". This is to keep the ** static variables organized and to reduce namespace pollution ** when this module is combined with other in the amalgamation. */ static struct { - + /* ** Mutex to control access to the memory allocation subsystem. */ sqlite3_mutex *mutex; @@ -27350,11 +21542,11 @@ /* ** Head and tail of a linked list of all outstanding allocations */ struct MemBlockHdr *pFirst; struct MemBlockHdr *pLast; - + /* ** The number of levels of backtrace to save in new allocations. */ int nBacktrace; void (*xBacktrace)(int, int, void **); @@ -27363,11 +21555,11 @@ ** Title text to insert in front of each block */ int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ char zTitle[100]; /* The title text */ - /* + /* ** sqlite3MallocDisallow() increments the following counter. ** sqlite3MallocAllow() decrements it. */ int disallow; /* Do not allow memory allocation */ @@ -27408,11 +21600,11 @@ ** Given an allocation, find the MemBlockHdr for that allocation. ** ** This routine checks the guards at either end of the allocation and ** if they are incorrect it asserts. */ -static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){ +static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ struct MemBlockHdr *p; int *pInt; u8 *pU8; int nReserve; @@ -27422,11 +21614,11 @@ nReserve = ROUND8(p->iSize); pInt = (int*)pAllocation; pU8 = (u8*)pAllocation; assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD ); /* This checks any of the "extra" bytes allocated due - ** to rounding up to an 8 byte boundary to ensure + ** to rounding up to an 8 byte boundary to ensure ** they haven't been overwritten. */ while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 ); return p; } @@ -27551,21 +21743,21 @@ randomFill((char*)pInt, nByte); memset(((char*)pInt)+nByte, 0x65, nReserve-nByte); p = (void*)pInt; } sqlite3_mutex_leave(mem.mutex); - return p; + return p; } /* ** Free memory. */ static void sqlite3MemFree(void *pPrior){ struct MemBlockHdr *pHdr; void **pBt; char *z; - assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0 + assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0 || mem.mutex!=0 ); pHdr = sqlite3MemsysGetHeader(pPrior); pBt = (void**)pHdr; pBt -= pHdr->nBacktraceSlots; sqlite3_mutex_enter(mem.mutex); @@ -27587,19 +21779,19 @@ z -= pHdr->nTitle; adjustStats((int)pHdr->iSize, -1); randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + (int)pHdr->iSize + sizeof(int) + pHdr->nTitle); free(z); - sqlite3_mutex_leave(mem.mutex); + sqlite3_mutex_leave(mem.mutex); } /* ** Change the size of an existing memory allocation. ** ** For this debugging implementation, we *always* make a copy of the -** allocation into a new place in memory. In this way, if the -** higher level code is using pointer to the old allocation, it is +** allocation into a new place in memory. In this way, if the +** higher level code is using pointer to the old allocation, it is ** much more likely to break and we are much more liking to find ** the error. */ static void *sqlite3MemRealloc(void *pPrior, int nByte){ struct MemBlockHdr *pOldHdr; @@ -27638,11 +21830,11 @@ /* ** Set the "type" of an allocation. */ SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){ - if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){ + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); pHdr->eType = eType; } @@ -27655,13 +21847,13 @@ ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); */ -SQLITE_PRIVATE int sqlite3MemdebugHasType(const void *p, u8 eType){ +SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){ int rc = 1; - if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){ + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ if( (pHdr->eType&eType)==0 ){ rc = 0; @@ -27677,13 +21869,13 @@ ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); */ -SQLITE_PRIVATE int sqlite3MemdebugNoType(const void *p, u8 eType){ +SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){ int rc = 1; - if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){ + if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ if( (pHdr->eType&eType)!=0 ){ rc = 0; @@ -27729,11 +21921,11 @@ mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]); } } /* -** Open the file indicated and write a log of all unfreed memory +** Open the file indicated and write a log of all unfreed memory ** allocations into that log. */ SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){ FILE *out; struct MemBlockHdr *pHdr; @@ -27746,11 +21938,11 @@ return; } for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ char *z = (char*)pHdr; z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; - fprintf(out, "**** %lld bytes at %p from %s ****\n", + fprintf(out, "**** %lld bytes at %p from %s ****\n", pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); if( pHdr->nBacktrace ){ fflush(out); pBt = (void**)pHdr; pBt -= pHdr->nBacktraceSlots; @@ -27759,11 +21951,11 @@ } } fprintf(out, "COUNTS:\n"); for(i=0; i=nBlock ); - if( nBlock>=mem3.szKeyBlk-1 ){ - /* Use the entire key chunk */ - void *p = memsys3Checkout(mem3.iKeyBlk, mem3.szKeyBlk); - mem3.iKeyBlk = 0; - mem3.szKeyBlk = 0; - mem3.mnKeyBlk = 0; + assert( mem3.szMaster>=nBlock ); + if( nBlock>=mem3.szMaster-1 ){ + /* Use the entire master */ + void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster); + mem3.iMaster = 0; + mem3.szMaster = 0; + mem3.mnMaster = 0; return p; }else{ - /* Split the key block. Return the tail. */ + /* Split the master block. Return the tail. */ u32 newi, x; - newi = mem3.iKeyBlk + mem3.szKeyBlk - nBlock; - assert( newi > mem3.iKeyBlk+1 ); - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = nBlock; - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x |= 2; + newi = mem3.iMaster + mem3.szMaster - nBlock; + assert( newi > mem3.iMaster+1 ); + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2; mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; - mem3.szKeyBlk -= nBlock; - mem3.aPool[newi-1].u.hdr.prevSize = mem3.szKeyBlk; - x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2; - mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x; - if( mem3.szKeyBlk < mem3.mnKeyBlk ){ - mem3.mnKeyBlk = mem3.szKeyBlk; + mem3.szMaster -= nBlock; + mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster; + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + if( mem3.szMaster < mem3.mnMaster ){ + mem3.mnMaster = mem3.szMaster; } return (void*)&mem3.aPool[newi]; } } /* ** *pRoot is the head of a list of free chunks of the same size ** or same size hash. In other words, *pRoot is an entry in either -** mem3.aiSmall[] or mem3.aiHash[]. +** mem3.aiSmall[] or mem3.aiHash[]. ** ** This routine examines all entries on the given list and tries -** to coalesce each entries with adjacent free chunks. +** to coalesce each entries with adjacent free chunks. ** -** If it sees a chunk that is larger than mem3.iKeyBlk, it replaces -** the current mem3.iKeyBlk with the new larger chunk. In order for -** this mem3.iKeyBlk replacement to work, the key chunk must be +** If it sees a chunk that is larger than mem3.iMaster, it replaces +** the current mem3.iMaster with the new larger chunk. In order for +** this mem3.iMaster replacement to work, the master chunk must be ** linked into the hash tables. That is not the normal state of -** affairs, of course. The calling routine must link the key +** affairs, of course. The calling routine must link the master ** chunk before invoking this routine, then must unlink the (possibly -** changed) key chunk once this routine has finished. +** changed) master chunk once this routine has finished. */ static void memsys3Merge(u32 *pRoot){ u32 iNext, prev, size, i, x; assert( sqlite3_mutex_held(mem3.mutex) ); @@ -28127,13 +22319,13 @@ memsys3Link(prev); i = prev; }else{ size /= 4; } - if( size>mem3.szKeyBlk ){ - mem3.iKeyBlk = i; - mem3.szKeyBlk = size; + if( size>mem3.szMaster ){ + mem3.iMaster = i; + mem3.szMaster = size; } } } /* @@ -28178,41 +22370,41 @@ } } /* STEP 2: ** Try to satisfy the allocation by carving a piece off of the end - ** of the key chunk. This step usually works if step 1 fails. + ** of the master chunk. This step usually works if step 1 fails. */ - if( mem3.szKeyBlk>=nBlock ){ - return memsys3FromKeyBlk(nBlock); + if( mem3.szMaster>=nBlock ){ + return memsys3FromMaster(nBlock); } - /* STEP 3: + /* STEP 3: ** Loop through the entire memory pool. Coalesce adjacent free - ** chunks. Recompute the key chunk as the largest free chunk. + ** chunks. Recompute the master chunk as the largest free chunk. ** Then try again to satisfy the allocation by carving a piece off - ** of the end of the key chunk. This step happens very + ** of the end of the master chunk. This step happens very ** rarely (we hope!) */ for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){ memsys3OutOfMemory(toFree); - if( mem3.iKeyBlk ){ - memsys3Link(mem3.iKeyBlk); - mem3.iKeyBlk = 0; - mem3.szKeyBlk = 0; + if( mem3.iMaster ){ + memsys3Link(mem3.iMaster); + mem3.iMaster = 0; + mem3.szMaster = 0; } for(i=0; i=nBlock ){ - return memsys3FromKeyBlk(nBlock); + if( mem3.szMaster ){ + memsys3Unlink(mem3.iMaster); + if( mem3.szMaster>=nBlock ){ + return memsys3FromMaster(nBlock); } } } /* If none of the above worked, then we fail. */ @@ -28238,27 +22430,27 @@ mem3.aPool[i-1].u.hdr.size4x &= ~1; mem3.aPool[i+size-1].u.hdr.prevSize = size; mem3.aPool[i+size-1].u.hdr.size4x &= ~2; memsys3Link(i); - /* Try to expand the key using the newly freed chunk */ - if( mem3.iKeyBlk ){ - while( (mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x&2)==0 ){ - size = mem3.aPool[mem3.iKeyBlk-1].u.hdr.prevSize; - mem3.iKeyBlk -= size; - mem3.szKeyBlk += size; - memsys3Unlink(mem3.iKeyBlk); - x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2; - mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x; - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk; - } - x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2; - while( (mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x&1)==0 ){ - memsys3Unlink(mem3.iKeyBlk+mem3.szKeyBlk); - mem3.szKeyBlk += mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x/4; - mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x; - mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk; + /* Try to expand the master using the newly freed chunk */ + if( mem3.iMaster ){ + while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){ + size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize; + mem3.iMaster -= size; + mem3.szMaster += size; + memsys3Unlink(mem3.iMaster); + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster; + } + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){ + memsys3Unlink(mem3.iMaster+mem3.szMaster); + mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster; } } } /* @@ -28292,11 +22484,11 @@ sqlite3_int64 *p; assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */ memsys3Enter(); p = memsys3MallocUnsafe(nBytes); memsys3Leave(); - return (void*)p; + return (void*)p; } /* ** Free memory. */ @@ -28350,15 +22542,15 @@ /* Store a pointer to the memory block in global structure mem3. */ assert( sizeof(Mem3Block)==8 ); mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap; mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2; - /* Initialize the key block. */ - mem3.szKeyBlk = mem3.nPool; - mem3.mnKeyBlk = mem3.szKeyBlk; - mem3.iKeyBlk = 1; - mem3.aPool[0].u.hdr.size4x = (mem3.szKeyBlk<<2) + 2; + /* Initialize the master block. */ + mem3.szMaster = mem3.nPool; + mem3.mnMaster = mem3.szMaster; + mem3.iMaster = 1; + mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2; mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool; mem3.aPool[mem3.nPool].u.hdr.size4x = 1; return SQLITE_OK; } @@ -28373,11 +22565,11 @@ } /* -** Open the file indicated and write a log of all unfreed memory +** Open the file indicated and write a log of all unfreed memory ** allocations into that log. */ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){ #ifdef SQLITE_DEBUG FILE *out; @@ -28414,34 +22606,34 @@ } if( size&1 ){ fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8); }else{ fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8, - i==mem3.iKeyBlk ? " **key**" : ""); + i==mem3.iMaster ? " **master**" : ""); } } for(i=0; i0; j=mem3.aPool[j].u.list.next){ fprintf(out, " %p(%d)", &mem3.aPool[j], (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); } - fprintf(out, "\n"); + fprintf(out, "\n"); } for(i=0; i0; j=mem3.aPool[j].u.list.next){ fprintf(out, " %p(%d)", &mem3.aPool[j], (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); } - fprintf(out, "\n"); + fprintf(out, "\n"); } - fprintf(out, "key=%d\n", mem3.iKeyBlk); - fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szKeyBlk*8); - fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnKeyBlk*8); + fprintf(out, "master=%d\n", mem3.iMaster); + fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8); + fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8); sqlite3_mutex_leave(mem3.mutex); if( out==stdout ){ fflush(stdout); }else{ fclose(out); @@ -28450,11 +22642,11 @@ UNUSED_PARAMETER(zFilename); #endif } /* -** This routine is the only routine in this file with external +** This routine is the only routine in this file with external ** linkage. ** ** Populate the low-level memory allocation function pointers in ** sqlite3GlobalConfig.m with pointers to the routines in this file. The ** arguments specify the block of memory to manage. @@ -28490,16 +22682,16 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement a memory -** allocation subsystem for use by SQLite. +** allocation subsystem for use by SQLite. ** ** This version of the memory allocation subsystem omits all ** use of malloc(). The application gives SQLite a block of memory ** before calling sqlite3_initialize() from which allocations -** are made and returned by the xMalloc() and xRealloc() +** are made and returned by the xMalloc() and xRealloc() ** implementations. Once sqlite3_initialize() has been called, ** the amount of memory available to SQLite is fixed and cannot ** be changed. ** ** This version of the memory allocation subsystem is included @@ -28515,16 +22707,16 @@ ** 3. New memory is allocated from the first available free block. ** ** This algorithm is described in: J. M. Robson. "Bounds for Some Functions ** Concerning Dynamic Storage Allocation". Journal of the Association for ** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. -** +** ** Let n be the size of the largest allocation divided by the minimum ** allocation size (after rounding all sizes up to a power of 2.) Let M ** be the maximum amount of memory ever outstanding at one time. Let ** N be the total amount of memory available for allocation. Robson -** proved that this memory allocator will never breakdown due to +** proved that this memory allocator will never breakdown due to ** fragmentation as long as the following constraint holds: ** ** N >= M*(1 + log2(n)/2) - n + 1 ** ** The sqlite3_status() logic tracks the maximum values of n and M so @@ -28531,11 +22723,11 @@ ** that an application can, at any time, verify this constraint. */ /* #include "sqliteInt.h" */ /* -** This version of the memory allocator is used only when +** This version of the memory allocator is used only when ** SQLITE_ENABLE_MEMSYS5 is defined. */ #ifdef SQLITE_ENABLE_MEMSYS5 /* @@ -28576,11 +22768,11 @@ ** Memory available for allocation */ int szAtom; /* Smallest possible allocation in bytes */ int nBlock; /* Number of szAtom sized blocks in zPool */ u8 *zPool; /* Memory available to be allocated */ - + /* ** Mutex to control access to the memory allocation subsystem. */ sqlite3_mutex *mutex; @@ -28595,11 +22787,11 @@ u32 currentCount; /* Current number of distinct checkouts */ u32 maxOut; /* Maximum instantaneous currentOut */ u32 maxCount; /* Maximum instantaneous currentCount */ u32 maxRequest; /* Largest allocation (exclusive of internal frag) */ #endif - + /* ** Lists of free blocks. aiFreelist[0] is a list of free blocks of ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2. ** aiFreelist[2] holds free blocks of size szAtom*4. And so forth. */ @@ -28771,11 +22963,11 @@ */ static void memsys5FreeUnsafe(void *pOld){ u32 size, iLogsize; int iBlock; - /* Set iBlock to the index of the block pointed to by pOld in + /* Set iBlock to the index of the block pointed to by pOld in ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool. */ iBlock = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom); /* Check that the pointer pOld points to a valid, non-free block. */ @@ -28840,11 +23032,11 @@ if( nBytes>0 ){ memsys5Enter(); p = memsys5MallocUnsafe(nBytes); memsys5Leave(); } - return (void*)p; + return (void*)p; } /* ** Free memory. ** @@ -28853,18 +23045,18 @@ */ static void memsys5Free(void *pPrior){ assert( pPrior!=0 ); memsys5Enter(); memsys5FreeUnsafe(pPrior); - memsys5Leave(); + memsys5Leave(); } /* ** Change the size of an existing memory allocation. ** ** The outer layer memory allocator prevents this routine from -** being called with pPrior==0. +** being called with pPrior==0. ** ** nBytes is always a value obtained from a prior call to ** memsys5Round(). Hence nBytes is always a non-negative power ** of two. If nBytes==0 that means that an oversize allocation ** (an allocation larger than 0x40000000) was requested and this @@ -28900,21 +23092,12 @@ ** 32-bit signed integer. Hence the largest allocation is 0x40000000 ** or 1073741824 bytes. */ static int memsys5Roundup(int n){ int iFullSz; - if( n<=mem5.szAtom*2 ){ - if( n<=mem5.szAtom ) return mem5.szAtom; - return mem5.szAtom*2; - } - if( n>0x10000000 ){ - if( n>0x40000000 ) return 0; - if( n>0x20000000 ) return 0x40000000; - return 0x20000000; - } - for(iFullSz=mem5.szAtom*8; iFullSz=(i64)n ) return iFullSz/2; + if( n > 0x40000000 ) return 0; + for(iFullSz=mem5.szAtom; iFullSzxMutexHeld(((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 ); - -#ifdef 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. */ -SQLITE_PRIVATE int sqlite3MutexInit(void){ +SQLITE_PRIVATE int sqlite3MutexInit(void){ int rc = SQLITE_OK; if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ /* If the xMutexAlloc method has not been set, then the user did not - ** install a mutex implementation via sqlite3_config() prior to + ** install a mutex implementation via sqlite3_config() prior to ** sqlite3_initialize() being called. This block copies pointers to ** the default implementation into the sqlite3GlobalConfig structure. */ sqlite3_mutex_methods const *pFrom; sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; if( sqlite3GlobalConfig.bCoreMutex ){ -#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS - pFrom = multiThreadedCheckMutex(); -#else pFrom = sqlite3DefaultMutex(); -#endif }else{ pFrom = sqlite3NoopMutex(); } pTo->xMutexInit = pFrom->xMutexInit; pTo->xMutexEnd = pFrom->xMutexEnd; @@ -29322,11 +23314,10 @@ #ifdef SQLITE_DEBUG GLOBAL(int, mutexIsInit) = 1; #endif - sqlite3MemoryBarrier(); return rc; } /* ** Shutdown the mutex system. This call frees resources allocated by @@ -29400,11 +23391,11 @@ return rc; } /* ** The sqlite3_mutex_leave() routine exits a mutex that was previously -** entered by the same thread. The behavior is undefined if the mutex +** entered by the same thread. The behavior is undefined if the mutex ** is not currently entered. If a NULL pointer is passed as an argument ** this function is a no-op. */ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ if( p ){ @@ -29415,33 +23406,20 @@ #ifndef NDEBUG /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. -** -** Because these routines raise false-positive alerts in TSAN, disable -** them (make them always return 1) when compiling with TSAN. */ SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){ -# if defined(__has_feature) -# if __has_feature(thread_sanitizer) - p = 0; -# endif -# endif assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); } SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ -# if defined(__has_feature) -# if __has_feature(thread_sanitizer) - p = 0; -# endif -# endif assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); } -#endif /* NDEBUG */ +#endif #endif /* !defined(SQLITE_MUTEX_OMIT) */ /************** End of mutex.c ***********************************************/ /************** Begin file mutex_noop.c **************************************/ @@ -29482,13 +23460,13 @@ ** ** This routines provide no mutual exclusion or error checking. */ static int noopMutexInit(void){ return SQLITE_OK; } static int noopMutexEnd(void){ return SQLITE_OK; } -static sqlite3_mutex *noopMutexAlloc(int id){ +static sqlite3_mutex *noopMutexAlloc(int id){ UNUSED_PARAMETER(id); - return (sqlite3_mutex*)8; + return (sqlite3_mutex*)8; } static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } static int noopMutexTry(sqlite3_mutex *p){ UNUSED_PARAMETER(p); @@ -29549,11 +23527,11 @@ static int debugMutexEnd(void){ return SQLITE_OK; } /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL -** that means that a mutex could not be allocated. +** that means that a mutex could not be allocated. */ static sqlite3_mutex *debugMutexAlloc(int id){ static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; sqlite3_debug_mutex *pNew = 0; switch( id ){ @@ -29689,11 +23667,11 @@ #include /* ** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields -** are necessary under two conditions: (1) Debug builds and (2) using +** are necessary under two condidtions: (1) Debug builds and (2) using ** home-grown mutexes. Encapsulate these conditions into a single #define. */ #if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX) # define SQLITE_MUTEX_NREF 1 #else @@ -29713,25 +23691,24 @@ volatile pthread_t owner; /* Thread that is within this mutex */ int trace; /* True to trace changes */ #endif }; #if SQLITE_MUTEX_NREF -# define SQLITE3_MUTEX_INITIALIZER(id) \ - {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0} +#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0} #elif defined(SQLITE_ENABLE_API_ARMOR) -# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id } +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 } #else -#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER } +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } #endif /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use only inside assert() statements. On some platforms, ** there might be race conditions that can cause these routines to ** deliver incorrect results. In particular, if pthread_equal() is ** not an atomic operation, then these routines might delivery -** incorrect results. On most platforms, pthread_equal() is a +** incorrect results. On most platforms, pthread_equal() is a ** comparison of two integers and is therefore atomic. But we are ** told that HPUX is not such a platform. If so, then these routines ** will not always work correctly on HPUX. ** ** On those platforms where pthread_equal() is not atomic, SQLite @@ -29775,11 +23752,11 @@ ** to sqlite3_mutex_alloc() is one of these integer constants: ** **
            **
          • SQLITE_MUTEX_FAST **
          • SQLITE_MUTEX_RECURSIVE -**
          • SQLITE_MUTEX_STATIC_MAIN +**
          • SQLITE_MUTEX_STATIC_MASTER **
          • SQLITE_MUTEX_STATIC_MEM **
          • SQLITE_MUTEX_STATIC_OPEN **
          • SQLITE_MUTEX_STATIC_PRNG **
          • SQLITE_MUTEX_STATIC_LRU **
          • SQLITE_MUTEX_STATIC_PMEM @@ -29809,28 +23786,28 @@ ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or ** SQLITE_MUTEX_RECURSIVE. ** ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. But for the static +** returns a different mutex on every call. But for the static ** mutex types, the same mutex is returned on every call that has ** the same type number. */ static sqlite3_mutex *pthreadMutexAlloc(int iType){ static sqlite3_mutex staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER(2), - SQLITE3_MUTEX_INITIALIZER(3), - SQLITE3_MUTEX_INITIALIZER(4), - SQLITE3_MUTEX_INITIALIZER(5), - SQLITE3_MUTEX_INITIALIZER(6), - SQLITE3_MUTEX_INITIALIZER(7), - SQLITE3_MUTEX_INITIALIZER(8), - SQLITE3_MUTEX_INITIALIZER(9), - SQLITE3_MUTEX_INITIALIZER(10), - SQLITE3_MUTEX_INITIALIZER(11), - SQLITE3_MUTEX_INITIALIZER(12), - SQLITE3_MUTEX_INITIALIZER(13) + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER }; sqlite3_mutex *p; switch( iType ){ case SQLITE_MUTEX_RECURSIVE: { p = sqlite3MallocZero( sizeof(*p) ); @@ -29845,23 +23822,17 @@ pthread_mutexattr_init(&recursiveAttr); pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&p->mutex, &recursiveAttr); pthread_mutexattr_destroy(&recursiveAttr); #endif -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - p->id = SQLITE_MUTEX_RECURSIVE; -#endif } break; } case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ pthread_mutex_init(&p->mutex, 0); -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - p->id = SQLITE_MUTEX_FAST; -#endif } break; } default: { #ifdef SQLITE_ENABLE_API_ARMOR @@ -29873,11 +23844,11 @@ p = &staticMutexes[iType-2]; break; } } #if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - assert( p==0 || p->id==iType ); + if( p ) p->id = iType; #endif return p; } @@ -29886,11 +23857,11 @@ ** allocated mutex. SQLite is careful to deallocate every ** mutex that it allocates. */ static void pthreadMutexFree(sqlite3_mutex *p){ assert( p->nRef==0 ); -#ifdef SQLITE_ENABLE_API_ARMOR +#if SQLITE_ENABLE_API_ARMOR if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) #endif { pthread_mutex_destroy(&p->mutex); sqlite3_free(p); @@ -29920,11 +23891,11 @@ /* If recursive mutexes are not available, then we have to grow ** our own. This implementation assumes that pthread_equal() ** is atomic - that it cannot be deceived into thinking self ** and p->owner are equal if p->owner changes between two values ** that are not equal to self while the comparison is taking place. - ** This implementation also assumes a coherent cache - that + ** This implementation also assumes a coherent cache - that ** separate processes cannot read different values from the same ** address at the same time. If either of these two conditions ** are not met, then the mutexes will fail and problems will result. */ { @@ -29963,11 +23934,11 @@ /* If recursive mutexes are not available, then we have to grow ** our own. This implementation assumes that pthread_equal() ** is atomic - that it cannot be deceived into thinking self ** and p->owner are equal if p->owner changes between two values ** that are not equal to self while the comparison is taking place. - ** This implementation also assumes a coherent cache - that + ** This implementation also assumes a coherent cache - that ** separate processes cannot read different values from the same ** address at the same time. If either of these two conditions ** are not met, then the mutexes will fail and problems will result. */ { @@ -30077,11 +24048,209 @@ #if SQLITE_OS_WIN /* ** Include code that is common to all os_*.c files */ -/* #include "os_common.h" */ +/************** Include os_common.h in the middle of mutex_w32.c *************/ +/************** Begin file os_common.h ***************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of os_common.h ****************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(SQLITE_HWTIME_H) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in os_common.h ******************/ + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#if defined(SQLITE_TEST) +SQLITE_API extern int sqlite3_io_error_hit; +SQLITE_API extern int sqlite3_io_error_hardhit; +SQLITE_API extern int sqlite3_io_error_pending; +SQLITE_API extern int sqlite3_io_error_persist; +SQLITE_API extern int sqlite3_io_error_benign; +SQLITE_API extern int sqlite3_diskfull_pending; +SQLITE_API extern int sqlite3_diskfull; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif /* defined(SQLITE_TEST) */ + +/* +** When testing, keep a count of the number of open files. +*/ +#if defined(SQLITE_TEST) +SQLITE_API extern int sqlite3_open_file_count; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif /* defined(SQLITE_TEST) */ + +#endif /* !defined(_OS_COMMON_H_) */ + +/************** End of os_common.h *******************************************/ +/************** Continuing where we left off in mutex_w32.c ******************/ /* ** Include the header file for the Windows VFS. */ /************** Include os_win.h in the middle of mutex_w32.c ****************/ @@ -30190,13 +24359,13 @@ */ struct sqlite3_mutex { CRITICAL_SECTION mutex; /* Mutex controlling the lock */ int id; /* Mutex type */ #ifdef SQLITE_DEBUG - volatile int nRef; /* Number of entrances */ + volatile int nRef; /* Number of enterances */ volatile DWORD owner; /* Thread holding this mutex */ - volatile LONG trace; /* True to trace changes */ + volatile int trace; /* True to trace changes */ #endif }; /* ** These are the initializer values used when declaring a "static" mutex @@ -30204,14 +24373,14 @@ ** on the Win32 platform. */ #define SQLITE_W32_MUTEX_INITIALIZER { 0 } #ifdef SQLITE_DEBUG -#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \ +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ 0L, (DWORD)0, 0 } #else -#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id } +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } #endif #ifdef SQLITE_DEBUG /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are @@ -30239,11 +24408,11 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); -#elif MSVC_VERSION>=1400 +#elif MSVC_VERSION>=1300 _ReadWriteBarrier(); #elif defined(MemoryBarrier) MemoryBarrier(); #endif } @@ -30250,22 +24419,22 @@ /* ** Initialize and deinitialize the mutex subsystem. */ static sqlite3_mutex winMutex_staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER(2), - SQLITE3_MUTEX_INITIALIZER(3), - SQLITE3_MUTEX_INITIALIZER(4), - SQLITE3_MUTEX_INITIALIZER(5), - SQLITE3_MUTEX_INITIALIZER(6), - SQLITE3_MUTEX_INITIALIZER(7), - SQLITE3_MUTEX_INITIALIZER(8), - SQLITE3_MUTEX_INITIALIZER(9), - SQLITE3_MUTEX_INITIALIZER(10), - SQLITE3_MUTEX_INITIALIZER(11), - SQLITE3_MUTEX_INITIALIZER(12), - SQLITE3_MUTEX_INITIALIZER(13) + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER }; static int winMutex_isInit = 0; static int winMutex_isNt = -1; /* <0 means "need to query" */ @@ -30323,11 +24492,11 @@ ** to sqlite3_mutex_alloc() is one of these integer constants: ** **
              **
            • SQLITE_MUTEX_FAST **
            • SQLITE_MUTEX_RECURSIVE -**
            • SQLITE_MUTEX_STATIC_MAIN +**
            • SQLITE_MUTEX_STATIC_MASTER **
            • SQLITE_MUTEX_STATIC_MEM **
            • SQLITE_MUTEX_STATIC_OPEN **
            • SQLITE_MUTEX_STATIC_PRNG **
            • SQLITE_MUTEX_STATIC_LRU **
            • SQLITE_MUTEX_STATIC_PMEM @@ -30391,19 +24560,19 @@ (void)SQLITE_MISUSE_BKPT; return 0; } #endif p = &winMutex_staticMutexes[iType-2]; + p->id = iType; #ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC - InterlockedCompareExchange(&p->trace, 1, 0); + p->trace = 1; #endif #endif break; } } - assert( p==0 || p->id==iType ); return p; } /* @@ -30587,30 +24756,40 @@ return 0; #endif } /* -** Default value of the hard heap limit. 0 means "no limit". +** An instance of the following object records the location of +** each unused scratch buffer. */ -#ifndef SQLITE_MAX_MEMORY -# define SQLITE_MAX_MEMORY 0 -#endif +typedef struct ScratchFreeslot { + struct ScratchFreeslot *pNext; /* Next unused scratch buffer */ +} ScratchFreeslot; /* ** State information local to the memory allocation subsystem. */ static SQLITE_WSD struct Mem0Global { sqlite3_mutex *mutex; /* Mutex to serialize access */ sqlite3_int64 alarmThreshold; /* The soft heap limit */ - sqlite3_int64 hardLimit; /* The hard upper bound on memory */ + + /* + ** 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, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 }; +} mem0 = { 0, 0, 0, 0, 0, 0 }; #define mem0 GLOBAL(struct Mem0Global, mem0) /* ** Return the memory allocator mutex. sqlite3_status() needs it. @@ -30636,19 +24815,12 @@ return SQLITE_OK; } #endif /* -** Set the soft heap-size limit for the library. An argument of -** zero disables the limit. A negative argument is a no-op used to -** obtain the return value. -** -** The return value is the value of the heap limit just before this -** interface was called. -** -** If the hard heap limit is enabled, then the soft heap limit cannot -** be disabled nor raised above the hard heap limit. +** Set the soft heap-size limit for the library. Passing a zero or +** negative value indicates no limit. */ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ sqlite3_int64 priorLimit; sqlite3_int64 excess; sqlite3_int64 nUsed; @@ -30660,66 +24832,55 @@ priorLimit = mem0.alarmThreshold; if( n<0 ){ sqlite3_mutex_leave(mem0.mutex); return priorLimit; } - if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){ - n = mem0.hardLimit; - } mem0.alarmThreshold = n; nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); - AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed); + mem0.nearlyFull = (n>0 && n<=nUsed); sqlite3_mutex_leave(mem0.mutex); excess = sqlite3_memory_used() - n; if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); return priorLimit; } SQLITE_API void sqlite3_soft_heap_limit(int n){ if( n<0 ) n = 0; sqlite3_soft_heap_limit64(n); } - -/* -** Set the hard heap-size limit for the library. An argument of zero -** disables the hard heap limit. A negative argument is a no-op used -** to obtain the return value without affecting the hard heap limit. -** -** The return value is the value of the hard heap limit just prior to -** calling this interface. -** -** Setting the hard heap limit will also activate the soft heap limit -** and constrain the soft heap limit to be no more than the hard heap -** limit. -*/ -SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){ - sqlite3_int64 priorLimit; -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if( rc ) return -1; -#endif - sqlite3_mutex_enter(mem0.mutex); - priorLimit = mem0.hardLimit; - if( n>=0 ){ - mem0.hardLimit = n; - if( n=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; sqlite3GlobalConfig.szPage = 0; } @@ -30732,11 +24893,11 @@ ** Return true if the heap is currently under memory pressure - in other ** words if the amount of heap used is close to the limit set by ** sqlite3_soft_heap_limit(). */ SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){ - return AtomicLoad(&mem0.nearlyFull); + return mem0.nearlyFull; } /* ** Deinitialize the memory allocation subsystem. */ @@ -30766,37 +24927,19 @@ sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag); return mx; } /* -** Trigger the alarm +** Trigger the alarm */ static void sqlite3MallocAlarm(int nByte){ if( mem0.alarmThreshold<=0 ) return; sqlite3_mutex_leave(mem0.mutex); sqlite3_release_memory(nByte); sqlite3_mutex_enter(mem0.mutex); } -#ifdef SQLITE_DEBUG -/* -** This routine is called whenever an out-of-memory condition is seen, -** It's only purpose to to serve as a breakpoint for gdb or similar -** code debuggers when working on out-of-memory conditions, for example -** caused by PRAGMA hard_heap_limit=N. -*/ -static SQLITE_NOINLINE void test_oom_breakpoint(u64 n){ - static u64 nOomFault = 0; - nOomFault += n; - /* The assert() is never reached in a human lifetime. It is here mostly - ** to prevent code optimizers from optimizing out this function. */ - assert( (nOomFault>>32) < 0xffffffff ); -} -#else -# define test_oom_breakpoint(X) /* No-op for production builds */ -#endif - /* ** Do a memory allocation with statistics and alarms. Assume the ** lock is already held. */ static void mallocWithAlarm(int n, void **pp){ @@ -30809,27 +24952,26 @@ ** 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); if( nUsed >= mem0.alarmThreshold - nFull ){ - AtomicStore(&mem0.nearlyFull, 1); + mem0.nearlyFull = 1; sqlite3MallocAlarm(nFull); - if( mem0.hardLimit ){ - nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); - if( nUsed >= mem0.hardLimit - nFull ){ - test_oom_breakpoint(1); - *pp = 0; - return; - } - } }else{ - AtomicStore(&mem0.nearlyFull, 0); + mem0.nearlyFull = 0; } } p = sqlite3GlobalConfig.m.xMalloc(nFull); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( p==0 && mem0.alarmThreshold>0 ){ @@ -30843,38 +24985,22 @@ sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); } *pp = p; } -/* -** Maximum size of any single memory allocation. -** -** This is not a limit on the total amount of memory used. This is -** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc(). -** -** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391 -** This provides a 256-byte safety margin for defense against 32-bit -** signed integer overflow bugs when computing memory allocation sizes. -** Paranoid applications might want to reduce the maximum allocation size -** further for an even larger safety margin. 0x3fffffff or 0x0fffffff -** or even smaller would be reasonable upper bounds on the size of a memory -** allocations for most applications. -*/ -#ifndef SQLITE_MAX_ALLOCATION_SIZE -# define SQLITE_MAX_ALLOCATION_SIZE 2147483391 -#endif -#if SQLITE_MAX_ALLOCATION_SIZE>2147483391 -# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391 -#endif - /* ** Allocate memory. This routine is like sqlite3_malloc() except that it ** assumes the memory subsystem has already been initialized. */ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ void *p; - if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){ + if( n==0 || n>=0x7fffff00 ){ + /* A memory allocation of a number of bytes which is near the maximum + ** signed integer value might cause an integer overflow inside of the + ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving + ** 255 bytes of overhead. SQLite itself will never use anything near + ** this amount. The only way to reach the limit is with sqlite3_malloc() */ p = 0; }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); mallocWithAlarm((int)n, &p); sqlite3_mutex_leave(mem0.mutex); @@ -30900,63 +25026,146 @@ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif 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 */ #ifndef SQLITE_OMIT_LOOKASIDE -static int isLookaside(sqlite3 *db, const void *p){ - return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd); +static int isLookaside(sqlite3 *db, void *p){ + return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd); } #else #define isLookaside(A,B) 0 #endif /* ** Return the size of a memory allocation previously obtained from ** sqlite3Malloc() or sqlite3_malloc(). */ -SQLITE_PRIVATE int sqlite3MallocSize(const void *p){ - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - return sqlite3GlobalConfig.m.xSize((void*)p); -} -static int lookasideMallocSize(sqlite3 *db, const void *p){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - return plookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL; -#else - return db->lookaside.szTrue; -#endif -} -SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, const void *p){ - assert( p!=0 ); -#ifdef SQLITE_DEBUG - if( db==0 ){ - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - }else if( !isLookaside(db,p) ){ - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - } -#endif - if( db ){ - if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){ - assert( sqlite3_mutex_held(db->mutex) ); - return LOOKASIDE_SMALL; - } -#endif - if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){ - assert( sqlite3_mutex_held(db->mutex) ); - return db->lookaside.szTrue; - } - } - } - return sqlite3GlobalConfig.m.xSize((void*)p); +SQLITE_PRIVATE int sqlite3MallocSize(void *p){ + assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + return sqlite3GlobalConfig.m.xSize(p); +} +SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ + assert( p!=0 ); + if( db==0 || !isLookaside(db,p) ){ +#ifdef SQLITE_DEBUG + if( db==0 ){ + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + }else{ + assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + } +#endif + return sqlite3GlobalConfig.m.xSize(p); + }else{ + assert( sqlite3_mutex_held(db->mutex) ); + return db->lookaside.sz; + } } SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return p ? sqlite3GlobalConfig.m.xSize(p) : 0; @@ -30995,82 +25204,32 @@ */ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ assert( db==0 || sqlite3_mutex_held(db->mutex) ); assert( p!=0 ); if( db ){ - if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pSmallFree; - db->lookaside.pSmallFree = pBuf; - return; - } -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pFree; - db->lookaside.pFree = pBuf; - return; - } - } if( db->pnBytesFreed ){ measureAllocationSize(db, p); return; + } + if( isLookaside(db, p) ){ + LookasideSlot *pBuf = (LookasideSlot*)p; +#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; } } assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); sqlite3_free(p); } -SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3 *db, void *p){ - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( p!=0 ); - if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pSmallFree; - db->lookaside.pSmallFree = pBuf; - return; - } -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - assert( db->pnBytesFreed==0 ); -#ifdef SQLITE_DEBUG - memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */ -#endif - pBuf->pNext = db->lookaside.pFree; - db->lookaside.pFree = pBuf; - return; - } - } - if( db->pnBytesFreed ){ - measureAllocationSize(db, p); - return; - } - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - 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); } @@ -31099,30 +25258,22 @@ ** xRoundup. */ nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); if( nOld==nNew ){ pNew = pOld; }else if( sqlite3GlobalConfig.bMemstat ){ - sqlite3_int64 nUsed; sqlite3_mutex_enter(mem0.mutex); sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); nDiff = nNew - nOld; - if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >= + if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= mem0.alarmThreshold-nDiff ){ sqlite3MallocAlarm(nDiff); - if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){ - sqlite3_mutex_leave(mem0.mutex); - test_oom_breakpoint(1); - return 0; - } } pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( pNew==0 && mem0.alarmThreshold>0 ){ sqlite3MallocAlarm((int)nBytes); pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); } -#endif if( pNew ){ nNew = sqlite3MallocSize(pNew); sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld); } sqlite3_mutex_leave(mem0.mutex); @@ -31152,11 +25303,11 @@ } /* ** Allocate and zero memory. -*/ +*/ SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){ void *p = sqlite3Malloc(n); if( p ){ memset(p, 0, (size_t)n); } @@ -31182,17 +25333,17 @@ static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ void *p; assert( db!=0 ); p = sqlite3Malloc(n); if( !p ) sqlite3OomFault(db); - sqlite3MemdebugSetType(p, + sqlite3MemdebugSetType(p, (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); return p; } /* -** Allocate memory, either lookaside (if possible) or heap. +** Allocate memory, either lookaside (if possible) or heap. ** If the allocation fails, set the mallocFailed flag in ** the connection pointer. ** ** If db!=0 and db->mallocFailed is true (indicating a prior malloc ** failure on the same database connection) then always return 0. @@ -31222,41 +25373,27 @@ #ifndef SQLITE_OMIT_LOOKASIDE LookasideSlot *pBuf; assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); assert( db->pnBytesFreed==0 ); - if( n>db->lookaside.sz ){ - if( !db->lookaside.bDisable ){ - db->lookaside.anStat[1]++; - }else if( db->mallocFailed ){ - return 0; - } - return dbMallocRawFinish(db, n); - } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( n<=LOOKASIDE_SMALL ){ - if( (pBuf = db->lookaside.pSmallFree)!=0 ){ - db->lookaside.pSmallFree = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){ - db->lookaside.pSmallInit = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - } - } -#endif - if( (pBuf = db->lookaside.pFree)!=0 ){ - db->lookaside.pFree = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else if( (pBuf = db->lookaside.pInit)!=0 ){ - db->lookaside.pInit = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else{ - db->lookaside.anStat[2]++; + if( db->lookaside.bDisable==0 ){ + 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{ + 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( db->mallocFailed ){ + return 0; } #else assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); assert( db->pnBytesFreed==0 ); @@ -31276,20 +25413,11 @@ */ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ assert( db!=0 ); if( p==0 ) return sqlite3DbMallocRawNN(db, n); assert( sqlite3_mutex_held(db->mutex) ); - if( ((uptr)p)<(uptr)db->lookaside.pEnd ){ -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){ - if( n<=LOOKASIDE_SMALL ) return p; - }else -#endif - if( ((uptr)p)>=(uptr)db->lookaside.pStart ){ - if( n<=db->lookaside.szTrue ) return p; - } - } + if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; return dbReallocFinish(db, p, n); } static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ void *pNew = 0; assert( db!=0 ); @@ -31296,18 +25424,18 @@ assert( p!=0 ); if( db->mallocFailed==0 ){ if( isLookaside(db, p) ){ pNew = sqlite3DbMallocRawNN(db, n); if( pNew ){ - memcpy(pNew, p, lookasideMallocSize(db, p)); + memcpy(pNew, p, db->lookaside.sz); sqlite3DbFree(db, p); } }else{ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - pNew = sqlite3Realloc(p, n); + pNew = sqlite3_realloc64(p, n); if( !pNew ){ sqlite3OomFault(db); } sqlite3MemdebugSetType(pNew, (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); @@ -31328,13 +25456,13 @@ } return pNew; } /* -** Make a copy of a string in memory obtained from sqliteMalloc(). These +** Make a copy of a string in memory obtained from sqliteMalloc(). These ** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This -** is because when memory debugging is turned on, these two functions are +** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the ** ThreadData structure. */ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){ char *zNew; @@ -31350,78 +25478,44 @@ return zNew; } SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ char *zNew; assert( db!=0 ); - assert( z!=0 || n==0 ); + if( z==0 ){ + return 0; + } assert( (n&0x7fffffff)==n ); - zNew = z ? sqlite3DbMallocRawNN(db, n+1) : 0; + zNew = sqlite3DbMallocRawNN(db, n+1); if( zNew ){ memcpy(zNew, z, (size_t)n); zNew[n] = 0; } 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; -#ifdef SQLITE_DEBUG - /* Because of the way the parser works, the span is guaranteed to contain - ** at least one non-space character */ - for(n=0; sqlite3Isspace(zStart[n]); n++){ assert( &zStart[n]mallocFailed, and also ** temporarily disable the lookaside memory allocator and interrupt ** any running VDBEs. -** -** Always return a NULL pointer so that this routine can be invoked using -** -** return sqlite3OomFault(db); -** -** and thereby avoid unnecessary stack frame allocations for the overwhelmingly -** common case where no OOM occurs. */ -SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){ +SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ db->mallocFailed = 1; if( db->nVdbeExec>0 ){ - AtomicStore(&db->u1.isInterrupted, 1); - } - DisableLookaside; - if( db->pParse ){ - Parse *pParse; - sqlite3ErrorMsg(db->pParse, "out of memory"); - db->pParse->rc = SQLITE_NOMEM_BKPT; - for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){ - pParse->nErr++; - pParse->rc = SQLITE_NOMEM; - } - } - } - return 0; + db->u1.isInterrupted = 1; + } + db->lookaside.bDisable++; + } } /* ** This routine reactivates the memory allocator and clears the ** db->mallocFailed flag as necessary. @@ -31430,58 +25524,55 @@ ** VDBEs. */ SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){ if( db->mallocFailed && db->nVdbeExec==0 ){ db->mallocFailed = 0; - AtomicStore(&db->u1.isInterrupted, 0); + db->u1.isInterrupted = 0; assert( db->lookaside.bDisable>0 ); - EnableLookaside; + db->lookaside.bDisable--; } } /* -** Take actions at the end of an API call to deal with error codes. +** Take actions at the end of an API call to indicate an OOM error */ -static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){ - if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomClear(db); - sqlite3Error(db, SQLITE_NOMEM); - return SQLITE_NOMEM_BKPT; - } - return rc & db->errMask; +static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ + sqlite3OomClear(db); + sqlite3Error(db, SQLITE_NOMEM); + return SQLITE_NOMEM_BKPT; } /* -** This function must be called before exiting any API function (i.e. +** This function must be called before exiting any API function (i.e. ** returning control to the user) that has called sqlite3_malloc or ** sqlite3_realloc. ** ** The returned value is normally a copy of the second argument to this ** function. However, if a malloc() failure has occurred since the previous -** invocation SQLITE_NOMEM is returned instead. +** invocation SQLITE_NOMEM is returned instead. ** ** If an OOM as occurred, then the connection error-code (the value ** returned by sqlite3_errcode()) is set to SQLITE_NOMEM. */ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ /* If the db handle must hold the connection handle mutex here. - ** Otherwise the read (and possible write) of db->mallocFailed + ** Otherwise the read (and possible write) of db->mallocFailed ** is unsafe, as is the call to sqlite3Error(). */ assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); - if( db->mallocFailed || rc ){ - return apiHandleError(db, rc); + if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ + return apiOomError(db); } - return 0; + return rc & db->errMask; } /************** End of malloc.c **********************************************/ /************** Begin file printf.c ******************************************/ /* ** The "printf" code that follows dates from the 1980's. It is in -** the public domain. +** the public domain. ** ************************************************************************** ** ** This file contains code for a set of "printf"-like routines. These ** routines format strings much like the printf() from the standard C @@ -31506,11 +25597,11 @@ /* The rest are extensions, not normally found in printf() */ #define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */ #define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '', NULL pointers replaced by SQL NULL. %Q */ #define etTOKEN 11 /* a pointer to a Token structure */ -#define etSRCITEM 12 /* a pointer to a SrcItem */ +#define etSRCLIST 12 /* a pointer to a SrcList */ #define etPOINTER 13 /* The %p conversion */ #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ #define etDECIMAL 16 /* %d or %u, but not %x, %o */ @@ -31572,28 +25663,52 @@ { '%', 0, 0, etPERCENT, 0, 0 }, { 'p', 16, 0, etPOINTER, 0, 1 }, /* All the rest are undocumented and are for internal use only */ { 'T', 0, 0, etTOKEN, 0, 0 }, - { 'S', 0, 0, etSRCITEM, 0, 0 }, + { 'S', 0, 0, etSRCLIST, 0, 0 }, { 'r', 10, 1, etORDINAL, 0, 0 }, }; -/* Notes: +/* +** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point +** conversions will work. +*/ +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** "*val" is a double such that 0.1 <= *val < 10.0 +** Return the ascii code for the leading digit of *val, then +** multiply "*val" by 10.0 to renormalize. ** -** %S Takes a pointer to SrcItem. Shows name or database.name -** %!S Like %S but prefer the zName over the zAlias +** Example: +** input: *val = 3.14159 +** output: *val = 1.4159 function return = '3' +** +** The counter *cnt is incremented each time. After counter exceeds +** 16 (the number of significant digits in a 64-bit float) '0' is +** always returned. */ +static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ + int digit; + LONGDOUBLE_TYPE d; + if( (*cnt)<=0 ) return '0'; + (*cnt)--; + digit = (int)*val; + d = digit; + digit += '0'; + *val = (*val - d)*10.0; + return (char)digit; +} +#endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** Set the StrAccum object to an error mode. */ -SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum *p, u8 eError){ - assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); +static void setStrAccumError(StrAccum *p, u8 eError){ + assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); p->accError = eError; - if( p->mxAlloc ) sqlite3_str_reset(p); - if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError); + p->nAlloc = 0; } /* ** Extra argument values from a PrintfArguments object */ @@ -31608,32 +25723,10 @@ static char *getTextArg(PrintfArguments *p){ if( p->nArg<=p->nUsed ) return 0; return (char*)sqlite3_value_text(p->apArg[p->nUsed++]); } -/* -** Allocate memory for a temporary buffer needed for printf rendering. -** -** If the requested size of the temp buffer is larger than the size -** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error. -** Do the size check before the memory allocation to prevent rogue -** SQL from requesting large allocations using the precision or width -** field of the printf() function. -*/ -static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){ - char *z; - if( pAccum->accError ) return 0; - if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){ - sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG); - return 0; - } - z = sqlite3DbMallocRaw(pAccum->db, n); - if( z==0 ){ - sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM); - } - return z; -} /* ** On machines with a small stack size, you can redefine the ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. */ @@ -31640,22 +25733,15 @@ #ifndef SQLITE_PRINT_BUF_SIZE # define SQLITE_PRINT_BUF_SIZE 70 #endif #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ -/* -** Hard limit on the precision of floating-point conversions. -*/ -#ifndef SQLITE_PRINTF_PRECISION_LIMIT -# define SQLITE_FP_PRECISION_LIMIT 100000000 -#endif - /* ** Render a string given by "fmt" into the StrAccum object. */ -SQLITE_API void sqlite3_str_vappendf( - sqlite3_str *pAccum, /* Accumulate results here */ +SQLITE_PRIVATE void sqlite3VXPrintf( + StrAccum *pAccum, /* Accumulate results here */ const char *fmt, /* Format string */ va_list ap /* arguments */ ){ int c; /* Next character in the format string */ char *bufpt; /* Pointer to the conversion buffer */ @@ -31673,27 +25759,25 @@ etByte cThousand; /* Thousands separator for %d and %u */ etByte xtype = etINVALID; /* Conversion paradigm */ u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ - double realvalue; /* Value for real types */ + LONGDOUBLE_TYPE realvalue; /* Value for real types */ const et_info *infop; /* Pointer to the appropriate info structure */ char *zOut; /* Rendering buffer */ int nOut; /* Size of the rendering buffer */ char *zExtra = 0; /* Malloced memory used by some conversion */ - int exp, e2; /* exponent of real numbers */ +#ifndef SQLITE_OMIT_FLOATING_POINT + int exp, e2; /* exponent of real numbers */ + int nsd; /* Number of significant digits returned */ + double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ - +#endif PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ - /* pAccum never starts out with an empty buffer that was obtained from - ** malloc(). This precondition is required by the mprintf("%z...") - ** optimization. */ - assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); - bufpt = 0; if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ pArgList = va_arg(ap, PrintfArguments*); bArgList = 1; }else{ @@ -31705,24 +25789,21 @@ #if HAVE_STRCHRNUL fmt = strchrnul(fmt, '%'); #else do{ fmt++; }while( *fmt && *fmt != '%' ); #endif - sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); + sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); if( *fmt==0 ) break; } if( (c=(*++fmt))==0 ){ - sqlite3_str_append(pAccum, "%", 1); + sqlite3StrAccumAppend(pAccum, "%", 1); break; } /* Find out what flags are present */ flag_leftjustify = flag_prefix = cThousand = flag_alternateform = flag_altform2 = flag_zeropad = 0; done = 0; - width = 0; - flag_long = 0; - precision = -1; do{ switch( c ){ case '-': flag_leftjustify = 1; break; case '+': flag_prefix = '+'; break; case ' ': flag_prefix = ' '; break; @@ -31729,97 +25810,84 @@ case '#': flag_alternateform = 1; break; case '!': flag_altform2 = 1; break; case '0': flag_zeropad = 1; break; case ',': cThousand = ','; break; default: done = 1; break; - case 'l': { - flag_long = 1; - c = *++fmt; - if( c=='l' ){ - c = *++fmt; - flag_long = 2; - } - done = 1; - break; - } - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': { - unsigned wx = c - '0'; - while( (c = *++fmt)>='0' && c<='9' ){ - wx = wx*10 + c - '0'; - } - testcase( wx>0x7fffffff ); - width = wx & 0x7fffffff; -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ - width = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - if( c!='.' && c!='l' ){ - done = 1; - }else{ - fmt--; - } - break; - } - case '*': { - if( bArgList ){ - width = (int)getIntArg(pArgList); - }else{ - width = va_arg(ap,int); - } - if( width<0 ){ - flag_leftjustify = 1; - width = width >= -2147483647 ? -width : 0; - } -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ - width = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - if( (c = fmt[1])!='.' && c!='l' ){ - c = *++fmt; - done = 1; - } - break; - } - case '.': { - c = *++fmt; - if( c=='*' ){ - if( bArgList ){ - precision = (int)getIntArg(pArgList); - }else{ - precision = va_arg(ap,int); - } - if( precision<0 ){ - precision = precision >= -2147483647 ? -precision : -1; - } - c = *++fmt; - }else{ - unsigned px = 0; - while( c>='0' && c<='9' ){ - px = px*10 + c - '0'; - c = *++fmt; - } - testcase( px>0x7fffffff ); - precision = px & 0x7fffffff; - } -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){ - precision = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - if( c=='l' ){ - --fmt; - }else{ - done = 1; - } - break; - } } }while( !done && (c=(*++fmt))!=0 ); + /* Get the field width */ + if( c=='*' ){ + if( bArgList ){ + width = (int)getIntArg(pArgList); + }else{ + width = va_arg(ap,int); + } + if( width<0 ){ + flag_leftjustify = 1; + width = width >= -2147483647 ? -width : 0; + } + c = *++fmt; + }else{ + unsigned wx = 0; + while( c>='0' && c<='9' ){ + wx = wx*10 + c - '0'; + c = *++fmt; + } + testcase( wx>0x7fffffff ); + width = wx & 0x7fffffff; + } + assert( width>=0 ); +#ifdef SQLITE_PRINTF_PRECISION_LIMIT + if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ + width = SQLITE_PRINTF_PRECISION_LIMIT; + } +#endif + /* Get the precision */ + if( c=='.' ){ + c = *++fmt; + if( c=='*' ){ + if( bArgList ){ + precision = (int)getIntArg(pArgList); + }else{ + precision = va_arg(ap,int); + } + c = *++fmt; + if( precision<0 ){ + precision = precision >= -2147483647 ? -precision : -1; + } + }else{ + unsigned px = 0; + while( c>='0' && c<='9' ){ + px = px*10 + c - '0'; + c = *++fmt; + } + testcase( px>0x7fffffff ); + precision = px & 0x7fffffff; + } + }else{ + precision = -1; + } + assert( precision>=(-1) ); +#ifdef SQLITE_PRINTF_PRECISION_LIMIT + if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){ + precision = SQLITE_PRINTF_PRECISION_LIMIT; + } +#endif + + + /* Get the conversion type modifier */ + if( c=='l' ){ + flag_long = 1; + c = *++fmt; + if( c=='l' ){ + flag_long = 2; + c = *++fmt; + } + }else{ + flag_long = 0; + } /* Fetch the info entry for the field */ infop = &fmtinfo[0]; xtype = etINVALID; for(idx=0; idx=0 ); - assert( precision>=(-1) ); switch( xtype ){ case etPOINTER: flag_long = sizeof(char*)==sizeof(i64) ? 2 : sizeof(char*)==sizeof(long int) ? 1 : 0; - /* no break */ deliberate_fall_through + /* Fall through into the next case */ case etORDINAL: - case etRADIX: + case etRADIX: cThousand = 0; - /* no break */ deliberate_fall_through + /* Fall through into the next case */ case etDECIMAL: if( infop->flags & FLAG_SIGNED ){ i64 v; if( bArgList ){ v = getIntArg(pArgList); @@ -31870,14 +25936,15 @@ } }else{ v = va_arg(ap,int); } if( v<0 ){ - testcase( v==SMALLEST_INT64 ); - testcase( v==(-1) ); - longvalue = ~v; - longvalue++; + if( v==SMALLEST_INT64 ){ + longvalue = ((u64)1)<<63; + }else{ + longvalue = -v; + } prefix = '-'; }else{ longvalue = v; prefix = flag_prefix; } @@ -31901,15 +25968,16 @@ } if( precisionSQLITE_FP_PRECISION_LIMIT ){ - precision = SQLITE_FP_PRECISION_LIMIT; - } -#endif - if( xtype==etFLOAT ){ - iRound = -precision; - }else if( xtype==etGENERIC ){ - if( precision==0 ) precision = 1; - iRound = precision; - }else{ - iRound = precision+1; - } - sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16); - if( s.isSpecial ){ - if( s.isSpecial==2 ){ - bufpt = flag_zeropad ? "null" : "NaN"; - length = sqlite3Strlen30(bufpt); - break; - }else if( flag_zeropad ){ - s.z[0] = '9'; - s.iDP = 1000; - s.n = 1; - }else{ - memcpy(buf, "-Inf", 5); - bufpt = buf; - if( s.sign=='-' ){ - /* no-op */ - }else if( flag_prefix ){ - buf[0] = flag_prefix; - }else{ - bufpt++; - } - length = sqlite3Strlen30(bufpt); - break; - } - } - if( s.sign=='-' ){ + if( realvalue<0.0 ){ + realvalue = -realvalue; prefix = '-'; }else{ prefix = flag_prefix; } - - exp = s.iDP-1; - + if( xtype==etGENERIC && precision>0 ) precision--; + testcase( precision>0xfff ); + for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} + if( xtype==etFLOAT ) realvalue += rounder; + /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ + exp = 0; + if( sqlite3IsNaN((double)realvalue) ){ + bufpt = "NaN"; + length = 3; + break; + } + if( realvalue>0.0 ){ + LONGDOUBLE_TYPE scale = 1.0; + while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} + while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; } + while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } + realvalue /= scale; + while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } + while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } + if( exp>350 ){ + bufpt = buf; + buf[0] = prefix; + memcpy(buf+(prefix!=0),"Inf",4); + length = 3+(prefix!=0); + break; + } + } + bufpt = buf; /* ** If the field type is etGENERIC, then convert to either etEXP ** or etFLOAT, as appropriate. */ + if( xtype!=etFLOAT ){ + realvalue += rounder; + if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } + } if( xtype==etGENERIC ){ - assert( precision>0 ); - precision--; flag_rtz = !flag_alternateform; if( exp<-4 || exp>precision ){ xtype = etEXP; }else{ precision = precision - exp; @@ -32032,50 +26090,48 @@ flag_rtz = flag_altform2; } if( xtype==etEXP ){ e2 = 0; }else{ - e2 = s.iDP - 1; - } - bufpt = buf; - { - i64 szBufNeeded; /* Size of a temporary buffer needed */ - szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15; - if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3; - if( szBufNeeded > etBUFSIZE ){ - bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded); - if( bufpt==0 ) return; + e2 = exp; + } + if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){ + bufpt = zExtra + = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); + if( bufpt==0 ){ + setStrAccumError(pAccum, STRACCUM_NOMEM); + return; } } zOut = bufpt; + nsd = 16 + flag_altform2*10; flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; /* The sign in front of the number */ if( prefix ){ *(bufpt++) = prefix; } /* Digits prior to the decimal point */ - j = 0; if( e2<0 ){ *(bufpt++) = '0'; }else{ for(; e2>=0; e2--){ - *(bufpt++) = j1 ) *(bufpt++) = ','; + *(bufpt++) = et_getdigit(&realvalue,&nsd); } } /* The decimal point */ if( flag_dp ){ *(bufpt++) = '.'; } /* "0" digits after the decimal point but before the first ** significant digit of the number */ - for(e2++; e2<0 && precision>0; precision--, e2++){ + for(e2++; e2<0; precision--, e2++){ + assert( precision>0 ); *(bufpt++) = '0'; } /* Significant digits after the decimal point */ while( (precision--)>0 ){ - *(bufpt++) = jzOut ); @@ -32087,11 +26143,10 @@ } } } /* Add the "eNNN" suffix */ if( xtype==etEXP ){ - exp = s.iDP - 1; *(bufpt++) = aDigits[infop->charset]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; }else{ *(bufpt++) = '+'; @@ -32121,12 +26176,12 @@ } i = prefix!=0; while( nPad-- ) bufpt[i++] = '0'; length = width; } +#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ break; - } case etSIZE: if( !bArgList ){ *(va_arg(ap,int*)) = pAccum->nChar; } length = width = 0; @@ -32137,69 +26192,26 @@ length = 1; break; case etCHARX: if( bArgList ){ bufpt = getTextArg(pArgList); - length = 1; - if( bufpt ){ - buf[0] = c = *(bufpt++); - if( (c&0xc0)==0xc0 ){ - while( length<4 && (bufpt[0]&0xc0)==0x80 ){ - buf[length++] = *(bufpt++); - } - } - }else{ - buf[0] = 0; - } - }else{ - unsigned int ch = va_arg(ap,unsigned int); - if( ch<0x00080 ){ - buf[0] = ch & 0xff; - length = 1; - }else if( ch<0x00800 ){ - buf[0] = 0xc0 + (u8)((ch>>6)&0x1f); - buf[1] = 0x80 + (u8)(ch & 0x3f); - length = 2; - }else if( ch<0x10000 ){ - buf[0] = 0xe0 + (u8)((ch>>12)&0x0f); - buf[1] = 0x80 + (u8)((ch>>6) & 0x3f); - buf[2] = 0x80 + (u8)(ch & 0x3f); - length = 3; - }else{ - buf[0] = 0xf0 + (u8)((ch>>18) & 0x07); - buf[1] = 0x80 + (u8)((ch>>12) & 0x3f); - buf[2] = 0x80 + (u8)((ch>>6) & 0x3f); - buf[3] = 0x80 + (u8)(ch & 0x3f); - length = 4; - } + c = bufpt ? bufpt[0] : 0; + }else{ + c = va_arg(ap,int); } if( precision>1 ){ - i64 nPrior = 1; width -= precision-1; if( width>1 && !flag_leftjustify ){ - sqlite3_str_appendchar(pAccum, width-1, ' '); + sqlite3AppendChar(pAccum, width-1, ' '); width = 0; } - sqlite3_str_append(pAccum, buf, length); - precision--; - while( precision > 1 ){ - i64 nCopyBytes; - if( nPrior > precision-1 ) nPrior = precision - 1; - nCopyBytes = length*nPrior; - if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){ - sqlite3StrAccumEnlarge(pAccum, nCopyBytes); - } - if( pAccum->accError ) break; - sqlite3_str_append(pAccum, - &pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes); - precision -= nPrior; - nPrior *= 2; - } - } + sqlite3AppendChar(pAccum, precision-1, c); + } + length = 1; + buf[0] = c; bufpt = buf; - flag_altform2 = 1; - goto adjust_width_for_utf8; + break; case etSTRING: case etDYNSTRING: if( bArgList ){ bufpt = getTextArg(pArgList); xtype = etSTRING; @@ -32207,56 +26219,23 @@ bufpt = va_arg(ap,char*); } if( bufpt==0 ){ bufpt = ""; }else if( xtype==etDYNSTRING ){ - if( pAccum->nChar==0 - && pAccum->mxAlloc - && width==0 - && precision<0 - && pAccum->accError==0 - ){ - /* Special optimization for sqlite3_mprintf("%z..."): - ** Extend an existing memory allocation rather than creating - ** a new one. */ - assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); - pAccum->zText = bufpt; - pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt); - pAccum->nChar = 0x7fffffff & (int)strlen(bufpt); - pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED; - length = 0; - break; - } zExtra = bufpt; } if( precision>=0 ){ - if( flag_altform2 ){ - /* Set length to the number of bytes needed in order to display - ** precision characters */ - unsigned char *z = (unsigned char*)bufpt; - while( precision-- > 0 && z[0] ){ - SQLITE_SKIP_UTF8(z); - } - length = (int)(z - (unsigned char*)bufpt); - }else{ - for(length=0; length0 ){ - /* Adjust width to account for extra bytes in UTF-8 characters */ - int ii = length - 1; - while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; + for(length=0; lengthetBUFSIZE ){ - bufpt = zExtra = printfTempBuf(pAccum, n); - if( bufpt==0 ) return; + bufpt = zExtra = sqlite3Malloc( n ); + if( bufpt==0 ){ + setStrAccumError(pAccum, STRACCUM_NOMEM); + return; + } }else{ bufpt = buf; } j = 0; if( needQuote ) bufpt[j++] = q; @@ -32294,64 +26268,41 @@ if( ch==q ) bufpt[j++] = ch; } if( needQuote ) bufpt[j++] = q; bufpt[j] = 0; length = j; - goto adjust_width_for_utf8; + /* The precision in %q and %Q means how many input characters to + ** consume, not the length of the output... + ** if( precision>=0 && precisionprintfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - if( flag_alternateform ){ - /* %#T means an Expr pointer that uses Expr.u.zToken */ - Expr *pExpr = va_arg(ap,Expr*); - if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){ - sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken); - sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr); - } - }else{ - /* %T means a Token pointer */ - Token *pToken = va_arg(ap, Token*); - assert( bArgList==0 ); - if( pToken && pToken->n ){ - sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); - sqlite3RecordErrorByteOffset(pAccum->db, pToken->z); - } + pToken = va_arg(ap, Token*); + assert( bArgList==0 ); + if( pToken && pToken->n ){ + sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); } length = width = 0; break; } - case etSRCITEM: { - SrcItem *pItem; + case etSRCLIST: { + SrcList *pSrc; + int k; + struct SrcList_item *pItem; if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - pItem = va_arg(ap, SrcItem*); + pSrc = va_arg(ap, SrcList*); + k = va_arg(ap, int); + pItem = &pSrc->a[k]; assert( bArgList==0 ); - if( pItem->zAlias && !flag_altform2 ){ - sqlite3_str_appendall(pAccum, pItem->zAlias); - }else if( pItem->zName ){ - if( pItem->fg.fixedSchema==0 - && pItem->fg.isSubquery==0 - && pItem->u4.zDatabase!=0 - ){ - sqlite3_str_appendall(pAccum, pItem->u4.zDatabase); - sqlite3_str_append(pAccum, ".", 1); - } - sqlite3_str_appendall(pAccum, pItem->zName); - }else if( pItem->zAlias ){ - sqlite3_str_appendall(pAccum, pItem->zAlias); - }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */ - Select *pSel = pItem->u4.pSubq->pSelect; - assert( pSel!=0 ); - if( pSel->selFlags & SF_NestedFrom ){ - sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); - }else if( pSel->selFlags & SF_MultiValue ){ - assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy ); - sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE", - pItem->u1.nRow); - }else{ - sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); - } - } + assert( k>=0 && knSrc ); + if( pItem->zDatabase ){ + sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); + sqlite3StrAccumAppend(pAccum, ".", 1); + } + sqlite3StrAccumAppendAll(pAccum, pItem->zName); length = width = 0; break; } default: { assert( xtype==etINVALID ); @@ -32359,160 +26310,122 @@ } }/* End switch over the format type */ /* ** The text of the conversion is pointed to by "bufpt" and is ** "length" characters long. The field width is "width". Do - ** the output. Both length and width are in bytes, not characters, - ** at this point. If the "!" flag was present on string conversions - ** indicating that width and precision should be expressed in characters, - ** then the values have been translated prior to reaching this point. + ** the output. */ width -= length; if( width>0 ){ - if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); - sqlite3_str_append(pAccum, bufpt, length); - if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); + if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + sqlite3StrAccumAppend(pAccum, bufpt, length); + if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); }else{ - sqlite3_str_append(pAccum, bufpt, length); + sqlite3StrAccumAppend(pAccum, bufpt, length); } if( zExtra ){ sqlite3DbFree(pAccum->db, zExtra); zExtra = 0; } }/* End for loop over the format string */ } /* End of function */ - -/* -** The z string points to the first character of a token that is -** associated with an error. If db does not already have an error -** byte offset recorded, try to compute the error byte offset for -** z and set the error byte offset in db. -*/ -SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){ - const Parse *pParse; - const char *zText; - const char *zEnd; - assert( z!=0 ); - if( NEVER(db==0) ) return; - if( db->errByteOffset!=(-2) ) return; - pParse = db->pParse; - if( NEVER(pParse==0) ) return; - zText =pParse->zTail; - if( NEVER(zText==0) ) return; - zEnd = &zText[strlen(zText)]; - if( SQLITE_WITHIN(z,zText,zEnd) ){ - db->errByteOffset = (int)(z-zText); - } -} - -/* -** If pExpr has a byte offset for the start of a token, record that as -** as the error offset. -*/ -SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){ - while( pExpr - && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0) - ){ - pExpr = pExpr->pLeft; - } - if( pExpr==0 ) return; - if( ExprHasProperty(pExpr, EP_FromDDL) ) return; - db->errByteOffset = pExpr->w.iOfst; -} - /* ** Enlarge the memory allocation on a StrAccum object so that it is ** able to accept at least N more bytes of text. ** ** Return the number of bytes of text that StrAccum is able to accept ** after the attempted enlargement. The value returned might be zero. */ -SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){ +static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; - assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ + assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ - testcase(p->accError==SQLITE_TOOBIG); - testcase(p->accError==SQLITE_NOMEM); + testcase(p->accError==STRACCUM_TOOBIG); + testcase(p->accError==STRACCUM_NOMEM); return 0; } if( p->mxAlloc==0 ){ - sqlite3StrAccumSetError(p, SQLITE_TOOBIG); - return p->nAlloc - p->nChar - 1; + N = p->nAlloc - p->nChar - 1; + setStrAccumError(p, STRACCUM_TOOBIG); + return N; }else{ char *zOld = isMalloced(p) ? p->zText : 0; - i64 szNew = p->nChar + N + 1; + 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, ** to avoid having to call this routine too often */ szNew += p->nChar; } if( szNew > p->mxAlloc ){ - sqlite3_str_reset(p); - sqlite3StrAccumSetError(p, SQLITE_TOOBIG); + sqlite3StrAccumReset(p); + setStrAccumError(p, STRACCUM_TOOBIG); return 0; }else{ p->nAlloc = (int)szNew; } if( p->db ){ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); }else{ - zNew = sqlite3Realloc(zOld, p->nAlloc); + zNew = sqlite3_realloc64(zOld, p->nAlloc); } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; p->nAlloc = sqlite3DbMallocSize(p->db, zNew); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ - sqlite3_str_reset(p); - sqlite3StrAccumSetError(p, SQLITE_NOMEM); + sqlite3StrAccumReset(p); + setStrAccumError(p, STRACCUM_NOMEM); return 0; } } - assert( N>=0 && N<=0x7fffffff ); - return (int)N; + return N; } /* ** Append N copies of character c to the given string buffer. */ -SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){ +SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ testcase( p->nChar + (i64)N > 0x7fffffff ); 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; } /* ** The StrAccum "p" is not large enough to accept N new bytes of z[]. ** So enlarge if first, then do the append. ** -** This is a helper routine to sqlite3_str_append() that does special-case +** This is a helper routine to sqlite3StrAccumAppend() that does special-case ** work (enlarging the buffer) using tail recursion, so that the -** sqlite3_str_append() routine can use fast calling semantics. +** sqlite3StrAccumAppend() routine can use fast calling semantics. */ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ N = sqlite3StrAccumEnlarge(p, N); if( N>0 ){ memcpy(&p->zText[p->nChar], z, N); p->nChar += N; } + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); } /* ** Append N bytes of text from z to the StrAccum object. Increase the ** size of the memory allocation for StrAccum if necessary. */ -SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ +SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ assert( z!=0 || N==0 ); assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); - assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 ); + assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); }else if( N ){ assert( p->zText ); p->nChar += N; @@ -32521,109 +26434,51 @@ } /* ** Append the complete text of zero-terminated string z[] to the p string. */ -SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){ - sqlite3_str_append(p, z, sqlite3Strlen30(z)); +SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ + sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); } /* ** Finish off a string by making sure it is zero-terminated. ** 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->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->zText ){ + memcpy(p->zText, p->zBase, p->nChar+1); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ - sqlite3StrAccumSetError(p, SQLITE_NOMEM); + setStrAccumError(p, STRACCUM_NOMEM); } - p->zText = zText; - return zText; + return p->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) ){ return strAccumFinishRealloc(p); } } return p->zText; } -/* -** Use the content of the StrAccum passed as the second argument -** as the result of an SQL function. -*/ -SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){ - if( p->accError ){ - sqlite3_result_error_code(pCtx, p->accError); - sqlite3_str_reset(p); - }else if( isMalloced(p) ){ - sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC); - }else{ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - sqlite3_str_reset(p); - } -} - -/* -** This singleton is an sqlite3_str object that is returned if -** sqlite3_malloc() fails to provide space for a real one. This -** sqlite3_str object accepts no new text and always returns -** an SQLITE_NOMEM error. -*/ -static sqlite3_str sqlite3OomStr = { - 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 -}; - -/* Finalize a string created using sqlite3_str_new(). -*/ -SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){ - char *z; - if( p!=0 && p!=&sqlite3OomStr ){ - z = sqlite3StrAccumFinish(p); - sqlite3_free(p); - }else{ - z = 0; - } - return z; -} - -/* Return any error code associated with p */ -SQLITE_API int sqlite3_str_errcode(sqlite3_str *p){ - return p ? p->accError : SQLITE_NOMEM; -} - -/* Return the current length of p in bytes */ -SQLITE_API int sqlite3_str_length(sqlite3_str *p){ - return p ? p->nChar : 0; -} - -/* Return the current value for p */ -SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ - if( p==0 || p->nChar==0 ) return 0; - p->zText[p->nChar] = 0; - return p->zText; -} - /* ** Reset an StrAccum string. Reclaim all malloced memory. */ -SQLITE_API void sqlite3_str_reset(StrAccum *p){ +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; } - p->nAlloc = 0; - p->nChar = 0; p->zText = 0; } /* ** Initialize a string accumulator. @@ -32638,31 +26493,19 @@ ** n then no memory allocations ever occur. ** mx: Maximum number of bytes to accumulate. If mx==0 then no memory ** allocations will ever occur. */ SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ - p->zText = zBase; + p->zText = p->zBase = zBase; p->db = db; + p->nChar = 0; p->nAlloc = n; p->mxAlloc = mx; - p->nChar = 0; p->accError = 0; p->printfFlags = 0; } -/* Allocate and initialize a new dynamic string object */ -SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){ - sqlite3_str *p = sqlite3_malloc64(sizeof(*p)); - if( p ){ - sqlite3StrAccumInit(p, 0, 0, 0, - db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); - }else{ - p = &sqlite3OomStr; - } - return p; -} - /* ** Print into memory obtained from sqliteMalloc(). Use the internal ** %-conversion extensions. */ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ @@ -32671,13 +26514,13 @@ StrAccum acc; assert( db!=0 ); sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); acc.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_vappendf(&acc, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); - if( acc.accError==SQLITE_NOMEM ){ + if( acc.accError==STRACCUM_NOMEM ){ sqlite3OomFault(db); } return z; } @@ -32701,21 +26544,21 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; -#ifdef SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( zFormat==0 ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); - sqlite3_str_vappendf(&acc, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; } /* @@ -32756,31 +26599,21 @@ if( zBuf ) zBuf[0] = 0; return zBuf; } #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); - sqlite3_str_vappendf(&acc, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); zBuf[acc.nChar] = 0; return zBuf; } SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ - StrAccum acc; + char *z; va_list ap; - if( n<=0 ) return zBuf; -#ifdef SQLITE_ENABLE_API_ARMOR - if( zBuf==0 || zFormat==0 ) { - (void)SQLITE_MISUSE_BKPT; - if( zBuf ) zBuf[0] = 0; - return zBuf; - } -#endif - sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); va_start(ap,zFormat); - sqlite3_str_vappendf(&acc, zFormat, ap); + z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); va_end(ap); - zBuf[acc.nChar] = 0; - return zBuf; + return z; } /* ** This is the routine that actually formats the sqlite3_log() message. ** We house it in a separate routine from sqlite3_log() to avoid using @@ -32788,21 +26621,21 @@ ** ** sqlite3_log() must render into a static buffer. It cannot dynamically ** allocate memory because it might be called while the memory allocator ** mutex is held. ** -** sqlite3_str_vappendf() might ask for *temporary* memory allocations for +** sqlite3VXPrintf() might ask for *temporary* memory allocations for ** certain format characters (%q) or for very large precisions or widths. ** Care must be taken that any sqlite3_log() calls that occur while the ** memory mutex is held do not use these mechanisms. */ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); - sqlite3_str_vappendf(&acc, zFormat, ap); + sqlite3VXPrintf(&acc, zFormat, ap); sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, sqlite3StrAccumFinish(&acc)); } /* @@ -32824,109 +26657,33 @@ ** and segfaults if you give it a long long int. */ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ va_list ap; StrAccum acc; - char zBuf[SQLITE_PRINT_BUF_SIZE*10]; + char zBuf[500]; sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); va_start(ap,zFormat); - sqlite3_str_vappendf(&acc, zFormat, ap); + 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 /* -** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument +** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. */ -SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ va_list ap; va_start(ap,zFormat); - sqlite3_str_vappendf(p, zFormat, ap); + sqlite3VXPrintf(p, zFormat, ap); va_end(ap); } - -/***************************************************************************** -** Reference counted string/blob storage -*****************************************************************************/ - -/* -** Increase the reference count of the string by one. -** -** The input parameter is returned. -*/ -SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){ - RCStr *p = (RCStr*)z; - assert( p!=0 ); - p--; - p->nRCRef++; - return z; -} - -/* -** Decrease the reference count by one. Free the string when the -** reference count reaches zero. -*/ -SQLITE_PRIVATE void sqlite3RCStrUnref(void *z){ - RCStr *p = (RCStr*)z; - assert( p!=0 ); - p--; - assert( p->nRCRef>0 ); - if( p->nRCRef>=2 ){ - p->nRCRef--; - }else{ - sqlite3_free(p); - } -} - -/* -** Create a new string that is capable of holding N bytes of text, not counting -** the zero byte at the end. The string is uninitialized. -** -** The reference count is initially 1. Call sqlite3RCStrUnref() to free the -** newly allocated string. -** -** This routine returns 0 on an OOM. -*/ -SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){ - RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 ); - if( p==0 ) return 0; - p->nRCRef = 1; - return (char*)&p[1]; -} - -/* -** Change the size of the string so that it is able to hold N bytes. -** The string might be reallocated, so return the new allocation. -*/ -SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){ - RCStr *p = (RCStr*)z; - RCStr *pNew; - assert( p!=0 ); - p--; - assert( p->nRCRef==1 ); - pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1); - if( pNew==0 ){ - sqlite3_free(p); - return 0; - }else{ - return (char*)&pNew[1]; - } -} - /************** End of printf.c **********************************************/ /************** Begin file treeview.c ****************************************/ /* ** 2015-06-08 ** @@ -32939,11 +26696,11 @@ ** ************************************************************************* ** ** This file contains C code to implement the TreeView debugging routines. ** These routines print a parse tree to standard output for debugging and -** analysis. +** analysis. ** ** The interfaces in this file is only available when compiling ** with SQLITE_DEBUG. */ /* #include "sqliteInt.h" */ @@ -32951,119 +26708,66 @@ /* ** Add a new subitem to the tree. The moreToFollow flag indicates that this ** is not the last item in the tree. */ -static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){ - TreeView *p = *pp; +static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ if( p==0 ){ - *pp = p = sqlite3_malloc64( sizeof(*p) ); - if( p==0 ) return; + p = sqlite3_malloc64( sizeof(*p) ); + if( p==0 ) return 0; memset(p, 0, sizeof(*p)); }else{ p->iLevel++; } assert( moreToFollow==0 || moreToFollow==1 ); - if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow; + if( p->iLevelbLine) ) p->bLine[p->iLevel] = moreToFollow; + return p; } /* ** Finished with one layer of the tree */ -static void sqlite3TreeViewPop(TreeView **pp){ - TreeView *p = *pp; +static void sqlite3TreeViewPop(TreeView *p){ if( p==0 ) return; p->iLevel--; - if( p->iLevel<0 ){ - sqlite3_free(p); - *pp = 0; - } + if( p->iLevel<0 ) sqlite3_free(p); } /* ** Generate a single line of output for the tree, with a prefix that contains ** all the appropriate tree lines */ -SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ +static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ va_list ap; int i; StrAccum acc; - char zBuf[1000]; + char zBuf[500]; sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); if( p ){ - for(i=0; iiLevel && i<(int)sizeof(p->bLine)-1; i++){ - sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4); - } - sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); - } - if( zFormat!=0 ){ - va_start(ap, zFormat); - sqlite3_str_vappendf(&acc, zFormat, ap); - va_end(ap); - assert( acc.nChar>0 || acc.accError ); - sqlite3_str_append(&acc, "\n", 1); - } + for(i=0; iiLevel && ibLine)-1; i++){ + sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); + } + sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); + } + 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); fflush(stdout); } /* ** Shorthand for starting a new tree item that consists of a single label */ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){ - sqlite3TreeViewPush(&p, moreFollows); + p = sqlite3TreeViewPush(p, moreFollows); sqlite3TreeViewLine(p, "%s", zLabel); } -/* -** Show a list of Column objects in tree format. -*/ -SQLITE_PRIVATE void sqlite3TreeViewColumnList( - TreeView *pView, - const Column *aCol, - int nCol, - u8 moreToFollow -){ - int i; - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewLine(pView, "COLUMNS"); - for(i=0; ipOuter); }else{ sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith); } if( pWith->nCte>0 ){ - sqlite3TreeViewPush(&pView, moreToFollow); + pView = sqlite3TreeViewPush(pView, 1); for(i=0; inCte; i++){ StrAccum x; char zLine[1000]; const struct Cte *pCte = &pWith->a[i]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3_str_appendf(&x, "%s", pCte->zName); + sqlite3XPrintf(&x, "%s", pCte->zName); if( pCte->pCols && pCte->pCols->nExpr>0 ){ char cSep = '('; int j; for(j=0; jpCols->nExpr; j++){ - sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName); + sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); cSep = ','; } - sqlite3_str_appendf(&x, ")"); - } - if( pCte->eM10d!=M10d_Any ){ - sqlite3_str_appendf(&x, " %sMATERIALIZED", - pCte->eM10d==M10d_No ? "NOT " : ""); - } - if( pCte->pUse ){ - sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse, - pCte->pUse->nUse); - } + sqlite3XPrintf(&x, ")"); + } + sqlite3XPrintf(&x, " AS"); sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, inCte-1); sqlite3TreeViewSelect(pView, pCte->pSelect, 0); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); - } -} - -/* -** Generate a human-readable description of a SrcList object. -*/ -SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ - int i; - if( pSrc==0 ) return; - for(i=0; inSrc; i++){ - const SrcItem *pItem = &pSrc->a[i]; - StrAccum x; - int n = 0; - char zLine[1000]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - x.printfFlags |= SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); - if( pItem->pSTab ){ - sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s", - pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab, - pItem->colUsed, - pItem->fg.rowidUsed ? "+rowid" : ""); - } - if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){ - sqlite3_str_appendf(&x, " FULL-OUTER-JOIN"); - }else if( pItem->fg.jointype & JT_LEFT ){ - sqlite3_str_appendf(&x, " LEFT-JOIN"); - }else if( pItem->fg.jointype & JT_RIGHT ){ - sqlite3_str_appendf(&x, " RIGHT-JOIN"); - }else if( pItem->fg.jointype & JT_CROSS ){ - sqlite3_str_appendf(&x, " CROSS-JOIN"); - } - if( pItem->fg.jointype & JT_LTORJ ){ - sqlite3_str_appendf(&x, " LTORJ"); - } - if( pItem->fg.fromDDL ){ - sqlite3_str_appendf(&x, " DDL"); - } - if( pItem->fg.isCte ){ - static const char *aMat[] = {",MAT", "", ",NO-MAT"}; - sqlite3_str_appendf(&x, " CteUse=%d%s", - pItem->u2.pCteUse->nUse, - aMat[pItem->u2.pCteUse->eM10d]); - } - if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){ - sqlite3_str_appendf(&x, " isOn"); - } - if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc"); - if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated"); - if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized"); - if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine"); - if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte"); - if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom"); - if( pItem->fg.fixedSchema ) sqlite3_str_appendf(&x, " fixedSchema"); - if( pItem->fg.hadSchema ) sqlite3_str_appendf(&x, " hadSchema"); - if( pItem->fg.isSubquery ) sqlite3_str_appendf(&x, " isSubquery"); - - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, inSrc-1); - n = 0; - if( pItem->fg.isSubquery ) n++; - if( pItem->fg.isTabFunc ) n++; - if( pItem->fg.isUsing ) n++; - if( pItem->fg.isUsing ){ - sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); - } - if( pItem->fg.isSubquery ){ - assert( n==1 ); - if( pItem->pSTab ){ - Table *pTab = pItem->pSTab; - sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1); - } - assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) ); - sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0); - } - if( pItem->fg.isTabFunc ){ - sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); - } - sqlite3TreeViewPop(&pView); - } -} + sqlite3TreeViewPop(pView); + } + sqlite3TreeViewPop(pView); + } +} + /* ** Generate a human-readable description of a Select object. */ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ @@ -33194,101 +26813,98 @@ int n = 0; int cnt = 0; if( p==0 ){ sqlite3TreeViewLine(pView, "nil-SELECT"); return; - } - sqlite3TreeViewPush(&pView, moreToFollow); + } + pView = sqlite3TreeViewPush(pView, moreToFollow); if( p->pWith ){ sqlite3TreeViewWith(pView, p->pWith, 1); cnt = 1; - sqlite3TreeViewPush(&pView, 1); + sqlite3TreeViewPush(pView, 1); } do{ - if( p->selFlags & SF_WhereBegin ){ - sqlite3TreeViewLine(pView, "sqlite3WhereBegin()"); - }else{ - sqlite3TreeViewLine(pView, - "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d", - ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), - p->selId, p, p->selFlags, - (int)p->nSelectRow - ); - } - if( cnt++ ) sqlite3TreeViewPop(&pView); + sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags, + (int)p->nSelectRow + ); + if( cnt++ ) sqlite3TreeViewPop(pView); if( p->pPrior ){ n = 1000; }else{ n = 0; - if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++; + if( p->pSrc && p->pSrc->nSrc ) n++; if( p->pWhere ) n++; if( p->pGroupBy ) n++; if( p->pHaving ) n++; if( p->pOrderBy ) n++; if( p->pLimit ) n++; -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ) n++; - if( p->pWinDefn ) n++; -#endif - } - if( p->pEList ){ - sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set"); - } - n--; -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ){ - Window *pX; - sqlite3TreeViewPush(&pView, (n--)>0); - sqlite3TreeViewLine(pView, "window-functions"); - for(pX=p->pWin; pX; pX=pX->pNextWin){ - sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0); - } - sqlite3TreeViewPop(&pView); - } -#endif - if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){ - sqlite3TreeViewPush(&pView, (n--)>0); + if( p->pOffset ) n++; + } + sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); + if( p->pSrc && p->pSrc->nSrc ){ + int i; + pView = sqlite3TreeViewPush(pView, (n--)>0); sqlite3TreeViewLine(pView, "FROM"); - sqlite3TreeViewSrcList(pView, p->pSrc); - sqlite3TreeViewPop(&pView); + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + StrAccum x; + char zLine[100]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); + sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); + if( pItem->zDatabase ){ + sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); + }else if( pItem->zName ){ + sqlite3XPrintf(&x, " %s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); + } + if( pItem->fg.jointype & JT_LEFT ){ + sqlite3XPrintf(&x, " LEFT-JOIN"); + } + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, ipSrc->nSrc-1); + if( pItem->pSelect ){ + sqlite3TreeViewSelect(pView, pItem->pSelect, 0); + } + if( pItem->fg.isTabFunc ){ + sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); + } + sqlite3TreeViewPop(pView); + } + sqlite3TreeViewPop(pView); } if( p->pWhere ){ sqlite3TreeViewItem(pView, "WHERE", (n--)>0); sqlite3TreeViewExpr(pView, p->pWhere, 0); - sqlite3TreeViewPop(&pView); + sqlite3TreeViewPop(pView); } if( p->pGroupBy ){ sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY"); } if( p->pHaving ){ sqlite3TreeViewItem(pView, "HAVING", (n--)>0); sqlite3TreeViewExpr(pView, p->pHaving, 0); - sqlite3TreeViewPop(&pView); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWinDefn ){ - Window *pX; - sqlite3TreeViewItem(pView, "WINDOW", (n--)>0); - for(pX=p->pWinDefn; pX; pX=pX->pNextWin){ - sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0); - } - sqlite3TreeViewPop(&pView); - } -#endif + sqlite3TreeViewPop(pView); + } if( p->pOrderBy ){ sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); } if( p->pLimit ){ sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); - sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); - if( p->pLimit->pRight ){ - sqlite3TreeViewItem(pView, "OFFSET", 0); - sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); + sqlite3TreeViewExpr(pView, p->pLimit, 0); + sqlite3TreeViewPop(pView); + } + if( p->pOffset ){ + sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); + sqlite3TreeViewExpr(pView, p->pOffset, 0); + sqlite3TreeViewPop(pView); } if( p->pPrior ){ const char *zOp = "UNION"; switch( p->op ){ case TK_ALL: zOp = "UNION ALL"; break; @@ -33297,165 +26913,33 @@ } sqlite3TreeViewItem(pView, zOp, 1); } p = p->pPrior; }while( p!=0 ); - sqlite3TreeViewPop(&pView); -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Generate a description of starting or stopping bounds -*/ -SQLITE_PRIVATE void sqlite3TreeViewBound( - TreeView *pView, /* View context */ - u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */ - Expr *pExpr, /* Value for PRECEDING or FOLLOWING */ - u8 moreToFollow /* True if more to follow */ -){ - switch( eBound ){ - case TK_UNBOUNDED: { - sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow); - sqlite3TreeViewPop(&pView); - break; - } - case TK_CURRENT: { - sqlite3TreeViewItem(pView, "CURRENT", moreToFollow); - sqlite3TreeViewPop(&pView); - break; - } - case TK_PRECEDING: { - sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow); - sqlite3TreeViewExpr(pView, pExpr, 0); - sqlite3TreeViewPop(&pView); - break; - } - case TK_FOLLOWING: { - sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow); - sqlite3TreeViewExpr(pView, pExpr, 0); - sqlite3TreeViewPop(&pView); - break; - } - } -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Generate a human-readable explanation for a Window object -*/ -SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ - int nElement = 0; - if( pWin==0 ) return; - if( pWin->pFilter ){ - sqlite3TreeViewItem(pView, "FILTER", 1); - sqlite3TreeViewExpr(pView, pWin->pFilter, 0); - sqlite3TreeViewPop(&pView); - if( pWin->eFrmType==TK_FILTER ) return; - } - sqlite3TreeViewPush(&pView, more); - if( pWin->zName ){ - sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin); - }else{ - sqlite3TreeViewLine(pView, "OVER (%p)", pWin); - } - if( pWin->zBase ) nElement++; - if( pWin->pOrderBy ) nElement++; - if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++; - if( pWin->eExclude ) nElement++; - if( pWin->zBase ){ - sqlite3TreeViewPush(&pView, (--nElement)>0); - sqlite3TreeViewLine(pView, "window: %s", pWin->zBase); - sqlite3TreeViewPop(&pView); - } - if( pWin->pPartition ){ - sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY"); - } - if( pWin->pOrderBy ){ - sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); - } - if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){ - char zBuf[30]; - const char *zFrmType = "ROWS"; - if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; - if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS"; - sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType, - pWin->bImplicitFrame ? " (implied)" : ""); - sqlite3TreeViewItem(pView, zBuf, (--nElement)>0); - sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); - sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); - sqlite3TreeViewPop(&pView); - } - if( pWin->eExclude ){ - char zBuf[30]; - const char *zExclude; - switch( pWin->eExclude ){ - case TK_NO: zExclude = "NO OTHERS"; break; - case TK_CURRENT: zExclude = "CURRENT ROW"; break; - case TK_GROUP: zExclude = "GROUP"; break; - case TK_TIES: zExclude = "TIES"; break; - default: - sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude); - zExclude = zBuf; - break; - } - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Generate a human-readable explanation for a Window Function object -*/ -SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){ - if( pWin==0 ) return; - sqlite3TreeViewPush(&pView, more); - sqlite3TreeViewLine(pView, "WINFUNC %s(%d)", - pWin->pWFunc->zName, pWin->pWFunc->nArg); - sqlite3TreeViewWindow(pView, pWin, 0); - sqlite3TreeViewPop(&pView); -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ + sqlite3TreeViewPop(pView); +} /* ** Generate a human-readable explanation of an expression tree. */ 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[200]; - sqlite3TreeViewPush(&pView, moreToFollow); + char zFlgs[60]; + pView = sqlite3TreeViewPush(pView, moreToFollow); if( pExpr==0 ){ sqlite3TreeViewLine(pView, "nil"); - sqlite3TreeViewPop(&pView); + sqlite3TreeViewPop(pView); return; } - if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){ - StrAccum x; - sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0); - sqlite3_str_appendf(&x, " fg.af=%x.%c", - pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n'); - if( ExprHasProperty(pExpr, EP_OuterON) ){ - sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin); - } - if( ExprHasProperty(pExpr, EP_InnerON) ){ - sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin); - } - if( ExprHasProperty(pExpr, EP_FromDDL) ){ - sqlite3_str_appendf(&x, " DDL"); - } - if( ExprHasVVAProperty(pExpr, EP_Immutable) ){ - sqlite3_str_appendf(&x, " IMMUTABLE"); - } - if( pExpr->pAggInfo!=0 ){ - sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg); - } - sqlite3StrAccumFinish(&x); + if( pExpr->flags ){ + if( ExprHasProperty(pExpr, EP_FromJoin) ){ + sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d", + pExpr->flags, pExpr->iRightJoinTable); + }else{ + sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags); + } }else{ zFlgs[0] = 0; } switch( pExpr->op ){ case TK_AGG_COLUMN: { @@ -33464,26 +26948,14 @@ break; } case TK_COLUMN: { if( pExpr->iTable<0 ){ /* This only happens when coding check constraints */ - char zOp2[16]; - if( pExpr->op2 ){ - sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2); - }else{ - zOp2[0] = 0; - } - sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s", - pExpr->iColumn, zFlgs, zOp2); - }else{ - assert( ExprUseYTab(pExpr) ); - sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s", - pExpr->iTable, pExpr->iColumn, - pExpr->y.pTab, zFlgs); - } - if( ExprHasProperty(pExpr, EP_FixedCol) ){ - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs); + }else{ + sqlite3TreeViewLine(pView, "{%d:%d}%s", + pExpr->iTable, pExpr->iColumn, zFlgs); } break; } case TK_INTEGER: { if( pExpr->flags & EP_IntValue ){ @@ -33493,55 +26965,44 @@ } break; } #ifndef SQLITE_OMIT_FLOATING_POINT case TK_FLOAT: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); break; } #endif case TK_STRING: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken); break; } case TK_NULL: { sqlite3TreeViewLine(pView,"NULL"); break; } - case TK_TRUEFALSE: { - sqlite3TreeViewLine(pView,"%s%s", - sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs); - break; - } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); break; } #endif case TK_VARIABLE: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)", pExpr->u.zToken, pExpr->iColumn); break; } case TK_REGISTER: { sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable); break; } case TK_ID: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken); break; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } #endif /* SQLITE_OMIT_CAST */ @@ -33564,137 +27025,64 @@ case TK_SLASH: zBinOp = "DIV"; break; case TK_LSHIFT: zBinOp = "LSHIFT"; break; case TK_RSHIFT: zBinOp = "RSHIFT"; break; case TK_CONCAT: zBinOp = "CONCAT"; break; case TK_DOT: zBinOp = "DOT"; break; - case TK_LIMIT: zBinOp = "LIMIT"; break; case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; - case TK_TRUTH: { - int x; - const char *azOp[] = { - "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" - }; - assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); - assert( pExpr->pRight ); - assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op - == TK_TRUEFALSE ); - x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); - zUniOp = azOp[x]; - break; - } - case TK_SPAN: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } case TK_COLLATE: { - /* COLLATE operators without the EP_Collate flag are intended to - ** emulate collation associated with a table column. These show - ** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE - ** operators that appear in the original SQL always have the - ** EP_Collate bit set and appear in treeview output as just "COLLATE" */ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s", - !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "", - pExpr->u.zToken, zFlgs); + sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } case TK_AGG_FUNCTION: case TK_FUNCTION: { ExprList *pFarg; /* List of function arguments */ - Window *pWin; if( ExprHasProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; - pWin = 0; }else{ - assert( ExprUseXList(pExpr) ); pFarg = pExpr->x.pList; -#ifndef SQLITE_OMIT_WINDOWFUNC - pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0; -#else - pWin = 0; -#endif } - assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( pExpr->op==TK_AGG_FUNCTION ){ - sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p", - pExpr->op2, pExpr->u.zToken, zFlgs, - pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0, - pExpr->iAgg, pExpr->pAggInfo); - }else if( pExpr->op2!=0 ){ - const char *zOp2; - char zBuf[8]; - sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2); - zOp2 = zBuf; - if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck"; - if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr"; - if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx"; - if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol"; - sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s", - pExpr->u.zToken, zFlgs, zOp2); + sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", + pExpr->op2, pExpr->u.zToken); }else{ - sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); + sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); } if( pFarg ){ - sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0); - if( pExpr->pLeft ){ - Expr *pOB = pExpr->pLeft; - assert( pOB->op==TK_ORDER ); - assert( ExprUseXList(pOB) ); - sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY"); - } - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin ){ - sqlite3TreeViewWindow(pView, pWin, 0); - } -#endif - break; - } - case TK_ORDER: { - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY"); + sqlite3TreeViewExprList(pView, pFarg, 0, 0); + } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: { - assert( ExprUseXSelect(pExpr) ); sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags); sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); break; } case TK_SELECT: { - assert( ExprUseXSelect(pExpr) ); - sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags); + sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags); sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); break; } case TK_IN: { - sqlite3_str *pStr = sqlite3_str_new(0); - char *z; - sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags); - if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable); - if( ExprHasProperty(pExpr, EP_Subrtn) ){ - sqlite3_str_appendf(pStr, " subrtn(%d,%d)", - pExpr->y.sub.regReturn, pExpr->y.sub.iAddr); - } - z = sqlite3_str_finish(pStr); - sqlite3TreeViewLine(pView, z); - sqlite3_free(z); + sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - if( ExprUseXSelect(pExpr) ){ + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); }else{ sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); } break; @@ -33711,17 +27099,14 @@ ** X is stored in pExpr->pLeft. ** Y is stored in pExpr->pList->a[0].pExpr. ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { - const Expr *pX, *pY, *pZ; - pX = pExpr->pLeft; - assert( ExprUseXList(pExpr) ); - assert( pExpr->x.pList->nExpr==2 ); - pY = pExpr->x.pList->a[0].pExpr; - pZ = pExpr->x.pList->a[1].pExpr; - sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs); + Expr *pX = pExpr->pLeft; + Expr *pY = pExpr->x.pList->a[0].pExpr; + Expr *pZ = pExpr->x.pList->a[1].pExpr; + sqlite3TreeViewLine(pView, "BETWEEN"); sqlite3TreeViewExpr(pView, pX, 1); sqlite3TreeViewExpr(pView, pY, 1); sqlite3TreeViewExpr(pView, pZ, 0); break; } @@ -33731,33 +27116,30 @@ ** trigger programs. In this case Expr.iTable is set to 1 for the ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn ** is set to the column of the pseudo-table to read, or to -1 to ** read the rowid field. */ - sqlite3TreeViewLine(pView, "%s(%d)", + sqlite3TreeViewLine(pView, "%s(%d)", pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); break; } case TK_CASE: { sqlite3TreeViewLine(pView, "CASE"); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - assert( ExprUseXList(pExpr) ); sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { const char *zType = "unk"; - switch( pExpr->affExpr ){ + switch( pExpr->affinity ){ case OE_Rollback: zType = "rollback"; break; case OE_Abort: zType = "abort"; break; case OE_Fail: zType = "fail"; break; case OE_Ignore: zType = "ignore"; break; } - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3TreeViewLine(pView, "RAISE %s", zType); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken); break; } #endif case TK_MATCH: { sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s", @@ -33764,44 +27146,21 @@ pExpr->iTable, pExpr->iColumn, zFlgs); sqlite3TreeViewExpr(pView, pExpr->pRight, 0); break; } case TK_VECTOR: { - char *z = sqlite3_mprintf("VECTOR%s",zFlgs); - assert( ExprUseXList(pExpr) ); - sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z); - sqlite3_free(z); + sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR"); break; } case TK_SELECT_COLUMN: { - sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s", - pExpr->iColumn, pExpr->iTable-1, - pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : ""); - assert( ExprUseXSelect(pExpr->pLeft) ); + sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn); 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; - } - case TK_ERROR: { - Expr tmp; - sqlite3TreeViewLine(pView, "ERROR"); - tmp = *pExpr; - tmp.op = pExpr->op2; - sqlite3TreeViewExpr(pView, &tmp, 0); - break; - } - case TK_ROW: { - if( pExpr->iColumn<=0 ){ - sqlite3TreeViewLine(pView, "First FROM table rowid"); - }else{ - sqlite3TreeViewLine(pView, "First FROM table column %d", - pExpr->iColumn-1); - } break; } default: { sqlite3TreeViewLine(pView, "op=%d", pExpr->op); break; @@ -33811,13 +27170,13 @@ sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); sqlite3TreeViewExpr(pView, pExpr->pRight, 0); }else if( zUniOp ){ sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); } - sqlite3TreeViewPop(&pView); + sqlite3TreeViewPop(pView); } /* ** Generate a human-readable explanation of an expression list. @@ -33833,418 +27192,29 @@ }else{ int i; sqlite3TreeViewLine(pView, "%s", zLabel); for(i=0; inExpr; i++){ int j = pList->a[i].u.x.iOrderByCol; - u8 sortFlags = pList->a[i].fg.sortFlags; - char *zName = pList->a[i].zEName; - int moreToFollow = inExpr - 1; - if( j || zName || sortFlags ){ - sqlite3TreeViewPush(&pView, moreToFollow); - moreToFollow = 0; - sqlite3TreeViewLine(pView, 0); - if( zName ){ - switch( pList->a[i].fg.eEName ){ - default: - fprintf(stdout, "AS %s ", zName); - break; - case ENAME_TAB: - fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName); - if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) "); - if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) "); - if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) "); - break; - case ENAME_SPAN: - fprintf(stdout, "SPAN(\"%s\") ", zName); - break; - } - } - if( j ){ - fprintf(stdout, "iOrderByCol=%d ", j); - } - if( sortFlags & KEYINFO_ORDER_DESC ){ - fprintf(stdout, "DESC "); - }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){ - fprintf(stdout, "NULLS-LAST"); - } - fprintf(stdout, "\n"); - fflush(stdout); - } - sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow); - if( j || zName || sortFlags ){ - sqlite3TreeViewPop(&pView); - } + if( j ){ + sqlite3TreeViewPush(pView, 0); + sqlite3TreeViewLine(pView, "iOrderByCol=%d", j); + } + sqlite3TreeViewExpr(pView, pList->a[i].pExpr, inExpr-1); + if( j ) sqlite3TreeViewPop(pView); } } } SQLITE_PRIVATE void sqlite3TreeViewExprList( TreeView *pView, const ExprList *pList, u8 moreToFollow, const char *zLabel ){ - sqlite3TreeViewPush(&pView, moreToFollow); + pView = sqlite3TreeViewPush(pView, moreToFollow); sqlite3TreeViewBareExprList(pView, pList, zLabel); - sqlite3TreeViewPop(&pView); -} - -/* -** Generate a human-readable explanation of an id-list. -*/ -SQLITE_PRIVATE void sqlite3TreeViewBareIdList( - TreeView *pView, - const IdList *pList, - const char *zLabel -){ - if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; - if( pList==0 ){ - sqlite3TreeViewLine(pView, "%s (empty)", zLabel); - }else{ - int i; - sqlite3TreeViewLine(pView, "%s", zLabel); - for(i=0; inId; i++){ - char *zName = pList->a[i].zName; - int moreToFollow = inId - 1; - if( zName==0 ) zName = "(null)"; - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewLine(pView, 0); - fprintf(stdout, "%s\n", zName); - sqlite3TreeViewPop(&pView); - } - } -} -SQLITE_PRIVATE void sqlite3TreeViewIdList( - TreeView *pView, - const IdList *pList, - u8 moreToFollow, - const char *zLabel -){ - sqlite3TreeViewPush(&pView, moreToFollow); - sqlite3TreeViewBareIdList(pView, pList, zLabel); - sqlite3TreeViewPop(&pView); -} - -/* -** Generate a human-readable explanation of a list of Upsert objects -*/ -SQLITE_PRIVATE void sqlite3TreeViewUpsert( - TreeView *pView, - const Upsert *pUpsert, - u8 moreToFollow -){ - if( pUpsert==0 ) return; - sqlite3TreeViewPush(&pView, moreToFollow); - while( pUpsert ){ - int n; - sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow); - sqlite3TreeViewLine(pView, "ON CONFLICT DO %s", - pUpsert->isDoUpdate ? "UPDATE" : "NOTHING"); - n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0); - sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET"); - sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET"); - if( pUpsert->pUpsertWhere ){ - sqlite3TreeViewItem(pView, "WHERE", (n--)>0); - sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0); - sqlite3TreeViewPop(&pView); - } - sqlite3TreeViewPop(&pView); - pUpsert = pUpsert->pNextUpsert; - } - sqlite3TreeViewPop(&pView); -} - -#if TREETRACE_ENABLED -/* -** Generate a human-readable diagram of the data structure that go -** into generating an DELETE statement. -*/ -SQLITE_PRIVATE void sqlite3TreeViewDelete( - const With *pWith, - const SrcList *pTabList, - const Expr *pWhere, - const ExprList *pOrderBy, - const Expr *pLimit, - const Trigger *pTrigger -){ - int n = 0; - TreeView *pView = 0; - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, "DELETE"); - if( pWith ) n++; - if( pTabList ) n++; - if( pWhere ) n++; - if( pOrderBy ) n++; - if( pLimit ) n++; - if( pTrigger ) n++; - if( pWith ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewWith(pView, pWith, 0); - sqlite3TreeViewPop(&pView); - } - if( pTabList ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "FROM"); - sqlite3TreeViewSrcList(pView, pTabList); - sqlite3TreeViewPop(&pView); - } - if( pWhere ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "WHERE"); - sqlite3TreeViewExpr(pView, pWhere, 0); - sqlite3TreeViewPop(&pView); - } - if( pOrderBy ){ - sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY"); - } - if( pLimit ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "LIMIT"); - sqlite3TreeViewExpr(pView, pLimit, 0); - sqlite3TreeViewPop(&pView); - } - if( pTrigger ){ - sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); - } - sqlite3TreeViewPop(&pView); -} -#endif /* TREETRACE_ENABLED */ - -#if TREETRACE_ENABLED -/* -** Generate a human-readable diagram of the data structure that go -** into generating an INSERT statement. -*/ -SQLITE_PRIVATE void sqlite3TreeViewInsert( - const With *pWith, - const SrcList *pTabList, - const IdList *pColumnList, - const Select *pSelect, - const ExprList *pExprList, - int onError, - const Upsert *pUpsert, - const Trigger *pTrigger -){ - TreeView *pView = 0; - int n = 0; - const char *zLabel = "INSERT"; - switch( onError ){ - case OE_Replace: zLabel = "REPLACE"; break; - case OE_Ignore: zLabel = "INSERT OR IGNORE"; break; - case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break; - case OE_Abort: zLabel = "INSERT OR ABORT"; break; - case OE_Fail: zLabel = "INSERT OR FAIL"; break; - } - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, zLabel); - if( pWith ) n++; - if( pTabList ) n++; - if( pColumnList ) n++; - if( pSelect ) n++; - if( pExprList ) n++; - if( pUpsert ) n++; - if( pTrigger ) n++; - if( pWith ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewWith(pView, pWith, 0); - sqlite3TreeViewPop(&pView); - } - if( pTabList ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "INTO"); - sqlite3TreeViewSrcList(pView, pTabList); - sqlite3TreeViewPop(&pView); - } - if( pColumnList ){ - sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS"); - } - if( pSelect ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "DATA-SOURCE"); - sqlite3TreeViewSelect(pView, pSelect, 0); - sqlite3TreeViewPop(&pView); - } - if( pExprList ){ - sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES"); - } - if( pUpsert ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "UPSERT"); - sqlite3TreeViewUpsert(pView, pUpsert, 0); - sqlite3TreeViewPop(&pView); - } - if( pTrigger ){ - sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); - } - sqlite3TreeViewPop(&pView); -} -#endif /* TREETRACE_ENABLED */ - -#if TREETRACE_ENABLED -/* -** Generate a human-readable diagram of the data structure that go -** into generating an UPDATE statement. -*/ -SQLITE_PRIVATE void sqlite3TreeViewUpdate( - const With *pWith, - const SrcList *pTabList, - const ExprList *pChanges, - const Expr *pWhere, - int onError, - const ExprList *pOrderBy, - const Expr *pLimit, - const Upsert *pUpsert, - const Trigger *pTrigger -){ - int n = 0; - TreeView *pView = 0; - const char *zLabel = "UPDATE"; - switch( onError ){ - case OE_Replace: zLabel = "UPDATE OR REPLACE"; break; - case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break; - case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break; - case OE_Abort: zLabel = "UPDATE OR ABORT"; break; - case OE_Fail: zLabel = "UPDATE OR FAIL"; break; - } - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, zLabel); - if( pWith ) n++; - if( pTabList ) n++; - if( pChanges ) n++; - if( pWhere ) n++; - if( pOrderBy ) n++; - if( pLimit ) n++; - if( pUpsert ) n++; - if( pTrigger ) n++; - if( pWith ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewWith(pView, pWith, 0); - sqlite3TreeViewPop(&pView); - } - if( pTabList ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "FROM"); - sqlite3TreeViewSrcList(pView, pTabList); - sqlite3TreeViewPop(&pView); - } - if( pChanges ){ - sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET"); - } - if( pWhere ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "WHERE"); - sqlite3TreeViewExpr(pView, pWhere, 0); - sqlite3TreeViewPop(&pView); - } - if( pOrderBy ){ - sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY"); - } - if( pLimit ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "LIMIT"); - sqlite3TreeViewExpr(pView, pLimit, 0); - sqlite3TreeViewPop(&pView); - } - if( pUpsert ){ - sqlite3TreeViewPush(&pView, (--n)>0); - sqlite3TreeViewLine(pView, "UPSERT"); - sqlite3TreeViewUpsert(pView, pUpsert, 0); - sqlite3TreeViewPop(&pView); - } - if( pTrigger ){ - sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); - } - sqlite3TreeViewPop(&pView); -} -#endif /* TREETRACE_ENABLED */ - -#ifndef SQLITE_OMIT_TRIGGER -/* -** Show a human-readable graph of a TriggerStep -*/ -SQLITE_PRIVATE void sqlite3TreeViewTriggerStep( - TreeView *pView, - const TriggerStep *pStep, - u8 moreToFollow, - u8 showFullList -){ - int cnt = 0; - if( pStep==0 ) return; - sqlite3TreeViewPush(&pView, - moreToFollow || (showFullList && pStep->pNext!=0)); - do{ - if( cnt++ && pStep->pNext==0 ){ - sqlite3TreeViewPop(&pView); - sqlite3TreeViewPush(&pView, 0); - } - sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING"); - }while( showFullList && (pStep = pStep->pNext)!=0 ); - sqlite3TreeViewPop(&pView); -} - -/* -** Show a human-readable graph of a Trigger -*/ -SQLITE_PRIVATE void sqlite3TreeViewTrigger( - TreeView *pView, - const Trigger *pTrigger, - u8 moreToFollow, - u8 showFullList -){ - int cnt = 0; - if( pTrigger==0 ) return; - sqlite3TreeViewPush(&pView, - moreToFollow || (showFullList && pTrigger->pNext!=0)); - do{ - if( cnt++ && pTrigger->pNext==0 ){ - sqlite3TreeViewPop(&pView); - sqlite3TreeViewPush(&pView, 0); - } - sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName); - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1); - sqlite3TreeViewPop(&pView); - }while( showFullList && (pTrigger = pTrigger->pNext)!=0 ); - sqlite3TreeViewPop(&pView); -} -#endif /* SQLITE_OMIT_TRIGGER */ - - -/* -** These simplified versions of the tree-view routines omit unnecessary -** parameters. These variants are intended to be used from a symbolic -** debugger, such as "gdb", during interactive debugging sessions. -** -** This routines are given external linkage so that they will always be -** accessible to the debugging, and to avoid warnings about unused -** functions. But these routines only exist in debugging builds, so they -** do not contaminate the interface. -** -** See Also: -** -** sqlite3ShowWhereTerm() in where.c -*/ -SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);} -SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); } -SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); } -SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); } -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep *p){ - sqlite3TreeViewTriggerStep(0,p,0,0); -} -SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep *p){ - sqlite3TreeViewTriggerStep(0,p,0,1); -} -SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); } -SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);} -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); } -SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); } -#endif + sqlite3TreeViewPop(pView); +} #endif /* SQLITE_DEBUG */ /************** End of treeview.c ********************************************/ /************** Begin file random.c ******************************************/ @@ -34270,45 +27240,20 @@ /* All threads share a single random number generator. ** This structure is the current state of the generator. */ static SQLITE_WSD struct sqlite3PrngType { - u32 s[16]; /* 64 bytes of chacha20 state */ - u8 out[64]; /* Output bytes */ - u8 n; /* Output bytes remaining */ + unsigned char isInit; /* True if initialized */ + unsigned char i, j; /* State variables */ + unsigned char s[256]; /* State variables */ } sqlite3Prng; - -/* The RFC-7539 ChaCha20 block function -*/ -#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) -#define QR(a, b, c, d) ( \ - a += b, d ^= a, d = ROTL(d,16), \ - c += d, b ^= c, b = ROTL(b,12), \ - a += b, d ^= a, d = ROTL(d, 8), \ - c += d, b ^= c, b = ROTL(b, 7)) -static void chacha_block(u32 *out, const u32 *in){ - int i; - u32 x[16]; - memcpy(x, in, 64); - for(i=0; i<10; i++){ - QR(x[0], x[4], x[ 8], x[12]); - QR(x[1], x[5], x[ 9], x[13]); - QR(x[2], x[6], x[10], x[14]); - QR(x[3], x[7], x[11], x[15]); - QR(x[0], x[5], x[10], x[15]); - QR(x[1], x[6], x[11], x[12]); - QR(x[2], x[7], x[ 8], x[13]); - QR(x[3], x[4], x[ 9], x[14]); - } - for(i=0; i<16; i++) out[i] = x[i]+in[i]; -} - /* ** Return N random bytes. */ SQLITE_API void sqlite3_randomness(int N, void *pBuf){ + unsigned char t; unsigned char *zBuf = pBuf; /* The "wsdPrng" macro will resolve to the pseudo-random number generator ** state vector. If writable static data is unsupported on the target, ** we have to locate the state vector at run-time. In the more common @@ -34334,50 +27279,52 @@ mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); #endif sqlite3_mutex_enter(mutex); if( N<=0 || pBuf==0 ){ - wsdPrng.s[0] = 0; + wsdPrng.isInit = 0; sqlite3_mutex_leave(mutex); return; } /* Initialize the state of the random number generator once, - ** the first time this routine is called. + ** the first time this routine is called. The seed value does + ** not need to contain a lot of randomness since we are not + ** trying to do secure encryption or anything like that... + ** + ** Nothing in this file or anywhere else in SQLite does any kind of + ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random + ** number generator) not as an encryption device. */ - if( wsdPrng.s[0]==0 ){ - sqlite3_vfs *pVfs = sqlite3_vfs_find(0); - static const u32 chacha20_init[] = { - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }; - memcpy(&wsdPrng.s[0], chacha20_init, 16); - if( NEVER(pVfs==0) ){ - memset(&wsdPrng.s[4], 0, 44); - }else{ - sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]); - } - wsdPrng.s[15] = wsdPrng.s[12]; - wsdPrng.s[12] = 0; - wsdPrng.n = 0; + if( !wsdPrng.isInit ){ + int i; + char k[256]; + wsdPrng.j = 0; + wsdPrng.i = 0; + sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k); + for(i=0; i<256; i++){ + wsdPrng.s[i] = (u8)i; + } + for(i=0; i<256; i++){ + wsdPrng.j += wsdPrng.s[i] + k[i]; + t = wsdPrng.s[wsdPrng.j]; + wsdPrng.s[wsdPrng.j] = wsdPrng.s[i]; + wsdPrng.s[i] = t; + } + wsdPrng.isInit = 1; } assert( N>0 ); - while( 1 /* exit by break */ ){ - if( N<=wsdPrng.n ){ - memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N); - wsdPrng.n -= N; - break; - } - if( wsdPrng.n>0 ){ - memcpy(zBuf, wsdPrng.out, wsdPrng.n); - N -= wsdPrng.n; - zBuf += wsdPrng.n; - } - wsdPrng.s[12]++; - chacha_block((u32*)wsdPrng.out, wsdPrng.s); - wsdPrng.n = 64; - } + do{ + wsdPrng.i++; + t = wsdPrng.s[wsdPrng.i]; + wsdPrng.j += t; + wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j]; + wsdPrng.s[wsdPrng.j] = t; + t += wsdPrng.s[wsdPrng.i]; + *(zBuf++) = wsdPrng.s[t]; + }while( --N ); sqlite3_mutex_leave(mutex); } #ifndef SQLITE_UNTESTABLE /* @@ -34475,17 +27422,17 @@ p = sqlite3Malloc(sizeof(*p)); if( p==0 ) return SQLITE_NOMEM_BKPT; memset(p, 0, sizeof(*p)); p->xTask = xTask; p->pIn = pIn; - /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a + /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a ** function that returns SQLITE_ERROR when passed the argument 200, that - ** forces worker threads to run sequentially and deterministically + ** forces worker threads to run sequentially and deterministically ** for testing purposes. */ if( sqlite3FaultSim(200) ){ rc = 1; - }else{ + }else{ rc = pthread_create(&p->tid, 0, xTask, pIn); } if( rc ){ p->done = 1; p->pOut = xTask(pIn); @@ -34563,13 +27510,13 @@ assert( ppThread!=0 ); assert( xTask!=0 ); *ppThread = 0; p = sqlite3Malloc(sizeof(*p)); if( p==0 ) return SQLITE_NOMEM_BKPT; - /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a + /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a ** function that returns SQLITE_ERROR when passed the argument 200, that - ** forces worker threads to run sequentially and deterministically + ** forces worker threads to run sequentially and deterministically ** (via the sqlite3FaultSim() term of the conditional) for testing ** purposes. */ if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){ memset(p, 0, sizeof(*p)); }else{ @@ -34694,11 +27641,11 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains routines used to translate between UTF-8, +** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** ** Notes on UTF-8: ** ** Byte-0 Byte-1 Byte-2 Byte-3 Value @@ -34789,10 +27736,30 @@ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \ *zOut++ = (u8)(c&0x00FF); \ } \ } + +#define READ_UTF16LE(zIn, TERM, c){ \ + c = (*zIn++); \ + c += ((*zIn++)<<8); \ + if( c>=0xD800 && c<0xE000 && TERM ){ \ + int c2 = (*zIn++); \ + c2 += ((*zIn++)<<8); \ + c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \ + } \ +} + +#define READ_UTF16BE(zIn, TERM, c){ \ + c = ((*zIn++)<<8); \ + c += (*zIn++); \ + if( c>=0xD800 && c<0xE000 && TERM ){ \ + int c2 = ((*zIn++)<<8); \ + c2 += (*zIn++); \ + c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \ + } \ +} /* ** Translate a single UTF-8 character. Return the unicode value. ** ** During translation, assume that the byte that zTerm points @@ -34821,11 +27788,11 @@ */ #define READ_UTF8(zIn, zTerm, c) \ c = *(zIn++); \ if( c>=0xc0 ){ \ c = sqlite3Utf8Trans1[c-0xc0]; \ - while( zIn0 ); - c = z[0]; - if( c>=0xc0 ){ - c = sqlite3Utf8Trans1[c-0xc0]; - if( n>4 ) n = 4; - while( idb==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->flags&MEM_Str ); assert( pMem->enc!=desiredEnc ); @@ -34911,19 +27847,17 @@ assert( pMem->enc!=0 ); assert( pMem->n>=0 ); #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) { - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3VdbeMemPrettyPrint(pMem, &acc); - fprintf(stderr, "INPUT: %s\n", sqlite3StrAccumFinish(&acc)); + char zBuf[100]; + sqlite3VdbeMemPrettyPrint(pMem, zBuf); + fprintf(stderr, "INPUT: %s\n", zBuf); } #endif - /* If the translation is between UTF-16 little and big endian, then + /* If the translation is between UTF-16 little and big endian, then ** all that is required is to swap the byte order. This case is handled ** differently from the others. */ if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){ u8 temp; @@ -34951,18 +27885,18 @@ ** translating a 2-byte character to a 4-byte UTF-8 character. ** A single byte is required for the output string ** nul-terminator. */ pMem->n &= ~1; - len = 2 * (sqlite3_int64)pMem->n + 1; + len = pMem->n * 2 + 1; }else{ /* When converting from UTF-8 to UTF-16 the maximum growth is caused ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 ** character. Two bytes are required in the output buffer for the ** nul-terminator. */ - len = 2 * (sqlite3_int64)pMem->n + 2; + len = pMem->n * 2 + 2; } /* Set zIn to point at the start of the input buffer and zTerm to point 1 ** byte past the end. ** @@ -34997,96 +27931,48 @@ }else{ assert( desiredEnc==SQLITE_UTF8 ); if( pMem->enc==SQLITE_UTF16LE ){ /* UTF-16 Little-endian -> UTF-8 */ while( zIn=0xd800 && c<0xe000 ){ -#ifdef SQLITE_REPLACE_INVALID_UTF - if( c>=0xdc00 || zIn>=zTerm ){ - c = 0xfffd; - }else{ - int c2 = *(zIn++); - c2 += (*(zIn++))<<8; - if( c2<0xdc00 || c2>=0xe000 ){ - zIn -= 2; - c = 0xfffd; - }else{ - c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000; - } - } -#else - if( zIn UTF-8 */ while( zIn=0xd800 && c<0xe000 ){ -#ifdef SQLITE_REPLACE_INVALID_UTF - if( c>=0xdc00 || zIn>=zTerm ){ - c = 0xfffd; - }else{ - int c2 = (*(zIn++))<<8; - c2 += *(zIn++); - if( c2<0xdc00 || c2>=0xe000 ){ - zIn -= 2; - c = 0xfffd; - }else{ - c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000; - } - } -#else - if( zInn = (int)(z - zOut); } *z = 0; assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); - c = MEM_Str|MEM_Term|(pMem->flags&(MEM_AffMask|MEM_Subtype)); + c = pMem->flags; sqlite3VdbeMemRelease(pMem); - pMem->flags = c; + pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype)); pMem->enc = desiredEnc; pMem->z = (char*)zOut; pMem->zMalloc = pMem->z; pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); translate_out: #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) { - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3VdbeMemPrettyPrint(pMem, &acc); - fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc)); + char zBuf[100]; + sqlite3VdbeMemPrettyPrint(pMem, zBuf); + fprintf(stderr, "OUTPUT: %s\n", zBuf); } #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 +** This routine checks for a byte-order mark at the beginning of the ** UTF-16 string stored in *pMem. If one is present, it is removed and ** the encoding of the Mem adjusted. This routine does not do any ** byte-swapping, it just sets Mem.enc appropriately. ** ** The allocation (static, dynamic etc.) and encoding of the Mem may be @@ -35105,11 +27991,11 @@ } if( b1==0xFF && b2==0xFE ){ bom = SQLITE_UTF16LE; } } - + if( bom ){ rc = sqlite3VdbeMemMakeWriteable(pMem); if( rc==SQLITE_OK ){ pMem->n -= 2; memmove(pMem->z, &pMem->z[2], pMem->n); @@ -35125,11 +28011,11 @@ /* ** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, ** return the number of unicode characters in pZ up to (but not including) ** the first 0x00 byte. If nByte is not less than zero, return the -** number of unicode characters in the first nByte of pZ (or up to +** number of unicode characters in the first nByte of pZ (or up to ** the first 0x00, whichever comes first). */ SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){ int r = 0; const u8 *z = (const u8*)zIn; @@ -35145,11 +28031,11 @@ r++; } return r; } -/* This test function is not currently used by the automated test-suite. +/* This test function is not currently used by the automated test-suite. ** Hence it is only available in debug builds. */ #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) /* ** Translate UTF-8 to UTF-8. @@ -35199,30 +28085,31 @@ assert( m.z || db->mallocFailed ); return m.z; } /* -** zIn is a UTF-16 encoded unicode string at least nByte bytes long. +** zIn is a UTF-16 encoded unicode string at least nChar characters long. ** Return the number of bytes in the first nChar unicode characters -** in pZ. nChar must be non-negative. Surrogate pairs count as a single -** character. +** in pZ. nChar must be non-negative. */ -SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nByte, int nChar){ +SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){ int c; unsigned char const *z = zIn; - unsigned char const *zEnd = &z[nByte-1]; int n = 0; - - if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++; - while( n=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2; - n++; - } - return (int)(z-(unsigned char const *)zIn) - - (SQLITE_UTF16NATIVE==SQLITE_UTF16LE); + + if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){ + while( n=0xD800 && i<=0xDFFF ) t = 0xFFFD; if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD; assert( c==t ); assert( (z-zBuf)==n ); } + for(i=0; i<0x00110000; i++){ + if( i>=0xD800 && i<0xE000 ) continue; + z = zBuf; + WRITE_UTF16LE(z, i); + n = (int)(z-zBuf); + assert( n>0 && n<=4 ); + z[0] = 0; + z = zBuf; + READ_UTF16LE(z, 1, c); + assert( c==i ); + assert( (z-zBuf)==n ); + } + for(i=0; i<0x00110000; i++){ + if( i>=0xD800 && i<0xE000 ) continue; + z = zBuf; + WRITE_UTF16BE(z, i); + n = (int)(z-zBuf); + assert( n>0 && n<=4 ); + z[0] = 0; + z = zBuf; + READ_UTF16BE(z, 1, c); + assert( c==i ); + assert( (z-zBuf)==n ); + } } #endif /* SQLITE_TEST */ #endif /* SQLITE_OMIT_UTF16 */ /************** End of utf.c *************************************************/ @@ -35273,32 +28184,34 @@ ** strings, and stuff like that. ** */ /* #include "sqliteInt.h" */ /* #include */ -#ifndef SQLITE_OMIT_FLOATING_POINT -#include +#if HAVE_ISNAN || SQLITE_HAVE_ISNAN +# include #endif /* -** Calls to sqlite3FaultSim() are used to simulate a failure during testing, -** or to bypass normal error detection during testing in order to let -** execute proceed further downstream. -** -** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The -** sqlite3FaultSim() function only returns non-zero during testing. -** -** During testing, if the test harness has set a fault-sim callback using -** a call to sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL), then -** each call to sqlite3FaultSim() is relayed to that application-supplied -** callback and the integer return value form the application-supplied -** callback is returned by sqlite3FaultSim(). -** -** The integer argument to sqlite3FaultSim() is a code to identify which -** sqlite3FaultSim() instance is being invoked. Each call to sqlite3FaultSim() -** should have a unique code. To prevent legacy testing applications from -** breaking, the codes should not be changed or reused. +** Routine needed to support the testcase() macro. +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int x){ + static unsigned dummy = 0; + dummy += (unsigned)x; +} +#endif + +/* +** Give a callback to the test harness that can be used to simulate faults +** in places where it is difficult or expensive to do so purely by means +** of inputs. +** +** The intent of the integer argument is to let the fault simulator know +** which of multiple sqlite3FaultSim() calls has been hit. +** +** Return whatever integer value the test callback returns, or return +** SQLITE_OK if no test callback is installed. */ #ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback; return xCallback ? xCallback(iTest) : SQLITE_OK; @@ -35313,32 +28226,45 @@ ** Otherwise, we have our own implementation that works on most systems. */ SQLITE_PRIVATE int sqlite3IsNaN(double x){ int rc; /* The value return */ #if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN - u64 y; - memcpy(&y,&x,sizeof(y)); - rc = IsNaN(y); -#else + /* + ** Systems that support the isnan() library function should probably + ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have + ** found that many systems do not have a working isnan() function so + ** this implementation is provided as an alternative. + ** + ** This NaN test sometimes fails if compiled on GCC with -ffast-math. + ** On the other hand, the use of -ffast-math comes with the following + ** warning: + ** + ** This option [-ffast-math] should never be turned on by any + ** -O option since it can result in incorrect output for programs + ** which depend on an exact implementation of IEEE or ISO + ** rules/specifications for math functions. + ** + ** Under MSVC, this NaN test may fail if compiled with a floating- + ** point precision mode other than /fp:precise. From the MSDN + ** documentation: + ** + ** The compiler [with /fp:precise] will properly handle comparisons + ** involving NaN. For example, x != x evaluates to true if x is NaN + ** ... + */ +#ifdef __FAST_MATH__ +# error SQLite will not work correctly with the -ffast-math option of GCC. +#endif + volatile double y = x; + volatile double z = y; + rc = (y!=z); +#else /* if HAVE_ISNAN */ rc = isnan(x); #endif /* HAVE_ISNAN */ testcase( rc ); return rc; } -#endif /* SQLITE_OMIT_FLOATING_POINT */ - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Return true if the floating point value is NaN or +Inf or -Inf. -*/ -SQLITE_PRIVATE int sqlite3IsOverflow(double x){ - int rc; /* The value return */ - u64 y; - memcpy(&y,&x,sizeof(y)); - rc = IsOvfl(y); - return rc; -} #endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. @@ -35351,25 +28277,19 @@ if( z==0 ) return 0; return 0x3fffffff & (int)strlen(z); } /* -** Return the declared type of a column. Or return zDflt if the column +** Return the declared type of a column. Or return zDflt if the column ** has no declared type. ** ** The column type is an extra string stored after the zero-terminator on ** the column name if and only if the COLFLAG_HASTYPE flag is set. */ SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){ - if( pCol->colFlags & COLFLAG_HASTYPE ){ - return pCol->zCnName + strlen(pCol->zCnName) + 1; - }else if( pCol->eCType ){ - assert( pCol->eCType<=SQLITE_N_STDTYPE ); - return (char*)sqlite3StdType[pCol->eCType-1]; - }else{ - return zDflt; - } + if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt; + return pCol->zName + strlen(pCol->zName) + 1; } /* ** Helper function for sqlite3Error() - called rarely. Broken out into ** a separate routine to avoid unnecessary register saves on entry to @@ -35386,51 +28306,19 @@ ** that would be appropriate. */ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; - if( err_code || db->pErr ){ - sqlite3ErrorFinish(db, err_code); - }else{ - db->errByteOffset = -1; - } -} - -/* -** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state -** and error message. -*/ -SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){ - assert( db!=0 ); - db->errCode = SQLITE_OK; - db->errByteOffset = -1; - if( db->pErr ) sqlite3ValueSetNull(db->pErr); + if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code); } /* ** Load the sqlite3.iSysErrno field if that is an appropriate thing ** to do based on the SQLite error code in rc. */ SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ if( rc==SQLITE_IOERR_NOMEM ) return; -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) - if( rc==SQLITE_IOERR_IN_PAGE ){ - int ii; - int iErr; - sqlite3BtreeEnterAll(db); - for(ii=0; iinDb; ii++){ - if( db->aDb[ii].pBt ){ - iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); - if( iErr ){ - db->iSysErrno = iErr; - } - } - } - sqlite3BtreeLeaveAll(db); - return; - } -#endif rc &= 0xff; if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ db->iSysErrno = sqlite3OsGetLastError(db->pVfs); } } @@ -35438,12 +28326,21 @@ /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". ** ** If it is not NULL, string zFormat specifies the format of the -** error string. zFormat and any string tokens that follow it are -** assumed to be encoded in UTF-8. +** error string in the style of the printf functions: The following +** format characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList +** +** zFormat and any string tokens that follow it are assumed to be +** encoded in UTF-8. ** ** To clear the most recent error for sqlite handle "db", sqlite3Error ** should be called with err_code set to SQLITE_OK and zFormat set ** to NULL. */ @@ -35461,36 +28358,19 @@ va_end(ap); sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); } } -/* -** Check for interrupts and invoke progress callback. -*/ -SQLITE_PRIVATE void sqlite3ProgressCheck(Parse *p){ - sqlite3 *db = p->db; - if( AtomicLoad(&db->u1.isInterrupted) ){ - p->nErr++; - p->rc = SQLITE_INTERRUPT; - } -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress ){ - if( p->rc==SQLITE_INTERRUPT ){ - p->nProgressSteps = 0; - }else if( (++p->nProgressSteps)>=db->nProgressOps ){ - if( db->xProgress(db->pProgressArg) ){ - p->nErr++; - p->rc = SQLITE_INTERRUPT; - } - p->nProgressSteps = 0; - } - } -#endif -} - /* ** Add an error message to pParse->zErrMsg and increment pParse->nErr. +** The following formatting characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList ** ** This function should be used to report any error that occurs while ** compiling an SQL statement (i.e. within sqlite3_prepare()). The ** last thing the sqlite3_prepare() function does is copy the error ** stored by this function into the database handle using sqlite3Error(). @@ -35499,43 +28379,21 @@ */ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; va_list ap; sqlite3 *db = pParse->db; - assert( db!=0 ); - assert( db->pParse==pParse || db->pParse->pToplevel==pParse ); - db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); - if( db->errByteOffset<-1 ) db->errByteOffset = -1; if( db->suppressErr ){ sqlite3DbFree(db, zMsg); - if( db->mallocFailed ){ - pParse->nErr++; - pParse->rc = SQLITE_NOMEM; - } }else{ pParse->nErr++; sqlite3DbFree(db, pParse->zErrMsg); pParse->zErrMsg = zMsg; pParse->rc = SQLITE_ERROR; - pParse->pWith = 0; - } -} - -/* -** If database connection db is currently parsing SQL, then transfer -** error code errCode to that parser if the parser has not already -** encountered some other kind of error. -*/ -SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3 *db, int errCode){ - Parse *pParse; - if( db==0 || (pParse = db->pParse)==0 ) return errCode; - pParse->rc = errCode; - pParse->nErr++; - return errCode; + } } /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the @@ -35547,11 +28405,11 @@ ** ** The return value is -1 if no dequoting occurs or the length of the ** dequoted string, exclusive of the zero terminator, if dequoting does ** occur. ** -** 2002-02-14: This routine is extended to remove MS-Access style +** 2002-Feb-14: This routine is extended to remove MS-Access style ** brackets from around identifiers. For example: "[a-b-c]" becomes ** "a-b-c". */ SQLITE_PRIVATE void sqlite3Dequote(char *z){ char quote; @@ -35573,76 +28431,10 @@ z[j++] = z[i]; } } z[j] = 0; } -SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){ - assert( !ExprHasProperty(p, EP_IntValue) ); - assert( sqlite3Isquote(p->u.zToken[0]) ); - p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted; - sqlite3Dequote(p->u.zToken); -} - -/* -** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken -** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those -** that contain '_' characters that must be removed before further processing. -*/ -SQLITE_PRIVATE void sqlite3DequoteNumber(Parse *pParse, Expr *p){ - assert( p!=0 || pParse->db->mallocFailed ); - if( p ){ - const char *pIn = p->u.zToken; - char *pOut = p->u.zToken; - int bHex = (pIn[0]=='0' && (pIn[1]=='x' || pIn[1]=='X')); - int iValue; - assert( p->op==TK_QNUMBER ); - p->op = TK_INTEGER; - do { - if( *pIn!=SQLITE_DIGIT_SEPARATOR ){ - *pOut++ = *pIn; - if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT; - }else{ - if( (bHex==0 && (!sqlite3Isdigit(pIn[-1]) || !sqlite3Isdigit(pIn[1]))) - || (bHex==1 && (!sqlite3Isxdigit(pIn[-1]) || !sqlite3Isxdigit(pIn[1]))) - ){ - sqlite3ErrorMsg(pParse, "unrecognized token: \"%s\"", p->u.zToken); - } - } - }while( *pIn++ ); - if( bHex ) p->op = TK_INTEGER; - - /* tag-20240227-a: If after dequoting, the number is an integer that - ** fits in 32 bits, then it must be converted into EP_IntValue. Other - ** parts of the code expect this. See also tag-20240227-b. */ - if( p->op==TK_INTEGER && sqlite3GetInt32(p->u.zToken, &iValue) ){ - p->u.iValue = iValue; - p->flags |= EP_IntValue; - } - } -} - -/* -** If the input token p is quoted, try to adjust the token to remove -** the quotes. This is not always possible: -** -** "abc" -> abc -** "ab""cd" -> (not possible because of the interior "") -** -** Remove the quotes if possible. This is a optimization. The overall -** system should still return the correct answer even if this routine -** is always a no-op. -*/ -SQLITE_PRIVATE void sqlite3DequoteToken(Token *p){ - unsigned int i; - if( p->n<2 ) return; - if( !sqlite3Isquote(p->z[0]) ) return; - for(i=1; in-1; i++){ - if( sqlite3Isquote(p->z[i]) ) return; - } - p->n -= 2; - p->z++; -} /* ** Generate a Token object from a string */ SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ @@ -35671,22 +28463,16 @@ } return sqlite3StrICmp(zLeft, zRight); } SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ unsigned char *a, *b; - int c, x; + int c; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; for(;;){ - c = *a; - x = *b; - if( c==x ){ - if( c==0 ) break; - }else{ - c = (int)UpperToLower[c] - (int)UpperToLower[x]; - if( c ) break; - } + c = (int)UpperToLower[*a] - (int)UpperToLower[*b]; + if( c || *a==0 ) break; a++; b++; } return c; } @@ -35701,76 +28487,20 @@ b = (unsigned char *)zRight; while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; } -/* -** Compute an 8-bit hash on a string that is insensitive to case differences -*/ -SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ - u8 h = 0; - if( z==0 ) return 0; - while( z[0] ){ - h += UpperToLower[(unsigned char)z[0]]; - z++; - } - return h; -} - -/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) -** -** Reference: -** T. J. Dekker, "A Floating-Point Technique for Extending the -** Available Precision". 1971-07-26. -*/ -static void dekkerMul2(volatile double *x, double y, double yy){ - /* - ** The "volatile" keywords on parameter x[] and on local variables - ** below are needed force intermediate results to be truncated to - ** binary64 rather than be carried around in an extended-precision - ** format. The truncation is necessary for the Dekker algorithm to - ** work. Intel x86 floating point might omit the truncation without - ** the use of volatile. - */ - volatile double tx, ty, p, q, c, cc; - double hx, hy; - u64 m; - memcpy(&m, (void*)&x[0], 8); - m &= 0xfffffffffc000000LL; - memcpy(&hx, &m, 8); - tx = x[0] - hx; - memcpy(&m, &y, 8); - m &= 0xfffffffffc000000LL; - memcpy(&hy, &m, 8); - ty = y - hy; - p = hx*hy; - q = hx*ty + tx*hy; - c = p+q; - cc = p - c + q + tx*ty; - cc = x[0]*yy + x[1]*y + cc; - x[0] = c + cc; - x[1] = c - x[0]; - x[1] += cc; -} - /* ** The string z[] is an text representation of a real number. ** Convert this string to a double and write it into *pResult. ** ** The string z[] is length bytes in length (bytes, not characters) and ** uses the encoding enc. The string is not necessarily zero-terminated. ** ** Return TRUE if the result is a valid real number (or integer) and FALSE -** if the string is empty or contains extraneous text. More specifically -** return -** 1 => The input string is a pure integer -** 2 or more => The input has a decimal point or eNNN clause -** 0 or less => The input string is not a valid number -** -1 => Not a valid number, but has a valid prefix which -** includes a decimal point and/or an eNNN clause -** -** Valid numbers are in one of these formats: +** if the string is empty or contains extraneous text. Valid numbers +** are in one of these formats: ** ** [+-]digits[E[+-]digits] ** [+-]digits.[digits][E[+-]digits] ** [+-].digits[E[+-]digits] ** @@ -35779,45 +28509,36 @@ ** ** If some prefix of the input string is a valid number, this routine ** returns FALSE but it still converts the prefix and writes the result ** into *pResult. */ -#if defined(_MSC_VER) -#pragma warning(disable : 4756) -#endif SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT int incr; - const char *zEnd; + const char *zEnd = z + length; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ - u64 s = 0; /* significand */ + i64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ - int nDigit = 0; /* Number of digits processed */ - int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ - u64 s2; /* round-tripped significand */ - double rr[2]; + double result; + int nDigits = 0; + int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ - if( length==0 ) return 0; if( enc==SQLITE_UTF8 ){ incr = 1; - zEnd = z + length; }else{ int i; incr = 2; - length &= ~1; assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - testcase( enc==SQLITE_UTF16LE ); - testcase( enc==SQLITE_UTF16BE ); for(i=3-enc; i=((LARGEST_UINT64-9)/10) ){ - /* skip non-significant significand digits - ** (increase exponent by d to shift decimal left) */ - while( z=zEnd ) goto do_atof_calc; /* if decimal point is present */ if( *z=='.' ){ z+=incr; - eType++; /* copy digits from after decimal to significand ** (decrease exponent by d to shift decimal right) */ while( z=zEnd ) goto do_atof_calc; /* if exponent is present */ if( *z=='e' || *z=='E' ){ z+=incr; eValid = 0; - eType++; - /* This branch is needed to avoid a (harmless) buffer overread. The + /* This branch is needed to avoid a (harmless) buffer overread. The ** special comment alerts the mutation tester that the correct answer ** is obtained even if the branch is omitted */ if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/ /* get sign of exponent */ @@ -35889,124 +28606,88 @@ /* skip trailing spaces */ while( z0 && s<((LARGEST_UINT64-0x7ff)/10) ){ - s *= 10; - e--; - } - while( e<0 && (s%10)==0 ){ - s /= 10; - e++; - } - - rr[0] = (double)s; - assert( sizeof(s2)==sizeof(rr[0]) ); -#ifdef SQLITE_DEBUG - rr[1] = 18446744073709549568.0; - memcpy(&s2, &rr[1], sizeof(s2)); - assert( s2==0x43efffffffffffffLL ); -#endif - /* Largest double that can be safely converted to u64 - ** vvvvvvvvvvvvvvvvvvvvvv */ - if( rr[0]<=18446744073709549568.0 ){ - s2 = (u64)rr[0]; - rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); - }else{ - rr[1] = 0.0; - } - assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */ - - if( e>0 ){ - while( e>=100 ){ - e -= 100; - dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); - } - while( e>=10 ){ - e -= 10; - dekkerMul2(rr, 1.0e+10, 0.0); - } - while( e>=1 ){ - e -= 1; - dekkerMul2(rr, 1.0e+01, 0.0); - } - }else{ - while( e<=-100 ){ - e += 100; - dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); - } - while( e<=-10 ){ - e += 10; - dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); - } - while( e<=-1 ){ - e += 1; - dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); - } - } - *pResult = rr[0]+rr[1]; - if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; - if( sign<0 ) *pResult = -*pResult; - assert( !sqlite3IsNaN(*pResult) ); - -atof_return: - /* return true if number and no extra non-whitespace characters after */ - if( z==zEnd && nDigit>0 && eValid && eType>0 ){ - return eType; - }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){ - return -1; - }else{ - return 0; - } + if( e<0 ) { + esign = -1; + e *= -1; + } else { + esign = 1; + } + + if( s==0 ) { + /* In the IEEE 754 standard, zero is signed. */ + result = sign<0 ? -(double)0 : (double)0; + } else { + /* Attempt to reduce exponent. + ** + ** Branches that are not required for the correct answer but which only + ** help to obtain the correct answer faster are marked with special + ** comments, as a hint to the mutation tester. + */ + while( e>0 ){ /*OPTIMIZATION-IF-TRUE*/ + if( esign>0 ){ + if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ + s *= 10; + }else{ + if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ + s /= 10; + } + e--; + } + + /* adjust the sign of significand */ + s = sign<0 ? -s : s; + + 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; } + if( esign<0 ){ + result = s / scale; + result /= 1.0e+308; + }else{ + result = s * scale; + result *= 1.0e+308; + } + }else{ assert( e>=342 ); + if( esign<0 ){ + result = 0.0*s; + }else{ + result = 1e308*1e308*s; /* Infinity */ + } + } + }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; } + if( esign<0 ){ + result = s / scale; + }else{ + result = s * scale; + } + } + } + } + + /* store the result */ + *pResult = result; + + /* return true if number and no extra non-whitespace chracters after */ + return z==zEnd && nDigits>0 && eValid && nonNum==0; #else return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */ } -#if defined(_MSC_VER) -#pragma warning(default : 4756) -#endif - -/* -** Render an signed 64-bit integer as text. Store the result in zOut[] and -** return the length of the string that was stored, in bytes. The value -** returned does not include the zero terminator at the end of the output -** string. -** -** The caller must ensure that zOut[] is at least 21 bytes in size. -*/ -SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){ - int i; - u64 x; - char zTemp[22]; - if( v<0 ){ - x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v; - }else{ - x = v; - } - i = sizeof(zTemp)-2; - zTemp[sizeof(zTemp)-1] = 0; - while( 1 /*exit-by-break*/ ){ - zTemp[i] = (x%10) + '0'; - x = x/10; - if( x==0 ) break; - i--; - }; - if( v<0 ) zTemp[--i] = '-'; - memcpy(zOut, &zTemp[i], sizeof(zTemp)-i); - return sizeof(zTemp)-1-i; -} /* ** Compare the 19-character string zNum against the text representation ** value 2^63: 9223372036854775808. Return negative, zero, or positive ** if zNum is less than, equal to, or greater than the string. @@ -36039,17 +28720,20 @@ /* ** Convert zNum to a 64-bit signed integer. zNum must be decimal. This ** routine does *not* accept hexadecimal notation. ** -** Returns: +** If the zNum value is representable as a 64-bit twos-complement +** integer, then write that value into *pNum and return 0. ** -** -1 Not even a prefix of the input text looks like an integer -** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Excess non-space text after the integer value -** 2 Integer too large for a 64-bit signed integer or is malformed -** 3 Special case of 9223372036854775808 +** 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. +** +** 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. ** ** length is the number of bytes in the string (bytes, not characters). ** The string is not necessarily zero-terminated. The encoding is ** given by enc. */ @@ -36058,19 +28742,17 @@ u64 u = 0; int neg = 0; /* assume positive */ 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 ); if( enc==SQLITE_UTF8 ){ incr = 1; }else{ incr = 2; - length &= ~1; assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); for(i=3-enc; i='0' && c<='9'; i+=incr){ u = u*10 + c - '0'; } - testcase( i==18*incr ); - testcase( i==19*incr ); - testcase( i==20*incr ); if( u>LARGEST_INT64 ){ - /* This test and assignment is needed only to suppress UB warnings - ** from clang and -fsanitize=undefined. This test and assignment make - ** the code a little larger and slower, and no harm comes from omitting - ** them, but we must appease the undefined-behavior pharisees. */ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; }else if( neg ){ *pNum = -(i64)u; }else{ *pNum = (i64)u; } - rc = 0; - if( i==0 && zStart==zNum ){ /* No digits */ - rc = -1; - }else if( nonNum ){ /* UTF16 with high-order bytes non-zero */ - rc = 1; - }else if( &zNum[i]19*incr /* Too many digits */ + || nonNum /* UTF16 with high-order bytes non-zero */ + ){ + /* zNum is empty or contains non-numeric text or is longer + ** than 19 digits (thus guaranteeing that it is too large) */ + return 1; + }else if( i<19*incr ){ /* Less than 19 digits, so we know that it fits in 64 bits */ assert( u<=LARGEST_INT64 ); - return rc; + return 0; }else{ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ - c = i>19*incr ? 1 : compare2pow63(zNum, incr); + c = compare2pow63(zNum, incr); if( c<0 ){ /* zNum is less than 9223372036854775808 so it fits */ assert( u<=LARGEST_INT64 ); - return rc; - }else{ - *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; - if( c>0 ){ - /* zNum is greater than 9223372036854775808 so it overflows */ - return 2; - }else{ - /* zNum is exactly 9223372036854775808. Fits if negative. The - ** special case 2 overflow if positive */ - assert( u-1==LARGEST_INT64 ); - return neg ? rc : 3; - } + return 0; + }else if( c>0 ){ + /* zNum is greater than 9223372036854775808 so it overflows */ + return 1; + }else{ + /* zNum is exactly 9223372036854775808. Fits if negative. The + ** special case 2 overflow if positive */ + assert( u-1==LARGEST_INT64 ); + return neg ? 0 : 2; } } } /* @@ -36150,13 +28818,12 @@ ** whereas sqlite3Atoi64() does not. ** ** Returns: ** ** 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 +** 1 Integer too large for a 64-bit signed integer or is malformed +** 2 Special case of 9223372036854775808 */ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') @@ -36166,19 +28833,15 @@ for(i=2; z[i]=='0'; i++){} for(k=i; sqlite3Isxdigit(z[k]); k++){ u = u*16 + sqlite3HexToInt(z[k]); } memcpy(pOut, &u, 8); - if( k-i>16 ) return 2; - if( z[k]!=0 ) return 1; - return 0; + return (z[k]==0 && k-i<=16) ? 0 : 1; }else #endif /* SQLITE_OMIT_HEX_INTEGER */ { - int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789")); - if( z[n] ) n++; - return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8); + return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); } } /* ** If zNum represents an integer that will fit in 32-bits, then set @@ -36206,11 +28869,11 @@ && sqlite3Isxdigit(zNum[2]) ){ u32 u = 0; zNum += 2; while( zNum[0]=='0' ) zNum++; - for(i=0; i<8 && sqlite3Isxdigit(zNum[i]); i++){ + for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){ u = u*16 + sqlite3HexToInt(zNum[i]); } if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ memcpy(pValue, &u, 4); return 1; @@ -36249,168 +28912,14 @@ ** Return a 32-bit integer value extracted from a string. If the ** string is not an integer, just return 0. */ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ int x = 0; - sqlite3GetInt32(z, &x); + if( z ) sqlite3GetInt32(z, &x); return x; } -/* -** Decode a floating-point value into an approximate decimal -** representation. -** -** If iRound<=0 then round to -iRound significant digits to the -** the left of the decimal point, or to a maximum of mxRound total -** significant digits. -** -** If iRound>0 round to min(iRound,mxRound) significant digits total. -** -** mxRound must be positive. -** -** The significant digits of the decimal representation are -** stored in p->z[] which is a often (but not always) a pointer -** into the middle of p->zBuf[]. There are p->n significant digits. -** The p->z[] array is *not* zero-terminated. -*/ -SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ - int i; - u64 v; - int e, exp = 0; - double rr[2]; - - p->isSpecial = 0; - p->z = p->zBuf; - assert( mxRound>0 ); - - /* Convert negative numbers to positive. Deal with Infinity, 0.0, and - ** NaN. */ - if( r<0.0 ){ - p->sign = '-'; - r = -r; - }else if( r==0.0 ){ - p->sign = '+'; - p->n = 1; - p->iDP = 1; - p->z = "0"; - return; - }else{ - p->sign = '+'; - } - memcpy(&v,&r,8); - e = v>>52; - if( (e&0x7ff)==0x7ff ){ - p->isSpecial = 1 + (v!=0x7ff0000000000000LL); - p->n = 0; - p->iDP = 0; - return; - } - - /* Multiply r by powers of ten until it lands somewhere in between - ** 1.0e+19 and 1.0e+17. - ** - ** Use Dekker-style double-double computation to increase the - ** precision. - ** - ** The error terms on constants like 1.0e+100 computed using the - ** decimal extension, for example as follows: - ** - ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); - */ - rr[0] = r; - rr[1] = 0.0; - if( rr[0]>9.223372036854774784e+18 ){ - while( rr[0]>9.223372036854774784e+118 ){ - exp += 100; - dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); - } - while( rr[0]>9.223372036854774784e+28 ){ - exp += 10; - dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); - } - while( rr[0]>9.223372036854774784e+18 ){ - exp += 1; - dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); - } - }else{ - while( rr[0]<9.223372036854774784e-83 ){ - exp -= 100; - dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); - } - while( rr[0]<9.223372036854774784e+07 ){ - exp -= 10; - dekkerMul2(rr, 1.0e+10, 0.0); - } - while( rr[0]<9.22337203685477478e+17 ){ - exp -= 1; - dekkerMul2(rr, 1.0e+01, 0.0); - } - } - v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; - - /* Extract significant digits. */ - i = sizeof(p->zBuf)-1; - assert( v>0 ); - while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } - assert( i>=0 && izBuf)-1 ); - p->n = sizeof(p->zBuf) - 1 - i; - assert( p->n>0 ); - assert( p->nzBuf) ); - p->iDP = p->n + exp; - if( iRound<=0 ){ - iRound = p->iDP - iRound; - if( iRound==0 && p->zBuf[i+1]>='5' ){ - iRound = 1; - p->zBuf[i--] = '0'; - p->n++; - p->iDP++; - } - } - if( iRound>0 && (iRoundn || p->n>mxRound) ){ - char *z = &p->zBuf[i+1]; - if( iRound>mxRound ) iRound = mxRound; - p->n = iRound; - if( z[iRound]>='5' ){ - int j = iRound-1; - while( 1 /*exit-by-break*/ ){ - z[j]++; - if( z[j]<='9' ) break; - z[j] = '0'; - if( j==0 ){ - p->z[i--] = '1'; - p->n++; - p->iDP++; - break; - }else{ - j--; - } - } - } - } - p->z = &p->zBuf[i+1]; - assert( i+p->n < sizeof(p->zBuf) ); - while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; } -} - -/* -** Try to convert z into an unsigned 32-bit integer. Return true on -** success and false if there is an error. -** -** Only decimal notation is accepted. -*/ -SQLITE_PRIVATE int sqlite3GetUInt32(const char *z, u32 *pI){ - u64 v = 0; - int i; - for(i=0; sqlite3Isdigit(z[i]); i++){ - v = v*10 + z[i] - '0'; - if( v>4294967296LL ){ *pI = 0; return 0; } - } - if( i==0 || z[i]!=0 ){ *pI = 0; return 0; } - *pI = (u32)v; - return 1; -} - /* ** The variable-length integer encoding is as follows: ** ** KEY: ** A = 0xxxxxxx 7 bits of data and one flag bit @@ -36447,11 +28956,11 @@ for(i=7; i>=0; i--){ p[i] = (u8)((v & 0x7f) | 0x80); v >>= 7; } return 9; - } + } n = 0; do{ buf[n++] = (u8)((v & 0x7f) | 0x80); v >>= 7; }while( v!=0 ); @@ -36493,26 +29002,36 @@ ** Return the number of bytes read. The value is stored in *v. */ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ u32 a,b,s; - if( ((signed char*)p)[0]>=0 ){ - *v = *p; + a = *p; + /* a: p0 (unmasked) */ + if (!(a&0x80)) + { + *v = a; return 1; } - if( ((signed char*)p)[1]>=0 ){ - *v = ((u32)(p[0]&0x7f)<<7) | p[1]; + + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + a |= b; + *v = a; return 2; } /* Verify that constants are precomputed correctly */ assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); - a = ((u32)p[0])<<14; - b = p[1]; - p += 2; + p++; + a = a<<14; a |= *p; /* a: p0<<14 | p2 (unmasked) */ if (!(a&0x80)) { a &= SLOT_2_0; @@ -36647,41 +29166,131 @@ ** Return the number of bytes read. The value is stored in *v. ** ** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned ** integer, then set *v to 0xffffffff. ** -** A MACRO version, getVarint32, is provided which inlines the -** single-byte case. All code should use the MACRO version as +** A MACRO version, getVarint32, is provided which inlines the +** single-byte case. All code should use the MACRO version as ** this function assumes the single-byte case has already been handled. */ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ - u64 v64; - u8 n; - - /* Assume that the single-byte case has already been handled by - ** the getVarint32() macro */ - assert( (p[0] & 0x80)!=0 ); - - if( (p[1] & 0x80)==0 ){ - /* This is the two-byte case */ - *v = ((p[0]&0x7f)<<7) | p[1]; + u32 a,b; + + /* The 1-byte case. Overwhelmingly the most common. Handled inline + ** by the getVarin32() macro */ + a = *p; + /* a: p0 (unmasked) */ +#ifndef getVarint32 + if (!(a&0x80)) + { + /* Values between 0 and 127 */ + *v = a; + return 1; + } +#endif + + /* The 2-byte case */ + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 128 and 16383 */ + a &= 0x7f; + a = a<<7; + *v = a | b; return 2; } - if( (p[2] & 0x80)==0 ){ - /* This is the three-byte case */ - *v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2]; + + /* The 3-byte case */ + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 16384 and 2097151 */ + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + *v = a | b; return 3; } - /* four or more bytes */ - n = sqlite3GetVarint(p, &v64); - assert( n>3 && n<=9 ); - if( (v64 & SQLITE_MAX_U32)!=v64 ){ - *v = 0xffffffff; - }else{ + + /* A 32-bit varint is used to store size information in btrees. + ** Objects are rarely larger than 2MiB limit of a 3-byte varint. + ** A 3-byte varint is sufficient, for example, to record the size + ** of a 1048569-byte BLOB or string. + ** + ** We only unroll the first 1-, 2-, and 3- byte cases. The very + ** rare larger cases can be handled by the slower 64-bit varint + ** routine. + */ +#if 1 + { + u64 v64; + u8 n; + + p -= 2; + n = sqlite3GetVarint(p, &v64); + assert( n>3 && n<=9 ); + if( (v64 & SQLITE_MAX_U32)!=v64 ){ + *v = 0xffffffff; + }else{ + *v = (u32)v64; + } + return n; + } + +#else + /* For following code (kept for historical record only) shows an + ** unrolling for the 3- and 4-byte varint cases. This code is + ** slightly faster, but it is also larger and much harder to test. + */ + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 2097152 and 268435455 */ + b &= (0x7f<<14)|(0x7f); + a &= (0x7f<<14)|(0x7f); + a = a<<7; + *v = a | b; + return 4; + } + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 268435456 and 34359738367 */ + a &= SLOT_4_2_0; + b &= SLOT_4_2_0; + b = b<<7; + *v = a | b; + return 5; + } + + /* We can only reach this point when reading a corrupt database + ** file. In that case we are not in any hurry. Use the (relatively + ** slow) general-purpose sqlite3GetVarint() routine to extract the + ** value. */ + { + u64 v64; + u8 n; + + p -= 4; + n = sqlite3GetVarint(p, &v64); + assert( n>5 && n<=9 ); *v = (u32)v64; + return n; } - return n; +#endif } /* ** Return the number of bytes that will be needed to store the given ** 64-bit integer. @@ -36747,11 +29356,11 @@ h += 9*(1&~(h>>4)); #endif return (u8)(h & 0xf); } -#if !defined(SQLITE_OMIT_BLOB_LITERAL) +#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary ** value. Return a pointer to its binary value. Space to hold the ** binary value has been obtained from malloc and must be freed by ** the calling routine. @@ -36768,19 +29377,19 @@ } zBlob[i/2] = 0; } return zBlob; } -#endif /* !SQLITE_OMIT_BLOB_LITERAL */ +#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ /* ** Log an error that is an API call on a connection pointer that should ** not have been used. The "type" of connection pointer is given as the ** argument. The zType is a word like "NULL" or "closed" or "invalid". */ static void logBadConnection(const char *zType){ - sqlite3_log(SQLITE_MISUSE, + sqlite3_log(SQLITE_MISUSE, "API call with %s database connection pointer", zType ); } @@ -36797,17 +29406,17 @@ ** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to ** open properly and is not fit for general use but which can be ** used as an argument to sqlite3_errmsg() or sqlite3_close(). */ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ - u8 eOpenState; + u32 magic; if( db==0 ){ logBadConnection("NULL"); return 0; } - eOpenState = db->eOpenState; - if( eOpenState!=SQLITE_STATE_OPEN ){ + magic = db->magic; + if( magic!=SQLITE_MAGIC_OPEN ){ if( sqlite3SafetyCheckSickOrOk(db) ){ testcase( sqlite3GlobalConfig.xLog!=0 ); logBadConnection("unopened"); } return 0; @@ -36814,31 +29423,31 @@ }else{ return 1; } } SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ - u8 eOpenState; - eOpenState = db->eOpenState; - if( eOpenState!=SQLITE_STATE_SICK && - eOpenState!=SQLITE_STATE_OPEN && - eOpenState!=SQLITE_STATE_BUSY ){ + u32 magic; + magic = db->magic; + if( magic!=SQLITE_MAGIC_SICK && + magic!=SQLITE_MAGIC_OPEN && + magic!=SQLITE_MAGIC_BUSY ){ testcase( sqlite3GlobalConfig.xLog!=0 ); logBadConnection("invalid"); return 0; }else{ return 1; } } /* -** Attempt to add, subtract, or multiply the 64-bit signed value iB against +** Attempt to add, substract, or multiply the 64-bit signed value iB against ** the other 64-bit signed integer at *pA and store the result in *pA. ** Return 0 on success. Or if the operation would have resulted in an ** overflow, leave *pA unchanged and return 1. */ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) +#if GCC_VERSION>=5004000 return __builtin_add_overflow(*pA, iB, pA); #else i64 iA = *pA; testcase( iA==0 ); testcase( iA==1 ); testcase( iB==-1 ); testcase( iB==0 ); @@ -36850,15 +29459,15 @@ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 ); testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 ); if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1; } *pA += iB; - return 0; + return 0; #endif } SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) +#if GCC_VERSION>=5004000 return __builtin_sub_overflow(*pA, iB, pA); #else testcase( iB==SMALLEST_INT64+1 ); if( iB==SMALLEST_INT64 ){ testcase( (*pA)==(-1) ); testcase( (*pA)==0 ); @@ -36869,11 +29478,11 @@ return sqlite3AddInt64(pA, -iB); } #endif } SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) +#if GCC_VERSION>=5004000 return __builtin_mul_overflow(*pA, iB, pA); #else i64 iA = *pA; if( iB>0 ){ if( iA>LARGEST_INT64/iB ) return 1; @@ -36891,11 +29500,11 @@ return 0; #endif } /* -** Compute the absolute value of a 32-bit signed integer, of possible. Or +** Compute the absolute value of a 32-bit signed integer, of possible. Or ** if the integer has a value of -2147483648, return +2147483647 */ SQLITE_PRIVATE int sqlite3AbsInt32(int x){ if( x>=0 ) return x; if( x==(int)0x80000000 ) return 0x7fffffff; @@ -36931,15 +29540,15 @@ if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); } } #endif -/* +/* ** Find (an approximate) sum of two LogEst values. This computation is ** not a simple "+" operator because LogEst is stored as a logarithmic ** value. -** +** */ SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){ static const unsigned char x[] = { 10, 10, /* 0,1 */ 9, 9, /* 2,3 */ @@ -36971,22 +29580,17 @@ LogEst y = 40; if( x<8 ){ 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; } +#ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Convert a double into a LogEst ** In other words, compute an approximation for 10*log2(x). */ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){ @@ -36997,23 +29601,38 @@ if( x<=2000000000 ) return sqlite3LogEst((u64)x); memcpy(&a, &x, 8); e = (a>>52) - 1022; return e*10; } +#endif /* SQLITE_OMIT_VIRTUALTABLE */ +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ + defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ + defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) /* ** Convert a LogEst into an integer. +** +** Note that this routine is only used when one or more of various +** non-standard compile-time options is enabled. */ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ u64 n; n = x%10; x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ + defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) if( x>60 ) return (u64)LARGEST_INT64; +#else + /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input + ** possible to this routine is 310, resulting in a maximum x of 31 */ + assert( x<=60 ); +#endif return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x); } +#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ /* ** Add a new name/number pair to a VList. This might require that the ** VList object be reallocated, so return the new VList. If an OOM ** error occurs, the original VList returned and the @@ -37033,21 +29652,21 @@ ** is always zero-terminated. ** ** Conceptually: ** ** struct VList { -** int nAlloc; // Number of allocated slots -** int nUsed; // Number of used slots +** int nAlloc; // Number of allocated slots +** int nUsed; // Number of used slots ** struct VListEntry { ** int iValue; // Value for this entry ** int nSlot; // Slots used by this entry ** // ... 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 +** 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() */ @@ -37062,11 +29681,11 @@ 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 */ - sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt; + 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; @@ -37215,11 +29834,11 @@ pH->first = pNew; } } -/* Resize the hash table so that it contains "new_size" buckets. +/* Resize the hash table so that it cantains "new_size" buckets. ** ** The hash table might fail to resize if sqlite3_malloc() fails or ** if the new size is the same as the prior size. ** Return TRUE if the resize occurs and false if not. */ @@ -37234,11 +29853,11 @@ if( new_size==pH->htsize ) return 0; #endif /* The inability to allocates space for a larger hash table is ** a performance hit but it is not a fatal error. So mark the - ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of + ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero() ** only zeroes the requested number of bytes whereas this module will ** use the actual amount of space allocated for the hash table (which ** may be larger than the requested amount). */ @@ -37268,11 +29887,11 @@ const Hash *pH, /* The pH to be searched */ const char *pKey, /* The key we are searching for */ unsigned int *pHash /* Write the hash value here */ ){ HashElem *elem; /* Used to loop thru the element list */ - unsigned int count; /* Number of elements left to test */ + int count; /* Number of elements left to test */ unsigned int h; /* The computed hash */ static HashElem nullElement = { 0, 0, 0, 0 }; if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ struct _ht *pEntry; @@ -37284,17 +29903,16 @@ h = 0; elem = pH->first; count = pH->count; } if( pHash ) *pHash = h; - while( count ){ + while( count-- ){ assert( elem!=0 ); - if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ + if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ return elem; } elem = elem->next; - count--; } return &nullElement; } /* Remove a single entry from the hash table given a pointer to that @@ -37305,11 +29923,11 @@ HashElem* elem, /* The element to be removed from the pH */ unsigned int h /* Hash value for the element */ ){ struct _ht *pEntry; if( elem->prev ){ - elem->prev->next = elem->next; + elem->prev->next = elem->next; }else{ pH->first = elem->next; } if( elem->next ){ elem->next->prev = elem->prev; @@ -37317,12 +29935,12 @@ if( pH->ht ){ pEntry = &pH->ht[h]; if( pEntry->chain==elem ){ pEntry->chain = elem->next; } - assert( pEntry->count>0 ); pEntry->count--; + assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; if( pH->count==0 ){ assert( pH->first==0 ); @@ -37404,1185 +30022,179 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ static const char *const azName[] = { /* 0 */ "Savepoint" OpHelp(""), /* 1 */ "AutoCommit" OpHelp(""), /* 2 */ "Transaction" OpHelp(""), - /* 3 */ "Checkpoint" OpHelp(""), - /* 4 */ "JournalMode" OpHelp(""), - /* 5 */ "Vacuum" OpHelp(""), - /* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), - /* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"), - /* 8 */ "Init" OpHelp("Start at P2"), - /* 9 */ "Goto" OpHelp(""), - /* 10 */ "Gosub" OpHelp(""), - /* 11 */ "InitCoroutine" OpHelp(""), - /* 12 */ "Yield" OpHelp(""), - /* 13 */ "MustBeInt" OpHelp(""), - /* 14 */ "Jump" OpHelp(""), - /* 15 */ "Once" OpHelp(""), - /* 16 */ "If" OpHelp(""), - /* 17 */ "IfNot" OpHelp(""), - /* 18 */ "IsType" OpHelp("if typeof(P1.P3) in P5 goto P2"), + /* 3 */ "SorterNext" OpHelp(""), + /* 4 */ "PrevIfOpen" OpHelp(""), + /* 5 */ "NextIfOpen" OpHelp(""), + /* 6 */ "Prev" OpHelp(""), + /* 7 */ "Next" OpHelp(""), + /* 8 */ "Checkpoint" OpHelp(""), + /* 9 */ "JournalMode" OpHelp(""), + /* 10 */ "Vacuum" OpHelp(""), + /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), + /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), + /* 13 */ "Goto" OpHelp(""), + /* 14 */ "Gosub" OpHelp(""), + /* 15 */ "InitCoroutine" OpHelp(""), + /* 16 */ "Yield" OpHelp(""), + /* 17 */ "MustBeInt" OpHelp(""), + /* 18 */ "Jump" OpHelp(""), /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), - /* 21 */ "SeekLT" OpHelp("key=r[P3@P4]"), - /* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"), - /* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"), - /* 24 */ "SeekGT" OpHelp("key=r[P3@P4]"), - /* 25 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"), - /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"), - /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"), - /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"), - /* 29 */ "Found" OpHelp("key=r[P3@P4]"), - /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"), - /* 31 */ "NotExists" OpHelp("intkey=r[P3]"), - /* 32 */ "Last" OpHelp(""), - /* 33 */ "IfSizeBetween" OpHelp(""), - /* 34 */ "SorterSort" OpHelp(""), - /* 35 */ "Sort" OpHelp(""), - /* 36 */ "Rewind" OpHelp(""), - /* 37 */ "SorterNext" OpHelp(""), - /* 38 */ "Prev" OpHelp(""), - /* 39 */ "Next" OpHelp(""), - /* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"), - /* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"), - /* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"), - /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"), - /* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 48 */ "Program" OpHelp(""), - /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), - /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), - /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), - /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"), - /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"), - /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"), - /* 57 */ "Lt" OpHelp("IF r[P3]=r[P1]"), - /* 59 */ "ElseEq" OpHelp(""), - /* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), - /* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 62 */ "IncrVacuum" OpHelp(""), - /* 63 */ "VNext" OpHelp(""), - /* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"), - /* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"), - /* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"), - /* 67 */ "Return" OpHelp(""), - /* 68 */ "EndCoroutine" OpHelp(""), - /* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 70 */ "Halt" OpHelp(""), - /* 71 */ "Integer" OpHelp("r[P2]=P1"), - /* 72 */ "Int64" OpHelp("r[P2]=P4"), - /* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"), - /* 75 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 76 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1)"), - /* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 83 */ "FkCheck" OpHelp(""), - /* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 85 */ "CollSeq" OpHelp(""), - /* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 87 */ "RealAffinity" OpHelp(""), - /* 88 */ "Cast" OpHelp("affinity(r[P1])"), - /* 89 */ "Permutation" OpHelp(""), - /* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), - /* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"), - /* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), - /* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"), - /* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"), - /* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 98 */ "Count" OpHelp("r[P2]=count()"), - /* 99 */ "ReadCookie" OpHelp(""), - /* 100 */ "SetCookie" OpHelp(""), - /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 114 */ "OpenDup" OpHelp(""), - /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), - /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 118 */ "String8" OpHelp("r[P2]='P4'"), - /* 119 */ "SorterOpen" OpHelp(""), - /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 122 */ "Close" OpHelp(""), - /* 123 */ "ColumnsUsed" OpHelp(""), - /* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"), - /* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"), - /* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 127 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 129 */ "RowCell" OpHelp(""), - /* 130 */ "Delete" OpHelp(""), - /* 131 */ "ResetCount" OpHelp(""), - /* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 133 */ "SorterData" OpHelp("r[P2]=data"), - /* 134 */ "RowData" OpHelp("r[P2]=data"), - /* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"), - /* 136 */ "NullRow" OpHelp(""), - /* 137 */ "SeekEnd" OpHelp(""), - /* 138 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 139 */ "SorterInsert" OpHelp("key=r[P2]"), - /* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), - /* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"), - /* 143 */ "FinishSeek" OpHelp(""), - /* 144 */ "Destroy" OpHelp(""), - /* 145 */ "Clear" OpHelp(""), - /* 146 */ "ResetSorter" OpHelp(""), - /* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), - /* 148 */ "SqlExec" OpHelp(""), - /* 149 */ "ParseSchema" OpHelp(""), - /* 150 */ "LoadAnalysis" OpHelp(""), - /* 151 */ "DropTable" OpHelp(""), - /* 152 */ "DropIndex" OpHelp(""), - /* 153 */ "DropTrigger" OpHelp(""), - /* 154 */ "Real" OpHelp("r[P2]=P4"), - /* 155 */ "IntegrityCk" OpHelp(""), - /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 157 */ "Param" OpHelp(""), - /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), - /* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"), - /* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 166 */ "Expire" OpHelp(""), - /* 167 */ "CursorLock" OpHelp(""), - /* 168 */ "CursorUnlock" OpHelp(""), - /* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 170 */ "VBegin" OpHelp(""), - /* 171 */ "VCreate" OpHelp(""), - /* 172 */ "VDestroy" OpHelp(""), - /* 173 */ "VOpen" OpHelp(""), - /* 174 */ "VCheck" OpHelp(""), - /* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), - /* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 177 */ "VRename" OpHelp(""), - /* 178 */ "Pagecount" OpHelp(""), - /* 179 */ "MaxPgcnt" OpHelp(""), - /* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), - /* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"), - /* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"), - /* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), - /* 184 */ "Trace" OpHelp(""), - /* 185 */ "CursorHint" OpHelp(""), - /* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), - /* 187 */ "Noop" OpHelp(""), - /* 188 */ "Explain" OpHelp(""), - /* 189 */ "Abortable" OpHelp(""), + /* 20 */ "Once" OpHelp(""), + /* 21 */ "If" OpHelp(""), + /* 22 */ "IfNot" OpHelp(""), + /* 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 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 44 */ "Program" OpHelp(""), + /* 45 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 46 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), + /* 47 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), + /* 48 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 49 */ "IncrVacuum" OpHelp(""), + /* 50 */ "VNext" OpHelp(""), + /* 51 */ "Init" OpHelp("Start at P2"), + /* 52 */ "Return" OpHelp(""), + /* 53 */ "EndCoroutine" OpHelp(""), + /* 54 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 55 */ "Halt" OpHelp(""), + /* 56 */ "Integer" OpHelp("r[P2]=P1"), + /* 57 */ "Int64" OpHelp("r[P2]=P4"), + /* 58 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 59 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 60 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 61 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 62 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 63 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 64 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 65 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 66 */ "IntCopy" OpHelp("r[P2]=r[P1]"), + /* 67 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 68 */ "CollSeq" OpHelp(""), + /* 69 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 70 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 71 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), + /* 72 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 73 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 74 */ "RealAffinity" OpHelp(""), + /* 75 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 76 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 77 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), + /* 78 */ "Eq" OpHelp("IF r[P3]==r[P1]"), + /* 79 */ "Gt" OpHelp("IF r[P3]>r[P1]"), + /* 80 */ "Le" OpHelp("IF r[P3]<=r[P1]"), + /* 81 */ "Lt" OpHelp("IF r[P3]=r[P1]"), + /* 83 */ "ElseNotEq" 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 */ "Cast" OpHelp("affinity(r[P1])"), + /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), + /* 96 */ "Permutation" OpHelp(""), + /* 97 */ "String8" OpHelp("r[P2]='P4'"), + /* 98 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 99 */ "Column" OpHelp("r[P3]=PX"), + /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 102 */ "Count" OpHelp("r[P2]=count()"), + /* 103 */ "ReadCookie" OpHelp(""), + /* 104 */ "SetCookie" OpHelp(""), + /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 108 */ "OpenDup" OpHelp(""), + /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 111 */ "SorterOpen" OpHelp(""), + /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 114 */ "Close" OpHelp(""), + /* 115 */ "ColumnsUsed" OpHelp(""), + /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 120 */ "Delete" OpHelp(""), + /* 121 */ "ResetCount" OpHelp(""), + /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 123 */ "SorterData" OpHelp("r[P2]=data"), + /* 124 */ "RowData" OpHelp("r[P2]=data"), + /* 125 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 126 */ "NullRow" 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 */ "Destroy" OpHelp(""), + /* 134 */ "Clear" OpHelp(""), + /* 135 */ "ResetSorter" OpHelp(""), + /* 136 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), + /* 137 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), + /* 138 */ "SqlExec" OpHelp(""), + /* 139 */ "ParseSchema" OpHelp(""), + /* 140 */ "LoadAnalysis" OpHelp(""), + /* 141 */ "DropTable" OpHelp(""), + /* 142 */ "DropIndex" OpHelp(""), + /* 143 */ "DropTrigger" OpHelp(""), + /* 144 */ "IntegrityCk" OpHelp(""), + /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 146 */ "Param" OpHelp(""), + /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 153 */ "Expire" OpHelp(""), + /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 155 */ "VBegin" OpHelp(""), + /* 156 */ "VCreate" OpHelp(""), + /* 157 */ "VDestroy" OpHelp(""), + /* 158 */ "VOpen" OpHelp(""), + /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 160 */ "VRename" OpHelp(""), + /* 161 */ "Pagecount" OpHelp(""), + /* 162 */ "MaxPgcnt" OpHelp(""), + /* 163 */ "CursorHint" OpHelp(""), + /* 164 */ "Noop" OpHelp(""), + /* 165 */ "Explain" OpHelp(""), }; return azName[i]; } #endif /************** End of opcodes.c *********************************************/ -/************** Begin file os_kv.c *******************************************/ -/* -** 2022-09-06 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains an experimental VFS layer that operates on a -** Key/Value storage engine where both keys and values must be pure -** text. -*/ -/* #include */ -#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)) - -/***************************************************************************** -** Debugging logic -*/ - -/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */ -#if 0 -#define SQLITE_KV_TRACE(X) printf X -#else -#define SQLITE_KV_TRACE(X) -#endif - -/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */ -#if 0 -#define SQLITE_KV_LOG(X) printf X -#else -#define SQLITE_KV_LOG(X) -#endif - - -/* -** Forward declaration of objects used by this VFS implementation -*/ -typedef struct KVVfsFile KVVfsFile; - -/* A single open file. There are only two files represented by this -** VFS - the database and the rollback journal. -*/ -struct KVVfsFile { - sqlite3_file base; /* IO methods */ - const char *zClass; /* Storage class */ - int isJournal; /* True if this is a journal file */ - unsigned int nJrnl; /* Space allocated for aJrnl[] */ - char *aJrnl; /* Journal content */ - int szPage; /* Last known page size */ - sqlite3_int64 szDb; /* Database file size. -1 means unknown */ - char *aData; /* Buffer to hold page data */ -}; -#define SQLITE_KVOS_SZ 133073 - -/* -** Methods for KVVfsFile -*/ -static int kvvfsClose(sqlite3_file*); -static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64); -static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64); -static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size); -static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size); -static int kvvfsSyncDb(sqlite3_file*, int flags); -static int kvvfsSyncJrnl(sqlite3_file*, int flags); -static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize); -static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize); -static int kvvfsLock(sqlite3_file*, int); -static int kvvfsUnlock(sqlite3_file*, int); -static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut); -static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg); -static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg); -static int kvvfsSectorSize(sqlite3_file*); -static int kvvfsDeviceCharacteristics(sqlite3_file*); - -/* -** Methods for sqlite3_vfs -*/ -static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir); -static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename); -static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int kvvfsSleep(sqlite3_vfs*, int microseconds); -static int kvvfsCurrentTime(sqlite3_vfs*, double*); -static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); - -static sqlite3_vfs sqlite3OsKvvfsObject = { - 1, /* iVersion */ - sizeof(KVVfsFile), /* szOsFile */ - 1024, /* mxPathname */ - 0, /* pNext */ - "kvvfs", /* zName */ - 0, /* pAppData */ - kvvfsOpen, /* xOpen */ - kvvfsDelete, /* xDelete */ - kvvfsAccess, /* xAccess */ - kvvfsFullPathname, /* xFullPathname */ - kvvfsDlOpen, /* xDlOpen */ - 0, /* xDlError */ - 0, /* xDlSym */ - 0, /* xDlClose */ - kvvfsRandomness, /* xRandomness */ - kvvfsSleep, /* xSleep */ - kvvfsCurrentTime, /* xCurrentTime */ - 0, /* xGetLastError */ - kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */ -}; - -/* Methods for sqlite3_file objects referencing a database file -*/ -static sqlite3_io_methods kvvfs_db_io_methods = { - 1, /* iVersion */ - kvvfsClose, /* xClose */ - kvvfsReadDb, /* xRead */ - kvvfsWriteDb, /* xWrite */ - kvvfsTruncateDb, /* xTruncate */ - kvvfsSyncDb, /* xSync */ - kvvfsFileSizeDb, /* xFileSize */ - kvvfsLock, /* xLock */ - kvvfsUnlock, /* xUnlock */ - kvvfsCheckReservedLock, /* xCheckReservedLock */ - kvvfsFileControlDb, /* xFileControl */ - kvvfsSectorSize, /* xSectorSize */ - kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - 0, /* xFetch */ - 0 /* xUnfetch */ -}; - -/* Methods for sqlite3_file objects referencing a rollback journal -*/ -static sqlite3_io_methods kvvfs_jrnl_io_methods = { - 1, /* iVersion */ - kvvfsClose, /* xClose */ - kvvfsReadJrnl, /* xRead */ - kvvfsWriteJrnl, /* xWrite */ - kvvfsTruncateJrnl, /* xTruncate */ - kvvfsSyncJrnl, /* xSync */ - kvvfsFileSizeJrnl, /* xFileSize */ - kvvfsLock, /* xLock */ - kvvfsUnlock, /* xUnlock */ - kvvfsCheckReservedLock, /* xCheckReservedLock */ - kvvfsFileControlJrnl, /* xFileControl */ - kvvfsSectorSize, /* xSectorSize */ - kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - 0, /* xFetch */ - 0 /* xUnfetch */ -}; - -/****** Storage subsystem **************************************************/ -#include -#include -#include - -/* Forward declarations for the low-level storage engine -*/ -static int kvstorageWrite(const char*, const char *zKey, const char *zData); -static int kvstorageDelete(const char*, const char *zKey); -static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); -#define KVSTORAGE_KEY_SZ 32 - -/* Expand the key name with an appropriate prefix and put the result -** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least -** KVSTORAGE_KEY_SZ bytes. -*/ -static void kvstorageMakeKey( - const char *zClass, - const char *zKeyIn, - char *zKeyOut -){ - sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); -} - -/* Write content into a key. zClass is the particular namespace of the -** underlying key/value store to use - either "local" or "session". -** -** Both zKey and zData are zero-terminated pure text strings. -** -** Return the number of errors. -*/ -static int kvstorageWrite( - const char *zClass, - const char *zKey, - const char *zData -){ - FILE *fd; - char zXKey[KVSTORAGE_KEY_SZ]; - kvstorageMakeKey(zClass, zKey, zXKey); - fd = fopen(zXKey, "wb"); - if( fd ){ - SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, - (int)strlen(zData), zData, - strlen(zData)>50 ? "..." : "")); - fputs(zData, fd); - fclose(fd); - return 0; - }else{ - return 1; - } -} - -/* Delete a key (with its corresponding data) from the key/value -** namespace given by zClass. If the key does not previously exist, -** this routine is a no-op. -*/ -static int kvstorageDelete(const char *zClass, const char *zKey){ - char zXKey[KVSTORAGE_KEY_SZ]; - kvstorageMakeKey(zClass, zKey, zXKey); - unlink(zXKey); - SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); - return 0; -} - -/* Read the value associated with a zKey from the key/value namespace given -** by zClass and put the text data associated with that key in the first -** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large -** enough to hold it all. The value put into zBuf must always be zero -** terminated, even if it gets truncated because nBuf is not large enough. -** -** Return the total number of bytes in the data, without truncation, and -** not counting the final zero terminator. Return -1 if the key does -** not exist. -** -** If nBuf<=0 then this routine simply returns the size of the data without -** actually reading it. -*/ -static int kvstorageRead( - const char *zClass, - const char *zKey, - char *zBuf, - int nBuf -){ - FILE *fd; - struct stat buf; - char zXKey[KVSTORAGE_KEY_SZ]; - kvstorageMakeKey(zClass, zKey, zXKey); - if( access(zXKey, R_OK)!=0 - || stat(zXKey, &buf)!=0 - || !S_ISREG(buf.st_mode) - ){ - SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); - return -1; - } - if( nBuf<=0 ){ - return (int)buf.st_size; - }else if( nBuf==1 ){ - zBuf[0] = 0; - SQLITE_KV_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey, - (int)buf.st_size)); - return (int)buf.st_size; - } - if( nBuf > buf.st_size + 1 ){ - nBuf = buf.st_size + 1; - } - fd = fopen(zXKey, "rb"); - if( fd==0 ){ - SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); - return -1; - }else{ - sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd); - fclose(fd); - zBuf[n] = 0; - SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey, - n, zBuf, n>50 ? "..." : "")); - return (int)n; - } -} - -/* -** An internal level of indirection which enables us to replace the -** kvvfs i/o methods with JavaScript implementations in WASM builds. -** Maintenance reminder: if this struct changes in any way, the JSON -** rendering of its structure must be updated in -** sqlite3_wasm_enum_json(). There are no binary compatibility -** concerns, so it does not need an iVersion member. This file is -** necessarily always compiled together with sqlite3_wasm_enum_json(), -** and JS code dynamically creates the mapping of members based on -** that JSON description. -*/ -typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; -struct sqlite3_kvvfs_methods { - int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf); - int (*xWrite)(const char *zClass, const char *zKey, const char *zData); - int (*xDelete)(const char *zClass, const char *zKey); - const int nKeySize; -}; - -/* -** This object holds the kvvfs I/O methods which may be swapped out -** for JavaScript-side implementations in WASM builds. In such builds -** it cannot be const, but in native builds it should be so that -** the compiler can hopefully optimize this level of indirection out. -** That said, kvvfs is intended primarily for use in WASM builds. -** -** Note that this is not explicitly flagged as static because the -** amalgamation build will tag it with SQLITE_PRIVATE. -*/ -#ifndef SQLITE_WASM -const -#endif -SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { -kvstorageRead, -kvstorageWrite, -kvstorageDelete, -KVSTORAGE_KEY_SZ -}; - -/****** Utility subroutines ************************************************/ - -/* -** Encode binary into the text encoded used to persist on disk. -** The output text is stored in aOut[], which must be at least -** nData+1 bytes in length. -** -** Return the actual length of the encoded text, not counting the -** zero terminator at the end. -** -** Encoding format -** --------------- -** -** * Non-zero bytes are encoded as upper-case hexadecimal -** -** * A sequence of one or more zero-bytes that are not at the -** beginning of the buffer are encoded as a little-endian -** base-26 number using a..z. "a" means 0. "b" means 1, -** "z" means 25. "ab" means 26. "ac" means 52. And so forth. -** -** * Because there is no overlap between the encoding characters -** of hexadecimal and base-26 numbers, it is always clear where -** one stops and the next begins. -*/ -static int kvvfsEncode(const char *aData, int nData, char *aOut){ - int i, j; - const unsigned char *a = (const unsigned char*)aData; - for(i=j=0; i>4]; - aOut[j++] = "0123456789ABCDEF"[c&0xf]; - }else{ - /* A sequence of 1 or more zeros is stored as a little-endian - ** base-26 number using a..z as the digits. So one zero is "b". - ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb", - ** and so forth. - */ - int k; - for(k=1; i+k0 ){ - aOut[j++] = 'a'+(k%26); - k /= 26; - } - } - } - aOut[j] = 0; - return j; -} - -static const signed char kvvfsHexValue[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -/* -** Decode the text encoding back to binary. The binary content is -** written into pOut, which must be at least nOut bytes in length. -** -** The return value is the number of bytes actually written into aOut[]. -*/ -static int kvvfsDecode(const char *a, char *aOut, int nOut){ - int i, j; - int c; - const unsigned char *aIn = (const unsigned char*)a; - i = 0; - j = 0; - while( 1 ){ - c = kvvfsHexValue[aIn[i]]; - if( c<0 ){ - int n = 0; - int mult = 1; - c = aIn[i]; - if( c==0 ) break; - while( c>='a' && c<='z' ){ - n += (c - 'a')*mult; - mult *= 26; - c = aIn[++i]; - } - if( j+n>nOut ) return -1; - memset(&aOut[j], 0, n); - j += n; - if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */ - }else{ - aOut[j] = c<<4; - c = kvvfsHexValue[aIn[++i]]; - if( c<0 ) break; - aOut[j++] += c; - i++; - } - } - return j; -} - -/* -** Decode a complete journal file. Allocate space in pFile->aJrnl -** and store the decoding there. Or leave pFile->aJrnl set to NULL -** if an error is encountered. -** -** The first few characters of the text encoding will be a little-endian -** base-26 number (digits a..z) that is the total number of bytes -** in the decoded journal file image. This base-26 number is followed -** by a single space, then the encoding of the journal. The space -** separator is required to act as a terminator for the base-26 number. -*/ -static void kvvfsDecodeJournal( - KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */ - const char *zTxt, /* Text encoding. Zero-terminated */ - int nTxt /* Bytes in zTxt, excluding zero terminator */ -){ - unsigned int n = 0; - int c, i, mult; - i = 0; - mult = 1; - while( (c = zTxt[i++])>='a' && c<='z' ){ - n += (zTxt[i] - 'a')*mult; - mult *= 26; - } - sqlite3_free(pFile->aJrnl); - pFile->aJrnl = sqlite3_malloc64( n ); - if( pFile->aJrnl==0 ){ - pFile->nJrnl = 0; - return; - } - pFile->nJrnl = n; - n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl); - if( nnJrnl ){ - sqlite3_free(pFile->aJrnl); - pFile->aJrnl = 0; - pFile->nJrnl = 0; - } -} - -/* -** Read or write the "sz" element, containing the database file size. -*/ -static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){ - char zData[50]; - zData[0] = 0; - sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1); - return strtoll(zData, 0, 0); -} -static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){ - char zData[50]; - sqlite3_snprintf(sizeof(zData), zData, "%lld", sz); - return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData); -} - -/****** sqlite3_io_methods methods ******************************************/ - -/* -** Close an kvvfs-file. -*/ -static int kvvfsClose(sqlite3_file *pProtoFile){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - - SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass, - pFile->isJournal ? "journal" : "db")); - sqlite3_free(pFile->aJrnl); - sqlite3_free(pFile->aData); - return SQLITE_OK; -} - -/* -** Read from the -journal file. -*/ -static int kvvfsReadJrnl( - sqlite3_file *pProtoFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - assert( pFile->isJournal ); - SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); - if( pFile->aJrnl==0 ){ - int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0); - char *aTxt; - if( szTxt<=4 ){ - return SQLITE_IOERR; - } - aTxt = sqlite3_malloc64( szTxt+1 ); - if( aTxt==0 ) return SQLITE_NOMEM; - kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1); - kvvfsDecodeJournal(pFile, aTxt, szTxt); - sqlite3_free(aTxt); - if( pFile->aJrnl==0 ) return SQLITE_IOERR; - } - if( iOfst+iAmt>pFile->nJrnl ){ - return SQLITE_IOERR_SHORT_READ; - } - memcpy(zBuf, pFile->aJrnl+iOfst, iAmt); - return SQLITE_OK; -} - -/* -** Read from the database file. -*/ -static int kvvfsReadDb( - sqlite3_file *pProtoFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - unsigned int pgno; - int got, n; - char zKey[30]; - char *aData = pFile->aData; - assert( iOfst>=0 ); - assert( iAmt>=0 ); - SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); - if( iOfst+iAmt>=512 ){ - if( (iOfst % iAmt)!=0 ){ - return SQLITE_IOERR_READ; - } - if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){ - return SQLITE_IOERR_READ; - } - pFile->szPage = iAmt; - pgno = 1 + iOfst/iAmt; - }else{ - pgno = 1; - } - sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey, - aData, SQLITE_KVOS_SZ-1); - if( got<0 ){ - n = 0; - }else{ - aData[got] = 0; - if( iOfst+iAmt<512 ){ - int k = iOfst+iAmt; - aData[k*2] = 0; - n = kvvfsDecode(aData, &aData[2000], SQLITE_KVOS_SZ-2000); - if( n>=iOfst+iAmt ){ - memcpy(zBuf, &aData[2000+iOfst], iAmt); - n = iAmt; - }else{ - n = 0; - } - }else{ - n = kvvfsDecode(aData, zBuf, iAmt); - } - } - if( nzClass, iAmt, iOfst)); - if( iEnd>=0x10000000 ) return SQLITE_FULL; - if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd); - if( aNew==0 ){ - return SQLITE_IOERR_NOMEM; - } - pFile->aJrnl = aNew; - if( pFile->nJrnlaJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl); - } - pFile->nJrnl = iEnd; - } - memcpy(pFile->aJrnl+iOfst, zBuf, iAmt); - return SQLITE_OK; -} - -/* -** Write into the database file. -*/ -static int kvvfsWriteDb( - sqlite3_file *pProtoFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - unsigned int pgno; - char zKey[30]; - char *aData = pFile->aData; - SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); - assert( iAmt>=512 && iAmt<=65536 ); - assert( (iAmt & (iAmt-1))==0 ); - assert( pFile->szPage<0 || pFile->szPage==iAmt ); - pFile->szPage = iAmt; - pgno = 1 + iOfst/iAmt; - sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - kvvfsEncode(zBuf, iAmt, aData); - if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){ - return SQLITE_IOERR; - } - if( iOfst+iAmt > pFile->szDb ){ - pFile->szDb = iOfst + iAmt; - } - return SQLITE_OK; -} - -/* -** Truncate an kvvfs-file. -*/ -static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); - assert( size==0 ); - sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl"); - sqlite3_free(pFile->aJrnl); - pFile->aJrnl = 0; - pFile->nJrnl = 0; - return SQLITE_OK; -} -static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - if( pFile->szDb>size - && pFile->szPage>0 - && (size % pFile->szPage)==0 - ){ - char zKey[50]; - unsigned int pgno, pgnoMax; - SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size)); - pgno = 1 + size/pFile->szPage; - pgnoMax = 2 + pFile->szDb/pFile->szPage; - while( pgno<=pgnoMax ){ - sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey); - pgno++; - } - pFile->szDb = size; - return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK; - } - return SQLITE_IOERR; -} - -/* -** Sync an kvvfs-file. -*/ -static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ - int i, n; - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - char *zOut; - SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass)); - if( pFile->nJrnl<=0 ){ - return kvvfsTruncateJrnl(pProtoFile, 0); - } - zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 ); - if( zOut==0 ){ - return SQLITE_IOERR_NOMEM; - } - n = pFile->nJrnl; - i = 0; - do{ - zOut[i++] = 'a' + (n%26); - n /= 26; - }while( n>0 ); - zOut[i++] = ' '; - kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); - i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut); - sqlite3_free(zOut); - return i ? SQLITE_IOERR : SQLITE_OK; -} -static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){ - return SQLITE_OK; -} - -/* -** Return the current file-size of an kvvfs-file. -*/ -static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass)); - *pSize = pFile->nJrnl; - return SQLITE_OK; -} -static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass)); - if( pFile->szDb>=0 ){ - *pSize = pFile->szDb; - }else{ - *pSize = kvvfsReadFileSize(pFile); - } - return SQLITE_OK; -} - -/* -** Lock an kvvfs-file. -*/ -static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - assert( !pFile->isJournal ); - SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock)); - - if( eLock!=SQLITE_LOCK_NONE ){ - pFile->szDb = kvvfsReadFileSize(pFile); - } - return SQLITE_OK; -} - -/* -** Unlock an kvvfs-file. -*/ -static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - assert( !pFile->isJournal ); - SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock)); - if( eLock==SQLITE_LOCK_NONE ){ - pFile->szDb = -1; - } - return SQLITE_OK; -} - -/* -** Check if another file-handle holds a RESERVED lock on an kvvfs-file. -*/ -static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){ - SQLITE_KV_LOG(("xCheckReservedLock\n")); - *pResOut = 0; - return SQLITE_OK; -} - -/* -** File control method. For custom operations on an kvvfs-file. -*/ -static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){ - SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op)); - return SQLITE_NOTFOUND; -} -static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){ - SQLITE_KV_LOG(("xFileControl(%d) on database\n", op)); - if( op==SQLITE_FCNTL_SYNC ){ - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - int rc = SQLITE_OK; - SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass)); - if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){ - rc = SQLITE_IOERR; - } - return rc; - } - return SQLITE_NOTFOUND; -} - -/* -** Return the sector-size in bytes for an kvvfs-file. -*/ -static int kvvfsSectorSize(sqlite3_file *pFile){ - return 512; -} - -/* -** Return the device characteristic flags supported by an kvvfs-file. -*/ -static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){ - return 0; -} - -/****** sqlite3_vfs methods *************************************************/ - -/* -** Open an kvvfs file handle. -*/ -static int kvvfsOpen( - sqlite3_vfs *pProtoVfs, - const char *zName, - sqlite3_file *pProtoFile, - int flags, - int *pOutFlags -){ - KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - if( zName==0 ) zName = ""; - SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName)); - if( strcmp(zName, "local")==0 - || strcmp(zName, "session")==0 - ){ - pFile->isJournal = 0; - pFile->base.pMethods = &kvvfs_db_io_methods; - }else - if( strcmp(zName, "local-journal")==0 - || strcmp(zName, "session-journal")==0 - ){ - pFile->isJournal = 1; - pFile->base.pMethods = &kvvfs_jrnl_io_methods; - }else{ - return SQLITE_CANTOPEN; - } - if( zName[0]=='s' ){ - pFile->zClass = "session"; - }else{ - pFile->zClass = "local"; - } - pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ); - if( pFile->aData==0 ){ - return SQLITE_NOMEM; - } - pFile->aJrnl = 0; - pFile->nJrnl = 0; - pFile->szPage = -1; - pFile->szDb = -1; - return SQLITE_OK; -} - -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - if( strcmp(zPath, "local-journal")==0 ){ - sqlite3KvvfsMethods.xDelete("local", "jrnl"); - }else - if( strcmp(zPath, "session-journal")==0 ){ - sqlite3KvvfsMethods.xDelete("session", "jrnl"); - } - return SQLITE_OK; -} - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -*/ -static int kvvfsAccess( - sqlite3_vfs *pProtoVfs, - const char *zPath, - int flags, - int *pResOut -){ - SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath)); - if( strcmp(zPath, "local-journal")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0; - }else - if( strcmp(zPath, "session-journal")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0; - }else - if( strcmp(zPath, "local")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0; - }else - if( strcmp(zPath, "session")==0 ){ - *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0; - }else - { - *pResOut = 0; - } - SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut)); - return SQLITE_OK; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (INST_MAX_PATHNAME+1) bytes. -*/ -static int kvvfsFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - size_t nPath; -#ifdef SQLITE_OS_KV_ALWAYS_LOCAL - zPath = "local"; -#endif - nPath = strlen(zPath); - SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath)); - if( nOut -static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ - static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; - struct timeval sNow; - (void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */ - *pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000; - return SQLITE_OK; -} -#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */ - -#if SQLITE_OS_KV -/* -** This routine is called initialize the KV-vfs as the default VFS. -*/ -SQLITE_API int sqlite3_os_init(void){ - return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1); -} -SQLITE_API int sqlite3_os_end(void){ - return SQLITE_OK; -} -#endif /* SQLITE_OS_KV */ - -#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) -SQLITE_PRIVATE int sqlite3KvvfsInit(void){ - return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0); -} -#endif - -/************** End of os_kv.c ***********************************************/ /************** Begin file os_unix.c *****************************************/ /* ** 2004 May 22 ** ** The author disclaims copyright to this source code. In place of @@ -38604,11 +30216,11 @@ ** skip locking all together. ** ** This source file is organized into divisions where the logic for various ** subfunctions is contained within the appropriate division. PLEASE ** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed -** in the correct division and should be clearly labelled. +** in the correct division and should be clearly labeled. ** ** The layout of divisions is as follows: ** ** * General-purpose declarations and utility functions. ** * Unique file ID logic used by VxWorks. @@ -38643,11 +30255,11 @@ ** 7. proxy locking. (OSX only) ** ** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE ** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic ** selection of the appropriate locking style based on the filesystem -** where the database is located. +** where the database is located. */ #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 # else @@ -38654,11 +30266,11 @@ # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif #endif /* Use pread() and pwrite() if they are available */ -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) # define HAVE_PREAD 1 # define HAVE_PWRITE 1 #endif #if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) # undef USE_PREAD @@ -38669,53 +30281,34 @@ #endif /* ** standard include files. */ -#include /* amalgamator: keep */ -#include /* amalgamator: keep */ +#include +#include #include -#include -#include /* amalgamator: keep */ +#include /* #include */ -#include /* amalgamator: keep */ +#include #include -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ - && !defined(SQLITE_WASI) +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 # include #endif #if SQLITE_ENABLE_LOCKING_STYLE -/* # include */ +# include # include # include #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -/* -** Try to determine if gethostuuid() is available based on standard -** macros. This might sometimes compute the wrong value for some -** obscure platforms. For those cases, simply compile with one of -** the following: -** -** -DHAVE_GETHOSTUUID=0 -** -DHAVE_GETHOSTUUID=1 -** -** None if this matters except when building on Apple products with -** -DSQLITE_ENABLE_LOCKING_STYLE. -*/ -#ifndef HAVE_GETHOSTUUID -# define HAVE_GETHOSTUUID 0 -# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ - (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) -# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ - && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\ - && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0)) -# undef HAVE_GETHOSTUUID -# define HAVE_GETHOSTUUID 1 -# else -# warning "gethostuuid() is disabled." -# endif +#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ + (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) +# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ + && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) +# define HAVE_GETHOSTUUID 1 +# else +# warning "gethostuuid() is disabled." # endif #endif #if OS_VXWORKS @@ -38736,14 +30329,16 @@ ** Allowed values of unixFile.fsFlags */ #define SQLITE_FSFLAGS_IS_MSDOS 0x1 /* -** If we are to be thread-safe, include the pthreads header. +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. */ #if SQLITE_THREADSAFE /* # include */ +# define SQLITE_UNIX_THREADS 1 #endif /* ** Default permissions when creating a new file */ @@ -38766,53 +30361,16 @@ /* ** Maximum supported symbolic links */ #define SQLITE_MAX_SYMLINKS 100 -/* -** Remove and stub certain info for WASI (WebAssembly System -** Interface) builds. -*/ -#ifdef SQLITE_WASI -# undef HAVE_FCHMOD -# undef HAVE_FCHOWN -# undef HAVE_MREMAP -# define HAVE_MREMAP 0 -# ifndef SQLITE_DEFAULT_UNIX_VFS -# define SQLITE_DEFAULT_UNIX_VFS "unix-dotfile" - /* ^^^ should SQLITE_DEFAULT_UNIX_VFS be "unix-none"? */ -# endif -# ifndef F_RDLCK -# define F_RDLCK 0 -# define F_WRLCK 1 -# define F_UNLCK 2 -# if __LONG_MAX == 0x7fffffffL -# define F_GETLK 12 -# define F_SETLK 13 -# define F_SETLKW 14 -# else -# define F_GETLK 5 -# define F_SETLK 6 -# define F_SETLKW 7 -# endif -# endif -#else /* !SQLITE_WASI */ -# ifndef HAVE_FCHMOD -# define HAVE_FCHMOD 1 -# endif -#endif /* SQLITE_WASI */ - -#ifdef SQLITE_WASI -# define osGetpid(X) (pid_t)1 -#else /* Always cast the getpid() return type for compatibility with ** kernel modules in VxWorks. */ -# define osGetpid(X) (pid_t)getpid() -#endif +#define osGetpid(X) (pid_t)getpid() /* -** Only set the lastErrno if the error code is a real error and not +** Only set the lastErrno if the error code is a real error and not ** a normal expected return code of SQLITE_BUSY or SQLITE_OK */ #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) /* Forward references */ @@ -38845,11 +30403,11 @@ int h; /* The file descriptor */ unsigned char eFileLock; /* The type of lock held on this fd */ 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 *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */ + UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ #if SQLITE_MAX_MMAP_SIZE>0 int nFetchOut; /* Number of outstanding xFetch refs */ @@ -38856,40 +30414,39 @@ sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ 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 #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - unsigned iBusyTimeout; /* Wait this many millisec on locks */ -#endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif #ifdef SQLITE_DEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated ** whenever any part of the database changes. An assertion fault will ** occur if a file is updated without also updating the transaction ** counter. This test is made to avoid new problems similar to the - ** one described by ticket #3584. + ** one described by ticket #3584. */ unsigned char transCntrChng; /* True if the transaction counter changed */ unsigned char dbUpdate; /* True if any part of database file changed */ unsigned char inNormalWrite; /* True if in a normal write operation */ #endif #ifdef SQLITE_TEST - /* In test mode, increase the size of this structure a bit so that + /* In test mode, increase the size of this structure a bit so that ** it is larger than the struct CrashFile defined in test6.c. */ char aPadding[32]; #endif }; @@ -38904,11 +30461,11 @@ ** Allowed values for the unixFile.ctrlFlags bitmask: */ #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ #define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ -#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX) +#ifndef SQLITE_DISABLE_DIRSYNC # define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */ #else # define UNIXFILE_DIRSYNC 0x00 #endif #define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ @@ -38917,11 +30474,209 @@ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ /* ** Include code that is common to all os_*.c files */ -/* #include "os_common.h" */ +/************** Include os_common.h in the middle of os_unix.c ***************/ +/************** Begin file os_common.h ***************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of os_common.h ****************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(SQLITE_HWTIME_H) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in os_common.h ******************/ + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#if defined(SQLITE_TEST) +SQLITE_API extern int sqlite3_io_error_hit; +SQLITE_API extern int sqlite3_io_error_hardhit; +SQLITE_API extern int sqlite3_io_error_pending; +SQLITE_API extern int sqlite3_io_error_persist; +SQLITE_API extern int sqlite3_io_error_benign; +SQLITE_API extern int sqlite3_diskfull_pending; +SQLITE_API extern int sqlite3_diskfull; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif /* defined(SQLITE_TEST) */ + +/* +** When testing, keep a count of the number of open files. +*/ +#if defined(SQLITE_TEST) +SQLITE_API extern int sqlite3_open_file_count; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif /* defined(SQLITE_TEST) */ + +#endif /* !defined(_OS_COMMON_H_) */ + +/************** End of os_common.h *******************************************/ +/************** Continuing where we left off in os_unix.c ********************/ /* ** Define various macros that are missing from some systems. */ #ifndef O_LARGEFILE @@ -38964,24 +30719,10 @@ ** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined. */ #ifdef __ANDROID__ # 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,...). ** The difference is important when using a pointer to the function. @@ -39030,11 +30771,11 @@ ** DJGPP. But it is DOS - what did you expect? */ #ifdef __DJGPP__ { "fstat", 0, 0 }, #define osFstat(a,b,c) 0 -#else +#else { "fstat", (sqlite3_syscall_ptr)fstat, 0 }, #define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent) #endif { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 }, @@ -39077,15 +30818,11 @@ { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\ aSyscall[13].pCurrent) -#if defined(HAVE_FCHMOD) { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, -#else - { "fchmod", (sqlite3_syscall_ptr)0, 0 }, -#endif #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else @@ -39110,32 +30847,26 @@ #else { "fchown", (sqlite3_syscall_ptr)0, 0 }, #endif #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) -#if defined(HAVE_FCHOWN) { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, -#else - { "geteuid", (sqlite3_syscall_ptr)0, 0 }, -#endif #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ - && !defined(SQLITE_WASI) +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, #else { "mmap", (sqlite3_syscall_ptr)0, 0 }, #endif #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent) -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ - && !defined(SQLITE_WASI) +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, #else { "munmap", (sqlite3_syscall_ptr)0, 0 }, #endif -#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent) +#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent) #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, #else { "mremap", (sqlite3_syscall_ptr)0, 0 }, @@ -39161,22 +30892,10 @@ #else { "lstat", (sqlite3_syscall_ptr)0, 0 }, #endif #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) -#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) -# ifdef __ANDROID__ - { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 }, -#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) -# else - { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, -#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent) -# endif -#else - { "ioctl", (sqlite3_syscall_ptr)0, 0 }, -#endif - }; /* End of the overrideable system calls */ /* ** On some systems, calls to fchown() will trigger a message in a security @@ -39191,11 +30910,11 @@ #endif } /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "unix" VFSes. Return SQLITE_OK upon successfully updating the +** "unix" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. */ static int unixSetSystemCall( sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ @@ -39274,11 +30993,11 @@ return 0; } /* ** Do not accept any file descriptor less than this value, in order to avoid -** opening database file using file descriptors that are commonly used for +** opening database file using file descriptors that are commonly used for ** standard input, output, and error. */ #ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR # define SQLITE_MINIMUM_FILE_DESCRIPTOR 3 #endif @@ -39312,25 +31031,22 @@ if( fd<0 ){ if( errno==EINTR ) continue; break; } if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break; - if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){ - (void)osUnlink(z); - } osClose(fd); - sqlite3_log(SQLITE_WARNING, + sqlite3_log(SQLITE_WARNING, "attempt to open \"%s\" as file descriptor %d", z, fd); fd = -1; - if( osOpen("/dev/null", O_RDONLY, m)<0 ) break; + if( osOpen("/dev/null", f, m)<0 ) break; } if( fd>=0 ){ if( m!=0 ){ struct stat statbuf; - if( osFstat(fd, &statbuf)==0 + if( osFstat(fd, &statbuf)==0 && statbuf.st_size==0 - && (statbuf.st_mode&0777)!=m + && (statbuf.st_mode&0777)!=m ){ osFchmod(fd, m); } } #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) @@ -39341,44 +31057,30 @@ } /* ** Helper functions to obtain and relinquish the global mutex. The ** global mutex is used to protect the unixInodeInfo and -** vxworksFileId objects used by this file, all of which may be +** vxworksFileId objects used by this file, all of which may be ** shared by multiple threads. ** -** Function unixMutexHeld() is used to assert() that the global mutex -** is held when required. This function is only used as part of assert() +** Function unixMutexHeld() is used to assert() that the global mutex +** is held when required. This function is only used as part of assert() ** statements. e.g. ** ** unixEnterMutex() ** assert( unixMutexHeld() ); ** unixEnterLeave() -** -** To prevent deadlock, the global unixBigLock must must be acquired -** before the unixInodeInfo.pLockMutex mutex, if both are held. It is -** OK to get the pLockMutex without holding unixBigLock first, but if -** that happens, the unixBigLock mutex must not be acquired until after -** pLockMutex is released. -** -** OK: enter(unixBigLock), enter(pLockInfo) -** OK: enter(unixBigLock) -** OK: enter(pLockInfo) -** ERROR: enter(pLockInfo), enter(unixBigLock) */ -static sqlite3_mutex *unixBigLock = 0; static void unixEnterMutex(void){ - assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */ - sqlite3_mutex_enter(unixBigLock); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); } static void unixLeaveMutex(void){ - assert( sqlite3_mutex_held(unixBigLock) ); - sqlite3_mutex_leave(unixBigLock); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); } #ifdef SQLITE_DEBUG static int unixMutexHeld(void) { - return sqlite3_mutex_held(unixBigLock); + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); } #endif #ifdef SQLITE_HAVE_OS_TRACE @@ -39467,11 +31169,11 @@ ** could lead to a corrupt database. */ static int robust_ftruncate(int h, sqlite3_int64 sz){ int rc; #ifdef __ANDROID__ - /* On Android, ftruncate() always uses 32-bit offsets, even if + /* On Android, ftruncate() always uses 32-bit offsets, even if ** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to ** truncate a file to any size larger than 2GiB. Silently ignore any ** such attempts. */ if( sz>(sqlite3_int64)0x7FFFFFFF ){ rc = SQLITE_OK; @@ -39483,36 +31185,36 @@ /* ** This routine translates a standard POSIX errno code into something ** useful to the clients of the sqlite3 functions. Specifically, it is ** intended to translate a variety of "try again" errors into SQLITE_BUSY -** and a variety of "please close the file descriptor NOW" errors into +** and a variety of "please close the file descriptor NOW" errors into ** SQLITE_IOERR -** +** ** Errors during initialization of locks, or file system support for locks, ** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately. */ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) { - assert( (sqliteIOErr == SQLITE_IOERR_LOCK) || - (sqliteIOErr == SQLITE_IOERR_UNLOCK) || + assert( (sqliteIOErr == SQLITE_IOERR_LOCK) || + (sqliteIOErr == SQLITE_IOERR_UNLOCK) || (sqliteIOErr == SQLITE_IOERR_RDLOCK) || (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ); switch (posixError) { - case EACCES: + case EACCES: case EAGAIN: case ETIMEDOUT: case EBUSY: case EINTR: - case ENOLCK: - /* random NFS retry error, unless during file system support + case ENOLCK: + /* random NFS retry error, unless during file system support * introspection, in which it actually means what it says */ return SQLITE_BUSY; - - case EPERM: + + case EPERM: return SQLITE_PERM; - - default: + + default: return sqliteIOErr; } } @@ -39523,11 +31225,11 @@ ** the device number and the inode number. But this does not work on VxWorks. ** On VxWorks, a unique file id must be based on the canonical filename. ** ** A pointer to an instance of the following structure can be used as a ** unique file ID in VxWorks. Each instance of this structure contains -** a copy of the canonical filename. There is also a reference count. +** a copy of the canonical filename. There is also a reference count. ** The structure is reclaimed when the number of pointers to it drops to ** zero. ** ** There are never very many files open at one time and lookups are not ** a performance-critical path, so it is sufficient to put these @@ -39539,11 +31241,11 @@ int nName; /* Length of the zCanonicalName[] string */ char *zCanonicalName; /* Canonical filename */ }; #if OS_VXWORKS -/* +/* ** All unique filenames are held on a linked list headed by this ** variable: */ static struct vxworksFileId *vxworksFileList = 0; @@ -39611,11 +31313,11 @@ ** If found, increment the reference count and return a pointer to ** the existing file ID. */ unixEnterMutex(); for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ - if( pCandidate->nName==n + if( pCandidate->nName==n && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 ){ sqlite3_free(pNew); pCandidate->nRef++; unixLeaveMutex(); @@ -39704,20 +31406,20 @@ ** field that tells us its internal lock status. cnt==0 means the ** file is unlocked. cnt==-1 means the file has an exclusive lock. ** cnt>0 means there are cnt shared locks on the file. ** ** Any attempt to lock or unlock a file first checks the locking -** structure. The fcntl() system call is only invoked to set a +** structure. The fcntl() system call is only invoked to set a ** POSIX lock if the internal lock structure transitions between ** a locked and an unlocked state. ** ** But wait: there are yet more problems with POSIX advisory locks. ** ** If you close a file descriptor that points to a file that has locks, ** all locks on that file that are owned by the current process are ** released. To work around this problem, each unixInodeInfo object -** maintains a count of the number of pending locks on the inode. +** maintains a count of the number of pending locks on tha inode. ** When an attempt is made to close an unixFile, if there are ** other unixFile open on the same inode that are holding locks, the call ** to close() the file descriptor is deferred until all of the locks clear. ** The unixInodeInfo structure keeps a list of file descriptors that need to ** be closed and that list is walked (and cleared) when the last lock @@ -39727,21 +31429,21 @@ ** ** Many older versions of linux use the LinuxThreads library which is ** not posix compliant. Under LinuxThreads, a lock created by thread ** A cannot be modified or overridden by a different thread B. ** Only thread A can modify the lock. Locking behavior is correct -** if the application uses the newer Native Posix Thread Library (NPTL) +** if the appliation uses the newer Native Posix Thread Library (NPTL) ** on linux - with NPTL a lock created by thread A can override locks ** in thread B. But there is no way to know at compile-time which ** threading library is being used. So there is no way to know at ** compile-time whether or not thread A can override locks on thread B. ** One has to do a run-time check to discover the behavior of the ** current process. ** ** SQLite used to support LinuxThreads. But support for LinuxThreads ** was dropped beginning with version 3.7.0. SQLite will still work with -** LinuxThreads provided that (1) there is no more than one connection +** LinuxThreads provided that (1) there is no more than one connection ** per database file in the same process and (2) database connections ** do not move across threads. */ /* @@ -39754,53 +31456,36 @@ struct vxworksFileId *pId; /* Unique file ID for vxworks. */ #else /* We are told that some versions of Android contain a bug that ** sizes ino_t at only 32-bits instead of 64-bits. (See ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c) - ** To work around this, always allocate 64-bits for the inode number. + ** To work around this, always allocate 64-bits for the inode number. ** On small machines that only have 32-bit inodes, this wastes 4 bytes, ** but that should not be a big deal. */ /* WAS: ino_t ino; */ u64 ino; /* Inode number */ #endif }; /* ** An instance of the following structure is allocated for each open -** inode. +** inode. Or, on LinuxThreads, there is one of these structures for +** each inode opened by each thread. ** ** A single inode can have multiple file descriptors, so each unixFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of unixFile pointing to it. -** -** Mutex rules: -** -** (1) Only the pLockMutex mutex must be held in order to read or write -** any of the locking fields: -** nShared, nLock, eFileLock, bProcessLock, pUnused -** -** (2) When nRef>0, then the following fields are unchanging and can -** be read (but not written) without holding any mutex: -** fileId, pLockMutex -** -** (3) With the exceptions above, all the fields may only be read -** or written while holding the global unixBigLock mutex. -** -** Deadlock prevention: The global unixBigLock mutex may not -** be acquired while holding the pLockMutex mutex. If both unixBigLock -** and pLockMutex are needed, then unixBigLock must be acquired first. */ struct unixInodeInfo { struct unixFileId fileId; /* The lookup key */ - sqlite3_mutex *pLockMutex; /* Hold this mutex for... */ - int nShared; /* Number of SHARED locks held */ - int nLock; /* Number of outstanding file locks */ - unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ - unsigned char bProcessLock; /* An exclusive process lock is held */ - UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + int nShared; /* Number of SHARED locks held */ + unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + unsigned char bProcessLock; /* An exclusive process lock is held */ int nRef; /* Number of pointers to this structure */ unixShmNode *pShmNode; /* Shared memory associated with this inode */ + int nLock; /* Number of outstanding file locks */ + UnixUnusedFd *pUnused; /* Unused file descriptors to close */ unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ unixInodeInfo *pPrev; /* .... doubly linked */ #if SQLITE_ENABLE_LOCKING_STYLE unsigned long long sharedByte; /* for AFP simulated shared lock */ #endif @@ -39810,30 +31495,12 @@ #endif }; /* ** A lists of all unixInodeInfo objects. -** -** Must hold unixBigLock in order to read or write this variable. -*/ -static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ - -#ifdef SQLITE_DEBUG -/* -** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not. -** This routine is used only within assert() to help verify correct mutex -** usage. -*/ -int unixFileMutexHeld(unixFile *pFile){ - assert( pFile->pInode ); - return sqlite3_mutex_held(pFile->pInode->pLockMutex); -} -int unixFileMutexNotheld(unixFile *pFile){ - assert( pFile->pInode ); - return sqlite3_mutex_notheld(pFile->pInode->pLockMutex); -} -#endif +*/ +static unixInodeInfo *inodeList = 0; /* ** ** This function - unixLogErrorAtLine(), is only ever called via the macro ** unixLogError(). @@ -39842,11 +31509,11 @@ ** set. It logs a message using sqlite3_log() containing the current value of ** errno and, if possible, the human-readable equivalent from strerror() or ** strerror_r(). ** ** The first argument passed to the macro should be the error code that -** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). +** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). ** The two subsequent arguments should be the name of the OS function that ** failed (e.g. "unlink", "open") and the associated file-system path, ** if any. */ #define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__) @@ -39860,34 +31527,30 @@ int iErrno = errno; /* Saved syscall error number */ /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use ** the strerror() function to obtain the human-readable error message ** equivalent to errno. Otherwise, use strerror_r(). - */ + */ #if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R) char aErr[80]; memset(aErr, 0, sizeof(aErr)); zErr = aErr; /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined, ** assume that the system provides the GNU version of strerror_r() that - ** returns a pointer to a buffer containing the error message. That pointer - ** may point to aErr[], or it may point to some static storage somewhere. - ** Otherwise, assume that the system provides the POSIX version of + ** returns a pointer to a buffer containing the error message. That pointer + ** may point to aErr[], or it may point to some static storage somewhere. + ** Otherwise, assume that the system provides the POSIX version of ** strerror_r(), which always writes an error message into aErr[]. ** ** If the code incorrectly assumes that it is the POSIX version that is ** available, the error message will often be an empty string. Not a - ** huge problem. Incorrectly concluding that the GNU version is available + ** huge problem. Incorrectly concluding that the GNU version is available ** could lead to a segfault though. - ** - ** Forum post 3f13857fa4062301 reports that the Android SDK may use - ** int-type return, depending on its version. */ -#if (defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)) \ - && !defined(ANDROID) && !defined(__ANDROID__) - zErr = +#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU) + zErr = # endif strerror_r(iErrno, aErr, sizeof(aErr)-1); #elif SQLITE_THREADSAFE /* This is a threadsafe build, but strerror_r() is not available. */ @@ -39933,17 +31596,16 @@ static void storeLastErrno(unixFile *pFile, int error){ pFile->lastErrno = error; } /* -** Close all file descriptors accumulated in the unixInodeInfo->pUnused list. -*/ +** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. +*/ static void closePendingFds(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; UnixUnusedFd *p; UnixUnusedFd *pNext; - assert( unixFileMutexHeld(pFile) ); for(p=pInode->pUnused; p; p=pNext){ pNext = p->pNext; robust_close(pFile, p->fd, __LINE__); sqlite3_free(p); } @@ -39951,24 +31613,21 @@ } /* ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). ** -** The global mutex must be held when this routine is called, but the mutex -** on the inode being deleted must NOT be held. +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. */ static void releaseInodeInfo(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; assert( unixMutexHeld() ); - assert( unixFileMutexNotheld(pFile) ); if( ALWAYS(pInode) ){ pInode->nRef--; if( pInode->nRef==0 ){ assert( pInode->pShmNode==0 ); - sqlite3_mutex_enter(pInode->pLockMutex); closePendingFds(pFile); - sqlite3_mutex_leave(pInode->pLockMutex); if( pInode->pPrev ){ assert( pInode->pPrev->pNext==pInode ); pInode->pPrev->pNext = pInode->pNext; }else{ assert( inodeList==pInode ); @@ -39976,11 +31635,10 @@ } if( pInode->pNext ){ assert( pInode->pNext->pPrev==pInode ); pInode->pNext->pPrev = pInode->pPrev; } - sqlite3_mutex_free(pInode->pLockMutex); sqlite3_free(pInode); } } } @@ -39987,11 +31645,12 @@ /* ** Given a file descriptor, locate the unixInodeInfo object that ** describes that file descriptor. Create a new one if necessary. The ** return value might be uninitialized if an error occurs. ** -** The global mutex must held when calling this routine. +** The mutex entered using the unixEnterMutex() function must be held +** when this function is called. ** ** Return an appropriate error code. */ static int findInodeInfo( unixFile *pFile, /* Unix file with file desc used in the key */ @@ -40048,11 +31707,10 @@ #if OS_VXWORKS fileId.pId = pFile->pId; #else fileId.ino = (u64)statbuf.st_ino; #endif - assert( unixMutexHeld() ); pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ pInode = pInode->pNext; } if( pInode==0 ){ @@ -40060,19 +31718,11 @@ if( pInode==0 ){ return SQLITE_NOMEM_BKPT; } memset(pInode, 0, sizeof(*pInode)); memcpy(&pInode->fileId, &fileId, sizeof(fileId)); - if( sqlite3GlobalConfig.bCoreMutex ){ - pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pInode->pLockMutex==0 ){ - sqlite3_free(pInode); - return SQLITE_NOMEM_BKPT; - } - } pInode->nRef = 1; - assert( unixMutexHeld() ); pInode->pNext = inodeList; pInode->pPrev = 0; if( inodeList ) inodeList->pPrev = pInode; inodeList = pInode; }else{ @@ -40089,11 +31739,11 @@ #if OS_VXWORKS return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId; #else struct stat buf; return pFile->pInode!=0 && - (osStat(pFile->zPath, &buf)!=0 + (osStat(pFile->zPath, &buf)!=0 || (u64)buf.st_ino!=pFile->pInode->fileId.ino); #endif } @@ -40146,11 +31796,11 @@ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( pFile ); assert( pFile->eFileLock<=SHARED_LOCK ); - sqlite3_mutex_enter(pFile->pInode->pLockMutex); + unixEnterMutex(); /* Because pFile->pInode is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pInode->eFileLock>SHARED_LOCK ){ reserved = 1; } @@ -40170,61 +31820,20 @@ } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } } #endif - - sqlite3_mutex_leave(pFile->pInode->pLockMutex); + + unixLeaveMutex(); OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); *pResOut = reserved; return rc; } -/* Forward declaration*/ -static int unixSleep(sqlite3_vfs*,int); - -/* -** Set a posix-advisory-lock. -** -** There are two versions of this routine. If compiled with -** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter -** which is a pointer to a unixFile. If the unixFile->iBusyTimeout -** value is set, then it is the number of milliseconds to wait before -** failing the lock. The iBusyTimeout value is always reset back to -** zero on each call. -** -** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking -** attempt to set the lock. -*/ -#ifndef SQLITE_ENABLE_SETLK_TIMEOUT -# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x) -#else -static int osSetPosixAdvisoryLock( - int h, /* The file descriptor on which to take the lock */ - struct flock *pLock, /* The description of the lock */ - unixFile *pFile /* Structure holding timeout value */ -){ - int tm = pFile->iBusyTimeout; - int rc = osFcntl(h,F_SETLK,pLock); - while( rc<0 && tm>0 ){ - /* On systems that support some kind of blocking file lock with a timeout, - ** make appropriate changes here to invoke that blocking file lock. On - ** generic posix, however, there is no such API. So we simply try the - ** lock once every millisecond until either the timeout expires, or until - ** the lock is obtained. */ - unixSleep(0,1000); - rc = osFcntl(h,F_SETLK,pLock); - tm--; - } - return rc; -} -#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ - - -/* -** Attempt to set a system-lock on the file pFile. The lock is +/* +** Attempt to set a system-lock on the file pFile. The lock is ** described by pLock. ** ** If the pFile was opened read/write from unix-excl, then the only lock ** ever obtained is an exclusive lock, and it is obtained exactly once ** the first time any lock is attempted. All subsequent system locking @@ -40241,29 +31850,29 @@ ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()). */ static int unixFileLock(unixFile *pFile, struct flock *pLock){ int rc; unixInodeInfo *pInode = pFile->pInode; + assert( unixMutexHeld() ); assert( pInode!=0 ); - assert( sqlite3_mutex_held(pInode->pLockMutex) ); if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ if( pInode->bProcessLock==0 ){ struct flock lock; - /* assert( pInode->nLock==0 ); <-- Not true if unix-excl READONLY used */ + assert( pInode->nLock==0 ); lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; - rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); + rc = osFcntl(pFile->h, F_SETLK, &lock); if( rc<0 ) return rc; pInode->bProcessLock = 1; pInode->nLock++; }else{ rc = 0; } }else{ - rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); + rc = osFcntl(pFile->h, F_SETLK, pLock); } return rc; } /* @@ -40281,11 +31890,11 @@ ** still short of its goal. The following chart shows the allowed ** transitions and the inserted intermediate states: ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED -** SHARED -> EXCLUSIVE +** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. @@ -40296,42 +31905,41 @@ ** lock primitives (called read-locks and write-locks below, to avoid ** confusion with SQLite lock names). The algorithms are complicated ** slightly in order to be compatible with Windows95 systems simultaneously ** accessing the same database file, in case that is ever required. ** - ** Symbols defined in os.h identify the 'pending byte' and the 'reserved + ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved ** byte', each single bytes at well known offsets, and the 'shared byte ** range', a range of 510 bytes at a well known offset. ** ** To obtain a SHARED lock, a read-lock is obtained on the 'pending ** byte'. If this is successful, 'shared byte range' is read-locked ** and the lock on the 'pending byte' released. (Legacy note: When ** SQLite was first developed, Windows95 systems were still very common, - ** and Windows95 lacks a shared-lock capability. So on Windows95, a + ** and Widnows95 lacks a shared-lock capability. So on Windows95, a ** single randomly selected by from the 'shared byte range' is locked. ** Windows95 is now pretty much extinct, but this work-around for the ** lack of shared-locks on Windows95 lives on, for backwards ** compatibility.) ** ** A process may only obtain a RESERVED lock after it has a SHARED lock. ** A RESERVED lock is implemented by grabbing a write-lock on the - ** 'reserved byte'. - ** - ** An EXCLUSIVE lock may only be requested after either a SHARED or - ** RESERVED lock is held. An EXCLUSIVE lock is implemented by obtaining - ** a write-lock on the entire 'shared byte range'. Since all other locks - ** require a read-lock on one of the bytes within this range, this ensures - ** that no other locks are held on the database. - ** - ** If a process that holds a RESERVED lock requests an EXCLUSIVE, then - ** a PENDING lock is obtained first. A PENDING lock is implemented by - ** obtaining a write-lock on the 'pending byte'. This ensures that no new - ** SHARED locks can be obtained, but existing SHARED locks are allowed to - ** persist. If the call to this function fails to obtain the EXCLUSIVE - ** lock in this case, it holds the PENDING lock instead. The client may - ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED - ** locks have cleared. + ** 'reserved byte'. + ** + ** A process may only obtain a PENDING lock after it has obtained a + ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock + ** on the 'pending byte'. This ensures that no new SHARED locks can be + ** obtained, but existing SHARED locks are allowed to persist. A process + ** does not have to obtain a RESERVED lock on the way to a PENDING lock. + ** This property is used by the algorithm for rolling back a journal file + ** after a crash. + ** + ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is + ** implemented by obtaining a write-lock on the entire 'shared byte + ** range'. Since all other locks require a read-lock on one of the bytes + ** within this range, this ensures that no other locks are held on the + ** database. */ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; unixInodeInfo *pInode; struct flock lock; @@ -40353,26 +31961,26 @@ return SQLITE_OK; } /* Make sure the locking sequence is correct. ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pending lock. + ** (2) SQLite never explicitly requests a pendig lock. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); assert( eFileLock!=PENDING_LOCK ); assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK ); /* This mutex is needed because pFile->pInode is shared across threads */ + unixEnterMutex(); pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); /* If some thread using this PID has a lock via a different unixFile* ** handle that precludes the requested lock, return BUSY. */ - if( (pFile->eFileLock!=pInode->eFileLock && + if( (pFile->eFileLock!=pInode->eFileLock && (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) ){ rc = SQLITE_BUSY; goto end_lock; } @@ -40379,11 +31987,11 @@ /* If a SHARED lock is requested, and some thread using this PID already ** has a SHARED or RESERVED lock, then increment reference counts and ** return SQLITE_OK. */ - if( eFileLock==SHARED_LOCK && + if( eFileLock==SHARED_LOCK && (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){ assert( eFileLock==SHARED_LOCK ); assert( pFile->eFileLock==0 ); assert( pInode->nShared>0 ); pFile->eFileLock = SHARED_LOCK; @@ -40397,12 +32005,12 @@ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ lock.l_len = 1L; lock.l_whence = SEEK_SET; - if( eFileLock==SHARED_LOCK - || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock==RESERVED_LOCK) + if( eFileLock==SHARED_LOCK + || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLockeFileLock = PENDING_LOCK; - pInode->eFileLock = PENDING_LOCK; } } /* If control gets to this point, then actually go ahead and make @@ -40439,11 +32044,11 @@ lock.l_len = 1L; lock.l_type = F_UNLCK; if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){ /* This could happen with a network mount */ tErrno = errno; - rc = SQLITE_IOERR_UNLOCK; + rc = SQLITE_IOERR_UNLOCK; } if( rc ){ if( rc!=SQLITE_BUSY ){ storeLastErrno(pFile, tErrno); @@ -40481,11 +32086,11 @@ if( rc!=SQLITE_BUSY ){ storeLastErrno(pFile, tErrno); } } } - + #ifdef SQLITE_DEBUG /* Set up the transaction-counter change checking flags when ** transitioning from a SHARED to a RESERVED lock. The change ** from SHARED to RESERVED marks the beginning of a normal @@ -40498,19 +32103,23 @@ pFile->transCntrChng = 0; pFile->dbUpdate = 0; pFile->inNormalWrite = 1; } #endif + if( rc==SQLITE_OK ){ pFile->eFileLock = eFileLock; pInode->eFileLock = eFileLock; + }else if( eFileLock==EXCLUSIVE_LOCK ){ + pFile->eFileLock = PENDING_LOCK; + pInode->eFileLock = PENDING_LOCK; } end_lock: - sqlite3_mutex_leave(pInode->pLockMutex); - OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), + unixLeaveMutex(); + OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), rc==SQLITE_OK ? "ok" : "failed")); return rc; } /* @@ -40517,29 +32126,28 @@ ** Add the file descriptor used by file handle pFile to the corresponding ** pUnused list. */ static void setPendingFd(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; - UnixUnusedFd *p = pFile->pPreallocatedUnused; - assert( unixFileMutexHeld(pFile) ); + UnixUnusedFd *p = pFile->pUnused; p->pNext = pInode->pUnused; pInode->pUnused = p; pFile->h = -1; - pFile->pPreallocatedUnused = 0; + pFile->pUnused = 0; } /* ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. -** +** ** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED ** the byte range is divided into 2 parts and the first part is unlocked then -** set to a read lock, then the other part is simply unlocked. This works -** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to +** set to a read lock, then the other part is simply unlocked. This works +** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to ** remove the write lock on a region when a read lock is set. */ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ unixFile *pFile = (unixFile*)id; unixInodeInfo *pInode; @@ -40553,12 +32161,12 @@ assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ return SQLITE_OK; } + unixEnterMutex(); pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); #ifdef SQLITE_DEBUG @@ -40573,11 +32181,11 @@ pFile->inNormalWrite = 0; #endif /* downgrading to a shared lock on NFS involves clearing the write lock ** before establishing the readlock - to avoid a race condition we downgrade - ** the lock in 2 blocks, so that part of the range will be covered by a + ** the lock in 2 blocks, so that part of the range will be covered by a ** write lock until the rest is covered by a read lock: ** 1: [WWWWW] ** 2: [....W] ** 3: [RRRRW] ** 4: [RRRR.] @@ -40589,11 +32197,11 @@ #endif #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE if( handleNFSUnlock ){ int tErrno; /* Error code from system call errors */ off_t divSize = SHARED_SIZE - 1; - + lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; if( unixFileLock(pFile, &lock)==(-1) ){ @@ -40631,15 +32239,15 @@ lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; if( unixFileLock(pFile, &lock) ){ /* In theory, the call to unixFileLock() cannot fail because another - ** process is holding an incompatible lock. If it does, this + ** process is holding an incompatible lock. If it does, this ** indicates that the other process is not following the locking ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning - ** SQLITE_BUSY would confuse the upper layer (in practice it causes - ** an assert to fail). */ + ** SQLITE_BUSY would confuse the upper layer (in practice it causes + ** an assert to fail). */ rc = SQLITE_IOERR_RDLOCK; storeLastErrno(pFile, errno); goto end_unlock; } } @@ -40680,18 +32288,18 @@ ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ pInode->nLock--; assert( pInode->nLock>=0 ); - if( pInode->nLock==0 ) closePendingFds(pFile); + if( pInode->nLock==0 ){ + closePendingFds(pFile); + } } end_unlock: - sqlite3_mutex_leave(pInode->pLockMutex); - if( rc==SQLITE_OK ){ - pFile->eFileLock = eFileLock; - } + unixLeaveMutex(); + if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; return rc; } /* ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock @@ -40711,11 +32319,11 @@ static int unixMapfile(unixFile *pFd, i64 nByte); static void unixUnmapfile(unixFile *pFd); #endif /* -** This function performs the parts of the "close file" operation +** This function performs the parts of the "close file" operation ** common to all locking schemes. It closes the directory and file ** handles, if they are valid, and sets all fields of the unixFile ** structure to 0. ** ** It is *not* necessary to hold the mutex when this routine is called, @@ -40747,11 +32355,11 @@ pFile->zPath = 0; } #endif OSTRACE(("CLOSE %-3d\n", pFile->h)); OpenCounter(-1); - sqlite3_free(pFile->pPreallocatedUnused); + sqlite3_free(pFile->pUnused); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } /* @@ -40758,34 +32366,27 @@ ** Close a file. */ static int unixClose(sqlite3_file *id){ int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; - unixInodeInfo *pInode = pFile->pInode; - - assert( pInode!=0 ); verifyDbFile(pFile); unixUnlock(id, NO_LOCK); - assert( unixFileMutexNotheld(pFile) ); unixEnterMutex(); /* unixFile.pInode is always valid here. Otherwise, a different close ** routine (e.g. nolockClose()) would be called instead. */ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); - sqlite3_mutex_enter(pInode->pLockMutex); - if( pInode->nLock ){ + if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->pUnused list. It will be automatically closed + ** descriptor to pInode->pUnused list. It will be automatically closed ** when the last lock is cleared. */ setPendingFd(pFile); } - sqlite3_mutex_leave(pInode->pLockMutex); releaseInodeInfo(pFile); - assert( pFile->pShm==0 ); rc = closeUnixFile(id); unixLeaveMutex(); return rc; } @@ -40861,26 +32462,30 @@ */ #define DOTLOCK_SUFFIX ".lock" /* ** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If the caller holds a SHARED -** or greater lock when it is called, then it is assumed that no other -** client may hold RESERVED. Or, if the caller holds no lock, then it -** is assumed another client holds RESERVED if the lock-file exists. +** file by this or any other process. If such a lock is held, set *pResOut +** to a non-zero value otherwise *pResOut is set to zero. The return value +** is set to SQLITE_OK unless an I/O error occurs during lock checking. +** +** In dotfile locking, either a lock exists or it does not. So in this +** variation of CheckReservedLock(), *pResOut is set to true if any lock +** is held on the file and false if the file is unlocked. */ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) { + int rc = SQLITE_OK; + int reserved = 0; unixFile *pFile = (unixFile*)id; + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - - if( pFile->eFileLock>=SHARED_LOCK ){ - *pResOut = 0; - }else{ - *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0; - } - OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut)); - return SQLITE_OK; + + assert( pFile ); + reserved = osAccess((const char*)pFile->lockingContext, 0)==0; + OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved)); + *pResOut = reserved; + return rc; } /* ** Lock the file with the lock specified by parameter eFileLock - one ** of the following: @@ -40925,11 +32530,11 @@ #else utimes(zLockFile, NULL); #endif return SQLITE_OK; } - + /* grab an exclusive lock */ rc = osMkdir(zLockFile, 0777); if( rc<0 ){ /* failed to open/create the lock directory */ int tErrno = errno; @@ -40940,12 +32545,12 @@ if( rc!=SQLITE_BUSY ){ storeLastErrno(pFile, tErrno); } } return rc; - } - + } + /* got it, set the type and return ok */ pFile->eFileLock = eFileLock; return rc; } @@ -40965,11 +32570,11 @@ assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); - + /* no-op if possible */ if( pFile->eFileLock==eFileLock ){ return SQLITE_OK; } @@ -40978,11 +32583,11 @@ */ if( eFileLock==SHARED_LOCK ){ pFile->eFileLock = SHARED_LOCK; return SQLITE_OK; } - + /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); rc = osRmdir(zLockFile); if( rc<0 ){ int tErrno = errno; @@ -40990,11 +32595,11 @@ rc = SQLITE_OK; }else{ rc = SQLITE_IOERR_UNLOCK; storeLastErrno(pFile, tErrno); } - return rc; + return rc; } pFile->eFileLock = NO_LOCK; return SQLITE_OK; } @@ -41037,46 +32642,67 @@ return rc; } #else # define robust_flock(a,b) flock(a,b) #endif - + /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ -#ifdef SQLITE_DEBUG + int rc = SQLITE_OK; + int reserved = 0; unixFile *pFile = (unixFile*)id; -#else - UNUSED_PARAMETER(id); -#endif - + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - + assert( pFile ); - assert( pFile->eFileLock<=SHARED_LOCK ); - - /* The flock VFS only ever takes exclusive locks (see function flockLock). - ** Therefore, if this connection is holding any lock at all, no other - ** connection may be holding a RESERVED lock. So set *pResOut to 0 - ** in this case. - ** - ** Or, this connection may be holding no lock. In that case, set *pResOut to - ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the - ** db in order to roll the hot journal back. If there is another connection - ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to - ** the user. With other VFS, we try to avoid this, in order to allow a reader - ** to proceed while a writer is preparing its transaction. But that won't - ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is - ** not a problem in this case. */ - *pResOut = 0; - - return SQLITE_OK; + + /* Check if a thread in this process holds such a lock */ + if( pFile->eFileLock>SHARED_LOCK ){ + reserved = 1; + } + + /* Otherwise see if some other process holds it. */ + if( !reserved ){ + /* attempt to get the lock */ + int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB); + if( !lrc ){ + /* got the lock, unlock it */ + lrc = robust_flock(pFile->h, LOCK_UN); + if ( lrc ) { + int tErrno = errno; + /* unlock failed with an error */ + lrc = SQLITE_IOERR_UNLOCK; + storeLastErrno(pFile, tErrno); + rc = lrc; + } + } else { + int tErrno = errno; + reserved = 1; + /* someone else might have it reserved */ + lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); + if( IS_LOCK_ERROR(lrc) ){ + storeLastErrno(pFile, tErrno); + rc = lrc; + } + } + } + OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved)); + +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS + if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ + rc = SQLITE_OK; + reserved=1; + } +#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ + *pResOut = reserved; + return rc; } /* ** Lock the file with the lock specified by parameter eFileLock - one ** of the following: @@ -41110,19 +32736,19 @@ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); - /* if we already have a lock, it is exclusive. + /* if we already have a lock, it is exclusive. ** Just adjust level and punt on outta here. */ if (pFile->eFileLock > NO_LOCK) { pFile->eFileLock = eFileLock; return SQLITE_OK; } - + /* grab an exclusive lock */ - + if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) { int tErrno = errno; /* didn't get, must be busy */ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ @@ -41130,14 +32756,14 @@ } } else { /* got it, set the type and return ok */ pFile->eFileLock = eFileLock; } - OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), + OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), rc==SQLITE_OK ? "ok" : "failed")); #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - if( (rc & 0xff) == SQLITE_IOERR ){ + if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ rc = SQLITE_BUSY; } #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ return rc; } @@ -41150,27 +32776,27 @@ ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int flockUnlock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; - + assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock, pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); - + /* no-op if possible */ if( pFile->eFileLock==eFileLock ){ return SQLITE_OK; } - + /* shared can just be set because we always have an exclusive */ if (eFileLock==SHARED_LOCK) { pFile->eFileLock = eFileLock; return SQLITE_OK; } - + /* no, really, unlock. */ if( robust_flock(pFile->h, LOCK_UN) ){ #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS return SQLITE_OK; #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ @@ -41217,18 +32843,18 @@ int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - + assert( pFile ); /* Check if a thread in this process holds such a lock */ if( pFile->eFileLock>SHARED_LOCK ){ reserved = 1; } - + /* Otherwise see if some other process holds it. */ if( !reserved ){ sem_t *pSem = pFile->pInode->pSem; if( sem_trywait(pSem)==-1 ){ @@ -41283,18 +32909,18 @@ static int semXLock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pInode->pSem; int rc = SQLITE_OK; - /* if we already have a lock, it is exclusive. + /* if we already have a lock, it is exclusive. ** Just adjust level and punt on outta here. */ if (pFile->eFileLock > NO_LOCK) { pFile->eFileLock = eFileLock; rc = SQLITE_OK; goto sem_end_lock; } - + /* lock semaphore now but bail out when already locked. */ if( sem_trywait(pSem)==-1 ){ rc = SQLITE_BUSY; goto sem_end_lock; } @@ -41320,30 +32946,30 @@ assert( pFile ); assert( pSem ); OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); - + /* no-op if possible */ if( pFile->eFileLock==eFileLock ){ return SQLITE_OK; } - + /* shared can just be set because we always have an exclusive */ if (eFileLock==SHARED_LOCK) { pFile->eFileLock = eFileLock; return SQLITE_OK; } - + /* no, really unlock. */ if ( sem_post(pSem)==-1 ) { int rc, tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } - return rc; + return rc; } pFile->eFileLock = NO_LOCK; return SQLITE_OK; } @@ -41353,11 +32979,10 @@ static int semXClose(sqlite3_file *id) { if( id ){ unixFile *pFile = (unixFile*)id; semXUnlock(id, NO_LOCK); assert( pFile ); - assert( unixFileMutexNotheld(pFile) ); unixEnterMutex(); releaseInodeInfo(pFile); unixLeaveMutex(); closeUnixFile(id); } @@ -41405,11 +33030,11 @@ #define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) /* ** This is a utility for setting or clearing a bit-range lock on an ** AFP filesystem. -** +** ** Return SQLITE_OK on success, SQLITE_BUSY on failure. */ static int afpSetLock( const char *path, /* Name of the file to be locked or unlocked */ unixFile *pFile, /* Open file descriptor on path */ @@ -41417,18 +33042,18 @@ unsigned long long length, /* Number of bytes to lock */ int setLockFlag /* True to set lock. False to clear lock */ ){ struct ByteRangeLockPB2 pb; int err; - + pb.unLockFlag = setLockFlag ? 0 : 1; pb.startEndFlag = 0; pb.offset = offset; - pb.length = length; + pb.length = length; pb.fd = pFile->h; - - OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", + + OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""), offset, length)); err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); if ( err==-1 ) { int rc; @@ -41459,30 +33084,31 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; afpLockingContext *context; - + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - + assert( pFile ); context = (afpLockingContext *) pFile->lockingContext; if( context->reserved ){ *pResOut = 1; return SQLITE_OK; } - sqlite3_mutex_enter(pFile->pInode->pLockMutex); + unixEnterMutex(); /* Because pFile->pInode is shared across threads */ + /* Check if a thread in this process holds such a lock */ if( pFile->pInode->eFileLock>SHARED_LOCK ){ reserved = 1; } - + /* Otherwise see if some other process holds it. */ if( !reserved ){ /* lock the RESERVED byte */ - int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); + int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); if( SQLITE_OK==lrc ){ /* if we succeeded in taking the reserved lock, unlock it to restore ** the original state */ lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); } else { @@ -41491,14 +33117,14 @@ } if( IS_LOCK_ERROR(lrc) ){ rc=lrc; } } - - sqlite3_mutex_leave(pFile->pInode->pLockMutex); + + unixLeaveMutex(); OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved)); - + *pResOut = reserved; return rc; } /* @@ -41528,11 +33154,11 @@ static int afpLock(sqlite3_file *id, int eFileLock){ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; unixInodeInfo *pInode = pFile->pInode; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; - + assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0))); @@ -41546,85 +33172,85 @@ return SQLITE_OK; } /* Make sure the locking sequence is correct ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pending lock. + ** (2) SQLite never explicitly requests a pendig lock. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); assert( eFileLock!=PENDING_LOCK ); assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK ); - + /* This mutex is needed because pFile->pInode is shared across threads */ + unixEnterMutex(); pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); /* If some thread using this PID has a lock via a different unixFile* ** handle that precludes the requested lock, return BUSY. */ - if( (pFile->eFileLock!=pInode->eFileLock && + if( (pFile->eFileLock!=pInode->eFileLock && (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) ){ rc = SQLITE_BUSY; goto afp_end_lock; } - + /* If a SHARED lock is requested, and some thread using this PID already ** has a SHARED or RESERVED lock, then increment reference counts and ** return SQLITE_OK. */ - if( eFileLock==SHARED_LOCK && + if( eFileLock==SHARED_LOCK && (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){ assert( eFileLock==SHARED_LOCK ); assert( pFile->eFileLock==0 ); assert( pInode->nShared>0 ); pFile->eFileLock = SHARED_LOCK; pInode->nShared++; pInode->nLock++; goto afp_end_lock; } - + /* A PENDING lock is needed before acquiring a SHARED lock and before ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ - if( eFileLock==SHARED_LOCK + if( eFileLock==SHARED_LOCK || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLockdbPath, pFile, PENDING_BYTE, 1, 1); if (failed) { rc = failed; goto afp_end_lock; } } - + /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( eFileLock==SHARED_LOCK ){ int lrc1, lrc2, lrc1Errno = 0; long lk, mask; - + assert( pInode->nShared==0 ); assert( pInode->eFileLock==0 ); - + mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; /* Now get the read-lock SHARED_LOCK */ /* note that the quality of the randomness doesn't matter that much */ - lk = random(); + lk = random(); pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1); - lrc1 = afpSetLock(context->dbPath, pFile, + lrc1 = afpSetLock(context->dbPath, pFile, SHARED_FIRST+pInode->sharedByte, 1, 1); if( IS_LOCK_ERROR(lrc1) ){ lrc1Errno = pFile->lastErrno; } /* Drop the temporary PENDING lock */ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); - + if( IS_LOCK_ERROR(lrc1) ) { storeLastErrno(pFile, lrc1Errno); rc = lrc1; goto afp_end_lock; } else if( IS_LOCK_ERROR(lrc2) ){ @@ -41655,49 +33281,49 @@ context->reserved = 1; } } if (!failed && eFileLock == EXCLUSIVE_LOCK) { /* Acquire an EXCLUSIVE lock */ - - /* Remove the shared lock before trying the range. we'll need to + + /* Remove the shared lock before trying the range. we'll need to ** reestablish the shared lock if we can't get the afpUnlock */ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + pInode->sharedByte, 1, 0)) ){ int failed2 = SQLITE_OK; - /* now attempt to get the exclusive lock range */ - failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, + /* now attemmpt to get the exclusive lock range */ + failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 1); - if( failed && (failed2 = afpSetLock(context->dbPath, pFile, + if( failed && (failed2 = afpSetLock(context->dbPath, pFile, SHARED_FIRST + pInode->sharedByte, 1, 1)) ){ /* Can't reestablish the shared lock. Sqlite can't deal, this is ** a critical I/O error */ - rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 : + rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : SQLITE_IOERR_LOCK; goto afp_end_lock; - } + } }else{ - rc = failed; + rc = failed; } } if( failed ){ rc = failed; } } - + if( rc==SQLITE_OK ){ pFile->eFileLock = eFileLock; pInode->eFileLock = eFileLock; }else if( eFileLock==EXCLUSIVE_LOCK ){ pFile->eFileLock = PENDING_LOCK; pInode->eFileLock = PENDING_LOCK; } - + afp_end_lock: - sqlite3_mutex_leave(pInode->pLockMutex); - OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), + unixLeaveMutex(); + OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), rc==SQLITE_OK ? "ok" : "failed")); return rc; } /* @@ -41711,10 +33337,13 @@ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; unixInodeInfo *pInode; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int skipShared = 0; +#ifdef SQLITE_TEST + int h = pFile->h; +#endif assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, osGetpid(0))); @@ -41721,16 +33350,19 @@ assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ return SQLITE_OK; } + unixEnterMutex(); pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); - + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); + #ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start ** reading the database file again, make sure that the ** transaction counter was updated if any part of the database ** file changed. If the transaction counter is not updated, @@ -41741,11 +33373,11 @@ assert( pFile->inNormalWrite==0 || pFile->dbUpdate==0 || pFile->transCntrChng==1 ); pFile->inNormalWrite = 0; #endif - + if( pFile->eFileLock==EXCLUSIVE_LOCK ){ rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){ /* only re-establish the shared lock if necessary */ int sharedLockByte = SHARED_FIRST+pInode->sharedByte; @@ -41754,15 +33386,15 @@ skipShared = 1; } } if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){ rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); - } + } if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){ rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); - if( !rc ){ - context->reserved = 0; + if( !rc ){ + context->reserved = 0; } } if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){ pInode->eFileLock = SHARED_LOCK; } @@ -41774,10 +33406,13 @@ ** the lock. */ unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; pInode->nShared--; if( pInode->nShared==0 ){ + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); if( !skipShared ){ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); } if( !rc ){ pInode->eFileLock = NO_LOCK; @@ -41785,43 +33420,37 @@ } } if( rc==SQLITE_OK ){ pInode->nLock--; assert( pInode->nLock>=0 ); - if( pInode->nLock==0 ) closePendingFds(pFile); + if( pInode->nLock==0 ){ + closePendingFds(pFile); + } } } - - sqlite3_mutex_leave(pInode->pLockMutex); - if( rc==SQLITE_OK ){ - pFile->eFileLock = eFileLock; - } + + unixLeaveMutex(); + if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; return rc; } /* -** Close a file & cleanup AFP specific locking context +** Close a file & cleanup AFP specific locking context */ static int afpClose(sqlite3_file *id) { int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( id!=0 ); afpUnlock(id, NO_LOCK); - assert( unixFileMutexNotheld(pFile) ); unixEnterMutex(); - if( pFile->pInode ){ - unixInodeInfo *pInode = pFile->pInode; - sqlite3_mutex_enter(pInode->pLockMutex); - if( pInode->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->aPending. It will be automatically closed when - ** the last lock is cleared. - */ - setPendingFd(pFile); - } - sqlite3_mutex_leave(pInode->pLockMutex); + if( pFile->pInode && pFile->pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + setPendingFd(pFile); } releaseInodeInfo(pFile); sqlite3_free(pFile->lockingContext); rc = closeUnixFile(id); unixLeaveMutex(); @@ -41855,28 +33484,34 @@ #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ /* ** The code above is the NFS lock implementation. The code is specific ** to MacOSX and does not work on other unix platforms. No alternative -** is available. +** is available. ** ********************* End of the NFS lock implementation ********************** ******************************************************************************/ /****************************************************************************** **************** Non-locking sqlite3_file methods ***************************** ** -** The next division contains implementations for all methods of the +** The next division contains implementations for all methods of the ** sqlite3_file object other than the locking methods. The locking ** methods were defined in divisions above (one locking method per ** division). Those methods that are common to all locking modes ** are gather together into this division. */ /* -** Seek to the offset passed as the second argument, then read cnt +** Seek to the offset passed as the second argument, then read cnt ** bytes into pBuf. Return the number of bytes actually read. +** +** NB: If you define USE_PREAD or USE_PREAD64, then it might also +** be necessary to define _XOPEN_SOURCE to be 500. This varies from +** one system to another. Since SQLite does not define USE_PREAD +** in any form by default, we will not attempt to define _XOPEN_SOURCE. +** See tickets #2741 and #2681. ** ** To avoid stomping the errno value on a failed read the lastErrno value ** is set before returning. */ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ @@ -41927,32 +33562,32 @@ ** Read data from a file into a buffer. Return SQLITE_OK if all ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ static int unixRead( - sqlite3_file *id, - void *pBuf, + sqlite3_file *id, + void *pBuf, int amt, sqlite3_int64 offset ){ unixFile *pFile = (unixFile *)id; int got; assert( id ); assert( offset>=0 ); assert( amt>0 ); - /* If this is a database file (not a journal, super-journal or temp + /* 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->pPreallocatedUnused==0 + assert( pFile->pUnused==0 || offset>=PENDING_BYTE+512 - || offset+amt<=PENDING_BYTE + || offset+amt<=PENDING_BYTE ); #endif #if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transferring + /* Deal with as much of this read request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); return SQLITE_OK; @@ -41968,28 +33603,11 @@ got = seekAndRead(pFile, offset, pBuf, amt); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ - /* pFile->lastErrno has been set by seekAndRead(). - ** Usually we return SQLITE_IOERR_READ here, though for some - ** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The - ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT - ** prior to returning to the application by the sqlite3ApiExit() - ** routine. - */ - switch( pFile->lastErrno ){ - case ERANGE: - case EIO: -#ifdef ENXIO - case ENXIO: -#endif -#ifdef EDEVERR - case EDEVERR: -#endif - return SQLITE_IOERR_CORRUPTFS; - } + /* lastErrno set by seekAndRead */ return SQLITE_IOERR_READ; }else{ storeLastErrno(pFile, 0); /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[got], 0, amt-got); @@ -41998,11 +33616,11 @@ } /* ** Attempt to seek the file-descriptor passed as the first argument to ** absolute offset iOff, then attempt to write nBuf bytes of data from -** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, +** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, ** return the actual number of bytes written (which may be less than ** nBuf). */ static int seekAndWriteFd( int fd, /* File descriptor to write to */ @@ -42058,26 +33676,26 @@ /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ static int unixWrite( - sqlite3_file *id, - const void *pBuf, + sqlite3_file *id, + const void *pBuf, int amt, - sqlite3_int64 offset + sqlite3_int64 offset ){ unixFile *pFile = (unixFile*)id; int wrote = 0; assert( id ); assert( amt>0 ); - /* If this is a database file (not a journal, super-journal or temp + /* 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->pPreallocatedUnused==0 + assert( pFile->pUnused==0 || offset>=PENDING_BYTE+512 - || offset+amt<=PENDING_BYTE + || offset+amt<=PENDING_BYTE ); #endif #ifdef SQLITE_DEBUG /* If we are doing a normal write to a database file (as opposed to @@ -42100,11 +33718,11 @@ } } #endif #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transferring + /* Deal with as much of this write request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); return SQLITE_OK; @@ -42115,11 +33733,11 @@ amt -= nCopy; offset += nCopy; } } #endif - + while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))0 ){ amt -= wrote; offset += wrote; pBuf = &((char*)pBuf)[wrote]; } @@ -42181,12 +33799,12 @@ ** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash ** or power failure will likely corrupt the database file. ** ** SQLite sets the dataOnly flag if the size of the file is unchanged. ** The idea behind dataOnly is that it should only write the file content -** to disk, not the inode. We only set dataOnly if the file size is -** unchanged since the file size is part of the inode. However, +** to disk, not the inode. We only set dataOnly if the file size is +** unchanged since the file size is part of the inode. However, ** Ted Ts'o tells us that fdatasync() will also write the inode if the ** file size has changed. The only real difference between fdatasync() ** and fsync(), Ted tells us, is that fdatasync() will not flush the ** inode if the mtime or owner or other inode attributes have changed. ** We only care about the file size, not the other file attributes, so @@ -42196,11 +33814,11 @@ */ static int full_fsync(int fd, int fullSync, int dataOnly){ int rc; /* The following "ifdef/elif/else/" block has the same structure as - ** the one below. It is replicated here solely to avoid cluttering + ** the one below. It is replicated here solely to avoid cluttering ** up the real code with the UNUSED_PARAMETER() macros. */ #ifdef SQLITE_NO_SYNC UNUSED_PARAMETER(fd); UNUSED_PARAMETER(fullSync); @@ -42210,11 +33828,11 @@ #else UNUSED_PARAMETER(fullSync); UNUSED_PARAMETER(dataOnly); #endif - /* Record the number of times that we do a normal fsync() and + /* Record the number of times that we do a normal fsync() and ** FULLSYNC. This is used during testing to verify that this procedure ** gets called with the correct arguments. */ #ifdef SQLITE_TEST if( fullSync ) sqlite3_fullsync_count++; @@ -42222,11 +33840,11 @@ #endif /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a ** no-op. But go ahead and call fstat() to validate the file ** descriptor as we need a method to provoke a failure during - ** coverage testing. + ** coverate testing. */ #ifdef SQLITE_NO_SYNC { struct stat buf; rc = osFstat(fd, &buf); @@ -42236,25 +33854,25 @@ rc = osFcntl(fd, F_FULLFSYNC, 0); }else{ rc = 1; } /* If the FULLFSYNC failed, fall back to attempting an fsync(). - ** It shouldn't be possible for fullfsync to fail on the local + ** It shouldn't be possible for fullfsync to fail on the local ** file system (on OSX), so failure indicates that FULLFSYNC - ** isn't supported for this file system. So, attempt an fsync - ** and (for now) ignore the overhead of a superfluous fcntl call. - ** It'd be better to detect fullfsync support once and avoid + ** isn't supported for this file system. So, attempt an fsync + ** and (for now) ignore the overhead of a superfluous fcntl call. + ** It'd be better to detect fullfsync support once and avoid ** the fcntl call every time sync is called. */ if( rc ) rc = fsync(fd); #elif defined(__APPLE__) /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly ** so currently we default to the macro that redefines fdatasync to fsync */ rc = fsync(fd); -#else +#else rc = fdatasync(fd); #if OS_VXWORKS if( rc==-1 && errno==ENOTSUP ){ rc = fsync(fd); } @@ -42411,11 +34029,11 @@ #endif #if SQLITE_MAX_MMAP_SIZE>0 /* If the file was just truncated to a size smaller than the currently ** mapped region, reduce the effective mapping size as well. SQLite will - ** use read() and write() to access data beyond this point from now on. + ** use read() and write() to access data beyond this point from now on. */ if( nBytemmapSize ){ pFile->mmapSize = nByte; } #endif @@ -42457,39 +34075,39 @@ ** proxying locking division. */ static int proxyFileControl(sqlite3_file*,int,void*); #endif -/* -** This function is called to handle the SQLITE_FCNTL_SIZE_HINT +/* +** This function is called to handle the SQLITE_FCNTL_SIZE_HINT ** file-control operation. Enlarge the database to nBytes in size ** (rounded up to the next chunk-size). If the database is already ** nBytes or larger, this routine is a no-op. */ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ if( pFile->szChunk>0 ){ i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ - + if( osFstat(pFile->h, &buf) ){ return SQLITE_IOERR_FSTAT; } nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; if( nSize>(i64)buf.st_size ){ #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE - /* The code below is handling the return value of osFallocate() - ** correctly. posix_fallocate() is defined to "returns zero on success, + /* The code below is handling the return value of osFallocate() + ** correctly. posix_fallocate() is defined to "returns zero on success, ** or an error number on failure". See the manpage for details. */ int err; do{ err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); }while( err==EINTR ); - if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; + if( err ) return SQLITE_IOERR_WRITE; #else - /* If the OS does not have posix_fallocate(), fake it. Write a + /* If the OS does not have posix_fallocate(), fake it. Write a ** single byte to the last byte in each block that falls entirely ** within the extended region. Then, if required, a single byte ** at offset (nSize-1), to set the size of the file correctly. ** This is a similar technique to that used by glibc on systems ** that do not have a real fallocate() call. @@ -42544,40 +34162,17 @@ } } /* Forward declaration */ static int unixGetTempname(int nBuf, char *zBuf); -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) - static int unixFcntlExternalReader(unixFile*, int*); -#endif /* ** Information and control of an open file handle. */ 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_NULL_IO: { - osClose(pFile->h); - pFile->h = -1; - return SQLITE_OK; - } case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = pFile->eFileLock; return SQLITE_OK; } case SQLITE_FCNTL_LAST_ERRNO: { @@ -42617,39 +34212,17 @@ } case SQLITE_FCNTL_HAS_MOVED: { *(int*)pArg = fileHasMoved(pFile); return SQLITE_OK; } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - case SQLITE_FCNTL_LOCK_TIMEOUT: { - int iOld = pFile->iBusyTimeout; -#if SQLITE_ENABLE_SETLK_TIMEOUT==1 - pFile->iBusyTimeout = *(int*)pArg; -#elif SQLITE_ENABLE_SETLK_TIMEOUT==2 - pFile->iBusyTimeout = !!(*(int*)pArg); -#else -# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" -#endif - *(int*)pArg = iOld; - return SQLITE_OK; - } -#endif #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; int rc = SQLITE_OK; 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; if( pFile->mmapSize>0 ){ unixUnmapfile(pFile); @@ -42674,68 +34247,47 @@ case SQLITE_FCNTL_SET_LOCKPROXYFILE: case SQLITE_FCNTL_GET_LOCKPROXYFILE: { return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ - - case SQLITE_FCNTL_EXTERNAL_READER: { -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) - return unixFcntlExternalReader((unixFile*)id, (int*)pArg); -#else - *(int*)pArg = 0; - return SQLITE_OK; -#endif - } } return SQLITE_NOTFOUND; } /* -** If pFd->sectorSize is non-zero when this function is called, it is a -** no-op. Otherwise, the values of pFd->sectorSize and -** pFd->deviceCharacteristics are set according to the file-system -** characteristics. +** 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. ** -** There are two versions of this function. One for QNX and one for all -** other systems. +** 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. */ -#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; - - /* 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->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ; - - pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; - } -} -#else +#ifndef __QNXNTO__ +static int unixSectorSize(sqlite3_file *NotUsed){ + UNUSED_PARAMETER(NotUsed); + return SQLITE_DEFAULT_SECTOR_SIZE; +} +#endif + +/* +** The following version of unixSectorSize() is optimized for QNX. +*/ +#ifdef __QNXNTO__ #include #include -static void setDeviceCharacteristics(unixFile *pFile){ +static int unixSectorSize(sqlite3_file *id){ + unixFile *pFile = (unixFile*)id; if( pFile->sectorSize == 0 ){ struct statvfs fsInfo; - + /* Set defaults for non-supported filesystems */ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; pFile->deviceCharacteristics = 0; if( fstatvfs(pFile->h, &fsInfo) == -1 ) { - return; + return pFile->sectorSize; } if( !strcmp(fsInfo.f_basetype, "tmp") ) { pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = @@ -42766,19 +34318,19 @@ 0; }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){ pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = /* full bitset of atomics from max sector size and smaller */ - (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) | + ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 | SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else if( strstr(fsInfo.f_basetype, "dos") ){ pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = /* full bitset of atomics from max sector size and smaller */ - (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) | + ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 | SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else{ pFile->deviceCharacteristics = @@ -42792,28 +34344,13 @@ ** then it isn't valid.*/ if( pFile->sectorSize % 512 != 0 ){ pFile->deviceCharacteristics = 0; pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; } -} -#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 pFile->sectorSize; +} +#endif /* __QNXNTO__ */ /* ** Return the device characteristics for the file. ** ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. @@ -42825,21 +34362,28 @@ ** of required I/O for journaling, since a lot of padding is eliminated. ** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control ** available to turn it off and URI query parameter available to turn it off. */ static int unixDeviceCharacteristics(sqlite3_file *id){ - unixFile *pFd = (unixFile*)id; - setDeviceCharacteristics(pFd); - return pFd->deviceCharacteristics; + 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; } #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 /* ** Return the system page size. ** -** This function should not be called directly by other code in this file. +** This function should not be called directly by other code in this file. ** Instead, it should be called via macro osGetpagesize(). */ static int unixGetpagesize(void){ #if OS_VXWORKS return 1024; @@ -42850,14 +34394,14 @@ #endif } #endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */ -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) +#ifndef SQLITE_OMIT_WAL /* -** Object used to represent an shared memory buffer. +** Object used to represent an shared memory buffer. ** ** When multiple threads all reference the same wal-index, each thread ** has its own unixShm object, but they all point to a single instance ** of this unixShmNode object. In other words, each wal-index is opened ** only once per process. @@ -42873,54 +34417,32 @@ ** this object or while reading or writing the following fields: ** ** nRef ** ** The following fields are read-only after the object is created: -** -** hShm +** +** fid ** zFilename ** -** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and +** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and ** unixMutexHeld() is true when reading or writing any other field ** in this structure. -** -** aLock[SQLITE_SHM_NLOCK]: -** This array records the various locks held by clients on each of the -** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no -** locks are held by the process on this slot. If it is set to -1, then -** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[] -** value is set to a positive value, then it is the number of shared -** locks currently held on the slot. -** -** aMutex[SQLITE_SHM_NLOCK]: -** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex -** pShmMutex is used to protect the aLock[] array and the right to -** call fcntl() on unixShmNode.hShm to obtain or release locks. -** -** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array -** of mutexes - one for each locking slot. To read or write locking -** slot aLock[iSlot], the caller must hold the corresponding mutex -** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a -** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held. */ struct unixShmNode { unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ - sqlite3_mutex *pShmMutex; /* Mutex to access this object */ + sqlite3_mutex *mutex; /* Mutex to access this object */ char *zFilename; /* Name of the mmapped file */ - int hShm; /* Open file descriptor */ + int h; /* Open file descriptor */ 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 */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK]; -#endif - int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */ #ifdef SQLITE_DEBUG + u8 exclMask; /* Mask of exclusive locks held */ + u8 sharedMask; /* Mask of shared locks held */ u8 nextShmId; /* Next available unixShm.id value */ #endif }; /* @@ -42928,20 +34450,20 @@ ** open shared memory connection. ** ** The following fields are initialized when this object is created and ** are read-only thereafter: ** -** unixShm.pShmNode +** unixShm.pFile ** unixShm.id ** -** All other fields are read/write. The unixShm.pShmNode->pShmMutex must -** be held while accessing any read/write fields. +** All other fields are read/write. The unixShm.pFile->mutex must be held +** while accessing any read/write fields. */ struct unixShm { unixShmNode *pShmNode; /* The underlying unixShmNode object */ unixShm *pNext; /* Next unixShm with the same unixShmNode */ - u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ + u8 hasMutex; /* True if holding the unixShmNode mutex */ u8 id; /* Id of this connection within its unixShmNode */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ }; @@ -42948,44 +34470,10 @@ /* ** Constants used for locking */ #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ - -/* -** Use F_GETLK to check whether or not there are any readers with open -** wal-mode transactions in other processes on database file pFile. If -** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are -** such transactions, or 0 otherwise. If an error occurs, return an -** SQLite error code. The final value of *piOut is undefined in this -** case. -*/ -static int unixFcntlExternalReader(unixFile *pFile, int *piOut){ - int rc = SQLITE_OK; - *piOut = 0; - if( pFile->pShm){ - unixShmNode *pShmNode = pFile->pShm->pShmNode; - struct flock f; - - memset(&f, 0, sizeof(f)); - f.l_type = F_WRLCK; - f.l_whence = SEEK_SET; - f.l_start = UNIX_SHM_BASE + 3; - f.l_len = SQLITE_SHM_NLOCK - 3; - - sqlite3_mutex_enter(pShmNode->pShmMutex); - if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){ - rc = SQLITE_IOERR_LOCK; - }else{ - *piOut = (f.l_type!=F_UNLCK); - } - sqlite3_mutex_leave(pShmNode->pShmMutex); - } - - return rc; -} - /* ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. ** ** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking @@ -42999,82 +34487,68 @@ ){ unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */ struct flock f; /* The posix advisory locking structure */ int rc = SQLITE_OK; /* Result code form fcntl() */ + /* Access to the unixShmNode object is serialized by the caller */ pShmNode = pFile->pInode->pShmNode; - - /* Assert that the parameters are within expected range and that the - ** correct mutex or mutexes are held. */ - assert( pShmNode->nRef>=0 ); - assert( (ofst==UNIX_SHM_DMS && n==1) - || (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK)) - ); - if( ofst==UNIX_SHM_DMS ){ - assert( pShmNode->nRef>0 || unixMutexHeld() ); - assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); - }else{ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int ii; - for(ii=ofst-UNIX_SHM_BASE; iiaMutex[ii]) ); - } -#else - assert( sqlite3_mutex_held(pShmNode->pShmMutex) ); - assert( pShmNode->nRef>0 ); -#endif - } + assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); /* Shared locks never span more than one byte */ assert( n==1 || lockType!=F_RDLCK ); /* Locks are within range */ assert( n>=1 && n<=SQLITE_SHM_NLOCK ); - assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) ); - if( pShmNode->hShm>=0 ){ - int res; + if( pShmNode->h>=0 ){ /* Initialize the locking parameters */ + memset(&f, 0, sizeof(f)); f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; - res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); - if( res==-1 ){ -#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1 - rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY); -#else - rc = SQLITE_BUSY; -#endif - } - } - - /* Do debug tracing */ -#ifdef SQLITE_DEBUG - OSTRACE(("SHM-LOCK ")); - if( rc==SQLITE_OK ){ - if( lockType==F_UNLCK ){ - OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1)); - }else if( lockType==F_RDLCK ){ - OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1)); - }else{ - assert( lockType==F_WRLCK ); - OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1)); - } - }else{ - if( lockType==F_UNLCK ){ - OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1)); - }else if( lockType==F_RDLCK ){ - OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1)); - }else{ - assert( lockType==F_WRLCK ); - OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1)); - } - } -#endif - - return rc; + + rc = osFcntl(pShmNode->h, F_SETLK, &f); + rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + } + + /* Update the global lock state and do debug tracing */ +#ifdef SQLITE_DEBUG + { u16 mask; + OSTRACE(("SHM-LOCK ")); + mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<exclMask &= ~mask; + pShmNode->sharedMask &= ~mask; + }else if( lockType==F_RDLCK ){ + OSTRACE(("read-lock %d ok", ofst)); + pShmNode->exclMask &= ~mask; + pShmNode->sharedMask |= mask; + }else{ + assert( lockType==F_WRLCK ); + OSTRACE(("write-lock %d ok", ofst)); + pShmNode->exclMask |= mask; + pShmNode->sharedMask &= ~mask; + } + }else{ + if( lockType==F_UNLCK ){ + OSTRACE(("unlock %d failed", ofst)); + }else if( lockType==F_RDLCK ){ + OSTRACE(("read-lock failed")); + }else{ + assert( lockType==F_WRLCK ); + OSTRACE(("write-lock %d failed", ofst)); + } + } + OSTRACE((" - afterwards %03x,%03x\n", + pShmNode->sharedMask, pShmNode->exclMask)); + } +#endif + + return rc; } /* ** Return the minimum number of 32KB shm regions that should be mapped at ** a time, assuming that each mapping must be an integer multiple of the @@ -43103,124 +34577,43 @@ assert( unixMutexHeld() ); if( p && ALWAYS(p->nRef==0) ){ int nShmPerMap = unixShmRegionPerMap(); int i; assert( p->pInode==pFd->pInode ); - sqlite3_mutex_free(p->pShmMutex); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - for(i=0; iaMutex[i]); - } -#endif + sqlite3_mutex_free(p->mutex); for(i=0; inRegion; i+=nShmPerMap){ - if( p->hShm>=0 ){ + if( p->h>=0 ){ osMunmap(p->apRegion[i], p->szRegion); }else{ sqlite3_free(p->apRegion[i]); } } sqlite3_free(p->apRegion); - if( p->hShm>=0 ){ - robust_close(pFd, p->hShm, __LINE__); - p->hShm = -1; + if( p->h>=0 ){ + robust_close(pFd, p->h, __LINE__); + p->h = -1; } p->pInode->pShmNode = 0; sqlite3_free(p); } } /* -** 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->hShm, 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{ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* Do not use a blocking lock here. If the lock cannot be obtained - ** immediately, it means some other connection is truncating the - ** *-shm file. And after it has done so, it will not release its - ** lock, but only downgrade it to a shared lock. So no point in - ** blocking here. The call below to obtain the shared DMS lock may - ** use a blocking lock. */ - int iSaveTimeout = pDbFd->iBusyTimeout; - pDbFd->iBusyTimeout = 0; -#endif - rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - pDbFd->iBusyTimeout = iSaveTimeout; -#endif - /* The first connection to attach must truncate the -shm file. We - ** truncate to 3 bytes (an arbitrary small number, less than the - ** -shm header size) rather than 0 as a system debugging aid, to - ** help detect if a -shm file truncation is legitimate or is the work - ** or a rogue process. */ - if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){ - rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); - } - } - }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. +** Open a shared-memory area associated with open database file pDbFd. ** This particular implementation uses mmapped files. ** ** The file used to implement shared-memory is in the same directory ** as the open database file and has the same name as the open database ** file with the "-shm" suffix added. For example, if the database file ** is "/home/user1/config.db" then the file that is created and mmapped -** for shared memory will be called "/home/user1/config.db-shm". +** for shared memory will be called "/home/user1/config.db-shm". ** ** Another approach to is to use files in /dev/shm or /dev/tmp or an ** some other tmpfs mount. But if a file in a different directory ** from the database file is used, then differing access permissions ** or a chroot() might cause two different processes on the same -** database to end up using different files for shared memory - +** database to end up using different files for shared memory - ** meaning that their memory would not really be shared - resulting ** in database corruption. Nevertheless, this tmpfs file usage ** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm" ** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time ** option results in an incompatible build of SQLite; builds of SQLite @@ -43240,13 +34633,13 @@ ** file is created. The shared memory will be simulated with heap memory. */ static int unixOpenSharedMemory(unixFile *pDbFd){ struct unixShm *p = 0; /* The connection to be opened */ struct unixShmNode *pShmNode; /* The underlying mmapped file */ - int rc = SQLITE_OK; /* Result code */ + int rc; /* Result code */ unixInodeInfo *pInode; /* The inode of fd */ - char *zShm; /* Name of the file used for SHM */ + char *zShmFilename; /* Name of the file used for SHM */ int nShmFilename; /* Size of the SHM filename in bytes */ /* Allocate space for the new unixShm object. */ p = sqlite3_malloc64( sizeof(*p) ); if( p==0 ) return SQLITE_NOMEM_BKPT; @@ -43254,11 +34647,10 @@ assert( pDbFd->pShm==0 ); /* Check to see if a unixShmNode object already exists. Reuse an existing ** one if present. Create a new one if necessary. */ - assert( unixFileMutexNotheld(pDbFd) ); unixEnterMutex(); pInode = pDbFd->pInode; pShmNode = pInode->pShmNode; if( pShmNode==0 ){ struct stat sStat; /* fstat() info for database file */ @@ -43284,65 +34676,61 @@ if( pShmNode==0 ){ rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename); - zShm = pShmNode->zFilename = (char*)&pShmNode[1]; -#ifdef SQLITE_SHM_DIRECTORY - sqlite3_snprintf(nShmFilename, zShm, - SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", - (u32)sStat.st_ino, (u32)sStat.st_dev); -#else - sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); - sqlite3FileSuffix3(pDbFd->zPath, zShm); -#endif - pShmNode->hShm = -1; - pDbFd->pInode->pShmNode = pShmNode; - pShmNode->pInode = pDbFd->pInode; - if( sqlite3GlobalConfig.bCoreMutex ){ - pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->pShmMutex==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shm_open_err; - } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - { - int ii; - for(ii=0; iiaMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->aMutex[ii]==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto shm_open_err; - } - } - } -#endif - } - - if( pInode->bProcessLock==0 ){ - if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ - pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW, - (sStat.st_mode&0777)); - } - if( pShmNode->hShm<0 ){ - pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW, - (sStat.st_mode&0777)); - if( pShmNode->hShm<0 ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); - goto shm_open_err; - } - pShmNode->isReadonly = 1; + zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1]; +#ifdef SQLITE_SHM_DIRECTORY + sqlite3_snprintf(nShmFilename, zShmFilename, + 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); +#endif + pShmNode->h = -1; + pDbFd->pInode->pShmNode = pShmNode; + pShmNode->pInode = pDbFd->pInode; + if( sqlite3GlobalConfig.bCoreMutex ){ + pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->mutex==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shm_open_err; + } + } + + 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; + } + 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; } /* If this process is running as root, make sure that the SHM file ** is owned by the same user that owns the original database. Otherwise, ** the original owner will not be able to connect. */ - robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); - - rc = unixLockSharedMemory(pDbFd, pShmNode); - if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; + 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; } } /* Make the new connection a child of the unixShmNode */ p->pShmNode = pShmNode; @@ -43355,18 +34743,18 @@ /* The reference count on pShmNode has already been incremented under ** the cover of the unixEnterMutex() mutex and the pointer from the ** new (struct unixShm) object to the pShmNode has been set. All that is ** left to do is to link the new object into the linked list starting - ** at pShmNode->pFirst. This must be done while holding the - ** pShmNode->pShmMutex. + ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex + ** mutex. */ - sqlite3_mutex_enter(pShmNode->pShmMutex); + sqlite3_mutex_enter(pShmNode->mutex); p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; - sqlite3_mutex_leave(pShmNode->pShmMutex); - return rc; + sqlite3_mutex_leave(pShmNode->mutex); + return SQLITE_OK; /* Jump here on any error */ shm_open_err: unixShmPurge(pDbFd); /* This call frees pShmNode if required */ sqlite3_free(p); @@ -43373,26 +34761,26 @@ unixLeaveMutex(); return rc; } /* -** This function is called to obtain a pointer to region iRegion of the -** shared-memory associated with the database file fd. Shared-memory regions -** are numbered starting from zero. Each shared-memory region is szRegion +** This function is called to obtain a pointer to region iRegion of the +** shared-memory associated with the database file fd. Shared-memory regions +** are numbered starting from zero. Each shared-memory region is szRegion ** bytes in size. ** ** If an error occurs, an error code is returned and *pp is set to NULL. ** ** Otherwise, if the bExtend parameter is 0 and the requested shared-memory ** region has not been allocated (by any client, including one running in a -** separate process), then *pp is set to NULL and SQLITE_OK returned. If -** bExtend is non-zero and the requested shared-memory region has not yet +** separate process), then *pp is set to NULL and SQLITE_OK returned. If +** bExtend is non-zero and the requested shared-memory region has not yet ** been allocated, it is allocated by this function. ** ** If the shared-memory region has already been allocated or is allocated by -** this call as described above, then it is mapped into this processes -** address space (if it is not already), *pp is set to point to the mapped +** this call as described above, then it is mapped into this processes +** address space (if it is not already), *pp is set to point to the mapped ** memory and SQLITE_OK returned. */ static int unixShmMap( sqlite3_file *fd, /* Handle open on database file */ int iRegion, /* Region to retrieve */ @@ -43413,20 +34801,15 @@ if( rc!=SQLITE_OK ) return rc; } p = pDbFd->pShm; pShmNode = p->pShmNode; - sqlite3_mutex_enter(pShmNode->pShmMutex); - if( pShmNode->isUnlocked ){ - rc = unixLockSharedMemory(pDbFd, pShmNode); - if( rc!=SQLITE_OK ) goto shmpage_out; - pShmNode->isUnlocked = 0; - } + sqlite3_mutex_enter(pShmNode->mutex); assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); assert( pShmNode->pInode==pDbFd->pInode ); - assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); + assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); /* Minimum number of regions required to be mapped. */ nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; if( pShmNode->nRegionszRegion = szRegion; - if( pShmNode->hShm>=0 ){ + if( pShmNode->h>=0 ){ /* The requested region is not mapped into this processes address space. ** Check to see if it has been allocated (i.e. if the wal-index file is ** large enough to contain the requested region). */ - if( osFstat(pShmNode->hShm, &sStat) ){ + if( osFstat(pShmNode->h, &sStat) ){ rc = SQLITE_IOERR_SHMSIZE; goto shmpage_out; } - + if( sStat.st_sizehShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){ + if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){ const char *zFile = pShmNode->zFilename; rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); goto shmpage_out; } } @@ -43490,26 +34873,26 @@ pShmNode->apRegion = apNew; while( pShmNode->nRegionhShm>=0 ){ + if( pShmNode->h>=0 ){ pMem = osMmap(0, nMap, - pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, - MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion + pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion ); if( pMem==MAP_FAILED ){ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); goto shmpage_out; } }else{ - pMem = sqlite3_malloc64(nMap); + pMem = sqlite3_malloc64(szRegion); if( pMem==0 ){ rc = SQLITE_NOMEM_BKPT; goto shmpage_out; } - memset(pMem, 0, nMap); + memset(pMem, 0, szRegion); } for(i=0; iapRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i]; } @@ -43522,53 +34905,18 @@ *pp = pShmNode->apRegion[iRegion]; }else{ *pp = 0; } if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; - sqlite3_mutex_leave(pShmNode->pShmMutex); + sqlite3_mutex_leave(pShmNode->mutex); return rc; } -/* -** Check that the pShmNode->aLock[] array comports with the locking bitmasks -** held by each client. Return true if it does, or false otherwise. This -** is to be used in an assert(). e.g. -** -** assert( assertLockingArrayOk(pShmNode) ); -*/ -#ifdef SQLITE_DEBUG -static int assertLockingArrayOk(unixShmNode *pShmNode){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - return 1; -#else - unixShm *pX; - int aLock[SQLITE_SHM_NLOCK]; - - memset(aLock, 0, sizeof(aLock)); - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ - int i; - for(i=0; iexclMask & (1<sharedMask & (1<=0 ); - aLock[i]++; - } - } - } - - assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) ); - return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0); -#endif -} -#endif - /* ** Change the lock state for a shared-memory segment. ** -** Note that the relationship between SHARED and EXCLUSIVE locks is a little +** Note that the relationship between SHAREd and EXCLUSIVE locks is a little ** different here than in posix. In xShmLock(), one can go from unlocked ** to shared and back or from unlocked to exclusive and back. But one may ** not go from shared to exclusive or from exclusive to shared. */ static int unixShmLock( @@ -43576,21 +34924,15 @@ int ofst, /* First lock to acquire or release */ int n, /* Number of locks to acquire or release */ int flags /* What to do with the lock */ ){ unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */ - unixShm *p; /* The shared memory being locked */ - unixShmNode *pShmNode; /* The underlying file iNode */ + unixShm *p = pDbFd->pShm; /* The shared memory being locked */ + unixShm *pX; /* For looping over all siblings */ + unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */ int rc = SQLITE_OK; /* Result code */ - u16 mask = (1<<(ofst+n)) - (1<pShm; - if( p==0 ) return SQLITE_IOERR_SHMLOCK; - pShmNode = p->pShmNode; - if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; - aLock = pShmNode->aLock; + u16 mask; /* Mask of locks to take or release */ assert( pShmNode==pDbFd->pInode->pShmNode ); assert( pShmNode->pInode==pDbFd->pInode ); assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); assert( n>=1 ); @@ -43597,197 +34939,111 @@ assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); - assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); - - /* Check that, if this to be a blocking lock, no locks that occur later - ** in the following list than the lock being obtained are already held: - ** - ** 1. Checkpointer lock (ofst==1). - ** 2. Write lock (ofst==0). - ** 3. Read locks (ofst>=3 && ofstexclMask|p->sharedMask); - assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( - (ofst!=2) /* not RECOVER */ - && (ofst!=1 || lockMask==0 || lockMask==2) - && (ofst!=0 || lockMask<3) - && (ofst<3 || lockMask<(1<exclMask & mask) - ); - if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) - || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) - || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) - ){ - - /* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if - ** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any - ** other thread is holding this mutex, then it is either holding or about - ** to hold a lock exclusive to the one being requested, and we may - ** therefore return SQLITE_BUSY to the caller. - ** - ** Doing this prevents some deadlock scenarios. For example, thread 1 may - ** be a checkpointer blocked waiting on the WRITER lock. And thread 2 - ** may be a normal SQL client upgrading to a write transaction. In this - ** case thread 2 does a non-blocking request for the WRITER lock. But - - ** if it were to use sqlite3_mutex_enter() then it would effectively - ** become a (doomed) blocking request, as thread 2 would block until thread - ** 1 obtained WRITER and released the mutex. Since thread 2 already holds - ** a lock on a read-locking slot at this point, this breaks the - ** anti-deadlock rules (see above). */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int iMutex; - for(iMutex=ofst; iMutexaMutex[iMutex]); - if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes; - }else{ - sqlite3_mutex_enter(pShmNode->aMutex[iMutex]); - } - } -#else - sqlite3_mutex_enter(pShmNode->pShmMutex); -#endif - - if( ALWAYS(rc==SQLITE_OK) ){ - if( flags & SQLITE_SHM_UNLOCK ){ - /* Case (a) - unlock. */ - int bUnlock = 1; - assert( (p->exclMask & p->sharedMask)==0 ); - assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); - assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); - - /* If this is a SHARED lock being unlocked, it is possible that other - ** clients within this process are holding the same SHARED lock. In - ** this case, set bUnlock to 0 so that the posix lock is not removed - ** from the file-descriptor below. */ - if( flags & SQLITE_SHM_SHARED ){ - assert( n==1 ); - assert( aLock[ofst]>=1 ); - if( aLock[ofst]>1 ){ - bUnlock = 0; - aLock[ofst]--; - p->sharedMask &= ~mask; - } - } - - if( bUnlock ){ - rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); - if( rc==SQLITE_OK ){ - memset(&aLock[ofst], 0, sizeof(int)*n); - p->sharedMask &= ~mask; - p->exclMask &= ~mask; - } - } - }else if( flags & SQLITE_SHM_SHARED ){ - /* Case (b) - a shared lock. */ - - if( aLock[ofst]<0 ){ - /* An exclusive lock is held by some other connection. BUSY. */ - rc = SQLITE_BUSY; - }else if( aLock[ofst]==0 ){ - rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); - } - - /* Get the local shared locks */ - if( rc==SQLITE_OK ){ - p->sharedMask |= mask; - aLock[ofst]++; - } - }else{ - /* Case (c) - an exclusive lock. */ - int ii; - - assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ); + assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + + mask = (1<<(ofst+n)) - (1<1 || mask==(1<mutex); + if( flags & SQLITE_SHM_UNLOCK ){ + u16 allMask = 0; /* Mask of locks held by siblings */ + + /* See if any siblings hold this same lock */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( pX==p ) continue; + assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); + allMask |= pX->sharedMask; + } + + /* Unlock the system-level locks */ + if( (mask & allMask)==0 ){ + rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); + }else{ + rc = SQLITE_OK; + } + + /* Undo the local locks */ + if( rc==SQLITE_OK ){ + p->exclMask &= ~mask; + p->sharedMask &= ~mask; + } + }else if( flags & SQLITE_SHM_SHARED ){ + u16 allShared = 0; /* Union of locks held by connections other than "p" */ + + /* Find out which shared locks are already held by sibling connections. + ** If any sibling already holds an exclusive lock, go ahead and return + ** SQLITE_BUSY. + */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( (pX->exclMask & mask)!=0 ){ + rc = SQLITE_BUSY; + break; + } + allShared |= pX->sharedMask; + } + + /* Get shared locks at the system level, if necessary */ + if( rc==SQLITE_OK ){ + if( (allShared & mask)==0 ){ + rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); + }else{ + rc = SQLITE_OK; + } + } + + /* Get the local shared locks */ + if( rc==SQLITE_OK ){ + p->sharedMask |= mask; + } + }else{ + /* Make sure no sibling connections hold locks that will block this + ** lock. If any do, return SQLITE_BUSY right away. + */ + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ + if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ + rc = SQLITE_BUSY; + break; + } + } + + /* Get the exclusive locks at the system level. Then if successful + ** also mark the local connection as being locked. + */ + if( rc==SQLITE_OK ){ + rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n); + if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); - assert( (p->exclMask & mask)==0 ); - - /* Make sure no sibling connections hold locks that will block this - ** lock. If any do, return SQLITE_BUSY right away. */ - for(ii=ofst; iiexclMask |= mask; - for(ii=ofst; ii=ofst; iMutex--){ - sqlite3_mutex_leave(pShmNode->aMutex[iMutex]); - } -#else - sqlite3_mutex_leave(pShmNode->pShmMutex); -#endif - } - + p->exclMask |= mask; + } + } + } + sqlite3_mutex_leave(pShmNode->mutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", p->id, osGetpid(0), p->sharedMask, p->exclMask)); return rc; } /* -** Implement a memory barrier or memory fence on shared memory. +** Implement a memory barrier or memory fence on shared memory. ** ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. */ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ UNUSED_PARAMETER(fd); sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ - assert( fd->pMethods->xLock==nolockLock - || unixFileMutexNotheld((unixFile*)fd) - ); unixEnterMutex(); /* Also mutex, for redundancy */ unixLeaveMutex(); } /* -** Close a connection to shared-memory. Delete the underlying +** Close a connection to shared-memory. Delete the underlying ** storage if deleteFlag is true. ** ** If there is no shared memory associated with the connection then this ** routine is a harmless no-op. */ @@ -43808,27 +35064,26 @@ assert( pShmNode==pDbFd->pInode->pShmNode ); assert( pShmNode->pInode==pDbFd->pInode ); /* Remove connection p from the set of connections associated ** with pShmNode */ - sqlite3_mutex_enter(pShmNode->pShmMutex); + sqlite3_mutex_enter(pShmNode->mutex); for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} *pp = p->pNext; /* Free the connection p */ sqlite3_free(p); pDbFd->pShm = 0; - sqlite3_mutex_leave(pShmNode->pShmMutex); + sqlite3_mutex_leave(pShmNode->mutex); /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ - assert( unixFileMutexNotheld(pDbFd) ); unixEnterMutex(); assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->hShm>=0 ){ + if( deleteFlag && pShmNode->h>=0 ){ osUnlink(pShmNode->zFilename); } unixShmPurge(pDbFd); } unixLeaveMutex(); @@ -43857,11 +35112,11 @@ pFd->mmapSizeActual = 0; } } /* -** Attempt to set the size of the memory mapping maintained by file +** Attempt to set the size of the memory mapping maintained by file ** descriptor pFd to nNew bytes. Any existing mapping is discarded. ** ** If successful, this function sets the following variables: ** ** unixFile.pMapRegion @@ -43949,18 +35204,18 @@ pFd->mmapSize = pFd->mmapSizeActual = nNew; } /* ** Memory map or remap the file opened by file-descriptor pFd (if the file -** is already mapped, the existing mapping is replaced by the new). Or, if -** there already exists a mapping for this file, and there are still +** is already mapped, the existing mapping is replaced by the new). Or, if +** there already exists a mapping for this file, and there are still ** outstanding xFetch() references to it, this function is a no-op. ** -** If parameter nByte is non-negative, then it is the requested size of -** the mapping to create. Otherwise, if nByte is less than zero, then the +** If parameter nByte is non-negative, then it is the requested size of +** the mapping to create. Otherwise, if nByte is less than zero, then the ** requested size is the size of the file on disk. The actual size of the -** created mapping is either the requested size or the value configured +** created mapping is either the requested size or the value configured ** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller. ** ** SQLITE_OK is returned if no error occurs (even if the mapping is not ** recreated as a result of outstanding references) or an SQLite error ** code otherwise. @@ -43997,11 +35252,11 @@ ** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. ** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. ** Finally, if an error does occur, return an SQLite error code. The final ** value of *pp is undefined in this case. ** -** If this function does return a pointer, the caller must eventually +** If this function does return a pointer, the caller must eventually ** release the reference by calling unixUnfetch(). */ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ #if SQLITE_MAX_MMAP_SIZE>0 unixFile *pFd = (unixFile *)fd; /* The underlying database file */ @@ -44008,44 +35263,39 @@ #endif *pp = 0; #if SQLITE_MAX_MMAP_SIZE>0 if( pFd->mmapSizeMax>0 ){ - /* Ensure that there is always at least a 256 byte buffer of addressable - ** memory following the returned page. If the database is corrupt, - ** SQLite may overread the page slightly (in practice only a few bytes, - ** but 256 is safe, round, number). */ - const int nEofBuffer = 256; if( pFd->pMapRegion==0 ){ int rc = unixMapfile(pFd, -1); if( rc!=SQLITE_OK ) return rc; } - if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ + if( pFd->mmapSize >= iOff+nAmt ){ *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; } } #endif return SQLITE_OK; } /* -** If the third argument is non-NULL, then this function releases a +** If the third argument is non-NULL, then this function releases a ** reference obtained by an earlier call to unixFetch(). The second ** argument passed to this function must be the same as the corresponding -** argument that was passed to the unixFetch() invocation. +** argument that was passed to the unixFetch() invocation. ** -** Or, if the third argument is NULL, then this function is being called -** to inform the VFS layer that, according to POSIX, any existing mapping +** Or, if the third argument is NULL, then this function is being called +** to inform the VFS layer that, according to POSIX, any existing mapping ** may now be invalid and should be unmapped. */ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ #if SQLITE_MAX_MMAP_SIZE>0 unixFile *pFd = (unixFile *)fd; /* The underlying database file */ UNUSED_PARAMETER(iOff); - /* If p==0 (unmap the entire file) then there must be no outstanding + /* If p==0 (unmap the entire file) then there must be no outstanding ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), ** then there must be at least one outstanding. */ assert( (p==0)==(pFd->nFetchOut==0) ); /* If p!=0, it must match the iOff value. */ @@ -44151,11 +35401,11 @@ unixShmMap /* xShmMap method */ ) IOMETHODS( nolockIoFinder, /* Finder function name */ nolockIoMethods, /* sqlite3_io_methods object name */ - 3, /* shared memory and mmap are enabled */ + 3, /* shared memory is disabled */ nolockClose, /* xClose method */ nolockLock, /* xLock method */ nolockUnlock, /* xUnlock method */ nolockCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ @@ -44249,12 +35499,12 @@ 0 /* xShmMap method */ ) #endif #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE -/* -** This "finder" function attempts to determine the best locking strategy +/* +** This "finder" function attempts to determine the best locking strategy ** for the database file "filePath". It then returns the sqlite3_io_methods ** object that implements that strategy. ** ** This is for MacOSX only. */ @@ -44292,12 +35542,12 @@ } } } /* Default case. Handles, amongst others, "nfs". - ** Test byte-range lock using fcntl(). If the call succeeds, - ** assume that the file-system supports POSIX style locks. + ** Test byte-range lock using fcntl(). If the call succeeds, + ** assume that the file-system supports POSIX style locks. */ lockInfo.l_len = 1; lockInfo.l_start = 0; lockInfo.l_whence = SEEK_SET; lockInfo.l_type = F_RDLCK; @@ -44309,11 +35559,11 @@ } }else{ return &dotlockIoMethods; } } -static const sqlite3_io_methods +static const sqlite3_io_methods *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ #if OS_VXWORKS @@ -44345,11 +35595,11 @@ return &posixIoMethods; }else{ return &semIoMethods; } } -static const sqlite3_io_methods +static const sqlite3_io_methods *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl; #endif /* OS_VXWORKS */ /* @@ -44378,10 +35628,21 @@ const sqlite3_io_methods *pLockingStyle; unixFile *pNew = (unixFile *)pId; int rc = SQLITE_OK; 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 ); OSTRACE(("OPEN %-3d %s\n", h, zFilename)); @@ -44473,18 +35734,18 @@ if( rc!=SQLITE_OK ){ sqlite3_free(pNew->lockingContext); robust_close(pNew, h, __LINE__); h = -1; } - unixLeaveMutex(); + unixLeaveMutex(); } } #endif else if( pLockingStyle == &dotlockIoMethods ){ /* Dotfile locking uses the file path so it needs to be included in - ** the dotlockLockingContext + ** the dotlockLockingContext */ char *zLockFile; int nFilename; assert( zFilename!=0 ); nFilename = (int)strlen(zFilename) + 6; @@ -44518,11 +35779,11 @@ } } unixLeaveMutex(); } #endif - + storeLastErrno(pNew, 0); #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; @@ -44531,56 +35792,46 @@ } #endif if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); }else{ - pId->pMethods = pLockingStyle; + pNew->pMethod = pLockingStyle; OpenCounter(+1); verifyDbFile(pNew); } return rc; } -/* -** Directories to consider for temp files. -*/ -static const char *azTempDirs[] = { - 0, - 0, - "/var/tmp", - "/usr/tmp", - "/tmp", - "." -}; - -/* -** Initialize first two members of azTempDirs[] array. -*/ -static void unixTempFileInit(void){ - azTempDirs[0] = getenv("SQLITE_TMPDIR"); - azTempDirs[1] = getenv("TMPDIR"); -} - /* ** Return the name of a directory in which to put temporary files. ** If no suitable temporary file directory can be found, return NULL. */ static const char *unixTempFileDir(void){ + static const char *azDirs[] = { + 0, + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + "." + }; unsigned int i = 0; struct stat buf; const char *zDir = sqlite3_temp_directory; + if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); + if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); while(1){ if( zDir!=0 && osStat(zDir, &buf)==0 && S_ISDIR(buf.st_mode) && osAccess(zDir, 03)==0 ){ return zDir; } - if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break; - zDir = azTempDirs[i++]; + if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break; + zDir = azDirs[i++]; } return 0; } /* @@ -44589,39 +35840,30 @@ ** pVfs->mxPathname bytes. */ static int unixGetTempname(int nBuf, char *zBuf){ const char *zDir; int iLimit = 0; - int rc = SQLITE_OK; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this - ** function failing. + ** function failing. */ zBuf[0] = 0; SimulateIOError( return SQLITE_IOERR ); - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); zDir = unixTempFileDir(); - if( zDir==0 ){ - rc = SQLITE_IOERR_GETTEMPPATH; - }else{ - do{ - u64 r; - sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", - zDir, r, 0); - if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){ - rc = SQLITE_ERROR; - break; - } - }while( osAccess(zBuf,0)==0 ); - } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - return rc; + if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH; + do{ + u64 r; + sqlite3_randomness(sizeof(r), &r); + assert( nBuf>2 ); + zBuf[nBuf-2] = 0; + sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", + zDir, r, 0); + if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR; + }while( osAccess(zBuf,0)==0 ); + return SQLITE_OK; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) /* ** Routine to transform a unixFile into a proxy-locking unixFile. @@ -44630,20 +35872,20 @@ */ static int proxyTransformUnixFile(unixFile*, const char*); #endif /* -** Search for an unused file descriptor that was opened on the database -** file (not a journal or super-journal file) identified by pathname +** Search for an unused file descriptor that was opened on the database +** file (not a journal or master-journal file) identified by pathname ** zPath with SQLITE_OPEN_XXX flags matching those passed as the second ** argument to this function. ** ** Such a file descriptor may exist if a database connection was closed ** but the associated file descriptor could not be closed because some ** other file descriptor open on the same file is holding a file-lock. ** Refer to comments in the unixClose() function and the lengthy comment -** describing "Posix Advisory Locking" at the start of this file for +** describing "Posix Advisory Locking" at the start of this file for ** further details. Also, ticket #4018. ** ** If a suitable file descriptor is found, then it is returned. If no ** such file descriptor is located, -1 is returned. */ @@ -44650,54 +35892,49 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ UnixUnusedFd *pUnused = 0; /* Do not search for an unused file descriptor on vxworks. Not because ** vxworks would not benefit from the change (it might, we're not sure), - ** but because no way to test it is currently available. It is better - ** not to risk breaking vxworks support for the sake of such an obscure + ** but because no way to test it is currently available. It is better + ** not to risk breaking vxworks support for the sake of such an obscure ** feature. */ #if !OS_VXWORKS struct stat sStat; /* Results of stat() call */ - 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 ** ignored and -1 is returned. The caller will try to open a new file ** descriptor on the same path, fail, and return an error to SQLite. ** ** Even if a subsequent open() call does succeed, the consequences of ** not searching for a reusable file descriptor are not dire. */ - if( inodeList!=0 && 0==osStat(zPath, &sStat) ){ + if( 0==osStat(zPath, &sStat) ){ unixInodeInfo *pInode; + unixEnterMutex(); pInode = inodeList; while( pInode && (pInode->fileId.dev!=sStat.st_dev || pInode->fileId.ino!=(u64)sStat.st_ino) ){ pInode = pInode->pNext; } if( pInode ){ UnixUnusedFd **pp; - assert( sqlite3_mutex_notheld(pInode->pLockMutex) ); - sqlite3_mutex_enter(pInode->pLockMutex); - flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE); for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); pUnused = *pp; if( pUnused ){ *pp = pUnused->pNext; } - sqlite3_mutex_leave(pInode->pLockMutex); } + unixLeaveMutex(); } - unixLeaveMutex(); #endif /* if !OS_VXWORKS */ return pUnused; } /* -** Find the mode, uid and gid of file zFile. +** Find the mode, uid and gid of file zFile. */ static int getFileMode( const char *zFile, /* File name */ mode_t *pMode, /* OUT: Permissions of zFile */ uid_t *pUid, /* OUT: uid of zFile. */ @@ -44717,26 +35954,26 @@ /* ** This function is called by unixOpen() to determine the unix permissions ** to create new files with. If no error occurs, then SQLITE_OK is returned ** and a value suitable for passing as the third argument to open(2) is -** written to *pMode. If an IO error occurs, an SQLite error code is +** written to *pMode. If an IO error occurs, an SQLite error code is ** returned and the value of *pMode is not modified. ** ** In most cases, this routine sets *pMode to 0, which will become ** an indication to robust_open() to create the file using ** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask. -** But if the file being opened is a WAL or regular journal file, then -** this function queries the file-system for the permissions on the -** corresponding database file and sets *pMode to this value. Whenever -** possible, WAL and journal files are created using the same permissions +** But if the file being opened is a WAL or regular journal file, then +** this function queries the file-system for the permissions on the +** corresponding database file and sets *pMode to this value. Whenever +** possible, WAL and journal files are created using the same permissions ** as the associated database file. ** ** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the ** original filename is unavailable. But 8_3_NAMES is only used for ** FAT filesystems and permissions do not matter there, so just use -** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero. +** the default permissions. */ static int findCreateFileMode( const char *zPath, /* Path of file (possibly) being created */ int flags, /* Flags passed as 4th argument to xOpen() */ mode_t *pMode, /* OUT: Permissions to open file with */ @@ -44758,29 +35995,31 @@ ** "-journal" ** "-wal" ** "-journalNN" ** "-walNN" ** - ** where NN is a decimal number. The NN naming schemes are + ** where NN is a decimal number. The NN naming schemes are ** used by the test_multiplex.c module. - ** - ** In normal operation, the journal file name will always contain - ** a '-' character. However in 8+3 filename mode, or if a corrupt - ** rollback journal specifies a super-journal with a goofy name, then - ** the '-' might be missing or the '-' might be the first character in - ** the filename. In that case, just return SQLITE_OK with *pMode==0. */ - nDb = sqlite3Strlen30(zPath) - 1; - while( nDb>0 && zPath[nDb]!='.' ){ - if( zPath[nDb]=='-' ){ - memcpy(zDb, zPath, nDb); - zDb[nDb] = '\0'; - rc = getFileMode(zDb, pMode, pUid, pGid); - break; - } + 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. */ + if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK; +#endif nDb--; } + memcpy(zDb, zPath, nDb); + zDb[nDb] = '\0'; + + rc = getFileMode(zDb, pMode, pUid, pGid); }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; }else if( flags & SQLITE_OPEN_URI ){ /* If this is a main database file and the file was opened using a URI ** filename, check for the "modeof" parameter. If present, interpret @@ -44794,11 +36033,11 @@ return rc; } /* ** Open the file zPath. -** +** ** Previously, the SQLite OS layer used three functions in place of this ** one: ** ** sqlite3OsOpenReadWrite(); ** sqlite3OsOpenReadOnly(); @@ -44805,17 +36044,17 @@ ** sqlite3OsOpenExclusive(); ** ** These calls correspond to the following combinations of flags: ** ** ReadWrite() -> (READWRITE | CREATE) -** ReadOnly() -> (READONLY) +** ReadOnly() -> (READONLY) ** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) ** ** The old OpenExclusive() accepted a boolean argument - "delFlag". If ** true, the file was configured to be automatically deleted when the -** file handle closed. To achieve the same effect using this new -** interface, add the DELETEONCLOSE flag to those specified above for +** file handle closed. To achieve the same effect using this new +** interface, add the DELETEONCLOSE flag to those specified above for ** OpenExclusive(). */ static int unixOpen( sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ const char *zPath, /* Pathname of file to be opened */ @@ -44824,11 +36063,11 @@ int *pOutFlags /* Output flags returned to SQLite core */ ){ unixFile *p = (unixFile *)pFile; int fd = -1; /* File descriptor returned by open() */ int openFlags = 0; /* Flags to pass to open() */ - int eType = flags&0x0FFF00; /* Type of file to open */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ int rc = SQLITE_OK; /* Function Return Code */ int ctrlFlags = 0; /* UNIXFILE_* flags */ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); @@ -44841,49 +36080,49 @@ #endif #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE struct statfs fsInfo; #endif - /* If creating a super- or main-file journal, this function will open + /* If creating a master or main-file journal, this function will open ** a file-descriptor on the directory too. The first time unixSync() ** is called the directory file descriptor will be fsync()ed and close()d. */ - int isNewJrnl = (isCreate && ( - eType==SQLITE_OPEN_SUPER_JOURNAL - || eType==SQLITE_OPEN_MAIN_JOURNAL + int syncDir = (isCreate && ( + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL )); /* If argument zPath is a NULL pointer, this function is required to open ** a temporary file. Use this buffer to store the file name in. */ char zTmpname[MAX_PATHNAME+2]; const char *zName = zPath; - /* Check the following statements are true: + /* Check the following statements are true: ** - ** (a) Exactly one of the READWRITE and READONLY flags must be set, and + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and ** (b) if CREATE is set, then READWRITE must also be set, and ** (c) if EXCLUSIVE is set, then CREATE must also be set. ** (d) if DELETEONCLOSE is set, then CREATE must also be set. */ assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); assert(isCreate==0 || isReadWrite); assert(isExclusive==0 || isCreate); assert(isDelete==0 || isCreate); - /* The main DB, main journal, WAL file and super-journal are never + /* The main DB, main journal, WAL file and master journal are never ** automatically deleted. Nor are they ever temporary files. */ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); /* Assert that the upper layer has set one of the "file-type" flags. */ - assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB - || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL - || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); /* Detect a pid change and reset the PRNG. There is a race condition ** here such that two or more threads all trying to open databases at @@ -44892,17 +36131,13 @@ */ if( randomnessPid!=osGetpid(0) ){ randomnessPid = osGetpid(0); sqlite3_randomness(0,0); } + memset(p, 0, sizeof(unixFile)); -#ifdef SQLITE_ASSERT_NO_FILES - /* Applications that never read or write a persistent disk files */ - assert( zName==0 ); -#endif - if( eType==SQLITE_OPEN_MAIN_DB ){ UnixUnusedFd *pUnused; pUnused = findReusableFd(zName, flags); if( pUnused ){ fd = pUnused->fd; @@ -44910,20 +36145,20 @@ pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM_BKPT; } } - p->pPreallocatedUnused = pUnused; + p->pUnused = pUnused; /* Database filenames are double-zero terminated if they are not ** URIs with parameters. Hence, they can always be passed into ** sqlite3_uri_parameter(). */ assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 ); }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ - assert(isDelete && !isNewJrnl); + assert(isDelete && !syncDir); rc = unixGetTempname(pVfs->mxPathname, zTmpname); if( rc!=SQLITE_OK ){ return rc; } zName = zTmpname; @@ -44933,84 +36168,61 @@ assert( zName[strlen(zName)+1]==0 ); } /* Determine the value of the flags parameter passed to POSIX function ** open(). These must be calculated even if open() is not called, as - ** they may be stored as part of the file handle and used by the + ** they may be stored as part of the file handle and used by the ** 'conch file' locking functions later on. */ if( isReadonly ) openFlags |= O_RDONLY; if( isReadWrite ) openFlags |= O_RDWR; if( isCreate ) openFlags |= O_CREAT; if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); - openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW); + openFlags |= (O_LARGEFILE|O_BINARY); if( fd<0 ){ mode_t openMode; /* Permissions to create file with */ uid_t uid; /* Userid for the file */ gid_t gid; /* Groupid for the file */ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ - assert( !p->pPreallocatedUnused ); + assert( !p->pUnused ); 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 ){ - 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. */ - UnixUnusedFd *pReadonly = 0; - flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); - openFlags &= ~(O_RDWR|O_CREAT); - flags |= SQLITE_OPEN_READONLY; - openFlags |= O_RDONLY; - isReadonly = 1; - pReadonly = findReusableFd(zName, flags); - if( pReadonly ){ - fd = pReadonly->fd; - sqlite3_free(pReadonly); - }else{ - fd = robust_open(zName, openFlags, openMode); - } - } - } - if( fd<0 ){ - int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); - if( rc==SQLITE_OK ) rc = rc2; + 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 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); goto open_finished; } - /* The owner of the rollback journal or WAL file should always be the - ** same as the owner of the database file. Try to ensure that this is - ** the case. The chown() system call will be a no-op if the current - ** process lacks root privileges, be we should at least try. Without - ** this step, if a root process opens a database file, it can leave - ** behinds a journal/WAL that is owned by root and hence make the - ** database inaccessible to unprivileged processes. - ** - ** If openMode==0, then that means uid and gid are not set correctly - ** (probably because SQLite is configured to use 8+3 filename mode) and - ** in that case we do not want to attempt the chown(). + /* If this process is running as root and if creating a new rollback + ** journal or WAL file, set the ownership of the journal or WAL to be + ** the same as the original database. */ - if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){ + if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ robustFchown(fd, uid, gid); } } assert( fd>=0 ); if( pOutFlags ){ *pOutFlags = flags; } - if( p->pPreallocatedUnused ){ - p->pPreallocatedUnused->fd = fd; - p->pPreallocatedUnused->flags = - flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE); + if( p->pUnused ){ + p->pUnused->fd = fd; + p->pUnused->flags = flags; } if( isDelete ){ #if OS_VXWORKS zPath = zName; @@ -45027,11 +36239,11 @@ #if SQLITE_ENABLE_LOCKING_STYLE else{ p->openFlags = openFlags; } #endif - + #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ storeLastErrno(p, errno); robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; @@ -45047,11 +36259,11 @@ /* Set up appropriate ctrlFlags */ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; noLock = eType!=SQLITE_OPEN_MAIN_DB; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; - if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC; + if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; #if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_PREFER_PROXY_LOCKING isAutoProxy = 1; @@ -45058,11 +36270,11 @@ #endif if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); int useProxy = 0; - /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means + /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means ** never use proxy, NULL means use proxy for non-local files only. */ if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ useProxy = !(fsInfo.f_flags&MNT_LOCAL); @@ -45070,31 +36282,28 @@ if( useProxy ){ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); if( rc==SQLITE_OK ){ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); if( rc!=SQLITE_OK ){ - /* Use unixClose to clean up the resources added in fillInUnixFile - ** and clear all the structure's references. Specifically, - ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op + /* Use unixClose to clean up the resources added in fillInUnixFile + ** and clear all the structure's references. Specifically, + ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op */ unixClose(pFile); return rc; } } goto open_finished; } } #endif - - assert( zPath==0 || zPath[0]=='/' - || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL - ); + rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); open_finished: if( rc!=SQLITE_OK ){ - sqlite3_free(p->pPreallocatedUnused); + sqlite3_free(p->pUnused); } return rc; } @@ -45164,147 +36373,136 @@ ** two of them are actually used */ assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE ); if( flags==SQLITE_ACCESS_EXISTS ){ struct stat buf; - *pResOut = 0==osStat(zPath, &buf) && - (!S_ISREG(buf.st_mode) || buf.st_size>0); + *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0); }else{ *pResOut = osAccess(zPath, W_OK|R_OK)==0; } return SQLITE_OK; } /* -** A pathname under construction -*/ -typedef struct DbPath DbPath; -struct DbPath { - int rc; /* Non-zero following any error */ - int nSymlink; /* Number of symlinks resolved */ - char *zOut; /* Write the pathname here */ - int nOut; /* Bytes of space available to zOut[] */ - int nUsed; /* Bytes of zOut[] currently being used */ -}; - -/* Forward reference */ -static void appendAllPathElements(DbPath*,const char*); - -/* -** Append a single path element to the DbPath under construction -*/ -static void appendOnePathElement( - DbPath *pPath, /* Path under construction, to which to append zName */ - const char *zName, /* Name to append to pPath. Not zero-terminated */ - int nName /* Number of significant bytes in zName */ -){ - assert( nName>0 ); - assert( zName!=0 ); - if( zName[0]=='.' ){ - if( nName==1 ) return; - if( zName[1]=='.' && nName==2 ){ - if( pPath->nUsed>1 ){ - assert( pPath->zOut[0]=='/' ); - while( pPath->zOut[--pPath->nUsed]!='/' ){} - } - return; - } - } - if( pPath->nUsed + nName + 2 >= pPath->nOut ){ - pPath->rc = SQLITE_ERROR; - return; - } - pPath->zOut[pPath->nUsed++] = '/'; - memcpy(&pPath->zOut[pPath->nUsed], zName, nName); - pPath->nUsed += nName; -#if defined(HAVE_READLINK) && defined(HAVE_LSTAT) - if( pPath->rc==SQLITE_OK ){ - const char *zIn; - struct stat buf; - pPath->zOut[pPath->nUsed] = 0; - zIn = pPath->zOut; - if( osLstat(zIn, &buf)!=0 ){ - if( errno!=ENOENT ){ - pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); - } - }else if( S_ISLNK(buf.st_mode) ){ - ssize_t got; - char zLnk[SQLITE_MAX_PATHLEN+2]; - if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){ - pPath->rc = SQLITE_CANTOPEN_BKPT; - return; - } - got = osReadlink(zIn, zLnk, sizeof(zLnk)-2); - if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){ - pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); - return; - } - zLnk[got] = 0; - if( zLnk[0]=='/' ){ - pPath->nUsed = 0; - }else{ - pPath->nUsed -= nName + 1; - } - appendAllPathElements(pPath, zLnk); - } - } -#endif -} - -/* -** Append all path elements in zPath to the DbPath under construction. -*/ -static void appendAllPathElements( - DbPath *pPath, /* Path under construction, to which to append zName */ - const char *zPath /* Path to append to pPath. Is zero-terminated */ -){ - int i = 0; - int j = 0; - do{ - while( zPath[i] && zPath[i]!='/' ){ i++; } - if( i>j ){ - appendOnePathElement(pPath, &zPath[j], i-j); - } - j = i+1; - }while( zPath[i++] ); +** +*/ +static int mkFullPathname( + const char *zPath, /* Input path */ + char *zOut, /* Output buffer */ + int nOut /* Allocated size of buffer zOut */ +){ + int nPath = sqlite3Strlen30(zPath); + int iOff = 0; + if( zPath[0]!='/' ){ + if( osGetcwd(zOut, nOut-2)==0 ){ + return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); + } + iOff = sqlite3Strlen30(zOut); + zOut[iOff++] = '/'; + } + if( (iOff+nPath+1)>nOut ){ + /* SQLite assumes that xFullPathname() nul-terminates the output buffer + ** even if it returns an error. */ + zOut[iOff] = '\0'; + return SQLITE_CANTOPEN_BKPT; + } + sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); + return SQLITE_OK; } /* ** Turn a relative pathname into a full pathname. The relative path ** is stored as a nul-terminated string in the buffer pointed to by -** zPath. +** zPath. ** -** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes +** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes ** (in this case, MAX_PATHNAME bytes). The full-path is written to ** this buffer before returning. */ static int unixFullPathname( sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zPath, /* Possibly relative input path */ int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ - DbPath path; +#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) + return mkFullPathname(zPath, zOut, nOut); +#else + int rc = SQLITE_OK; + int nByte; + int nLink = 1; /* Number of symbolic links followed so far */ + const char *zIn = zPath; /* Input path for each iteration of loop */ + char *zDel = 0; + + assert( pVfs->mxPathname==MAX_PATHNAME ); UNUSED_PARAMETER(pVfs); - path.rc = 0; - path.nUsed = 0; - path.nSymlink = 0; - path.nOut = nOut; - path.zOut = zOut; - if( zPath[0]!='/' ){ - char zPwd[SQLITE_MAX_PATHLEN+2]; - if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){ - return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); - } - appendAllPathElements(&path, zPwd); - } - appendAllPathElements(&path, zPath); - zOut[path.nUsed] = 0; - if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT; - if( path.nSymlink ) return SQLITE_OK_SYMLINK; - return SQLITE_OK; -} + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directory has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + + do { + + /* Call stat() on path zIn. Set bLink to true if the path is a symbolic + ** link, or false otherwise. */ + int bLink = 0; + struct stat buf; + if( osLstat(zIn, &buf)!=0 ){ + if( errno!=ENOENT ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); + } + }else{ + bLink = S_ISLNK(buf.st_mode); + } + + if( bLink ){ + if( zDel==0 ){ + zDel = sqlite3_malloc(nOut); + if( zDel==0 ) rc = SQLITE_NOMEM_BKPT; + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ + rc = SQLITE_CANTOPEN_BKPT; + } + + if( rc==SQLITE_OK ){ + nByte = osReadlink(zIn, zDel, nOut-1); + if( nByte<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); + }else{ + if( zDel[0]!='/' ){ + int n; + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); + if( nByte+n+1>nOut ){ + rc = SQLITE_CANTOPEN_BKPT; + }else{ + memmove(&zDel[n], zDel, nByte+1); + memcpy(zDel, zIn, n); + nByte += n; + } + } + zDel[nByte] = '\0'; + } + } + + zIn = zDel; + } + + assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); + if( rc==SQLITE_OK && zIn!=zOut ){ + rc = mkFullPathname(zIn, zOut, nOut); + } + if( bLink==0 ) break; + zIn = zOut; + }while( rc==SQLITE_OK ); + + sqlite3_free(zDel); + return rc; +#endif /* HAVE_READLINK && HAVE_LSTAT */ +} + #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. @@ -45331,21 +36529,21 @@ sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); } unixLeaveMutex(); } static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){ - /* + /* ** GCC with -pedantic-errors says that C90 does not allow a void* to be ** cast into a pointer to a function. And yet the library dlsym() routine ** returns a void* which is really a pointer to a function. So how do we ** use dlsym() with -pedantic-errors? ** ** Variable x below is defined to be a pointer to a function taking ** parameters void* and const char* and returning a pointer to a function. ** We initialize x by assigning it a pointer to the dlsym() function. ** (That assignment requires a cast.) Then we call the function that - ** x points to. + ** x points to. ** ** This work-around is unlikely to work correctly on any system where ** you really cannot cast a function pointer into void*. But then, on the ** other hand, dlsym() will not work on such a system either, so we have ** not really lost anything. @@ -45384,11 +36582,11 @@ ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset(zBuf, 0, nBuf); - randomnessPid = osGetpid(0); + randomnessPid = osGetpid(0); #if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) { int fd, got; fd = robust_open("/dev/urandom", O_RDONLY, 0); if( fd<0 ){ @@ -45415,26 +36613,20 @@ ** requested from the underlying operating system, a number which ** might be greater than or equal to the argument, but not less ** than the argument. */ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ -#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0 +#if OS_VXWORKS struct timespec sp; + sp.tv_sec = microseconds / 1000000; sp.tv_nsec = (microseconds % 1000000) * 1000; - - /* Almost all modern unix systems support nanosleep(). But if you are - ** compiling for one of the rare exceptions, you can use - ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if - ** usleep() is available) in order to bypass the use of nanosleep() */ nanosleep(&sp, NULL); - UNUSED_PARAMETER(NotUsed); return microseconds; #elif defined(HAVE_USLEEP) && HAVE_USLEEP - if( microseconds>=1000000 ) sleep(microseconds/1000000); - if( microseconds%1000000 ) usleep(microseconds%1000000); + usleep(microseconds); UNUSED_PARAMETER(NotUsed); return microseconds; #else int seconds = (microseconds+999999)/1000000; sleep(seconds); @@ -45457,11 +36649,11 @@ ** the current time and date as a Julian Day number times 86_400_000. In ** other words, write into *piNow the number of milliseconds since the Julian ** epoch of noon in Greenwich on November 24, 4714 B.C according to the ** proleptic Gregorian calendar. ** -** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date +** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date ** cannot be found. */ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; int rc = SQLITE_OK; @@ -45564,11 +36756,11 @@ ** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html]. ** ** To address the performance and cache coherency issues, proxy file locking ** changes the way database access is controlled by limiting access to a ** single host at a time and moving file locks off of the database file -** and onto a proxy file on the local file system. +** and onto a proxy file on the local file system. ** ** ** Using proxy locks ** ----------------- ** @@ -45590,23 +36782,23 @@ ** a proxy path based on the user's temp dir ** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the ** actual proxy file name is generated from the name and path of the ** database file. For example: ** -** For database path "/Users/me/foo.db" +** For database path "/Users/me/foo.db" ** The lock path will be "/sqliteplocks/_Users_me_foo.db:auto:") ** ** Once a lock proxy is configured for a database connection, it can not ** be removed, however it may be switched to a different proxy path via ** the above APIs (assuming the conch file is not being held by another -** connection or process). +** connection or process). ** ** ** How proxy locking works ** ----------------------- ** -** Proxy file locking relies primarily on two new supporting files: +** Proxy file locking relies primarily on two new supporting files: ** ** * conch file to limit access to the database file to a single host ** at a time ** ** * proxy file to act as a proxy for the advisory locks normally @@ -45629,15 +36821,15 @@ ** normally taken on the database file. This allows for safe sharing ** of the database file for multiple readers and writers on the same ** host (the conch ensures that they all use the same local lock file). ** ** Requesting the lock proxy does not immediately take the conch, it is -** only taken when the first request to lock database file is made. +** only taken when the first request to lock database file is made. ** This matches the semantics of the traditional locking behavior, where ** opening a connection to a database file does not take a lock on it. -** The shared lock and an open file descriptor are maintained until -** the connection to the database is closed. +** The shared lock and an open file descriptor are maintained until +** the connection to the database is closed. ** ** The proxy file and the lock file are never deleted so they only need ** to be created the first time they are used. ** ** Configuration options @@ -45647,11 +36839,11 @@ ** ** Database files accessed on non-local file systems are ** automatically configured for proxy locking, lock files are ** named automatically using the same logic as ** PRAGMA lock_proxy_file=":auto:" -** +** ** SQLITE_PROXY_DEBUG ** ** Enables the logging of error messages during host id file ** retrieval and creation ** @@ -45662,27 +36854,27 @@ ** ** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS ** ** Permissions to use when creating a directory for storing the ** lock proxy files, only used when LOCKPROXYDIR is not set. -** -** +** +** ** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING, ** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will ** force proxy locking to be used for every database file opened, and 0 ** will force automatic proxy locking to be disabled for all database ** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or ** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING). */ /* -** Proxy locking is only available on MacOSX +** Proxy locking is only available on MacOSX */ #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE /* -** The proxyLockingContext has the path and file structures for the remote +** The proxyLockingContext has the path and file structures for the remote ** and local proxy files in it */ typedef struct proxyLockingContext proxyLockingContext; struct proxyLockingContext { unixFile *conchFile; /* Open conch file */ @@ -45694,14 +36886,14 @@ int nFails; /* Number of conch taking failures */ void *oldLockingContext; /* Original lockingcontext to restore on close */ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ }; -/* -** The proxy lock file path for the database at dbPath is written into lPath, +/* +** The proxy lock file path for the database at dbPath is written into lPath, ** which must point to valid, writable memory large enough for a maxLen length -** file path. +** file path. */ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ int len; int dbLen; int i; @@ -45714,21 +36906,21 @@ if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", lPath, errno, osGetpid(0))); return SQLITE_IOERR_LOCK; } - len = strlcat(lPath, "sqliteplocks", maxLen); + len = strlcat(lPath, "sqliteplocks", maxLen); } # else len = strlcpy(lPath, "/tmp/", maxLen); # endif #endif if( lPath[len-1]!='/' ){ len = strlcat(lPath, "/", maxLen); } - + /* transform the db path to a unique cache name */ dbLen = (int)strlen(dbPath); for( i=0; i 0) ){ /* only mkdir if leaf dir != "." or "/" or ".." */ - if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') + if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){ buf[i]='\0'; if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ int err=errno; if( err!=EEXIST ) { @@ -45788,11 +36980,11 @@ int islockfile /* if non zero missing dirs will be created */ ) { int fd = -1; unixFile *pNew; int rc = SQLITE_OK; - int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW; + int openFlags = O_RDWR | O_CREAT; sqlite3_vfs dummyVfs; int terrno = 0; UnixUnusedFd *pUnused = NULL; /* 1. first try to open/create the file @@ -45818,11 +37010,11 @@ fd = robust_open(path, openFlags, 0); } } } if( fd<0 ){ - openFlags = O_RDONLY | O_NOFOLLOW; + openFlags = O_RDONLY; fd = robust_open(path, openFlags, 0); terrno = errno; } if( fd<0 ){ if( islockfile ){ @@ -45829,17 +37021,17 @@ return SQLITE_BUSY; } switch (terrno) { case EACCES: return SQLITE_PERM; - case EIO: + case EIO: return SQLITE_IOERR_LOCK; /* even though it is the conch */ default: return SQLITE_CANTOPEN_BKPT; } } - + pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); if( pNew==NULL ){ rc = SQLITE_NOMEM_BKPT; goto end_create_proxy; } @@ -45848,18 +37040,18 @@ memset(&dummyVfs, 0, sizeof(dummyVfs)); dummyVfs.pAppData = (void*)&autolockIoFinder; dummyVfs.zName = "dummy"; pUnused->fd = fd; pUnused->flags = openFlags; - pNew->pPreallocatedUnused = pUnused; - + pNew->pUnused = pUnused; + rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); if( rc==SQLITE_OK ){ *ppFile = pNew; return SQLITE_OK; } -end_create_proxy: +end_create_proxy: robust_close(pNew, fd, __LINE__); sqlite3_free(pNew); sqlite3_free(pUnused); return rc; } @@ -45869,22 +37061,22 @@ SQLITE_API int sqlite3_hostid_num = 0; #endif #define PROXY_HOSTIDLEN 16 /* conch file host id length */ -#if HAVE_GETHOSTUUID +#ifdef HAVE_GETHOSTUUID /* Not always defined in the headers as it ought to be */ extern int gethostuuid(uuid_t id, const struct timespec *wait); #endif -/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN +/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN ** bytes of writable memory. */ static int proxyGetHostID(unsigned char *pHostID, int *pError){ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); memset(pHostID, 0, PROXY_HOSTIDLEN); -#if HAVE_GETHOSTUUID +#ifdef HAVE_GETHOSTUUID { struct timespec timeout = {1, 0}; /* 1 sec timeout */ if( gethostuuid(pHostID, &timeout) ){ int err = errno; if( pError ){ @@ -45900,11 +37092,11 @@ /* simulate multiple hosts by creating unique hostid file paths */ if( sqlite3_hostid_num != 0){ pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF)); } #endif - + return SQLITE_OK; } /* The conch file contains the header, host id and lock file path */ @@ -45911,18 +37103,18 @@ #define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */ #define PROXY_HEADERLEN 1 /* conch file header length */ #define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN) #define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN) -/* -** Takes an open conch file, copies the contents to a new path and then moves +/* +** Takes an open conch file, copies the contents to a new path and then moves ** it back. The newly created file's file descriptor is assigned to the -** conch file structure and finally the original conch file descriptor is +** conch file structure and finally the original conch file descriptor is ** closed. Returns zero if successful. */ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *conchFile = pCtx->conchFile; char tPath[MAXPATHLEN]; char buf[PROXY_MAXCONCHLEN]; char *cPath = pCtx->conchFilePath; size_t readLen = 0; @@ -45932,11 +37124,11 @@ int rc = -1; UNUSED_PARAMETER(myHostID); /* create a new path by replace the trailing '-conch' with '-break' */ pathLen = strlcpy(tPath, cPath, MAXPATHLEN); - if( pathLen>MAXPATHLEN || pathLen<6 || + if( pathLen>MAXPATHLEN || pathLen<6 || (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen); goto end_breaklock; } /* read the conch content */ @@ -45944,11 +37136,11 @@ if( readLenlockingContext; + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *conchFile = pCtx->conchFile; int rc = SQLITE_OK; int nTries = 0; struct timespec conchModTime; - + memset(&conchModTime, 0, sizeof(conchModTime)); do { rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); nTries ++; if( rc==SQLITE_BUSY ){ /* If the lock failed (busy): - * 1st try: get the mod time of the conch, wait 0.5s and try again. - * 2nd try: fail if the mod time changed or host id is different, wait + * 1st try: get the mod time of the conch, wait 0.5s and try again. + * 2nd try: fail if the mod time changed or host id is different, wait * 10 sec and try again * 3rd try: break the lock unless the mod time has changed. */ struct stat buf; if( osFstat(conchFile->h, &buf) ){ storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } - + if( nTries==1 ){ conchModTime = buf.st_mtimespec; - unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/ - continue; + usleep(500000); /* wait 0.5 sec and try the lock again*/ + continue; } assert( nTries>1 ); - if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || + if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ return SQLITE_BUSY; } - - if( nTries==2 ){ + + if( nTries==2 ){ char tBuf[PROXY_MAXCONCHLEN]; int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; @@ -46029,14 +37221,14 @@ } }else{ /* don't break the lock on short read or a version mismatch */ return SQLITE_BUSY; } - unixSleep(0,10000000); /* wait 10 sec and try the lock again */ - continue; + usleep(10000000); /* wait 10 sec and try the lock again */ + continue; } - + assert( nTries==3 ); if( 0==proxyBreakConchLock(pFile, myHostID) ){ rc = SQLITE_OK; if( lockType==EXCLUSIVE_LOCK ){ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); @@ -46045,23 +37237,23 @@ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); } } } } while( rc==SQLITE_BUSY && nTries<3 ); - + return rc; } -/* Takes the conch by taking a shared lock and read the contents conch, if -** lockPath is non-NULL, the host ID and lock file path must match. A NULL -** lockPath means that the lockPath in the conch file will be used if the -** host IDs match, or a new lock path will be generated automatically +/* Takes the conch by taking a shared lock and read the contents conch, if +** lockPath is non-NULL, the host ID and lock file path must match. A NULL +** lockPath means that the lockPath in the conch file will be used if the +** host IDs match, or a new lock path will be generated automatically ** and written to the conch file. */ static int proxyTakeConch(unixFile *pFile){ - proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; - + proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; + if( pCtx->conchHeld!=0 ){ return SQLITE_OK; }else{ unixFile *conchFile = pCtx->conchFile; uuid_t myHostID; @@ -46073,11 +37265,11 @@ int createConch = 0; int hostIdMatch = 0; int readLen = 0; int tryOldLockPath = 0; int forceNewLockPath = 0; - + OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h, (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), osGetpid(0))); rc = proxyGetHostID(myHostID, &pError); @@ -46094,34 +37286,34 @@ if( readLen<0 ){ /* I/O error: lastErrno set by seekAndRead */ storeLastErrno(pFile, conchFile->lastErrno); rc = SQLITE_IOERR_READ; goto end_takeconch; - }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || + }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || readBuf[0]!=(char)PROXY_CONCHVERSION ){ - /* a short read or version format mismatch means we need to create a new - ** conch file. + /* a short read or version format mismatch means we need to create a new + ** conch file. */ createConch = 1; } /* if the host id matches and the lock path already exists in the conch - ** we'll try to use the path there, if we can't open that path, we'll - ** retry with a new auto-generated path + ** we'll try to use the path there, if we can't open that path, we'll + ** retry with a new auto-generated path */ do { /* in case we need to try again for an :auto: named lock file */ if( !createConch && !forceNewLockPath ){ - hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, + hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); /* if the conch has data compare the contents */ if( !pCtx->lockProxyPath ){ /* for auto-named local lock file, just check the host ID and we'll ** use the local lock file path that's already in there */ if( hostIdMatch ){ size_t pathLen = (readLen - PROXY_PATHINDEX); - + if( pathLen>=MAXPATHLEN ){ pathLen=MAXPATHLEN-1; } memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen); lockPath[pathLen] = 0; @@ -46133,27 +37325,27 @@ }else if( hostIdMatch && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX], readLen-PROXY_PATHINDEX) ){ /* conch host and lock path match */ - goto end_takeconch; + goto end_takeconch; } } - + /* if the conch isn't writable and doesn't match, we can't take it */ if( (conchFile->openFlags&O_RDWR) == 0 ){ rc = SQLITE_BUSY; goto end_takeconch; } - + /* either the conch didn't match or we need to create a new one */ if( !pCtx->lockProxyPath ){ proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); tempLockPath = lockPath; /* create a copy of the lock path _only_ if the conch is taken */ } - + /* update conch with host and path (this will fail if other process ** has a shared lock already), if the host id matches, use the big ** stick. */ futimes(conchFile->h, NULL); @@ -46160,20 +37352,20 @@ if( hostIdMatch && !createConch ){ if( conchFile->pInode && conchFile->pInode->nShared>1 ){ /* We are trying for an exclusive lock but another thread in this ** same process is still holding a shared lock. */ rc = SQLITE_BUSY; - } else { + } else { rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } }else{ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } if( rc==SQLITE_OK ){ char writeBuffer[PROXY_MAXCONCHLEN]; int writeSize = 0; - + writeBuffer[0] = (char)PROXY_CONCHVERSION; memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); if( pCtx->lockProxyPath!=NULL ){ strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); @@ -46182,12 +37374,12 @@ } writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); robust_ftruncate(conchFile->h, writeSize); rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); full_fsync(conchFile->h,0,0); - /* If we created a new conch file (not just updated the contents of a - ** valid conch file), try to match the permissions of the database + /* If we created a new conch file (not just updated the contents of a + ** valid conch file), try to match the permissions of the database */ if( rc==SQLITE_OK && createConch ){ struct stat buf; int err = osFstat(pFile->h, &buf); if( err==0 ){ @@ -46207,18 +37399,18 @@ } else { fprintf(stderr, "fchmod %o SUCCEDED\n",cmode); } }else{ int code = errno; - fprintf(stderr, "STAT FAILED[%d] with %d %s\n", + fprintf(stderr, "STAT FAILED[%d] with %d %s\n", err, code, strerror(code)); #endif } } } conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); - + end_takeconch: OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h)); if( rc==SQLITE_OK && pFile->openFlags ){ int fd; if( pFile->h>=0 ){ @@ -46237,11 +37429,11 @@ if( rc==SQLITE_OK && !pCtx->lockProxy ){ char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath; rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1); if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){ /* we couldn't create the proxy lock file with the old lock file path - ** so try again via auto-naming + ** so try again via auto-naming */ forceNewLockPath = 1; tryOldLockPath = 0; continue; /* go back to the do {} while start point, try again */ } @@ -46257,11 +37449,11 @@ } } } if( rc==SQLITE_OK ){ pCtx->conchHeld = 1; - + if( pCtx->lockProxy->pMethod == &afpIoMethods ){ afpLockingContext *afpCtx; afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext; afpCtx->dbPath = pCtx->lockProxyPath; } @@ -46269,11 +37461,11 @@ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); } OSTRACE(("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed")); return rc; - } while (1); /* in case we need to retry the :auto: lock file - + } while (1); /* in case we need to retry the :auto: lock file - ** we should never get here except via the 'continue' call. */ } } /* @@ -46285,11 +37477,11 @@ unixFile *conchFile; /* Name of the conch file */ pCtx = (proxyLockingContext *)pFile->lockingContext; conchFile = pCtx->conchFile; OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h, - (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), + (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), osGetpid(0))); if( pCtx->conchHeld>0 ){ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); } pCtx->conchHeld = 0; @@ -46313,17 +37505,17 @@ int i; /* Loop counter */ int len = (int)strlen(dbPath); /* Length of database filename - dbPath */ char *conchPath; /* buffer in which to construct conch name */ /* Allocate space for the conch filename and initialize the name to - ** the name of the original database file. */ + ** the name of the original database file. */ *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); if( conchPath==0 ){ return SQLITE_NOMEM_BKPT; } memcpy(conchPath, dbPath, len+1); - + /* now insert a "." before the last / character */ for( i=(len-1); i>=0; i-- ){ if( conchPath[i]=='/' ){ i++; break; @@ -46342,20 +37534,20 @@ return SQLITE_OK; } /* Takes a fully configured proxy locking-style unix file and switches -** the local lock file path +** the local lock file path */ static int switchLockProxyPath(unixFile *pFile, const char *path) { proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; char *oldPath = pCtx->lockProxyPath; int rc = SQLITE_OK; if( pFile->eFileLock!=NO_LOCK ){ return SQLITE_BUSY; - } + } /* nothing to do if the path is NULL, :auto: or matches the existing path */ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") || (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){ return SQLITE_OK; @@ -46369,11 +37561,11 @@ sqlite3_free(lockProxy); } sqlite3_free(oldPath); pCtx->lockProxyPath = sqlite3DbStrDup(0, path); } - + return rc; } /* ** pFile is a file that has been opened by a prior xOpen call. dbPath @@ -46383,11 +37575,11 @@ ** int dbPath. */ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ #if defined(__APPLE__) if( pFile->pMethod == &afpIoMethods ){ - /* afp style keeps a reference to the db path in the filePath field + /* afp style keeps a reference to the db path in the filePath field ** of the struct */ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); } else @@ -46404,33 +37596,33 @@ } return SQLITE_OK; } /* -** Takes an already filled in unix file and alters it so all file locking +** Takes an already filled in unix file and alters it so all file locking ** will be performed on the local proxy lock file. The following fields -** are preserved in the locking context so that they can be restored and +** are preserved in the locking context so that they can be restored and ** the unix structure properly cleaned up at close time: ** ->lockingContext ** ->pMethod */ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { proxyLockingContext *pCtx; char dbPath[MAXPATHLEN+1]; /* Name of the database file */ char *lockPath=NULL; int rc = SQLITE_OK; - + if( pFile->eFileLock!=NO_LOCK ){ return SQLITE_BUSY; } proxyGetDbPathForUnixFile(pFile, dbPath); if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){ lockPath=NULL; }else{ lockPath=(char *)path; } - + OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h, (lockPath ? lockPath : ":auto:"), osGetpid(0))); pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ @@ -46460,11 +37652,11 @@ if( goLockless ){ pCtx->conchHeld = -1; /* read only FS/ lockless */ rc = SQLITE_OK; } } - } + } if( rc==SQLITE_OK && lockPath ){ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); } if( rc==SQLITE_OK ){ @@ -46472,24 +37664,24 @@ if( pCtx->dbPath==NULL ){ rc = SQLITE_NOMEM_BKPT; } } if( rc==SQLITE_OK ){ - /* all memory is allocated, proxys are created and assigned, + /* all memory is allocated, proxys are created and assigned, ** switch the locking context and pMethod then return. */ pCtx->oldLockingContext = pFile->lockingContext; pFile->lockingContext = pCtx; pCtx->pOldMethod = pFile->pMethod; pFile->pMethod = &proxyIoMethods; }else{ - if( pCtx->conchFile ){ + if( pCtx->conchFile ){ pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile); sqlite3_free(pCtx->conchFile); } sqlite3DbFree(0, pCtx->lockProxyPath); - sqlite3_free(pCtx->conchFilePath); + sqlite3_free(pCtx->conchFilePath); sqlite3_free(pCtx); } OSTRACE(("TRANSPROXY %d %s\n", pFile->h, (rc==SQLITE_OK ? "ok" : "failed"))); return rc; @@ -46523,23 +37715,23 @@ int isProxyStyle = (pFile->pMethod == &proxyIoMethods); if( pArg==NULL || (const char *)pArg==0 ){ if( isProxyStyle ){ /* turn off proxy locking - not supported. If support is added for ** switching proxy locking mode off then it will need to fail if - ** the journal mode is WAL mode. + ** the journal mode is WAL mode. */ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; }else{ /* turn off proxy locking - already off - NOOP */ rc = SQLITE_OK; } }else{ const char *proxyPath = (const char *)pArg; if( isProxyStyle ){ - proxyLockingContext *pCtx = + proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; - if( !strcmp(pArg, ":auto:") + if( !strcmp(pArg, ":auto:") || (pCtx->lockProxyPath && !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN)) ){ rc = SQLITE_OK; }else{ @@ -46554,11 +37746,11 @@ } default: { assert( 0 ); /* The call assures that only valid opcodes are sent */ } } - /*NOTREACHED*/ assert(0); + /*NOTREACHED*/ return SQLITE_ERROR; } /* ** Within this division (the proxying locking implementation) the procedures @@ -46660,11 +37852,11 @@ unixFile *pFile = (unixFile*)id; proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *lockProxy = pCtx->lockProxy; unixFile *conchFile = pCtx->conchFile; int rc = SQLITE_OK; - + if( lockProxy ){ rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK); if( rc ) return rc; rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy); if( rc ) return rc; @@ -46697,11 +37889,11 @@ #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ /* ** The proxy locking style is intended for use with AFP filesystems. ** And since AFP is only supported on MacOSX, the proxy locking is also ** restricted to MacOSX. -** +** ** ******************* End of the proxy lock implementation ********************** ******************************************************************************/ /* @@ -46715,12 +37907,12 @@ ** This routine is called once during SQLite initialization and by a ** single thread. The memory allocation and mutex subsystems have not ** necessarily been initialized when this routine is called, and so they ** should not be used. */ -SQLITE_API int sqlite3_os_init(void){ - /* +SQLITE_API int sqlite3_os_init(void){ + /* ** The following macro defines an initializer for an sqlite3_vfs object. ** The name of the VFS is NAME. The pAppData is a pointer to a pointer ** to the "finder" function. (pAppData is a pointer to a pointer because ** silly C90 rules prohibit a void* from being cast to a function pointer ** and so we have to go through the intermediate pointer to avoid problems @@ -46732,11 +37924,11 @@ ** behaviors. See the division above that contains the IOMETHODS ** macro for addition information on finder-functions. ** ** Most finders simply return a pointer to a fixed sqlite3_io_methods ** object. But the "autolockIoFinder" available on MacOSX does a little - ** more than that; it looks at the filesystem type that hosts the + ** more than that; it looks at the filesystem type that hosts the ** database file and tries to choose an locking method appropriate for ** that filesystem time. */ #define UNIXVFS(VFSNAME, FINDER) { \ 3, /* iVersion */ \ @@ -46798,62 +37990,30 @@ }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==29 ); + assert( ArraySize(aSyscall)==28 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ -#ifdef SQLITE_DEFAULT_UNIX_VFS - sqlite3_vfs_register(&aVfs[i], - 0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS)); -#else sqlite3_vfs_register(&aVfs[i], i==0); -#endif - } -#ifdef SQLITE_OS_KV_OPTIONAL - sqlite3KvvfsInit(); -#endif - unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); - -#ifndef SQLITE_OMIT_WAL - /* Validate lock assumptions */ - assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */ - assert( UNIX_SHM_BASE==120 ); /* Start of locking area */ - /* Locks: - ** WRITE UNIX_SHM_BASE 120 - ** CKPT UNIX_SHM_BASE+1 121 - ** RECOVER UNIX_SHM_BASE+2 122 - ** READ-0 UNIX_SHM_BASE+3 123 - ** READ-1 UNIX_SHM_BASE+4 124 - ** READ-2 UNIX_SHM_BASE+5 125 - ** READ-3 UNIX_SHM_BASE+6 126 - ** READ-4 UNIX_SHM_BASE+7 127 - ** DMS UNIX_SHM_BASE+8 128 - */ - assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */ -#endif - - /* Initialize temp file dir array. */ - unixTempFileInit(); - - return SQLITE_OK; + } + return SQLITE_OK; } /* ** Shutdown the operating system interface. ** ** Some operating systems might need to do some cleanup in this routine, ** to release dynamically allocated objects. But not on unix. ** This routine is a no-op for unix. */ -SQLITE_API int sqlite3_os_end(void){ - unixBigLock = 0; - return SQLITE_OK; +SQLITE_API int sqlite3_os_end(void){ + return SQLITE_OK; } - + #endif /* SQLITE_OS_UNIX */ /************** End of os_unix.c *********************************************/ /************** Begin file os_win.c ******************************************/ /* @@ -46874,11 +38034,209 @@ #if SQLITE_OS_WIN /* This file is used for Windows only */ /* ** Include code that is common to all os_*.c files */ -/* #include "os_common.h" */ +/************** Include os_common.h in the middle of os_win.c ****************/ +/************** Begin file os_common.h ***************************************/ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of os_common.h ****************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(SQLITE_HWTIME_H) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in os_common.h ******************/ + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#if defined(SQLITE_TEST) +SQLITE_API extern int sqlite3_io_error_hit; +SQLITE_API extern int sqlite3_io_error_hardhit; +SQLITE_API extern int sqlite3_io_error_pending; +SQLITE_API extern int sqlite3_io_error_persist; +SQLITE_API extern int sqlite3_io_error_benign; +SQLITE_API extern int sqlite3_diskfull_pending; +SQLITE_API extern int sqlite3_diskfull; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif /* defined(SQLITE_TEST) */ + +/* +** When testing, keep a count of the number of open files. +*/ +#if defined(SQLITE_TEST) +SQLITE_API extern int sqlite3_open_file_count; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif /* defined(SQLITE_TEST) */ + +#endif /* !defined(_OS_COMMON_H_) */ + +/************** End of os_common.h *******************************************/ +/************** Continuing where we left off in os_win.c *********************/ /* ** Include the header file for the Windows VFS. */ /* #include "os_win.h" */ @@ -47140,11 +38498,12 @@ #endif #if SQLITE_MAX_MMAP_SIZE>0 int nFetchOut; /* Number of outstanding xFetch references */ HANDLE hMap; /* Handle for accessing memory mapping */ void *pMapRegion; /* Area memory mapped */ - sqlite3_int64 mmapSize; /* Size of mapped region */ + sqlite3_int64 mmapSize; /* Usable size of mapped region */ + sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ #endif }; /* @@ -47170,10 +38529,26 @@ */ #ifndef SQLITE_WIN32_DBG_BUF_SIZE # define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) #endif +/* + * The value used with sqlite3_win32_set_directory() to specify that + * the data directory should be changed. + */ +#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE +# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) +#endif + +/* + * The value used with sqlite3_win32_set_directory() to specify that + * the temporary directory should be changed. + */ +#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE +# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) +#endif + /* * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the * various Win32 API heap functions instead of our own. */ #ifdef SQLITE_WIN32_MALLOC @@ -48015,11 +39390,11 @@ }; /* End of the overrideable system calls */ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "win32" VFSes. Return SQLITE_OK upon successfully updating the +** "win32" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. */ static int winSetSystemCall( sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ @@ -48146,21 +39521,21 @@ ** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will ** be returned and no changes will be made to the Win32 native heap. */ SQLITE_API int sqlite3_win32_reset_heap(){ int rc; - MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */ + MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ - MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) + MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) - sqlite3_mutex_enter(pMainMtx); + sqlite3_mutex_enter(pMaster); sqlite3_mutex_enter(pMem); winMemAssertMagic(); if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ /* ** At this point, there should be no outstanding memory allocations on - ** the heap. Also, since both the main and memsys locks are currently + ** the heap. Also, since both the master and memsys locks are currently ** being held by us, no other function (i.e. from another thread) should ** be able to even access the heap. Attempt to destroy and recreate our ** isolated Win32 native heap now. */ assert( winMemGetHeap()!=NULL ); @@ -48179,11 +39554,11 @@ ** The Win32 native heap cannot be modified because it may be in use. */ rc = SQLITE_BUSY; } sqlite3_mutex_leave(pMem); - sqlite3_mutex_leave(pMainMtx); + sqlite3_mutex_leave(pMaster); return rc; } #endif /* SQLITE_WIN32_MALLOC */ /* @@ -48766,24 +40141,22 @@ #endif return winUtf8ToMbcs(zText, useAnsi); } /* -** This function is the same as sqlite3_win32_set_directory (below); however, -** it accepts a UTF-8 string. +** This function sets the data directory or the temporary directory based on +** the provided arguments. The type argument must be 1 in order to set the +** data directory or 2 in order to set the temporary directory. The zValue +** argument is the name of the directory to use. The return value will be +** SQLITE_OK if successful. */ -SQLITE_API int sqlite3_win32_set_directory8( - unsigned long type, /* Identifier for directory being set or reset */ - const char *zValue /* New value for directory being set or reset */ -){ +SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ char **ppDirectory = 0; - int rc; #ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); + int rc = sqlite3_initialize(); if( rc ) return rc; #endif - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ ppDirectory = &sqlite3_data_directory; }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ ppDirectory = &sqlite3_temp_directory; } @@ -48790,60 +40163,22 @@ assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ); assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); if( ppDirectory ){ - char *zCopy = 0; + char *zValueUtf8 = 0; if( zValue && zValue[0] ){ - zCopy = sqlite3_mprintf("%s", zValue); - if ( zCopy==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto set_directory8_done; + zValueUtf8 = winUnicodeToUtf8(zValue); + if ( zValueUtf8==0 ){ + return SQLITE_NOMEM_BKPT; } } sqlite3_free(*ppDirectory); - *ppDirectory = zCopy; - rc = SQLITE_OK; - }else{ - rc = SQLITE_ERROR; - } -set_directory8_done: - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - return rc; -} - -/* -** This function is the same as sqlite3_win32_set_directory (below); however, -** it accepts a UTF-16 string. -*/ -SQLITE_API int sqlite3_win32_set_directory16( - unsigned long type, /* Identifier for directory being set or reset */ - const void *zValue /* New value for directory being set or reset */ -){ - int rc; - char *zUtf8 = 0; - if( zValue ){ - zUtf8 = sqlite3_win32_unicode_to_utf8(zValue); - if( zUtf8==0 ) return SQLITE_NOMEM_BKPT; - } - rc = sqlite3_win32_set_directory8(type, zUtf8); - if( zUtf8 ) sqlite3_free(zUtf8); - return rc; -} - -/* -** This function sets the data directory or the temporary directory based on -** the provided arguments. The type argument must be 1 in order to set the -** data directory or 2 in order to set the temporary directory. The zValue -** argument is the name of the directory to use. The return value will be -** SQLITE_OK if successful. -*/ -SQLITE_API int sqlite3_win32_set_directory( - unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ -){ - return sqlite3_win32_set_directory16(type, zValue); + *ppDirectory = zValueUtf8; + return SQLITE_OK; + } + return SQLITE_ERROR; } /* ** The return value of winGetLastErrorMsg ** is zero if the error message fits in the buffer, or non-zero @@ -49595,11 +40930,11 @@ OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transferring + /* Deal with as much of this read request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", @@ -49673,11 +41008,11 @@ OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transferring + /* Deal with as much of this write request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", @@ -49766,33 +41101,10 @@ */ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ winFile *pFile = (winFile*)id; /* File handle object */ int rc = SQLITE_OK; /* Return code for this function */ DWORD lastErrno; -#if SQLITE_MAX_MMAP_SIZE>0 - sqlite3_int64 oldMmapSize; - if( pFile->nFetchOut>0 ){ - /* File truncation is a no-op if there are outstanding memory mapped - ** pages. This is because truncating the file means temporarily unmapping - ** the file, and that might delete memory out from under existing cursors. - ** - ** This can result in incremental vacuum not truncating the file, - ** if there is an active read cursor when the incremental vacuum occurs. - ** No real harm comes of this - the database file is not corrupted, - ** though some folks might complain that the file is bigger than it - ** needs to be. - ** - ** The only feasible work-around is to defer the truncation until after - ** all references to memory-mapped content are closed. That is doable, - ** but involves adding a few branches in the common write code path which - ** could slow down normal operations slightly. Hence, we have decided for - ** now to simply make transactions a no-op if there are pending reads. We - ** can maybe revisit this decision in the future. - */ - return SQLITE_OK; - } -#endif assert( pFile ); SimulateIOError(return SQLITE_IOERR_TRUNCATE); OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); @@ -49804,19 +41116,10 @@ */ if( pFile->szChunk>0 ){ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; } -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->pMapRegion ){ - oldMmapSize = pFile->mmapSize; - }else{ - oldMmapSize = 0; - } - winUnmapfile(pFile); -#endif - /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ if( winSeekFile(pFile, nByte) ){ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, "winTruncate1", pFile->zPath); }else if( 0==osSetEndOfFile(pFile->h) && @@ -49825,16 +41128,16 @@ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, "winTruncate2", pFile->zPath); } #if SQLITE_MAX_MMAP_SIZE>0 - if( rc==SQLITE_OK && oldMmapSize>0 ){ - if( oldMmapSize>nByte ){ - winMapfile(pFile, -1); - }else{ - winMapfile(pFile, oldMmapSize); - } + /* If the file was truncated to a size smaller than the currently + ** mapped region, reduce the effective mapping size as well. SQLite will + ** use read() and write() to access data beyond this point from now on. + */ + if( pFile->pMapRegion && nBytemmapSize ){ + pFile->mmapSize = nByte; } #endif OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); @@ -49842,11 +41145,11 @@ } #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test -** that syncs and fullsyncs are occurring at the right times. +** that syncs and fullsyncs are occuring at the right times. */ SQLITE_API int sqlite3_sync_count = 0; SQLITE_API int sqlite3_fullsync_count = 0; #endif @@ -50199,11 +41502,11 @@ /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); - (void)winUnlockReadLock(pFile); + res = winUnlockReadLock(pFile); res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -50365,11 +41668,10 @@ } /* Forward references to VFS helper methods used for temporary files */ static int winGetTempname(sqlite3_vfs *, char **); static int winIsDir(const void *); -static BOOL winIsLongPathPrefix(const char *); static BOOL winIsDriveLetterAndColon(const char *); /* ** Control and query of the open file handle. */ @@ -50455,15 +41757,10 @@ OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n", hOldFile, pFile->h)); return SQLITE_OK; } #endif - case SQLITE_FCNTL_NULL_IO: { - (void)osCloseHandle(pFile->h); - pFile->h = NULL; - return SQLITE_OK; - } case SQLITE_FCNTL_TEMPFILENAME: { char *zTFile = 0; int rc = winGetTempname(pFile->pVfs, &zTFile); if( rc==SQLITE_OK ){ *(char**)pArg = zTFile; @@ -50476,18 +41773,10 @@ i64 newLimit = *(i64*)pArg; int rc = SQLITE_OK; 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; if( pFile->mmapSize>0 ){ winUnmapfile(pFile); @@ -50521,11 +41810,11 @@ /* ** Return a vector of device characteristics. */ static int winDeviceCharacteristics(sqlite3_file *id){ winFile *p = (winFile*)id; - return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ | + return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); } /* ** Windows will only let you create file view mappings @@ -50548,20 +41837,19 @@ ** ** winShmEnterMutex() ** assert( winShmMutexHeld() ); ** winShmLeaveMutex() */ -static sqlite3_mutex *winBigLock = 0; static void winShmEnterMutex(void){ - sqlite3_mutex_enter(winBigLock); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); } static void winShmLeaveMutex(void){ - sqlite3_mutex_leave(winBigLock); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); } #ifndef NDEBUG static int winShmMutexHeld(void) { - return sqlite3_mutex_held(winBigLock); + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); } #endif /* ** Object used to represent a single file opened and mmapped to provide @@ -50591,13 +41879,10 @@ char *zFilename; /* Name of the file */ winFile hFile; /* File handle from winOpen */ 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; } *aRegion; DWORD lastErrno; /* The Windows errno from the last I/O error */ @@ -50660,11 +41945,11 @@ int nByte /* Number of bytes to lock or unlock */ ){ int rc = 0; /* Result code form Lock/UnlockFileEx() */ /* Access to the winShmNode object is serialized by the caller */ - assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) ); + assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", pFile->hFile.h, lockType, ofst, nByte)); /* Release/Acquire the system-level lock */ @@ -50741,53 +42026,22 @@ pp = &p->pNext; } } } -/* -** 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. ** ** When opening a new shared-memory file, if no other instances of that ** file are currently open, in this process or in other processes, then ** the file must be truncated to zero length or have its header cleared. */ static int winOpenSharedMemory(winFile *pDbFd){ struct winShm *p; /* The connection to be opened */ - winShmNode *pShmNode = 0; /* The underlying mmapped file */ - int rc = SQLITE_OK; /* Result code */ - winShmNode *pNew; /* Newly allocated winShmNode */ + struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ + int rc; /* Result code */ + struct winShmNode *pNew; /* Newly allocated winShmNode */ int nName; /* Size of zName in bytes */ assert( pDbFd->pShm==0 ); /* Not previously opened */ /* Allocate space for the new sqlite3_shm object. Also speculatively @@ -50816,13 +42070,10 @@ if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; } 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; pShmNode->pNext = winShmNodeList; winShmNodeList = pShmNode; @@ -50833,27 +42084,34 @@ rc = SQLITE_IOERR_NOMEM_BKPT; goto shm_open_err; } } - 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); + 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 ){ goto shm_open_err; } - if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1; - rc = winLockSharedMemory(pShmNode); - if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; + /* Check to see if another process is holding the dead-man switch. + ** If not, truncate the file to zero length. + */ + if( winShmSystemLock(pShmNode, 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; } /* Make the new connection a child of the winShmNode */ p->pShmNode = pShmNode; #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) @@ -50872,11 +42130,11 @@ */ sqlite3_mutex_enter(pShmNode->mutex); p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; sqlite3_mutex_leave(pShmNode->mutex); - return rc; + return SQLITE_OK; /* Jump here on any error */ shm_open_err: winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ @@ -50938,18 +42196,14 @@ int flags /* What to do with the lock */ ){ winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ winShm *p = pDbFd->pShm; /* The shared memory being locked */ winShm *pX; /* For looping over all siblings */ - winShmNode *pShmNode; + winShmNode *pShmNode = p->pShmNode; int rc = SQLITE_OK; /* Result code */ u16 mask; /* Mask of locks to take or release */ - if( p==0 ) return SQLITE_IOERR_SHMLOCK; - pShmNode = p->pShmNode; - if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; - assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); assert( n>=1 ); assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) @@ -51080,28 +42334,20 @@ void volatile **pp /* OUT: Mapped memory */ ){ 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 ){ rc = winOpenSharedMemory(pDbFd); if( rc!=SQLITE_OK ) return rc; pShm = pDbFd->pShm; - assert( pShm!=0 ); } pShmNode = pShm->pShmNode; sqlite3_mutex_enter(pShmNode->mutex); - if( pShmNode->isUnlocked ){ - rc = winLockSharedMemory(pShmNode); - if( rc!=SQLITE_OK ) goto shmpage_out; - pShmNode->isUnlocked = 0; - } assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); if( pShmNode->nRegion<=iRegion ){ struct ShmRegion *apNew; /* New aRegion[] array */ int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ @@ -51144,44 +42390,39 @@ rc = SQLITE_IOERR_NOMEM_BKPT; goto shmpage_out; } 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, protect, nByte, NULL + NULL, PAGE_READWRITE, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_WIDE) hMap = osCreateFileMappingW(pShmNode->hFile.h, - NULL, protect, 0, nByte, NULL + NULL, PAGE_READWRITE, 0, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA hMap = osCreateFileMappingA(pShmNode->hFile.h, - NULL, protect, 0, nByte, NULL + NULL, PAGE_READWRITE, 0, nByte, NULL ); #endif OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", osGetCurrentProcessId(), pShmNode->nRegion, nByte, hMap ? "ok" : "failed")); if( hMap ){ int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; #if SQLITE_OS_WINRT - pMap = osMapViewOfFileFromApp(hMap, flags, + pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, iOffset - iOffsetShift, szRegion + iOffsetShift ); #else - pMap = osMapViewOfFile(hMap, flags, + pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, iOffset - iOffsetShift, szRegion + iOffsetShift ); #endif OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", osGetCurrentProcessId(), pShmNode->nRegion, iOffset, @@ -51208,11 +42449,10 @@ char *p = (char *)pShmNode->aRegion[iRegion].pMap; *pp = (void *)&p[iOffsetShift]; }else{ *pp = 0; } - if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; sqlite3_mutex_leave(pShmNode->mutex); return rc; } #else @@ -51227,13 +42467,13 @@ */ #if SQLITE_MAX_MMAP_SIZE>0 static int winUnmapfile(winFile *pFile){ assert( pFile!=0 ); OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " - "mmapSize=%lld, mmapSizeMax=%lld\n", + "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, - pFile->mmapSize, pFile->mmapSizeMax)); + pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); if( pFile->pMapRegion ){ if( !osUnmapViewOfFile(pFile->pMapRegion) ){ pFile->lastErrno = osGetLastError(); OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, " "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile, @@ -51241,10 +42481,11 @@ return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, "winUnmapfile1", pFile->zPath); } pFile->pMapRegion = 0; pFile->mmapSize = 0; + pFile->mmapSizeActual = 0; } if( pFile->hMap!=NULL ){ if( !osCloseHandle(pFile->hMap) ){ pFile->lastErrno = osGetLastError(); OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n", @@ -51351,10 +42592,11 @@ osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); return SQLITE_OK; } pFd->pMapRegion = pNew; pFd->mmapSize = nMap; + pFd->mmapSizeActual = nMap; } OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", osGetCurrentProcessId(), pFd)); return SQLITE_OK; @@ -51382,25 +42624,19 @@ OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", osGetCurrentProcessId(), fd, iOff, nAmt, pp)); #if SQLITE_MAX_MMAP_SIZE>0 if( pFd->mmapSizeMax>0 ){ - /* Ensure that there is always at least a 256 byte buffer of addressable - ** memory following the returned page. If the database is corrupt, - ** SQLite may overread the page slightly (in practice only a few bytes, - ** but 256 is safe, round, number). */ - const int nEofBuffer = 256; if( pFd->pMapRegion==0 ){ int rc = winMapfile(pFd, -1); if( rc!=SQLITE_OK ){ OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); return rc; } } - if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ - assert( pFd->pMapRegion!=0 ); + if( pFd->mmapSize >= iOff+nAmt ){ *pp = &((u8 *)pFd->pMapRegion)[iOff]; pFd->nFetchOut++; } } #endif @@ -51590,23 +42826,10 @@ } } return 0; } -/* -** If sqlite3_temp_directory is defined, take the mutex and return true. -** -** If sqlite3_temp_directory is NULL (undefined), omit the mutex and -** return false. -*/ -static int winTempDirDefined(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - if( sqlite3_temp_directory!=0 ) return 1; - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); - return 0; -} - /* ** Create a temporary file name and store the resulting pointer into pzBuf. ** The pointer returned in pzBuf must be freed via sqlite3_free(). */ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ @@ -51613,11 +42836,10 @@ static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; size_t i, j; - DWORD pid; int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX); int nMax, nBuf, nDir, nLen; char *zBuf; /* It's odd to simulate an io-error here, but really this is just @@ -51640,27 +42862,24 @@ ** has been explicitly set by the application; otherwise, use the one ** configured by the operating system. */ nDir = nMax - (nPre + 15); assert( nDir>0 ); - if( winTempDirDefined() ){ + if( sqlite3_temp_directory ){ int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); if( nDirLen>0 ){ if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ nDirLen++; } if( nDirLen>nDir ){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); } sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); } - #if defined(__CYGWIN__) else{ static const char *azDirs[] = { 0, /* getenv("SQLITE_TMPDIR") */ 0, /* getenv("TMPDIR") */ @@ -51826,14 +43045,11 @@ sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX); j = sqlite3Strlen30(zBuf); sqlite3_randomness(15, &zBuf[j]); - pid = osGetCurrentProcessId(); for(i=0; i<15; i++, j++){ - zBuf[j] += pid & 0xff; - pid >>= 8; zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; zBuf[j+1] = 0; *pzBuf = zBuf; @@ -51869,18 +43085,10 @@ #endif } 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. */ static int winOpen( sqlite3_vfs *pVfs, /* Used to get maximum path length and AppData */ @@ -51909,11 +43117,11 @@ */ char *zTmpname = 0; /* For temporary filename, if necessary. */ int rc = SQLITE_OK; /* Function Return Code */ #if !defined(NDEBUG) || SQLITE_OS_WINCE - int eType = flags&0x0FFF00; /* Type of file to open */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ #endif int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); @@ -51920,11 +43128,11 @@ int isReadonly = (flags & SQLITE_OPEN_READONLY); int isReadWrite = (flags & SQLITE_OPEN_READWRITE); #ifndef NDEBUG int isOpenJournal = (isCreate && ( - eType==SQLITE_OPEN_SUPER_JOURNAL + eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL )); #endif @@ -51941,21 +43149,21 @@ assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); assert(isCreate==0 || isReadWrite); assert(isExclusive==0 || isCreate); assert(isDelete==0 || isCreate); - /* The main DB, main journal, WAL file and super-journal are never + /* The main DB, main journal, WAL file and master journal are never ** automatically deleted. Nor are they ever temporary files. */ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL ); + assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); /* Assert that the upper layer has set one of the "file-type" flags. */ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL - || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); assert( pFile!=0 ); memset(pFile, 0, sizeof(winFile)); @@ -52023,15 +43231,11 @@ }else{ /* Opens a file, only if it exists. */ dwCreationDisposition = OPEN_EXISTING; } - if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){ - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - }else{ - dwShareMode = 0; - } + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; if( isDelete ){ #if SQLITE_OS_WINCE dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; isTemp = 1; @@ -52057,80 +43261,59 @@ dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; extendedParameters.lpSecurityAttributes = NULL; extendedParameters.hTemplateFile = NULL; - do{ - h = osCreateFile2((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, - dwCreationDisposition, - &extendedParameters); - if( h!=INVALID_HANDLE_VALUE ) break; - if( isReadWrite ){ - int rc2, isRO = 0; - sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); - sqlite3EndBenignMalloc(); - if( rc2==SQLITE_OK && isRO ) break; - } - }while( winRetryIoerr(&cnt, &lastErrno) ); + while( (h = osCreateFile2((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + &extendedParameters))==INVALID_HANDLE_VALUE && + winRetryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } #else - 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, zUtf8Name, SQLITE_ACCESS_READ, &isRO); - sqlite3EndBenignMalloc(); - if( rc2==SQLITE_OK && isRO ) break; - } - }while( winRetryIoerr(&cnt, &lastErrno) ); + while( (h = osCreateFileW((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL))==INVALID_HANDLE_VALUE && + winRetryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } #endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ - 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, zUtf8Name, SQLITE_ACCESS_READ, &isRO); - sqlite3EndBenignMalloc(); - if( rc2==SQLITE_OK && isRO ) break; - } - }while( winRetryIoerr(&cnt, &lastErrno) ); + while( (h = osCreateFileA((LPCSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL))==INVALID_HANDLE_VALUE && + winRetryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } } #endif winLogIoerr(cnt, __LINE__); OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, 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 ){ return winOpen(pVfs, zName, id, ((flags|SQLITE_OPEN_READONLY) & ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags); }else{ - pFile->lastErrno = lastErrno; - winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); return SQLITE_CANTOPEN_BKPT; } } if( pOutFlags ){ @@ -52167,27 +43350,26 @@ { sqlite3_free(zConverted); } sqlite3_free(zTmpname); - id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod; + pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod; pFile->pVfs = pVfs; pFile->h = h; if( isReadonly ){ pFile->ctrlFlags |= WINFILE_RDONLY; } - if( (flags & SQLITE_OPEN_MAIN_DB) - && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) - ){ + if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pFile->ctrlFlags |= WINFILE_PSOW; } pFile->lastErrno = NO_ERROR; pFile->zPath = zName; #if SQLITE_MAX_MMAP_SIZE>0 pFile->hMap = NULL; pFile->pMapRegion = 0; pFile->mmapSize = 0; + pFile->mmapSizeActual = 0; pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; #endif OpenCounter(+1); return rc; @@ -52327,17 +43509,10 @@ SimulateIOError( return SQLITE_IOERR_ACCESS; ); OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", zFilename, flags, pResOut)); - if( zFilename==0 ){ - *pResOut = 0; - OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", - zFilename, pResOut, *pResOut)); - return SQLITE_OK; - } - zConverted = winConvertFromUtf8Filename(zFilename); if( zConverted==0 ){ OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); return SQLITE_IOERR_NOMEM_BKPT; } @@ -52392,21 +43567,10 @@ OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", zFilename, pResOut, *pResOut)); return SQLITE_OK; } -/* -** Returns non-zero if the specified path name starts with the "long path" -** prefix. -*/ -static BOOL winIsLongPathPrefix( - const char *zPathname -){ - return ( zPathname[0]=='\\' && zPathname[1]=='\\' - && zPathname[2]=='?' && zPathname[3]=='\\' ); -} - /* ** Returns non-zero if the specified path name starts with a drive letter ** followed by a colon character. */ static BOOL winIsDriveLetterAndColon( @@ -52455,11 +43619,11 @@ /* ** Turn a relative pathname into a full pathname. Write the full ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname ** bytes in size. */ -static int winFullPathnameNoMutex( +static int winFullPathname( sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zRelative, /* Possibly relative input path */ int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */ ){ @@ -52467,15 +43631,14 @@ DWORD nByte; void *zConverted; char *zOut; #endif - /* If this path name begins with "/X:" or "\\?\", where "X" is any - ** alphabetic character, discard the initial "/" from the pathname. + /* If this path name begins with "/X:", where "X" is any alphabetic + ** character, discard the initial "/" from the pathname. */ - if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1) - || winIsLongPathPrefix(zRelative+1)) ){ + if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){ zRelative++; } #if defined(__CYGWIN__) SimulateIOError( return SQLITE_ERROR ); @@ -52634,24 +43797,10 @@ }else{ return SQLITE_IOERR_NOMEM_BKPT; } #endif } -static int winFullPathname( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - const char *zRelative, /* Possibly relative input path */ - int nFull, /* Size of output buffer in bytes */ - char *zFull /* Output buffer */ -){ - int rc; - MUTEX_LOGIC( sqlite3_mutex *pMutex; ) - MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); ) - sqlite3_mutex_enter(pMutex); - rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull); - sqlite3_mutex_leave(pMutex); - return rc; -} #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. @@ -52753,10 +43902,13 @@ return nBuf; #else 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; e.i = 0; { @@ -53047,14 +44199,10 @@ #if defined(SQLITE_WIN32_HAS_WIDE) sqlite3_vfs_register(&winLongPathNolockVfs, 0); #endif -#ifndef SQLITE_OMIT_WAL - winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#endif - return SQLITE_OK; } SQLITE_API int sqlite3_os_end(void){ #if SQLITE_OS_WINRT @@ -53061,960 +44209,16 @@ if( sleepObj!=NULL ){ osCloseHandle(sleepObj); sleepObj = NULL; } #endif - -#ifndef SQLITE_OMIT_WAL - winBigLock = 0; -#endif - return SQLITE_OK; } #endif /* SQLITE_OS_WIN */ /************** End of os_win.c **********************************************/ -/************** Begin file memdb.c *******************************************/ -/* -** 2016-09-07 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file implements an in-memory VFS. A database is held as a contiguous -** block of memory. -** -** This file also implements interface sqlite3_serialize() and -** sqlite3_deserialize(). -*/ -/* #include "sqliteInt.h" */ -#ifndef SQLITE_OMIT_DESERIALIZE - -/* -** Forward declaration of objects used by this utility -*/ -typedef struct sqlite3_vfs MemVfs; -typedef struct MemFile MemFile; -typedef struct MemStore MemStore; - -/* Access to a lower-level VFS that (might) implement dynamic loading, -** access to randomness, etc. -*/ -#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) - -/* Storage for a memdb file. -** -** An memdb object can be shared or separate. Shared memdb objects can be -** used by more than one database connection. Mutexes are used by shared -** memdb objects to coordinate access. Separate memdb objects are only -** connected to a single database connection and do not require additional -** mutexes. -** -** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created -** using "file:/name?vfs=memdb". The first character of the name must be -** "/" or else the object will be a separate memdb object. All shared -** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order. -** -** Separate memdb objects are created using a name that does not begin -** with "/" or using sqlite3_deserialize(). -** -** Access rules for shared MemStore objects: -** -** * .zFName is initialized when the object is created and afterwards -** is unchanged until the object is destroyed. So it can be accessed -** at any time as long as we know the object is not being destroyed, -** which means while either the SQLITE_MUTEX_STATIC_VFS1 or -** .pMutex is held or the object is not part of memdb_g.apMemStore[]. -** -** * Can .pMutex can only be changed while holding the -** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part -** of memdb_g.apMemStore[]. -** -** * Other fields can only be changed while holding the .pMutex mutex -** or when the .nRef is less than zero and the object is not part of -** memdb_g.apMemStore[]. -** -** * The .aData pointer has the added requirement that it can can only -** be changed (for resizing) when nMmap is zero. -** -*/ -struct MemStore { - sqlite3_int64 sz; /* Size of the file */ - sqlite3_int64 szAlloc; /* Space allocated to aData */ - sqlite3_int64 szMax; /* Maximum allowed size of the file */ - unsigned char *aData; /* content of the file */ - sqlite3_mutex *pMutex; /* Used by shared stores only */ - int nMmap; /* Number of memory mapped pages */ - unsigned mFlags; /* Flags */ - int nRdLock; /* Number of readers */ - int nWrLock; /* Number of writers. (Always 0 or 1) */ - int nRef; /* Number of users of this MemStore */ - char *zFName; /* The filename for shared stores */ -}; - -/* An open file */ -struct MemFile { - sqlite3_file base; /* IO methods */ - MemStore *pStore; /* The storage */ - int eLock; /* Most recent lock against this file */ -}; - -/* -** File-scope variables for holding the memdb files that are accessible -** to multiple database connections in separate threads. -** -** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object. -*/ -static struct MemFS { - int nMemStore; /* Number of shared MemStore objects */ - MemStore **apMemStore; /* Array of all shared MemStore objects */ -} memdb_g; - -/* -** Methods for MemFile -*/ -static int memdbClose(sqlite3_file*); -static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); -static int memdbSync(sqlite3_file*, int flags); -static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); -static int memdbLock(sqlite3_file*, int); -static int memdbUnlock(sqlite3_file*, int); -/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */ -static int memdbFileControl(sqlite3_file*, int op, void *pArg); -/* static int memdbSectorSize(sqlite3_file*); // not used */ -static int memdbDeviceCharacteristics(sqlite3_file*); -static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); -static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); - -/* -** Methods for MemVfs -*/ -static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); -/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */ -static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); -static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); -static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); -static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); -static void memdbDlClose(sqlite3_vfs*, void*); -static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); -static int memdbSleep(sqlite3_vfs*, int microseconds); -/* static int memdbCurrentTime(sqlite3_vfs*, double*); */ -static int memdbGetLastError(sqlite3_vfs*, int, char *); -static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); - -static sqlite3_vfs memdb_vfs = { - 2, /* iVersion */ - 0, /* szOsFile (set when registered) */ - 1024, /* mxPathname */ - 0, /* pNext */ - "memdb", /* zName */ - 0, /* pAppData (set when registered) */ - memdbOpen, /* xOpen */ - 0, /* memdbDelete, */ /* xDelete */ - memdbAccess, /* xAccess */ - memdbFullPathname, /* xFullPathname */ - memdbDlOpen, /* xDlOpen */ - memdbDlError, /* xDlError */ - memdbDlSym, /* xDlSym */ - memdbDlClose, /* xDlClose */ - memdbRandomness, /* xRandomness */ - memdbSleep, /* xSleep */ - 0, /* memdbCurrentTime, */ /* xCurrentTime */ - memdbGetLastError, /* xGetLastError */ - memdbCurrentTimeInt64, /* xCurrentTimeInt64 */ - 0, /* xSetSystemCall */ - 0, /* xGetSystemCall */ - 0, /* xNextSystemCall */ -}; - -static const sqlite3_io_methods memdb_io_methods = { - 3, /* iVersion */ - memdbClose, /* xClose */ - memdbRead, /* xRead */ - memdbWrite, /* xWrite */ - memdbTruncate, /* xTruncate */ - memdbSync, /* xSync */ - memdbFileSize, /* xFileSize */ - memdbLock, /* xLock */ - memdbUnlock, /* xUnlock */ - 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ - memdbFileControl, /* xFileControl */ - 0, /* memdbSectorSize,*/ /* xSectorSize */ - memdbDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - memdbFetch, /* xFetch */ - memdbUnfetch /* xUnfetch */ -}; - -/* -** Enter/leave the mutex on a MemStore -*/ -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0 -static void memdbEnter(MemStore *p){ - UNUSED_PARAMETER(p); -} -static void memdbLeave(MemStore *p){ - UNUSED_PARAMETER(p); -} -#else -static void memdbEnter(MemStore *p){ - sqlite3_mutex_enter(p->pMutex); -} -static void memdbLeave(MemStore *p){ - sqlite3_mutex_leave(p->pMutex); -} -#endif - - - -/* -** Close an memdb-file. -** Free the underlying MemStore object when its refcount drops to zero -** or less. -*/ -static int memdbClose(sqlite3_file *pFile){ - MemStore *p = ((MemFile*)pFile)->pStore; - if( p->zFName ){ - int i; -#ifndef SQLITE_MUTEX_OMIT - sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#endif - sqlite3_mutex_enter(pVfsMutex); - for(i=0; ALWAYS(inRef==1 ){ - memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore]; - if( memdb_g.nMemStore==0 ){ - sqlite3_free(memdb_g.apMemStore); - memdb_g.apMemStore = 0; - } - } - break; - } - } - sqlite3_mutex_leave(pVfsMutex); - }else{ - memdbEnter(p); - } - p->nRef--; - if( p->nRef<=0 ){ - if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){ - sqlite3_free(p->aData); - } - memdbLeave(p); - sqlite3_mutex_free(p->pMutex); - sqlite3_free(p); - }else{ - memdbLeave(p); - } - return SQLITE_OK; -} - -/* -** Read data from an memdb-file. -*/ -static int memdbRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst -){ - MemStore *p = ((MemFile*)pFile)->pStore; - memdbEnter(p); - if( iOfst+iAmt>p->sz ){ - memset(zBuf, 0, iAmt); - if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst); - memdbLeave(p); - return SQLITE_IOERR_SHORT_READ; - } - memcpy(zBuf, p->aData+iOfst, iAmt); - memdbLeave(p); - return SQLITE_OK; -} - -/* -** Try to enlarge the memory allocation to hold at least sz bytes -*/ -static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){ - unsigned char *pNew; - if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){ - return SQLITE_FULL; - } - if( newSz>p->szMax ){ - return SQLITE_FULL; - } - newSz *= 2; - if( newSz>p->szMax ) newSz = p->szMax; - pNew = sqlite3Realloc(p->aData, newSz); - if( pNew==0 ) return SQLITE_IOERR_NOMEM; - p->aData = pNew; - p->szAlloc = newSz; - return SQLITE_OK; -} - -/* -** Write data to an memdb-file. -*/ -static int memdbWrite( - sqlite3_file *pFile, - const void *z, - int iAmt, - sqlite_int64 iOfst -){ - MemStore *p = ((MemFile*)pFile)->pStore; - memdbEnter(p); - if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){ - /* Can't happen: memdbLock() will return SQLITE_READONLY before - ** reaching this point */ - memdbLeave(p); - return SQLITE_IOERR_WRITE; - } - if( iOfst+iAmt>p->sz ){ - int rc; - if( iOfst+iAmt>p->szAlloc - && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK - ){ - memdbLeave(p); - return rc; - } - if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); - p->sz = iOfst+iAmt; - } - memcpy(p->aData+iOfst, z, iAmt); - memdbLeave(p); - return SQLITE_OK; -} - -/* -** Truncate an memdb-file. -** -** In rollback mode (which is always the case for memdb, as it does not -** support WAL mode) the truncate() method is only used to reduce -** the size of a file, never to increase the size. -*/ -static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ - MemStore *p = ((MemFile*)pFile)->pStore; - int rc = SQLITE_OK; - memdbEnter(p); - if( size>p->sz ){ - /* This can only happen with a corrupt wal mode db */ - rc = SQLITE_CORRUPT; - }else{ - p->sz = size; - } - memdbLeave(p); - return rc; -} - -/* -** Sync an memdb-file. -*/ -static int memdbSync(sqlite3_file *pFile, int flags){ - UNUSED_PARAMETER(pFile); - UNUSED_PARAMETER(flags); - return SQLITE_OK; -} - -/* -** Return the current file-size of an memdb-file. -*/ -static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - MemStore *p = ((MemFile*)pFile)->pStore; - memdbEnter(p); - *pSize = p->sz; - memdbLeave(p); - return SQLITE_OK; -} - -/* -** Lock an memdb-file. -*/ -static int memdbLock(sqlite3_file *pFile, int eLock){ - MemFile *pThis = (MemFile*)pFile; - MemStore *p = pThis->pStore; - int rc = SQLITE_OK; - if( eLock<=pThis->eLock ) return SQLITE_OK; - memdbEnter(p); - - assert( p->nWrLock==0 || p->nWrLock==1 ); - assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 ); - assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 ); - - if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){ - rc = SQLITE_READONLY; - }else{ - switch( eLock ){ - case SQLITE_LOCK_SHARED: { - assert( pThis->eLock==SQLITE_LOCK_NONE ); - if( p->nWrLock>0 ){ - rc = SQLITE_BUSY; - }else{ - p->nRdLock++; - } - break; - }; - - case SQLITE_LOCK_RESERVED: - case SQLITE_LOCK_PENDING: { - assert( pThis->eLock>=SQLITE_LOCK_SHARED ); - if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){ - if( p->nWrLock>0 ){ - rc = SQLITE_BUSY; - }else{ - p->nWrLock = 1; - } - } - break; - } - - default: { - assert( eLock==SQLITE_LOCK_EXCLUSIVE ); - assert( pThis->eLock>=SQLITE_LOCK_SHARED ); - if( p->nRdLock>1 ){ - rc = SQLITE_BUSY; - }else if( pThis->eLock==SQLITE_LOCK_SHARED ){ - p->nWrLock = 1; - } - break; - } - } - } - if( rc==SQLITE_OK ) pThis->eLock = eLock; - memdbLeave(p); - return rc; -} - -/* -** Unlock an memdb-file. -*/ -static int memdbUnlock(sqlite3_file *pFile, int eLock){ - MemFile *pThis = (MemFile*)pFile; - MemStore *p = pThis->pStore; - if( eLock>=pThis->eLock ) return SQLITE_OK; - memdbEnter(p); - - assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE ); - if( eLock==SQLITE_LOCK_SHARED ){ - if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){ - p->nWrLock--; - } - }else{ - if( pThis->eLock>SQLITE_LOCK_SHARED ){ - p->nWrLock--; - } - p->nRdLock--; - } - - pThis->eLock = eLock; - memdbLeave(p); - return SQLITE_OK; -} - -#if 0 -/* -** This interface is only used for crash recovery, which does not -** occur on an in-memory database. -*/ -static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - *pResOut = 0; - return SQLITE_OK; -} -#endif - - -/* -** File control method. For custom operations on an memdb-file. -*/ -static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ - MemStore *p = ((MemFile*)pFile)->pStore; - int rc = SQLITE_NOTFOUND; - memdbEnter(p); - if( op==SQLITE_FCNTL_VFSNAME ){ - *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz); - rc = SQLITE_OK; - } - if( op==SQLITE_FCNTL_SIZE_LIMIT ){ - sqlite3_int64 iLimit = *(sqlite3_int64*)pArg; - if( iLimitsz ){ - if( iLimit<0 ){ - iLimit = p->szMax; - }else{ - iLimit = p->sz; - } - } - p->szMax = iLimit; - *(sqlite3_int64*)pArg = iLimit; - rc = SQLITE_OK; - } - memdbLeave(p); - return rc; -} - -#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */ -/* -** Return the sector-size in bytes for an memdb-file. -*/ -static int memdbSectorSize(sqlite3_file *pFile){ - return 1024; -} -#endif - -/* -** Return the device characteristic flags supported by an memdb-file. -*/ -static int memdbDeviceCharacteristics(sqlite3_file *pFile){ - UNUSED_PARAMETER(pFile); - return SQLITE_IOCAP_ATOMIC | - SQLITE_IOCAP_POWERSAFE_OVERWRITE | - SQLITE_IOCAP_SAFE_APPEND | - SQLITE_IOCAP_SEQUENTIAL; -} - -/* Fetch a page of a memory-mapped file */ -static int memdbFetch( - sqlite3_file *pFile, - sqlite3_int64 iOfst, - int iAmt, - void **pp -){ - MemStore *p = ((MemFile*)pFile)->pStore; - memdbEnter(p); - if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){ - *pp = 0; - }else{ - p->nMmap++; - *pp = (void*)(p->aData + iOfst); - } - memdbLeave(p); - return SQLITE_OK; -} - -/* Release a memory-mapped page */ -static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ - MemStore *p = ((MemFile*)pFile)->pStore; - UNUSED_PARAMETER(iOfst); - UNUSED_PARAMETER(pPage); - memdbEnter(p); - p->nMmap--; - memdbLeave(p); - return SQLITE_OK; -} - -/* -** Open an mem file handle. -*/ -static int memdbOpen( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_file *pFd, - int flags, - int *pOutFlags -){ - MemFile *pFile = (MemFile*)pFd; - MemStore *p = 0; - int szName; - UNUSED_PARAMETER(pVfs); - - memset(pFile, 0, sizeof(*pFile)); - szName = sqlite3Strlen30(zName); - if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){ - int i; -#ifndef SQLITE_MUTEX_OMIT - sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#endif - sqlite3_mutex_enter(pVfsMutex); - for(i=0; izFName,zName)==0 ){ - p = memdb_g.apMemStore[i]; - break; - } - } - if( p==0 ){ - MemStore **apNew; - p = sqlite3Malloc( sizeof(*p) + szName + 3 ); - if( p==0 ){ - sqlite3_mutex_leave(pVfsMutex); - return SQLITE_NOMEM; - } - apNew = sqlite3Realloc(memdb_g.apMemStore, - sizeof(apNew[0])*(memdb_g.nMemStore+1) ); - if( apNew==0 ){ - sqlite3_free(p); - sqlite3_mutex_leave(pVfsMutex); - return SQLITE_NOMEM; - } - apNew[memdb_g.nMemStore++] = p; - memdb_g.apMemStore = apNew; - memset(p, 0, sizeof(*p)); - p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE; - p->szMax = sqlite3GlobalConfig.mxMemdbSize; - p->zFName = (char*)&p[1]; - memcpy(p->zFName, zName, szName+1); - p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( p->pMutex==0 ){ - memdb_g.nMemStore--; - sqlite3_free(p); - sqlite3_mutex_leave(pVfsMutex); - return SQLITE_NOMEM; - } - p->nRef = 1; - memdbEnter(p); - }else{ - memdbEnter(p); - p->nRef++; - } - sqlite3_mutex_leave(pVfsMutex); - }else{ - p = sqlite3Malloc( sizeof(*p) ); - if( p==0 ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(*p)); - p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; - p->szMax = sqlite3GlobalConfig.mxMemdbSize; - } - pFile->pStore = p; - if( pOutFlags!=0 ){ - *pOutFlags = flags | SQLITE_OPEN_MEMORY; - } - pFd->pMethods = &memdb_io_methods; - memdbLeave(p); - return SQLITE_OK; -} - -#if 0 /* Only used to delete rollback journals, super-journals, and WAL - ** files, none of which exist in memdb. So this routine is never used */ -/* -** Delete the file located at zPath. If the dirSync argument is true, -** ensure the file-system modifications are synced to disk before -** returning. -*/ -static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return SQLITE_IOERR_DELETE; -} -#endif - -/* -** Test for access permissions. Return true if the requested permission -** is available, or false otherwise. -** -** With memdb, no files ever exist on disk. So always return false. -*/ -static int memdbAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut -){ - UNUSED_PARAMETER(pVfs); - UNUSED_PARAMETER(zPath); - UNUSED_PARAMETER(flags); - *pResOut = 0; - return SQLITE_OK; -} - -/* -** Populate buffer zOut with the full canonical pathname corresponding -** to the pathname in zPath. zOut is guaranteed to point to a buffer -** of at least (INST_MAX_PATHNAME+1) bytes. -*/ -static int memdbFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut -){ - UNUSED_PARAMETER(pVfs); - sqlite3_snprintf(nOut, zOut, "%s", zPath); - return SQLITE_OK; -} - -/* -** Open the dynamic library located at zPath and return a handle. -*/ -static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); -} - -/* -** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated -** with dynamic libraries. -*/ -static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); -} - -/* -** Return a pointer to the symbol zSymbol in the dynamic library pHandle. -*/ -static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); -} - -/* -** Close the dynamic library handle pHandle. -*/ -static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){ - ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); -} - -/* -** Populate the buffer pointed to by zBufOut with nByte bytes of -** random data. -*/ -static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); -} - -/* -** Sleep for nMicro microseconds. Return the number of microseconds -** actually slept. -*/ -static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ - return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); -} - -#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */ -/* -** Return the current time as a Julian Day number in *pTimeOut. -*/ -static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); -} -#endif - -static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ - return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); -} -static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ - return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); -} - -/* -** Translate a database connection pointer and schema name into a -** MemFile pointer. -*/ -static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ - MemFile *p = 0; - MemStore *pStore; - int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); - if( rc ) return 0; - if( p->base.pMethods!=&memdb_io_methods ) return 0; - pStore = p->pStore; - memdbEnter(pStore); - if( pStore->zFName!=0 ) p = 0; - memdbLeave(pStore); - return p; -} - -/* -** Return the serialization of a database -*/ -SQLITE_API unsigned char *sqlite3_serialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which database within the connection */ - sqlite3_int64 *piSize, /* Write size here, if not NULL */ - unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ -){ - MemFile *p; - int iDb; - Btree *pBt; - sqlite3_int64 sz; - int szPage = 0; - sqlite3_stmt *pStmt = 0; - unsigned char *pOut; - char *zSql; - int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - - if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; - p = memdbFromDbSchema(db, zSchema); - iDb = sqlite3FindDbName(db, zSchema); - if( piSize ) *piSize = -1; - if( iDb<0 ) return 0; - if( p ){ - MemStore *pStore = p->pStore; - assert( pStore->pMutex==0 ); - if( piSize ) *piSize = pStore->sz; - if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ - pOut = pStore->aData; - }else{ - pOut = sqlite3_malloc64( pStore->sz ); - if( pOut ) memcpy(pOut, pStore->aData, pStore->sz); - } - return pOut; - } - pBt = db->aDb[iDb].pBt; - if( pBt==0 ) return 0; - szPage = sqlite3BtreeGetPageSize(pBt); - zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); - rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; - sqlite3_free(zSql); - if( rc ) return 0; - rc = sqlite3_step(pStmt); - if( rc!=SQLITE_ROW ){ - pOut = 0; - }else{ - sz = sqlite3_column_int64(pStmt, 0)*szPage; - if( sz==0 ){ - sqlite3_reset(pStmt); - sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - sz = sqlite3_column_int64(pStmt, 0)*szPage; - } - } - if( piSize ) *piSize = sz; - if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ - pOut = 0; - }else{ - pOut = sqlite3_malloc64( sz ); - if( pOut ){ - int nPage = sqlite3_column_int(pStmt, 0); - Pager *pPager = sqlite3BtreePager(pBt); - int pgno; - for(pgno=1; pgno<=nPage; pgno++){ - DbPage *pPage = 0; - unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); - rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); - if( rc==SQLITE_OK ){ - memcpy(pTo, sqlite3PagerGetData(pPage), szPage); - }else{ - memset(pTo, 0, szPage); - } - sqlite3PagerUnref(pPage); - } - } - } - } - sqlite3_finalize(pStmt); - return pOut; -} - -/* Convert zSchema to a MemDB and initialize its content. -*/ -SQLITE_API int sqlite3_deserialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to reopen with the deserialization */ - unsigned char *pData, /* The serialized database content */ - sqlite3_int64 szDb, /* Number bytes in the deserialization */ - sqlite3_int64 szBuf, /* Total size of buffer pData[] */ - unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ -){ - MemFile *p; - char *zSql; - sqlite3_stmt *pStmt = 0; - int rc; - int iDb; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - if( szDb<0 ) return SQLITE_MISUSE_BKPT; - if( szBuf<0 ) return SQLITE_MISUSE_BKPT; -#endif - - sqlite3_mutex_enter(db->mutex); - if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; - iDb = sqlite3FindDbName(db, zSchema); - testcase( iDb==1 ); - if( iDb<2 && iDb!=0 ){ - rc = SQLITE_ERROR; - goto end_deserialize; - } - zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - if( rc ) goto end_deserialize; - db->init.iDb = (u8)iDb; - db->init.reopenMemdb = 1; - rc = sqlite3_step(pStmt); - db->init.reopenMemdb = 0; - if( rc!=SQLITE_DONE ){ - rc = SQLITE_ERROR; - goto end_deserialize; - } - p = memdbFromDbSchema(db, zSchema); - if( p==0 ){ - rc = SQLITE_ERROR; - }else{ - MemStore *pStore = p->pStore; - pStore->aData = pData; - pData = 0; - pStore->sz = szDb; - pStore->szAlloc = szBuf; - pStore->szMax = szBuf; - if( pStore->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize; - } - pStore->mFlags = mFlags; - rc = SQLITE_OK; - } - -end_deserialize: - sqlite3_finalize(pStmt); - if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){ - sqlite3_free(pData); - } - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Return true if the VFS is the memvfs. -*/ -SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs *pVfs){ - return pVfs==&memdb_vfs; -} - -/* -** This routine is called when the extension is loaded. -** Register the new VFS. -*/ -SQLITE_PRIVATE int sqlite3MemdbInit(void){ - sqlite3_vfs *pLower = sqlite3_vfs_find(0); - unsigned int sz; - if( NEVER(pLower==0) ) return SQLITE_ERROR; - sz = pLower->szOsFile; - memdb_vfs.pAppData = pLower; - /* The following conditional can only be true when compiled for - ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave - ** it in, to be safe, but it is marked as NO_TEST since there - ** is no way to reach it under most builds. */ - if( szu.aHash[h] ){ if (p->nSet<(BITVEC_NINT-1)) { goto bitvec_set_end; } else { goto bitvec_set_rehash; @@ -54367,11 +44571,11 @@ /* NULL pBitvec tests */ sqlite3BitvecSet(0, 1); sqlite3BitvecClear(0, 1, pTmpSpace); /* Run the program */ - pc = i = 0; + pc = 0; while( (op = aOp[pc])!=0 ){ switch( op ){ case 1: case 2: case 5: { @@ -54379,11 +44583,11 @@ i = aOp[pc+2] - 1; aOp[pc+2] += aOp[pc+3]; break; } case 3: - case 4: + case 4: default: { nx = 2; sqlite3_randomness(sizeof(i), &i); break; } @@ -54459,21 +44663,21 @@ ** PCache.pDirty points to the first (newest) element in the list and ** pDirtyTail to the last (oldest). ** ** The PCache.pSynced variable is used to optimize searching for a dirty ** page to eject from the cache mid-transaction. It is better to eject -** a page that does not require a journal sync than one that does. -** Therefore, pSynced is maintained so that it *almost* always points +** a page that does not require a journal sync than one that does. +** Therefore, pSynced is maintained to that it *almost* always points ** to either the oldest page in the pDirty/pDirtyTail list that has a ** clear PGHDR_NEED_SYNC flag or to a page that is older than this one ** (so that the right page to eject can be found by following pDirtyPrev ** pointers). */ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ - i64 nRefSum; /* Sum of ref counts over all pages */ + int nRefSum; /* Sum of ref counts over all pages */ int szCache; /* Configured cache size */ int szSpill; /* Size before spilling occurs */ int szPage; /* Size of every page in this cache */ int szExtra; /* Size of extra space for each page */ u8 bPurgeable; /* True if pages are on backing store */ @@ -54494,71 +44698,39 @@ */ #if defined(SQLITE_DEBUG) && 0 int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */ int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */ # define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;} - static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){ + void pcacheDump(PCache *pCache){ + int N; + int i, j; + sqlite3_pcache_page *pLower; PgHdr *pPg; unsigned char *a; - int j; - if( pLower==0 ){ - printf("%3d: NULL\n", i); - }else{ - pPg = (PgHdr*)pLower->pExtra; - printf("%3d: nRef %2lld flgs %02x data ", i, pPg->nRef, pPg->flags); - a = (unsigned char *)pLower->pBuf; - for(j=0; j<12; j++) printf("%02x", a[j]); - printf(" ptr %p\n", pPg); - } - } - static void pcacheDump(PCache *pCache){ - int N; - int i; - sqlite3_pcache_page *pLower; - + if( sqlite3PcacheTrace<2 ) return; if( pCache->pCache==0 ) return; N = sqlite3PcachePagecount(pCache); if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; for(i=1; i<=N; i++){ pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); - pcachePageTrace(i, pLower); - if( pLower && ((PgHdr*)pLower)->pPage==0 ){ + if( pLower==0 ) continue; + pPg = (PgHdr*)pLower->pExtra; + printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags); + a = (unsigned char *)pLower->pBuf; + for(j=0; j<12; j++) printf("%02x", a[j]); + printf("\n"); + if( pPg->pPage==0 ){ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); } } } -#else + #else # define pcacheTrace(X) -# define pcachePageTrace(PGNO, X) # define pcacheDump(X) #endif -/* -** Return 1 if pPg is on the dirty list for pCache. Return 0 if not. -** This routine runs inside of assert() statements only. -*/ -#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) -static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - if( p==pPg ) return 1; - } - return 0; -} -static int pageNotOnDirtyList(PCache *pCache, PgHdr *pPg){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - if( p==pPg ) return 0; - } - return 1; -} -#else -# define pageOnDirtyList(A,B) 1 -# define pageNotOnDirtyList(A,B) 1 -#endif - /* ** Check invariants on a PgHdr entry. Return true if everything is OK. ** Return false if any invariant is violated. ** ** This routine is for use inside of assert() statements only. For @@ -54573,17 +44745,12 @@ 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 ){ assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ - assert( pageNotOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirtylist */ - }else{ - assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */ - assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg ); - assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg ); - assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg ); - assert( pageOnDirtyList(pCache, pPg) ); + assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */ + assert( pCache->pDirtyTail!=pPg ); } /* WRITEABLE pages must also be DIRTY */ if( pPg->flags & PGHDR_WRITEABLE ){ assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */ } @@ -54629,26 +44796,26 @@ addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT", pPage->pgno)); if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); assert( pPage->pDirtyPrev || pPage==p->pDirty ); - + /* Update the PCache1.pSynced variable if necessary. */ if( p->pSynced==pPage ){ p->pSynced = pPage->pDirtyPrev; } - + if( pPage->pDirtyNext ){ pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; }else{ assert( pPage==p->pDirtyTail ); p->pDirtyTail = pPage->pDirtyPrev; } if( pPage->pDirtyPrev ){ pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; }else{ - /* If there are now no dirty pages in the cache, set eCreate to 2. + /* If there are now no dirty pages in the cache, set eCreate to 2. ** This is an optimization that allows sqlite3PcacheFetch() to skip ** searching for a dirty page to eject from the cache when it might ** otherwise have to. */ assert( pPage==p->pDirty ); p->pDirty = pPage->pDirtyNext; @@ -54656,13 +44823,16 @@ if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/ assert( p->bPurgeable==0 || p->eCreate==1 ); p->eCreate = 2; } } + pPage->pDirtyNext = 0; + pPage->pDirtyPrev = 0; } if( addRemove & PCACHE_DIRTYLIST_ADD ){ - pPage->pDirtyPrev = 0; + assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); + pPage->pDirtyNext = p->pDirty; if( pPage->pDirtyNext ){ assert( pPage->pDirtyNext->pDirtyPrev==0 ); pPage->pDirtyNext->pDirtyPrev = pPage; }else{ @@ -54673,15 +44843,15 @@ } } p->pDirty = pPage; /* If pSynced is NULL and this page has a clear NEED_SYNC flag, set - ** pSynced to point to it. Checking the NEED_SYNC flag is an + ** pSynced to point to it. Checking the NEED_SYNC flag is an ** optimization, as if pSynced points to a page with the NEED_SYNC - ** flag set sqlite3PcacheFetchStress() searches through all newer + ** flag set sqlite3PcacheFetchStress() searches through all newer ** entries of the dirty-list for a page with NEED_SYNC clear anyway. */ - if( !p->pSynced + if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/ ){ p->pSynced = pPage; } } @@ -54708,33 +44878,28 @@ if( p->szCache>=0 ){ /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the ** suggested cache size is set to N. */ return p->szCache; }else{ - i64 n; - /* IMPLEMENTATION-OF: R-59858-46238 If the argument N is negative, then the - ** number of cache pages is adjusted to be a number of pages that would - ** use approximately abs(N*1024) bytes of memory based on the current - ** page size. */ - n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); - if( n>1000000000 ) n = 1000000000; - return (int)n; + /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then + ** the number of cache pages is adjusted to use approximately abs(N*1024) + ** bytes of memory. */ + return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); } } /*************************************************** General Interfaces ****** ** -** Initialize and shutdown the page cache subsystem. Neither of these +** Initialize and shutdown the page cache subsystem. Neither of these ** functions are threadsafe. */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void){ if( sqlite3GlobalConfig.pcache2.xInit==0 ){ /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the ** built-in default page cache is used instead of the application defined ** page cache. */ sqlite3PCacheSetDefault(); - assert( sqlite3GlobalConfig.pcache2.xInit!=0 ); } return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg); } SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ if( sqlite3GlobalConfig.pcache2.xShutdown ){ @@ -54748,12 +44913,12 @@ */ SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); } /* ** Create a new PCache object. Storage space to hold the object -** has already been allocated and is passed in as the p pointer. -** The caller discovers how much space needs to be allocated by +** has already been allocated and is passed in as the p pointer. +** The caller discovers how much space needs to be allocated by ** calling sqlite3PcacheSize(). ** ** szExtra is some extra space allocated for each page. The first ** 8 bytes of the extra space will be zeroed as the page is allocated, ** but remaining content will be uninitialized. Though it is opaque @@ -54853,20 +45018,19 @@ eCreate = createFlag & pCache->eCreate; assert( eCreate==0 || eCreate==1 || eCreate==2 ); assert( createFlag==0 || pCache->eCreate==eCreate ); assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) ); pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); - pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno, + pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno, createFlag?" create":"",pRes)); - pcachePageTrace(pgno, pRes); return pRes; } /* ** If the sqlite3PcacheFetch() routine is unable to allocate a new ** page because no clean pages are available for reuse and the cache -** size limit has been reached, then this routine can be invoked to +** size limit has been reached, then this routine can be invoked to ** try harder to allocate a page. This routine might invoke the stress ** callback to spill dirty pages to the journal. It will then try to ** allocate the new page and will only fail to allocate a new page on ** an OOM error. ** @@ -54879,34 +45043,34 @@ ){ PgHdr *pPg; if( pCache->eCreate==2 ) return 0; if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){ - /* Find a dirty page to write-out and recycle. First try to find a + /* Find a dirty page to write-out and recycle. First try to find a ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC - ** cleared), but if that is not possible settle for any other + ** cleared), but if that is not possible settle for any other ** unreferenced dirty page. ** ** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC ** flag is currently referenced, then the following may leave pSynced ** set incorrectly (pointing to other than the LRU page with NEED_SYNC ** cleared). This is Ok, as pSynced is just an optimization. */ - for(pPg=pCache->pSynced; - pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); + for(pPg=pCache->pSynced; + pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); pPg=pPg->pDirtyPrev ); pCache->pSynced = pPg; if( !pPg ){ for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); } if( pPg ){ int rc; #ifdef SQLITE_LOG_CACHE_SPILL - sqlite3_log(SQLITE_FULL, + sqlite3_log(SQLITE_FULL, "spill page %d making room for %d - cache used: %d/%d", pPg->pgno, pgno, - sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache), + sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), numberOfCachePages(pCache)); #endif pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); rc = pCache->xStress(pCache->pStress, pPg); pcacheDump(pCache); @@ -54940,11 +45104,10 @@ memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); pPgHdr->pPage = pPage; pPgHdr->pData = pPage->pBuf; pPgHdr->pExtra = (void *)&pPgHdr[1]; memset(pPgHdr->pExtra, 0, 8); - assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) ); pPgHdr->pCache = pCache; pPgHdr->pgno = pgno; pPgHdr->flags = PGHDR_CLEAN; return sqlite3PcacheFetchFinish(pCache,pgno,pPage); } @@ -54982,13 +45145,16 @@ assert( p->nRef>0 ); p->pCache->nRefSum--; if( (--p->nRef)==0 ){ if( p->flags&PGHDR_CLEAN ){ pcacheUnpin(p); - }else{ + }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. */ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); - assert( sqlite3PcachePageSanity(p) ); } } } /* @@ -55028,11 +45194,10 @@ if( p->flags & PGHDR_CLEAN ){ p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN); pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno)); assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY ); pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); - assert( sqlite3PcachePageSanity(p) ); } assert( sqlite3PcachePageSanity(p) ); } } @@ -55040,19 +45205,20 @@ ** Make sure the page is marked as clean. If it isn't clean already, ** make it so. */ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ assert( sqlite3PcachePageSanity(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); + 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); + } } } /* ** Make every page in the cache clean. @@ -55087,32 +45253,22 @@ } pCache->pSynced = pCache->pDirtyTail; } /* -** Change the page number of page p to newPgno. +** Change the page number of page p to newPgno. */ SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ PCache *pCache = p->pCache; - sqlite3_pcache_page *pOther; assert( p->nRef>0 ); assert( newPgno>0 ); assert( sqlite3PcachePageSanity(p) ); pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno)); - pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0); - if( pOther ){ - PgHdr *pXPage = (PgHdr*)pOther->pExtra; - assert( pXPage->nRef==0 ); - pXPage->nRef++; - pCache->nRefSum++; - sqlite3PcacheDrop(pXPage); - } sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); - assert( sqlite3PcachePageSanity(p) ); } } /* ** Drop every cache entry whose page number is greater than "pgno". The @@ -55160,11 +45316,11 @@ assert( pCache->pCache!=0 ); pcacheTrace(("%p.CLOSE\n",pCache)); sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); } -/* +/* ** Discard the contents of the cache. */ SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){ sqlite3PcacheTruncate(pCache, 0); } @@ -55198,11 +45354,11 @@ } return result.pDirty; } /* -** Sort the list of pages in ascending order by pgno. Pages are +** Sort the list of pages in accending order by pgno. Pages are ** connected by pDirty pointers. The pDirtyPrev pointers are ** corrupted by this sort. ** ** Since there cannot be more than 2^31 distinct pages in a database, ** there cannot be more than 31 buckets required by the merge sorter. @@ -55251,28 +45407,28 @@ p->pDirty = p->pDirtyNext; } return pcacheSortDirtyList(pCache->pDirty); } -/* +/* ** Return the total number of references to all pages held by the cache. ** ** This is not the total number of pages referenced, but the sum of the ** reference count for all pages. */ -SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache *pCache){ +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){ return pCache->nRefSum; } /* ** Return the number of references to the page supplied as an argument. */ -SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr *p){ +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){ return p->nRef; } -/* +/* ** Return the total number of pages in the cache. */ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){ assert( pCache->pCache!=0 ); return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); @@ -55310,11 +45466,11 @@ mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra)); } p->szSpill = mxPage; } res = numberOfCachePages(p); - if( resszSpill ) res = p->szSpill; + if( resszSpill ) res = p->szSpill; return res; } /* ** Free up as much memory as possible from the page cache. @@ -55340,19 +45496,10 @@ int nCache = numberOfCachePages(pCache); for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++; return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; } -#ifdef SQLITE_DIRECT_OVERFLOW_READ -/* -** Return true if there are one or more dirty pages in the cache. Else false. -*/ -SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){ - return (pCache->pDirty!=0); -} -#endif - #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified ** callback. This is only used if the SQLITE_CHECK_PAGES macro is ** defined. @@ -55406,17 +45553,16 @@ ** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The ** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this ** size can vary according to architecture, compile-time options, and ** SQLite library version number. ** -** Historical note: It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER -** was defined, then the page content would be held in a separate memory -** allocation from the PgHdr1. This was intended to avoid clownshoe memory -** allocations. However, the btree layer needs a small (16-byte) overrun -** area after the page content buffer. The header serves as that overrun -** area. Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid -** any possibility of a memory error. +** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained +** using a separate memory allocation from the database page content. This +** seeks to overcome the "clownshoe" problem (also called "internal +** fragmentation" in academic literature) of allocating a few bytes more +** than a power of two with the memory allocator rounding up to the next +** power of two, and leaving the rounded-up space unused. ** ** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates ** with this module. Information is passed back and forth as PgHdr1 pointers. ** ** The pcache.c and pager.c modules deal pointers to PgHdr objects. @@ -55431,18 +45577,18 @@ ** SQLITE_CONFIG_PAGECACHE. ** (3) PCache-local bulk allocation. ** ** The third case is a chunk of heap memory (defaulting to 100 pages worth) ** that is allocated when the page cache is created. The size of the local -** bulk allocation can be adjusted using +** bulk allocation can be adjusted using ** ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N). ** ** If N is positive, then N pages worth of memory are allocated using a single ** sqlite3Malloc() call and that memory is used for the first N pages allocated. ** Or if N is negative, then -1024*N bytes of memory are allocated and used -** for as many pages as can be accommodated. +** for as many pages as can be accomodated. ** ** Only one of (2) or (3) can be used. Once the memory available to (2) or ** (3) is exhausted, subsequent allocations fail over to the general-purpose ** memory allocator (1). ** @@ -55456,55 +45602,28 @@ typedef struct PgHdr1 PgHdr1; typedef struct PgFreeslot PgFreeslot; typedef struct PGroup PGroup; /* -** Each cache entry is represented by an instance of the following -** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated -** directly before this structure and is used to cache the page content. -** -** When reading a corrupt database file, it is possible that SQLite might -** read a few bytes (no more than 16 bytes) past the end of the page buffer. -** It will only read past the end of the page buffer, never write. This -** object is positioned immediately after the page buffer to serve as an -** overrun area, so that overreads are harmless. -** -** Variables isBulkLocal and isAnchor were once type "u8". That works, -** but causes a 2-byte gap in the structure for most architectures (since -** pointers must be either 4 or 8-byte aligned). As this structure is located -** in memory directly after the associated page data, if the database is -** corrupt, code at the b-tree layer may overread the page buffer and -** read part of this structure before the corruption is detected. This -** can cause a valgrind error if the uninitialized gap is accessed. Using u16 -** ensures there is no such gap, and therefore no bytes of uninitialized -** memory in the structure. -** -** The pLruNext and pLruPrev pointers form a double-linked circular list -** of all pages that are unpinned. The PGroup.lru element (which should be -** the only element on the list with PgHdr1.isAnchor set to 1) forms the -** beginning and the end of the list. +** Each cache entry is represented by an instance of the following +** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of +** PgHdr1.pCache->szPage bytes is allocated directly before this structure +** in memory. */ struct PgHdr1 { - sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ - unsigned int iKey; /* Key value (page number) */ - u16 isBulkLocal; /* This page from bulk local storage */ - u16 isAnchor; /* This is the PGroup.lru element */ - PgHdr1 *pNext; /* Next in hash table chain */ - PCache1 *pCache; /* Cache that currently owns this page */ - PgHdr1 *pLruNext; /* Next in circular LRU list of unpinned pages */ - PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ - /* NB: pLruPrev is only valid if pLruNext!=0 */ + sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ + unsigned int iKey; /* Key value (page number) */ + 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 */ + PCache1 *pCache; /* Cache that currently owns this page */ + PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ + PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ }; -/* -** A page is pinned if it is not on the LRU list. To be "pinned" means -** that the page is in active use and must not be deallocated. -*/ -#define PAGE_IS_PINNED(p) ((p)->pLruNext==0) -#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) - -/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set +/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set ** of one or more PCaches that are able to recycle each other's unpinned ** pages when they are under memory pressure. A PGroup is an instance of ** the following object. ** ** This page cache implementation works in one of two modes: @@ -55527,40 +45646,37 @@ struct PGroup { sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ 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 nPurgeable; /* Number of purgeable pages allocated */ + unsigned int nCurrentPage; /* Number of purgeable pages allocated */ PgHdr1 lru; /* The beginning and end of the LRU list */ }; /* Each page cache is an instance of the following object. Every ** open database file (including each in-memory database and each ** temporary or transient database) has a single page cache which ** is an instance of this object. ** -** Pointers to structures of this type are cast and returned as +** Pointers to structures of this type are cast and returned as ** opaque sqlite3_pcache* handles. */ struct PCache1 { /* Cache configuration parameters. Page size (szPage) and the purgeable - ** flag (bPurgeable) and the pnPurgeable pointer are all set when the - ** cache is created and are never changed thereafter. nMax may be + ** flag (bPurgeable) are set when the cache is created. 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 */ int bPurgeable; /* True if cache is purgeable */ unsigned int nMin; /* Minimum number of pages reserved */ unsigned int nMax; /* Configured "cache_size" value */ unsigned int n90pct; /* nMax*9/10 */ unsigned int iMaxKey; /* Largest key seen since xTruncate() */ - unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/ /* Hash table of all pages. The following variables may only be accessed ** when the accessor is holding the PGroup mutex. */ unsigned int nRecyclable; /* Number of pages in the LRU list */ @@ -55590,11 +45706,11 @@ ** fixed at sqlite3_initialize() time and do not require mutex protection. ** The nFreeSlot and pFree values do require mutex protection. */ int isInit; /* True if initialized */ int separateCache; /* Use a new PGroup for each PCache */ - int nInitPage; /* Initial bulk allocation size */ + int nInitPage; /* Initial bulk allocation size */ int szSlot; /* Size of each free slot */ int nSlot; /* The number of pcache slots */ int nReserve; /* Try to keep nFreeSlot above this */ void *pStart, *pEnd; /* Bounds of global page cache memory */ /* Above requires no mutex. Use mutex below for variable that follow. */ @@ -55631,11 +45747,11 @@ /******************************************************************************/ /******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ /* -** This function is called during initialization if a static buffer is +** This function is called during initialization if a static buffer is ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE ** verb to sqlite3_config(). Parameter pBuf points to an allocation large ** enough to contain 'n' buffers of 'sz' bytes each. ** ** This routine is called from sqlite3_initialize() and so it is guaranteed @@ -55643,11 +45759,10 @@ */ 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; pcache1.nReserve = n>90 ? 10 : (n/10 + 1); pcache1.pStart = pBuf; @@ -55687,27 +45802,25 @@ if( zBulk ){ int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; do{ PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; pX->page.pBuf = zBulk; - pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX)); - assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) ); + pX->page.pExtra = &pX[1]; pX->isBulkLocal = 1; pX->isAnchor = 0; pX->pNext = pCache->pFree; - pX->pLruPrev = 0; /* Initializing this saves a valgrind error */ pCache->pFree = pX; zBulk += pCache->szAlloc; }while( --nBulk ); } return pCache->pFree!=0; } /* ** Malloc function used within this file to allocate space from the buffer -** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no -** such buffer exists or there is no space left in it, this function falls +** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no +** such buffer exists or there is no space left in it, this function falls ** back to sqlite3Malloc(). ** ** Multiple threads can run this routine at the same time. Global variables ** in pcache1 need to be protected via mutex. */ @@ -55803,39 +45916,48 @@ PgHdr1 *p = 0; void *pPg; assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ - assert( pCache->pFree!=0 ); p = pCache->pFree; pCache->pFree = p->pNext; p->pNext = 0; }else{ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* The group mutex must be released before pcache1Alloc() is called. This - ** is because it might call sqlite3_release_memory(), which assumes that + ** is because it might call sqlite3_release_memory(), which assumes that ** this mutex is not held. */ assert( pcache1.separateCache==0 ); assert( pCache->pGroup==&pcache1.grp ); pcache1LeaveMutex(pCache->pGroup); #endif if( benignMalloc ){ sqlite3BeginBenignMalloc(); } +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + pPg = pcache1Alloc(pCache->szPage); + p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); + if( !pPg || !p ){ + pcache1Free(pPg); + sqlite3_free(p); + pPg = 0; + } +#else pPg = pcache1Alloc(pCache->szAlloc); + p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; +#endif if( benignMalloc ){ sqlite3EndBenignMalloc(); } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT pcache1EnterMutex(pCache->pGroup); #endif if( pPg==0 ) return 0; - p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; p->page.pBuf = pPg; - p->page.pExtra = (u8*)p + ROUND8(sizeof(*p)); - assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) ); + p->page.pExtra = &p[1]; p->isBulkLocal = 0; p->isAnchor = 0; - p->pLruPrev = 0; /* Initializing this saves a valgrind error */ } - (*pCache->pnPurgeable)++; + if( pCache->bPurgeable ){ + pCache->pGroup->nCurrentPage++; + } return p; } /* ** Free a page object allocated by pcache1AllocPage(). @@ -55848,21 +45970,25 @@ if( p->isBulkLocal ){ p->pNext = pCache->pFree; pCache->pFree = p; }else{ pcache1Free(p->page.pBuf); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + sqlite3_free(p); +#endif } - (*pCache->pnPurgeable)--; + if( pCache->bPurgeable ){ + pCache->pGroup->nCurrentPage--; + } } /* ** Malloc function used by SQLite to obtain space from the buffer configured ** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer ** exists, this function falls back to sqlite3Malloc(). */ SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){ - assert( sz<=65536+8 ); /* These allocations are never very large */ return pcache1Alloc(sz); } /* ** Free an allocated buffer obtained from sqlite3PageMalloc(). @@ -55938,36 +46064,39 @@ p->nHash = nNew; } } /* -** This function is used internally to remove the page pPage from the +** This function is used internally to remove the page pPage from the ** PGroup LRU list, if is part of it. If pPage is not part of the PGroup ** LRU list, then this function is a no-op. ** ** The PGroup mutex must be held when this function is called. */ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ + PCache1 *pCache; + assert( pPage!=0 ); - assert( PAGE_IS_UNPINNED(pPage) ); + assert( pPage->isPinned==0 ); + pCache = pPage->pCache; assert( pPage->pLruNext ); assert( pPage->pLruPrev ); - assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) ); + assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); pPage->pLruPrev->pLruNext = pPage->pLruNext; pPage->pLruNext->pLruPrev = pPage->pLruPrev; pPage->pLruNext = 0; - /* pPage->pLruPrev = 0; - ** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */ + pPage->pLruPrev = 0; + pPage->isPinned = 1; assert( pPage->isAnchor==0 ); - assert( pPage->pCache->pGroup->lru.isAnchor==1 ); - pPage->pCache->nRecyclable--; + assert( pCache->pGroup->lru.isAnchor==1 ); + pCache->nRecyclable--; return pPage; } /* -** Remove the page supplied as an argument from the hash table +** Remove the page supplied as an argument from the hash table ** (PCache1.apHash structure) that it is currently stored in. ** Also free the page if freePage is true. ** ** The PGroup mutex must be held when this function is called. */ @@ -55991,15 +46120,15 @@ */ static void pcache1EnforceMaxPage(PCache1 *pCache){ PGroup *pGroup = pCache->pGroup; PgHdr1 *p; assert( sqlite3_mutex_held(pGroup->mutex) ); - while( pGroup->nPurgeable>pGroup->nMaxPage + while( pGroup->nCurrentPage>pGroup->nMaxPage && (p=pGroup->lru.pLruPrev)->isAnchor==0 ){ assert( p->pCache->pGroup==pGroup ); - assert( PAGE_IS_UNPINNED(p) ); + assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p, 1); } if( pCache->nPage==0 && pCache->pBulk ){ sqlite3_free(pCache->pBulk); @@ -56006,12 +46135,12 @@ pCache->pBulk = pCache->pFree = 0; } } /* -** Discard all pages from cache pCache with a page number (key value) -** greater than or equal to iLimit. Any pinned pages that meet this +** Discard all pages from cache pCache with a page number (key value) +** greater than or equal to iLimit. Any pinned pages that meet this ** criteria are unpinned before they are discarded. ** ** The PCache mutex must be held when this function is called. */ static void pcache1TruncateUnsafe( @@ -56039,16 +46168,16 @@ } for(;;){ PgHdr1 **pp; PgHdr1 *pPage; assert( hnHash ); - pp = &pCache->apHash[h]; + pp = &pCache->apHash[h]; while( (pPage = *pp)!=0 ){ if( pPage->iKey>=iLimit ){ pCache->nPage--; *pp = pPage->pNext; - if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage); + if( !pPage->isPinned ) pcache1PinPage(pPage); pcache1FreePage(pPage); }else{ pp = &pPage->pNext; TESTONLY( if( nPage>=0 ) nPage++; ) } @@ -56078,11 +46207,11 @@ ** ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT ** ** * Use a unified cache in single-threaded applications that have ** configured a start-time buffer for use as page-cache memory using - ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL + ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL ** pBuf argument. ** ** * Otherwise use separate caches (mode-1) */ #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) @@ -56113,11 +46242,11 @@ return SQLITE_OK; } /* ** Implementation of the sqlite3_pcache.xShutdown method. -** Note that the static mutex allocated in xInit does +** Note that the static mutex allocated in xInit does ** not need to be freed. */ static void pcache1Shutdown(void *NotUsed){ UNUSED_PARAMETER(NotUsed); assert( pcache1.isInit!=0 ); @@ -56147,28 +46276,25 @@ pGroup = (PGroup*)&pCache[1]; pGroup->mxPinned = 10; }else{ pGroup = &pcache1.grp; } - pcache1EnterMutex(pGroup); if( pGroup->lru.isAnchor==0 ){ pGroup->lru.isAnchor = 1; pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru; } pCache->pGroup = pGroup; pCache->szPage = szPage; pCache->szExtra = szExtra; pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1)); pCache->bPurgeable = (bPurgeable ? 1 : 0); + pcache1EnterMutex(pGroup); pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pCache->pnPurgeable = &pGroup->nPurgeable; - }else{ - pCache->pnPurgeable = &pCache->nPurgeableDummy; } pcache1LeaveMutex(pGroup); if( pCache->nHash==0 ){ pcache1Destroy((sqlite3_pcache*)pCache); pCache = 0; @@ -56176,44 +46302,38 @@ } return (sqlite3_pcache *)pCache; } /* -** Implementation of the sqlite3_pcache.xCachesize method. +** Implementation of the sqlite3_pcache.xCachesize method. ** ** Configure the cache_size limit for a cache. */ static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ PCache1 *pCache = (PCache1 *)p; - u32 n; - assert( nMax>=0 ); if( pCache->bPurgeable ){ PGroup *pGroup = pCache->pGroup; pcache1EnterMutex(pGroup); - n = (u32)nMax; - if( n > 0x7fff0000 - pGroup->nMaxPage + pCache->nMax ){ - n = 0x7fff0000 - pGroup->nMaxPage + pCache->nMax; - } - pGroup->nMaxPage += (n - pCache->nMax); + pGroup->nMaxPage += (nMax - pCache->nMax); pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pCache->nMax = n; + pCache->nMax = nMax; pCache->n90pct = pCache->nMax*9/10; pcache1EnforceMaxPage(pCache); pcache1LeaveMutex(pGroup); } } /* -** Implementation of the sqlite3_pcache.xShrink method. +** Implementation of the sqlite3_pcache.xShrink method. ** ** Free up as much memory as possible. */ static void pcache1Shrink(sqlite3_pcache *p){ PCache1 *pCache = (PCache1*)p; if( pCache->bPurgeable ){ PGroup *pGroup = pCache->pGroup; - unsigned int savedMaxPage; + int savedMaxPage; pcache1EnterMutex(pGroup); savedMaxPage = pGroup->nMaxPage; pGroup->nMaxPage = 0; pcache1EnforceMaxPage(pCache); pGroup->nMaxPage = savedMaxPage; @@ -56220,11 +46340,11 @@ pcache1LeaveMutex(pGroup); } } /* -** Implementation of the sqlite3_pcache.xPagecount method. +** Implementation of the sqlite3_pcache.xPagecount method. */ static int pcache1Pagecount(sqlite3_pcache *p){ int n; PCache1 *pCache = (PCache1*)p; pcache1EnterMutex(pCache->pGroup); @@ -56241,12 +46361,12 @@ ** This steps are broken out into a separate procedure because they are ** usually not needed, and by avoiding the stack initialization required ** for these steps, the main pcache1Fetch() procedure can run faster. */ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( - PCache1 *pCache, - unsigned int iKey, + PCache1 *pCache, + unsigned int iKey, int createFlag ){ unsigned int nPinned; PGroup *pGroup = pCache->pGroup; PgHdr1 *pPage = 0; @@ -56272,24 +46392,24 @@ && !pGroup->lru.pLruPrev->isAnchor && ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache)) ){ PCache1 *pOther; pPage = pGroup->lru.pLruPrev; - assert( PAGE_IS_UNPINNED(pPage) ); + assert( pPage->isPinned==0 ); pcache1RemoveFromHash(pPage, 0); pcache1PinPage(pPage); pOther = pPage->pCache; if( pOther->szAlloc != pCache->szAlloc ){ pcache1FreePage(pPage); pPage = 0; }else{ - pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable); + pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); } } - /* Step 5. If a usable page buffer has still not been found, - ** attempt to allocate a new one. + /* Step 5. If a usable page buffer has still not been found, + ** attempt to allocate a new one. */ if( !pPage ){ pPage = pcache1AllocPage(pCache, createFlag==1); } @@ -56297,13 +46417,13 @@ unsigned int h = iKey % pCache->nHash; pCache->nPage++; pPage->iKey = iKey; pPage->pNext = pCache->apHash[h]; pPage->pCache = pCache; + pPage->pLruPrev = 0; pPage->pLruNext = 0; - /* pPage->pLruPrev = 0; - ** No need to clear pLruPrev since it is not accessed when pLruNext==0 */ + pPage->isPinned = 1; *(void **)pPage->page.pExtra = 0; pCache->apHash[h] = pPage; if( iKey>pCache->iMaxKey ){ pCache->iMaxKey = iKey; } @@ -56310,17 +46430,17 @@ } return pPage; } /* -** Implementation of the sqlite3_pcache.xFetch method. +** Implementation of the sqlite3_pcache.xFetch method. ** ** Fetch a page by key value. ** ** Whether or not a new page may be allocated by this function depends on ** the value of the createFlag argument. 0 means do not allocate a new -** page. 1 means allocate a new page if space is easily available. 2 +** page. 1 means allocate a new page if space is easily available. 2 ** means to try really hard to allocate a new page. ** ** For a non-purgeable cache (a cache used as the storage for an in-memory ** database) there is really no difference between createFlag 1 and 2. So ** the calling function (pcache.c) will never have a createFlag of 1 on @@ -56327,11 +46447,11 @@ ** a non-purgeable cache. ** ** There are three different approaches to obtaining space for a page, ** depending on the value of parameter createFlag (which may be 0, 1 or 2). ** -** 1. Regardless of the value of createFlag, the cache is searched for a +** 1. Regardless of the value of createFlag, the cache is searched for a ** copy of the requested page. If one is found, it is returned. ** ** 2. If createFlag==0 and the page is not already in the cache, NULL is ** returned. ** @@ -56341,17 +46461,17 @@ ** ** (a) the number of pages pinned by the cache is greater than ** PCache1.nMax, or ** ** (b) the number of pages pinned by the cache is greater than -** the sum of nMax for all purgeable caches, less the sum of +** the sum of nMax for all purgeable caches, less the sum of ** nMin for all other purgeable caches, or ** ** 4. If none of the first three conditions apply and the cache is marked ** as purgeable, and if one of the following is true: ** -** (a) The number of pages allocated for the cache is already +** (a) The number of pages allocated for the cache is already ** PCache1.nMax, or ** ** (b) The number of pages allocated for all purgeable caches is ** already equal to or greater than the sum of nMax for all ** purgeable caches, @@ -56359,22 +46479,22 @@ ** (c) The system is under memory pressure and wants to avoid ** unnecessary pages cache entry allocations ** ** then attempt to recycle a page from the LRU list. If it is the right ** size, return the recycled buffer. Otherwise, free the buffer and -** proceed to step 5. +** proceed to step 5. ** ** 5. Otherwise, allocate and return a new page buffer. ** ** There are two versions of this routine. pcache1FetchWithMutex() is ** the general case. pcache1FetchNoMutex() is a faster implementation for ** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper ** invokes the appropriate routine. */ static PgHdr1 *pcache1FetchNoMutex( - sqlite3_pcache *p, - unsigned int iKey, + sqlite3_pcache *p, + unsigned int iKey, int createFlag ){ PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = 0; @@ -56385,11 +46505,11 @@ /* Step 2: If the page was found in the hash table, then return it. ** If the page was not in the hash table and createFlag is 0, abort. ** Otherwise (page not in hash and createFlag!=0) continue with ** subsequent steps to try to create the page. */ if( pPage ){ - if( PAGE_IS_UNPINNED(pPage) ){ + if( !pPage->isPinned ){ return pcache1PinPage(pPage); }else{ return pPage; } }else if( createFlag ){ @@ -56399,12 +46519,12 @@ return 0; } } #if PCACHE1_MIGHT_USE_GROUP_MUTEX static PgHdr1 *pcache1FetchWithMutex( - sqlite3_pcache *p, - unsigned int iKey, + sqlite3_pcache *p, + unsigned int iKey, int createFlag ){ PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage; @@ -56414,12 +46534,12 @@ pcache1LeaveMutex(pCache->pGroup); return pPage; } #endif static sqlite3_pcache_page *pcache1Fetch( - sqlite3_pcache *p, - unsigned int iKey, + sqlite3_pcache *p, + unsigned int iKey, int createFlag ){ #if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG) PCache1 *pCache = (PCache1 *)p; #endif @@ -56445,43 +46565,44 @@ ** Implementation of the sqlite3_pcache.xUnpin method. ** ** Mark a page as unpinned (eligible for asynchronous recycling). */ static void pcache1Unpin( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, + sqlite3_pcache *p, + sqlite3_pcache_page *pPg, int reuseUnlikely ){ PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = (PgHdr1 *)pPg; PGroup *pGroup = pCache->pGroup; - + assert( pPage->pCache==pCache ); pcache1EnterMutex(pGroup); - /* It is an error to call this function if the page is already + /* It is an error to call this function if the page is already ** part of the PGroup LRU list. */ - assert( pPage->pLruNext==0 ); - assert( PAGE_IS_PINNED(pPage) ); + assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); + assert( pPage->isPinned==1 ); - if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){ + if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ pcache1RemoveFromHash(pPage, 1); }else{ /* Add the page to the PGroup LRU list. */ PgHdr1 **ppFirst = &pGroup->lru.pLruNext; pPage->pLruPrev = &pGroup->lru; (pPage->pLruNext = *ppFirst)->pLruPrev = pPage; *ppFirst = pPage; pCache->nRecyclable++; + pPage->isPinned = 0; } pcache1LeaveMutex(pCache->pGroup); } /* -** Implementation of the sqlite3_pcache.xRekey method. +** Implementation of the sqlite3_pcache.xRekey method. */ static void pcache1Rekey( sqlite3_pcache *p, sqlite3_pcache_page *pPg, unsigned int iOld, @@ -56488,39 +46609,36 @@ unsigned int iNew ){ PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = (PgHdr1 *)pPg; PgHdr1 **pp; - unsigned int hOld, hNew; + unsigned int h; assert( pPage->iKey==iOld ); assert( pPage->pCache==pCache ); - assert( iOld!=iNew ); /* The page number really is changing */ pcache1EnterMutex(pCache->pGroup); - assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */ - hOld = iOld%pCache->nHash; - pp = &pCache->apHash[hOld]; + h = iOld%pCache->nHash; + pp = &pCache->apHash[h]; while( (*pp)!=pPage ){ pp = &(*pp)->pNext; } *pp = pPage->pNext; - assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */ - hNew = iNew%pCache->nHash; + h = iNew%pCache->nHash; pPage->iKey = iNew; - pPage->pNext = pCache->apHash[hNew]; - pCache->apHash[hNew] = pPage; + pPage->pNext = pCache->apHash[h]; + pCache->apHash[h] = pPage; if( iNew>pCache->iMaxKey ){ pCache->iMaxKey = iNew; } pcache1LeaveMutex(pCache->pGroup); } /* -** Implementation of the sqlite3_pcache.xTruncate method. +** Implementation of the sqlite3_pcache.xTruncate method. ** ** Discard all unpinned pages in the cache with a page number equal to ** or greater than parameter iLimit. Any pinned pages with a page number ** equal to or greater than iLimit are implicitly unpinned. */ @@ -56533,11 +46651,11 @@ } pcache1LeaveMutex(pCache->pGroup); } /* -** Implementation of the sqlite3_pcache.xDestroy method. +** Implementation of the sqlite3_pcache.xDestroy method. ** ** Destroy a cache allocated using pcache1Create(). */ static void pcache1Destroy(sqlite3_pcache *p){ PCache1 *pCache = (PCache1 *)p; @@ -56599,11 +46717,11 @@ ** This function is called to free superfluous dynamically allocated memory ** held by the pager system. Memory in use by any SQLite pager allocated ** by the current thread may be sqlite3_free()ed. ** ** nReq is the number of bytes of memory required. Once this much has -** been released, the function returns. The return value is the total number +** been released, the function returns. The return value is the total number ** of bytes of memory released. */ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); @@ -56614,11 +46732,14 @@ while( (nReq<0 || nFreeisAnchor==0 ){ nFree += pcache1MemSize(p->page.pBuf); - assert( PAGE_IS_UNPINNED(p) ); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + nFree += sqlite3MemSize(p); +#endif + assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p, 1); } pcache1LeaveMutex(&pcache1.grp); } @@ -56638,14 +46759,14 @@ int *pnRecyclable /* OUT: Total number of pages available for recycling */ ){ PgHdr1 *p; int nRecyclable = 0; for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ - assert( PAGE_IS_UNPINNED(p) ); + assert( p->isPinned==0 ); nRecyclable++; } - *pnCurrent = pcache1.grp.nPurgeable; + *pnCurrent = pcache1.grp.nCurrentPage; *pnMax = (int)pcache1.grp.nMaxPage; *pnMin = (int)pcache1.grp.nMinPage; *pnRecyclable = nRecyclable; } #endif @@ -56687,18 +46808,18 @@ ** obviously. The INSERT primitive adds a new element to the RowSet. ** TEST checks to see if an element is already in the RowSet. SMALLEST ** extracts the least value from the RowSet. ** ** The INSERT primitive might allocate additional memory. Memory is -** allocated in chunks so most INSERTs do no allocation. There is an +** allocated in chunks so most INSERTs do no allocation. There is an ** upper bound on the size of allocated memory. No memory is freed ** until DESTROY. ** ** The TEST primitive includes a "batch" number. The TEST primitive ** will only see elements that were inserted before the last change ** in the batch number. In other words, if an INSERT occurs between -** two TESTs where the TESTs have the same batch number, then the +** two TESTs where the TESTs have the same batch nubmer, then the ** value added by the INSERT will not be visible to the second TEST. ** The initial batch number is zero, so if the very first TEST contains ** a non-zero batch number, it will see all prior INSERTs. ** ** No INSERTs may occurs after a SMALLEST. An assertion will fail if @@ -56735,11 +46856,11 @@ ** This same object is reused to store a linked list of trees of RowSetEntry ** objects. In that alternative use, pRight points to the next entry ** in the list, pLeft points to the tree, and v is unused. The ** RowSet.pForest value points to the head of this forest list. */ -struct RowSetEntry { +struct RowSetEntry { i64 v; /* ROWID value for this entry */ struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ }; @@ -56776,37 +46897,43 @@ */ #define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ #define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ /* -** Allocate a RowSet object. Return NULL if a memory allocation -** error occurs. +** Turn bulk memory into a RowSet object. N bytes of memory +** are available at pSpace. The db pointer is used as a memory context +** for any subsequent allocations that need to occur. +** Return a pointer to the new RowSet object. +** +** It must be the case that N is sufficient to make a Rowset. If not +** an assertion fault occurs. +** +** If N is larger than the minimum, use the surplus as an initial +** allocation of entries available to be filled. */ -SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db){ - RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p)); - if( p ){ - int N = sqlite3DbMallocSize(db, p); - p->pChunk = 0; - p->db = db; - p->pEntry = 0; - p->pLast = 0; - p->pForest = 0; - p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); - p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); - p->rsFlags = ROWSET_SORTED; - p->iBatch = 0; - } +SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ + RowSet *p; + assert( N >= ROUND8(sizeof(*p)) ); + p = pSpace; + p->pChunk = 0; + p->db = db; + p->pEntry = 0; + p->pLast = 0; + p->pForest = 0; + p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); + p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); + p->rsFlags = ROWSET_SORTED; + p->iBatch = 0; return p; } /* ** Deallocate all chunks from a RowSet. This frees all memory that ** the RowSet has allocated over its lifetime. This routine is ** the destructor for the RowSet. */ -SQLITE_PRIVATE void sqlite3RowSetClear(void *pArg){ - RowSet *p = (RowSet*)pArg; +SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ struct RowSetChunk *pChunk, *pNextChunk; for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ pNextChunk = pChunk->pNextChunk; sqlite3DbFree(p->db, pChunk); } @@ -56816,24 +46943,14 @@ p->pLast = 0; p->pForest = 0; p->rsFlags = ROWSET_SORTED; } -/* -** Deallocate all chunks from a RowSet. This frees all memory that -** the RowSet has allocated over its lifetime. This routine is -** the destructor for the RowSet. -*/ -SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){ - sqlite3RowSetClear(pArg); - sqlite3DbFree(((RowSet*)pArg)->db, pArg); -} - /* ** Allocate a new RowSetEntry object that is associated with the ** given RowSet. Return a pointer to the new and completely uninitialized -** object. +** objected. ** ** In an OOM situation, the RowSet.db->mallocFailed flag is set and this ** routine returns NULL. */ static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ @@ -56887,11 +47004,11 @@ } /* ** Merge two lists of RowSetEntry objects. Remove duplicates. ** -** The input lists are connected via pRight pointers and are +** The input lists are connected via pRight pointers and are ** assumed to each already be in sorted order. */ static struct RowSetEntry *rowSetEntryMerge( struct RowSetEntry *pA, /* First sorted list to be merged */ struct RowSetEntry *pB /* Second sorted list to be merged */ @@ -56924,11 +47041,11 @@ } /* ** Sort all elements on the list of RowSetEntry objects into order of ** increasing v. -*/ +*/ static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ unsigned int i; struct RowSetEntry *pNext, *aBucket[40]; memset(aBucket, 0, sizeof(aBucket)); @@ -56997,11 +47114,11 @@ ){ struct RowSetEntry *p; /* Root of the new tree */ struct RowSetEntry *pLeft; /* Left subtree */ if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/ /* Prevent unnecessary deep recursion when we run out of entries */ - return 0; + return 0; } if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/ /* This branch causes a *balanced* tree to be generated. A valid tree ** is still generated without this branch, but the tree is wildly ** unbalanced and inefficient. */ @@ -57105,11 +47222,11 @@ if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/ p = pRowSet->pEntry; if( p ){ struct RowSetEntry **ppPrevTree = &pRowSet->pForest; if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/ - /* Only sort the current set of entries if they need it */ + /* Only sort the current set of entiries if they need it */ p = rowSetEntrySort(p); } for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ ppPrevTree = &pTree->pRight; if( pTree->pLeft==0 ){ @@ -57167,11 +47284,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of the page cache subsystem or "pager". -** +** ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while @@ -57190,25 +47307,25 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** This header file defines the interface to the write-ahead logging -** system. Refer to the comments below and the header comment attached to +** This header file defines the interface to the write-ahead logging +** system. Refer to the comments below and the header comment attached to ** the implementation of each function in log.c for further details. */ #ifndef SQLITE_WAL_H #define SQLITE_WAL_H /* #include "sqliteInt.h" */ -/* Macros for extracting appropriate sync flags for either transaction -** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)): +/* Additional values that can be added to the sync_flags argument of +** sqlite3WalFrames(): */ -#define WAL_SYNC_FLAGS(X) ((X)&0x03) -#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03) +#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ +#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ #ifdef SQLITE_OMIT_WAL # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalLimit(x,y) # define sqlite3WalClose(v,w,x,y,z) 0 @@ -57226,17 +47343,16 @@ # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 # define sqlite3WalFramesize(z) 0 # define sqlite3WalFindFrame(x,y,z) 0 # define sqlite3WalFile(x) 0 -# undef SQLITE_USE_SEH #else #define WAL_SAVEPOINT_NDATA 4 -/* Connection to a write-ahead log (WAL) file. -** There is one object of this type for each pager. +/* Connection to a write-ahead log (WAL) file. +** There is one object of this type for each pager. */ typedef struct Wal Wal; /* Open and close a connection to a write-ahead log. */ SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); @@ -57243,11 +47359,11 @@ SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); /* Set the limiting size of a WAL file. */ SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); -/* Used by readers to open (lock) and close (unlock) a snapshot. A +/* Used by readers to open (lock) and close (unlock) a snapshot. A ** snapshot is like a read-transaction. It is the state of the database ** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and ** preserves the current state even if the other threads or processes ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the ** transaction and releases the lock. @@ -57278,11 +47394,11 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData); /* Write a frame or frames to the log. */ SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); -/* Copy pages from the log to the database file */ +/* Copy pages from the log to the database file */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Write-ahead log connection */ sqlite3 *db, /* Check this handle's interrupt flag */ int eMode, /* One of PASSIVE, FULL and RESTART */ int (*xBusy)(void*), /* Function to call when busy */ @@ -57306,20 +47422,18 @@ */ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op); /* Return true if the argument is non-NULL and the WAL module is using ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the -** WAL module is using shared-memory, return false. +** WAL module is using shared-memory, return false. */ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); #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); -SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal); #endif #ifdef SQLITE_ENABLE_ZIPVFS /* If the WAL file is not empty, return the number of bytes of content ** stored in each frame (i.e. the db page-size when the WAL was created). @@ -57328,19 +47442,10 @@ #endif /* Return the sqlite3_file object for the WAL file */ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock); -SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db); -#endif - -#ifdef SQLITE_USE_SEH -SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*); -#endif - #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* SQLITE_WAL_H */ /************** End of wal.h *************************************************/ /************** Continuing where we left off in pager.c **********************/ @@ -57357,64 +47462,64 @@ ** Otherwise, the page is not synced until the xSync method of the VFS ** is called successfully on the file containing the page. ** ** Definition: A page of the database file is said to be "overwriteable" if ** one or more of the following are true about the page: -** +** ** (a) The original content of the page as it was at the beginning of ** the transaction has been written into the rollback journal and ** synced. -** +** ** (b) The page was a freelist leaf page at the start of the transaction. -** +** ** (c) The page number is greater than the largest page that existed in ** the database file at the start of the transaction. -** +** ** (1) A page of the database file is never overwritten unless one of the ** following are true: -** +** ** (a) The page and all other pages on the same sector are overwriteable. -** +** ** (b) The atomic page write optimization is enabled, and the entire ** transaction other than the update of the transaction sequence ** number consists of a single page change. -** +** ** (2) The content of a page written into the rollback journal exactly matches ** both the content in the database when the rollback journal was written ** and the content in the database at the beginning of the current ** transaction. -** +** ** (3) Writes to the database file are an integer multiple of the page size ** in length and are aligned on a page boundary. -** +** ** (4) Reads from the database file are either aligned on a page boundary and ** an integer multiple of the page size in length or are taken from the ** first 100 bytes of the database file. -** +** ** (5) All writes to the database file are synced prior to the rollback journal ** being deleted, truncated, or zeroed. -** -** (6) If a super-journal file is used, then all writes to the database file -** are synced prior to the super-journal being deleted. -** +** +** (6) If a master journal file is used, then all writes to the database file +** are synced prior to the master journal being deleted. +** ** Definition: Two databases (or the same database at two points it time) ** are said to be "logically equivalent" if they give the same answer to ** all queries. Note in particular the content of freelist leaf ** pages can be changed arbitrarily without affecting the logical equivalence ** of the database. -** +** ** (7) At any time, if any subset, including the empty set and the total set, -** of the unsynced changes to a rollback journal are removed and the +** of the unsynced changes to a rollback journal are removed and the ** journal is rolled back, the resulting database file will be logically ** equivalent to the database file at the beginning of the transaction. -** +** ** (8) When a transaction is rolled back, the xTruncate method of the VFS ** is called to restore the database file to the same size it was at ** the beginning of the transaction. (In some VFSes, the xTruncate ** method is a no-op, but that does not change the fact the SQLite will ** invoke it.) -** +** ** (9) Whenever the database file is modified, at least one bit in the range ** of bytes from 24 through 39 inclusive will be changed prior to releasing ** the EXCLUSIVE lock, thus signaling other connections on the same ** database to flush their caches. ** @@ -57443,18 +47548,18 @@ #define PAGERTRACE(X) #endif /* ** The following two macros are used within the PAGERTRACE() macros above -** to print out file-descriptors. +** to print out file-descriptors. ** ** PAGERID() takes a pointer to a Pager struct as its argument. The ** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file ** struct as its argument. */ -#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd)) -#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd)) +#define PAGERID(p) ((int)(p->fd)) +#define FILEHANDLEID(fd) ((int)fd) /* ** The Pager.eState variable stores the current 'state' of a pager. A ** pager may be in any one of the seven states shown in the following ** state diagram. @@ -57464,11 +47569,11 @@ ** V | | ** +---------> READER-------+ | ** | | | ** | V | ** |<-------WRITER_LOCKED------> ERROR -** | | ^ +** | | ^ ** | V | ** |<------WRITER_CACHEMOD-------->| ** | | | ** | V | ** |<-------WRITER_DBMOD---------->| @@ -57476,11 +47581,11 @@ ** | V | ** +<------WRITER_FINISHED-------->+ ** ** ** List of state transitions and the C [function] that performs each: -** +** ** OPEN -> READER [sqlite3PagerSharedLock] ** READER -> OPEN [pager_unlock] ** ** READER -> WRITER_LOCKED [sqlite3PagerBegin] ** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal] @@ -57488,11 +47593,11 @@ ** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne] ** WRITER_*** -> READER [pager_end_transaction] ** ** WRITER_*** -> ERROR [pager_error] ** ERROR -> OPEN [pager_unlock] -** +** ** ** OPEN: ** ** The pager starts up in this state. Nothing is guaranteed in this ** state - the file may or may not be locked and the database size is @@ -57502,52 +47607,52 @@ ** * Any lock, or no lock at all, may be held on the database file. ** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. ** ** READER: ** -** In this state all the requirements for reading the database in +** In this state all the requirements for reading the database in ** rollback (non-WAL) mode are met. Unless the pager is (or recently -** was) in exclusive-locking mode, a user-level read transaction is +** was) in exclusive-locking mode, a user-level read transaction is ** open. The database size is known in this state. ** ** A connection running with locking_mode=normal enters this state when ** it opens a read-transaction on the database and returns to state ** OPEN after the read-transaction is completed. However a connection ** running in locking_mode=exclusive (including temp databases) remains in ** this state even after the read-transaction is closed. The only way ** a locking_mode=exclusive connection can transition from READER to OPEN ** is via the ERROR state (see below). -** +** ** * A read transaction may be active (but a write-transaction cannot). ** * A SHARED or greater lock is held on the database file. -** * The dbSize variable may be trusted (even if a user-level read +** * The dbSize variable may be trusted (even if a user-level read ** transaction is not active). The dbOrigSize and dbFileSize variables ** may not be trusted at this point. ** * If the database is a WAL database, then the WAL connection is open. -** * Even if a read-transaction is not open, it is guaranteed that +** * Even if a read-transaction is not open, it is guaranteed that ** there is no hot-journal in the file-system. ** ** WRITER_LOCKED: ** ** The pager moves to this state from READER when a write-transaction -** is first opened on the database. In WRITER_LOCKED state, all locks -** required to start a write-transaction are held, but no actual +** is first opened on the database. In WRITER_LOCKED state, all locks +** required to start a write-transaction are held, but no actual ** modifications to the cache or database have taken place. ** -** In rollback mode, a RESERVED or (if the transaction was opened with +** In rollback mode, a RESERVED or (if the transaction was opened with ** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when -** moving to this state, but the journal file is not written to or opened -** to in this state. If the transaction is committed or rolled back while -** in WRITER_LOCKED state, all that is required is to unlock the database +** moving to this state, but the journal file is not written to or opened +** to in this state. If the transaction is committed or rolled back while +** in WRITER_LOCKED state, all that is required is to unlock the database ** file. ** ** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file. ** If the connection is running with locking_mode=exclusive, an attempt ** is made to obtain an EXCLUSIVE lock on the database file. ** ** * A write transaction is active. -** * If the connection is open in rollback-mode, a RESERVED or greater +** * If the connection is open in rollback-mode, a RESERVED or greater ** lock is held on the database file. ** * If the connection is open in WAL-mode, a WAL write transaction ** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully ** called). ** * The dbSize, dbOrigSize and dbFileSize variables are all valid. @@ -57562,11 +47667,11 @@ ** is opened (if it is not already open) and a header written to the ** start of it. The database file on disk has not been modified. ** ** * A write transaction is active. ** * A RESERVED or greater lock is held on the database file. -** * The journal file is open and the first header has been written +** * The journal file is open and the first header has been written ** to it, but the header has not been synced to disk. ** * The contents of the page cache have been modified. ** ** WRITER_DBMOD: ** @@ -57575,11 +47680,11 @@ ** never enter this state (since they do not modify the database file, ** just the log file). ** ** * A write transaction is active. ** * An EXCLUSIVE or greater lock is held on the database file. -** * The journal file is open and the first header has been written +** * The journal file is open and the first header has been written ** and synced to disk. ** * The contents of the page cache have been modified (and possibly ** written to disk). ** ** WRITER_FINISHED: @@ -57587,48 +47692,48 @@ ** It is not possible for a WAL connection to enter this state. ** ** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD ** state after the entire transaction has been successfully written into the ** database file. In this state the transaction may be committed simply -** by finalizing the journal file. Once in WRITER_FINISHED state, it is -** not possible to modify the database further. At this point, the upper +** by finalizing the journal file. Once in WRITER_FINISHED state, it is +** not possible to modify the database further. At this point, the upper ** layer must either commit or rollback the transaction. ** ** * A write transaction is active. ** * An EXCLUSIVE or greater lock is held on the database file. ** * All writing and syncing of journal and database data has finished. ** If no error occurred, all that remains is to finalize the journal to ** commit the transaction. If an error did occur, the caller will need -** to rollback the transaction. +** to rollback the transaction. ** ** ERROR: ** ** The ERROR state is entered when an IO or disk-full error (including -** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it -** difficult to be sure that the in-memory pager state (cache contents, +** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it +** difficult to be sure that the in-memory pager state (cache contents, ** db size etc.) are consistent with the contents of the file-system. ** ** Temporary pager files may enter the ERROR state, but in-memory pagers ** cannot. ** -** For example, if an IO error occurs while performing a rollback, +** For example, if an IO error occurs while performing a rollback, ** the contents of the page-cache may be left in an inconsistent state. ** At this point it would be dangerous to change back to READER state ** (as usually happens after a rollback). Any subsequent readers might ** report database corruption (due to the inconsistent cache), and if ** they upgrade to writers, they may inadvertently corrupt the database ** file. To avoid this hazard, the pager switches into the ERROR state ** instead of READER following such an error. ** ** Once it has entered the ERROR state, any attempt to use the pager -** to read or write data returns an error. Eventually, once all +** to read or write data returns an error. Eventually, once all ** outstanding transactions have been abandoned, the pager is able to -** transition back to OPEN state, discarding the contents of the +** transition back to OPEN state, discarding the contents of the ** page-cache and any other in-memory state at the same time. Everything -** is reloaded from disk (and, if necessary, hot-journal rollback performed) +** is reloaded from disk (and, if necessary, hot-journal rollback peformed) ** when a read-transaction is next opened on the pager (transitioning -** the pager into READER state). At that point the system has recovered +** the pager into READER state). At that point the system has recovered ** from the error. ** ** Specifically, the pager jumps into the ERROR state if: ** ** 1. An error occurs while attempting a rollback. This happens in @@ -57640,35 +47745,35 @@ ** 3. An error occurs while attempting to write to the journal or ** database file in function pagerStress() in order to free up ** memory. ** ** In other cases, the error is returned to the b-tree layer. The b-tree -** layer then attempts a rollback operation. If the error condition +** layer then attempts a rollback operation. If the error condition ** persists, the pager enters the ERROR state via condition (1) above. ** ** Condition (3) is necessary because it can be triggered by a read-only ** statement executed within a transaction. In this case, if the error ** code were simply returned to the user, the b-tree layer would not ** automatically attempt a rollback, as it assumes that an error in a -** read-only statement cannot leave the pager in an internally inconsistent +** read-only statement cannot leave the pager in an internally inconsistent ** state. ** ** * The Pager.errCode variable is set to something other than SQLITE_OK. ** * There are one or more outstanding references to pages (after the ** last reference is dropped the pager should move back to OPEN state). ** * The pager is not an in-memory pager. -** +** ** ** Notes: ** ** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the ** connection is open in WAL mode. A WAL connection is always in one ** of the first four states. ** ** * Normally, a connection open in exclusive mode is never in PAGER_OPEN ** state. There are two exceptions: immediately after exclusive-mode has -** been turned on (and before any read or write transactions are +** been turned on (and before any read or write transactions are ** executed), and when the pager is leaving the "error state". ** ** * See also: assert_pager_state(). */ #define PAGER_OPEN 0 @@ -57678,11 +47783,11 @@ #define PAGER_WRITER_DBMOD 4 #define PAGER_WRITER_FINISHED 5 #define PAGER_ERROR 6 /* -** The Pager.eLock variable is almost always set to one of the +** The Pager.eLock variable is almost always set to one of the ** following locking-states, according to the lock currently held on ** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. ** This variable is kept up to date as locks are taken and released by ** the pagerLockDb() and pagerUnlockDb() wrappers. ** @@ -57693,24 +47798,24 @@ ** when unlocking the file, and only updated when locking the file if the ** VFS call is successful. This way, the Pager.eLock variable may be set ** to a less exclusive (lower) value than the lock that is actually held ** at the system level, but it is never set to a more exclusive value. ** -** This is usually safe. If an xUnlock fails or appears to fail, there may +** This is usually safe. If an xUnlock fails or appears to fail, there may ** be a few redundant xLock() calls or a lock may be held for longer than ** required, but nothing really goes wrong. ** ** The exception is when the database file is unlocked as the pager moves -** from ERROR to OPEN state. At this point there may be a hot-journal file +** from ERROR to OPEN state. At this point there may be a hot-journal file ** in the file-system that needs to be rolled back (as part of an OPEN->SHARED ** transition, by the same pager or any other). If the call to xUnlock() ** fails at this point and the pager is left holding an EXCLUSIVE lock, this ** can confuse the call to xCheckReservedLock() call made later as part ** of hot-journal detection. ** -** xCheckReservedLock() is defined as returning true "if there is a RESERVED -** lock held by this process or any others". So xCheckReservedLock may +** xCheckReservedLock() is defined as returning true "if there is a RESERVED +** lock held by this process or any others". So xCheckReservedLock may ** return true because the caller itself is holding an EXCLUSIVE lock (but ** doesn't know it because of a previous error in xUnlock). If this happens ** a hot-journal may be mistaken for a journal being created by an active ** transaction in another process, causing SQLite to read from the database ** without rolling it back. @@ -57717,22 +47822,36 @@ ** ** To work around this, if a call to xUnlock() fails when unlocking the ** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It ** is only changed back to a real locking state after a successful call ** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition -** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK +** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK ** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE ** lock on the database file before attempting to roll it back. See function ** PagerSharedLock() for more detail. ** -** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in +** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in ** PAGER_OPEN state. */ #define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1) /* -** The maximum allowed sector size. 64KiB. If the xSectorsize() method +** A macro used for invoking the codec if there is one +*/ +#ifdef SQLITE_HAS_CODEC +# define CODEC1(P,D,N,X,E) \ + if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; } +# define CODEC2(P,D,N,X,E,O) \ + if( P->xCodec==0 ){ O=(char*)D; }else \ + if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; } +#else +# define CODEC1(P,D,N,X,E) /* NO-OP */ +# define CODEC2(P,D,N,X,E,O) O=(char*)D +#endif + +/* +** The maximum allowed sector size. 64KiB. If the xSectorsize() method ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. ** This could conceivably cause corruption following a power failure on ** such a system. This is currently an undocumented limit. */ #define MAX_SECTOR_SIZE 0x10000 @@ -57744,11 +47863,11 @@ ** are stored in the Pager.aSavepoint[] array, which is allocated and ** resized using sqlite3Realloc(). ** ** When a savepoint is created, the PagerSavepoint.iHdrOffset field is ** set to 0. If a journal-header is written into the main journal while -** the savepoint is active, then iHdrOffset is set to the byte offset +** the savepoint is active, then iHdrOffset is set to the byte offset ** immediately following the last journal record written into the main ** journal before the journal-header. This is required during savepoint ** rollback (see pagerPlaybackSavepoint()). */ typedef struct PagerSavepoint PagerSavepoint; @@ -57756,11 +47875,10 @@ i64 iOffset; /* Starting offset in main journal */ i64 iHdrOffset; /* See above */ Bitvec *pInSavepoint; /* Set of pages in this savepoint */ Pgno nOrig; /* Original number of pages in file */ Pgno iSubRec; /* Index of first record in sub-journal */ - int bTruncateOnRelease; /* If stmt journal may be truncated on RELEASE */ #ifndef SQLITE_OMIT_WAL u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ #endif }; @@ -57795,48 +47913,48 @@ ** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for ** details. ** ** changeCountDone ** -** This boolean variable is used to make sure that the change-counter -** (the 4-byte header field at byte offset 24 of the database file) is -** not updated more often than necessary. +** This boolean variable is used to make sure that the change-counter +** (the 4-byte header field at byte offset 24 of the database file) is +** not updated more often than necessary. ** -** It is set to true when the change-counter field is updated, which +** It is set to true when the change-counter field is updated, which ** can only happen if an exclusive lock is held on the database file. -** It is cleared (set to false) whenever an exclusive lock is +** It is cleared (set to false) whenever an exclusive lock is ** relinquished on the database file. Each time a transaction is committed, ** The changeCountDone flag is inspected. If it is true, the work of ** updating the change-counter is omitted for the current transaction. ** -** This mechanism means that when running in exclusive mode, a connection +** This mechanism means that when running in exclusive mode, a connection ** need only update the change-counter once, for the first transaction ** committed. ** -** setSuper +** setMaster ** ** When PagerCommitPhaseOne() is called to commit a transaction, it may -** (or may not) specify a super-journal name to be written into the +** (or may not) specify a master-journal name to be written into the ** journal file before it is synced to disk. ** -** Whether or not a journal file contains a super-journal pointer affects -** the way in which the journal file is finalized after the transaction is +** Whether or not a journal file contains a master-journal pointer affects +** the way in which the journal file is finalized after the transaction is ** committed or rolled back when running in "journal_mode=PERSIST" mode. -** If a journal file does not contain a super-journal pointer, it is +** If a journal file does not contain a master-journal pointer, it is ** finalized by overwriting the first journal header with zeroes. If -** it does contain a super-journal pointer the journal file is finalized -** by truncating it to zero bytes, just as if the connection were +** it does contain a master-journal pointer the journal file is finalized +** by truncating it to zero bytes, just as if the connection were ** running in "journal_mode=truncate" mode. ** -** Journal files that contain super-journal pointers cannot be finalized +** Journal files that contain master journal pointers cannot be finalized ** simply by overwriting the first journal-header with zeroes, as the -** super-journal pointer could interfere with hot-journal rollback of any +** master journal pointer could interfere with hot-journal rollback of any ** subsequently interrupted transaction that reuses the journal file. ** ** The flag is cleared as soon as the journal file is finalized (either ** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the -** journal file from being successfully finalized, the setSuper flag +** journal file from being successfully finalized, the setMaster flag ** is cleared anyway (and the pager will move to ERROR state). ** ** doNotSpill ** ** This variables control the behavior of cache-spills (calls made by @@ -57848,33 +47966,33 @@ ** The SPILLFLAG_ROLLBACK case is done in a very obscure case that ** comes up during savepoint rollback that requires the pcache module ** to allocate a new page to prevent the journal file from being written ** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF ** case is a user preference. -** +** ** If the SPILLFLAG_NOSYNC bit is set, writing to the database from ** pagerStress() is permitted, but syncing the journal file is not. ** This flag is set by sqlite3PagerWrite() when the file-system sector-size ** is larger than the database page-size in order to prevent a journal sync -** from happening in between the journalling of two pages on the same sector. +** from happening in between the journalling of two pages on the same sector. ** ** subjInMemory ** ** This is a boolean variable. If true, then any required sub-journal ** is opened as an in-memory journal file. If false, then in-memory ** sub-journals are only used for in-memory pager files. ** -** This variable is updated by the upper layer each time a new +** This variable is updated by the upper layer each time a new ** write-transaction is opened. ** ** dbSize, dbOrigSize, dbFileSize ** ** Variable dbSize is set to the number of pages in the database file. ** It is valid in PAGER_READER and higher states (all states except for -** OPEN and ERROR). +** OPEN and ERROR). ** -** dbSize is set based on the size of the database file, which may be +** dbSize is set based on the size of the database file, which may be ** larger than the size of the database (the value stored at offset ** 28 of the database header by the btree). If the size of the file ** is not an integer multiple of the page-size, the value stored in ** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2). ** Except, any file that is greater than 0 bytes in size is considered @@ -57881,28 +47999,28 @@ ** to have at least one page. (i.e. a 1KB file with 2K page-size leads ** to dbSize==1). ** ** During a write-transaction, if pages with page-numbers greater than ** dbSize are modified in the cache, dbSize is updated accordingly. -** Similarly, if the database is truncated using PagerTruncateImage(), +** Similarly, if the database is truncated using PagerTruncateImage(), ** dbSize is updated. ** -** Variables dbOrigSize and dbFileSize are valid in states +** Variables dbOrigSize and dbFileSize are valid in states ** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize ** variable at the start of the transaction. It is used during rollback, ** and to determine whether or not pages need to be journalled before ** being modified. ** ** Throughout a write-transaction, dbFileSize contains the size of ** the file on disk in pages. It is set to a copy of dbSize when the ** write-transaction is first opened, and updated when VFS calls are made -** to write or truncate the database file on disk. +** to write or truncate the database file on disk. ** -** The only reason the dbFileSize variable is required is to suppress -** unnecessary calls to xTruncate() after committing a transaction. If, -** when a transaction is committed, the dbFileSize variable indicates -** that the database file is larger than the database image (Pager.dbSize), +** The only reason the dbFileSize variable is required is to suppress +** unnecessary calls to xTruncate() after committing a transaction. If, +** when a transaction is committed, the dbFileSize variable indicates +** that the database file is larger than the database image (Pager.dbSize), ** pager_truncate() is called. The pager_truncate() call uses xFilesize() ** to measure the database file on disk, and then truncates it if required. ** dbFileSize is not used when rolling back a transaction. In this case ** pager_truncate() is called unconditionally (which means there may be ** a call to xFilesize() that is not strictly required). In either case, @@ -57909,53 +48027,41 @@ ** pager_truncate() may cause the file to become smaller or larger. ** ** dbHintSize ** ** The dbHintSize variable is used to limit the number of calls made to -** the VFS xFileControl(FCNTL_SIZE_HINT) method. +** the VFS xFileControl(FCNTL_SIZE_HINT) method. ** ** dbHintSize is set to a copy of the dbSize variable when a ** write-transaction is opened (at the same time as dbFileSize and ** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called, ** dbHintSize is increased to the number of pages that correspond to the -** size-hint passed to the method call. See pager_write_pagelist() for +** size-hint passed to the method call. See pager_write_pagelist() for ** details. ** ** errCode ** ** The Pager.errCode variable is only ever used in PAGER_ERROR state. It -** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode -** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX +** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode +** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX ** sub-codes. -** -** syncFlags, walSyncFlags -** -** 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 */ u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ u8 useJournal; /* Use a rollback journal on this file */ 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 */ u8 memDb; /* True to inhibit all file I/O */ - u8 memVfs; /* VFS-implemented memory database */ /************************************************************************** ** The following block contains those class members that change during ** routine operation. Class members not in this block are either fixed ** when the pager is first created or else only change when there is a @@ -57965,11 +48071,11 @@ ** "configuration" of the pager. */ u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */ u8 eLock; /* Current lock held on database file */ u8 changeCountDone; /* Set after incrementing the change-counter */ - u8 setSuper; /* Super-jrnl name is written into jrnl */ + u8 setMaster; /* True if a m-j name has been written to jrnl */ u8 doNotSpill; /* Do not spill the cache when non-zero */ u8 subjInMemory; /* True to use in-memory sub-journals */ u8 bUseFetch; /* True to use xFetch() */ u8 hasHeldSharedLock; /* True if a shared lock has ever been held */ Pgno dbSize; /* Number of pages in the database */ @@ -58001,24 +48107,29 @@ u16 nExtra; /* Add this many bytes to each in-memory page */ i16 nReserve; /* Number of unused bytes at end of each page */ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ u32 sectorSize; /* Assumed sector size during rollback */ + int pageSize; /* Number of bytes in a page */ Pgno mxPgno; /* Maximum allowed size of the database */ - Pgno lckPgno; /* Page number for the locking page */ - i64 pageSize; /* Number of bytes in a page */ i64 journalSizeLimit; /* Size limit for persistent journal files */ char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - u32 aStat[4]; /* Total cache hits, misses, writes, spills */ + int aStat[3]; /* Total cache hits, misses and writes */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ +#ifdef SQLITE_HAS_CODEC + void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ + void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ + void (*xCodecFree)(void*); /* Destructor for the codec */ + void *pCodec; /* First argument to xCodec... methods */ +#endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ PCache *pPCache; /* Pointer to page cache object */ #ifndef SQLITE_OMIT_WAL Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ char *zWal; /* File name for write-ahead log */ @@ -58025,17 +48136,16 @@ #endif }; /* ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains -** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS +** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS ** or CACHE_WRITE to sqlite3_db_status(). */ #define PAGER_STAT_HIT 0 #define PAGER_STAT_MISS 1 #define PAGER_STAT_WRITE 2 -#define PAGER_STAT_SPILL 3 /* ** The following global variables hold counters used for ** testing purposes only. These variables do not exist in ** a non-testing build. These variables are not thread-safe. @@ -58083,11 +48193,11 @@ ** the following macro. */ #define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) /* -** The journal header size for this pager. This is usually the same +** The journal header size for this pager. This is usually the same ** size as a single disk sector. See also setSectorSize(). */ #define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) /* @@ -58110,41 +48220,42 @@ # define USEFETCH(x) ((x)->bUseFetch) #else # define USEFETCH(x) 0 #endif -#ifdef SQLITE_DIRECT_OVERFLOW_READ -/* -** Return true if page pgno can be read directly from the database file -** by the b-tree layer. This is the case if: -** -** (1) the database file is open -** (2) the VFS for the database is able to do unaligned sub-page reads -** (3) there are no dirty pages in the cache, and -** (4) the desired page is not currently in the wal file. -*/ -SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ - assert( pPager!=0 ); - assert( pPager->fd!=0 ); - if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */ - if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */ -#ifndef SQLITE_OMIT_WAL - if( pPager->pWal ){ - u32 iRead = 0; - (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - if( iRead ) return 0; /* Case (4) */ - } -#endif - assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 ); - if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd) - & SQLITE_IOCAP_SUBPAGE_READ)==0 ){ - return 0; /* Case (2) */ - } - return 1; -} -#endif - +/* +** The maximum legal page number is (2^31 - 1). +*/ +#define PAGER_MAX_PGNO 2147483647 + +/* +** The argument to this macro is a file descriptor (type sqlite3_file*). +** Return 0 if it is not open, or non-zero (but not 1) if it is. +** +** This is so that expressions can be written as: +** +** if( isOpen(pPager->jfd) ){ ... +** +** instead of +** +** if( pPager->jfd->pMethods ){ ... +*/ +#define isOpen(pFd) ((pFd)->pMethods!=0) + +/* +** 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. +*/ +#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; +} +#endif #ifndef SQLITE_OMIT_WAL # define pagerUseWal(x) ((x)->pWal!=0) #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 @@ -58151,11 +48262,11 @@ # define pagerWalFrames(v,w,x,y) 0 # define pagerOpenWalIfPresent(z) SQLITE_OK # define pagerBeginReadTransaction(z) SQLITE_OK #endif -#ifndef NDEBUG +#ifndef NDEBUG /* ** Usage: ** ** assert( assert_pager_state(pPager) ); ** @@ -58180,29 +48291,29 @@ ** the change-counter field, so the changeCountDone flag is always set. */ assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); assert( p->tempFile==0 || pPager->changeCountDone ); - /* If the useJournal flag is clear, the journal-mode must be "OFF". + /* If the useJournal flag is clear, the journal-mode must be "OFF". ** And if the journal-mode is "OFF", the journal file must not be open. */ assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal ); assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) ); - /* Check that MEMDB implies noSync. And an in-memory journal. Since - ** this means an in-memory pager performs no IO at all, it cannot encounter - ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing - ** a journal file. (although the in-memory journal implementation may - ** return SQLITE_IOERR_NOMEM while the journal file is being written). It - ** is therefore not possible for an in-memory pager to enter the ERROR + /* Check that MEMDB implies noSync. And an in-memory journal. Since + ** this means an in-memory pager performs no IO at all, it cannot encounter + ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing + ** a journal file. (although the in-memory journal implementation may + ** return SQLITE_IOERR_NOMEM while the journal file is being written). It + ** is therefore not possible for an in-memory pager to enter the ERROR ** state. */ if( MEMDB ){ assert( !isOpen(p->fd) ); assert( p->noSync ); - assert( p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_MEMORY + assert( p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_MEMORY ); assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); assert( pagerUseWal(p)==0 ); } @@ -58232,11 +48343,11 @@ assert( p->eLock>=RESERVED_LOCK ); } assert( pPager->dbSize==pPager->dbOrigSize ); assert( pPager->dbOrigSize==pPager->dbFileSize ); assert( pPager->dbOrigSize==pPager->dbHintSize ); - assert( pPager->setSuper==0 ); + assert( pPager->setMaster==0 ); break; case PAGER_WRITER_CACHEMOD: assert( p->eLock!=UNKNOWN_LOCK ); assert( pPager->errCode==SQLITE_OK ); @@ -58245,13 +48356,13 @@ ** journal file nor the WAL file are open. This happens during ** a rollback transaction that switches from journal_mode=off ** to journal_mode=wal. */ assert( p->eLock>=RESERVED_LOCK ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL ); } assert( pPager->dbOrigSize==pPager->dbFileSize ); assert( pPager->dbOrigSize==pPager->dbHintSize ); break; @@ -58259,26 +48370,24 @@ case PAGER_WRITER_DBMOD: assert( p->eLock==EXCLUSIVE_LOCK ); assert( pPager->errCode==SQLITE_OK ); assert( !pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL ); assert( pPager->dbOrigSize<=pPager->dbHintSize ); break; case PAGER_WRITER_FINISHED: assert( p->eLock==EXCLUSIVE_LOCK ); assert( pPager->errCode==SQLITE_OK ); assert( !pagerUseWal(pPager) ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL ); break; case PAGER_ERROR: /* There must be at least one outstanding reference to the pager if @@ -58292,24 +48401,20 @@ return 1; } #endif /* ifndef NDEBUG */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_DEBUG /* ** Return a pointer to a human readable string in a static buffer ** containing the state of the Pager object passed as an argument. This ** is intended to be used within debuggers. For example, as an alternative ** to "print *pPager" in gdb: ** ** (gdb) printf "%s", print_pager_state(pPager) -** -** This routine has external linkage in order to suppress compiler warnings -** about an unused function. It is enclosed within SQLITE_DEBUG and so does -** not appear in normal builds. */ -char *print_pager_state(Pager *p){ +static char *print_pager_state(Pager *p){ static char zRet[1024]; sqlite3_snprintf(1024, zRet, "Filename: %s\n" "State: %s errCode=%d\n" @@ -58362,11 +48467,15 @@ */ static void setGetterMethod(Pager *pPager){ if( pPager->errCode ){ pPager->xGet = getPageError; #if SQLITE_MAX_MMAP_SIZE>0 - }else if( USEFETCH(pPager) ){ + }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; } @@ -58387,13 +48496,10 @@ Pgno pgno = pPg->pgno; int i; for(i=0; inSavepoint; i++){ p = &pPager->aSavepoint[i]; if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){ - for(i=i+1; inSavepoint; i++){ - pPager->aSavepoint[i].bTruncateOnRelease = 0; - } return 1; } } return 0; } @@ -58443,11 +48549,11 @@ ** Unlock the database file to level eLock, which must be either NO_LOCK ** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() ** succeeds, set the Pager.eLock variable to match the (attempted) new lock. ** ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is -** called, do not modify it. See the comment above the #define of +** called, do not modify it. See the comment above the #define of ** UNKNOWN_LOCK for an explanation of this. */ static int pagerUnlockDb(Pager *pPager, int eLock){ int rc = SQLITE_OK; @@ -58460,22 +48566,21 @@ if( pPager->eLock!=UNKNOWN_LOCK ){ pPager->eLock = (u8)eLock; } IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) } - pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */ return rc; } /* ** Lock the database file to level eLock, which must be either SHARED_LOCK, ** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the -** Pager.eLock variable to the new locking state. +** Pager.eLock variable to the new locking state. ** -** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is -** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. -** See the comment above the #define of UNKNOWN_LOCK for an explanation +** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is +** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. +** See the comment above the #define of UNKNOWN_LOCK for an explanation ** of this. */ static int pagerLockDb(Pager *pPager, int eLock){ int rc = SQLITE_OK; @@ -58489,65 +48594,52 @@ } return rc; } /* -** 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: +** This function determines whether or not the atomic-write optimization +** can be used with this pager. The 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. ** -** 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. -*/ +** 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 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. +*/ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE static int jrnlBufferSize(Pager *pPager){ assert( !MEMDB ); - -#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( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){ - return -1; - } -#endif - -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - { - int nSector = pPager->sectorSize; - int szPage = pPager->pageSize; + 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; assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ return 0; } } 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 ** and debugging only. */ @@ -58589,77 +48681,75 @@ #define CHECK_PAGE(x) #endif /* SQLITE_CHECK_PAGES */ /* ** When this is called the journal file for pager pPager must be open. -** This function attempts to read a super-journal file name from the -** end of the file and, if successful, copies it into memory supplied -** by the caller. See comments above writeSuperJournal() for the format -** used to store a super-journal file name at the end of a journal file. +** This function attempts to read a master journal file name from the +** end of the file and, if successful, copies it into memory supplied +** by the caller. See comments above writeMasterJournal() for the format +** used to store a master journal file name at the end of a journal file. ** -** zSuper must point to a buffer of at least nSuper bytes allocated by +** zMaster must point to a buffer of at least nMaster bytes allocated by ** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is -** enough space to write the super-journal name). If the super-journal -** name in the journal is longer than nSuper bytes (including a -** nul-terminator), then this is handled as if no super-journal name +** enough space to write the master journal name). If the master journal +** name in the journal is longer than nMaster bytes (including a +** nul-terminator), then this is handled as if no master journal name ** were present in the journal. ** -** If a super-journal file name is present at the end of the journal -** file, then it is copied into the buffer pointed to by zSuper. A -** nul-terminator byte is appended to the buffer following the -** super-journal file name. +** If a master journal file name is present at the end of the journal +** file, then it is copied into the buffer pointed to by zMaster. A +** nul-terminator byte is appended to the buffer following the master +** journal file name. ** -** If it is determined that no super-journal file name is present -** zSuper[0] is set to 0 and SQLITE_OK returned. +** If it is determined that no master journal file name is present +** zMaster[0] is set to 0 and SQLITE_OK returned. ** ** If an error occurs while reading from the journal file, an SQLite ** error code is returned. */ -static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){ +static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ int rc; /* Return code */ - u32 len; /* Length in bytes of super-journal name */ + u32 len; /* Length in bytes of master journal name */ i64 szJ; /* Total size in bytes of journal file pJrnl */ u32 cksum; /* MJ checksum value read from journal */ u32 u; /* Unsigned loop counter */ unsigned char aMagic[8]; /* A buffer to hold the magic header */ - zSuper[0] = '\0'; + zMaster[0] = '\0'; if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) || szJ<16 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) - || len>=nSuper - || len>szJ-16 - || len==0 + || len>=nMaster + || len==0 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) || memcmp(aMagic, aJournalMagic, 8) - || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len)) + || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len)) ){ return rc; } - /* See if the checksum matches the super-journal name */ + /* See if the checksum matches the master journal name */ for(u=0; ujournalOff, assuming a sector +** Return the offset of the sector boundary at or immediately +** following the value in pPager->journalOff, assuming a sector ** size of pPager->sectorSize bytes. ** ** i.e for a sector size of 512: ** ** Pager.journalOff Return value @@ -58666,11 +48756,11 @@ ** --------------------------------------- ** 0 0 ** 512 512 ** 100 512 ** 2000 2048 -** +** */ static i64 journalHdrOffset(Pager *pPager){ i64 offset = 0; i64 c = pPager->journalOff; if( c ){ @@ -58688,16 +48778,16 @@ ** This function is a no-op if the journal file has not been written to ** within the current transaction (i.e. if Pager.journalOff==0). ** ** If doTruncate is non-zero or the Pager.journalSizeLimit variable is ** set to 0, then truncate the journal file to zero bytes in size. Otherwise, -** zero the 28-byte header at the start of the journal file. In either case, -** if the pager is not in no-sync mode, sync the journal file immediately +** zero the 28-byte header at the start of the journal file. In either case, +** if the pager is not in no-sync mode, sync the journal file immediately ** after writing or truncating it. ** ** If Pager.journalSizeLimit is set to a positive, non-zero value, and -** following the truncation or zeroing described above the size of the +** following the truncation or zeroing described above the size of the ** journal file in bytes is larger than this value, then truncate the ** journal file to Pager.journalSizeLimit bytes. The journal file does ** not need to be synced following this operation. ** ** If an IO error occurs, abandon processing and return the IO error code. @@ -58719,12 +48809,12 @@ } if( rc==SQLITE_OK && !pPager->noSync ){ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags); } - /* At this point the transaction is committed but the write lock - ** is still held on the file. If there is a size limit configured for + /* At this point the transaction is committed but the write lock + ** is still held on the file. If there is a size limit configured for ** the persistent journal and the journal file currently consumes more ** space than that limit allows for, truncate it now. There is no need ** to sync the file following this operation. */ if( rc==SQLITE_OK && iLimit>0 ){ @@ -58748,11 +48838,11 @@ ** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. ** - 4 bytes: Random number used for page hash. ** - 4 bytes: Initial database page count. ** - 4 bytes: Sector size used by the process that wrote this journal. ** - 4 bytes: Database page size. -** +** ** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. */ static int writeJournalHdr(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */ @@ -58764,12 +48854,12 @@ if( nHeader>JOURNAL_HDR_SZ(pPager) ){ nHeader = JOURNAL_HDR_SZ(pPager); } - /* If there are active savepoints and any of them were created - ** since the most recent journal header was written, update the + /* If there are active savepoints and any of them were created + ** since the most recent journal header was written, update the ** PagerSavepoint.iHdrOffset fields now. */ for(ii=0; iinSavepoint; ii++){ if( pPager->aSavepoint[ii].iHdrOffset==0 ){ pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff; @@ -58776,14 +48866,14 @@ } } pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager); - /* + /* ** Write the nRec Field - the number of page records that follow this ** journal header. Normally, zero is written to this value at this time. - ** After the records are added to the journal (and the journal synced, + ** After the records are added to the journal (and the journal synced, ** if in full-sync mode), the zero is overwritten with the true number ** of records (see syncJournal()). ** ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When ** reading the journal this value tells SQLite to assume that the @@ -58798,44 +48888,21 @@ ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees ** that garbage data is never appended to the journal file. */ assert( isOpen(pPager->fd) || pPager->noSync ); if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) - || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) + || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) ){ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); }else{ memset(zHeader, 0, sizeof(aJournalMagic)+4); } - - - /* The random check-hash initializer */ - if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ - sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - } -#ifdef SQLITE_DEBUG - else{ - /* The Pager.cksumInit variable is usually randomized above to protect - ** against there being existing records in the journal file. This is - ** dangerous, as following a crash they may be mistaken for records - ** written by the current transaction and rolled back into the database - ** file, causing corruption. The following assert statements verify - ** that this is not required in "journal_mode=memory" mode, as in that - ** case the journal file is always 0 bytes in size at this point. - ** It is advantageous to avoid the sqlite3_randomness() call if possible - ** as it takes the global PRNG mutex. */ - i64 sz = 0; - sqlite3OsFileSize(pPager->jfd, &sz); - assert( sz==0 ); - assert( pPager->journalOff==journalHdrOffset(pPager) ); - assert( sqlite3JournalIsInMemory(pPager->jfd) ); - } -#endif + /* The random check-hash initializer */ + sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); - /* The initial database size */ put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize); /* The assumed sector size for this process */ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); @@ -58848,27 +48915,27 @@ ** take the performance hit. */ memset(&zHeader[sizeof(aJournalMagic)+20], 0, nHeader-(sizeof(aJournalMagic)+20)); - /* In theory, it is only necessary to write the 28 bytes that the - ** journal header consumes to the journal file here. Then increment the - ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next + /* In theory, it is only necessary to write the 28 bytes that the + ** journal header consumes to the journal file here. Then increment the + ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next ** record is written to the following sector (leaving a gap in the file ** that will be implicitly filled in by the OS). ** - ** However it has been discovered that on some systems this pattern can + ** However it has been discovered that on some systems this pattern can ** be significantly slower than contiguously writing data to the file, - ** even if that means explicitly writing data to the block of + ** even if that means explicitly writing data to the block of ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what - ** is done. + ** is done. ** - ** The loop is required here in case the sector-size is larger than the + ** The loop is required here in case the sector-size is larger than the ** database page size. Since the zHeader buffer is only Pager.pageSize ** bytes in size, more than one call to sqlite3OsWrite() may be required ** to populate the entire journal header sector. - */ + */ for(nWrite=0; rc==SQLITE_OK&&nWritejournalHdr, nHeader)) rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff); assert( pPager->journalHdr <= pPager->journalOff ); pPager->journalOff += nHeader; @@ -58962,33 +49029,33 @@ iPageSize = pPager->pageSize; } /* Check that the values read from the page-size and sector-size fields ** are within range. To be 'in range', both values need to be a power - ** of two greater than or equal to 512 or 32, and not greater than their + ** of two greater than or equal to 512 or 32, and not greater than their ** respective compile time maximum limits. */ if( iPageSize<512 || iSectorSize<32 || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE - || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0 + || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0 ){ - /* If the either the page-size or sector-size in the journal-header is - ** invalid, then the process that wrote the journal-header must have - ** crashed before the header was synced. In this case stop reading + /* If the either the page-size or sector-size in the journal-header is + ** invalid, then the process that wrote the journal-header must have + ** crashed before the header was synced. In this case stop reading ** the journal file here. */ return SQLITE_DONE; } - /* Update the page-size to match the value read from the journal. - ** Use a testcase() macro to make sure that malloc failure within + /* Update the page-size to match the value read from the journal. + ** Use a testcase() macro to make sure that malloc failure within ** PagerSetPagesize() is tested. */ rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1); testcase( rc!=SQLITE_OK ); - /* Update the assumed sector-size to match the value used by + /* Update the assumed sector-size to match the value used by ** the process that created this journal. If this journal was ** created by a process other than this one, then this routine ** is being called from within pager_playback(). The local value ** of Pager.sectorSize is restored at the end of that routine. */ @@ -58999,85 +49066,85 @@ return rc; } /* -** Write the supplied super-journal name into the journal file for pager -** pPager at the current location. The super-journal name must be the last +** Write the supplied master journal name into the journal file for pager +** pPager at the current location. The master journal name must be the last ** thing written to a journal file. If the pager is in full-sync mode, the ** journal file descriptor is advanced to the next sector boundary before ** anything is written. The format is: ** -** + 4 bytes: PAGER_SJ_PGNO. -** + N bytes: super-journal filename in utf-8. -** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator). -** + 4 bytes: super-journal name checksum. +** + 4 bytes: PAGER_MJ_PGNO. +** + N bytes: Master journal filename in utf-8. +** + 4 bytes: N (length of master journal name in bytes, no nul-terminator). +** + 4 bytes: Master journal name checksum. ** + 8 bytes: aJournalMagic[]. ** -** The super-journal page checksum is the sum of the bytes in the super-journal -** name, where each byte is interpreted as a signed 8-bit integer. +** The master journal page checksum is the sum of the bytes in the master +** journal name, where each byte is interpreted as a signed 8-bit integer. ** -** If zSuper is a NULL pointer (occurs for a single database transaction), +** If zMaster is a NULL pointer (occurs for a single database transaction), ** this call is a no-op. */ -static int writeSuperJournal(Pager *pPager, const char *zSuper){ +static int writeMasterJournal(Pager *pPager, const char *zMaster){ int rc; /* Return code */ - int nSuper; /* Length of string zSuper */ + int nMaster; /* Length of string zMaster */ i64 iHdrOff; /* Offset of header in journal file */ i64 jrnlSize; /* Size of journal file on disk */ - u32 cksum = 0; /* Checksum of string zSuper */ + u32 cksum = 0; /* Checksum of string zMaster */ - assert( pPager->setSuper==0 ); + assert( pPager->setMaster==0 ); assert( !pagerUseWal(pPager) ); - if( !zSuper - || pPager->journalMode==PAGER_JOURNALMODE_MEMORY + if( !zMaster + || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || !isOpen(pPager->jfd) ){ return SQLITE_OK; } - pPager->setSuper = 1; + pPager->setMaster = 1; assert( pPager->journalHdr <= pPager->journalOff ); - /* Calculate the length in bytes and the checksum of zSuper */ - for(nSuper=0; zSuper[nSuper]; nSuper++){ - cksum += zSuper[nSuper]; + /* Calculate the length in bytes and the checksum of zMaster */ + for(nMaster=0; zMaster[nMaster]; nMaster++){ + cksum += zMaster[nMaster]; } /* If in full-sync mode, advance to the next disk sector before writing - ** the super-journal name. This is in case the previous page written to + ** the master journal name. This is in case the previous page written to ** the journal has already been synced. */ if( pPager->fullSync ){ pPager->journalOff = journalHdrOffset(pPager); } iHdrOff = pPager->journalOff; - /* Write the super-journal data to the end of the journal file. If + /* Write the master journal data to the end of the journal file. If ** an error occurs, return the error code to the caller. */ - if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_SJ_PGNO(pPager)))) - || (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4))) - || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper))) - || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum))) + if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager)))) + || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4))) + || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster))) + || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum))) || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, - iHdrOff+4+nSuper+8))) + iHdrOff+4+nMaster+8))) ){ return rc; } - pPager->journalOff += (nSuper+20); + pPager->journalOff += (nMaster+20); - /* If the pager is in persistent-journal mode, then the physical - ** journal-file may extend past the end of the super-journal name - ** and 8 bytes of magic data just written to the file. This is + /* If the pager is in peristent-journal mode, then the physical + ** journal-file may extend past the end of the master-journal name + ** and 8 bytes of magic data just written to the file. This is ** dangerous because the code to rollback a hot-journal file - ** will not be able to find the super-journal name to determine - ** whether or not the journal is hot. + ** will not be able to find the master-journal name to determine + ** whether or not the journal is hot. ** - ** Easiest thing to do in this scenario is to truncate the journal + ** Easiest thing to do in this scenario is to truncate the journal ** file to the required size. - */ + */ if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize)) && jrnlSize>pPager->journalOff ){ rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff); } @@ -59095,10 +49162,11 @@ /* ** Return the pPager->iDataVersion value */ SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ + assert( pPager->eState>PAGER_OPEN ); return pPager->iDataVersion; } /* ** Free all structures in the Pager.aSavepoint[] array and set both @@ -59118,11 +49186,11 @@ pPager->nSavepoint = 0; pPager->nSubRec = 0; } /* -** Set the bit number pgno in the PagerSavepoint.pInSavepoint +** Set the bit number pgno in the PagerSavepoint.pInSavepoint ** bitvecs of all open savepoints. Return SQLITE_OK if successful ** or SQLITE_NOMEM if a malloc failure occurs. */ static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){ int ii; /* Loop counter */ @@ -59147,22 +49215,22 @@ ** If the pager is not in exclusive-access mode, the database file is ** completely unlocked. If the file is unlocked and the file-system does ** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is ** closed (if it is open). ** -** If the pager is in ERROR state when this function is called, the -** contents of the pager cache are discarded before switching back to +** If the pager is in ERROR state when this function is called, the +** contents of the pager cache are discarded before switching back to ** the OPEN state. Regardless of whether the pager is in exclusive-mode ** or not, any journal file left in the file-system will be treated ** as a hot-journal and rolled back the next time a read-transaction ** is opened (by this or by any other connection). */ static void pager_unlock(Pager *pPager){ - assert( pPager->eState==PAGER_READER - || pPager->eState==PAGER_OPEN - || pPager->eState==PAGER_ERROR + assert( pPager->eState==PAGER_READER + || pPager->eState==PAGER_OPEN + || pPager->eState==PAGER_ERROR ); sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; releaseAllSavepoints(pPager); @@ -59205,10 +49273,11 @@ /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here ** without clearing the error code. This is intentional - the error ** code is cleared and the cache reset in the block below. */ assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); + pPager->changeCountDone = 0; pPager->eState = PAGER_OPEN; } /* If Pager.errCode is set, the contents of the pager cache cannot be ** trusted. Now that there are no outstanding references to the pager, @@ -59229,27 +49298,27 @@ setGetterMethod(pPager); } pPager->journalOff = 0; pPager->journalHdr = 0; - pPager->setSuper = 0; + pPager->setMaster = 0; } /* ** This function is called whenever an IOERR or FULL error that requires -** the pager to transition into the ERROR state may have occurred. -** The first argument is a pointer to the pager structure, the second -** the error-code about to be returned by a pager API function. The -** value returned is a copy of the second argument to this function. +** the pager to transition into the ERROR state may ahve occurred. +** The first argument is a pointer to the pager structure, the second +** the error-code about to be returned by a pager API function. The +** value returned is a copy of the second argument to this function. ** ** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the ** IOERR sub-codes, the pager enters the ERROR state and the error code ** is stored in Pager.errCode. While the pager remains in the ERROR state, ** all major API calls on the Pager will immediately return Pager.errCode. ** -** The ERROR state indicates that the contents of the pager-cache -** cannot be trusted. This state can be cleared by completely discarding +** The ERROR state indicates that the contents of the pager-cache +** cannot be trusted. This state can be cleared by completely discarding ** the contents of the pager-cache. If a transaction was active when ** the persistent error occurred, then the rollback journal may need ** to be replayed to restore the contents of the database file (as if ** it were a hot-journal). */ @@ -59293,31 +49362,31 @@ if( !isOpen(pPager->fd) ) return 0; return (sqlite3PCachePercentDirty(pPager->pPCache)>=25); } /* -** This routine ends a transaction. A transaction is usually ended by -** either a COMMIT or a ROLLBACK operation. This routine may be called +** This routine ends a transaction. A transaction is usually ended by +** either a COMMIT or a ROLLBACK operation. This routine may be called ** after rollback of a hot-journal, or if an error occurs while opening ** the journal file or writing the very first journal-header of a ** database transaction. -** +** ** This routine is never called in PAGER_ERROR state. If it is called ** in PAGER_NONE or PAGER_SHARED state and the lock held is less ** exclusive than a RESERVED lock, it is a no-op. ** ** Otherwise, any active savepoints are released. ** -** If the journal file is open, then it is "finalized". Once a journal -** file has been finalized it is not possible to use it to roll back a +** If the journal file is open, then it is "finalized". Once a journal +** file has been finalized it is not possible to use it to roll back a ** transaction. Nor will it be considered to be a hot-journal by this ** or any other database connection. Exactly how a journal is finalized ** depends on whether or not the pager is running in exclusive mode and ** the current journal-mode (Pager.journalMode value), as follows: ** ** journalMode==MEMORY -** Journal file descriptor is simply closed. This destroys an +** Journal file descriptor is simply closed. This destroys an ** in-memory journal. ** ** journalMode==TRUNCATE ** Journal file is truncated to zero bytes in size. ** @@ -59333,23 +49402,23 @@ ** the journal file is never used. Instead, if the journalMode is ** DELETE and the pager is in exclusive mode, the method described under ** journalMode==PERSIST is used instead. ** ** After the journal is finalized, the pager moves to PAGER_READER state. -** If running in non-exclusive rollback mode, the lock on the file is +** If running in non-exclusive rollback mode, the lock on the file is ** downgraded to a SHARED_LOCK. ** ** SQLITE_OK is returned if no error occurs. If an error occurs during ** any of the IO operations to finalize the journal file or unlock the -** database then the IO error code is returned to the user. If the +** database then the IO error code is returned to the user. If the ** operation to finalize the journal file fails, then the code still ** tries to unlock the database file if not in exclusive mode. If the ** unlock operation fails as well, then the first error code related ** to the first error encountered (the journal finalization one) is ** returned. */ -static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ +static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ int rc = SQLITE_OK; /* Error code from journal finalization operation */ int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ /* Do nothing if the pager does not have an open write transaction ** or at least a RESERVED lock. This function may be called when there @@ -59357,25 +49426,23 @@ ** held under two circumstances: ** ** 1. After a successful hot-journal rollback, it is called with ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. ** - ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE + ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE ** lock switches back to locking_mode=normal and then executes a - ** read-transaction, this function is called with eState==PAGER_READER + ** read-transaction, this function is called with eState==PAGER_READER ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. */ assert( assert_pager_state(pPager) ); assert( pPager->eState!=PAGER_ERROR ); if( pPager->eStateeLockjfd) || pPager->pInJournal==0 - || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC) - ); + assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); if( isOpen(pPager->jfd) ){ assert( !pagerUseWal(pPager) ); /* Finalize the journal file. */ if( sqlite3JournalIsInMemory(pPager->jfd) ){ @@ -59395,25 +49462,25 @@ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); } } pPager->journalOff = 0; }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST - || (pPager->exclusiveMode && pPager->journalModeexclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL) ){ - rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile); + rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile); pPager->journalOff = 0; }else{ /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ int bDelete = !pPager->tempFile; assert( sqlite3JournalIsInMemory(pPager->jfd)==0 ); - assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE - || pPager->journalMode==PAGER_JOURNALMODE_MEMORY - || pPager->journalMode==PAGER_JOURNALMODE_WAL + assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE + || pPager->journalMode==PAGER_JOURNALMODE_MEMORY + || pPager->journalMode==PAGER_JOURNALMODE_WAL ); sqlite3OsClose(pPager->jfd); if( bDelete ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync); } @@ -59442,60 +49509,58 @@ } sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); } if( pagerUseWal(pPager) ){ - /* Drop the WAL write-lock, if any. Also, if the connection was in - ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE + /* Drop the WAL write-lock, if any. Also, if the connection was in + ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE ** lock held on the database file. */ rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); assert( rc2==SQLITE_OK ); }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ /* This branch is taken when committing a transaction in rollback-journal ** mode if the database file on disk is larger than the database image. - ** At this point the journal has been finalized and the transaction + ** At this point the journal has been finalized and the transaction ** successfully committed, but the EXCLUSIVE lock is still held on the ** file. So it is safe to truncate the database file to its minimum ** required size. */ assert( pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_truncate(pPager, pPager->dbSize); } - if( rc==SQLITE_OK && bCommit ){ + if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; } - if( !pPager->exclusiveMode + if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ rc2 = pagerUnlockDb(pPager, SHARED_LOCK); + pPager->changeCountDone = 0; } pPager->eState = PAGER_READER; - pPager->setSuper = 0; + pPager->setMaster = 0; return (rc==SQLITE_OK?rc2:rc); } -/* Forward reference */ -static int pager_playback(Pager *pPager, int isHot); - /* -** Execute a rollback if a transaction is active and unlock the -** database file. +** Execute a rollback if a transaction is active and unlock the +** database file. ** -** If the pager has already entered the ERROR state, do not attempt +** If the pager has already entered the ERROR state, do not attempt ** the rollback at this time. Instead, pager_unlock() is called. The ** call to pager_unlock() will discard all in-memory pages, unlock -** the database file and move the pager back to OPEN state. If this -** means that there is a hot-journal left in the file-system, the next -** connection to obtain a shared lock on the pager (which may be this one) +** the database file and move the pager back to OPEN state. If this +** means that there is a hot-journal left in the file-system, the next +** connection to obtain a shared lock on the pager (which may be this one) ** will roll it back. ** ** If the pager has not already entered the ERROR state, but an IO or -** malloc error occurs during a rollback, then this will itself cause +** malloc error occurs during a rollback, then this will itself cause ** the pager to enter the ERROR state. Which will be cleared by the ** call to pager_unlock(), as described above. */ static void pagerUnlockAndRollback(Pager *pPager){ if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){ @@ -59506,44 +49571,29 @@ sqlite3EndBenignMalloc(); }else if( !pPager->exclusiveMode ){ assert( pPager->eState==PAGER_READER ); pager_end_transaction(pPager, 0, 0); } - }else if( pPager->eState==PAGER_ERROR - && pPager->journalMode==PAGER_JOURNALMODE_MEMORY - && isOpen(pPager->jfd) - ){ - /* Special case for a ROLLBACK due to I/O error with an in-memory - ** journal: We have to rollback immediately, before the journal is - ** closed, because once it is closed, all content is forgotten. */ - int errCode = pPager->errCode; - u8 eLock = pPager->eLock; - pPager->eState = PAGER_OPEN; - pPager->errCode = SQLITE_OK; - pPager->eLock = EXCLUSIVE_LOCK; - pager_playback(pPager, 1); - pPager->errCode = errCode; - pPager->eLock = eLock; } pager_unlock(pPager); } /* ** Parameter aData must point to a buffer of pPager->pageSize bytes -** of data. Compute and return a checksum based on the contents of the +** of data. Compute and return a checksum based ont the contents of the ** page of data and the current value of pPager->cksumInit. ** -** This is not a real checksum. It is really just the sum of the +** This is not a real checksum. It is really just the sum of the ** random initial value (pPager->cksumInit) and every 200th byte ** of the page data, starting with byte offset (pPager->pageSize%200). ** Each byte is interpreted as an 8-bit unsigned integer. ** ** Changing the formula used to compute this checksum results in an ** incompatible journal file format. ** -** If journal corruption occurs due to a power failure, the most likely -** scenario is that one end or the other of the record will be changed. +** If journal corruption occurs due to a power failure, the most likely +** scenario is that one end or the other of the record will be changed. ** It is much less likely that the two ends of the journal record will be ** correct and the middle be corrupt. Thus, this "checksum" scheme, ** though fast and simple, catches the mostly likely kind of corruption. */ static u32 pager_cksum(Pager *pPager, const u8 *aData){ @@ -59554,17 +49604,46 @@ i -= 200; } return cksum; } +/* +** Report the current page size and number of reserved bytes back +** to the codec. +*/ +#ifdef SQLITE_HAS_CODEC +static void pagerReportSize(Pager *pPager){ + if( pPager->xCodecSizeChng ){ + pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize, + (int)pPager->nReserve); + } +} +#else +# define pagerReportSize(X) /* No-op if we do not support a codec */ +#endif + +#ifdef SQLITE_HAS_CODEC +/* +** Make sure the number of reserved bits is the same in the destination +** pager as it is in the source. This comes up when a VACUUM changes the +** number of reserved bits to the "optimal" amount. +*/ +SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){ + if( pDest->nReserve!=pSrc->nReserve ){ + pDest->nReserve = pSrc->nReserve; + pagerReportSize(pDest); + } +} +#endif + /* ** Read a single page from either the journal file (if isMainJrnl==1) or ** from the sub-journal (if isMainJrnl==0) and playback that page. ** The page begins at offset *pOffset into the file. The *pOffset ** value is increased to the start of the next page in the journal. ** -** The main rollback journal uses checksums - the statement journal does +** The main rollback journal uses checksums - the statement journal does ** not. ** ** If the page number of the page record read from the (sub-)journal file ** is greater than the current value of Pager.dbSize, then playback is ** skipped and SQLITE_OK is returned. @@ -59580,12 +49659,12 @@ ** while reading the record from the (sub-)journal file or while writing ** to the database file, then the IO error code is returned. If data ** is successfully read from the (sub-)journal file but appears to be ** corrupted, SQLITE_DONE is returned. Data is considered corrupted in ** two circumstances: -** -** * If the record page-number is illegal (0 or PAGER_SJ_PGNO), or +** +** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or ** * If the record is being rolled back from the main journal file ** and the checksum field does not match the record content. ** ** Neither of these two scenarios are possible during a savepoint rollback. ** @@ -59605,10 +49684,15 @@ Pgno pgno; /* The page number of a page in journal */ u32 cksum; /* Checksum used for sanity checking */ char *aData; /* Temporary storage for the page */ sqlite3_file *jfd; /* The file descriptor for the journal file */ int isSynced; /* True if journal page is synced */ +#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 */ assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */ assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */ @@ -59615,11 +49699,11 @@ aData = pPager->pTmpSpace; assert( aData ); /* Temp storage must have already been allocated */ assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) ); - /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction + /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction ** or savepoint rollback done at the request of the caller) or this is ** a hot-journal rollback. If it is a hot-journal rollback, the pager ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback ** only reads from the main journal, not the sub-journal. */ @@ -59641,11 +49725,11 @@ /* Sanity checking on the page. This is more important that I originally ** thought. If a power failure occurs while the journal is being written, ** it could cause invalid data to be written into the journal. We need to ** detect this invalid data (with high probability) and ignore it. */ - if( pgno==0 || pgno==PAGER_SJ_PGNO(pPager) ){ + if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ assert( !isSavepnt ); return SQLITE_DONE; } if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){ return SQLITE_OK; @@ -59667,10 +49751,11 @@ /* When playing back page 1, restore the nReserve setting */ if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){ pPager->nReserve = ((u8*)aData)[20]; + pagerReportSize(pPager); } /* If the pager is in CACHEMOD state, then there must be a copy of this ** page in the pager cache. In this case just update the pager cache, ** not the database file. The page is left marked dirty in this case. @@ -59681,11 +49766,11 @@ ** during a Movepage() call, then the page may not be in the cache ** either. So the condition described in the above paragraph is not ** assert()able. ** ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the - ** pager cache if it exists and the main file. The page is then marked + ** pager cache if it exists and the main file. The page is then marked ** not dirty. Since this code is only executed in PAGER_OPEN state for ** a hot-journal rollback, it is guaranteed that the page-cache is empty ** if the pager is in OPEN state. ** ** Ticket #1171: The statement journal might contain page content that is @@ -59734,33 +49819,47 @@ ** 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 ){ +#ifdef SQLITE_HAS_CODEC + if( jrnlEnc ){ + CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT); + sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); + CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData); + }else +#endif sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); } }else if( !isMainJrnl && pPg==0 ){ /* If this is a rollback of a savepoint and data was not written to ** the database and the page is not in-memory, there is a potential - ** problem. When the page is next fetched by the b-tree layer, it - ** will be read from the database file, which may or may not be - ** current. + ** problem. When the page is next fetched by the b-tree layer, it + ** will be read from the database file, which may or may not be + ** current. ** ** There are a couple of different ways this can happen. All are quite - ** obscure. When running in synchronous mode, this can only happen + ** obscure. When running in synchronous mode, this can only happen ** if the page is on the free-list at the start of the transaction, then ** populated, then moved using sqlite3PagerMovepage(). ** ** The solution is to add an in-memory page to the cache containing - ** the data just read from the sub-journal. Mark the page as dirty - ** and if the pager requires a journal-sync, then mark the page as + ** the data just read from the sub-journal. Mark the page as dirty + ** and if the pager requires a journal-sync, then mark the page as ** requiring a journal-sync before it is written. */ assert( isSavepnt ); assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 ); pPager->doNotSpill |= SPILLFLAG_ROLLBACK; @@ -59790,185 +49889,180 @@ /* If this was page 1, then restore the value of Pager.dbFileVers. ** Do this before any decoding. */ if( pgno==1 ){ memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); } + + /* Decode the page just read from disk */ +#if SQLITE_HAS_CODEC + if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); } +#endif sqlite3PcacheRelease(pPg); } return rc; } /* -** Parameter zSuper is the name of a super-journal file. A single journal -** file that referred to the super-journal file has just been rolled back. -** This routine checks if it is possible to delete the super-journal file, +** Parameter zMaster is the name of a master journal file. A single journal +** file that referred to the master journal file has just been rolled back. +** This routine checks if it is possible to delete the master journal file, ** and does so if it is. ** -** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not +** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not ** available for use within this function. ** -** When a super-journal file is created, it is populated with the names -** of all of its child journals, one after another, formatted as utf-8 -** encoded text. The end of each child journal file is marked with a -** nul-terminator byte (0x00). i.e. the entire contents of a super-journal +** When a master journal file is created, it is populated with the names +** of all of its child journals, one after another, formatted as utf-8 +** encoded text. The end of each child journal file is marked with a +** nul-terminator byte (0x00). i.e. the entire contents of a master journal ** file for a transaction involving two databases might be: ** ** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00" ** -** A super-journal file may only be deleted once all of its child +** A master journal file may only be deleted once all of its child ** journals have been rolled back. ** -** This function reads the contents of the super-journal file into +** This function reads the contents of the master-journal file into ** memory and loops through each of the child journal names. For ** each child journal, it checks if: ** ** * if the child journal exists, and if so -** * if the child journal contains a reference to super-journal -** file zSuper +** * if the child journal contains a reference to master journal +** file zMaster ** ** If a child journal can be found that matches both of the criteria ** above, this function returns without doing anything. Otherwise, if -** no such child journal can be found, file zSuper is deleted from +** no such child journal can be found, file zMaster is deleted from ** the file-system using sqlite3OsDelete(). ** ** If an IO error within this function, an error code is returned. This ** function allocates memory by calling sqlite3Malloc(). If an allocation -** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors +** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors ** occur, SQLITE_OK is returned. ** ** TODO: This function allocates a single block of memory to load -** the entire contents of the super-journal file. This could be -** a couple of kilobytes or so - potentially larger than the page +** the entire contents of the master journal file. This could be +** a couple of kilobytes or so - potentially larger than the page ** size. */ -static int pager_delsuper(Pager *pPager, const char *zSuper){ +static int pager_delmaster(Pager *pPager, const char *zMaster){ sqlite3_vfs *pVfs = pPager->pVfs; int rc; /* Return code */ - sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */ + sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */ sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */ - char *zSuperJournal = 0; /* Contents of super-journal file */ - i64 nSuperJournal; /* Size of super-journal file */ + char *zMasterJournal = 0; /* Contents of master journal file */ + i64 nMasterJournal; /* Size of master journal file */ char *zJournal; /* Pointer to one journal within MJ file */ - char *zSuperPtr; /* Space to hold super-journal filename */ - char *zFree = 0; /* Free this buffer */ - int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */ - - /* Allocate space for both the pJournal and pSuper file descriptors. - ** If successful, open the super-journal file for reading. - */ - pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2); - if( !pSuper ){ - rc = SQLITE_NOMEM_BKPT; - pJournal = 0; - }else{ - const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL); - rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0); - pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile); - } - if( rc!=SQLITE_OK ) goto delsuper_out; - - /* Load the entire super-journal file into space obtained from - ** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain - ** sufficient space (in zSuperPtr) to hold the names of super-journal - ** files extracted from regular rollback-journals. - */ - rc = sqlite3OsFileSize(pSuper, &nSuperJournal); - if( rc!=SQLITE_OK ) goto delsuper_out; - nSuperPtr = pVfs->mxPathname+1; - zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2); - if( !zFree ){ - rc = SQLITE_NOMEM_BKPT; - goto delsuper_out; - } - zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0; - zSuperJournal = &zFree[4]; - zSuperPtr = &zSuperJournal[nSuperJournal+2]; - rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0); - if( rc!=SQLITE_OK ) goto delsuper_out; - zSuperJournal[nSuperJournal] = 0; - zSuperJournal[nSuperJournal+1] = 0; - - zJournal = zSuperJournal; - while( (zJournal-zSuperJournal)szOsFile * 2); + pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); + if( !pMaster ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); + rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); + } + if( rc!=SQLITE_OK ) goto delmaster_out; + + /* Load the entire master journal file into space obtained from + ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain + ** sufficient space (in zMasterPtr) to hold the names of master + ** journal files extracted from regular rollback-journals. + */ + rc = sqlite3OsFileSize(pMaster, &nMasterJournal); + if( rc!=SQLITE_OK ) goto delmaster_out; + nMasterPtr = pVfs->mxPathname+1; + zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1); + if( !zMasterJournal ){ + rc = SQLITE_NOMEM_BKPT; + goto delmaster_out; + } + zMasterPtr = &zMasterJournal[nMasterJournal+1]; + rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0); + if( rc!=SQLITE_OK ) goto delmaster_out; + zMasterJournal[nMasterJournal] = 0; + + zJournal = zMasterJournal; + while( (zJournal-zMasterJournal)pageSize bytes). +** DBMOD or OPEN state, this function is a no-op. Otherwise, the size +** of the file is changed to nPage pages (nPage*pPager->pageSize bytes). ** If the file on disk is currently larger than nPage pages, then use the VFS ** xTruncate() method to truncate it. ** -** Or, it might be the case that the file on disk is smaller than -** nPage pages. Some operating system implementations can get confused if -** you try to truncate a file to some size that is larger than it -** currently is, so detect this case and write a single zero byte to +** Or, it might be the case that the file on disk is smaller than +** nPage pages. Some operating system implementations can get confused if +** you try to truncate a file to some size that is larger than it +** currently is, so detect this case and write a single zero byte to ** the end of the new file instead. ** ** If successful, return SQLITE_OK. If an IO error occurs while modifying ** the database file, return the error code to the caller. */ static int pager_truncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; assert( pPager->eState!=PAGER_ERROR ); assert( pPager->eState!=PAGER_READER ); - PAGERTRACE(("Truncate %d npage %u\n", PAGERID(pPager), nPage)); - - - if( isOpen(pPager->fd) - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) + + if( isOpen(pPager->fd) + && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ i64 currentSize, newSize; int szPage = pPager->pageSize; assert( pPager->eLock==EXCLUSIVE_LOCK ); /* TODO: Is it safe to use Pager.dbFileSize here? */ @@ -59980,11 +50074,10 @@ }else if( (currentSize+szPage)<=newSize ){ char *pTmp = pPager->pTmpSpace; memset(pTmp, 0, szPage); testcase( (newSize-szPage) == currentSize ); testcase( (newSize-szPage) > currentSize ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize); rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage); } if( rc==SQLITE_OK ){ pPager->dbFileSize = nPage; } @@ -60009,13 +50102,13 @@ } /* ** Set the value of the Pager.sectorSize variable for the given ** pager based on the value returned by the xSectorSize method -** of the open database file. The sector size will be used -** to determine the size and alignment of journal header and -** super-journal pointers within created journal files. +** of the open database file. The sector size will be used +** to determine the size and alignment of journal header and +** master journal pointers within created journal files. ** ** For temporary files the effective sector size is always 512 bytes. ** ** Otherwise, for non-temporary files, the effective sector size is ** the value returned by the xSectorSize() method rounded up to 32 if @@ -60033,11 +50126,11 @@ */ static void setSectorSize(Pager *pPager){ assert( isOpen(pPager->fd) || pPager->tempFile ); if( pPager->tempFile - || (sqlite3OsDeviceCharacteristics(pPager->fd) & + || (sqlite3OsDeviceCharacteristics(pPager->fd) & SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0 ){ /* Sector size doesn't matter for temporary files. Also, the file ** may not have been opened yet, in which case the OsSectorSize() ** call will segfault. */ @@ -60047,19 +50140,19 @@ } } /* ** Playback the journal and thus restore the database file to -** the state it was in before we started making changes. +** the state it was in before we started making changes. ** -** The journal file format is as follows: +** The journal file format is as follows: ** ** (1) 8 byte prefix. A copy of aJournalMagic[]. ** (2) 4 byte big-endian integer which is the number of valid page records ** in the journal. If this value is 0xffffffff, then compute the ** number of page records from the journal size. -** (3) 4 byte big-endian integer which is the initial value for the +** (3) 4 byte big-endian integer which is the initial value for the ** sanity checksum. ** (4) 4 byte integer which is the number of pages to truncate the ** database to during a rollback. ** (5) 4 byte big-endian integer which is the sector size. The header ** is this many bytes in size. @@ -60084,11 +50177,11 @@ ** ** If the nRec value is 0xffffffff it means that nRec should be computed ** from the file size. This value is used when the user selects the ** no-sync option for the journal. A power failure could lead to corruption ** in this case. But for things like temporary table (which will be -** deleted when the power is restored) we don't care. +** deleted when the power is restored) we don't care. ** ** If the file opened as the journal file is not a well-formed ** journal file then all pages up to the first corrupted page are rolled ** back (or no pages if the journal header is corrupted). The journal file ** is then deleted and SQLITE_OK returned, just as if no corruption had @@ -60096,11 +50189,11 @@ ** ** If an I/O or malloc() error occurs, the journal-file is not deleted ** and an error code is returned. ** ** The isHot parameter indicates that we are trying to rollback a journal -** that might be a hot journal. Or, it could be that the journal is +** that might be a hot journal. Or, it could be that the journal is ** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE. ** If the journal really is hot, reset the pager cache prior rolling ** back any content. If the journal is merely persistent, no reset is ** needed. */ @@ -60110,14 +50203,13 @@ u32 nRec; /* Number of Records in the journal */ u32 u; /* Unsigned loop counter */ Pgno mxPg = 0; /* Size of the original file in pages */ int rc; /* Result code of a subroutine */ int res = 1; /* Value returned by sqlite3OsAccess() */ - char *zSuper = 0; /* Name of super-journal file if any */ + 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. */ assert( isOpen(pPager->jfd) ); @@ -60124,45 +50216,45 @@ rc = sqlite3OsFileSize(pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } - /* Read the super-journal name from the journal, if it is present. - ** If a super-journal file name is specified, but the file is not + /* Read the master journal name from the journal, if it is present. + ** If a master journal file name is specified, but the file is not ** present on disk, then the journal is not hot and does not need to be ** played back. ** ** TODO: Technically the following is an error because it assumes that ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c, ** mxPathname is 512, which is the same as the minimum allowable value ** for pageSize. */ - zSuper = pPager->pTmpSpace; - rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1); - if( rc==SQLITE_OK && zSuper[0] ){ - rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res); + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + if( rc==SQLITE_OK && zMaster[0] ){ + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); } - zSuper = 0; + zMaster = 0; if( rc!=SQLITE_OK || !res ){ goto end_playback; } pPager->journalOff = 0; needPagerReset = isHot; - /* This loop terminates either when a readJournalHdr() or - ** pager_playback_one_page() call returns SQLITE_DONE or an IO error - ** occurs. + /* This loop terminates either when a readJournalHdr() or + ** pager_playback_one_page() call returns SQLITE_DONE or an IO error + ** occurs. */ while( 1 ){ /* Read the next journal header from the journal file. If there are ** not enough bytes left in the journal file for a complete header, or ** it is corrupted, then a process must have failed while writing it. ** This indicates nothing more needs to be rolled back. */ rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg); - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; } goto end_playback; } @@ -60186,11 +50278,11 @@ ** The third term of the test was added to fix ticket #2565. ** When rolling back a hot journal, nRec==0 always means that the next ** chunk of the journal contains zero pages to be rolled back. But ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in ** the journal, it means that the journal might contain additional - ** pages that need to be rolled back and that the number of pages + ** pages that need to be rolled back and that the number of pages ** should be computed based on the journal file size. */ if( nRec==0 && !isHot && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager)); @@ -60203,16 +50295,13 @@ rc = pager_truncate(pPager, mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } pPager->dbSize = mxPg; - if( pPager->mxPgnomxPgno = mxPg; - } } - /* Copy original pages out of the journal and back into the + /* Copy original pages out of the journal and back into the ** database file and/or page cache. */ for(u=0; ufd,SQLITE_FCNTL_DB_UNCHANGED,0); + if( pPager->fd->pMethods ){ + sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); + } #endif - /* If this playback is happening automatically as a result of an IO or - ** malloc error that occurred after the change-counter was updated but - ** before the transaction was committed, then the change-counter - ** modification may just have been reverted. If this happens in exclusive + /* If this playback is happening automatically as a result of an IO or + ** malloc error that occurred after the change-counter was updated but + ** before the transaction was committed, then the change-counter + ** modification may just have been reverted. If this happens in exclusive ** mode, then subsequent transactions performed by the connection will not ** update the change-counter at all. This may lead to cache inconsistency ** problems for other processes at some point in the future. So, just ** in case this has happened, clear the changeCountDone flag now. */ pPager->changeCountDone = pPager->tempFile; if( rc==SQLITE_OK ){ - /* Leave 4 bytes of space before the super-journal filename in memory. - ** This is because it may end up being passed to sqlite3OsOpen(), in - ** which case it requires 4 0x00 bytes in memory immediately before - ** the filename. */ - zSuper = &pPager->pTmpSpace[4]; - rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1); + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); testcase( rc!=SQLITE_OK ); } if( rc==SQLITE_OK && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ rc = sqlite3PagerSync(pPager, 0); } if( rc==SQLITE_OK ){ - rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0); + rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); testcase( rc!=SQLITE_OK ); } - if( rc==SQLITE_OK && zSuper[0] && res ){ - /* If there was a super-journal and this routine will return success, - ** see if it is possible to delete the super-journal. + if( rc==SQLITE_OK && zMaster[0] && res ){ + /* If there was a master journal and this routine will return success, + ** see if it is possible to delete the master journal. */ - assert( zSuper==&pPager->pTmpSpace[4] ); - memset(pPager->pTmpSpace, 0, 4); - rc = pager_delsuper(pPager, zSuper); + rc = pager_delmaster(pPager, zMaster); testcase( rc!=SQLITE_OK ); } if( isHot && nPlayback ){ sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s", nPlayback, pPager->zJournal); @@ -60311,48 +50393,44 @@ return rc; } /* -** 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 +** Read the content for page pPg out of the database file and into ** pPg->pData. A shared lock or greater must be held on the database ** file before this function is called. ** ** If page 1 is read, then the value of Pager.dbFileVers[] is set to ** the value read from the database file. ** ** If an IO error occurs, then the IO error is returned to the caller. ** Otherwise, SQLITE_OK is returned. */ -static int readDbPage(PgHdr *pPg){ +static int readDbPage(PgHdr *pPg, u32 iFrame){ Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ + Pgno pgno = pPg->pgno; /* Page number to read */ int rc = SQLITE_OK; /* Return code */ - -#ifndef SQLITE_OMIT_WAL - u32 iFrame = 0; /* Frame of WAL containing pgno */ + int pgsz = pPager->pageSize; /* Number of bytes to read */ assert( pPager->eState>=PAGER_READER && !MEMDB ); assert( isOpen(pPager->fd) ); - if( pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); - if( rc ) return rc; - } +#ifndef SQLITE_OMIT_WAL if( iFrame ){ - rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData); + /* Try to pull the page from the write-ahead log. */ + rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData); }else #endif { - i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize; - rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset); + i64 iOffset = (pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } } - if( pPg->pgno==1 ){ + if( pgno==1 ){ if( rc ){ /* If the read is unsuccessful, set the dbFileVers[] to something ** that will never be a valid file version. dbFileVers[] is a copy ** of bytes 24..39 of the database. Bytes 28..31 should always be ** zero or the size of the database in page. Bytes 32..35 and 35..39 @@ -60368,15 +50446,17 @@ }else{ u8 *dbFileVers = &((u8*)pPg->pData)[24]; memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); } } + CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM_BKPT); + PAGER_INCR(sqlite3_pager_readdb_count); PAGER_INCR(pPager->nRead); - IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno)); + IOTRACE(("PGIN %p %d\n", pPager, pgno)); PAGERTRACE(("FETCH %d page %d hash(%08x)\n", - PAGERID(pPager), pPg->pgno, pager_pagehash(pPg))); + PAGERID(pPager), pgno, pager_pagehash(pPg))); return rc; } /* @@ -60387,11 +50467,10 @@ ** routine which only updates the change-counter if the update is actually ** needed, as determined by the pPager->changeCountDone state variable. */ static void pager_write_changecounter(PgHdr *pPg){ u32 change_counter; - if( NEVER(pPg==0) ) return; /* Increment the value just read and write it back to byte 24. */ change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; put32bits(((char*)pPg->pData)+24, change_counter); @@ -60402,19 +50481,19 @@ put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); } #ifndef SQLITE_OMIT_WAL /* -** This function is invoked once for each page that has already been +** This function is invoked once for each page that has already been ** written into the log file when a WAL transaction is rolled back. -** Parameter iPg is the page number of said page. The pCtx argument +** Parameter iPg is the page number of said page. The pCtx argument ** is actually a pointer to the Pager structure. ** ** If page iPg is present in the cache, and has no outstanding references, ** it is discarded. Otherwise, if there are one or more outstanding ** references, the page content is reloaded from the database. If the -** attempt to reload content from the database is required and fails, +** attempt to reload content from the database is required and fails, ** return an SQLite error code. Otherwise, SQLITE_OK. */ static int pagerUndoCallback(void *pCtx, Pgno iPg){ int rc = SQLITE_OK; Pager *pPager = (Pager *)pCtx; @@ -60424,11 +50503,15 @@ pPg = sqlite3PagerLookup(pPager, iPg); if( pPg ){ if( sqlite3PcachePageRefcount(pPg)==1 ){ sqlite3PcacheDrop(pPg); }else{ - rc = readDbPage(pPg); + u32 iFrame = 0; + rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); + if( rc==SQLITE_OK ){ + rc = readDbPage(pPg, iFrame); + } if( rc==SQLITE_OK ){ pPager->xReiniter(pPg); } sqlite3PagerUnrefNotNull(pPg); } @@ -60436,11 +50519,11 @@ /* Normally, if a transaction is rolled back, any backup processes are ** updated as data is copied out of the rollback journal and into the ** database. This is not generally possible with a WAL database, as ** rollback involves simply truncating the log file. Therefore, if one - ** or more frames have already been written to the log (and therefore + ** or more frames have already been written to the log (and therefore ** also copied into the backup databases) as part of this transaction, ** the backups must be restarted. */ sqlite3BackupRestart(pPager->pBackup); @@ -60453,11 +50536,11 @@ static int pagerRollbackWal(Pager *pPager){ int rc; /* Return Code */ PgHdr *pList; /* List of dirty pages to revert */ /* For all pages in the cache that are currently dirty or have already - ** been written (but not committed) to the log file, do one of the + ** been written (but not committed) to the log file, do one of the ** following: ** ** + Discard the cached page (if refcount==0), or ** + Reload page content from the database (if refcount>0). */ @@ -60475,15 +50558,15 @@ /* ** This function is a wrapper around sqlite3WalFrames(). As well as logging ** the contents of the list of pages headed by pList (connected by pDirty), ** this function notifies any active backup processes that the pages have -** changed. +** changed. ** ** The list of pages passed into this routine is always sorted by page number. ** Hence, if page 1 appears anywhere on the list, it will be the first page. -*/ +*/ static int pagerWalFrames( Pager *pPager, /* Pager object */ PgHdr *pList, /* List of frames to log */ Pgno nTruncate, /* Database size after this commit */ int isCommit /* True if this is a commit */ @@ -60493,11 +50576,11 @@ PgHdr *p; /* For looping over pages */ assert( pPager->pWal ); assert( pList ); #ifdef SQLITE_DEBUG - /* Verify that the page list is in ascending order */ + /* Verify that the page list is in accending order */ for(p=pList; p && p->pDirty; p=p->pDirty){ assert( p->pgno < p->pDirty->pgno ); } #endif @@ -60520,11 +50603,11 @@ nList = 1; } pPager->aStat[PAGER_STAT_WRITE] += nList; if( pList->pgno==1 ) pager_write_changecounter(pList); - rc = sqlite3WalFrames(pPager->pWal, + rc = sqlite3WalFrames(pPager->pWal, pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags ); if( rc==SQLITE_OK && pPager->pBackup ){ for(p=pList; p; p=p->pDirty){ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); @@ -60624,11 +50707,11 @@ } #ifndef SQLITE_OMIT_WAL /* ** Check if the *-wal file that corresponds to the database opened by pPager -** exists if the database is not empty, or verify that the *-wal file does +** exists if the database is not empy, or verify that the *-wal file does ** not exist (by deleting it) if the database file is empty. ** ** If the database is not empty and the *-wal file exists, open the pager ** in WAL mode. If the database is empty or if no *-wal file exists and ** if no error occurs, make sure Pager.journalMode is not set to @@ -60635,13 +50718,13 @@ ** PAGER_JOURNALMODE_WAL. ** ** Return SQLITE_OK or an error code. ** ** The caller must hold a SHARED lock on the database file to call this -** function. Because an EXCLUSIVE lock on the db file is required to delete -** a WAL on a none-empty database, this ensures there is no race condition -** between the xAccess() below and an xDelete() being executed by some +** function. Because an EXCLUSIVE lock on the db file is required to delete +** a WAL on a none-empty database, this ensures there is no race condition +** between the xAccess() below and an xDelete() being executed by some ** other connection. */ static int pagerOpenWalIfPresent(Pager *pPager){ int rc = SQLITE_OK; assert( pPager->eState==PAGER_OPEN ); @@ -60673,25 +50756,25 @@ } #endif /* ** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback -** the entire super-journal file. The case pSavepoint==NULL occurs when -** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction +** the entire master journal file. The case pSavepoint==NULL occurs when +** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction ** savepoint. ** -** When pSavepoint is not NULL (meaning a non-transaction savepoint is +** When pSavepoint is not NULL (meaning a non-transaction savepoint is ** being rolled back), then the rollback consists of up to three stages, ** performed in the order specified: ** ** * Pages are played back from the main journal starting at byte -** offset PagerSavepoint.iOffset and continuing to +** offset PagerSavepoint.iOffset and continuing to ** PagerSavepoint.iHdrOffset, or to the end of the main journal ** file if PagerSavepoint.iHdrOffset is zero. ** ** * If PagerSavepoint.iHdrOffset is not zero, then pages are played -** back starting from the journal header immediately following +** back starting from the journal header immediately following ** PagerSavepoint.iHdrOffset to the end of the main journal file. ** ** * Pages are then played back from the sub-journal file, starting ** with the PagerSavepoint.iSubRec and continuing to the end of ** the journal file. @@ -60703,11 +50786,11 @@ ** ** If pSavepoint is NULL, then pages are only played back from the main ** journal file. There is no need for a bitvec in this case. ** ** In either case, before playback commences the Pager.dbSize variable -** is reset to the value that it held at the start of the savepoint +** is reset to the value that it held at the start of the savepoint ** (or transaction). No page with a page-number greater than this value ** is played back. If one is encountered it is simply skipped. */ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ i64 szJ; /* Effective size of the main journal */ @@ -60724,11 +50807,11 @@ if( !pDone ){ return SQLITE_NOMEM_BKPT; } } - /* Set the database size back to the value it was before the savepoint + /* Set the database size back to the value it was before the savepoint ** being reverted was opened. */ pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize; pPager->changeCountDone = pPager->tempFile; @@ -60777,11 +50860,11 @@ /* ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff" ** test is related to ticket #2565. See the discussion in the ** pager_playback() function for additional information. */ - if( nJRec==0 + if( nJRec==0 && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager)); } for(ii=0; rc==SQLITE_OK && iijournalOfffullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; } 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<<2); + pPager->walSyncFlags = pPager->syncFlags; if( pPager->fullSync ){ - pPager->walSyncFlags |= pPager->syncFlags; - } - if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){ - pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2); + pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS; } if( pgFlags & PAGER_CACHESPILL ){ pPager->doNotSpill &= ~SPILLFLAG_OFF; }else{ pPager->doNotSpill |= SPILLFLAG_OFF; } } +#endif /* ** The following global variable is incremented whenever the library ** attempts to open a temporary file. This information is used for -** testing and analysis only. +** testing and analysis only. */ #ifdef SQLITE_TEST SQLITE_API int sqlite3_opentemp_count = 0; #endif /* ** Open a temporary file. ** -** Write the file descriptor into *pFile. Return SQLITE_OK on success -** or some other error code if we fail. The OS will automatically +** Write the file descriptor into *pFile. Return SQLITE_OK on success +** or some other error code if we fail. The OS will automatically ** delete the temporary file when it is closed. ** ** The flags passed to the VFS layer xOpen() call are those specified ** by parameter vfsFlags ORed with the following: ** @@ -60993,13 +51081,13 @@ } /* ** Set the busy handler function. ** -** The pager invokes the busy-handler if sqlite3OsLock() returns +** The pager invokes the busy-handler if sqlite3OsLock() returns ** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock, -** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE +** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE ** lock. It does *not* invoke the busy handler when upgrading from ** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE ** (which occurs during hot-journal rollback). Summary: ** ** Transition | Invokes xBusyHandler @@ -61007,92 +51095,88 @@ ** NO_LOCK -> SHARED_LOCK | Yes ** SHARED_LOCK -> RESERVED_LOCK | No ** SHARED_LOCK -> EXCLUSIVE_LOCK | No ** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes ** -** If the busy-handler callback returns non-zero, the lock is +** If the busy-handler callback returns non-zero, the lock is ** retried. If it returns zero, then the SQLITE_BUSY error is ** returned to the caller of the pager API function. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyHandler( +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( Pager *pPager, /* Pager object */ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ ){ - void **ap; pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; - ap = (void **)&pPager->xBusyHandler; - assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); - assert( ap[1]==pBusyHandlerArg ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); + + if( isOpen(pPager->fd) ){ + void **ap = (void **)&pPager->xBusyHandler; + assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); + assert( ap[1]==pBusyHandlerArg ); + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); + } } /* -** Change the page size used by the Pager object. The new page size +** Change the page size used by the Pager object. The new page size ** is passed in *pPageSize. ** ** If the pager is in the error state when this function is called, it -** is a no-op. The value returned is the error state error code (i.e. +** is a no-op. The value returned is the error state error code (i.e. ** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL). ** ** Otherwise, if all of the following are true: ** -** * the new page size (value of *pPageSize) is valid (a power +** * the new page size (value of *pPageSize) is valid (a power ** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and ** ** * there are no outstanding page references, and ** ** * the database is either not an in-memory database or it is ** an in-memory database that currently consists of zero pages. ** ** then the pager object page size is set to *pPageSize. ** -** If the page size is changed, then this function uses sqlite3PagerMalloc() -** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt -** fails, SQLITE_NOMEM is returned and the page size remains unchanged. +** If the page size is changed, then this function uses sqlite3PagerMalloc() +** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt +** fails, SQLITE_NOMEM is returned and the page size remains unchanged. ** In all other cases, SQLITE_OK is returned. ** ** If the page size is not changed, either because one of the enumerated ** conditions above is not true, the pager was in error state when this -** function was called, or because the memory allocation attempt failed, +** function was called, or because the memory allocation attempt failed, ** then *pPageSize is set to the old, retained page size before returning. */ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){ int rc = SQLITE_OK; /* It is not possible to do a full assert_pager_state() here, as this ** function may be called from within PagerOpen(), before the state ** of the Pager object is internally consistent. ** - ** At one point this function returned an error if the pager was in + ** At one point this function returned an error if the pager was in ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that ** there is at least one outstanding page reference, this function ** is a no-op for that case anyhow. */ u32 pageSize = *pPageSize; assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); if( (pPager->memDb==0 || pPager->dbSize==0) - && sqlite3PcacheRefCount(pPager->pPCache)==0 - && pageSize && pageSize!=(u32)pPager->pageSize + && sqlite3PcacheRefCount(pPager->pPCache)==0 + && pageSize && pageSize!=(u32)pPager->pageSize ){ char *pNew = NULL; /* New temp space */ i64 nByte = 0; if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){ rc = sqlite3OsFileSize(pPager->fd, &nByte); } if( rc==SQLITE_OK ){ - /* 8 bytes of zeroed overrun space is sufficient so that the b-tree - * cell header parser will never run off the end of the allocation */ - pNew = (char *)sqlite3PageMalloc(pageSize+8); - if( !pNew ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - memset(pNew+pageSize, 0, 8); - } + pNew = (char *)sqlite3PageMalloc(pageSize); + if( !pNew ) rc = SQLITE_NOMEM_BKPT; } if( rc==SQLITE_OK ){ pager_reset(pPager); rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); @@ -61100,11 +51184,10 @@ if( rc==SQLITE_OK ){ sqlite3PageFree(pPager->pTmpSpace); pPager->pTmpSpace = pNew; pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize); pPager->pageSize = pageSize; - pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1; }else{ sqlite3PageFree(pNew); } } @@ -61111,10 +51194,11 @@ *pPageSize = pPager->pageSize; if( rc==SQLITE_OK ){ if( nReserve<0 ) nReserve = pPager->nReserve; assert( nReserve>=0 && nReserve<1000 ); pPager->nReserve = (i16)nReserve; + pagerReportSize(pPager); pagerFixMaplimit(pPager); } return rc; } @@ -61129,25 +51213,22 @@ SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){ return pPager->pTmpSpace; } /* -** Attempt to set the maximum database page count if mxPage is positive. +** Attempt to set the maximum database page count if mxPage is positive. ** Make no changes if mxPage is zero or negative. And never reduce the ** maximum page count below the current size of the database. ** ** Regardless of mxPage, return the current maximum page count. */ -SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){ +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ if( mxPage>0 ){ pPager->mxPgno = mxPage; } assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ - /* assert( pPager->mxPgno>=pPager->dbSize ); */ - /* OP_MaxPgcnt ensures that the parameter passed to this function is not - ** less than the total number of valid pages in the database. But this - ** may be less than Pager.dbSize, and so the assert() above is not valid */ + assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */ return pPager->mxPgno; } /* ** The following set of routines are used to disable the simulated @@ -61173,15 +51254,15 @@ # define enable_simulated_io_errors() #endif /* ** Read the first N bytes from the beginning of the file into memory -** that pDest points to. +** that pDest points to. ** ** If the pager was opened on a transient file (zFilename==""), or ** opened on a file less than N bytes in size, the output buffer is -** zeroed and SQLITE_OK returned. The rationale for this is that this +** zeroed and SQLITE_OK returned. The rationale for this is that this ** function is used to read database headers, and a new transient or ** zero sized database has a header than consists entirely of zeroes. ** ** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered, ** the error code is returned to the caller and the contents of the @@ -61210,11 +51291,11 @@ /* ** This function may only be called when a read-transaction is open on ** the pager. It returns the total number of pages in the database. ** -** However, if the file is between 1 and bytes in size, then +** However, if the file is between 1 and bytes in size, then ** this is considered a 1 page file. */ SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){ assert( pPager->eState>=PAGER_READER ); assert( pPager->eState!=PAGER_WRITER_FINISHED ); @@ -61225,23 +51306,23 @@ /* ** Try to obtain a lock of type locktype on the database file. If ** a similar or greater lock is already held, this function is a no-op ** (returning SQLITE_OK immediately). ** -** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke -** the busy callback if the lock is currently not available. Repeat -** until the busy callback returns false or until the attempt to +** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke +** the busy callback if the lock is currently not available. Repeat +** until the busy callback returns false or until the attempt to ** obtain the lock succeeds. ** ** Return SQLITE_OK on success and an error code if we cannot obtain -** the lock. If the lock is obtained successfully, set the Pager.state +** the lock. If the lock is obtained successfully, set the Pager.state ** variable to locktype before returning. */ static int pager_wait_on_lock(Pager *pPager, int locktype){ int rc; /* Return code */ - /* Check that this is either a no-op (because the requested lock is + /* Check that this is either a no-op (because the requested lock is ** already held), or one of the transitions that the busy-handler ** may be invoked during, according to the comment above ** sqlite3PagerSetBusyhandler(). */ assert( (pPager->eLock>=locktype) @@ -61254,73 +51335,66 @@ }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); return rc; } /* -** Function assertTruncateConstraint(pPager) checks that one of the +** Function assertTruncateConstraint(pPager) checks that one of the ** following is true for all dirty pages currently in the page-cache: ** -** a) The page number is less than or equal to the size of the +** a) The page number is less than or equal to the size of the ** current database image, in pages, OR ** ** b) if the page content were written at this time, it would not -** be necessary to write the current content out to the sub-journal. +** be necessary to write the current content out to the sub-journal +** (as determined by function subjRequiresPage()). ** ** If the condition asserted by this function were not true, and the ** dirty page were to be discarded from the cache via the pagerStress() ** routine, pagerStress() would not write the current page content to ** the database file. If a savepoint transaction were rolled back after ** this happened, the correct behavior would be to restore the current ** content of the page. However, since this content is not present in either -** the database file or the portion of the rollback journal and +** the database file or the portion of the rollback journal and ** sub-journal rolled back the content could not be restored and the -** database image would become corrupt. It is therefore fortunate that +** database image would become corrupt. It is therefore fortunate that ** this circumstance cannot arise. */ #if defined(SQLITE_DEBUG) static void assertTruncateConstraintCb(PgHdr *pPg){ - Pager *pPager = pPg->pPager; assert( pPg->flags&PGHDR_DIRTY ); - if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */ - Pgno pgno = pPg->pgno; - int i; - for(i=0; ipPager->nSavepoint; i++){ - PagerSavepoint *p = &pPager->aSavepoint[i]; - assert( p->nOrigpInSavepoint,pgno) ); - } - } + assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize ); } static void assertTruncateConstraint(Pager *pPager){ sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); } #else # define assertTruncateConstraint(pPager) #endif /* -** Truncate the in-memory database file image to nPage pages. This -** function does not actually modify the database file on disk. It -** just sets the internal state of the pager object so that the +** Truncate the in-memory database file image to nPage pages. This +** function does not actually modify the database file on disk. It +** just sets the internal state of the pager object so that the ** truncation will be done when the current transaction is committed. ** ** This function is only called right before committing a transaction. ** Once this function has been called, the transaction must either be ** rolled back or committed. It is not safe to call this function and ** then continue writing to the database. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ - assert( pPager->dbSize>=nPage || CORRUPT_DB ); + assert( pPager->dbSize>=nPage ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; /* At one point the code here called assertTruncateConstraint() to ** ensure that all pages being truncated away by this operation are, - ** if one or more savepoints are open, present in the savepoint + ** if one or more savepoints are open, present in the savepoint ** journal so that they can be restored if the savepoint is rolled ** back. This is no longer necessary as this function is now only - ** called right before committing a transaction. So although the - ** Pager object may still have open savepoints (Pager.nSavepoint!=0), + ** called right before committing a transaction. So although the + ** Pager object may still have open savepoints (Pager.nSavepoint!=0), ** they cannot be rolled back. So the assertTruncateConstraint() call ** is no longer correct. */ } @@ -61328,16 +51402,16 @@ ** This function is called before attempting a hot-journal rollback. It ** syncs the journal file to disk, then sets pPager->journalHdr to the ** size of the journal file so that the pager_playback() routine knows ** that the entire journal file has been synced. ** -** Syncing a hot-journal to disk before attempting to roll it back ensures +** Syncing a hot-journal to disk before attempting to roll it back ensures ** that if a power-failure occurs during the rollback, the process that ** attempts rollback following system recovery sees the same journal ** content as this process. ** -** If everything goes as planned, SQLITE_OK is returned. Otherwise, +** If everything goes as planned, SQLITE_OK is returned. Otherwise, ** an SQLite error code. */ static int pagerSyncHotJournal(Pager *pPager){ int rc = SQLITE_OK; if( !pPager->noSync ){ @@ -61349,11 +51423,11 @@ return rc; } #if SQLITE_MAX_MMAP_SIZE>0 /* -** Obtain a reference to a memory mapped page object for page number pgno. +** Obtain a reference to a memory mapped page object for page number pgno. ** The new object will use the pointer pData, obtained from xFetch(). ** If successful, set *ppPage to point to the new page reference ** and return SQLITE_OK. Otherwise, return an SQLite error code and set ** *ppPage to zero. ** @@ -61365,11 +51439,11 @@ Pgno pgno, /* Page number */ void *pData, /* xFetch()'d data for this page */ PgHdr **ppPage /* OUT: Acquired page object */ ){ PgHdr *p; /* Memory mapped page to return */ - + if( pPager->pMmapFreelist ){ *ppPage = p = pPager->pMmapFreelist; pPager->pMmapFreelist = p->pDirty; p->pDirty = 0; assert( pPager->nExtra>=8 ); @@ -61379,11 +51453,10 @@ if( p==0 ){ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData); return SQLITE_NOMEM_BKPT; } p->pExtra = (void *)&p[1]; - assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) ); p->flags = PGHDR_MMAP; p->nRef = 1; p->pPager = pPager; } @@ -61400,11 +51473,11 @@ return SQLITE_OK; } #endif /* -** Release a reference to page pPg. pPg must have been returned by an +** Release a reference to page pPg. pPg must have been returned by an ** earlier call to pagerAcquireMapPage(). */ static void pagerReleaseMapPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; pPager->nMmapOut--; @@ -61425,34 +51498,10 @@ pNext = p->pDirty; sqlite3_free(p); } } -/* Verify that the database file has not be deleted or renamed out from -** under the pager. Return SQLITE_OK if the database is still where it ought -** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error -** code from sqlite3OsAccess()) if the database has gone missing. -*/ -static int databaseIsUnmoved(Pager *pPager){ - int bHasMoved = 0; - int rc; - - if( pPager->tempFile ) return SQLITE_OK; - if( pPager->dbSize==0 ) return SQLITE_OK; - assert( pPager->zFilename && pPager->zFilename[0] ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); - if( rc==SQLITE_NOTFOUND ){ - /* If the HAS_MOVED file-control is unimplemented, assume that the file - ** has not been moved. That is the historical behavior of SQLite: prior to - ** version 3.8.3, it never checked */ - rc = SQLITE_OK; - }else if( rc==SQLITE_OK && bHasMoved ){ - rc = SQLITE_READONLY_DBMOVED; - } - return rc; -} - /* ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that @@ -61460,43 +51509,38 @@ ** and their memory is freed. Any attempt to use a page associated ** with this page cache after this function returns will likely ** result in a coredump. ** ** This function always succeeds. If a transaction is active an attempt -** is made to roll it back. If an error occurs during the rollback +** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ - u8 *pTmp = (u8*)pPager->pTmpSpace; + u8 *pTmp = (u8 *)pPager->pTmpSpace; + assert( db || pagerUseWal(pPager)==0 ); assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); pagerFreeMapHdrs(pPager); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL - { - u8 *a = 0; - assert( db || pPager->pWal==0 ); - if( db && 0==(db->flags & SQLITE_NoCkptOnClose) - && SQLITE_OK==databaseIsUnmoved(pPager) - ){ - a = pTmp; - } - sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); - pPager->pWal = 0; - } + assert( db || pPager->pWal==0 ); + sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, + (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) + ); + pPager->pWal = 0; #endif pager_reset(pPager); if( MEMDB ){ pager_unlock(pPager); }else{ /* If it is open, sync the journal file before calling UnlockAndRollback. - ** If this is not done, then an unsynced portion of the open journal - ** file may be played back into the database. If a power failure occurs + ** If this is not done, then an unsynced portion of the open journal + ** file may be played back into the database. If a power failure occurs ** while this is happening, the database could become corrupt. ** ** If an error occurs while trying to sync the journal, shift the pager ** into the ERROR state. This causes UnlockAndRollback to unlock the ** database and close the journal file without attempting to roll it @@ -61514,10 +51558,15 @@ IOTRACE(("CLOSE %p\n", pPager)) sqlite3OsClose(pPager->jfd); sqlite3OsClose(pPager->fd); sqlite3PageFree(pTmp); sqlite3PcacheClose(pPager->pPCache); + +#ifdef SQLITE_HAS_CODEC + if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); +#endif + assert( !pPager->aSavepoint && !pPager->pInJournal ); assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ); sqlite3_free(pPager); return SQLITE_OK; @@ -61543,11 +51592,11 @@ ** Sync the journal. In other words, make sure all the pages that have ** been written to the journal have actually reached the surface of the ** disk and can be restored in the event of a hot-journal rollback. ** ** If the Pager.noSync flag is set, then this function is a no-op. -** Otherwise, the actions required depend on the journal-mode and the +** Otherwise, the actions required depend on the journal-mode and the ** device characteristics of the file-system, as follows: ** ** * If the journal file is an in-memory journal file, no action need ** be taken. ** @@ -61555,24 +51604,24 @@ ** then the nRec field of the most recently written journal header ** is updated to contain the number of journal records that have ** been written following it. If the pager is operating in full-sync ** mode, then the journal file is synced before this field is updated. ** -** * If the device does not support the SEQUENTIAL property, then +** * If the device does not support the SEQUENTIAL property, then ** journal file is synced. ** ** Or, in pseudo-code: ** ** if( NOT ){ ** if( NOT SAFE_APPEND ){ ** if( ) xSync(); ** -** } +** } ** if( NOT SEQUENTIAL ) xSync(); ** } ** -** If successful, this routine clears the PGHDR_NEED_SYNC flag of every +** If successful, this routine clears the PGHDR_NEED_SYNC flag of every ** page currently held in memory before returning SQLITE_OK. If an IO ** error is encountered, then the IO error code is returned to the caller. */ static int syncJournal(Pager *pPager, int newHdr){ int rc; /* Return code */ @@ -61596,24 +51645,24 @@ /* This block deals with an obscure problem. If the last connection ** that wrote to this database was operating in persistent-journal ** mode, then the journal file may at this point actually be larger ** than Pager.journalOff bytes. If the next thing in the journal ** file happens to be a journal-header (written as part of the - ** previous connection's transaction), and a crash or power-failure - ** occurs after nRec is updated but before this connection writes - ** anything else to the journal file (or commits/rolls back its - ** transaction), then SQLite may become confused when doing the + ** previous connection's transaction), and a crash or power-failure + ** occurs after nRec is updated but before this connection writes + ** anything else to the journal file (or commits/rolls back its + ** transaction), then SQLite may become confused when doing the ** hot-journal rollback following recovery. It may roll back all ** of this connections data, then proceed to rolling back the old, ** out-of-date data that follows it. Database corruption. ** ** To work around this, if the journal file does appear to contain ** a valid header following Pager.journalOff, then write a 0x00 ** byte to the start of it to prevent it from being recognized. ** ** Variable iNextHdrOffset is set to the offset at which this - ** problematic header will occur, if it exists. aMagic is used + ** problematic header will occur, if it exists. aMagic is used ** as a temporary buffer to inspect the first couple of bytes of ** the potential journal header. */ i64 iNextHdrOffset; u8 aMagic[8]; @@ -61636,11 +51685,11 @@ ** full-synchronous mode, sync the journal first. This ensures that ** all data has really hit the disk before nRec is updated to mark ** it as a candidate for rollback. ** ** This is not required if the persistent media supports the - ** SAFE_APPEND property. Because in this case it is not possible + ** SAFE_APPEND property. Because in this case it is not possible ** for garbage data to be appended to the file, the nRec field ** is populated with 0xFFFFFFFF when the journal header is written ** and never needs to be updated. */ if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ @@ -61656,11 +51705,11 @@ if( rc!=SQLITE_OK ) return rc; } if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); IOTRACE(("JSYNC %p\n", pPager)) - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| + rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) ); if( rc!=SQLITE_OK ) return rc; } @@ -61673,12 +51722,12 @@ }else{ pPager->journalHdr = pPager->journalOff; } } - /* Unless the pager is in noSync mode, the journal file was just - ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on + /* Unless the pager is in noSync mode, the journal file was just + ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on ** all pages. */ sqlite3PcacheClearSyncFlags(pPager->pPCache); pPager->eState = PAGER_WRITER_DBMOD; assert( assert_pager_state(pPager) ); @@ -61694,13 +51743,13 @@ ** ** The pager must hold at least a RESERVED lock when this function ** is called. Before writing anything to the database file, this lock ** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained, ** SQLITE_BUSY is returned and no data is written to the database file. -** +** ** If the pager is a temp-file pager and the actual file-system file -** is not yet open, it is created and opened before any data is +** is not yet open, it is created and opened before any data is ** written out. ** ** Once the lock has been upgraded and, if necessary, the file opened, ** the pages are written out to the database file in list order. Writing ** a page is skipped if it meets either of the following criteria: @@ -61711,11 +51760,11 @@ ** If writing out a page causes the database file to grow, Pager.dbFileSize ** is updated accordingly. If page 1 is written out, then the value cached ** in Pager.dbFileVers[] is updated to match the new value stored in ** the database file. ** -** If everything is successful, SQLITE_OK is returned. If an IO error +** If everything is successful, SQLITE_OK is returned. If an IO error ** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot ** be obtained, SQLITE_BUSY is returned. */ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ int rc = SQLITE_OK; /* Return code */ @@ -61737,11 +51786,11 @@ /* Before the first write, give the VFS a hint of what the final ** file size will be. */ assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); - if( rc==SQLITE_OK + if( rc==SQLITE_OK && pPager->dbHintSizedbSize && (pList->pDirty || pList->pgno>pPager->dbHintSize) ){ sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize; sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile); @@ -61759,23 +51808,24 @@ ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag ** set (set by sqlite3PagerDontWrite()). */ if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ - char *pData; /* Data to write */ + char *pData; /* Data to write */ assert( (pList->flags&PGHDR_NEED_SYNC)==0 ); if( pList->pgno==1 ) pager_write_changecounter(pList); - pData = pList->pData; + /* Encode the database */ + CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData); /* Write out the page data. */ rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); /* If page 1 was just written, update Pager.dbFileVers to match - ** the value now stored in the database file. If writing this - ** page caused the database file to grow, update dbFileSize. + ** the value now stored in the database file. If writing this + ** page caused the database file to grow, update dbFileSize. */ if( pgno==1 ){ memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); } if( pgno>pPager->dbFileSize ){ @@ -61799,22 +51849,22 @@ return rc; } /* -** Ensure that the sub-journal file is open. If it is already open, this +** Ensure that the sub-journal file is open. If it is already open, this ** function is a no-op. ** -** SQLITE_OK is returned if everything goes according to plan. An -** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() +** SQLITE_OK is returned if everything goes according to plan. An +** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() ** fails. */ static int openSubJournal(Pager *pPager){ int rc = SQLITE_OK; if( !isOpen(pPager->sjfd) ){ - const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE - | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE + const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE + | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; int nStmtSpill = sqlite3Config.nStmtSpill; if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ nStmtSpill = -1; } @@ -61822,17 +51872,17 @@ } return rc; } /* -** Append a record of the current state of page pPg to the sub-journal. +** Append a record of the current state of page pPg to the sub-journal. ** ** If successful, set the bit corresponding to pPg->pgno in the bitvecs ** for all open savepoints before returning. ** ** This function returns SQLITE_OK if everything is successful, an IO -** error code if the attempt to write to the sub-journal fails, or +** error code if the attempt to write to the sub-journal fails, or ** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint ** bitvec. */ static int subjournalPage(PgHdr *pPg){ int rc = SQLITE_OK; @@ -61841,22 +51891,28 @@ /* Open the sub-journal, if it has not already been opened */ assert( pPager->useJournal ); assert( isOpen(pPager->jfd) || pagerUseWal(pPager) ); assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 ); - assert( pagerUseWal(pPager) - || pageInJournal(pPager, pPg) - || pPg->pgno>pPager->dbOrigSize + assert( pagerUseWal(pPager) + || pageInJournal(pPager, pPg) + || pPg->pgno>pPager->dbOrigSize ); rc = openSubJournal(pPager); /* If the sub-journal was opened successfully (or was already open), ** write the journal record into the file. */ if( rc==SQLITE_OK ){ void *pData = pPg->pData; i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize); char *pData2; + +#if SQLITE_HAS_CODEC + if( !pPager->subjInMemory ){ + CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); + }else +#endif pData2 = pData; PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); rc = write32bits(pPager->sjfd, offset, pPg->pgno); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4); @@ -61880,18 +51936,18 @@ /* ** This function is called by the pcache layer when it has reached some ** soft memory limit. The first argument is a pointer to a Pager object ** (cast as a void*). The pager is always 'purgeable' (not an in-memory -** database). The second argument is a reference to a page that is +** database). The second argument is a reference to a page that is ** currently dirty but has no outstanding references. The page -** is always associated with the Pager object passed as the first +** is always associated with the Pager object passed as the first ** argument. ** ** The job of this function is to make pPg clean by writing its contents ** out to the database file, if possible. This may involve syncing the -** journal file. +** journal file. ** ** If successful, sqlite3PcacheMakeClean() is called on the page and ** SQLITE_OK returned. If an IO error occurs while trying to make the ** page clean, the IO error code is returned. If the page cannot be ** made clean for some other reason, but no error occurs, then SQLITE_OK @@ -61912,11 +51968,11 @@ ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling ** regardless of whether or not a sync is required. This is set during ** a rollback or by user request, respectively. ** ** Spilling is also prohibited when in an error state since that could - ** lead to database corruption. In the current implementation it + ** lead to database corruption. In the current implementation it ** is impossible for sqlite3PcacheFetch() to be called with createFlag==3 ** while in the error state, hence it is impossible for this routine to ** be called in the error state. Nevertheless, we include a NEVER() ** test for the error state as a safeguard against future changes. */ @@ -61929,34 +51985,26 @@ || (pPg->flags & PGHDR_NEED_SYNC)!=0) ){ return SQLITE_OK; } - pPager->aStat[PAGER_STAT_SPILL]++; pPg->pDirty = 0; if( pagerUseWal(pPager) ){ /* Write a single frame for this page to the log. */ - rc = subjournalPageIfRequired(pPg); + rc = subjournalPageIfRequired(pPg); if( rc==SQLITE_OK ){ rc = pagerWalFrames(pPager, pPg, 0, 0); } }else{ - -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( pPager->tempFile==0 ){ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc!=SQLITE_OK ) return pager_error(pPager, rc); - } -#endif - + /* Sync the journal file if required. */ - if( pPg->flags&PGHDR_NEED_SYNC + if( pPg->flags&PGHDR_NEED_SYNC || pPager->eState==PAGER_WRITER_CACHEMOD ){ rc = syncJournal(pPager, 1); } - + /* Write the contents of the page out to the database file. */ if( rc==SQLITE_OK ){ assert( (pPg->flags&PGHDR_NEED_SYNC)==0 ); rc = pager_write_pagelist(pPager, pPg); } @@ -61966,11 +52014,11 @@ if( rc==SQLITE_OK ){ PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } - return pager_error(pPager, rc); + return pager_error(pPager, rc); } /* ** Flush all unreferenced dirty pages to disk. */ @@ -61997,12 +52045,12 @@ ** to sqlite3PagerClose(). ** ** The zFilename argument is the path to the database file to open. ** If zFilename is NULL then a randomly-named temporary file is created ** and used as the file to be cached. Temporary files are be deleted -** automatically when they are closed. If zFilename is ":memory:" then -** all information is held in cache. It is never written to disk. +** automatically when they are closed. If zFilename is ":memory:" then +** all information is held in cache. It is never written to disk. ** This can be used to implement an in-memory database. ** ** The nExtra parameter specifies the number of bytes of space allocated ** along with each page reference. This space is available to the user ** via the sqlite3PagerGetExtra() API. When a new page is allocated, the @@ -62012,17 +52060,17 @@ ** The flags argument is used to specify properties that affect the ** operation of the pager. It should be passed some bitwise combination ** of the PAGER_* flags. ** ** The vfsFlags parameter is a bitmask to pass to the flags parameter -** of the xOpen() method of the supplied VFS when opening files. +** of the xOpen() method of the supplied VFS when opening files. ** -** If the pager object is allocated and the specified file opened +** If the pager object is allocated and the specified file opened ** successfully, SQLITE_OK is returned and *ppPager set to point to ** the new pager object. If an error occurs, *ppPager is set to NULL ** and error code returned. This function may return SQLITE_NOMEM -** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or +** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or ** various SQLITE_IO_XXX errors. */ SQLITE_PRIVATE int sqlite3PagerOpen( sqlite3_vfs *pVfs, /* The virtual file system to use */ Pager **ppPager, /* OUT: Return the Pager structure here */ @@ -62035,20 +52083,19 @@ u8 *pPtr; Pager *pPager = 0; /* Pager object to allocate and return */ int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ - int memJM = 0; /* Memory journal mode */ int readOnly = 0; /* True if this is a read-only file */ int journalFileSize; /* Bytes to allocate for each journal fd */ char *zPathname = 0; /* Full path to database file */ int nPathname = 0; /* Number of bytes in zPathname */ int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */ int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ const char *zUri = 0; /* URI args to copy */ - int nUriByte = 1; /* Number of bytes of URI args at *zUri */ + int nUri = 0; /* Number of bytes of URI args at *zUri */ /* Figure out how much space is required for each journal file-handle ** (there are two of them, the main journal and the sub-journal). */ journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); @@ -62078,27 +52125,18 @@ if( zPathname==0 ){ return SQLITE_NOMEM_BKPT; } zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_OK_SYMLINK ){ - if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){ - rc = SQLITE_CANTOPEN_SYMLINK; - }else{ - rc = SQLITE_OK; - } - } - } nPathname = sqlite3Strlen30(zPathname); z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1]; while( *z ){ - z += strlen(z)+1; - z += strlen(z)+1; + z += sqlite3Strlen30(z)+1; + z += sqlite3Strlen30(z)+1; } - nUriByte = (int)(&z[1] - zUri); - assert( nUriByte>=1 ); + nUri = (int)(&z[1] - zUri); + assert( nUri>=0 ); if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){ /* This branch is taken when the journal path required by ** the database being opened will be more than pVfs->mxPathname ** bytes in length. This means the database cannot be opened, ** as it will not be possible to open the journal file or even @@ -62111,136 +52149,72 @@ return rc; } } /* Allocate memory for the Pager structure, PCache object, the - ** three file descriptors, the database file name and the journal + ** three file descriptors, the database file name and the journal ** file name. The layout in memory is as follows: ** ** Pager object (sizeof(Pager) bytes) ** PCache object (sqlite3PcacheSize() bytes) ** Database file handle (pVfs->szOsFile bytes) ** Sub-journal file handle (journalFileSize bytes) ** Main journal file handle (journalFileSize bytes) - ** Ptr back to the Pager (sizeof(Pager*) bytes) - ** \0\0\0\0 database prefix (4 bytes) ** Database file name (nPathname+1 bytes) - ** URI query parameters (nUriByte bytes) - ** Journal filename (nPathname+8+1 bytes) - ** WAL filename (nPathname+4+1 bytes) - ** \0\0\0 terminator (3 bytes) - ** - ** Some 3rd-party software, over which we have no control, depends on - ** the specific order of the filenames and the \0 separators between them - ** so that it can (for example) find the database filename given the WAL - ** filename without using the sqlite3_filename_database() API. This is a - ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party - ** software is in widespread use, so we try to avoid changing the filename - ** order and formatting if possible. In particular, the details of the - ** filename format expected by 3rd-party software should be as follows: - ** - ** - Main Database Path - ** - \0 - ** - Multiple URI components consisting of: - ** - Key - ** - \0 - ** - Value - ** - \0 - ** - \0 - ** - Journal Path - ** - \0 - ** - WAL Path (zWALName) - ** - \0 - ** - ** The sqlite3_create_filename() interface and the databaseFilename() utility - ** that is used by sqlite3_filename_database() and kin also depend on the - ** specific formatting and order of the various filenames, so if the format - ** changes here, be sure to change it there as well. + ** Journal file name (nPathname+8+1 bytes) */ - assert( SQLITE_PTRSIZE==sizeof(Pager*) ); pPtr = (u8 *)sqlite3MallocZero( - ROUND8(sizeof(*pPager)) + /* Pager structure */ - ROUND8(pcacheSize) + /* PCache object */ - ROUND8(pVfs->szOsFile) + /* The main db file */ - journalFileSize * 2 + /* The two journal files */ - SQLITE_PTRSIZE + /* Space to hold a pointer */ - 4 + /* Database prefix */ - nPathname + 1 + /* database filename */ - nUriByte + /* query parameters */ - nPathname + 8 + 1 + /* Journal filename */ + ROUND8(sizeof(*pPager)) + /* Pager structure */ + ROUND8(pcacheSize) + /* PCache object */ + ROUND8(pVfs->szOsFile) + /* The main db file */ + journalFileSize * 2 + /* The two journal files */ + nPathname + 1 + nUri + /* zFilename */ + nPathname + 8 + 2 /* zJournal */ #ifndef SQLITE_OMIT_WAL - nPathname + 4 + 1 + /* WAL filename */ + + nPathname + 4 + 2 /* zWal */ #endif - 3 /* Terminator */ ); assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); if( !pPtr ){ sqlite3DbFree(0, zPathname); return SQLITE_NOMEM_BKPT; } - pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager)); - pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize); - pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile); - pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; - pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; + pPager = (Pager*)(pPtr); + pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager))); + pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize)); + pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile)); + pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize); + pPager->zFilename = (char*)(pPtr += journalFileSize); assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); - memcpy(pPtr, &pPager, SQLITE_PTRSIZE); pPtr += SQLITE_PTRSIZE; - - /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ - pPtr += 4; /* Skip zero prefix */ - pPager->zFilename = (char*)pPtr; - if( nPathname>0 ){ - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1; - if( zUri ){ - memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte; - }else{ - pPtr++; - } - } - - - /* Fill in Pager.zJournal */ - if( nPathname>0 ){ - pPager->zJournal = (char*)pPtr; - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; - memcpy(pPtr, "-journal",8); pPtr += 8 + 1; -#ifdef SQLITE_ENABLE_8_3_NAMES - sqlite3FileSuffix3(zFilename,pPager->zJournal); - pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1); -#endif - }else{ - pPager->zJournal = 0; - } - + + /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ + if( zPathname ){ + assert( nPathname>0 ); + pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri); + memcpy(pPager->zFilename, zPathname, nPathname); + if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); + memcpy(pPager->zJournal, zPathname, nPathname); + memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2); + sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal); #ifndef SQLITE_OMIT_WAL - /* Fill in Pager.zWal */ - if( nPathname>0 ){ - pPager->zWal = (char*)pPtr; - memcpy(pPtr, zPathname, nPathname); pPtr += nPathname; - memcpy(pPtr, "-wal", 4); pPtr += 4 + 1; -#ifdef SQLITE_ENABLE_8_3_NAMES - sqlite3FileSuffix3(zFilename, pPager->zWal); - pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1); -#endif - }else{ - pPager->zWal = 0; - } -#endif - (void)pPtr; /* Suppress warning about unused pPtr value */ - - if( nPathname ) sqlite3DbFree(0, zPathname); + pPager->zWal = &pPager->zJournal[nPathname+8+1]; + memcpy(pPager->zWal, zPathname, nPathname); + memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1); + sqlite3FileSuffix3(pPager->zFilename, pPager->zWal); +#endif + sqlite3DbFree(0, zPathname); + } pPager->pVfs = pVfs; pPager->vfsFlags = vfsFlags; /* Open the pager file. */ if( zFilename && zFilename[0] ){ int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); - pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0; - readOnly = (fout&SQLITE_OPEN_READONLY)!=0; + readOnly = (fout&SQLITE_OPEN_READONLY); /* If the file was successfully opened for read/write access, ** choose a default page size in case we have to create the ** database file. The default page size is the maximum of: ** @@ -62272,13 +52246,13 @@ } } } #endif } - pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0); + pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0); if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0 - || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){ + || sqlite3_uri_boolean(zFilename, "immutable", 0) ){ vfsFlags |= SQLITE_OPEN_READONLY; goto act_like_temp_file; } } }else{ @@ -62289,20 +52263,20 @@ ** This branch is also run for an in-memory database. An in-memory ** database is the same as a temp-file that is never written out to ** disk and uses an in-memory rollback journal. ** ** This branch also runs for files marked as immutable. - */ + */ act_like_temp_file: tempFile = 1; pPager->eState = PAGER_READER; /* Pretend we already have a lock */ pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE mode */ pPager->noLock = 1; /* Do no locking */ readOnly = (vfsFlags&SQLITE_OPEN_READONLY); } - /* The following call to PagerSetPagesize() serves to set the value of + /* The following call to PagerSetPagesize() serves to set the value of ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. */ if( rc==SQLITE_OK ){ assert( pPager->memDb==0 ); rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1); @@ -62338,29 +52312,42 @@ /* pPager->nPage = 0; */ pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; /* pPager->state = PAGER_UNLOCK; */ /* pPager->errMask = 0; */ pPager->tempFile = (u8)tempFile; - assert( tempFile==PAGER_LOCKINGMODE_NORMAL + assert( tempFile==PAGER_LOCKINGMODE_NORMAL || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); - pPager->exclusiveMode = (u8)tempFile; + pPager->exclusiveMode = (u8)tempFile; pPager->changeCountDone = pPager->tempFile; pPager->memDb = (u8)memDb; pPager->readOnly = (u8)readOnly; assert( useJournal || pPager->tempFile ); - sqlite3PagerSetFlags(pPager, (SQLITE_DEFAULT_SYNCHRONOUS+1)|PAGER_CACHESPILL); + pPager->noSync = pPager->tempFile; + if( pPager->noSync ){ + assert( pPager->fullSync==0 ); + 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->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = (u16)nExtra; pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; assert( isOpen(pPager->fd) || tempFile ); setSectorSize(pPager); if( !useJournal ){ pPager->journalMode = PAGER_JOURNALMODE_OFF; - }else if( memDb || memJM ){ + }else if( memDb ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; @@ -62370,32 +52357,40 @@ *ppPager = pPager; return SQLITE_OK; } -/* -** Return the sqlite3_file for the main database given the name -** of the corresponding WAL or Journal name as passed into -** xOpen. + +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still were it ought +** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +** code from sqlite3OsAccess()) if the database has gone missing. */ -SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){ - Pager *pPager; - const char *p; - while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ - zName--; - } - p = zName - 4 - sizeof(Pager*); - assert( EIGHT_BYTE_ALIGNMENT(p) ); - pPager = *(Pager**)p; - return pPager->fd; +static int databaseIsUnmoved(Pager *pPager){ + int bHasMoved = 0; + int rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_NOTFOUND ){ + /* If the HAS_MOVED file-control is unimplemented, assume that the file + ** has not been moved. That is the historical behavior of SQLite: prior to + ** version 3.8.3, it never checked */ + rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bHasMoved ){ + rc = SQLITE_READONLY_DBMOVED; + } + return rc; } /* ** This function is called after transitioning from PAGER_UNLOCK to ** PAGER_SHARED state. It tests if there is a hot journal present in -** the file-system for the given pager. A hot journal is one that +** the file-system for the given pager. A hot journal is one that ** needs to be played back. According to this function, a hot-journal ** file exists if the following criteria are met: ** ** * The journal file exists in the file system, and ** * No process holds a RESERVED or greater lock on the database file, and @@ -62406,18 +52401,18 @@ ** exists, that is probably an old journal left over from a prior ** database with the same name. In this case the journal file is ** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK ** is returned. ** -** This routine does not check if there is a super-journal filename -** at the end of the file. If there is, and that super-journal file +** This routine does not check if there is a master journal filename +** at the end of the file. If there is, and that master journal file ** does not exist, then the journal file is not really hot. In this ** case this routine will return a false-positive. The pager_playback() -** routine will discover that the journal file is not really hot and -** will not roll it back. +** routine will discover that the journal file is not really hot and +** will not roll it back. ** -** If a hot-journal file is found to exist, *pExists is set to 1 and +** If a hot-journal file is found to exist, *pExists is set to 1 and ** SQLITE_OK returned. If no hot-journal file is present, *pExists is ** set to 0 and SQLITE_OK returned. If an IO error occurs while trying ** to determine whether or not a hot-journal file exists, the IO error ** code is returned and the value of *pExists is undefined. */ @@ -62441,11 +52436,11 @@ } if( rc==SQLITE_OK && exists ){ int locked = 0; /* True if some process holds a RESERVED lock */ /* Race condition here: Another process might have been holding the - ** the RESERVED lock and have a journal open at the sqlite3OsAccess() + ** the RESERVED lock and have a journal open at the sqlite3OsAccess() ** call above, but then delete the journal and drop the lock before ** we get to the following sqlite3OsCheckReservedLock() call. If that ** is the case, this routine might think there is a hot journal when ** in fact there is none. This results in a false-positive which will ** be dealt with by the playback routine. Ticket #3883. @@ -62474,11 +52469,11 @@ sqlite3EndBenignMalloc(); }else{ /* The journal file exists and no other connection has a reserved ** or greater lock on the database file. Now check that there is ** at least one non-zero bytes at the start of the journal file. - ** If there is, then we consider this journal to be hot. If not, + ** If there is, then we consider this journal to be hot. If not, ** it can be ignored. */ if( !jrnlOpen ){ int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL; rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f); @@ -62524,11 +52519,11 @@ ** ** 1) If the pager is currently in PAGER_OPEN state (no lock held ** on the database file), then an attempt is made to obtain a ** SHARED lock on the database file. Immediately after obtaining ** the SHARED lock, the file-system is checked for a hot-journal, -** which is played back if present. Following any hot-journal +** which is played back if present. Following any hot-journal ** rollback, the contents of the cache are validated by checking ** the 'change-counter' field of the database file header and ** discarded if they are found to be invalid. ** ** 2) If the pager is running in exclusive-mode, and there are currently @@ -62535,20 +52530,20 @@ ** no outstanding references to any pages, and is in the error state, ** then an attempt is made to clear the error state by discarding ** the contents of the page cache and rolling back any open journal ** file. ** -** If everything is successful, SQLITE_OK is returned. If an IO error -** occurs while locking the database, checking for a hot-journal file or +** If everything is successful, SQLITE_OK is returned. If an IO error +** occurs while locking the database, checking for a hot-journal file or ** rolling back a journal file, the IO error code is returned. */ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ /* This routine is only called from b-tree and only when there are no ** outstanding pages. This implies that the pager state should either - ** be OPEN or READER. READER is only possible if the pager is or was in + ** be OPEN or READER. READER is only possible if the pager is or was in ** exclusive access mode. */ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( assert_pager_state(pPager) ); assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); assert( pPager->errCode==SQLITE_OK ); @@ -62582,40 +52577,40 @@ /* Get an EXCLUSIVE lock on the database file. At this point it is ** important that a RESERVED lock is not obtained on the way to the ** EXCLUSIVE lock. If it were, another process might open the ** database file, detect the RESERVED lock, and conclude that the - ** database is safe to read while this process is still rolling the + ** database is safe to read while this process is still rolling the ** hot-journal back. - ** + ** ** Because the intermediate RESERVED lock is not requested, any - ** other process attempting to access the database file will get to - ** this point in the code and fail to obtain its own EXCLUSIVE lock + ** other process attempting to access the database file will get to + ** this point in the code and fail to obtain its own EXCLUSIVE lock ** on the database file. ** ** Unless the pager is in locking_mode=exclusive mode, the lock is ** downgraded to SHARED_LOCK before this function returns. */ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ goto failed; } - - /* If it is not already open and the file exists on disk, open the - ** journal for read/write access. Write access is required because - ** in exclusive-access mode the file descriptor will be kept open - ** and possibly used for a transaction later on. Also, write-access - ** is usually required to finalize the journal in journal_mode=persist + + /* If it is not already open and the file exists on disk, open the + ** journal for read/write access. Write access is required because + ** in exclusive-access mode the file descriptor will be kept open + ** and possibly used for a transaction later on. Also, write-access + ** is usually required to finalize the journal in journal_mode=persist ** mode (and also for journal_mode=truncate on some systems). ** - ** If the journal does not exist, it usually means that some - ** other connection managed to get in and roll it back before - ** this connection obtained the exclusive lock above. Or, it + ** If the journal does not exist, it usually means that some + ** other connection managed to get in and roll it back before + ** this connection obtained the exclusive lock above. Or, it ** may mean that the pager was in the error-state when this ** function was called and the journal file does not exist. */ - if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + if( !isOpen(pPager->jfd) ){ sqlite3_vfs * const pVfs = pPager->pVfs; int bExists; /* True if journal file exists */ rc = sqlite3OsAccess( pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); if( rc==SQLITE_OK && bExists ){ @@ -62628,11 +52623,11 @@ rc = SQLITE_CANTOPEN_BKPT; sqlite3OsClose(pPager->jfd); } } } - + /* Playback and delete the journal. Drop the database write ** lock and reacquire the read lock. Purge the cache before ** playing back the hot-journal so that we don't end up with ** an inconsistent cache. Sync the hot journal before playing ** it back since the process that crashed and left the hot journal @@ -62653,20 +52648,20 @@ if( rc!=SQLITE_OK ){ /* This branch is taken if an error occurs while trying to open ** or roll back a hot-journal while holding an EXCLUSIVE lock. The ** pager_unlock() routine will be called before returning to unlock ** the file. If the unlock attempt fails, then Pager.eLock must be - ** set to UNKNOWN_LOCK (see the comment above the #define for - ** UNKNOWN_LOCK above for an explanation). + ** set to UNKNOWN_LOCK (see the comment above the #define for + ** UNKNOWN_LOCK above for an explanation). ** ** In order to get pager_unlock() to do this, set Pager.eState to ** PAGER_ERROR now. This is not actually counted as a transition ** to ERROR state in the state diagram at the top of this file, ** since we know that the same call to pager_unlock() will very ** shortly transition the pager object to the OPEN state. Calling ** assert_pager_state() would fail now, as it should not be possible - ** to be in ERROR state when there are zero outstanding page + ** to be in ERROR state when there are zero outstanding page ** references. */ pager_error(pPager, rc); goto failed; } @@ -62687,12 +52682,12 @@ ** Database changes are detected by looking at 15 bytes beginning ** at offset 24 into the file. The first 4 of these 16 bytes are ** a 32-bit counter that is incremented with each change. The ** other bytes change randomly with each file change when ** a codec is in use. - ** - ** There is a vanishingly small chance that a change will not be + ** + ** There is a vanishingly small chance that a change will not be ** detected. The chance of an undetected change is so small that ** it can be neglected. */ char dbFileVers[sizeof(pPager->dbFileVers)]; @@ -62755,46 +52750,45 @@ ** transaction and unlock the pager. ** ** Except, in locking_mode=EXCLUSIVE when there is nothing to in ** the rollback journal, the unlock is not performed and there is ** nothing to rollback, so this routine is a no-op. -*/ +*/ static void pagerUnlockIfUnused(Pager *pPager){ - if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){ - assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */ + if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ pagerUnlockAndRollback(pPager); } } /* ** The page getter methods each try to acquire a reference to a -** page with page number pgno. If the requested reference is +** page with page number pgno. If the requested reference is ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. ** ** There are different implementations of the getter method depending ** 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. +** If the requested page is already in the cache, it is returned. ** Otherwise, a new page object is allocated and populated with data ** read from the database file. In some cases, the pcache module may ** choose not to allocate a new page object and may reuse an existing ** object with no outstanding references. ** -** The extra data appended to a page is always initialized to zeros the -** first time a page is loaded into memory. If the page requested is +** The extra data appended to a page is always initialized to zeros the +** first time a page is loaded into memory. If the page requested is ** already in the cache when this function is called, then the extra ** data is left as it was when the page object was last used. ** -** If the database image is smaller than the requested page or if -** the flags parameter contains the PAGER_GET_NOCONTENT bit and the -** requested page is not already stored in the cache, then no -** actual disk read occurs. In this case the memory image of the -** page is initialized to all zeros. +** If the database image is smaller than the requested page or if +** the flags parameter contains the PAGER_GET_NOCONTENT bit and the +** requested page is not already stored in the cache, then no +** actual disk read occurs. In this case the memory image of the +** page is initialized to all zeros. ** ** If PAGER_GET_NOCONTENT is true, it means that we do not care about ** the contents of the page. This occurs in two scenarios: ** ** a) When reading a free-list leaf page from the database, and @@ -62856,22 +52850,22 @@ 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. */ - assert( pgno!=PAGER_SJ_PGNO(pPager) ); + assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); pPager->aStat[PAGER_STAT_HIT]++; return SQLITE_OK; }else{ - /* The pager cache has created a new page. Its content needs to + /* The pager cache has created a new page. Its content needs to ** be initialized. But first some error checks: ** - ** (*) obsolete. Was: maximum page number is 2^31 + ** (1) The maximum page number is 2^31 ** (2) Never try to fetch the locking page */ - if( pgno==PAGER_SJ_PGNO(pPager) ){ + if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } pPg->pPager = pPager; @@ -62878,21 +52872,17 @@ assert( !isOpen(pPager->fd) || !MEMDB ); if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){ rc = SQLITE_FULL; - if( pgno<=pPager->dbSize ){ - sqlite3PcacheRelease(pPg); - pPg = 0; - } goto pager_acquire_err; } if( noContent ){ /* Failure to set the bits in the InJournal bit-vectors is benign. - ** It merely means that we might do some extra work to journal a - ** page that does not need to be journaled. Nevertheless, be sure - ** to test the case where a malloc error occurs while trying to set + ** It merely means that we might do some extra work to journal a + ** page that does not need to be journaled. Nevertheless, be sure + ** to test the case where a malloc error occurs while trying to set ** a bit in a bit vector. */ sqlite3BeginBenignMalloc(); if( pgno<=pPager->dbOrigSize ){ TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno); @@ -62903,13 +52893,18 @@ sqlite3EndBenignMalloc(); } memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ + u32 iFrame = 0; /* Frame to read from WAL file */ + if( pagerUseWal(pPager) ){ + 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); + rc = readDbPage(pPg, iFrame); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } } pager_set_pagehash(pPg); @@ -62938,17 +52933,20 @@ 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 + ** 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. */ @@ -62967,20 +52965,20 @@ return rc; } } if( bMmapOk && iFrame==0 ){ void *pData = 0; - rc = sqlite3OsFetch(pPager->fd, + rc = sqlite3OsFetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData ); if( rc==SQLITE_OK && pData ){ if( pPager->eState>PAGER_READER || pPager->tempFile ){ pPg = sqlite3PagerLookup(pPager, pgno); } if( pPg==0 ){ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ + }else{ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); } if( pPg ){ assert( rc==SQLITE_OK ); *ppPage = pPg; @@ -63017,35 +53015,22 @@ 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 */ ){ -#if 0 /* Trace page fetch by setting to 1 */ - int rc; - printf("PAGE %u\n", pgno); - fflush(stdout); - rc = pPager->xGet(pPager, pgno, ppPage, flags); - if( rc ){ - printf("PAGE %u failed with 0x%02x\n", pgno, rc); - fflush(stdout); - } - return rc; -#else - /* Normal, high-speed version of sqlite3PagerGet() */ return pPager->xGet(pPager, pgno, ppPage, flags); -#endif } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, -** or 0 if the page is not in cache. +** or 0 if the page is not in cache. ** ** See also sqlite3PagerGet(). The difference between this routine ** and sqlite3PagerGet() is that _get() will go to the disk and read ** in the page if the page is not already in cache. This routine -** returns NULL if the page is not in cache or if a disk I/O error +** returns NULL if the page is not in cache or if a disk I/O error ** has ever happened. */ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ sqlite3_pcache_page *pPage; assert( pPager!=0 ); @@ -63058,76 +53043,60 @@ } /* ** Release a page reference. ** -** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be used -** if we know that the page being released is not the last reference to page1. -** The btree layer always holds page1 open until the end, so these first -** two routines can be used to release any page other than BtShared.pPage1. -** The assert() at tag-20230419-2 proves that this constraint is always -** honored. -** -** 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. +** 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. */ SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ - TESTONLY( Pager *pPager = pPg->pPager; ) + Pager *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); } - /* Do not use this routine to release the last reference to page1 */ - assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); /* tag-20230419-2 */ + pagerUnlockIfUnused(pPager); } 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. -** There must already be a RESERVED or EXCLUSIVE lock on the database +** There must already be a RESERVED or EXCLUSIVE lock on the database ** file when this routine is called. ** ** Open the journal file for pager pPager and write a journal header ** to the start of it. If there are active savepoints, open the sub-journal -** as well. This function is only used when the journal file is being -** opened to write a rollback log for a transaction. It is not used +** as well. This function is only used when the journal file is being +** opened to write a rollback log for a transaction. It is not used ** when opening a hot journal file to roll it back. ** ** If the journal file is already open (as it may be in exclusive mode), ** then this function just writes a journal header to the start of the -** already open file. +** already open file. ** ** Whether or not the journal file is opened by this function, the ** Pager.pInJournal bitvec structure is allocated. ** -** Return SQLITE_OK if everything is successful. Otherwise, return -** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or +** Return SQLITE_OK if everything is successful. Otherwise, return +** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or ** an IO error code if opening or writing the journal file fails. */ static int pager_open_journal(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ assert( pPager->eState==PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); assert( pPager->pInJournal==0 ); - + /* If already in the error state, this function is a no-op. But on ** the other hand, this routine is never called if we are already in ** an error state. */ if( NEVER(pPager->errCode) ) return pPager->errCode; @@ -63134,11 +53103,11 @@ if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); if( pPager->pInJournal==0 ){ return SQLITE_NOMEM_BKPT; } - + /* Open the journal file if it is not already open. */ if( !isOpen(pPager->jfd) ){ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ sqlite3MemJournalOpen(pPager->jfd); }else{ @@ -63145,17 +53114,16 @@ int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; int nSpill; if( pPager->tempFile ){ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); - flags |= SQLITE_OPEN_EXCLUSIVE; nSpill = sqlite3Config.nStmtSpill; }else{ flags |= SQLITE_OPEN_MAIN_JOURNAL; nSpill = jrnlBufferSize(pPager); } - + /* Verify that the database still has the same name as it did when ** it was originally opened. */ rc = databaseIsUnmoved(pPager); if( rc==SQLITE_OK ){ rc = sqlite3JournalOpen ( @@ -63163,62 +53131,61 @@ ); } } assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); } - - - /* Write the first journal header to the journal file and open + + + /* Write the first journal header to the journal file and open ** the sub-journal if necessary. */ if( rc==SQLITE_OK ){ /* TODO: Check if all of these are really required. */ pPager->nRec = 0; pPager->journalOff = 0; - pPager->setSuper = 0; + pPager->setMaster = 0; pPager->journalHdr = 0; rc = writeJournalHdr(pPager); } } if( rc!=SQLITE_OK ){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; - pPager->journalOff = 0; }else{ assert( pPager->eState==PAGER_WRITER_LOCKED ); pPager->eState = PAGER_WRITER_CACHEMOD; } return rc; } /* -** Begin a write-transaction on the specified pager object. If a +** Begin a write-transaction on the specified pager object. If a ** write-transaction has already been opened, this function is a no-op. ** ** If the exFlag argument is false, then acquire at least a RESERVED ** lock on the database file. If exFlag is true, then acquire at least -** an EXCLUSIVE lock. If such a lock is already held, no locking +** an EXCLUSIVE lock. If such a lock is already held, no locking ** functions need be called. ** ** If the subjInMemory argument is non-zero, then any sub-journal opened ** within this transaction will be opened as an in-memory file. This ** has no effect if the sub-journal is already opened (as it may be when ** running in exclusive mode) or if the transaction does not require a ** sub-journal. If the subjInMemory argument is zero, then any required -** sub-journal is implemented in-memory if pPager is an in-memory database, +** sub-journal is implemented in-memory if pPager is an in-memory database, ** or using a temporary file otherwise. */ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ int rc = SQLITE_OK; if( pPager->errCode ) return pPager->errCode; assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory; - if( pPager->eState==PAGER_READER ){ + if( ALWAYS(pPager->eState==PAGER_READER) ){ assert( pPager->pInJournal==0 ); if( pagerUseWal(pPager) ){ /* If the pager is configured to use locking_mode=exclusive, and an ** exclusive lock on the database is not already held, obtain it now. @@ -63252,13 +53219,13 @@ if( rc==SQLITE_OK ){ /* Change to WRITER_LOCKED state. ** ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD ** when it has an open transaction, but never to DBMOD or FINISHED. - ** This is because in those states the code to roll back savepoint - ** transactions may copy data from the sub-journal into the database - ** file as well as into the page cache. Which would be incorrect in + ** This is because in those states the code to roll back savepoint + ** transactions may copy data from the sub-journal into the database + ** file as well as into the page cache. Which would be incorrect in ** WAL mode. */ pPager->eState = PAGER_WRITER_LOCKED; pPager->dbHintSize = pPager->dbSize; pPager->dbFileSize = pPager->dbSize; @@ -63286,14 +53253,14 @@ i64 iOff = pPager->journalOff; /* We should never write to the journal file the page that ** contains the database locks. The following assert verifies ** that we do not. */ - assert( pPg->pgno!=PAGER_SJ_PGNO(pPager) ); + assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); assert( pPager->journalHdr<=pPager->journalOff ); - pData2 = pPg->pData; + CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); cksum = pager_cksum(pPager, (u8*)pData2); /* Even if an IO or diskfull error occurs while journalling the ** page in the block above, set the need-sync flag for the page. ** Otherwise, when the transaction is rolled back, the logic in @@ -63308,15 +53275,15 @@ rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); if( rc!=SQLITE_OK ) return rc; rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); if( rc!=SQLITE_OK ) return rc; - IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, pPager->journalOff, pPager->pageSize)); PAGER_INCR(sqlite3_pager_writej_count); PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", - PAGERID(pPager), pPg->pgno, + PAGERID(pPager), pPg->pgno, ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); pPager->journalOff += 8 + pPager->pageSize; pPager->nRec++; assert( pPager->pInJournal!=0 ); @@ -63327,21 +53294,21 @@ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); return rc; } /* -** Mark a single data page as writeable. The page is written into the +** Mark a single data page as writeable. The page is written into the ** main journal or sub-journal as required. If the page is written into -** one of the journals, the corresponding bit is set in the +** one of the journals, the corresponding bit is set in the ** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs ** of any open savepoints as appropriate. */ static int pager_write(PgHdr *pPg){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; - /* This routine is not called unless a write-transaction has already + /* This routine is not called unless a write-transaction has already ** been started. The journal file may or may not be open at this point. ** It is never called in the ERROR state. */ assert( pPager->eState==PAGER_WRITER_LOCKED || pPager->eState==PAGER_WRITER_CACHEMOD @@ -63354,11 +53321,11 @@ /* The journal file needs to be opened. Higher level routines have already ** obtained the necessary locks to begin the write-transaction, but the ** rollback journal might not yet be open. Open it now if this is the case. ** - ** This is done before calling sqlite3PcacheMakeDirty() on the page. + ** This is done before calling sqlite3PcacheMakeDirty() on the page. ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then ** an error might occur and the pager would end up in WRITER_LOCKED state ** with pages marked as dirty in the cache. */ if( pPager->eState==PAGER_WRITER_LOCKED ){ @@ -63399,11 +53366,11 @@ ** and before writing the page into the rollback journal. Wait until now, ** after the page has been successfully journalled, before setting the ** PGHDR_WRITEABLE bit that indicates that the page can be safely modified. */ pPg->flags |= PGHDR_WRITEABLE; - + /* If the statement journal is open and the page is not in it, ** then write the page into the statement journal. */ if( pPager->nSavepoint>0 ){ rc = subjournalPageIfRequired(pPg); @@ -63465,11 +53432,11 @@ for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_SJ_PGNO(pPager) ){ + if( pg!=PAGER_MJ_PGNO(pPager) ){ rc = sqlite3PagerGet(pPager, pg, &pPage, 0); if( rc==SQLITE_OK ){ rc = pager_write(pPage); if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; @@ -63483,11 +53450,11 @@ } sqlite3PagerUnrefNotNull(pPage); } } - /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages + /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages ** starting at pg1, then it needs to be set for all of them. Because ** writing to any of these nPage pages may damage the others, the ** journal file must contain sync()ed copies of all of them ** before any of them can be written out to the database file. */ @@ -63506,13 +53473,13 @@ pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; return rc; } /* -** Mark a data page as writeable. This routine must be called before -** making changes to a page. The caller must check the return value -** of this function and be careful not to change any page data unless +** Mark a data page as writeable. This routine must be called before +** making changes to a page. The caller must check the return value +** of this function and be careful not to change any page data unless ** this routine returns SQLITE_OK. ** ** The difference between this function and pager_write() is that this ** function also deals with the special case where 2 or more pages ** fit on a single disk sector. In this case all co-resident pages @@ -63559,17 +53526,17 @@ ** ** The overlying software layer calls this routine when all of the data ** on the given page is unused. The pager marks the page as clean so ** that it does not get written to disk. ** -** Tests show that this optimization can quadruple the speed of large +** Tests show that this optimization can quadruple the speed of large ** DELETE operations. ** ** This optimization cannot be used with a temp-file, as the page may ** have been dirty at the start of the transaction. In that case, if -** memory pressure forces page pPg out of the cache, the data does need -** to be written out to disk so that it may be read back in if the +** memory pressure forces page pPg out of the cache, the data does need +** to be written out to disk so that it may be read back in if the ** current transaction is rolled back. */ SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ @@ -63581,29 +53548,29 @@ pager_set_pagehash(pPg); } } /* -** This routine is called to increment the value of the database file -** change-counter, stored as a 4-byte big-endian integer starting at +** This routine is called to increment the value of the database file +** change-counter, stored as a 4-byte big-endian integer starting at ** byte offset 24 of the pager file. The secondary change counter at ** 92 is also updated, as is the SQLite version number at offset 96. ** ** But this only happens if the pPager->changeCountDone flag is false. ** To avoid excess churning of page 1, the update only happens once. -** See also the pager_write_changecounter() routine that does an +** See also the pager_write_changecounter() routine that does an ** unconditional update of the change counters. ** -** If the isDirectMode flag is zero, then this is done by calling +** If the isDirectMode flag is zero, then this is done by calling ** sqlite3PagerWrite() on page 1, then modifying the contents of the ** page data. In this case the file will be updated when the current ** transaction is committed. ** ** The isDirectMode flag may only be non-zero if the library was compiled ** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, ** if isDirect is non-zero, then the database file is updated directly -** by writing an updated version of page 1 using a call to the +** by writing an updated version of page 1 using a call to the ** sqlite3OsWrite() function. */ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ int rc = SQLITE_OK; @@ -63628,21 +53595,21 @@ UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif - if( !pPager->changeCountDone && pPager->dbSize>0 ){ + if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){ PgHdr *pPgHdr; /* Reference to page 1 */ assert( !pPager->tempFile && isOpen(pPager->fd) ); /* Open page 1 of the file for writing. */ rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0); assert( pPgHdr==0 || rc==SQLITE_OK ); /* If page one was fetched successfully, and this function is not - ** operating in direct-mode, make page 1 writable. When not in + ** operating in direct-mode, make page 1 writable. When not in ** direct mode, page 1 is always held in cache and hence the PagerGet() ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. */ if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){ rc = sqlite3PagerWrite(pPgHdr); @@ -63654,11 +53621,11 @@ /* If running in direct mode, write the contents of page 1 to the file. */ if( DIRECT_MODE ){ const void *zBuf; assert( pPager->dbFileSize>0 ); - zBuf = pPgHdr->pData; + CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); pPager->aStat[PAGER_STAT_WRITE]++; } if( rc==SQLITE_OK ){ @@ -63685,40 +53652,43 @@ ** or pages with the Pager.noSync flag set. ** ** If successful, or if called on a pager for which it is a no-op, this ** function returns SQLITE_OK. Otherwise, an IO error code is returned. */ -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper){ +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; - void *pArg = (void*)zSuper; - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + + if( isOpen(pPager->fd) ){ + void *pArg = (void*)zMaster; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } if( rc==SQLITE_OK && !pPager->noSync ){ assert( !MEMDB ); rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); } return rc; } /* ** This function may only be called while a write-transaction is active in -** rollback. If the connection is in WAL mode, this call is a no-op. -** Otherwise, if the connection does not already have an EXCLUSIVE lock on +** rollback. If the connection is in WAL mode, this call is a no-op. +** Otherwise, if the connection does not already have an EXCLUSIVE lock on ** the database file, an attempt is made to obtain one. ** ** If the EXCLUSIVE lock is already held or the attempt to obtain it is ** successful, or the connection is in WAL mode, SQLITE_OK is returned. -** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is +** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is ** returned. */ SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){ int rc = pPager->errCode; assert( assert_pager_state(pPager) ); if( rc==SQLITE_OK ){ - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - || pPager->eState==PAGER_WRITER_LOCKED + assert( pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + || pPager->eState==PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); if( 0==pagerUseWal(pPager) ){ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); } @@ -63725,38 +53695,38 @@ } return rc; } /* -** Sync the database file for the pager pPager. zSuper points to the name -** of a super-journal file that should be written into the individual -** journal file. zSuper may be NULL, which is interpreted as no -** super-journal (a single database transaction). +** Sync the database file for the pager pPager. zMaster points to the name +** of a master journal file that should be written into the individual +** journal file. zMaster may be NULL, which is interpreted as no master +** journal (a single database transaction). ** ** This routine ensures that: ** ** * The database file change-counter is updated, ** * the journal is synced (unless the atomic-write optimization is used), -** * all dirty pages are written to the database file, +** * all dirty pages are written to the database file, ** * the database file is truncated (if required), and -** * the database file synced. +** * the database file synced. ** -** The only thing that remains to commit the transaction is to finalize -** (delete, truncate or zero the first part of) the journal file (or -** delete the super-journal file if specified). +** The only thing that remains to commit the transaction is to finalize +** (delete, truncate or zero the first part of) the journal file (or +** delete the master journal file if specified). ** -** Note that if zSuper==NULL, this does not overwrite a previous value +** Note that if zMaster==NULL, this does not overwrite a previous value ** passed to an sqlite3PagerCommitPhaseOne() call. ** ** If the final parameter - noSync - is true, then the database file itself ** is not synced. The caller must call sqlite3PagerSync() directly to ** sync the database file before calling CommitPhaseTwo() to delete the ** journal file in this case. */ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( Pager *pPager, /* Pager object */ - const char *zSuper, /* If not NULL, the super-journal name */ + const char *zMaster, /* If not NULL, the master journal name */ int noSync /* True to omit the xSync on the db file */ ){ int rc = SQLITE_OK; /* Return code */ assert( pPager->eState==PAGER_WRITER_LOCKED @@ -63770,12 +53740,12 @@ if( NEVER(pPager->errCode) ) return pPager->errCode; /* Provide the ability to easily simulate an I/O error during testing */ if( sqlite3FaultSim(400) ) return SQLITE_IOERR; - PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n", - pPager->zFilename, zSuper, pPager->dbSize)); + PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", + pPager->zFilename, zMaster, pPager->dbSize)); /* If no database changes have been made, return early. */ if( pPager->eStatetempFile ); @@ -63784,14 +53754,13 @@ /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is mostly a no-op. However, any ** backup in progress needs to be restarted. */ sqlite3BackupRestart(pPager->pBackup); }else{ - PgHdr *pList; if( pagerUseWal(pPager) ){ + PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); PgHdr *pPageOne = 0; - pList = sqlite3PcacheDirtyList(pPager->pPCache); if( pList==0 ){ /* Must have at least one page for the WAL commit flag. ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0); pList = pPageOne; @@ -63804,165 +53773,106 @@ sqlite3PagerUnref(pPageOne); if( rc==SQLITE_OK ){ 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. - */ -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - sqlite3_file *fd = pPager->fd; - int bBatch = zSuper==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 - ** runtime criteria to use the operation: + ** was enabled at compile time, and if this transaction meets the + ** runtime criteria to use the operation: ** ** * The file-system supports the atomic-write property for - ** blocks of size page-size, and + ** blocks of size page-size, and ** * This commit is not part of a multi-file transaction, and ** * Exactly one page has been modified and store in the journal file. ** ** If the optimization was not enabled at compile time, then the ** pager_incr_changecounter() function is called to update the change ** counter in 'indirect-mode'. If the optimization is compiled in but ** is not applicable to this transaction, call sqlite3JournalCreate() ** to make sure the journal file has actually been created, then call ** pager_incr_changecounter() to update the change-counter in indirect - ** mode. + ** mode. ** ** Otherwise, if the optimization is both enabled and applicable, ** then call pager_incr_changecounter() to update the change-counter ** in 'direct' mode. In this case the journal file will never be ** created for this transaction. */ - if( bBatch==0 ){ - PgHdr *pPg; - assert( isOpen(pPager->jfd) - || pPager->journalMode==PAGER_JOURNALMODE_OFF - || pPager->journalMode==PAGER_JOURNALMODE_WAL - ); - if( !zSuper && isOpen(pPager->jfd) - && pPager->journalOff==jrnlBufferSize(pPager) - && pPager->dbSize>=pPager->dbOrigSize - && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) - ){ - /* Update the db file change counter via the direct-write method. The - ** following call will modify the in-memory representation of page 1 - ** to include the updated change counter and then write page 1 - ** directly to the database file. Because of the atomic-write - ** 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 /* SQLITE_ENABLE_ATOMIC_WRITE */ -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( zSuper ){ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - assert( bBatch==0 ); - } -#endif - rc = pager_incr_changecounter(pPager, 0); -#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */ - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - /* Write the super-journal name into the journal file. If a - ** super-journal file name has already been written to the journal file, - ** or if zSuper is NULL (no super-journal), then this call is a no-op. - */ - rc = writeSuperJournal(pPager, zSuper); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - /* Sync the journal file and write all dirty pages to the database. - ** If the atomic-update optimization is being used, this sync will not + #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); + } + } + #else + rc = pager_incr_changecounter(pPager, 0); + #endif + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + /* Write the master journal name into the journal file. If a master + ** journal file name has already been written to the journal file, + ** or if zMaster is NULL (no master journal), then this call is a no-op. + */ + rc = writeMasterJournal(pPager, zMaster); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + /* Sync the journal file and write all dirty pages to the database. + ** If the atomic-update optimization is being used, this sync will not ** create the journal file or perform any real IO. ** ** Because the change-counter page was just modified, unless the ** atomic-update optimization is used it is almost certain that the ** journal requires a sync here. However, in locking_mode=exclusive - ** on a system under memory pressure it is just possible that this is + ** on a system under memory pressure it is just possible that this is ** not the case. In this case it is likely enough that the redundant - ** xSync() call will be changed to a no-op by the OS anyhow. + ** xSync() call will be changed to a no-op by the OS anyhow. */ rc = syncJournal(pPager, 0); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - pList = sqlite3PcacheDirtyList(pPager->pPCache); -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( bBatch ){ - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); - if( rc==SQLITE_OK ){ - rc = pager_write_pagelist(pPager, pList); - if( rc==SQLITE_OK && pPager->dbSize>pPager->dbFileSize ){ - char *pTmp = pPager->pTmpSpace; - int szPage = (int)pPager->pageSize; - memset(pTmp, 0, szPage); - rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, - ((i64)pPager->dbSize*pPager->pageSize)-szPage); - } - if( rc==SQLITE_OK ){ - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); - } - if( rc!=SQLITE_OK ){ - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); - } - } - - if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc!=SQLITE_OK ){ - sqlite3OsClose(pPager->jfd); - goto commit_phase_one_exit; - } - bBatch = 0; - }else{ - sqlite3OsClose(pPager->jfd); - } - } -#endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ - - if( bBatch==0 ){ - rc = pager_write_pagelist(pPager, pList); - } + + rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; } sqlite3PcacheCleanAll(pPager->pPCache); - /* If the file on disk is smaller than the database image, use + /* If the file on disk is smaller than the database image, use ** pager_truncate to grow the file here. This can happen if the database ** image was extended as part of the current transaction and then the ** last page in the db image moved to the free-list. In this case the ** last page is never written out to disk, leaving the database file ** undersized. Fix this now if it is the case. */ if( pPager->dbSize>pPager->dbFileSize ){ - Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_SJ_PGNO(pPager)); + Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); assert( pPager->eState==PAGER_WRITER_DBMOD ); rc = pager_truncate(pPager, nNew); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; } - + /* Finally, sync the database file. */ if( !noSync ){ - rc = sqlite3PagerSync(pPager, zSuper); + rc = sqlite3PagerSync(pPager, zMaster); } IOTRACE(("DBSYNC %p\n", pPager)) } } @@ -63975,16 +53885,16 @@ /* ** When this function is called, the database file has been completely ** updated to reflect the changes made by the current transaction and -** synced to disk. The journal file still exists in the file-system +** synced to disk. The journal file still exists in the file-system ** though, and if a failure occurs at this point it will eventually ** be used as a hot-journal and the current transaction rolled back. ** -** This function finalizes the journal file, either by deleting, -** truncating or partially zeroing it, so that it cannot be used +** This function finalizes the journal file, either by deleting, +** truncating or partially zeroing it, so that it cannot be used ** for hot-journal rollback. Once this is done the transaction is ** irrevocably committed. ** ** If an error occurs, an IO error code is returned and the pager ** moves into the error state. Otherwise, SQLITE_OK is returned. @@ -63994,11 +53904,10 @@ /* This routine should not be called if a prior error has occurred. ** But if (due to a coding error elsewhere in the system) it does get ** called, just return the same error code without doing anything. */ if( NEVER(pPager->errCode) ) return pPager->errCode; - pPager->iDataVersion++; assert( pPager->eState==PAGER_WRITER_LOCKED || pPager->eState==PAGER_WRITER_FINISHED || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD) ); @@ -64006,50 +53915,51 @@ /* An optimization. If the database was not actually modified during ** this transaction, the pager is running in exclusive-mode and is ** using persistent journals, then this function is a no-op. ** - ** The start of the journal file currently contains a single journal + ** The start of the journal file currently contains a single journal ** header with the nRec field set to 0. If such a journal is used as ** a hot-journal during hot-journal rollback, 0 changes will be made - ** to the database file. So there is no need to zero the journal + ** to the database file. So there is no need to zero the journal ** header. Since the pager is in exclusive mode, there is no need ** to drop any locks either. */ - if( pPager->eState==PAGER_WRITER_LOCKED - && pPager->exclusiveMode + if( pPager->eState==PAGER_WRITER_LOCKED + && pPager->exclusiveMode && pPager->journalMode==PAGER_JOURNALMODE_PERSIST ){ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); pPager->eState = PAGER_READER; return SQLITE_OK; } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); - rc = pager_end_transaction(pPager, pPager->setSuper, 1); + pPager->iDataVersion++; + rc = pager_end_transaction(pPager, pPager->setMaster, 1); return pager_error(pPager, rc); } /* -** If a write transaction is open, then all changes made within the +** If a write transaction is open, then all changes made within the ** transaction are reverted and the current write-transaction is closed. ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR ** state if an error occurs. ** ** If the pager is already in PAGER_ERROR state when this function is called, ** it returns Pager.errCode immediately. No work is performed in this case. ** ** Otherwise, in rollback mode, this function performs two functions: ** -** 1) It rolls back the journal file, restoring all database file and +** 1) It rolls back the journal file, restoring all database file and ** in-memory cache pages to the state they were in when the transaction ** was opened, and ** ** 2) It finalizes the journal file, so that it is not used for hot ** rollback at any point in the future. ** -** Finalization of the journal file (task 2) is only performed if the +** Finalization of the journal file (task 2) is only performed if the ** rollback is successful. ** ** In WAL mode, all cache-entries containing data modified within the ** current transaction are either expelled from the cache or reverted to ** their pre-transaction state by re-reading data from the database or @@ -64058,27 +53968,27 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); /* PagerRollback() is a no-op if called in READER or OPEN state. If - ** the pager is already in the ERROR state, the rollback is not + ** the pager is already in the ERROR state, the rollback is not ** attempted here. Instead, the error code is returned to the caller. */ assert( assert_pager_state(pPager) ); if( pPager->eState==PAGER_ERROR ) return pPager->errCode; if( pPager->eState<=PAGER_READER ) return SQLITE_OK; if( pagerUseWal(pPager) ){ int rc2; rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); - rc2 = pager_end_transaction(pPager, pPager->setSuper, 0); + rc2 = pager_end_transaction(pPager, pPager->setMaster, 0); if( rc==SQLITE_OK ) rc = rc2; }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ int eState = pPager->eState; rc = pager_end_transaction(pPager, 0, 0); if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ - /* This can happen using journal_mode=off. Move the pager to the error + /* This can happen using journal_mode=off. Move the pager to the error ** state to indicate that the contents of the cache may not be trusted. ** Any active readers will get SQLITE_ABORT. */ pPager->errCode = SQLITE_ABORT; pPager->eState = PAGER_ERROR; @@ -64089,11 +53999,11 @@ rc = pager_playback(pPager, 0); } assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT - || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR + || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR || rc==SQLITE_CANTOPEN ); /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error persistent. @@ -64121,12 +54031,12 @@ /* ** Return the approximate number of bytes of memory currently ** used by the pager and its associated cache. */ SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){ - int perPageSize = pPager->pageSize + pPager->nExtra - + (int)(sizeof(PgHdr) + 5*sizeof(void*)); + int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr) + + 5*sizeof(void*); return perPageSize*sqlite3PcachePagecount(pPager->pPCache) + sqlite3MallocSize(pPager) + pPager->pageSize; } @@ -64147,64 +54057,57 @@ a[1] = sqlite3PcachePagecount(pPager->pPCache); a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; a[4] = pPager->eState; a[5] = pPager->errCode; - a[6] = (int)pPager->aStat[PAGER_STAT_HIT] & 0x7fffffff; - a[7] = (int)pPager->aStat[PAGER_STAT_MISS] & 0x7fffffff; + a[6] = pPager->aStat[PAGER_STAT_HIT]; + a[7] = pPager->aStat[PAGER_STAT_MISS]; a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; - a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff; + a[10] = pPager->aStat[PAGER_STAT_WRITE]; return a; } #endif /* -** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE, -** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation -** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because -** it was added later. -** -** Before returning, *pnVal is incremented by the -** current cache hit or miss count, according to the value of eStat. If the -** reset parameter is non-zero, the cache hit or miss count is zeroed before +** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or +** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the +** current cache hit or miss count, according to the value of eStat. If the +** reset parameter is non-zero, the cache hit or miss count is zeroed before ** returning. */ -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){ +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ assert( eStat==SQLITE_DBSTATUS_CACHE_HIT || eStat==SQLITE_DBSTATUS_CACHE_MISS || eStat==SQLITE_DBSTATUS_CACHE_WRITE - || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1 ); assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); - assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 - && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 ); + assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); - eStat -= SQLITE_DBSTATUS_CACHE_HIT; - *pnVal += pPager->aStat[eStat]; + *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; if( reset ){ - pPager->aStat[eStat] = 0; + pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; } } /* ** Return true if this is an in-memory or temp-file backed pager. */ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){ - return pPager->tempFile || pPager->memVfs; + return pPager->tempFile; } /* ** Check that there are at least nSavepoint savepoints open. If there are ** currently less than nSavepoints open, then open one or more savepoints ** to make up the difference. If the number of savepoints is already ** equal to nSavepoint, then this function is a no-op. ** -** If a memory allocation fails, SQLITE_NOMEM is returned. If an error +** If a memory allocation fails, SQLITE_NOMEM is returned. If an error ** occurs while opening the sub-journal file, then an IO error code is ** returned. Otherwise, SQLITE_OK. */ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ int rc = SQLITE_OK; /* Return code */ @@ -64215,11 +54118,11 @@ assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); assert( nSavepoint>nCurrent && pPager->useJournal ); /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM - ** if the allocation fails. Otherwise, zero the new portion in case a + ** if the allocation fails. Otherwise, zero the new portion in case a ** malloc failure occurs while populating it in the for(...) loop below. */ aNew = (PagerSavepoint *)sqlite3Realloc( pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint ); @@ -64237,11 +54140,10 @@ }else{ aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); } aNew[ii].iSubRec = pPager->nSubRec; aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); - aNew[ii].bTruncateOnRelease = 1; if( !aNew[ii].pInSavepoint ){ return SQLITE_NOMEM_BKPT; } if( pagerUseWal(pPager) ){ sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); @@ -64264,41 +54166,41 @@ } /* ** This function is called to rollback or release (commit) a savepoint. -** The savepoint to release or rollback need not be the most recently +** The savepoint to release or rollback need not be the most recently ** created savepoint. ** ** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE. ** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with ** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes ** that have occurred since the specified savepoint was created. ** -** The savepoint to rollback or release is identified by parameter +** The savepoint to rollback or release is identified by parameter ** iSavepoint. A value of 0 means to operate on the outermost savepoint ** (the first created). A value of (Pager.nSavepoint-1) means operate ** on the most recently created savepoint. If iSavepoint is greater than ** (Pager.nSavepoint-1), then this function is a no-op. ** ** If a negative value is passed to this function, then the current -** transaction is rolled back. This is different to calling +** transaction is rolled back. This is different to calling ** sqlite3PagerRollback() because this function does not terminate -** the transaction or unlock the database, it just restores the -** contents of the database to its original state. +** the transaction or unlock the database, it just restores the +** contents of the database to its original state. ** -** In any case, all savepoints with an index greater than iSavepoint +** In any case, all savepoints with an index greater than iSavepoint ** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE), ** then savepoint iSavepoint is also destroyed. ** ** This function may return SQLITE_NOMEM if a memory allocation fails, -** or an IO error code if an IO error occurs while rolling back a +** or an IO error code if an IO error occurs while rolling back a ** savepoint. If no errors occur, SQLITE_OK is returned. -*/ +*/ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ int rc = pPager->errCode; - + #ifdef SQLITE_ENABLE_ZIPVFS if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK; #endif assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); @@ -64307,31 +54209,29 @@ if( rc==SQLITE_OK && iSavepointnSavepoint ){ int ii; /* Iterator variable */ int nNew; /* Number of remaining savepoints after this op. */ /* Figure out how many savepoints will still be active after this - ** operation. Store this value in nNew. Then free resources associated + ** operation. Store this value in nNew. Then free resources associated ** with any savepoints that are destroyed by this operation. */ nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); for(ii=nNew; iinSavepoint; ii++){ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); } pPager->nSavepoint = nNew; - /* Truncate the sub-journal so that it only includes the parts - ** that are still in use. */ + /* If this is a release of the outermost savepoint, truncate + ** the sub-journal to zero bytes in size. */ if( op==SAVEPOINT_RELEASE ){ - PagerSavepoint *pRel = &pPager->aSavepoint[nNew]; - if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){ + if( nNew==0 && isOpen(pPager->sjfd) ){ /* Only truncate if it is an in-memory sub-journal. */ if( sqlite3JournalIsInMemory(pPager->sjfd) ){ - i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec; - rc = sqlite3OsTruncate(pPager->sjfd, sz); + rc = sqlite3OsTruncate(pPager->sjfd, 0); assert( rc==SQLITE_OK ); } - pPager->nSubRec = pRel->iSubRec; + pPager->nSubRec = 0; } } /* Else this is a rollback operation, playback the specified savepoint. ** If this is a temp-file, it is possible that the journal file has ** not yet been opened. In this case there have been no changes to @@ -64340,18 +54240,18 @@ else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){ PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; rc = pagerPlaybackSavepoint(pPager, pSavepoint); assert(rc!=SQLITE_DONE); } - + #ifdef SQLITE_ENABLE_ZIPVFS - /* If the cache has been modified but the savepoint cannot be rolled + /* If the cache has been modified but the savepoint cannot be rolled ** back journal_mode=off, put the pager in the error state. This way, ** if the VFS used by this pager includes ZipVFS, the entire transaction ** can be rolled back at the ZipVFS level. */ - else if( - pPager->journalMode==PAGER_JOURNALMODE_OFF + else if( + pPager->journalMode==PAGER_JOURNALMODE_OFF && pPager->eState>=PAGER_WRITER_CACHEMOD ){ pPager->errCode = SQLITE_ABORT; pPager->eState = PAGER_ERROR; setGetterMethod(pPager); @@ -64369,21 +54269,13 @@ ** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when ** used to report the filename to the user, for compatibility with legacy ** behavior. But when the Btree needs to know the filename for matching to ** shared cache, it uses nullIfMemDb==0 so that in-memory databases can ** participate in shared-cache. -** -** The return value to this routine is always safe to use with -** sqlite3_uri_parameter() and sqlite3_filename_database() and friends. */ -SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){ - static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - if( nullIfMemDb && (pPager->memDb || sqlite3IsMemdb(pPager->pVfs)) ){ - return &zFake[4]; - }else{ - return pPager->zFilename; - } +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){ + return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename; } /* ** Return the VFS structure for the pager. */ @@ -64403,11 +54295,11 @@ /* ** Return the file handle for the journal file (if it exists). ** This will be either the rollback journal or the WAL file. */ SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ -#ifdef SQLITE_OMIT_WAL +#if SQLITE_OMIT_WAL return pPager->jfd; #else return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd; #endif } @@ -64417,10 +54309,54 @@ */ SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){ return pPager->zJournal; } +#ifdef SQLITE_HAS_CODEC +/* +** Set or retrieve the codec for this pager +*/ +SQLITE_PRIVATE void sqlite3PagerSetCodec( + Pager *pPager, + void *(*xCodec)(void*,void*,Pgno,int), + void (*xCodecSizeChng)(void*,int,int), + void (*xCodecFree)(void*), + void *pCodec +){ + if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); + pPager->xCodec = pPager->memDb ? 0 : xCodec; + pPager->xCodecSizeChng = xCodecSizeChng; + pPager->xCodecFree = xCodecFree; + pPager->pCodec = pCodec; + setGetterMethod(pPager); + pagerReportSize(pPager); +} +SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){ + return pPager->pCodec; +} + +/* +** This function is called by the wal module when writing page content +** into the log file. +** +** This function returns a pointer to a buffer containing the encrypted +** page content. If a malloc fails, this function may return NULL. +*/ +SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){ + void *aData = 0; + CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); + return aData; +} + +/* +** Return the current pager state +*/ +SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){ + return pPager->eState; +} +#endif /* SQLITE_HAS_CODEC */ + #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Move the page pPg to location pgno in the file. ** ** There must be no references to the page previously located at @@ -64436,12 +54372,12 @@ ** required that a statement transaction was not active, but this restriction ** has been removed (CREATE INDEX needs to move a page when a statement ** transaction is active). ** ** If the fourth argument, isCommit, is non-zero, then this page is being -** moved as part of a database reorganization just before the transaction -** is being committed. In this case, it is guaranteed that the database page +** moved as part of a database reorganization just before the transaction +** is being committed. In this case, it is guaranteed that the database page ** pPg refers to will not be written to again within this transaction. ** ** This function may return SQLITE_NOMEM or an IO error code if an error ** occurs. Otherwise, it returns SQLITE_OK. */ @@ -64465,11 +54401,11 @@ rc = sqlite3PagerWrite(pPg); if( rc ) return rc; } /* If the page being moved is dirty and has not been saved by the latest - ** savepoint, then save the current contents of the page into the + ** savepoint, then save the current contents of the page into the ** sub-journal now. This is required to handle the following scenario: ** ** BEGIN; ** ** SAVEPOINT one; @@ -64488,19 +54424,19 @@ && SQLITE_OK!=(rc = subjournalPageIfRequired(pPg)) ){ return rc; } - PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", + PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno)); IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) /* If the journal needs to be sync()ed before page pPg->pgno can ** be written to, store pPg->pgno in local variable needSyncPgno. ** ** If the isCommit flag is set, there is no need to remember that - ** the journal needs to be sync()ed before database page pPg->pgno + ** the journal needs to be sync()ed before database page pPg->pgno ** can be written to. The caller has already promised not to write to it. */ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ needSyncPgno = pPg->pgno; assert( pPager->journalMode==PAGER_JOURNALMODE_OFF || @@ -64507,22 +54443,18 @@ pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); assert( pPg->flags&PGHDR_DIRTY ); } /* If the cache contains a page with page-number pgno, remove it - ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for - ** page pgno before the 'move' operation, it needs to be retained + ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for + ** page pgno before the 'move' operation, it needs to be retained ** for the page moved there. */ pPg->flags &= ~PGHDR_NEED_SYNC; pPgOld = sqlite3PagerLookup(pPager, pgno); - assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB ); + assert( !pPgOld || pPgOld->nRef==1 ); if( pPgOld ){ - if( NEVER(pPgOld->nRef>1) ){ - sqlite3PagerUnrefNotNull(pPgOld); - return SQLITE_CORRUPT_BKPT; - } pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); if( pPager->tempFile ){ /* Do not discard pages from an in-memory database since we might ** need to rollback later. Just move the page out of the way. */ sqlite3PcacheMove(pPgOld, pPager->dbSize+1); @@ -64543,13 +54475,13 @@ sqlite3PcacheMove(pPgOld, origPgno); sqlite3PagerUnrefNotNull(pPgOld); } if( needSyncPgno ){ - /* If needSyncPgno is non-zero, then the journal file needs to be + /* If needSyncPgno is non-zero, then the journal file needs to be ** sync()ed before any data is written to database file page needSyncPgno. - ** Currently, no such page exists in the page-cache and the + ** Currently, no such page exists in the page-cache and the ** "is journaled" bitvec flag has been set. This needs to be remedied by ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC ** flag. ** ** If the attempt to load the page into the page-cache fails, (due @@ -64576,13 +54508,13 @@ return SQLITE_OK; } #endif /* -** The page handle passed as the first argument refers to a dirty page -** with a page number other than iNew. This function changes the page's -** page number to iNew and sets the value of the PgHdr.flags field to +** The page handle passed as the first argument refers to a dirty page +** with a page number other than iNew. This function changes the page's +** page number to iNew and sets the value of the PgHdr.flags field to ** the value passed as the third parameter. */ SQLITE_PRIVATE void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){ assert( pPg->pgno!=iNew ); pPg->flags = flags; @@ -64596,20 +54528,20 @@ assert( pPg->nRef>0 || pPg->pPager->memDb ); return pPg->pData; } /* -** Return a pointer to the Pager.nExtra bytes of "extra" space +** Return a pointer to the Pager.nExtra bytes of "extra" space ** allocated along with the specified page. */ SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){ return pPg->pExtra; } /* ** Get/set the locking-mode for this pager. Parameter eMode must be one -** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or +** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or ** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then ** the locking-mode is set to the value specified. ** ** The returned value is either PAGER_LOCKINGMODE_NORMAL or ** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) @@ -64648,18 +54580,25 @@ ** ** The returned indicate the current (possibly updated) journal-mode. */ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ u8 eOld = pPager->journalMode; /* Prior journalmode */ + +#ifdef SQLITE_DEBUG + /* The print_pager_state() routine is intended to be used by the debugger + ** only. We invoke it once here to suppress a compiler warning. */ + print_pager_state(pPager); +#endif + /* The eMode parameter is always valid */ - assert( eMode==PAGER_JOURNALMODE_DELETE /* 0 */ - || eMode==PAGER_JOURNALMODE_PERSIST /* 1 */ - || eMode==PAGER_JOURNALMODE_OFF /* 2 */ - || eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */ - || eMode==PAGER_JOURNALMODE_MEMORY /* 4 */ - || eMode==PAGER_JOURNALMODE_WAL /* 5 */ ); + assert( eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_TRUNCATE + || eMode==PAGER_JOURNALMODE_PERSIST + || eMode==PAGER_JOURNALMODE_OFF + || eMode==PAGER_JOURNALMODE_WAL + || eMode==PAGER_JOURNALMODE_MEMORY ); /* This routine is only called from the OP_JournalMode opcode, and ** the logic there will never allow a temporary file to be changed ** to WAL mode. */ @@ -64679,11 +54618,11 @@ /* Change the journal mode. */ assert( pPager->eState!=PAGER_ERROR ); pPager->journalMode = (u8)eMode; - /* When transitioning from TRUNCATE or PERSIST to any other journal + /* When transistioning from TRUNCATE or PERSIST to any other journal ** mode except WAL, unless the pager is in locking_mode=exclusive mode, ** delete the journal file. */ assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); @@ -64692,10 +54631,11 @@ assert( (PAGER_JOURNALMODE_OFF & 5)==0 ); assert( (PAGER_JOURNALMODE_WAL & 5)==5 ); assert( isOpen(pPager->fd) || pPager->exclusiveMode ); if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){ + /* In this case we would like to delete the journal file. If it is ** not possible, then that is not a problem. Deleting the journal file ** here is an optimization only. ** ** Before deleting the journal file, obtain a RESERVED lock on the @@ -64724,11 +54664,11 @@ }else if( state==PAGER_OPEN ){ pager_unlock(pPager); } assert( state==pPager->eState ); } - }else if( eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ){ + }else if( eMode==PAGER_JOURNALMODE_OFF ){ sqlite3OsClose(pPager->jfd); } } /* Return the new journal mode */ @@ -64803,27 +54743,15 @@ 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==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){ - /* This only happens when a database file is zero bytes in size opened and - ** then "PRAGMA journal_mode=WAL" is run and then sqlite3_wal_checkpoint() - ** is invoked without any intervening transactions. We need to start - ** a transaction to initialize pWal. The PRAGMA table_list statement is - ** used for this since it starts transactions on every database file, - ** including all ATTACHed databases. This seems expensive for a single - ** sqlite3_wal_checkpoint() call, but it happens very rarely. - ** https://sqlite.org/forum/forumpost/fd0f19d229156939 - */ - sqlite3_exec(db, "PRAGMA table_list",0,0,0); - } if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, - pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, + pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); } return rc; } @@ -64846,26 +54774,24 @@ ** Attempt to take an exclusive lock on the database file. If a PENDING lock ** is obtained instead, immediately release it. */ static int pagerExclusiveLock(Pager *pPager){ int rc; /* Return code */ - u8 eOrigLock; /* Original lock */ - assert( pPager->eLock>=SHARED_LOCK ); - eOrigLock = pPager->eLock; + assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - /* If the attempt to grab the exclusive lock failed, release the + /* If the attempt to grab the exclusive lock failed, release the ** pending lock that may have been obtained instead. */ - pagerUnlockDb(pPager, eOrigLock); + pagerUnlockDb(pPager, SHARED_LOCK); } return rc; } /* -** Call sqlite3WalOpen() to open the WAL handle. If the pager is in +** Call sqlite3WalOpen() to open the WAL handle. If the pager is in ** exclusive-locking mode when this function is called, take an EXCLUSIVE ** lock on the database file and use heap-memory to store the wal-index ** in. Otherwise, use the normal shared-memory. */ static int pagerOpenWal(Pager *pPager){ @@ -64872,20 +54798,20 @@ int rc = SQLITE_OK; assert( pPager->pWal==0 && pPager->tempFile==0 ); assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); - /* If the pager is already in exclusive-mode, the WAL module will use - ** heap-memory for the wal-index instead of the VFS shared-memory + /* If the pager is already in exclusive-mode, the WAL module will use + ** heap-memory for the wal-index instead of the VFS shared-memory ** implementation. Take the exclusive lock now, before opening the WAL ** file, to make sure this is safe. */ if( pPager->exclusiveMode ){ rc = pagerExclusiveLock(pPager); } - /* Open the connection to the log file. If this operation fails, + /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode, @@ -64903,11 +54829,11 @@ ** this function. ** ** If the pager passed as the first argument is open on a real database ** file (not a temp file or an in-memory database), and the WAL file ** is not already open, make an attempt to open it now. If successful, -** return SQLITE_OK. If an error occurs or the VFS used by the pager does +** return SQLITE_OK. If an error occurs or the VFS used by the pager does ** not support the xShmXXX() methods, return an error code. *pbOpen is ** not modified in either case. ** ** If the pager is open on a temp-file (or in-memory database), or if ** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK @@ -64945,11 +54871,11 @@ /* ** This function is called to close the connection to the log file prior ** to switching from WAL to rollback mode. ** -** Before closing the log file, this function attempts to take an +** Before closing the log file, this function attempts to take an ** EXCLUSIVE lock on the database file. If this cannot be obtained, an ** error (SQLITE_BUSY) is returned and the log connection is not closed. ** If successful, the EXCLUSIVE lock is not released before returning. */ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ @@ -64971,53 +54897,27 @@ } if( rc==SQLITE_OK && logexists ){ rc = pagerOpenWal(pPager); } } - + /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on ** the database file, the log and log-summary files will be deleted. */ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ - rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, + rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } } return rc; } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -/* -** If pager pPager is a wal-mode database not in exclusive locking mode, -** invoke the sqlite3WalWriteLock() function on the associated Wal object -** with the same db and bLock parameters as were passed to this function. -** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. -*/ -SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){ - int rc = SQLITE_OK; - if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){ - rc = sqlite3WalWriteLock(pPager->pWal, bLock); - } - return rc; -} - -/* -** Set the database handle used by the wal layer to determine if -** blocking locks are required. -*/ -SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){ - if( pagerUseWal(pPager) ){ - sqlite3WalDb(pPager->pWal, db); - } -} -#endif - #ifdef SQLITE_ENABLE_SNAPSHOT /* ** If this is a WAL database, obtain a snapshot handle for the snapshot ** currently open. Otherwise, return an error. */ @@ -65029,17 +54929,14 @@ return rc; } /* ** If this is a WAL database, store a pointer to pSnapshot. Next time a -** read transaction is opened, attempt to read from the snapshot it +** read transaction is opened, attempt to read from the snapshot it ** identifies. If this is not a WAL database, return an error. */ -SQLITE_PRIVATE int sqlite3PagerSnapshotOpen( - Pager *pPager, - sqlite3_snapshot *pSnapshot -){ +SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){ int rc = SQLITE_OK; if( pPager->pWal ){ sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); }else{ rc = SQLITE_ERROR; @@ -65046,11 +54943,11 @@ } return rc; } /* -** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this +** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this ** is not a WAL database, return an error. */ SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){ int rc; if( pPager->pWal ){ @@ -65058,42 +54955,10 @@ }else{ rc = SQLITE_ERROR; } return rc; } - -/* -** The caller currently has a read transaction open on the database. -** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise, -** this function takes a SHARED lock on the CHECKPOINTER slot and then -** checks if the snapshot passed as the second argument is still -** available. If so, SQLITE_OK is returned. -** -** If the snapshot is not available, SQLITE_ERROR is returned. Or, if -** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error -** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER -** lock is released before returning. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){ - int rc; - if( pPager->pWal ){ - rc = sqlite3WalSnapshotCheck(pPager->pWal, pSnapshot); - }else{ - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** Release a lock obtained by an earlier successful call to -** sqlite3PagerSnapshotCheck(). -*/ -SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){ - assert( pPager->pWal ); - sqlite3WalSnapshotUnlock(pPager->pWal); -} - #endif /* SQLITE_ENABLE_SNAPSHOT */ #endif /* !SQLITE_OMIT_WAL */ #ifdef SQLITE_ENABLE_ZIPVFS /* @@ -65105,16 +54970,10 @@ */ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ assert( pPager->eState>=PAGER_READER ); return sqlite3WalFramesize(pPager->pWal); } -#endif - -#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL) -SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ - return sqlite3WalSystemErrno(pPager->pWal); -} #endif #endif /* SQLITE_OMIT_DISKIO */ /************** End of pager.c ***********************************************/ @@ -65129,20 +54988,20 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** -** This file contains the implementation of a write-ahead log (WAL) used in +** This file contains the implementation of a write-ahead log (WAL) used in ** "journal_mode=WAL" mode. ** ** WRITE-AHEAD LOG (WAL) FILE FORMAT ** ** A WAL file consists of a header followed by zero or more "frames". ** Each frame records the revised content of a single page from the ** database file. All changes to the database are recorded by writing ** frames into the WAL. Transactions commit when a frame is written that -** contains a commit marker. A single WAL can and usually does record +** contains a commit marker. A single WAL can and usually does record ** multiple transactions. Periodically, the content of the WAL is ** transferred back into the database file in an operation called a ** "checkpoint". ** ** A single WAL file can be used multiple times. In other words, the @@ -65163,16 +55022,16 @@ ** 20: Salt-2, a different random integer changing with each ckpt ** 24: Checksum-1 (first part of checksum for first 24 bytes of header). ** 28: Checksum-2 (second part of checksum for first 24 bytes of header). ** ** Immediately following the wal-header are zero or more frames. Each -** frame consists of a 24-byte frame-header followed by bytes -** of page data. The frame-header is six big-endian 32-bit unsigned +** frame consists of a 24-byte frame-header followed by a bytes +** of page data. The frame-header is six big-endian 32-bit unsigned ** integer values, as follows: ** ** 0: Page number. -** 4: For commit records, the size of the database image in pages +** 4: For commit records, the size of the database image in pages ** after the commit. For all other records, zero. ** 8: Salt-1 (copied from the header) ** 12: Salt-2 (copied from the header) ** 16: Checksum-1. ** 20: Checksum-2. @@ -65194,19 +55053,19 @@ ** The checksum values are always stored in the frame header in a ** big-endian format regardless of which byte order is used to compute ** the checksum. The checksum is computed by interpreting the input as ** an even number of unsigned 32-bit integers: x[0] through x[N]. The ** algorithm used for the checksum is as follows: -** +** ** for i from 0 to n-1 step 2: ** s0 += x[i] + s1; ** s1 += x[i+1] + s0; ** endfor ** ** Note that s0 and s1 are both weighted checksums using fibonacci weights ** in reverse order (the largest fibonacci weight occurs on the first element -** of the sequence being summed.) The s1 value spans all 32-bit +** of the sequence being summed.) The s1 value spans all 32-bit ** terms of the sequence whereas s0 omits the final term. ** ** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the ** WAL is transferred into the database, then the database is VFS.xSync-ed. ** The VFS.xSync operations serve as write barriers - all writes launched @@ -65235,30 +55094,26 @@ ** and ignores the newly appended content, it will see a consistent snapshot ** of the database from a single point in time. This technique allows ** multiple concurrent readers to view different versions of the database ** content simultaneously. ** -** The reader algorithm in the previous paragraphs works correctly, but +** The reader algorithm in the previous paragraphs works correctly, but ** because frames for page P can appear anywhere within the WAL, the ** reader has to scan the entire WAL looking for page P frames. If the ** WAL is large (multiple megabytes is typical) that scan can be slow, ** and read performance suffers. To overcome this problem, a separate ** data structure called the wal-index is maintained to expedite the ** search for frames of a particular page. -** +** ** WAL-INDEX FORMAT ** ** Conceptually, the wal-index is shared memory, though VFS implementations ** might choose to implement the wal-index using a mmapped file. Because -** the wal-index is shared memory, SQLite does not support journal_mode=WAL +** the wal-index is shared memory, SQLite does not support journal_mode=WAL ** on a network filesystem. All users of the database must be able to ** share memory. ** -** 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 ** connection to it closes. Because the wal-index is transient, it can ** use an architecture-specific format; it does not have to be cross-platform. @@ -65265,35 +55120,32 @@ ** Hence, unlike the database and WAL file formats which store all values ** as big endian, the wal-index can store multi-byte values in the native ** byte order of the host computer. ** ** The purpose of the wal-index is to answer this question quickly: Given -** a page number P and a maximum frame index M, return the index of the +** a page number P and a maximum frame index M, return the index of the ** last frame in the wal before frame M for page P in the WAL, or return ** NULL if there are no frames for page P in the WAL prior to M. ** ** The wal-index consists of a header region, followed by an one or -** more index blocks. +** more index blocks. ** ** The wal-index header contains the total number of frames within the WAL ** in the mxFrame field. ** -** Each index block except for the first contains information on +** Each index block except for the first contains information on ** HASHTABLE_NPAGE frames. The first index block contains information on -** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and +** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and ** HASHTABLE_NPAGE are selected so that together the wal-index header and ** first index block are the same size as all other index blocks in the -** wal-index. The values are: -** -** HASHTABLE_NPAGE 4096 -** HASHTABLE_NPAGE_ONE 4062 +** wal-index. ** ** Each index block contains two sections, a page-mapping that contains the -** database page number associated with each wal frame, and a hash-table +** database page number associated with each wal frame, and a hash-table ** that allows readers to query an index block for a specific page number. ** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE -** for the first index block) 32-bit page numbers. The first entry in the +** for the first index block) 32-bit page numbers. The first entry in the ** first index-block contains the database page number corresponding to the ** first frame in the WAL file. The first entry in the second index block ** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in ** the log, and so on. ** @@ -65310,12 +55162,12 @@ ** beginning. The first entry that equals P corresponds to the frame ** holding the content for that page. ** ** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers. ** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the -** hash table for each page number in the mapping section, so the hash -** table is never more than half full. The expected number of collisions +** hash table for each page number in the mapping section, so the hash +** table is never more than half full. The expected number of collisions ** prior to finding a match is 1. Each entry of the hash table is an ** 1-based index of an entry in the mapping section of the same ** index block. Let K be the 1-based index of the largest entry in ** the mapping section. (For index blocks other than the last, K will ** always be exactly HASHTABLE_NPAGE (4096) and for the last index block @@ -65330,16 +55182,16 @@ ** Then start scanning entries of the hash table, starting with iKey ** (wrapping around to the beginning when the end of the hash table is ** reached) until an unused hash slot is found. Let the first unused slot ** be at index iUnused. (iUnused might be less than iKey if there was ** wrap-around.) Because the hash table is never more than half full, -** the search is guaranteed to eventually hit an unused entry. Let +** the search is guaranteed to eventually hit an unused entry. Let ** iMax be the value between iKey and iUnused, closest to iUnused, ** where aHash[iMax]==P. If there is no iMax entry (if there exists ** no hash slot such that aHash[i]==p) then page P is not in the ** current index block. Otherwise the iMax-th mapping entry of the -** current index block corresponds to the last entry that references +** current index block corresponds to the last entry that references ** page P. ** ** A hash search begins with the last index block and moves toward the ** first index block, looking for entries corresponding to page P. On ** average, only two or three slots in each index block need to be @@ -65360,11 +55212,11 @@ ** K>K0 but to the first reader, those entries will appear to be unused ** slots in the hash table and so the first reader will get an answer as ** if no values greater than K0 had ever been inserted into the hash table ** in the first place - which is what reader one wants. Meanwhile, the ** second reader using K1 will see additional values that were inserted -** later, which is exactly what reader two wants. +** later, which is exactly what reader two wants. ** ** When a rollback occurs, the value of K is decreased. Hash table entries ** that correspond to frames greater than the new K value are removed ** from the hash table at this point. */ @@ -65388,31 +55240,22 @@ ** ** If a client begins recovering a WAL file and finds that (a) the checksum ** values in the wal-header are correct and (b) the version field is not ** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN. ** -** Similarly, if a client successfully reads a wal-index header (i.e. the +** Similarly, if a client successfully reads a wal-index header (i.e. the ** checksum test is successful) and finds that the version field is not ** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite ** returns SQLITE_CANTOPEN. */ #define WAL_MAX_VERSION 3007000 #define WALINDEX_MAX_VERSION 3007000 /* -** Index numbers for various locking bytes. WAL_NREADER is the number +** Indices of 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 implementation 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 #define WAL_CKPT_LOCK 1 #define WAL_RECOVER_LOCK 2 @@ -65435,11 +55278,11 @@ ** the locking bytes (WalCkptInfo.aLock) start at offset 120 and ** the total header size is 136 bytes. ** ** The szPage value can be any power of 2 between 512 and 32768, inclusive. ** Or it can be 1 to represent a 65536-byte page. The latter case was -** added in 3.7.1 when support for 64K pages was added. +** added in 3.7.1 when support for 64K pages was added. */ struct WalIndexHdr { u32 iVersion; /* Wal-index version */ u32 unused; /* Unused (padding) field */ u32 iChange; /* Counter incremented each transaction */ @@ -65477,13 +55320,13 @@ ** never be read or written. ** ** There is one entry in aReadMark[] for each reader lock. If a reader ** holds read-lock K, then the value in aReadMark[K] is no greater than ** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) -** for any aReadMark[] means that entry is unused. aReadMark[0] is +** for any aReadMark[] means that entry is unused. aReadMark[0] is ** a special case; its value is never used and it exists as a place-holder -** to avoid having to offset aReadMark[] indexes by one. Readers holding +** to avoid having to offset aReadMark[] indexs by one. Readers holding ** WAL_READ_LOCK(0) always ignore the entire WAL and read all content ** directly from the database. ** ** The value of aReadMark[K] may only be changed by a thread that ** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of @@ -65497,11 +55340,11 @@ ** largest value and will increase an unused aReadMark[] to mxFrame if there ** is not already an aReadMark[] equal to mxFrame. The exception to the ** previous sentence is when nBackfill equals mxFrame (meaning that everything ** in the WAL has been backfilled into the database) then new readers ** will choose aReadMark[0] which has value 0 and hence such reader will -** get all their all content directly from the database file and ignore +** get all their all content directly from the database file and ignore ** the WAL. ** ** Writers normally append new frames to the end of the WAL. However, ** if nBackfill equals mxFrame (meaning that all WAL content has been ** written back into the database) and if no readers are using the WAL @@ -65519,74 +55362,10 @@ u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */ u32 notUsed0; /* Available for future enhancements */ }; #define READMARK_NOT_USED 0xffffffff -/* -** This is a schematic view of the complete 136-byte header of the -** wal-index file (also known as the -shm file): -** -** +-----------------------------+ -** 0: | iVersion | \ -** +-----------------------------+ | -** 4: | (unused padding) | | -** +-----------------------------+ | -** 8: | iChange | | -** +-------+-------+-------------+ | -** 12: | bInit | bBig | szPage | | -** +-------+-------+-------------+ | -** 16: | mxFrame | | First copy of the -** +-----------------------------+ | WalIndexHdr object -** 20: | nPage | | -** +-----------------------------+ | -** 24: | aFrameCksum | | -** | | | -** +-----------------------------+ | -** 32: | aSalt | | -** | | | -** +-----------------------------+ | -** 40: | aCksum | | -** | | / -** +-----------------------------+ -** 48: | iVersion | \ -** +-----------------------------+ | -** 52: | (unused padding) | | -** +-----------------------------+ | -** 56: | iChange | | -** +-------+-------+-------------+ | -** 60: | bInit | bBig | szPage | | -** +-------+-------+-------------+ | Second copy of the -** 64: | mxFrame | | WalIndexHdr -** +-----------------------------+ | -** 68: | nPage | | -** +-----------------------------+ | -** 72: | aFrameCksum | | -** | | | -** +-----------------------------+ | -** 80: | aSalt | | -** | | | -** +-----------------------------+ | -** 88: | aCksum | | -** | | / -** +-----------------------------+ -** 96: | nBackfill | -** +-----------------------------+ -** 100: | 5 read marks | -** | | -** | | -** | | -** | | -** +-------+-------+------+------+ -** 120: | Write | Ckpt | Rcvr | Rd0 | \ -** +-------+-------+------+------+ ) 8 lock bytes -** | Read1 | Read2 | Rd3 | Rd4 | / -** +-------+-------+------+------+ -** 128: | nBackfillAttempted | -** +-----------------------------+ -** 132: | (unused padding) | -** +-----------------------------+ -*/ /* A block of WALINDEX_LOCK_RESERVED bytes beginning at ** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems ** only support mandatory file-locks, we do not read or write data ** from the region of the file on which locks are applied. @@ -65596,25 +55375,26 @@ /* Size of header before each frame in wal */ #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 ** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit ** big-endian format in the first 4 bytes of a WAL file. ** ** If the LSB is set, then the checksums for each frame within the WAL -** file are calculated by treating all data as an array of 32-bit -** big-endian words. Otherwise, they are calculated by interpreting +** file are calculated by treating all data as an array of 32-bit +** big-endian words. Otherwise, they are calculated by interpreting ** all data as 32-bit little-endian words. */ #define WAL_MAGIC 0x377f0682 /* -** Return the offset of frame iFrame in the write-ahead log file, +** Return the offset of frame iFrame in the write-ahead log file, ** assuming a database page size of szPage bytes. The offset returned ** is to the start of the write-ahead log frame-header. */ #define walFrameOffset(iFrame, szPage) ( \ WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \ @@ -65641,41 +55421,28 @@ u8 ckptLock; /* True if holding a checkpoint lock */ u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */ 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 */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -#ifdef SQLITE_USE_SEH - u32 lockMask; /* Mask of locks held */ - void *pFree; /* Pointer to sqlite3_free() if exception thrown */ - u32 *pWiValue; /* Value to write into apWiData[iWiPg] */ - int iWiPg; /* Write pWiValue into apWiData[iWiPg] */ - int iSysErrno; /* System error code following exception */ -#endif #ifdef SQLITE_DEBUG - int nSehTry; /* Number of nested SEH_TRY{} blocks */ u8 lockError; /* True if a locking error has occurred */ #endif #ifdef SQLITE_ENABLE_SNAPSHOT WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ - int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */ -#endif -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3 *db; #endif }; /* ** Candidate values for Wal.exclusiveMode. */ #define WAL_NORMAL_MODE 0 -#define WAL_EXCLUSIVE_MODE 1 +#define WAL_EXCLUSIVE_MODE 1 #define WAL_HEAPMEMORY_MODE 2 /* ** Possible values for WAL.readOnly */ @@ -65690,11 +55457,11 @@ typedef u16 ht_slot; /* ** This structure is used to implement an iterator that loops through ** all frames in the WAL in database page order. Where two or more frames -** correspond to the same database page, the iterator visits only the +** correspond to the same database page, the iterator visits only the ** frame most recently written to the WAL (in other words, the frame with ** the largest index). ** ** The internals of this structure are only accessed by: ** @@ -65703,11 +55470,11 @@ ** walIteratorFree() - Free an iterator. ** ** This functionality is used by the checkpoint code (see walCheckpoint()). */ struct WalIterator { - u32 iPrior; /* Last result returned from the iterator */ + int iPrior; /* Last result returned from the iterator */ int nSegment; /* Number of entries in aSegment[] */ struct WalSegment { int iNext; /* Next slot in aIndex[] not yet returned */ ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */ u32 *aPgno; /* Array of page numbers. */ @@ -65726,11 +55493,11 @@ */ #define HASHTABLE_NPAGE 4096 /* Must be power of 2 */ #define HASHTABLE_HASH_1 383 /* Should be prime */ #define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */ -/* +/* ** The block of page numbers associated with the first hash-table in a ** wal-index is smaller than usual. This is so that there is a complete ** hash-table on each aligned 32KB page of the wal-index. */ #define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32))) @@ -65737,148 +55504,28 @@ /* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ #define WALINDEX_PGSZ ( \ sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ ) - -/* -** Structured Exception Handling (SEH) is a Windows-specific technique -** for catching exceptions raised while accessing memory-mapped files. -** -** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and -** deal with system-level errors that arise during WAL -shm file processing. -** Without this compile-time option, any system-level faults that appear -** while accessing the memory-mapped -shm file will cause a process-wide -** signal to be deliver, which will more than likely cause the entire -** process to exit. -*/ -#ifdef SQLITE_USE_SEH -#include - -/* Beginning of a block of code in which an exception might occur */ -# define SEH_TRY __try { \ - assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ - VVA_ONLY(pWal->nSehTry++); - -/* The end of a block of code in which an exception might occur */ -# define SEH_EXCEPT(X) \ - VVA_ONLY(pWal->nSehTry--); \ - assert( pWal->nSehTry==0 ); \ - } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } - -/* Simulate a memory-mapping fault in the -shm file for testing purposes */ -# define SEH_INJECT_FAULT sehInjectFault(pWal) - -/* -** The second argument is the return value of GetExceptionCode() for the -** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code -** indicates that the exception may have been caused by accessing the *-shm -** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. -*/ -static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ - VVA_ONLY(pWal->nSehTry--); - if( eCode==EXCEPTION_IN_PAGE_ERROR ){ - if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ - /* From MSDN: For this type of exception, the first element of the - ** ExceptionInformation[] array is a read-write flag - 0 if the exception - ** was thrown while reading, 1 if while writing. The second element is - ** the virtual address being accessed. The "third array element specifies - ** the underlying NTSTATUS code that resulted in the exception". */ - pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; - } - return EXCEPTION_EXECUTE_HANDLER; - } - return EXCEPTION_CONTINUE_SEARCH; -} - -/* -** If one is configured, invoke the xTestCallback callback with 650 as -** the argument. If it returns true, throw the same exception that is -** thrown by the system if the *-shm file mapping is accessed after it -** has been invalidated. -*/ -static void sehInjectFault(Wal *pWal){ - int res; - assert( pWal->nSehTry>0 ); - - res = sqlite3FaultSim(650); - if( res!=0 ){ - ULONG_PTR aArg[3]; - aArg[0] = 0; - aArg[1] = 0; - aArg[2] = (ULONG_PTR)res; - RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); - } -} - -/* -** There are two ways to use this macro. To set a pointer to be freed -** if an exception is thrown: -** -** SEH_FREE_ON_ERROR(0, pPtr); -** -** and to cancel the same: -** -** SEH_FREE_ON_ERROR(pPtr, 0); -** -** In the first case, there must not already be a pointer registered to -** be freed. In the second case, pPtr must be the registered pointer. -*/ -#define SEH_FREE_ON_ERROR(X,Y) \ - assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y - -/* -** There are two ways to use this macro. To arrange for pWal->apWiData[iPg] -** to be set to pValue if an exception is thrown: -** -** SEH_SET_ON_ERROR(iPg, pValue); -** -** and to cancel the same: -** -** SEH_SET_ON_ERROR(0, 0); -*/ -#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y - -#else -# define SEH_TRY VVA_ONLY(pWal->nSehTry++); -# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); -# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); -# define SEH_FREE_ON_ERROR(X,Y) -# define SEH_SET_ON_ERROR(X,Y) -#endif /* ifdef SQLITE_USE_SEH */ - /* ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index ** 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. -** -** Three possible result scenarios: -** -** (1) rc==SQLITE_OK and *ppPage==Requested-Wal-Index-Page -** (2) rc>=SQLITE_ERROR and *ppPage==NULL -** (3) rc==SQLITE_OK and *ppPage==NULL // only if iPage==0 -** -** Scenario (3) can only occur when pWal->writeLock is false and iPage==0 +** 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. */ -static SQLITE_NOINLINE int walIndexPageRealloc( - Wal *pWal, /* The WAL context */ - int iPage, /* The page we seek */ - volatile u32 **ppPage /* Write the page pointer here */ -){ +static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ int rc = SQLITE_OK; /* Enlarge the pWal->apWiData[] array if required */ if( pWal->nWiData<=iPage ){ - sqlite3_int64 nByte = sizeof(u32*)*(iPage+1); + int nByte = sizeof(u32*)*(iPage+1); volatile u32 **apNew; - apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte); + apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; return SQLITE_NOMEM_BKPT; } memset((void*)&apNew[pWal->nWiData], 0, @@ -65886,63 +55533,43 @@ pWal->apWiData = apNew; pWal->nWiData = iPage+1; } /* Request a pointer to the required page from the VFS */ - assert( pWal->apWiData[iPage]==0 ); - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ - pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); - if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, - pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] - ); - assert( pWal->apWiData[iPage]!=0 - || rc!=SQLITE_OK - || (pWal->writeLock==0 && iPage==0) ); - testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK ); - if( rc==SQLITE_OK ){ - if( iPage>0 && sqlite3FaultSim(600) ) rc = SQLITE_NOMEM; - }else if( (rc&0xff)==SQLITE_READONLY ){ - pWal->readOnly |= WAL_SHM_RDONLY; + if( pWal->apWiData[iPage]==0 ){ + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ + pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); + if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; + }else{ + rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, + pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] + ); if( rc==SQLITE_READONLY ){ + pWal->readOnly |= WAL_SHM_RDONLY; rc = SQLITE_OK; } } } *ppPage = pWal->apWiData[iPage]; assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); return rc; } -static int walIndexPage( - Wal *pWal, /* The WAL context */ - int iPage, /* The page we seek */ - volatile u32 **ppPage /* Write the page pointer here */ -){ - SEH_INJECT_FAULT; - if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ - return walIndexPageRealloc(pWal, iPage, ppPage); - } - return SQLITE_OK; -} /* ** Return a pointer to the WalCkptInfo structure in the wal-index. */ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); - SEH_INJECT_FAULT; return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); } /* ** Return a pointer to the WalIndexHdr structure in the wal-index. */ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); - SEH_INJECT_FAULT; return (volatile WalIndexHdr*)pWal->apWiData[0]; } /* ** The argument to this macro must be of type u32. On a little-endian @@ -65955,11 +55582,11 @@ (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \ + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \ ) /* -** Generate or extend an 8 byte checksum based on the data in +** Generate or extend an 8 byte checksum based on the data in ** array aByte[] and the initial values of aIn[0] and aIn[1] (or ** initial values of 0 and 0 if aIn==NULL). ** ** The checksum is written back into aOut[] before returning. ** @@ -65983,99 +55610,59 @@ s1 = s2 = 0; } assert( nByte>=8 ); assert( (nByte&0x00000007)==0 ); - assert( nByte<=65536 ); - assert( nByte%4==0 ); - if( !nativeCksum ){ + if( nativeCksum ){ + do { + s1 += *aData++ + s2; + s2 += *aData++ + s1; + }while( aDataexclusiveMode!=WAL_HEAPMEMORY_MODE ){ sqlite3OsShmBarrier(pWal->pDbFd); } } -/* -** Add the SQLITE_NO_TSAN as part of the return-type of a function -** definition as a hint that the function contains constructs that -** might give false-positive TSAN warnings. -** -** See tag-20200519-1. -*/ -#if defined(__clang__) && !defined(SQLITE_NO_TSAN) -# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread)) -#else -# define SQLITE_NO_TSAN -#endif - /* ** Write the header information in pWal->hdr into the wal-index. ** ** The checksum on pWal->hdr is updated before it is written. */ -static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){ +static void walIndexWriteHdr(Wal *pWal){ volatile WalIndexHdr *aHdr = walIndexHdr(pWal); const int nCksum = offsetof(WalIndexHdr, aCksum); assert( pWal->writeLock ); pWal->hdr.isInit = 1; pWal->hdr.iVersion = WALINDEX_MAX_VERSION; walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); - /* Possible TSAN false-positive. See tag-20200519-1 */ memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); walShmBarrier(pWal); memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); } /* ** This function encodes a single frame header and writes it to a buffer -** supplied by the caller. A frame-header is made up of a series of +** supplied by the caller. A frame-header is made up of a series of ** 4-byte big-endian integers, as follows: ** ** 0: Page number. -** 4: For commit records, the size of the database image in pages +** 4: For commit records, the size of the database image in pages ** after the commit. For all other records, zero. ** 8: Salt-1 (copied from the wal-header) ** 12: Salt-2 (copied from the wal-header) ** 16: Checksum-1. ** 20: Checksum-2. @@ -66122,33 +55709,33 @@ u32 *aCksum = pWal->hdr.aFrameCksum; u32 pgno; /* Page number of the frame */ assert( WAL_FRAME_HDRSIZE==24 ); /* A frame is only valid if the salt values in the frame-header - ** match the salt values in the wal-header. + ** match the salt values in the wal-header. */ if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){ return 0; } - /* A frame is only valid if the page number is greater than zero. + /* A frame is only valid if the page number is creater than zero. */ pgno = sqlite3Get4byte(&aFrame[0]); if( pgno==0 ){ return 0; } /* A frame is only valid if a checksum of the WAL header, - ** all prior frames, the first 16 bytes of this frame-header, - ** and the frame-data matches the checksum in the last 8 + ** all prior frams, the first 16 bytes of this frame-header, + ** and the frame-data matches the checksum in the last 8 ** bytes of this frame-header. */ nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); - if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) - || aCksum[1]!=sqlite3Get4byte(&aFrame[20]) + if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) + || aCksum[1]!=sqlite3Get4byte(&aFrame[20]) ){ /* Checksum failed. */ return 0; } @@ -66179,11 +55766,11 @@ lockIdx-WAL_READ_LOCK(0)); return zName; } } #endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ - + /* ** Set or release locks on the WAL. Locks are either shared or exclusive. ** A lock cannot be moved directly between shared and exclusive - it must go ** through the unlocked state first. @@ -66195,47 +55782,33 @@ if( pWal->exclusiveMode ) return SQLITE_OK; rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) -#ifdef SQLITE_USE_SEH - if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); -#endif + VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); -#ifdef SQLITE_USE_SEH - pWal->lockMask &= ~(1 << lockIdx); -#endif WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); } static int walLockExclusive(Wal *pWal, int lockIdx, int n){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, walLockName(lockIdx), n, rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) -#ifdef SQLITE_USE_SEH - if( rc==SQLITE_OK ){ - pWal->lockMask |= (((1<lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) return rc; } static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); -#ifdef SQLITE_USE_SEH - pWal->lockMask &= ~(((1<aHash to point to the start of the hash table -** in the wal-index file. Set pLoc->iZero to one less than the frame +** Set output variable *paHash to point to the start of the hash table +** in the wal-index file. Set *piZero to one less than the frame ** number of the first frame indexed by this hash table. If a -** slot in the hash table is set to N, it refers to frame number -** (pLoc->iZero+N) in the log. +** slot in the hash table is set to N, it refers to frame number +** (*piZero+N) in the log. ** -** Finally, set pLoc->aPgno so that pLoc->aPgno[0] is the page number of the -** first frame indexed by the hash table, frame (pLoc->iZero). +** Finally, set *paPgno so that *paPgno[1] is the page number of the +** first frame indexed by the hash table, frame (*piZero+1). */ static int walHashGet( Wal *pWal, /* WAL handle */ int iHash, /* Find the iHash'th table */ - WalHashLoc *pLoc /* OUT: Hash table location */ + volatile ht_slot **paHash, /* OUT: Pointer to hash index */ + volatile u32 **paPgno, /* OUT: Pointer to page number array */ + u32 *piZero /* OUT: Frame associated with *paPgno[0] */ ){ int rc; /* Return code */ + volatile u32 *aPgno; - rc = walIndexPage(pWal, iHash, &pLoc->aPgno); + rc = walIndexPage(pWal, iHash, &aPgno); assert( rc==SQLITE_OK || iHash>0 ); - if( pLoc->aPgno ){ - pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE]; + if( rc==SQLITE_OK ){ + u32 iZero; + volatile ht_slot *aHash; + + aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE]; if( iHash==0 ){ - pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; - pLoc->iZero = 0; + aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; + iZero = 0; }else{ - pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; + iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; } - }else if( NEVER(rc==SQLITE_OK) ){ - rc = SQLITE_ERROR; + + *paPgno = &aPgno[-1]; + *paHash = aHash; + *piZero = iZero; } return rc; } /* ** Return the number of the wal-index page that contains the hash-table ** and page-number array that contain entries corresponding to WAL frame -** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages +** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages ** are numbered starting from 0. */ static int walFramePage(u32 iFrame){ int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE; assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE) @@ -66314,20 +55883,18 @@ && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE) && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)) && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE) && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE)) ); - assert( iHash>=0 ); return iHash; } /* ** Return the page number associated with frame iFrame in this WAL. */ static u32 walFramePgno(Wal *pWal, u32 iFrame){ int iHash = walFramePage(iFrame); - SEH_INJECT_FAULT; if( iHash==0 ){ return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; } return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; } @@ -66343,11 +55910,13 @@ ** updated. Any later hash tables will be automatically cleared when ** pWal->hdr.mxFrame advances to the point where those hash tables are ** actually needed. */ static void walCleanupHash(Wal *pWal){ - WalHashLoc sLoc; /* Hash table location */ + volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */ + volatile u32 *aPgno = 0; /* Page number array for hash table */ + u32 iZero = 0; /* frame == (aHash[x]+iZero) */ int iLimit = 0; /* Zero values greater than this */ int nByte; /* Number of bytes to zero in aPgno[] */ int i; /* Used to iterate through aHash[] */ assert( pWal->writeLock ); @@ -66355,49 +55924,47 @@ testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE ); testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 ); if( pWal->hdr.mxFrame==0 ) return; - /* Obtain pointers to the hash-table and page-number array containing + /* Obtain pointers to the hash-table and page-number array containing ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed - ** that the page said hash-table and array reside on is already mapped.(1) + ** that the page said hash-table and array reside on is already mapped. */ assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); - i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc); - if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */ + walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero); /* Zero all hash-table entries that correspond to frame numbers greater ** than pWal->hdr.mxFrame. */ - iLimit = pWal->hdr.mxFrame - sLoc.iZero; + iLimit = pWal->hdr.mxFrame - iZero; assert( iLimit>0 ); for(i=0; iiLimit ){ - sLoc.aHash[i] = 0; + if( aHash[i]>iLimit ){ + aHash[i] = 0; } } - + /* Zero the entries in the aPgno array that correspond to frames with - ** frame numbers greater than pWal->hdr.mxFrame. + ** frame numbers greater than pWal->hdr.mxFrame. */ - nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit]); - assert( nByte>=0 ); - memset((void *)&sLoc.aPgno[iLimit], 0, nByte); + nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]); + memset((void *)&aPgno[iLimit+1], 0, nByte); #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the every entry in the mapping region is still reachable ** via the hash table even after the cleanup. */ if( iLimit ){ int j; /* Loop counter */ int iKey; /* Hash key */ - for(j=0; j=0 ); - memset((void*)sLoc.aPgno, 0, nByte); + int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); + memset((void*)&aPgno[1], 0, nByte); } /* If the entry in aPgno[] is already set, then the previous writer ** must have exited unexpectedly in the middle of a transaction (after - ** writing one or more dirty pages to the WAL to free up memory). - ** Remove the remnants of that writers uncommitted transaction from + ** writing one or more dirty pages to the WAL to free up memory). + ** Remove the remnants of that writers uncommitted transaction from ** the hash-table before writing any new entries. */ - if( sLoc.aPgno[idx-1] ){ + if( aPgno[idx] ){ walCleanupHash(pWal); - assert( !sLoc.aPgno[idx-1] ); + assert( !aPgno[idx] ); } /* Write the aPgno[] array entry and the hash-table slot. */ nCollide = idx; - for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ + for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; } - sLoc.aPgno[idx-1] = iPage; - AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx); + aPgno[idx] = iPage; + aHash[iKey] = (ht_slot)idx; #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the number of entries in the hash table exactly equals ** the number of entries in the mapping region. */ { int i; /* Loop counter */ int nEntry = 0; /* Number of entries in the hash table */ - for(i=0; ickptLock==1 || pWal->ckptLock==0 ); assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 ); assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE ); assert( pWal->writeLock ); iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; - rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); + nLock = SQLITE_SHM_NLOCK - iLock; + rc = walLockExclusive(pWal, iLock, nLock); if( rc ){ return rc; } - WALTRACE(("WAL%p: recovery begin...\n", pWal)); memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); rc = sqlite3OsFileSize(pWal->pWalFd, &nSize); @@ -66526,48 +56094,47 @@ goto recovery_error; } if( nSize>WAL_HDRSIZE ){ u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ - u32 *aPrivate = 0; /* Heap copy of *-shm hash being populated */ u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ int szFrame; /* Number of bytes in buffer aFrame[] */ u8 *aData; /* Pointer to data part of aFrame buffer */ + int iFrame; /* Index of last frame read */ + i64 iOffset; /* Next offset to read from log file */ int szPage; /* Page size according to the log */ u32 magic; /* Magic value read from WAL header */ u32 version; /* Magic value read from WAL header */ int isValid; /* True if this frame is valid */ - u32 iPg; /* Current 32KB wal-index page */ - u32 iLastFrame; /* Last frame in wal, based on nSize alone */ /* Read in the WAL header. */ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); if( rc!=SQLITE_OK ){ goto recovery_error; } /* If the database page size is not a power of two, or is greater than - ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid + ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid ** data. Similarly, if the 'magic' value is invalid, ignore the whole ** WAL file. */ magic = sqlite3Get4byte(&aBuf[0]); szPage = sqlite3Get4byte(&aBuf[8]); - if( (magic&0xFFFFFFFE)!=WAL_MAGIC - || szPage&(szPage-1) - || szPage>SQLITE_MAX_PAGE_SIZE - || szPage<512 + if( (magic&0xFFFFFFFE)!=WAL_MAGIC + || szPage&(szPage-1) + || szPage>SQLITE_MAX_PAGE_SIZE + || szPage<512 ){ goto finished; } pWal->hdr.bigEndCksum = (u8)(magic&0x00000001); pWal->szPage = szPage; pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); /* Verify that the WAL header checksum is correct */ - walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, + walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum ); if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24]) || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28]) ){ @@ -66582,94 +56149,44 @@ goto finished; } /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); - SEH_FREE_ON_ERROR(0, aFrame); + aFrame = (u8 *)sqlite3_malloc64(szFrame); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; } aData = &aFrame[WAL_FRAME_HDRSIZE]; - aPrivate = (u32*)&aData[szPage]; /* Read all frames from the log file. */ - iLastFrame = (nSize - WAL_HDRSIZE) / szFrame; - for(iPg=0; iPg<=(u32)walFramePage(iLastFrame); iPg++){ - u32 *aShare; - u32 iFrame; /* Index of last frame read */ - u32 iLast = MIN(iLastFrame, HASHTABLE_NPAGE_ONE+iPg*HASHTABLE_NPAGE); - u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE); - u32 nHdr, nHdr32; - rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare); - assert( aShare!=0 || rc!=SQLITE_OK ); - if( aShare==0 ) break; - SEH_SET_ON_ERROR(iPg, aShare); - pWal->apWiData[iPg] = aPrivate; - - for(iFrame=iFirst; iFrame<=iLast; iFrame++){ - i64 iOffset = walFrameOffset(iFrame, szPage); - u32 pgno; /* Database page number for frame */ - u32 nTruncate; /* dbsize field from frame header */ - - /* Read and decode the next log frame. */ - rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); - if( rc!=SQLITE_OK ) break; - isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame); - if( !isValid ) break; - rc = walIndexAppend(pWal, iFrame, pgno); - if( NEVER(rc!=SQLITE_OK) ) break; - - /* If nTruncate is non-zero, this is a commit record. */ - if( nTruncate ){ - pWal->hdr.mxFrame = iFrame; - pWal->hdr.nPage = nTruncate; - pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; - aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; - } - } - pWal->apWiData[iPg] = aShare; - SEH_SET_ON_ERROR(0,0); - nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0); - nHdr32 = nHdr / sizeof(u32); -#ifndef SQLITE_SAFER_WALINDEX_RECOVERY - /* Memcpy() should work fine here, on all reasonable implementations. - ** Technically, memcpy() might change the destination to some - ** intermediate value before setting to the final value, and that might - ** cause a concurrent reader to malfunction. Memcpy() is allowed to - ** do that, according to the spec, but no memcpy() implementation that - ** we know of actually does that, which is why we say that memcpy() - ** is safe for this. Memcpy() is certainly a lot faster. - */ - memcpy(&aShare[nHdr32], &aPrivate[nHdr32], WALINDEX_PGSZ-nHdr); -#else - /* In the event that some platform is found for which memcpy() - ** changes the destination to some intermediate value before - ** setting the final value, this alternative copy routine is - ** provided. - */ - { - int i; - for(i=nHdr32; ipWalFd, aFrame, szFrame, iOffset); + if( rc!=SQLITE_OK ) break; + isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame); + if( !isValid ) break; + rc = walIndexAppend(pWal, iFrame, pgno); + if( rc!=SQLITE_OK ) break; + + /* If nTruncate is non-zero, this is a commit record. */ + if( nTruncate ){ + pWal->hdr.mxFrame = iFrame; + pWal->hdr.nPage = nTruncate; + pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); + testcase( szPage<=32768 ); + testcase( szPage>=65536 ); + aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; + aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; + } + } + sqlite3_free(aFrame); } finished: if( rc==SQLITE_OK ){ @@ -66677,32 +56194,20 @@ int i; pWal->hdr.aFrameCksum[0] = aFrameCksum[0]; pWal->hdr.aFrameCksum[1] = aFrameCksum[1]; walIndexWriteHdr(pWal); - /* Reset the checkpoint-header. This is safe because this thread is - ** currently holding locks that exclude all other writers and - ** checkpointers. Then set the values of read-mark slots 1 through N. + /* Reset the checkpoint-header. This is safe because this thread is + ** currently holding locks that exclude all other readers, writers and + ** checkpointers. */ pInfo = walCkptInfo(pWal); pInfo->nBackfill = 0; pInfo->nBackfillAttempted = pWal->hdr.mxFrame; pInfo->aReadMark[0] = 0; - for(i=1; ihdr.mxFrame ){ - pInfo->aReadMark[i] = pWal->hdr.mxFrame; - }else{ - pInfo->aReadMark[i] = READMARK_NOT_USED; - } - SEH_INJECT_FAULT; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - }else if( rc!=SQLITE_BUSY ){ - goto recovery_error; - } - } + for(i=1; iaReadMark[i] = READMARK_NOT_USED; + if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame; /* If more than one frame was recovered from the log file, report an ** event via sqlite3_log(). This is to help with identifying performance ** problems caused by applications routinely shutting down without ** checkpointing the log file. @@ -66715,42 +56220,41 @@ } } recovery_error: WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); - walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); + walUnlockExclusive(pWal, iLock, nLock); return rc; } /* ** Close an open wal-index. */ static void walIndexClose(Wal *pWal, int isDelete){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){ + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ int i; for(i=0; inWiData; i++){ sqlite3_free((void *)pWal->apWiData[i]); pWal->apWiData[i] = 0; } - } - if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){ + }else{ sqlite3OsShmUnmap(pWal->pDbFd, isDelete); } } -/* -** Open a connection to the WAL file zWalName. The database file must +/* +** Open a connection to the WAL file zWalName. The database file must ** already be opened on connection pDbFd. The buffer that zWalName points ** to must remain valid for the lifetime of the returned Wal* handle. ** ** A SHARED lock should be held on the database file when this function ** is called. The purpose of this SHARED lock is to prevent any other ** client from unlinking the WAL or wal-index file. If another process ** were to do this just after this client opened one of these files, the ** system would be badly broken. ** -** If the log file is successfully opened, SQLITE_OK is returned and +** If the log file is successfully opened, SQLITE_OK is returned and ** *ppWal is set to point to a new WAL handle. If an error occurs, ** an SQLite error code is returned and *ppWal is left unmodified. */ SQLITE_PRIVATE int sqlite3WalOpen( sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ @@ -66765,47 +56269,18 @@ int flags; /* Flags passed to OsOpen() */ assert( zWalName && zWalName[0] ); assert( pDbFd ); - /* Verify the values of various constants. Any changes to the values - ** of these constants would result in an incompatible on-disk format - ** for the -shm file. Any change that causes one of these asserts to - ** fail is a backward compatibility problem, even if the change otherwise - ** works. - ** - ** This table also serves as a helpful cross-reference when trying to - ** interpret hex dumps of the -shm file. - */ - assert( 48 == sizeof(WalIndexHdr) ); - assert( 40 == sizeof(WalCkptInfo) ); - assert( 120 == WALINDEX_LOCK_OFFSET ); - assert( 136 == WALINDEX_HDR_SIZE ); - assert( 4096 == HASHTABLE_NPAGE ); - assert( 4062 == HASHTABLE_NPAGE_ONE ); - assert( 8192 == HASHTABLE_NSLOT ); - assert( 383 == HASHTABLE_HASH_1 ); - assert( 32768 == WALINDEX_PGSZ ); - assert( 8 == SQLITE_SHM_NLOCK ); - assert( 5 == WAL_NREADER ); - assert( 24 == WAL_FRAME_HDRSIZE ); - assert( 32 == WAL_HDRSIZE ); - assert( 120 == WALINDEX_LOCK_OFFSET + WAL_WRITE_LOCK ); - assert( 121 == WALINDEX_LOCK_OFFSET + WAL_CKPT_LOCK ); - assert( 122 == WALINDEX_LOCK_OFFSET + WAL_RECOVER_LOCK ); - assert( 123 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(0) ); - assert( 124 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(1) ); - assert( 125 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(2) ); - assert( 126 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(3) ); - assert( 127 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(4) ); - /* In the amalgamation, the os_unix.c and os_win.c source files come before ** this source file. Verify that the #defines of the locking byte offsets ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. ** For that matter, if the lock offset ever changes from its initial design ** value of 120, we need to know that so there is an assert() to check it. */ + assert( 120==WALINDEX_LOCK_OFFSET ); + assert( 136==WALINDEX_HDR_SIZE ); #ifdef WIN_SHM_BASE assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); #endif #ifdef UNIX_SHM_BASE assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); @@ -66851,11 +56326,11 @@ } return rc; } /* -** Change the size to which the WAL file is truncated on each reset. +** Change the size to which the WAL file is trucated on each reset. */ SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){ if( pWal ) pWal->mxWalSize = iLimit; } @@ -66939,11 +56414,11 @@ assert( nLeft>0 && nRight>0 ); while( iRight=nRight || aContent[aLeft[iLeft]]ckptLock && pWal->hdr.mxFrame>0 ); iLast = pWal->hdr.mxFrame; /* Allocate space for the WalIterator object. */ nSegment = walFramePage(iLast) + 1; - nByte = sizeof(WalIterator) + nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte - + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); + p = (WalIterator *)sqlite3_malloc64(nByte); if( !p ){ return SQLITE_NOMEM_BKPT; } memset(p, 0, nByte); p->nSegment = nSegment; - aTmp = (ht_slot*)&(((u8*)p)[nByte]); - SEH_FREE_ON_ERROR(0, p); - for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iHASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) + ); + if( !aTmp ){ + rc = SQLITE_NOMEM_BKPT; + } + + for(i=0; rc==SQLITE_OK && iaSegment[p->nSegment])[sLoc.iZero]; - sLoc.iZero++; - + aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero]; + iZero++; + for(j=0; jaSegment[i].iZero = sLoc.iZero; + walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); + p->aSegment[i].iZero = iZero; p->aSegment[i].nEntry = nEntry; p->aSegment[i].aIndex = aIndex; - p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; + p->aSegment[i].aPgno = (u32 *)aPgno; } } + sqlite3_free(aTmp); + if( rc!=SQLITE_OK ){ - SEH_FREE_ON_ERROR(p, 0); walIteratorFree(p); - p = 0; } *pp = p; return rc; } - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - - -/* -** Attempt to enable blocking locks that block for nMs ms. Return 1 if -** blocking locks are successfully enabled, or 0 otherwise. -*/ -static int walEnableBlockingMs(Wal *pWal, int nMs){ - int rc = sqlite3OsFileControl( - pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs - ); - return (rc==SQLITE_OK); -} - -/* -** Attempt to enable blocking locks. Blocking locks are enabled only if (a) -** they are supported by the VFS, and (b) the database handle is configured -** with a busy-timeout. Return 1 if blocking locks are successfully enabled, -** or 0 otherwise. -*/ -static int walEnableBlocking(Wal *pWal){ - int res = 0; - if( pWal->db ){ - int tmout = pWal->db->busyTimeout; - if( tmout ){ - res = walEnableBlockingMs(pWal, tmout); - } - } - return res; -} - -/* -** Disable blocking locks. -*/ -static void walDisableBlocking(Wal *pWal){ - int tmout = 0; - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); -} - -/* -** If parameter bLock is true, attempt to enable blocking locks, take -** the WRITER lock, and then disable blocking locks. If blocking locks -** cannot be enabled, no attempt to obtain the WRITER lock is made. Return -** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not -** an error if blocking locks can not be enabled. -** -** If the bLock parameter is false and the WRITER lock is held, release it. -*/ -SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock){ - int rc = SQLITE_OK; - assert( pWal->readLock<0 || bLock==0 ); - if( bLock ){ - assert( pWal->db ); - if( walEnableBlocking(pWal) ){ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - } - walDisableBlocking(pWal); - } - }else if( pWal->writeLock ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - } - return rc; -} - -/* -** Set the database handle used to determine if blocking locks are required. -*/ -SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){ - pWal->db = db; -} - -#else -# define walEnableBlocking(x) 0 -# define walDisableBlocking(x) -# define walEnableBlockingMs(pWal, ms) 0 -# define sqlite3WalDb(pWal, db) -#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ - /* ** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and ** n. If the attempt fails and parameter xBusy is not NULL, then it is a ** busy-handler function. Invoke it and retry the lock until either the @@ -67222,16 +56624,10 @@ ){ int rc; do { rc = walLockExclusive(pWal, lockIdx, n); }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ){ - walDisableBlocking(pWal); - rc = SQLITE_BUSY; - } -#endif return rc; } /* ** The cache of the wal-index header must be valid to call this function. @@ -67252,12 +56648,12 @@ ** ** This function updates the shared-memory structures so that the next ** client to write to the database (which may be this one) does so by ** writing frames into the start of the log file. ** -** The value of parameter salt1 is used as the aSalt[1] value in the -** new wal-index header. It should be passed a pseudo-random value (i.e. +** The value of parameter salt1 is used as the aSalt[1] value in the +** new wal-index header. It should be passed a pseudo-random value (i.e. ** one obtained from sqlite3_randomness()). */ static void walRestartHdr(Wal *pWal, u32 salt1){ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); int i; /* Loop counter */ @@ -67265,11 +56661,11 @@ pWal->nCkpt++; pWal->hdr.mxFrame = 0; sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); memcpy(&pWal->hdr.aSalt[1], &salt1, 4); walIndexWriteHdr(pWal); - AtomicStore(&pInfo->nBackfill, 0); + pInfo->nBackfill = 0; pInfo->nBackfillAttempted = 0; pInfo->aReadMark[1] = 0; for(i=2; iaReadMark[i] = READMARK_NOT_USED; assert( pInfo->aReadMark[0]==0 ); } @@ -67281,12 +56677,12 @@ ** The amount of information copies from WAL to database might be limited ** by active readers. This routine will never overwrite a database page ** that a concurrent reader might be using. ** ** All I/O barrier operations (a.k.a fsyncs) occur in this routine when -** SQLite is in WAL-mode in synchronous=NORMAL. That means that if -** checkpoints are always run by a background thread or background +** SQLite is in WAL-mode in synchronous=NORMAL. That means that if +** checkpoints are always run by a background thread or background ** process, foreground threads will never block on a lengthy fsync call. ** ** Fsync is called on the WAL before writing content out of the WAL and ** into the database. This ensures that if the new content is persistent ** in the WAL and can be recovered following a power-loss or hard reset. @@ -67295,11 +56691,11 @@ ** WAL content is copied into the database file. This second fsync makes ** it safe to delete the WAL since the new content will persist in the ** database file. ** ** This routine uses and updates the nBackfill field of the wal-index header. -** This is the only routine that will increase the value of nBackfill. +** This is the only routine that will increase the value of nBackfill. ** (A WAL reset or recovery will revert nBackfill to zero, but not increase ** its value.) ** ** The caller must be holding sufficient locks to ensure that no other ** checkpoint is running (in any other thread or process) at the same @@ -67327,10 +56723,17 @@ szPage = walPagesize(pWal); testcase( szPage<=32768 ); testcase( szPage>=65536 ); pInfo = walCkptInfo(pWal); if( pInfo->nBackfillhdr.mxFrame ){ + + /* Allocate the iterator */ + rc = walIteratorInit(pWal, &pIter); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pIter ); /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); @@ -67340,17 +56743,24 @@ ** cannot be backfilled from the WAL. */ mxSafeFrame = pWal->hdr.mxFrame; mxPage = pWal->hdr.nPage; for(i=1; iaReadMark+i); SEH_INJECT_FAULT; + /* Thread-sanitizer reports that the following is an unsafe read, + ** as some other thread may be in the process of updating the value + ** of the aReadMark[] slot. The assumption here is that if that is + ** happening, the other client may only be increasing the value, + ** not decreasing it. So assuming either that either the "old" or + ** "new" version of the value is read, and not some arbitrary value + ** that would never be written by a real client, things are still + ** safe. */ + u32 y = pInfo->aReadMark[i]; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ - u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; + pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc==SQLITE_BUSY ){ mxSafeFrame = y; xBusy = 0; }else{ @@ -67357,53 +56767,40 @@ goto walcheckpoint_out; } } } - /* Allocate the iterator */ - if( pInfo->nBackfillnBackfill, &pIter); - assert( rc==SQLITE_OK || pIter==0 ); - } - - if( pIter - && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK + if( pInfo->nBackfillnBackfill; - pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; + + pInfo->nBackfillAttempted = mxSafeFrame; /* Sync the WAL to disk */ - rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); + if( sync_flags ){ + rc = sqlite3OsSync(pWal->pWalFd, 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. */ if( rc==SQLITE_OK ){ i64 nReq = ((i64)mxPage * szPage); - i64 nSize; /* Current size of database file */ - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0); rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); if( rc==SQLITE_OK && nSizehdr.mxFrame*szPage)pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq); - } - } - - } + sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); + } + } + /* Iterate through the contents of the WAL, copying data to the db file */ while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); - SEH_INJECT_FAULT; - if( AtomicLoad(&db->u1.isInterrupted) ){ + if( db->u1.isInterrupted ){ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; break; } if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ continue; @@ -67415,24 +56812,23 @@ iOffset = (iDbpage-1)*(i64)szPage; testcase( IS_BIG_INT(iOffset) ); rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); if( rc!=SQLITE_OK ) break; } - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0); /* If work was actually accomplished... */ if( rc==SQLITE_OK ){ if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ i64 szDb = pWal->hdr.nPage*(i64)szPage; testcase( IS_BIG_INT(szDb) ); rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK ){ - rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); + if( rc==SQLITE_OK && sync_flags ){ + rc = sqlite3OsSync(pWal->pDbFd, sync_flags); } } if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; + pInfo->nBackfill = mxSafeFrame; } } /* Release the reader lock held while backfilling */ walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); @@ -67444,17 +56840,16 @@ rc = SQLITE_OK; } } /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the - ** entire wal file has been copied into the database file, then block - ** until all readers have finished using the wal file. This ensures that + ** entire wal file has been copied into the database file, then block + ** until all readers have finished using the wal file. This ensures that ** the next process to write to the database restarts the wal file. */ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ assert( pWal->writeLock ); - SEH_INJECT_FAULT; if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ u32 salt1; sqlite3_randomness(4, &salt1); @@ -67470,11 +56865,11 @@ ** In theory, it might be safe to do this without updating the ** wal-index header in shared memory, as all subsequent reader or ** writer clients should see that the entire log file has been ** checkpointed and behave accordingly. This seems unsafe though, ** as it would leave the system in a state where the contents of - ** the wal-index header do not match the contents of the + ** the wal-index header do not match the contents of the ** file-system. To avoid this, update the wal-index header to ** indicate that the log file contains zero valid frames. */ walRestartHdr(pWal, salt1); rc = sqlite3OsTruncate(pWal->pWalFd, 0); } @@ -67482,11 +56877,10 @@ } } } walcheckpoint_out: - SEH_FREE_ON_ERROR(pIter, 0); walIteratorFree(pIter); return rc; } /* @@ -67505,97 +56899,10 @@ if( rx ){ sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); } } -#ifdef SQLITE_USE_SEH -/* -** This is the "standard" exception handler used in a few places to handle -** an exception thrown by reading from the *-shm mapping after it has become -** invalid in SQLITE_USE_SEH builds. It is used as follows: -** -** SEH_TRY { ... } -** SEH_EXCEPT( rc = walHandleException(pWal); ) -** -** This function does three things: -** -** 1) Determines the locks that should be held, based on the contents of -** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other -** held locks are assumed to be transient locks that would have been -** released had the exception not been thrown and are dropped. -** -** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). -** -** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL -** -** 4) Returns SQLITE_IOERR. -*/ -static int walHandleException(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<lockMask & ~( - (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) - ); - for(ii=0; iipFree); - pWal->pFree = 0; - if( pWal->pWiValue ){ - pWal->apWiData[pWal->iWiPg] = pWal->pWiValue; - pWal->pWiValue = 0; - } - return SQLITE_IOERR_IN_PAGE; -} - -/* -** Assert that the Wal.lockMask mask, which indicates the locks held -** by the connection, is consistent with the Wal.readLock, Wal.writeLock -** and Wal.ckptLock variables. To be used as: -** -** assert( walAssertLockmask(pWal) ); -*/ -static int walAssertLockmask(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) -#ifdef SQLITE_ENABLE_SNAPSHOT - | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) -#endif - ); - assert( mExpect==pWal->lockMask ); - } - return 1; -} - -/* -** Return and zero the "system error" field set when an -** EXCEPTION_IN_PAGE_ERROR exception is caught. -*/ -SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){ - int iRet = 0; - if( pWal ){ - iRet = pWal->iSysErrno; - pWal->iSysErrno = 0; - } - return iRet; -} - -#else -# define walAssertLockmask(x) 1 -#endif /* ifdef SQLITE_USE_SEH */ - /* ** Close a connection to a log file. */ SQLITE_PRIVATE int sqlite3WalClose( Wal *pWal, /* Wal to close */ @@ -67606,12 +56913,10 @@ ){ int rc = SQLITE_OK; if( pWal ){ int isDelete = 0; /* True to unlink wal and wal-index files */ - assert( walAssertLockmask(pWal) ); - /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. @@ -67622,21 +56927,21 @@ && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) ){ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } - rc = sqlite3WalCheckpoint(pWal, db, + rc = sqlite3WalCheckpoint(pWal, db, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 ); if( rc==SQLITE_OK ){ int bPersist = -1; sqlite3OsFileControlHint( pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist ); if( bPersist!=1 ){ /* Try to delete the WAL file if the checkpoint completed and - ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal + ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal ** mode (!bPersist) */ isDelete = 1; }else if( pWal->mxWalSize>=0 ){ /* Try to truncate the WAL file to zero bytes if the checkpoint ** completed and fsynced (rc==SQLITE_OK) and we are in persistent @@ -67678,11 +56983,11 @@ ** and *pChanged is set to 1. ** ** If the checksum cannot be verified return non-zero. If the header ** is read successfully and the checksum verified, return zero. */ -static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){ +static int walIndexTryHdr(Wal *pWal, int *pChanged){ u32 aCksum[2]; /* Checksum on the header content */ WalIndexHdr h1, h2; /* Two copies of the header content */ WalIndexHdr volatile *aHdr; /* Header in shared memory */ /* The first page of the wal-index must be mapped at this point. */ @@ -67691,29 +56996,23 @@ /* Read the header. This might happen concurrently with a write to the ** same area of shared memory on a different CPU in a SMP, ** meaning it is possible that an inconsistent snapshot is read ** from the file. If this happens, return non-zero. ** - ** tag-20200519-1: ** There are two copies of the header at the beginning of the wal-index. ** When reading, read [0] first then [1]. Writes are in the reverse order. ** Memory barriers are used to prevent the compiler or the hardware from - ** reordering the reads and writes. TSAN and similar tools can sometimes - ** give false-positive warnings about these accesses because the tools do not - ** account for the double-read and the memory barrier. The use of mutexes - ** here would be problematic as the memory being accessed is potentially - ** shared among multiple processes and not all mutex implementations work - ** reliably in that environment. + ** reordering the reads and writes. */ aHdr = walIndexHdr(pWal); - memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */ + memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); walShmBarrier(pWal); memcpy(&h2, (void *)&aHdr[1], sizeof(h2)); if( memcmp(&h1, &h2, sizeof(h1))!=0 ){ return 1; /* Dirty read */ - } + } if( h1.isInit==0 ){ return 1; /* Malformed header - probably all zeros */ } walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum); if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){ @@ -67730,102 +57029,69 @@ /* The header was successfully read. Return zero. */ 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 ** wal-index from the WAL before returning. ** ** Set *pChanged to 1 if the wal-index header value in pWal->hdr is ** changed by this operation. If pWal->hdr is unchanged, set *pChanged ** to 0. ** -** If the wal-index header is successfully read, return SQLITE_OK. +** If the wal-index header is successfully read, return SQLITE_OK. ** Otherwise an SQLite error code. */ static int walIndexReadHdr(Wal *pWal, int *pChanged){ int rc; /* Return code */ int badHdr; /* True if a header read failed */ volatile u32 *page0; /* Chunk of wal-index containing header */ - /* Ensure that page 0 of the wal-index (the page that contains the + /* Ensure that page 0 of the wal-index (the page that contains the ** wal-index header) is mapped. Return early if an error occurs here. */ assert( pChanged ); rc = walIndexPage(pWal, 0, &page0); if( rc!=SQLITE_OK ){ - 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 ); + return rc; + }; + assert( page0 || 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 - ** works, but may fail if the wal-index header is corrupt or currently + ** works, but may fail if the wal-index header is corrupt or currently ** being modified by another thread or process. */ badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1); /* If the first attempt failed, it might have been due to a race ** with a writer. So get a WRITE lock and try again. */ + assert( badHdr==0 || pWal->writeLock==0 ); if( badHdr ){ - if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){ + if( pWal->readOnly & WAL_SHM_RDONLY ){ if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ walUnlockShared(pWal, WAL_WRITE_LOCK); rc = SQLITE_READONLY_RECOVERY; } - }else{ - int bWriteLock = pWal->writeLock; - if( bWriteLock - || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) - ){ - pWal->writeLock = 1; - if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ - badHdr = walIndexTryHdr(pWal, pChanged); - if( badHdr ){ - /* If the wal-index header is still malformed even while holding - ** a WRITE lock, it can only mean that the header is corrupted and - ** needs to be reconstructed. So run recovery to do exactly that. - ** Disable blocking locks first. */ - walDisableBlocking(pWal); - rc = walIndexRecover(pWal); - *pChanged = 1; - } - } - if( bWriteLock==0 ){ - pWal->writeLock = 0; - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - } - } + }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ + pWal->writeLock = 1; + if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ + badHdr = walIndexTryHdr(pWal, pChanged); + if( badHdr ){ + /* If the wal-index header is still malformed even while holding + ** a WRITE lock, it can only mean that the header is corrupted and + ** needs to be reconstructed. So run recovery to do exactly that. + */ + rc = walIndexRecover(pWal); + *pChanged = 1; + } + } + pWal->writeLock = 0; + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); } } /* If the header is read successfully, check the version number to make ** sure the wal-index was not constructed with some future format that @@ -67832,230 +57098,19 @@ ** this version of SQLite cannot understand. */ 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; -} - -/* -** 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. -*/ -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 */ - assert( (pWal->szPage & (pWal->szPage-1))==0 ); - assert( pWal->szPage>=512 && pWal->szPage<=65536 ); - szFrame = pWal->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->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; -} - -/* -** The final argument passed to walTryBeginRead() is of type (int*). The -** caller should invoke walTryBeginRead as follows: -** -** int cnt = 0; -** do { -** rc = walTryBeginRead(..., &cnt); -** }while( rc==WAL_RETRY ); -** -** The final value of "cnt" is of no use to the caller. It is used by -** the implementation of walTryBeginRead() as follows: -** -** + Each time walTryBeginRead() is called, it is incremented. Once -** it reaches WAL_RETRY_PROTOCOL_LIMIT - indicating that walTryBeginRead() -** has many times been invoked and failed with WAL_RETRY - walTryBeginRead() -** returns SQLITE_PROTOCOL. -** -** + If SQLITE_ENABLE_SETLK_TIMEOUT is defined and walTryBeginRead() failed -** because a blocking lock timed out (SQLITE_BUSY_TIMEOUT from the OS -** layer), the WAL_RETRY_BLOCKED_MASK bit is set in "cnt". In this case -** the next invocation of walTryBeginRead() may omit an expected call to -** sqlite3OsSleep(). There has already been a delay when the previous call -** waited on a lock. -*/ -#define WAL_RETRY_PROTOCOL_LIMIT 100 -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -# define WAL_RETRY_BLOCKED_MASK 0x10000000 -#else -# define WAL_RETRY_BLOCKED_MASK 0 -#endif + + return rc; +} + +/* +** This is the value that walTryBeginRead returns when it needs to +** be retried. +*/ +#define WAL_RETRY (-1) /* ** Attempt to start a read transaction. This might fail due to a race or ** other transient condition. When that happens, it returns WAL_RETRY to ** indicate to the caller that it is safe to retry immediately. @@ -68064,14 +57119,14 @@ ** I/O error or an SQLITE_BUSY because another process is running ** recovery) return a positive error code. ** ** The useWal parameter is true to force the use of the WAL and disable ** the case where the WAL is bypassed because it has been completely -** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() -** to make a copy of the wal-index header into pWal->hdr. If the -** wal-index header has changed, *pChanged is set to 1 (as an indication -** to the caller that the local page cache is obsolete and needs to be +** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() +** to make a copy of the wal-index header into pWal->hdr. If the +** wal-index header has changed, *pChanged is set to 1 (as an indication +** to the caller that the local paget 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. ** ** The caller must set the cnt parameter to the number of prior calls to ** this routine during the current read attempt that returned WAL_RETRY. @@ -68082,11 +57137,11 @@ ** and is not honoring the locking protocol. There is a vanishingly small ** chance that SQLITE_PROTOCOL could be returned because of a run of really ** bad luck when there is lots of contention for the wal-index, but that ** possibility is so small that it can be safely neglected, we believe. ** -** On success, this routine obtains a read lock on +** On success, this routine obtains a read lock on ** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is ** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1) ** that means the Wal does not hold any read lock. The reader must not ** access any database page that is modified by a WAL frame up to and ** including frame number aReadMark[pWal->readLock]. The reader will @@ -68103,81 +57158,49 @@ ** checkpoint process do as much work as possible. This routine might ** update values of the aReadMark[] array in the header, but if it does ** so it takes care to hold an exclusive lock on the corresponding ** WAL_READ_LOCK() while changing values. */ -static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){ +static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ + u32 mxReadMark; /* Largest aReadMark[] value */ + int mxI; /* Index of largest aReadMark[] value */ + int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int nBlockTmout = 0; -#endif + u32 mxFrame; /* Wal frame to lock to */ 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 ** instances of time. No I/O or other system calls are done while the - ** locks are held, so the locks should not be held for very long. But + ** locks are held, so the locks should not be held for very long. But ** if we are unlucky, another process that is holding a lock might get - ** paged out or take a page-fault that is time-consuming to resolve, + ** paged out or take a page-fault that is time-consuming to resolve, ** during the few nanoseconds that it is holding the lock. In that case, ** it might take longer than normal for the lock to free. ** ** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this ** is more of a scheduler yield than an actual delay. But on the 10th - ** an subsequent retries, the delays start becoming longer and longer, + ** an subsequent retries, the delays start becoming longer and longer, ** so that on the 100th (and last) RETRY we delay for 323 milliseconds. ** The total delay time before giving up is less than 10 seconds. */ - (*pCnt)++; - if( *pCnt>5 ){ + if( cnt>5 ){ int nDelay = 1; /* Pause time in microseconds */ - int cnt = (*pCnt & ~WAL_RETRY_BLOCKED_MASK); - if( cnt>WAL_RETRY_PROTOCOL_LIMIT ){ + if( cnt>100 ){ VVA_ONLY( pWal->lockError = 1; ) return SQLITE_PROTOCOL; } - if( *pCnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor - ** to block for locks for approximately nDelay us. This affects three - ** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if - ** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the - ** first attempted read fails, and (c) the shared lock taken on the - ** read-mark. - ** - ** If the previous call failed due to an SQLITE_BUSY_TIMEOUT error, - ** then sleep for the minimum of 1us. The previous call already provided - ** an extra delay while it was blocking on the lock. - */ - nBlockTmout = (nDelay+998) / 1000; - if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){ - if( *pCnt & WAL_RETRY_BLOCKED_MASK ) nDelay = 1; - } -#endif + if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; sqlite3OsSleep(pWal->pVfs, nDelay); - *pCnt &= ~WAL_RETRY_BLOCKED_MASK; } if( !useWal ){ - assert( rc==SQLITE_OK ); - if( pWal->bShmUnreliable==0 ){ - rc = walIndexReadHdr(pWal, pChanged); - } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - walDisableBlocking(pWal); - if( rc==SQLITE_BUSY_TIMEOUT ){ - rc = SQLITE_BUSY; - *pCnt |= WAL_RETRY_BLOCKED_MASK; - } -#endif + 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 ** be running, convert BUSY to BUSY_RECOVERY. There is a race here ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY @@ -68186,13 +57209,13 @@ ** right on the second iteration. */ if( pWal->apWiData[0]==0 ){ /* This branch is taken when the xShmMap() method returns SQLITE_BUSY. ** We assume this is a transient condition, so return WAL_RETRY. The - ** xShmMap() implementation used by the default unix and win32 VFS - ** modules may return SQLITE_BUSY due to a race condition in the - ** code that determines whether or not the shared-memory region + ** xShmMap() implementation used by the default unix and win32 VFS + ** modules may return SQLITE_BUSY due to a race condition in the + ** code that determines whether or not the shared-memory region ** must be zeroed before the requested page is returned. */ rc = WAL_RETRY; }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){ walUnlockShared(pWal, WAL_RECOVER_LOCK); @@ -68202,223 +57225,153 @@ } } 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); - SEH_INJECT_FAULT; - { - u32 mxReadMark; /* Largest aReadMark[] value */ - int mxI; /* Index of largest aReadMark[] value */ - int i; /* Loop counter */ - u32 mxFrame; /* Wal frame to lock to */ - if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame -#ifdef SQLITE_ENABLE_SNAPSHOT - && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0) -#endif - ){ - /* The WAL has been completely backfilled (or it is empty). - ** and can be safely ignored. - */ - rc = walLockShared(pWal, WAL_READ_LOCK(0)); - walShmBarrier(pWal); - if( rc==SQLITE_OK ){ - if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){ - /* It is not safe to allow the reader to continue here if frames - ** may have been appended to the log before READ_LOCK(0) was obtained. - ** When holding READ_LOCK(0), the reader ignores the entire log file, - ** which implies that the database file contains a trustworthy - ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from - ** happening, this is usually correct. - ** - ** However, if frames have been appended to the log (or if the log - ** is wrapped and written for that matter) before the READ_LOCK(0) - ** is obtained, that is not necessarily true. A checkpointer may - ** have started to backfill the appended frames but crashed before - ** it finished. Leaving a corrupt image in the database file. - */ - walUnlockShared(pWal, WAL_READ_LOCK(0)); - return WAL_RETRY; - } - pWal->readLock = 0; - return SQLITE_OK; - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - - /* If we get this far, it means that the reader will want to use - ** the WAL to get at content from recent commits. The job now is - ** to select one of the aReadMark[] entries that is closest to - ** but not exceeding pWal->hdr.mxFrame and lock that entry. - */ - mxReadMark = 0; - mxI = 0; - mxFrame = pWal->hdr.mxFrame; -#ifdef SQLITE_ENABLE_SNAPSHOT - if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame; - } -#endif - for(i=1; iaReadMark+i); SEH_INJECT_FAULT; - if( mxReadMark<=thisMark && thisMark<=mxFrame ){ - assert( thisMark!=READMARK_NOT_USED ); - mxReadMark = thisMark; - mxI = i; - } - } - if( (pWal->readOnly & WAL_SHM_RDONLY)==0 - && (mxReadMarkaReadMark+i,mxFrame); - mxReadMark = mxFrame; - mxI = i; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - break; - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - } - if( mxI==0 ){ - assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); - return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT; - } - - (void)walEnableBlockingMs(pWal, nBlockTmout); - rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); - walDisableBlocking(pWal); - if( rc ){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ){ - *pCnt |= WAL_RETRY_BLOCKED_MASK; - } -#else - assert( rc!=SQLITE_BUSY_TIMEOUT ); -#endif - assert((rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT); - return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc; - } - /* Now that the read-lock has been obtained, check that neither the - ** value in the aReadMark[] array or the contents of the wal-index - ** header have changed. - ** - ** It is necessary to check that the wal-index header did not change - ** between the time it was read and when the shared-lock was obtained - ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility - ** that the log file may have been wrapped by a writer, or that frames - ** that occur later in the log than pWal->hdr.mxFrame may have been - ** copied into the database by a checkpointer. If either of these things - ** happened, then reading the database with the current value of - ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry - ** instead. - ** - ** Before checking that the live wal-index header has not changed - ** since it was read, set Wal.minFrame to the first frame in the wal - ** file that has not yet been checkpointed. This client will not need - ** to read any frames earlier than minFrame from the wal file - they - ** can be safely read directly from the database file. - ** - ** Because a ShmBarrier() call is made between taking the copy of - ** nBackfill and checking that the wal-header in shared-memory still - ** matches the one cached in pWal->hdr, it is guaranteed that the - ** checkpointer that set nBackfill was not working with a wal-index - ** header newer than that cached in pWal->hdr. If it were, that could - ** cause a problem. The checkpointer could omit to checkpoint - ** a version of page X that lies before pWal->minFrame (call that version - ** A) on the basis that there is a newer version (version B) of the same - ** page later in the wal file. But if version B happens to like past - ** frame pWal->hdr.mxFrame - then the client would incorrectly assume - ** that it can read version A from the database file. However, since - ** we can guarantee that the checkpointer that set nBackfill could not - ** see any pages past pWal->hdr.mxFrame, this problem does not come up. - */ - pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; - walShmBarrier(pWal); - if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark - || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) - ){ - walUnlockShared(pWal, WAL_READ_LOCK(mxI)); - return WAL_RETRY; - }else{ - assert( mxReadMark<=pWal->hdr.mxFrame ); - pWal->readLock = (i16)mxI; - } + } + + pInfo = walCkptInfo(pWal); + 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))) +#endif + ){ + /* The WAL has been completely backfilled (or it is empty). + ** and can be safely ignored. + */ + rc = walLockShared(pWal, WAL_READ_LOCK(0)); + walShmBarrier(pWal); + if( rc==SQLITE_OK ){ + if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ + /* It is not safe to allow the reader to continue here if frames + ** may have been appended to the log before READ_LOCK(0) was obtained. + ** When holding READ_LOCK(0), the reader ignores the entire log file, + ** which implies that the database file contains a trustworthy + ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from + ** happening, this is usually correct. + ** + ** However, if frames have been appended to the log (or if the log + ** is wrapped and written for that matter) before the READ_LOCK(0) + ** is obtained, that is not necessarily true. A checkpointer may + ** have started to backfill the appended frames but crashed before + ** it finished. Leaving a corrupt image in the database file. + */ + walUnlockShared(pWal, WAL_READ_LOCK(0)); + return WAL_RETRY; + } + pWal->readLock = 0; + return SQLITE_OK; + }else if( rc!=SQLITE_BUSY ){ + return rc; + } + } + + /* If we get this far, it means that the reader will want to use + ** the WAL to get at content from recent commits. The job now is + ** to select one of the aReadMark[] entries that is closest to + ** but not exceeding pWal->hdr.mxFrame and lock that entry. + */ + mxReadMark = 0; + mxI = 0; + mxFrame = pWal->hdr.mxFrame; +#ifdef SQLITE_ENABLE_SNAPSHOT + if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame; + } +#endif + for(i=1; iaReadMark[i]; + if( mxReadMark<=thisMark && thisMark<=mxFrame ){ + assert( thisMark!=READMARK_NOT_USED ); + mxReadMark = thisMark; + mxI = i; + } + } + if( (pWal->readOnly & WAL_SHM_RDONLY)==0 + && (mxReadMarkaReadMark[i] = mxFrame; + mxI = i; + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + break; + }else if( rc!=SQLITE_BUSY ){ + return rc; + } + } + } + if( mxI==0 ){ + assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); + return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; + } + + rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); + if( rc ){ + return rc==SQLITE_BUSY ? WAL_RETRY : rc; + } + /* Now that the read-lock has been obtained, check that neither the + ** value in the aReadMark[] array or the contents of the wal-index + ** header have changed. + ** + ** It is necessary to check that the wal-index header did not change + ** between the time it was read and when the shared-lock was obtained + ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility + ** that the log file may have been wrapped by a writer, or that frames + ** that occur later in the log than pWal->hdr.mxFrame may have been + ** copied into the database by a checkpointer. If either of these things + ** happened, then reading the database with the current value of + ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry + ** instead. + ** + ** Before checking that the live wal-index header has not changed + ** since it was read, set Wal.minFrame to the first frame in the wal + ** file that has not yet been checkpointed. This client will not need + ** to read any frames earlier than minFrame from the wal file - they + ** can be safely read directly from the database file. + ** + ** Because a ShmBarrier() call is made between taking the copy of + ** nBackfill and checking that the wal-header in shared-memory still + ** matches the one cached in pWal->hdr, it is guaranteed that the + ** checkpointer that set nBackfill was not working with a wal-index + ** header newer than that cached in pWal->hdr. If it were, that could + ** cause a problem. The checkpointer could omit to checkpoint + ** a version of page X that lies before pWal->minFrame (call that version + ** A) on the basis that there is a newer version (version B) of the same + ** page later in the wal file. But if version B happens to like past + ** frame pWal->hdr.mxFrame - then the client would incorrectly assume + ** that it can read version A from the database file. However, since + ** we can guarantee that the checkpointer that set nBackfill could not + ** see any pages past pWal->hdr.mxFrame, this problem does not come up. + */ + pWal->minFrame = pInfo->nBackfill+1; + walShmBarrier(pWal); + if( pInfo->aReadMark[mxI]!=mxReadMark + || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) + ){ + walUnlockShared(pWal, WAL_READ_LOCK(mxI)); + return WAL_RETRY; + }else{ + assert( mxReadMark<=pWal->hdr.mxFrame ); + pWal->readLock = (i16)mxI; } return rc; } #ifdef SQLITE_ENABLE_SNAPSHOT /* -** This function does the work of sqlite3WalSnapshotRecover(). -*/ -static int walSnapshotRecover( - Wal *pWal, /* WAL handle */ - void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ - void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ -){ - int szPage = (int)pWal->szPage; - int rc; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ - WalHashLoc sLoc; /* Hash table location */ - u32 pgno; /* Page number in db file */ - i64 iDbOff; /* Offset of db file entry */ - i64 iWalOff; /* Offset of wal file entry */ - - rc = walHashGet(pWal, walFramePage(i), &sLoc); - if( rc!=SQLITE_OK ) break; - assert( i - sLoc.iZero - 1 >=0 ); - pgno = sLoc.aPgno[i-sLoc.iZero-1]; - 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; - } - } - - return rc; -} - -/* -** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted +** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted ** variable so that older snapshots can be accessed. To do this, loop -** through all wal frames from nBackfillAttempted to (nBackfill+1), +** through all wal frames from nBackfillAttempted to (nBackfill+1), ** comparing their content to the corresponding page with the database ** file, if any. Set nBackfillAttempted to the frame number of the ** first frame for which the wal file content matches the db file. ** -** This is only really safe if the file-system is such that any page -** writes made by earlier checkpointers were atomic operations, which +** This is only really safe if the file-system is such that any page +** writes made by earlier checkpointers were atomic operations, which ** is not always true. It is also possible that nBackfillAttempted ** may be left set to a value larger than expected, if a wal frame ** contains content that duplicate of an earlier version of the same ** page. ** @@ -68430,75 +57383,90 @@ int rc; assert( pWal->readLock>=0 ); rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(pWal->szPage); - void *pBuf2 = sqlite3_malloc(pWal->szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - pWal->ckptLock = 1; - SEH_TRY { - rc = walSnapshotRecover(pWal, pBuf1, pBuf2); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - pWal->ckptLock = 0; - } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); + 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 */ /* -** This function does the work of sqlite3WalBeginReadTransaction() (see -** below). That function simply calls this one inside an SEH_TRY{...} block. -*/ -static int walBeginReadTransaction(Wal *pWal, int *pChanged){ - int rc; /* Return code */ - int cnt = 0; /* Number of TryBeginRead attempts */ -#ifdef SQLITE_ENABLE_SNAPSHOT - int ckptLock = 0; - int bChanged = 0; - WalIndexHdr *pSnapshot = pWal->pSnapshot; -#endif - - assert( pWal->ckptLock==0 ); - assert( pWal->nSehTry>0 ); - -#ifdef SQLITE_ENABLE_SNAPSHOT - if( pSnapshot ){ - if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ - bChanged = 1; - } - - /* It is possible that there is a checkpointer thread running - ** concurrent with this code. If this is the case, it may be that the - ** checkpointer has already determined that it will checkpoint - ** snapshot X, where X is later in the wal file than pSnapshot, but - ** has not yet set the pInfo->nBackfillAttempted variable to indicate - ** its intent. To avoid the race condition this leads to, ensure that - ** there is no checkpointer process by taking a shared CKPT lock - ** before checking pInfo->nBackfillAttempted. */ - (void)walEnableBlocking(pWal); - rc = walLockShared(pWal, WAL_CKPT_LOCK); - walDisableBlocking(pWal); - - if( rc!=SQLITE_OK ){ - return rc; - } - ckptLock = 1; - } -#endif - - do{ - rc = walTryBeginRead(pWal, pChanged, 0, &cnt); +** Begin a read transaction on the database. +** +** This routine used to be called sqlite3OpenSnapshot() and with good reason: +** it takes a snapshot of the state of the WAL and wal-index for the current +** instant in time. The current thread will continue to use this snapshot. +** Other threads might append new content to the WAL and wal-index but +** that extra content is ignored by the current thread. +** +** If the database contents have changes since the previous read +** transaction, then *pChanged is set to 1 before returning. The +** Pager layer will use this to know that is cache is stale and +** needs to be flushed. +*/ +SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + int rc; /* Return code */ + int cnt = 0; /* Number of TryBeginRead attempts */ + +#ifdef SQLITE_ENABLE_SNAPSHOT + int bChanged = 0; + WalIndexHdr *pSnapshot = pWal->pSnapshot; + if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ + bChanged = 1; + } +#endif + + do{ + rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); }while( rc==WAL_RETRY ); testcase( (rc&0xff)==SQLITE_BUSY ); testcase( (rc&0xff)==SQLITE_IOERR ); testcase( rc==SQLITE_PROTOCOL ); testcase( rc==SQLITE_OK ); @@ -68522,72 +57490,55 @@ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 ); assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame ); - /* Check that the wal file has not been wrapped. Assuming that it has - ** not, also check that no checkpointer has attempted to checkpoint any - ** frames beyond pSnapshot->mxFrame. If either of these conditions are - ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr - ** with *pSnapshot and set *pChanged as appropriate for opening the - ** snapshot. */ - if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - && pSnapshot->mxFrame>=pInfo->nBackfillAttempted - ){ - assert( pWal->readLock>0 ); - memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); - *pChanged = bChanged; - }else{ - rc = SQLITE_ERROR_SNAPSHOT; - } - - /* A client using a non-current snapshot may not ignore any frames - ** from the start of the wal file. This is because, for a system - ** where (minFrame < iSnapshot < maxFrame), a checkpointer may - ** have omitted to checkpoint a frame earlier than minFrame in - ** the file because there exists a frame after iSnapshot that - ** is the same database page. */ - pWal->minFrame = 1; + /* It is possible that there is a checkpointer thread running + ** concurrent with this code. If this is the case, it may be that the + ** checkpointer has already determined that it will checkpoint + ** snapshot X, where X is later in the wal file than pSnapshot, but + ** has not yet set the pInfo->nBackfillAttempted variable to indicate + ** its intent. To avoid the race condition this leads to, ensure that + ** there is no checkpointer process by taking a shared CKPT lock + ** before checking pInfo->nBackfillAttempted. + ** + ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing + ** this already? + */ + rc = walLockShared(pWal, WAL_CKPT_LOCK); + + if( rc==SQLITE_OK ){ + /* Check that the wal file has not been wrapped. Assuming that it has + ** not, also check that no checkpointer has attempted to checkpoint any + ** frames beyond pSnapshot->mxFrame. If either of these conditions are + ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr + ** with *pSnapshot and set *pChanged as appropriate for opening the + ** snapshot. */ + if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) + && pSnapshot->mxFrame>=pInfo->nBackfillAttempted + ){ + assert( pWal->readLock>0 ); + memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); + *pChanged = bChanged; + }else{ + rc = SQLITE_BUSY_SNAPSHOT; + } + + /* Release the shared CKPT lock obtained above. */ + walUnlockShared(pWal, WAL_CKPT_LOCK); + } + if( rc!=SQLITE_OK ){ sqlite3WalEndReadTransaction(pWal); } } } - - /* Release the shared CKPT lock obtained above. */ - if( ckptLock ){ - assert( pSnapshot ); - walUnlockShared(pWal, WAL_CKPT_LOCK); - } #endif return rc; } -/* -** Begin a read transaction on the database. -** -** This routine used to be called sqlite3OpenSnapshot() and with good reason: -** it takes a snapshot of the state of the WAL and wal-index for the current -** instant in time. The current thread will continue to use this snapshot. -** Other threads might append new content to the WAL and wal-index but -** that extra content is ignored by the current thread. -** -** If the database contents have changes since the previous read -** transaction, then *pChanged is set to 1 before returning. The -** Pager layer will use this to know that its cache is stale and -** needs to be flushed. -*/ -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ - int rc; - SEH_TRY { - rc = walBeginReadTransaction(pWal, pChanged); - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - return rc; -} - /* ** Finish with a read transaction. All this does is release the ** read-lock. */ SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ @@ -68604,11 +57555,11 @@ ** to zero. ** ** Return SQLITE_OK if successful, or an error code if an error occurs. If an ** error does occur, the final value of *piRead is undefined. */ -static int walFindFrame( +SQLITE_PRIVATE int sqlite3WalFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ u32 *piRead /* OUT: Frame number (or zero) */ ){ u32 iRead = 0; /* If !=0, WAL frame to return data from */ @@ -68619,83 +57570,79 @@ /* This routine is only be called from within a read transaction. */ assert( pWal->readLock>=0 || pWal->lockError ); /* If the "last page" field of the wal-index header snapshot is 0, then ** no data will be read from the wal under any circumstances. Return early - ** in this case as an optimization. Likewise, if pWal->readLock==0, - ** then the WAL is ignored by the reader so return early, as if the + ** in this case as an optimization. Likewise, if pWal->readLock==0, + ** then the WAL is ignored by the reader so return early, as if the ** WAL were empty. */ - if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){ + if( iLast==0 || pWal->readLock==0 ){ *piRead = 0; return SQLITE_OK; } /* Search the hash table or tables for an entry matching page number ** pgno. Each iteration of the following for() loop searches one ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames). ** ** This code might run concurrently to the code in walIndexAppend() - ** that adds entries to the wal-index (and possibly to this hash - ** table). This means the value just read from the hash - ** slot (aHash[iKey]) may have been added before or after the + ** that adds entries to the wal-index (and possibly to this hash + ** table). This means the value just read from the hash + ** slot (aHash[iKey]) may have been added before or after the ** current read transaction was opened. Values added after the ** read transaction was opened may have been written incorrectly - ** i.e. these slots may contain garbage data. However, we assume ** that any slots written before the current read transaction was ** opened remain unmodified. ** ** For the reasons above, the if(...) condition featured in the inner - ** loop of the following block is more stringent that would be required + ** loop of the following block is more stringent that would be required ** if we had exclusive access to the hash-table: ** - ** (aPgno[iFrame]==pgno): + ** (aPgno[iFrame]==pgno): ** This condition filters out normal hash-table collisions. ** - ** (iFrame<=iLast): + ** (iFrame<=iLast): ** This condition filters out entries that were added to the hash ** table after the current read-transaction had started. */ iMinHash = walFramePage(pWal->minFrame); - for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){ - WalHashLoc sLoc; /* Hash table location */ + for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){ + volatile ht_slot *aHash; /* Pointer to hash table */ + volatile u32 *aPgno; /* Pointer to array of page numbers */ + u32 iZero; /* Frame number corresponding to aPgno[0] */ int iKey; /* Hash slot index */ int nCollide; /* Number of hash collisions remaining */ int rc; /* Error code */ - u32 iH; - rc = walHashGet(pWal, iHash, &sLoc); + rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero); if( rc!=SQLITE_OK ){ return rc; } nCollide = HASHTABLE_NSLOT; - iKey = walHash(pgno); - SEH_INJECT_FAULT; - while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ - u32 iFrame = iH + sLoc.iZero; - if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){ + for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ + u32 iFrame = aHash[iKey] + iZero; + if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){ assert( iFrame>iRead || CORRUPT_DB ); iRead = iFrame; } if( (nCollide--)==0 ){ - *piRead = 0; return SQLITE_CORRUPT_BKPT; } - iKey = walNextHash(iKey); } - if( iRead ) break; } #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* If expensive assert() statements are available, do a linear search ** of the wal-index file content. Make sure the results agree with the ** result obtained using the hash indexes above. */ { u32 iRead2 = 0; u32 iTest; - assert( pWal->bShmUnreliable || pWal->minFrame>0 ); - for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){ + assert( pWal->minFrame>0 ); + for(iTest=iLast; iTest>=pWal->minFrame; iTest--){ if( walFramePgno(pWal, iTest)==pgno ){ iRead2 = iTest; break; } } @@ -68705,34 +57652,10 @@ *piRead = iRead; return SQLITE_OK; } -/* -** Search the wal file for page pgno. If found, set *piRead to the frame that -** contains the page. Otherwise, if pgno is not in the wal file, set *piRead -** to zero. -** -** Return SQLITE_OK if successful, or an error code if an error occurs. If an -** error does occur, the final value of *piRead is undefined. -** -** The difference between this function and walFindFrame() is that this -** function wraps walFindFrame() in an SEH_TRY{...} block. -*/ -SQLITE_PRIVATE int sqlite3WalFindFrame( - Wal *pWal, /* WAL handle */ - Pgno pgno, /* Database page number to read data for */ - u32 *piRead /* OUT: Frame number (or zero) */ -){ - int rc; - SEH_TRY { - rc = walFindFrame(pWal, pgno, piRead); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - return rc; -} - /* ** Read the contents of frame iRead from the wal file into buffer pOut ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an ** error code otherwise. */ @@ -68751,11 +57674,11 @@ iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); } -/* +/* ** Return the size of the database in pages (or zero, if unknown). */ SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){ if( pWal && ALWAYS(pWal->readLock>=0) ){ return pWal->hdr.nPage; @@ -68762,11 +57685,11 @@ } return 0; } -/* +/* ** This function starts a write transaction on the WAL. ** ** A read transaction must have already been started by a prior call ** to sqlite3WalBeginReadTransaction(). ** @@ -68778,20 +57701,10 @@ ** There can only be a single writer active at a time. */ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ int rc; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* If the write-lock is already held, then it was obtained before the - ** read-transaction was even opened, making this call a no-op. - ** Return early. */ - if( pWal->writeLock ){ - assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) ); - return SQLITE_OK; - } -#endif - /* Cannot start a write transaction without first holding a read ** transaction. */ assert( pWal->readLock>=0 ); assert( pWal->writeLock==0 && pWal->iReCksum==0 ); @@ -68810,21 +57723,16 @@ /* If another connection has written to the database file since the ** time the read transaction on this connection was started, then ** the write is disallowed. */ - SEH_TRY { - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ - rc = SQLITE_BUSY_SNAPSHOT; - } - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) - - if( rc!=SQLITE_OK ){ + if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; + rc = SQLITE_BUSY_SNAPSHOT; } + return rc; } /* ** End a write transaction. The commit has already been done. This @@ -68855,46 +57763,43 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ int rc = SQLITE_OK; if( ALWAYS(pWal->writeLock) ){ Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; - - SEH_TRY { - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - for(iFrame=pWal->hdr.mxFrame+1; - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; - iFrame++ - ){ - /* This call cannot fail. Unless the page for which the page number - ** is passed as the second argument is (a) in the cache and - ** (b) has an outstanding reference, then xUndo is either a no-op - ** (if (a) is false) or simply expels the page from the cache (if (b) - ** is false). - ** - ** If the upper layer is doing a rollback, it is guaranteed that there - ** are no outstanding references to any page other than page 1. And - ** page 1 is never written to the log until the transaction is - ** committed. As a result, the call to xUndo may not fail. - */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); - } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + + /* Restore the clients cache of the wal-index header to the state it + ** was in before the client began writing to the database. + */ + memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + for(iFrame=pWal->hdr.mxFrame+1; + ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; + iFrame++ + ){ + /* This call cannot fail. Unless the page for which the page number + ** is passed as the second argument is (a) in the cache and + ** (b) has an outstanding reference, then xUndo is either a no-op + ** (if (a) is false) or simply expels the page from the cache (if (b) + ** is false). + ** + ** If the upper layer is doing a rollback, it is guaranteed that there + ** are no outstanding references to any page other than page 1. And + ** page 1 is never written to the log until the transaction is + ** committed. As a result, the call to xUndo may not fail. + */ + assert( walFramePgno(pWal, iFrame)!=1 ); + rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + } + if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } return rc; } -/* -** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 -** values. This function populates the array with values required to -** "rollback" the write position of the WAL handle back to the current +/* +** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 +** values. This function populates the array with values required to +** "rollback" the write position of the WAL handle back to the current ** point in the event of a savepoint rollback (via WalSavepointUndo()). */ SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){ assert( pWal->writeLock ); aWalData[0] = pWal->hdr.mxFrame; @@ -68901,11 +57806,11 @@ aWalData[1] = pWal->hdr.aFrameCksum[0]; aWalData[2] = pWal->hdr.aFrameCksum[1]; aWalData[3] = pWal->nCkpt; } -/* +/* ** Move the write position of the WAL back to the point identified by ** the values in the aWalData[] array. aWalData must point to an array ** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated ** by a call to WalSavepoint(). */ @@ -68926,14 +57831,11 @@ if( aWalData[0]hdr.mxFrame ){ pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; - SEH_TRY { - walCleanupHash(pWal); - } - SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + walCleanupHash(pWal); } return rc; } @@ -68979,11 +57881,11 @@ walUnlockShared(pWal, WAL_READ_LOCK(0)); pWal->readLock = -1; cnt = 0; do{ int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1, &cnt); + rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); }while( rc==WAL_RETRY ); assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ testcase( (rc&0xff)==SQLITE_IOERR ); testcase( rc==SQLITE_PROTOCOL ); testcase( rc==SQLITE_OK ); @@ -69024,12 +57926,12 @@ rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset); if( rc ) return rc; iOffset += iFirstAmt; iAmt -= iFirstAmt; pContent = (void*)(iFirstAmt + (char*)pContent); - assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 ); - rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags)); + assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); + rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK); if( iAmt==0 || rc ) return rc; } rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); return rc; } @@ -69044,11 +57946,15 @@ sqlite3_int64 iOffset /* Byte offset at which to write */ ){ int rc; /* Result code from subfunctions */ void *pData; /* Data actually written */ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ +#if defined(SQLITE_HAS_CODEC) + if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT; +#else pData = pPage->pData; +#endif walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); if( rc ) return rc; /* Write the page data */ rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame)); @@ -69106,15 +58012,15 @@ sqlite3_free(aBuf); return rc; } -/* +/* ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). */ -static int walFrames( +SQLITE_PRIVATE int sqlite3WalFrames( Wal *pWal, /* Wal handle to write to */ int szPage, /* Database page-size in bytes */ PgHdr *pList, /* List of dirty pages to write */ Pgno nTruncate, /* Database size after this commit */ int isCommit, /* True if this is a commit */ @@ -69173,11 +58079,11 @@ if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt); memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); sqlite3Put4byte(&aWalHdr[24], aCksum[0]); sqlite3Put4byte(&aWalHdr[28], aCksum[1]); - + pWal->szPage = szPage; pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; pWal->hdr.aFrameCksum[0] = aCksum[0]; pWal->hdr.aFrameCksum[1] = aCksum[1]; pWal->truncateOnCommit = 1; @@ -69191,20 +58097,18 @@ /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise ** an out-of-order write following a WAL restart could result in ** database corruption. See the ticket: ** - ** https://sqlite.org/src/info/ff5be73dee + ** http://localhost:591/sqlite/info/ff5be73dee */ - if( pWal->syncHeader ){ - rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); + if( pWal->syncHeader && sync_flags ){ + rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK); if( rc ) return rc; } } - if( (int)pWal->szPage!=szPage ){ - return SQLITE_CORRUPT_BKPT; /* TH3 test case: cov1/corrupt155.test */ - } + assert( (int)pWal->szPage==szPage ); /* Setup information needed to write frames into the WAL */ w.pWal = pWal; w.pFd = pWal->pWalFd; w.iSyncPoint = 0; @@ -69217,23 +58121,27 @@ for(p=pList; p; p=p->pDirty){ int nDbSize; /* 0 normally. Positive == commit flag */ /* Check if this page has already been written into the wal file by ** the current transaction. If so, overwrite the existing frame and - ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that + ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that ** checksums must be recomputed when the transaction is committed. */ if( iFirst && (p->pDirty || isCommit==0) ){ u32 iWrite = 0; - VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); + VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); assert( rc==SQLITE_OK || iWrite==0 ); if( iWrite>=iFirst ){ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; void *pData; if( pWal->iReCksum==0 || iWriteiReCksum ){ pWal->iReCksum = iWrite; } +#if defined(SQLITE_HAS_CODEC) + if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM; +#else pData = p->pData; +#endif rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff); if( rc ) return rc; p->flags &= ~PGHDR_WAL_APPEND; continue; } @@ -69267,11 +58175,11 @@ ** final frame is repeated (with its commit mark) until the next sector ** boundary is crossed. Only the part of the WAL prior to the last ** sector boundary is synced; the part of the last frame that extends ** past the sector boundary is written after the sync. */ - if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){ + if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){ int bSync = 1; if( pWal->padToSectorBoundary ){ int sectorSize = sqlite3SectorSize(pWal->pWalFd); w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; bSync = (w.iSyncPoint==iOffset); @@ -69279,16 +58187,15 @@ while( iOffsettruncateOnCommit = 0; } - /* Append data to the wal-index. It is not necessary to lock the + /* Append data to the wal-index. It is not necessary to lock the ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index ** guarantees that there are no other writers, and no data that may ** be in use by existing readers is being overwritten. */ iFrame = pWal->hdr.mxFrame; @@ -69312,11 +58219,10 @@ for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){ if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue; iFrame++; rc = walIndexAppend(pWal, iFrame, p->pgno); } - assert( pLast!=0 || nExtra==0 ); while( rc==SQLITE_OK && nExtra>0 ){ iFrame++; nExtra--; rc = walIndexAppend(pWal, iFrame, pLast->pgno); } @@ -69340,34 +58246,11 @@ WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); return rc; } -/* -** Write a set of frames to the log. The caller must hold the write-lock -** on the log file (obtained using sqlite3WalBeginWriteTransaction()). -** -** The difference between this function and walFrames() is that this -** function wraps walFrames() in an SEH_TRY{...} block. -*/ -SQLITE_PRIVATE int sqlite3WalFrames( - Wal *pWal, /* Wal handle to write to */ - int szPage, /* Database page-size in bytes */ - PgHdr *pList, /* List of dirty pages to write */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit, /* True if this is a commit */ - int sync_flags /* Flags to pass to OsSync() (or 0) */ -){ - int rc; - SEH_TRY { - rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - return rc; -} - -/* +/* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. ** ** Obtain a CHECKPOINT lock and then backfill as much information as ** we can from WAL into the database. @@ -69400,107 +58283,85 @@ assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); - /* Enable blocking locks, if possible. */ - sqlite3WalDb(pWal, db); - if( xBusy2 ) (void)walEnableBlocking(pWal); - - /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive - ** "checkpoint" lock on the database file. - ** EVIDENCE-OF: R-10421-19736 If any other process is running a - ** checkpoint operation at the same time, the lock cannot be obtained and - ** SQLITE_BUSY is returned. - ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, - ** it will not be invoked in this case. - */ + /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive + ** "checkpoint" lock on the database file. */ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - testcase( rc==SQLITE_BUSY ); - testcase( rc!=SQLITE_OK && xBusy2!=0 ); - if( rc==SQLITE_OK ){ - pWal->ckptLock = 1; - - /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and - ** TRUNCATE modes also obtain the exclusive "writer" lock on the database - ** file. - ** - ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained - ** immediately, and a busy-handler is configured, it is invoked and the - ** writer lock retried until either the busy-handler returns 0 or the - ** lock is successfully obtained. - */ - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - }else if( rc==SQLITE_BUSY ){ - eMode2 = SQLITE_CHECKPOINT_PASSIVE; - xBusy2 = 0; - rc = SQLITE_OK; - } - } - } - + if( rc ){ + /* EVIDENCE-OF: R-10421-19736 If any other process is running a + ** checkpoint operation at the same time, the lock cannot be obtained and + ** SQLITE_BUSY is returned. + ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, + ** it will not be invoked in this case. + */ + testcase( rc==SQLITE_BUSY ); + testcase( xBusy!=0 ); + return rc; + } + pWal->ckptLock = 1; + + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and + ** TRUNCATE modes also obtain the exclusive "writer" lock on the database + ** file. + ** + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained + ** immediately, and a busy-handler is configured, it is invoked and the + ** writer lock retried until either the busy-handler returns 0 or the + ** lock is successfully obtained. + */ + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + }else if( rc==SQLITE_BUSY ){ + eMode2 = SQLITE_CHECKPOINT_PASSIVE; + xBusy2 = 0; + rc = SQLITE_OK; + } + } /* Read the wal-index header. */ - SEH_TRY { - if( rc==SQLITE_OK ){ - /* For a passive checkpoint, do not re-enable blocking locks after - ** reading the wal-index header. A passive checkpoint should not block - ** or invoke the busy handler. The only lock such a checkpoint may - ** attempt to obtain is a lock on a read-slot, and it should give up - ** immediately and do a partial checkpoint if it cannot obtain it. */ - walDisableBlocking(pWal); - rc = walIndexReadHdr(pWal, &isChanged); - if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); - } - } - - /* Copy data from the log to the database file. */ - if( rc==SQLITE_OK ){ - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); - } - - /* If no error occurred, set the output variables. */ - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; - SEH_INJECT_FAULT; - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); - } - } - } - SEH_EXCEPT( rc = walHandleException(pWal); ) + if( rc==SQLITE_OK ){ + rc = walIndexReadHdr(pWal, &isChanged); + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + } + } + + /* Copy data from the log to the database file. */ + if( rc==SQLITE_OK ){ + + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + } + + /* If no error occurred, set the output variables. */ + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); + } + } if( isChanged ){ - /* If a new wal-index header was loaded before the checkpoint was + /* If a new wal-index header was loaded before the checkpoint was ** performed, then the pager-cache associated with pWal is now ** out of date. So zero the cached wal-index header to ensure that ** next time the pager opens a snapshot on this database it knows that ** the cache needs to be reset. */ memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); } - walDisableBlocking(pWal); - sqlite3WalDb(pWal, 0); - /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); - if( pWal->ckptLock ){ - walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); - pWal->ckptLock = 0; - } + walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); + pWal->ckptLock = 0; WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; -#endif return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); } /* Return the value to pass to a sqlite3_wal_hook callback, the ** number of frames in the WAL at the point of the last commit since @@ -69526,11 +58387,11 @@ ** or if the acquisition of the lock fails, then return 0. If the ** transition out of exclusive-mode is successful, return 1. This ** operation must occur while the pager is still holding the exclusive ** lock on the main database file. ** -** If op is one, then change from locking_mode=NORMAL into +** If op is one, then change from locking_mode=NORMAL into ** locking_mode=EXCLUSIVE. This means that the pWal->readLock must ** be released. Return 1 if the transition is made and 0 if the ** WAL is already in exclusive-locking mode - meaning that this ** routine is a no-op. The pager must already hold the exclusive lock ** on the main database file before invoking this operation. @@ -69543,48 +58404,46 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ int rc; assert( pWal->writeLock==0 ); assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 ); - /* pWal->readLock is usually set, but might be -1 if there was a - ** prior error while attempting to acquire are read-lock. This cannot + /* pWal->readLock is usually set, but might be -1 if there was a + ** prior error while attempting to acquire are read-lock. This cannot ** happen if the connection is actually in exclusive mode (as no xShmLock ** locks are taken in this case). Nor should the pager attempt to ** upgrade to exclusive-mode following such an error. */ -#ifndef SQLITE_USE_SEH assert( pWal->readLock>=0 || pWal->lockError ); -#endif assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); if( op==0 ){ - if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ - pWal->exclusiveMode = WAL_NORMAL_MODE; + if( pWal->exclusiveMode ){ + pWal->exclusiveMode = 0; if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ - pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; + pWal->exclusiveMode = 1; } - rc = pWal->exclusiveMode==WAL_NORMAL_MODE; + rc = pWal->exclusiveMode==0; }else{ /* Already in locking_mode=NORMAL */ rc = 0; } }else if( op>0 ){ - assert( pWal->exclusiveMode==WAL_NORMAL_MODE ); + assert( pWal->exclusiveMode==0 ); assert( pWal->readLock>=0 ); walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); - pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; + pWal->exclusiveMode = 1; rc = 1; }else{ - rc = pWal->exclusiveMode==WAL_NORMAL_MODE; + rc = pWal->exclusiveMode==0; } return rc; } -/* +/* ** Return true if the argument is non-NULL and the WAL module is using ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the -** WAL module is using shared-memory, return false. +** WAL module is using shared-memory, return false. */ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); } @@ -69615,31 +58474,15 @@ return rc; } /* Try to open on pSnapshot when the next read-transaction starts */ -SQLITE_PRIVATE void sqlite3WalSnapshotOpen( - Wal *pWal, - sqlite3_snapshot *pSnapshot -){ - if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){ - /* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In - ** this case set the bGetSnapshot flag so that if the call to - ** sqlite3_snapshot_get() is about to read transaction on this wal - ** file, it does not take read-lock 0 if the wal file has been completely - ** checkpointed. Taking read-lock 0 would work, but then it would be - ** possible for a subsequent writer to destroy the snapshot even while - ** this connection is holding its read-transaction open. This is contrary - ** to user expectations, so we avoid it by not taking read-lock 0. */ - pWal->bGetSnapshot = 1; - }else{ - pWal->pSnapshot = (WalIndexHdr*)pSnapshot; - pWal->bGetSnapshot = 0; - } -} - -/* +SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){ + pWal->pSnapshot = (WalIndexHdr*)pSnapshot; +} + +/* ** Return a +ve value if snapshot p1 is newer than p2. A -ve value if ** p1 is older than p2 and zero if p1 and p2 are the same snapshot. */ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ WalIndexHdr *pHdr1 = (WalIndexHdr*)p1; @@ -69651,50 +58494,10 @@ if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1; if( pHdr1->mxFramemxFrame ) return -1; if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1; return 0; } - -/* -** The caller currently has a read transaction open on the database. -** This function takes a SHARED lock on the CHECKPOINTER slot and then -** checks if the snapshot passed as the second argument is still -** available. If so, SQLITE_OK is returned. -** -** If the snapshot is not available, SQLITE_ERROR is returned. Or, if -** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error -** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER -** lock is released before returning. -*/ -SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ - int rc; - SEH_TRY { - rc = walLockShared(pWal, WAL_CKPT_LOCK); - if( rc==SQLITE_OK ){ - WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; - if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - || pNew->mxFramenBackfillAttempted - ){ - rc = SQLITE_ERROR_SNAPSHOT; - walUnlockShared(pWal, WAL_CKPT_LOCK); - } - } - } - SEH_EXCEPT( rc = walHandleException(pWal); ) - return rc; -} - -/* -** Release a lock obtained by an earlier successful call to -** sqlite3WalSnapshotCheck(). -*/ -SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal){ - assert( pWal ); - walUnlockShared(pWal, WAL_CKPT_LOCK); -} - - #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_ZIPVFS /* ** If the argument is not NULL, it points to a Wal object that holds a @@ -69765,20 +58568,20 @@ ** than Key(0). All of the keys on page Ptr(1) and its subpages have ** values greater than Key(0) and less than Key(1). All of the keys ** on Ptr(N) and its subpages have values greater than Key(N-1). And ** so forth. ** -** Finding a particular key requires reading O(log(M)) pages from the +** Finding a particular key requires reading O(log(M)) pages from the ** disk where M is the number of entries in the tree. ** -** In this implementation, a single file can hold one or more separate +** In this implementation, a single file can hold one or more separate ** BTrees. Each BTree is identified by the index of its root page. The ** key and data for any entry are combined to form the "payload". A ** fixed amount of payload can be carried directly on the database ** page. If the payload is larger than the preset amount then surplus ** bytes are stored on overflow pages. The payload for an entry -** and the preceding pointer are combined to form a "Cell". Each +** and the preceding pointer are combined to form a "Cell". Each ** page has a small header which contains the Ptr(N) pointer and other ** information such as the size of key and data. ** ** FORMAT DETAILS ** @@ -69800,11 +58603,11 @@ ** 20 1 Bytes of unused space at the end of each page ** 21 1 Max embedded payload fraction (must be 64) ** 22 1 Min embedded payload fraction (must be 32) ** 23 1 Min leaf payload fraction (must be 32) ** 24 4 File change counter -** 28 4 The size of the database in pages +** 28 4 Reserved for future use ** 32 4 First freelist page ** 36 4 Number of freelist pages in the file ** 40 60 15 4-byte meta values passed to higher layers ** ** 40 4 Schema cookie @@ -69904,23 +58707,23 @@ ** the end of the page. Pointers to the cells are in the cell pointer array ** that immediately follows the page header. Cells is not necessarily ** contiguous or in order, but cell pointers are contiguous and in order. ** ** Cell content makes use of variable length integers. A variable -** length integer is 1 to 9 bytes where the lower 7 bits of each +** length integer is 1 to 9 bytes where the lower 7 bits of each ** byte are used. The integer consists of all bytes that have bit 8 set and ** the first byte with bit 8 clear. The most significant byte of the integer ** appears first. A variable-length integer may not be more than 9 bytes long. -** As a special case, all 8 bits of the 9th byte are used as data. This +** As a special case, all 8 bytes of the 9th byte are used as data. This ** allows a 64-bit integer to be encoded in 9 bytes. ** ** 0x00 becomes 0x00000000 ** 0x7f becomes 0x0000007f ** 0x81 0x00 becomes 0x00000080 ** 0x82 0x00 becomes 0x00000100 ** 0x80 0x7f becomes 0x0000007f -** 0x81 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 ** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 ** ** Variable length integers are used for rowids and to hold the number of ** bytes of key and data in a btree cell. ** @@ -69977,11 +58780,11 @@ ** ** You can change this value at compile-time by specifying a ** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The ** header must be exactly 16 bytes including the zero-terminator so ** the string itself should be 15 characters long. If you change -** the header, then your custom library will not be able to read +** the header, then your custom library will not be able to read ** databases generated by the standard tools and the standard tools ** will not be able to read databases created by your custom library. */ #ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ # define SQLITE_FILE_HEADER "SQLite format 3" @@ -69999,19 +58802,20 @@ /* ** 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. ** -** As each database page is loaded into memory, the pager allocates an +** 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 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 */ @@ -70021,31 +58825,29 @@ u8 max1bytePayload; /* min(maxLocal,127) */ 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 */ - int nFree; /* Number of free bytes on the page. -1 for unknown */ + 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[4]; /* Insert the i-th overflow cell before the aiOvfl-th ** non-overflow cell */ 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 the entire page - not just - ** the usable space, the entire page. Used to prevent - ** corruption-induced buffer overflow. */ + u8 *aDataEnd; /* One byte past the end of usable data */ u8 *aCellIdx; /* The cell index area */ u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */ DbPage *pDbPage; /* Pager page handle */ u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */ void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */ }; /* ** A linked list of the following structures is stored at BtShared.pLock. -** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor ** is opened on the table with root page BtShared.iTable. Locks are removed ** from this list when a transaction is committed or rolled back, or when ** a btree handle is closed. */ struct BtLock { @@ -70065,19 +58867,19 @@ ** this object for every database file that it has open. This structure ** is opaque to the database connection. The database connection cannot ** see the internals of this structure and only deals with pointers to ** this structure. ** -** For some database files, the same underlying database cache might be +** For some database files, the same underlying database cache might be ** shared between multiple connections. In that case, each connection ** has it own instance of this object. But each instance of this object ** points to the same BtShared object. The database cache and the ** schema associated with the database file are all contained within ** the BtShared object. ** ** All fields in this structure are accessed under sqlite3.mutex. -** The pBt pointer itself may not be changed while there exists cursors +** The pBt pointer itself may not be changed while there exists cursors ** in the referenced BtShared that point back to this Btree since those ** cursors have to go through this Btree to find their BtShared and ** they often do so without holding sqlite3.mutex. */ struct Btree { @@ -70087,16 +58889,13 @@ u8 sharable; /* True if we can share pBt with another db */ u8 locked; /* True if db currently has pBt locked */ u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */ int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ int nBackup; /* Number of backup operations reading this btree */ - u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */ + u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ Btree *pNext; /* List of other sharable Btrees from the same db */ Btree *pPrev; /* Back pointer of the same list */ -#ifdef SQLITE_DEBUG - u64 nSeek; /* Calls to sqlite3BtreeMovetoUnpacked() */ -#endif #ifndef SQLITE_OMIT_SHARED_CACHE BtLock lock; /* Object used to lock page 1 */ #endif }; @@ -70104,42 +58903,28 @@ ** Btree.inTrans may take one of the following values. ** ** If the shared-data extension is enabled, there may be multiple users ** of the Btree structure. At most one of these may open a write transaction, ** but any number may have active read transactions. -** -** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and -** SQLITE_TXN_WRITE */ #define TRANS_NONE 0 #define TRANS_READ 1 #define TRANS_WRITE 2 - -#if TRANS_NONE!=SQLITE_TXN_NONE -# error wrong numeric code for no-transaction -#endif -#if TRANS_READ!=SQLITE_TXN_READ -# error wrong numeric code for read-transaction -#endif -#if TRANS_WRITE!=SQLITE_TXN_WRITE -# error wrong numeric code for write-transaction -#endif - /* ** An instance of this object represents a single database file. -** +** ** A single database file can be in use at the same time by two ** or more database connections. When two or more connections are ** sharing the same database file, each connection has it own ** private Btree object for the file and each of those Btrees points ** to this one BtShared object. BtShared.nRef is the number of ** connections currently sharing this database file. ** ** Fields in this structure are accessed under the BtShared.mutex ** mutex, except for nRef and pNext which are accessed under the -** global SQLITE_MUTEX_STATIC_MAIN mutex. The pPager field +** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field ** may not be modified once it is initially set as long as nRef>0. ** The pSchema field may be set once under BtShared.mutex and ** thereafter is unchanged as long as nRef>0. ** ** isPending: @@ -70171,11 +58956,13 @@ u8 incrVacuum; /* True if incr-vacuum is enabled */ u8 bDoTruncate; /* True to truncate db on commit */ #endif u8 inTransaction; /* Transaction state */ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ - u8 nReserveWanted; /* Desired number of extra bytes per page */ +#ifdef SQLITE_HAS_CODEC + u8 optimalReserve; /* Desired amount of reserved space per page */ +#endif u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */ u16 minLeaf; /* Minimum local payload in a LEAFDATA table */ @@ -70192,11 +58979,10 @@ BtShared *pNext; /* Next on a list of sharable BtShared structs */ BtLock *pLock; /* List of locks held on this shared-btree struct */ Btree *pWriter; /* Btree with currently open write transaction */ #endif u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */ - int nPreformatSize; /* Size of last cell written by TransferRow() */ }; /* ** Allowed values for BtShared.btsFlags */ @@ -70244,68 +59030,59 @@ ** A single database file can be shared by two more database connections, ** but cursors cannot be shared. Each cursor is associated with a ** particular database connection identified BtCursor.pBtree.db. ** ** Fields in this structure are accessed under the BtShared.mutex -** found at self->pBt->mutex. +** found at self->pBt->mutex. ** ** skipNext meaning: -** The meaning of skipNext depends on the value of eState: -** -** eState Meaning of skipNext -** VALID skipNext is meaningless and is ignored -** INVALID skipNext is meaningless and is ignored -** SKIPNEXT sqlite3BtreeNext() is a no-op if skipNext>0 and -** sqlite3BtreePrevious() is no-op if skipNext<0. -** REQUIRESEEK restoreCursorPosition() restores the cursor to -** eState=SKIPNEXT if skipNext!=0 -** FAULT skipNext holds the cursor fault error code. +** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op. +** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op. +** eState==FAULT: Cursor fault with skipNext as error code. */ struct BtCursor { - u8 eState; /* One of the CURSOR_XXX constants (see below) */ + 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 */ + Pgno *aOverflow; /* Cache of overflow page locations */ + CellInfo info; /* A parse of the cell we are pointing at */ + 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() */ - int skipNext; /* Prev() is noop if negative. Next() is noop if positive. - ** Error code if eState==CURSOR_FAULT */ - Btree *pBtree; /* The Btree to which this cursor belongs */ - Pgno *aOverflow; /* Cache of overflow page locations */ - void *pKey; /* Saved key that was cursor last known position */ /* All fields above are zeroed when the cursor is allocated. See ** sqlite3BtreeCursorZero(). Fields that follow must be manually ** initialized. */ -#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */ - BtShared *pBt; /* The BtShared this cursor points to */ - BtCursor *pNext; /* Forms a linked list of all cursors */ - CellInfo info; /* A parse of the cell we are pointing at */ - i64 nKey; /* Size of pKey, or last integer key */ - Pgno pgnoRoot; /* The root page of this tree */ i8 iPage; /* Index of current page in apPage */ u8 curIntKey; /* Value of apPage[0]->intKey */ 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 */ + MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; /* ** Legal values for BtCursor.curFlags */ #define BTCF_WriteFlag 0x01 /* True if a write cursor */ #define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */ #define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */ -#define BTCF_AtLast 0x08 /* Cursor is pointing to the last entry */ +#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */ #define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */ #define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */ -#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */ /* ** Potential values for BtCursor.eState. ** ** CURSOR_INVALID: -** Cursor does not point to a valid entry. This can happen (for example) +** Cursor does not point to a valid entry. This can happen (for example) ** because the table is empty or because BtreeCursorFirst() has not been ** called. ** ** CURSOR_VALID: ** Cursor points to a valid entry. getPayload() etc. may be called. @@ -70314,13 +59091,13 @@ ** Cursor is valid except that the Cursor.skipNext field is non-zero ** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious() ** operation should be a no-op. ** ** CURSOR_REQUIRESEEK: -** The table that this cursor was opened on still exists, but has been +** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved -** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in +** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in ** this state, restoreCursorPosition() can be called to attempt to ** seek the cursor to the saved position. ** ** CURSOR_FAULT: ** An unrecoverable error (an I/O error or a malloc failure) has occurred @@ -70327,23 +59104,23 @@ ** on a different connection that shares the BtShared cache with this ** cursor. The error has left the cache in an inconsistent state. ** Do nothing else with this cursor. Any attempt to use the cursor ** should return the error code stored in BtCursor.skipNext */ -#define CURSOR_VALID 0 -#define CURSOR_INVALID 1 +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 #define CURSOR_SKIPNEXT 2 #define CURSOR_REQUIRESEEK 3 #define CURSOR_FAULT 4 -/* +/* ** The database page the PENDING_BYTE occupies. This page is never used. */ -#define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1)) +# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt) /* -** These macros define the location of the pointer-map entry for a +** These macros define the location of the pointer-map entry for a ** database page. The first argument to each is the number of usable ** bytes on each page of the database (often 1024). The second is the ** page number to look up in the pointer map. ** ** PTRMAP_PAGENO returns the database page number of the pointer-map @@ -70374,14 +59151,14 @@ ** new location. The pointer map is used to locate the parent page quickly. ** ** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not ** used in this case. ** -** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number +** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number ** is not used in this case. ** -** PTRMAP_OVERFLOW1: The database page is the first page in a list of +** PTRMAP_OVERFLOW1: The database page is the first page in a list of ** overflow pages. The page number identifies the page that ** contains the cell with a pointer to this overflow page. ** ** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of ** overflow pages. The page-number identifies the previous @@ -70399,55 +59176,50 @@ /* A bunch of assert() statements to check the transaction state variables ** of handle p (type Btree*) are internally consistent. */ #define btreeIntegrity(p) \ assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ - assert( p->pBt->inTransaction>=p->inTrans ); + assert( p->pBt->inTransaction>=p->inTrans ); /* ** The ISAUTOVACUUM macro is used within balance_nonroot() to determine ** if the database supports auto-vacuum or not. Because it is used -** within an expression that is an argument to another macro +** within an expression that is an argument to another macro ** (sqliteMallocRaw), it is not possible to use conditional compilation. ** So, this macro is defined instead. */ #ifndef SQLITE_OMIT_AUTOVACUUM -#define ISAUTOVACUUM(pBt) (pBt->autoVacuum) +#define ISAUTOVACUUM (pBt->autoVacuum) #else -#define ISAUTOVACUUM(pBt) 0 +#define ISAUTOVACUUM 0 #endif /* -** This structure is passed around through all the PRAGMA integrity_check -** checking routines in order to keep track of some global state information. +** This structure is passed around through all the sanity checking routines +** in order to keep track of some global state information. ** ** The aRef[] array is allocated so that there is 1 bit for each page in ** the database. As the integrity-check proceeds, for each page used in -** the database the corresponding bit is set. This allows integrity-check to -** detect pages that are used twice and orphaned pages (both of which +** the database the corresponding bit is set. This allows integrity-check to +** detect pages that are used twice and orphaned pages (both of which ** indicate corruption). */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ u8 *aPgRef; /* 1 bit per page in the db (see above) */ - Pgno nCkPage; /* Pages in the database. 0 for partial check */ + Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ - int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */ - u32 nStep; /* Number of steps into the integrity_check process */ + int mallocFailed; /* A memory allocation error has occurred */ const char *zPfx; /* Error message prefix */ - Pgno v0; /* Value for first %u substitution in zPfx (root page) */ - Pgno v1; /* Value for second %u substitution in zPfx (current pg) */ - int v2; /* Value for third %d substitution in zPfx */ + int v1, v2; /* Values for up to two %d fields in zPfx */ StrAccum errMsg; /* Accumulate the error message text here */ u32 *heap; /* Min-heap used for analyzing cell coverage */ - sqlite3 *db; /* Database connection running the check */ - i64 nRow; /* Number of rows visited in current tree */ }; /* ** Routines to read or write a two- and four-byte big-endian integer values. */ @@ -70456,11 +59228,11 @@ #define get4byte sqlite3Get4byte #define put4byte sqlite3Put4byte /* ** get2byteAligned(), unlike get2byte(), requires that its argument point to a -** two-byte aligned address. get2byteAligned() is only used for accessing the +** two-byte aligned address. get2bytea() is only used for accessing the ** cell addresses in a btree header. */ #if SQLITE_BYTEORDER==4321 # define get2byteAligned(x) (*(u16*)(x)) #elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000 @@ -70633,11 +59405,11 @@ ** against all schemas and we do not want those schemas being ** reset out from under us. ** ** There is a corresponding leave-all procedures. ** -** Enter the mutexes in ascending order by BtShared pointer address +** Enter the mutexes in accending order by BtShared pointer address ** to avoid the possibility of deadlock when two threads with ** two or more btrees in common both try to lock all their btrees ** at the same instant. */ static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ @@ -70650,14 +59422,14 @@ if( p && p->sharable ){ sqlite3BtreeEnter(p); skipOk = 0; } } - db->noSharedCache = skipOk; + db->skipBtreeMutex = skipOk; } SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - if( db->noSharedCache==0 ) btreeEnterAll(db); + if( db->skipBtreeMutex==0 ) btreeEnterAll(db); } static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ int i; Btree *p; assert( sqlite3_mutex_held(db->mutex) ); @@ -70665,11 +59437,11 @@ p = db->aDb[i].pBt; if( p ) sqlite3BtreeLeave(p); } } SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ - if( db->noSharedCache==0 ) btreeLeaveAll(db); + if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); } #ifndef NDEBUG /* ** Return true if the current thread holds the database connection @@ -70707,11 +59479,10 @@ ** db using sqlite3SchemaToIndex(). */ SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ Btree *p; assert( db!=0 ); - if( db->pVfs==0 && db->nDb==0 ) return 1; if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema); assert( iDb>=0 && iDbnDb ); if( !sqlite3_mutex_held(db->mutex) ) return 0; if( iDb==1 ) return 1; p = db->aDb[iDb].pBt; @@ -70745,14 +59516,14 @@ } #endif /* if SQLITE_THREADSAFE */ #ifndef SQLITE_OMIT_INCRBLOB /* -** Enter a mutex on a Btree given a cursor owned by that Btree. +** Enter a mutex on a Btree given a cursor owned by that Btree. ** -** These entry points are used by incremental I/O only. Enter() is required -** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not +** These entry points are used by incremental I/O only. Enter() is required +** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not ** the build is threadsafe. Leave() is only required by threadsafe builds. */ SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){ sqlite3BtreeEnter(pCur->pBtree); } @@ -70818,11 +59589,11 @@ #define BTALLOC_ANY 0 /* Allocate any page */ #define BTALLOC_EXACT 1 /* Allocate exact page if possible */ #define BTALLOC_LE 2 /* Allocate any page <= the parameter */ /* -** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not +** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not ** defined, or 0 if it is. For example: ** ** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum); */ #ifndef SQLITE_OMIT_AUTOVACUUM @@ -70833,14 +59604,14 @@ #ifndef SQLITE_OMIT_SHARED_CACHE /* ** A list of BtShared objects that are eligible for participation ** in shared cache. This variable has file scope during normal builds, -** but the test harness needs to access it so we make it global for +** but the test harness needs to access it so we make it global for ** test builds. ** -** Access to this variable is protected by SQLITE_MUTEX_STATIC_MAIN. +** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER. */ #ifdef SQLITE_TEST SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; #else static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; @@ -70868,11 +59639,11 @@ ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(), ** and clearAllSharedCacheTableLocks() ** manipulate entries in the BtShared.pLock linked list used to store ** shared-cache table level locks. If the library is compiled with the ** shared-cache feature disabled, then there is only ever one user - ** of each BtShared structure and so this locking is not necessary. + ** of each BtShared structure and so this locking is not necessary. ** So define the lock related functions as no-ops. */ #define querySharedCacheTableLock(a,b,c) SQLITE_OK #define setSharedCacheTableLock(a,b,c) SQLITE_OK #define clearAllSharedCacheTableLocks(a) @@ -70879,103 +59650,25 @@ #define downgradeAllSharedCacheTableLocks(a) #define hasSharedCacheTableLock(a,b,c,d) 1 #define hasReadConflicts(a, b) 0 #endif -#ifdef SQLITE_DEBUG -/* -** Return and reset the seek counter for a Btree object. -*/ -SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){ - u64 n = pBt->nSeek; - pBt->nSeek = 0; - return n; -} -#endif - -/* -** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single -** (MemPage*) as an argument. The (MemPage*) must not be NULL. -** -** 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 %u of %s", - 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 - -/* Default value for SHARED_LOCK_TRACE macro if shared-cache is disabled -** or if the lock tracking is disabled. This is always the value for -** release builds. -*/ -#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) /*no-op*/ - #ifndef SQLITE_OMIT_SHARED_CACHE -#if 0 -/* ^---- Change to 1 and recompile to enable shared-lock tracing -** for debugging purposes. -** -** Print all shared-cache locks on a BtShared. Debugging use only. -*/ -static void sharedLockTrace( - BtShared *pBt, - const char *zMsg, - int iRoot, - int eLockType -){ - BtLock *pLock; - if( iRoot>0 ){ - printf("%s-%p %u%s:", zMsg, pBt, iRoot, eLockType==READ_LOCK?"R":"W"); - }else{ - printf("%s-%p:", zMsg, pBt); - } - for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ - printf(" %p/%u%s", pLock->pBtree, pLock->iTable, - pLock->eLock==READ_LOCK ? "R" : "W"); - while( pLock->pNext && pLock->pBtree==pLock->pNext->pBtree ){ - pLock = pLock->pNext; - printf(",%u%s", pLock->iTable, pLock->eLock==READ_LOCK ? "R" : "W"); - } - } - printf("\n"); - fflush(stdout); -} -#undef SHARED_LOCK_TRACE -#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) sharedLockTrace(X,MSG,TAB,TYPE) -#endif /* Shared-lock tracing */ - #ifdef SQLITE_DEBUG /* **** This function is only used as part of an assert() statement. *** ** -** Check to see if pBtree holds the required locks to read or write to the +** Check to see if pBtree holds the required locks to read or write to the ** table with root page iRoot. Return 1 if it does and 0 if not. ** -** For example, when writing to a table with root-page iRoot via +** For example, when writing to a table with root-page iRoot via ** Btree connection pBtree: ** ** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) ); ** -** When writing to an index that resides in a sharable database, the +** When writing to an index that resides in a sharable database, the ** caller should have first obtained a lock specifying the root page of ** the corresponding table. This makes things a bit more complicated, ** as this module treats each table as a separate structure. To determine ** the table corresponding to the index being written, this ** function has to search through the database schema. @@ -70993,11 +59686,11 @@ Schema *pSchema = (Schema *)pBtree->pBt->pSchema; Pgno iTab = 0; BtLock *pLock; /* If this database is not shareable, or if the client is reading - ** and has the read-uncommitted flag set, then no lock is required. + ** and has the read-uncommitted flag set, then no lock is required. ** Return true immediately. */ if( (pBtree->sharable==0) || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit)) ){ @@ -71017,37 +59710,33 @@ ** b-trees, this is just the root page of the b-tree being read or ** written. For index b-trees, it is the root page of the associated ** table. */ if( isIndex ){ HashElem *p; - int bSeen = 0; for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ Index *pIdx = (Index *)sqliteHashData(p); - if( pIdx->tnum==iRoot ){ - if( bSeen ){ + if( pIdx->tnum==(int)iRoot ){ + if( iTab ){ /* Two or more indexes share the same root page. There must ** be imposter tables. So just return true. The assert is not ** useful in that case. */ return 1; } iTab = pIdx->pTable->tnum; - bSeen = 1; } } }else{ iTab = iRoot; } - SHARED_LOCK_TRACE(pBtree->pBt,"hasLock",iRoot,eLockType); - - /* Search for the required lock. Either a write-lock on root-page iTab, a + /* Search for the required lock. Either a write-lock on root-page iTab, a ** write-lock on the schema table, or (if the client is reading) a ** read-lock on iTab will suffice. Return 1 if any of these are found. */ for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){ - if( pLock->pBtree==pBtree + if( pLock->pBtree==pBtree && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1)) - && pLock->eLock>=eLockType + && pLock->eLock>=eLockType ){ return 1; } } @@ -71076,11 +59765,11 @@ ** assert( !hasReadConflicts(pBtree, iRoot) ); */ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ BtCursor *p; for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - if( p->pgnoRoot==iRoot + if( p->pgnoRoot==iRoot && p->pBtree!=pBtree && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit) ){ return 1; } @@ -71088,11 +59777,11 @@ return 0; } #endif /* #ifdef SQLITE_DEBUG */ /* -** Query to see if Btree handle p may obtain a lock of type eLock +** Query to see if Btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return ** SQLITE_OK if the lock may be obtained (by calling ** setSharedCacheTableLock()), or SQLITE_LOCKED if not. */ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){ @@ -71101,18 +59790,18 @@ assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 ); - + /* If requesting a write-lock, then the Btree must have an open write - ** transaction on this file. And, obviously, for this to be so there + ** transaction on this file. And, obviously, for this to be so there ** must be an open write transaction on the file itself. */ assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) ); assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE ); - + /* This routine is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } @@ -71123,11 +59812,11 @@ sqlite3ConnectionBlocked(p->db, pBt->pWriter->db); return SQLITE_LOCKED_SHAREDCACHE; } for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - /* The condition (pIter->eLock!=eLock) in the following if(...) + /* The condition (pIter->eLock!=eLock) in the following if(...) ** statement is a simplification of: ** ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK) ** ** since we know that if eLock==WRITE_LOCK, then no other connection @@ -71150,11 +59839,11 @@ #endif /* !SQLITE_OMIT_SHARED_CACHE */ #ifndef SQLITE_OMIT_SHARED_CACHE /* ** Add a lock on the table with root-page iTable to the shared-btree used -** by Btree handle p. Parameter eLock must be either READ_LOCK or +** by Btree handle p. Parameter eLock must be either READ_LOCK or ** WRITE_LOCK. ** ** This function assumes the following: ** ** (a) The specified Btree object p is connected to a sharable @@ -71162,31 +59851,29 @@ ** ** (b) No other Btree objects hold a lock that conflicts ** with the requested lock (i.e. querySharedCacheTableLock() has ** already been called and returned SQLITE_OK). ** -** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM +** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM ** is returned if a malloc attempt fails. */ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pLock = 0; BtLock *pIter; - SHARED_LOCK_TRACE(pBt,"setLock", iTable, eLock); - assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); /* A connection with the read-uncommitted flag set will never try to ** obtain a read-lock using this function. The only read-lock obtained - ** by a connection in read-uncommitted mode is on the sqlite_schema + ** 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_ReadUncommit) || eLock==WRITE_LOCK ); - /* This function should only be called on a sharable b-tree after it + /* This function should only be called on a sharable b-tree after it ** has been determined that no other b-tree holds a conflicting lock. */ assert( p->sharable ); assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); /* First search the list for an existing lock on this table. */ @@ -71227,11 +59914,11 @@ #ifndef SQLITE_OMIT_SHARED_CACHE /* ** Release all the table locks (locks obtained via calls to ** the setSharedCacheTableLock() procedure) held by Btree object p. ** -** This function assumes that Btree p has an open read or write +** This function assumes that Btree p has an open read or write ** transaction. If it does not, then the BTS_PENDING flag ** may be incorrectly cleared. */ static void clearAllSharedCacheTableLocks(Btree *p){ BtShared *pBt = p->pBt; @@ -71239,12 +59926,10 @@ assert( sqlite3BtreeHoldsMutex(p) ); assert( p->sharable || 0==*ppIter ); assert( p->inTrans>0 ); - SHARED_LOCK_TRACE(pBt, "clearAllLocks", 0, 0); - while( *ppIter ){ BtLock *pLock = *ppIter; assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree ); assert( pLock->pBtree->inTrans>=pLock->eLock ); if( pLock->pBtree==p ){ @@ -71261,11 +59946,11 @@ assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter ); if( pBt->pWriter==p ){ pBt->pWriter = 0; pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); }else if( pBt->nTransaction==2 ){ - /* This function is called when Btree p is concluding its + /* This function is called when Btree p is concluding its ** transaction. If there currently exists a writer, and p is not ** that writer, then the number of locks held by connections other ** than the writer must be about to drop to zero. In this case ** set the BTS_PENDING flag to 0. ** @@ -71279,13 +59964,10 @@ /* ** This function changes all write-locks held by Btree p into read-locks. */ static void downgradeAllSharedCacheTableLocks(Btree *p){ BtShared *pBt = p->pBt; - - SHARED_LOCK_TRACE(pBt, "downgradeLocks", 0, 0); - if( pBt->pWriter==p ){ BtLock *pLock; pBt->pWriter = 0; pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ @@ -71295,13 +59977,11 @@ } } #endif /* SQLITE_OMIT_SHARED_CACHE */ -static void releasePage(MemPage *pPage); /* Forward reference */ -static void releasePageOne(MemPage *pPage); /* Forward reference */ -static void releasePageNotNull(MemPage *pPage); /* Forward reference */ +static void releasePage(MemPage *pPage); /* Forward reference */ /* ***** This routine is used inside of assert() only **** ** ** Verify that the cursor holds the mutex on its BtShared @@ -71310,11 +59990,11 @@ static int cursorHoldsMutex(BtCursor *p){ return sqlite3_mutex_held(p->pBt->mutex); } /* Verify that the cursor and the BtShared agree about what is the current -** database connetion. This is important in shared-cache mode. If the database +** database connetion. This is important in shared-cache mode. If the database ** connection pointers get out-of-sync, it is possible for routines like ** btreeInitPage() to reference an stale connection pointer that references a ** a connection that has already closed. This routine is used inside assert() ** statements only and for the purpose of double-checking that the btree code ** does keep the database connection pointers up-to-date. @@ -71362,11 +60042,11 @@ 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 */ ){ BtCursor *p; - assert( pBtree->hasIncrblobCur ); + if( pBtree->hasIncrblobCur==0 ) return; assert( sqlite3BtreeHoldsMutex(pBtree) ); pBtree->hasIncrblobCur = 0; for(p=pBtree->pBt->pCursor; p; p=p->pNext){ if( (p->curFlags & BTCF_Incrblob)!=0 ){ pBtree->hasIncrblobCur = 1; @@ -71381,12 +60061,12 @@ /* Stub function when INCRBLOB is omitted */ #define invalidateIncrblobCursors(w,x,y,z) #endif /* SQLITE_OMIT_INCRBLOB */ /* -** Set bit pgno of the BtShared.pHasContent bitvec. This is called -** when a page that previously contained data becomes a free-list leaf +** Set bit pgno of the BtShared.pHasContent bitvec. This is called +** when a page that previously contained data becomes a free-list leaf ** page. ** ** The BtShared.pHasContent bitvec exists to work around an obscure ** bug caused by the interaction of two useful IO optimizations surrounding ** free-list leaf pages: @@ -71408,11 +60088,11 @@ ** it is moved to the free-list and it is also not journalled when it ** is extracted from the free-list and reused, then the original data ** may be lost. In the event of a rollback, it may not be possible ** to restore the database to its original configuration. ** -** The solution is the BtShared.pHasContent bitvec. Whenever a page is +** The solution is the BtShared.pHasContent bitvec. Whenever a page is ** moved to become a free-list leaf page, the corresponding bit is ** set in the bitvec. Whenever a leaf page is extracted from the free-list, ** optimization 2 above is omitted if the corresponding bit is already ** set in BtShared.pHasContent. The contents of the bitvec are cleared ** at the end of every transaction. @@ -71439,11 +60119,11 @@ ** free-list for reuse. It returns false if it is safe to retrieve the ** page from the pager layer with the 'no-content' flag set. True otherwise. */ static int btreeGetHasContent(BtShared *pBt, Pgno pgno){ Bitvec *p = pBt->pHasContent; - return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno)); + return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno))); } /* ** Clear (destroy) the BtShared.pHasContent bitvec. This should be ** invoked at the conclusion of each write-transaction. @@ -71456,30 +60136,28 @@ /* ** Release all of the apPage[] pages for a cursor. */ static void btreeReleaseAllCursorPages(BtCursor *pCur){ int i; - if( pCur->iPage>=0 ){ - for(i=0; iiPage; i++){ - releasePageNotNull(pCur->apPage[i]); - } - releasePageNotNull(pCur->pPage); - pCur->iPage = -1; + for(i=0; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); + pCur->apPage[i] = 0; } + pCur->iPage = -1; } /* ** The cursor passed as the only argument must point to a valid entry ** when this function is called (i.e. have eState==CURSOR_VALID). This ** function saves the current cursor key in variables pCur->nKey and -** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error +** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error ** code otherwise. ** ** If the cursor is open on an intkey table, then the integer key ** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to -** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is -** set to point to a malloced buffer pCur->nKey bytes in size containing +** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is +** set to point to a malloced buffer pCur->nKey bytes in size containing ** the key. */ static int saveCursorKey(BtCursor *pCur){ int rc = SQLITE_OK; assert( CURSOR_VALID==pCur->eState ); @@ -71488,23 +60166,17 @@ if( pCur->curIntKey ){ /* Only the rowid is required for a table btree */ pCur->nKey = sqlite3BtreeIntegerKey(pCur); }else{ - /* For an index btree, save the complete key content. It is possible - ** that the current key is corrupt. In that case, it is possible that - ** the sqlite3VdbeRecordUnpack() function may overread the buffer by - ** up to the size of 1 varint plus 1 8-byte value when the cursor - ** position is restored. Hence the 17 bytes of padding allocated - ** below. */ + /* For an index btree, save the complete key content */ void *pKey; pCur->nKey = sqlite3BtreePayloadSize(pCur); - pKey = sqlite3Malloc( pCur->nKey + 9 + 8 ); + pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey); if( rc==SQLITE_OK ){ - memset(((u8*)pKey)+pCur->nKey, 0, 9+8); pCur->pKey = pKey; }else{ sqlite3_free(pKey); } }else{ @@ -71514,26 +60186,23 @@ assert( !pCur->curIntKey || !pCur->pKey ); return rc; } /* -** Save the current cursor position in the variables BtCursor.nKey +** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ** ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) -** prior to calling this routine. +** prior to calling this routine. */ static int saveCursorPosition(BtCursor *pCur){ int rc; assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); - if( pCur->curFlags & BTCF_Pinned ){ - return SQLITE_CONSTRAINT_PINNED; - } if( pCur->eState==CURSOR_SKIPNEXT ){ pCur->eState = CURSOR_VALID; }else{ pCur->skipNext = 0; } @@ -71557,11 +60226,11 @@ ** the location in the btree is remembered in such a way that it can be ** moved back to the same spot after the btree has been modified. This ** routine is called just before cursor pExcept is used to modify the ** table, for example in BtreeDelete() or BtreeInsert(). ** -** If there are two or more cursors on the same btree, then all such +** If there are two or more cursors on the same btree, then all such ** cursors should have their BTCF_Multiple flag set. The btreeCursor() ** routine enforces that rule. This routine only needs to be called in ** the uncommon case when pExpect has the BTCF_Multiple flag set. ** ** If pExpect!=NULL and if no other cursors are found on the same root-page, @@ -71600,11 +60269,11 @@ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; } }else{ - testcase( p->iPage>=0 ); + testcase( p->iPage>0 ); btreeReleaseAllCursorPages(p); } } p = p->pNext; }while( p ); @@ -71622,11 +60291,11 @@ } /* ** In this version of BtreeMoveto, pKey is a packed index record ** such as is generated by the OP_MakeRecord opcode. Unpack the -** record and then call sqlite3BtreeIndexMoveto() to do the work. +** record and then call BtreeMovetoUnpacked() to do the work. */ static int btreeMoveto( BtCursor *pCur, /* Cursor open on the btree to be searched */ const void *pKey, /* Packed key if the btree is an index */ i64 nKey, /* Integer key for tables. Size of pKey for indices */ @@ -71635,54 +60304,51 @@ ){ int rc; /* Status code */ UnpackedRecord *pIdxKey; /* Unpacked index key */ if( pKey ){ - KeyInfo *pKeyInfo = pCur->pKeyInfo; assert( nKey==(i64)(int)nKey ); - pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); + pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; - sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); - if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes); + sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); + if( pIdxKey->nField==0 ){ + rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno); + goto moveto_done; } - sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); }else{ pIdxKey = 0; - rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes); + } + rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); +moveto_done: + if( pIdxKey ){ + sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); } return rc; } /* ** Restore the cursor to the position it was in (or as close to as possible) -** when saveCursorPosition() was called. Note that this call deletes the +** when saveCursorPosition() was called. Note that this call deletes the ** saved position info stored by saveCursorPosition(), so there can be -** at most one effective restoreCursorPosition() call after each +** at most one effective restoreCursorPosition() call after each ** saveCursorPosition(). */ static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; - int skipNext = 0; + int skipNext; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - if( sqlite3FaultSim(410) ){ - rc = SQLITE_IOERR; - }else{ - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); - } + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); - if( skipNext ) pCur->skipNext = skipNext; + pCur->skipNext |= skipNext; if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ pCur->eState = CURSOR_SKIPNEXT; } } return rc; @@ -71704,32 +60370,17 @@ ** ** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor ** back to where it ought to be if this routine returns true. */ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ - assert( EIGHT_BYTE_ALIGNMENT(pCur) - || pCur==sqlite3BtreeFakeValidCursor() ); - assert( offsetof(BtCursor, eState)==0 ); - assert( sizeof(pCur->eState)==1 ); - return CURSOR_VALID != *(u8*)pCur; -} - -/* -** 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; + return pCur->eState!=CURSOR_VALID; } /* ** This routine restores a cursor back to its original position after it ** has been moved by some outside activity (such as a btree rebalance or -** a row having been deleted out from under the cursor). +** a row having been deleted out from under the cursor). ** ** On success, the *pDifferentRow parameter is false if the cursor is left ** pointing at exactly the same row. *pDifferntRow is the row the cursor ** was pointing to has been deleted, forcing the cursor to point to some ** nearby row. @@ -71748,10 +60399,11 @@ return rc; } if( pCur->eState!=CURSOR_VALID ){ *pDifferentRow = 1; }else{ + assert( pCur->skipNext==0 ); *pDifferentRow = 0; } return SQLITE_OK; } @@ -71761,29 +60413,12 @@ ** and number of the varargs parameters) is determined by the eHintType ** parameter. See the definitions of the BTREE_HINT_* macros for details. */ SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){ /* Used only by system that substitute their own storage engine */ -#ifdef SQLITE_DEBUG - if( ALWAYS(eHintType==BTREE_HINT_RANGE) ){ - va_list ap; - Expr *pExpr; - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3CursorRangeHintExprCheck; - va_start(ap, eHintType); - pExpr = va_arg(ap, Expr*); - w.u.aMem = va_arg(ap, Mem*); - va_end(ap); - assert( pExpr!=0 ); - assert( w.u.aMem!=0 ); - sqlite3WalkExpr(&w, pExpr); - } -#endif /* SQLITE_DEBUG */ -} -#endif /* SQLITE_ENABLE_CURSOR_HINTS */ - +} +#endif /* ** Provide flag hints to the cursor. */ SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){ @@ -71807,11 +60442,11 @@ Pgno iPtrMap, ret; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno<2 ) return 0; nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; - ret = (iPtrMap*nPagesPerMapPage) + 2; + ret = (iPtrMap*nPagesPerMapPage) + 2; if( ret==PENDING_BYTE_PAGE(pBt) ){ ret++; } return ret; } @@ -71834,11 +60469,11 @@ int rc; /* Return code from subfunctions */ if( *pRC ) return; assert( sqlite3_mutex_held(pBt->mutex) ); - /* The super-journal page number must never be used as a pointer map page */ + /* The master-journal page number must never be used as a pointer map page */ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); assert( pBt->autoVacuum ); if( key==0 ){ *pRC = SQLITE_CORRUPT_BKPT; @@ -71848,27 +60483,20 @@ rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); if( rc!=SQLITE_OK ){ *pRC = rc; return; } - if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){ - /* The first byte of the extra data is the MemPage.isInit byte. - ** If that byte is set, it means this page is also being used - ** as a btree page. */ - *pRC = SQLITE_CORRUPT_BKPT; - goto ptrmap_exit; - } offset = PTRMAP_PTROFFSET(iPtrmap, key); if( offset<0 ){ *pRC = SQLITE_CORRUPT_BKPT; goto ptrmap_exit; } assert( offset <= (int)pBt->usableSize-5 ); pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ - TRACE(("PTRMAP_UPDATE: %u->(%u,%u)\n", key, eType, parent)); + TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); *pRC= rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ pPtrmap[offset] = eType; put4byte(&pPtrmap[offset+1], parent); } @@ -71917,11 +60545,11 @@ } #else /* if defined SQLITE_OMIT_AUTOVACUUM */ #define ptrmapPut(w,x,y,z,rc) #define ptrmapGet(w,x,y,z) SQLITE_OK - #define ptrmapPutOvflPtr(x, y, z, rc) + #define ptrmapPutOvflPtr(x, y, rc) #endif /* ** Given a btree page and a cell index (0 means the first cell on ** the page, 1 means the second cell, and so forth) return a pointer @@ -71973,28 +60601,10 @@ pInfo->nLocal = (u16)minLocal; } pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4; } -/* -** Given a record with nPayload bytes of payload stored within btree -** page pPage, return the number of bytes of payload stored locally. -*/ -static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){ - int maxLocal; /* Maximum amount of payload held locally */ - maxLocal = pPage->maxLocal; - if( nPayload<=maxLocal ){ - return nPayload; - }else{ - int minLocal; /* Minimum amount of payload held locally */ - int surplus; /* Overflow payload available for local storage */ - minLocal = pPage->minLocal; - surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4); - return ( surplus <= maxLocal ) ? surplus : minLocal; - } -} - /* ** The following routines are implementations of the MemPage.xParseCell() ** method. ** ** Parse a cell content block and fill in the CellInfo structure. @@ -72057,50 +60667,32 @@ /* The next block of code is equivalent to: ** ** pIter += getVarint(pIter, (u64*)&pInfo->nKey); ** - ** The code is inlined and the loop is unrolled for performance. - ** This routine is a high-runner. + ** The code is inlined to avoid a function call. */ iKey = *pIter; if( iKey>=0x80 ){ - u8 x; - iKey = (iKey<<7) ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x10204000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); - if( x>=0x80 ){ - iKey = (iKey<<8) ^ 0x8000 ^ (*++pIter); - } - } - } - } - } - }else{ - iKey ^= 0x204000; - } - }else{ - iKey ^= 0x4000; + u8 *pEnd = &pIter[7]; + iKey &= 0x7f; + while(1){ + iKey = (iKey<<7) | (*++pIter & 0x7f); + if( (*pIter)<0x80 ) break; + if( pIter>=pEnd ){ + iKey = (iKey<<8) | *++pIter; + break; + } } } pIter++; pInfo->nKey = *(i64*)&iKey; pInfo->nPayload = nPayload; pInfo->pPayload = pIter; testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==(u32)pPage->maxLocal+1 ); + testcase( nPayload==pPage->maxLocal+1 ); if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. */ pInfo->nSize = nPayload + (u16)(pIter - pCell); @@ -72133,11 +60725,11 @@ pIter++; pInfo->nKey = nPayload; pInfo->nPayload = nPayload; pInfo->pPayload = pIter; testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==(u32)pPage->maxLocal+1 ); + testcase( nPayload==pPage->maxLocal+1 ); if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. */ pInfo->nSize = nPayload + (u16)(pIter - pCell); @@ -72163,16 +60755,14 @@ ** data area of the btree-page. The return number includes the cell ** data header and the local payload, but not any overflow page or ** the space used by the cell pointer. ** ** cellSizePtrNoPayload() => table internal nodes -** cellSizePtrTableLeaf() => table leaf nodes -** cellSizePtr() => index internal nodes -** cellSizeIdxLeaf() => index leaf nodes +** cellSizePtr() => all index nodes & table leaf nodes */ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ - u8 *pIter = pCell + 4; /* For looping over bytes of pCell */ + u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */ u8 *pEnd; /* End mark for a varint */ u32 nSize; /* Size value to return */ #ifdef SQLITE_DEBUG /* The value returned by this function should always be the same as @@ -72181,72 +60771,36 @@ ** this function verifies that this invariant is not violated. */ CellInfo debuginfo; pPage->xParseCell(pPage, pCell, &debuginfo); #endif - assert( pPage->childPtrSize==4 ); nSize = *pIter; if( nSize>=0x80 ){ pEnd = &pIter[8]; nSize &= 0x7f; do{ nSize = (nSize<<7) | (*++pIter & 0x7f); }while( *(pIter)>=0x80 && pItermaxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); - if( nSize<=pPage->maxLocal ){ - nSize += (u32)(pIter - pCell); - assert( nSize>4 ); - }else{ - int minLocal = pPage->minLocal; - nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); - testcase( nSize==pPage->maxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); - if( nSize>pPage->maxLocal ){ - nSize = minLocal; - } - nSize += 4 + (u16)(pIter - pCell); - } - assert( nSize==debuginfo.nSize || CORRUPT_DB ); - return (u16)nSize; -} -static u16 cellSizePtrIdxLeaf(MemPage *pPage, u8 *pCell){ - u8 *pIter = pCell; /* For looping over bytes of pCell */ - u8 *pEnd; /* End mark for a varint */ - u32 nSize; /* Size value to return */ - -#ifdef SQLITE_DEBUG - /* The value returned by this function should always be the same as - ** the (CellInfo.nSize) value found by doing a full parse of the - ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of - ** this function verifies that this invariant is not violated. */ - CellInfo debuginfo; - pPage->xParseCell(pPage, pCell, &debuginfo); -#endif - - assert( pPage->childPtrSize==0 ); - nSize = *pIter; - if( nSize>=0x80 ){ - pEnd = &pIter[8]; - nSize &= 0x7f; - do{ - nSize = (nSize<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pItermaxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); + if( pPage->intKey ){ + /* pIter now points at the 64-bit integer key value, a variable length + ** integer. The following block moves pIter to point at the first byte + ** past the end of the key value. */ + pEnd = &pIter[9]; + while( (*pIter++)&0x80 && pItermaxLocal ); + testcase( nSize==pPage->maxLocal+1 ); if( nSize<=pPage->maxLocal ){ nSize += (u32)(pIter - pCell); if( nSize<4 ) nSize = 4; }else{ int minLocal = pPage->minLocal; nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); testcase( nSize==pPage->maxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); + testcase( nSize==pPage->maxLocal+1 ); if( nSize>pPage->maxLocal ){ nSize = minLocal; } nSize += 4 + (u16)(pIter - pCell); } @@ -72272,62 +60826,10 @@ pEnd = pIter + 9; while( (*pIter++)&0x80 && pIterxParseCell(pPage, pCell, &debuginfo); -#endif - - nSize = *pIter; - if( nSize>=0x80 ){ - pEnd = &pIter[8]; - nSize &= 0x7f; - do{ - nSize = (nSize<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pItermaxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); - if( nSize<=pPage->maxLocal ){ - nSize += (u32)(pIter - pCell); - if( nSize<4 ) nSize = 4; - }else{ - int minLocal = pPage->minLocal; - nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); - testcase( nSize==pPage->maxLocal ); - testcase( nSize==(u32)pPage->maxLocal+1 ); - if( nSize>pPage->maxLocal ){ - nSize = minLocal; - } - nSize += 4 + (u16)(pIter - pCell); - } - assert( nSize==debuginfo.nSize || CORRUPT_DB ); - return (u16)nSize; -} #ifdef SQLITE_DEBUG /* This variation on cellSizePtr() is used inside of assert() statements ** only. */ @@ -72336,28 +60838,21 @@ } #endif #ifndef SQLITE_OMIT_AUTOVACUUM /* -** The cell pCell is currently part of page pSrc but will ultimately be part -** of pPage. (pSrc and pPage are often the same.) If pCell contains a -** pointer to an overflow page, insert an entry into the pointer-map for -** the overflow page that will be valid after pCell has been moved to pPage. +** If the cell pCell, part of page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. */ -static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ +static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ CellInfo info; if( *pRC ) return; assert( pCell!=0 ); pPage->xParseCell(pPage, pCell, &info); if( info.nLocalaDataEnd, pCell, pCell+info.nLocal) ){ - testcase( pSrc!=pPage ); - *pRC = SQLITE_CORRUPT_BKPT; - return; - } - ovfl = get4byte(&pCell[info.nSize-4]); + Pgno ovfl = get4byte(&pCell[info.nSize-4]); ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); } } #endif @@ -72386,55 +60881,58 @@ unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ unsigned char *src; /* Source of content */ int iCellFirst; /* First allowable cell index */ int iCellLast; /* Last possible cell index */ - int iCellStart; /* First cell offset in input */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - data = pPage->aData; + temp = 0; + src = data = pPage->aData; hdr = pPage->hdrOffset; cellOffset = pPage->cellOffset; nCell = pPage->nCell; - assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB ); + 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 + ** offsets to each pointer in the cell-pointer array than it is to ** reconstruct the entire page. */ if( (int)data[hdr+7]<=nMaxFrag ){ int iFree = get2byte(&data[hdr+1]); - if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); if( iFree ){ int iFree2 = get2byte(&data[iFree]); - if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); + + /* 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 ){ - if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage); + if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno); sz2 = get2byte(&data[iFree2+2]); - if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); + assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; - }else if( iFree+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); } - cbrk = top+sz; assert( cbrk+(iFree-top) <= usableSize ); memmove(&data[cbrk], &data[top], iFree-top); for(pAddr=&data[cellOffset]; pAddr0 ){ - temp = sqlite3PagerTempSpace(pPage->pBt->pPager); - memcpy(temp, data, usableSize); - src = temp; - for(i=0; iiCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( pc>=0 && pc<=iCellLast ); - size = pPage->xCellSize(pPage, &src[pc]); - cbrk -= size; - if( cbrkusableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( cbrk+size<=usableSize && cbrk>=iCellStart ); - testcase( cbrk+size==usableSize ); - testcase( pc+size==usableSize ); - put2byte(pAddr, cbrk); - memcpy(&data[cbrk], &src[pc], size); - } + for(i=0; iiCellLast ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + assert( pc>=iCellFirst && pc<=iCellLast ); + size = pPage->xCellSize(pPage, &src[pc]); + cbrk -= size; + if( cbrkusableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); + testcase( cbrk+size==usableSize ); + testcase( pc+size==usableSize ); + put2byte(pAddr, cbrk); + if( temp==0 ){ + int x; + if( cbrk==pc ) continue; + temp = sqlite3PagerTempSpace(pPage->pBt->pPager); + x = get2byte(&data[hdr+5]); + memcpy(&temp[x], &data[x], (cbrk+size) - x); + src = temp; + } + memcpy(&data[cbrk], &src[pc], size); } data[hdr+7] = 0; -defragment_out: - assert( pPage->nFree>=0 ); + defragment_out: if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); data[hdr+1] = 0; data[hdr+2] = 0; @@ -72507,65 +61006,56 @@ ** Slots on the free list that are between 1 and 3 bytes larger than nByte ** will be ignored if adding the extra space to the fragmentation count ** causes the fragmentation count to exceed 60. */ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ - const int hdr = pPg->hdrOffset; /* Offset to page header */ - u8 * const aData = pPg->aData; /* Page data */ - int iAddr = hdr + 1; /* Address of ptr to pc */ - u8 *pTmp = &aData[iAddr]; /* Temporary ptr into aData[] */ - int pc = get2byte(pTmp); /* Address of a free slot */ - int x; /* Excess size of the slot */ - int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */ - int size; /* Size of the free slot */ + const int hdr = pPg->hdrOffset; + u8 * const aData = pPg->aData; + int iAddr = hdr + 1; + int pc = get2byte(&aData[iAddr]); + int x; + int usableSize = pPg->pBt->usableSize; assert( pc>0 ); - while( pc<=maxPC ){ + 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 || pcpgno); + return 0; + } /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each ** freeblock form a big-endian integer which is the size of the freeblock ** in bytes, including the 4-byte header. */ - pTmp = &aData[pc+2]; - size = get2byte(pTmp); + size = get2byte(&aData[pc+2]); if( (x = size - nByte)>=0 ){ testcase( x==4 ); testcase( x==3 ); - if( x<4 ){ + if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){ + *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); + return 0; + }else if( x<4 ){ /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total ** number of bytes in fragments may not exceed 60. */ if( aData[hdr+7]>57 ) return 0; /* Remove the slot from the free-list. Update the number of ** fragmented bytes within the page. */ memcpy(&aData[iAddr], &aData[pc], 2); aData[hdr+7] += (u8)x; - return &aData[pc]; - }else if( x+pc > maxPC ){ - /* This slot extends off the end of the usable part of the page */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); - return 0; }else{ /* The slot remains on the free-list. Reduce its size to account - ** for the portion used by the new allocation. */ + ** for the portion used by the new allocation. */ put2byte(&aData[pc+2], x); } return &aData[pc + x]; } iAddr = pc; - pTmp = &aData[pc]; - pc = get2byte(pTmp); - if( pc<=iAddr ){ - if( pc ){ - /* The next slot in the chain comes before the current slot */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); - } - return 0; - } - } - if( pc>maxPC+nByte-4 ){ - /* The free slot chain extends off the end of the page */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); - } + pc = get2byte(&aData[pc]); + }while( pc ); + return 0; } /* ** Allocate nByte bytes of space from within the B-Tree page passed @@ -72578,18 +61068,17 @@ ** all the space together, however. This routine will avoid using ** the first two bytes past the cell pointer area since presumably this ** allocation is being made in order to insert a new cell, so we will ** also end up needing a new cell pointer. */ -static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ +static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int top; /* First byte of cell content area */ int rc = SQLITE_OK; /* Integer return code */ - u8 *pTmp; /* Temp ptr into data[] */ int gap; /* First byte of gap between cell pointers and cell content */ - + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( nByte>=0 ); /* Minimum cell size is 4 */ assert( pPage->nFree>=nByte ); @@ -72602,40 +61091,33 @@ /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size ** and the reserved space is zero (the usual value for reserved space) ** then the cell content offset of an empty page wants to be 65536. ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ - pTmp = &data[hdr+5]; - top = get2byte(pTmp); + top = get2byte(&data[hdr+5]); + assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */ if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } - }else if( top>(int)pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); } - /* If there is enough space between gap and top for one more cell pointer, - ** and if the freelist is not empty, then search the - ** freelist looking for a slot big enough to satisfy the request. + /* If there is enough space between gap and top for one more cell pointer + ** array entry offset, and if the freelist is not empty, then search the + ** freelist looking for a free slot big enough to satisfy the request. */ testcase( gap+2==top ); testcase( gap+1==top ); testcase( gap==top ); if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ u8 *pSpace = pageFindSlot(pPage, nByte, &rc); if( pSpace ){ - int g2; - assert( pSpace+nByte<=data+pPage->pBt->usableSize ); - *pIdx = g2 = (int)(pSpace-data); - if( g2<=gap ){ - return SQLITE_CORRUPT_PAGE(pPage); - }else{ - return SQLITE_OK; - } + assert( pSpace>=data && (pSpace - data)<65536 ); + *pIdx = (int)(pSpace - data); + return SQLITE_OK; }else if( rc ){ return rc; } } @@ -72643,20 +61125,19 @@ ** to see if defragmentation is necessary. */ testcase( gap+2+nByte==top ); if( gap+2+nByte>top ){ assert( pPage->nCell>0 || CORRUPT_DB ); - assert( pPage->nFree>=0 ); rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte))); if( rc ) return rc; top = get2byteNotZero(&data[hdr+5]); assert( gap+2+nByte<=top ); } /* Allocate memory from the gap in between the cell pointer array - ** and the cell content area. The btreeComputeFreeSpace() call has already + ** and the cell content area. The btreeInitPage() call has already ** validated the freelist. Given that the freelist is valid, there ** is no way that the allocation can extend off the end of the page. ** The assert() below verifies the previous sentence. */ top -= nByte; @@ -72671,101 +61152,96 @@ ** The first byte of the new free block is pPage->aData[iStart] ** and the size of the block is iSize bytes. ** ** Adjacent freeblocks are coalesced. ** -** Even though the freeblock list was checked by btreeComputeFreeSpace(), +** Note that even though the freeblock list was checked by btreeInitPage(), ** that routine will not detect overlap between cells or freeblocks. Nor -** does it detect cells or freeblocks that encroach into the reserved bytes +** does it detect cells or freeblocks that encrouch into the reserved bytes ** at the end of the page. So do additional corruption checks inside this ** routine and return SQLITE_CORRUPT if any problems are found. */ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ u16 iPtr; /* Address of ptr to next freeblock */ u16 iFreeBlk; /* Address of the next freeblock */ u8 hdr; /* Page header size. 0 or 100 */ u8 nFrag = 0; /* Reduction in fragmentation */ u16 iOrigSize = iSize; /* Original value of iSize */ - u16 x; /* Offset to cell content area */ + u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */ u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ unsigned char *data = pPage->aData; /* Page content */ - u8 *pTmp; /* Temporary ptr into data[] */ assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iSize>=4 ); /* Minimum cell size is 4 */ - assert( CORRUPT_DB || iStart<=pPage->pBt->usableSize-4 ); + assert( iStart<=iLast ); - /* The list of freeblocks must be in ascending order. Find the + /* Overwrite deleted information with zeros when the secure_delete + ** option is enabled */ + if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ + memset(&data[iStart], 0, iSize); + } + + /* The list of freeblocks must be in ascending order. Find the ** spot on the list where iStart should be inserted. */ hdr = pPage->hdrOffset; iPtr = hdr + 1; if( data[iPtr+1]==0 && data[iPtr]==0 ){ iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ }else{ while( (iFreeBlk = get2byte(&data[iPtr]))pgno); } iPtr = iFreeBlk; } - if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); - + if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + assert( iFreeBlk>iPtr || iFreeBlk==0 ); + /* At this point: ** iFreeBlk: First freeblock after iStart, or zero if none ** iPtr: The address of a pointer to iFreeBlk ** ** Check to see if iFreeBlk should be coalesced onto the end of iStart. */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno); iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); if( iEnd > pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); } - + /* If iPtr is another freeblock (that is, if iPtr is not the freelist ** pointer in the page header) then check to see if iStart should be ** coalesced onto the end of iPtr. */ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno); nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno); data[hdr+7] -= nFrag; } - pTmp = &data[hdr+5]; - x = get2byte(pTmp); - if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ - memset(&data[iStart], 0, iSize); - } - if( iStart<=x ){ + if( iStart==get2byte(&data[hdr+5]) ){ /* 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( iStartpgno); put2byte(&data[hdr+1], iFreeBlk); put2byte(&data[hdr+5], iEnd); }else{ /* Insert the new freeblock into the freelist */ put2byte(&data[iPtr], iStart); @@ -72781,83 +61257,80 @@ ** and initialize fields of the MemPage structure accordingly. ** ** Only the following combinations are supported. Anything different ** indicates a corrupt database files: ** -** PTF_ZERODATA (0x02, 2) -** PTF_LEAFDATA | PTF_INTKEY (0x05, 5) -** PTF_ZERODATA | PTF_LEAF (0x0a, 10) -** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF (0x0d, 13) +** PTF_ZERODATA +** PTF_ZERODATA | PTF_LEAF +** PTF_LEAFDATA | PTF_INTKEY +** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF */ static int decodeFlags(MemPage *pPage, int flagByte){ BtShared *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); + flagByte &= ~PTF_LEAF; + pPage->childPtrSize = 4-4*pPage->leaf; + pPage->xCellSize = cellSizePtr; pBt = pPage->pBt; - pPage->max1bytePayload = pBt->max1bytePayload; - if( flagByte>=(PTF_ZERODATA | PTF_LEAF) ){ - pPage->childPtrSize = 0; - pPage->leaf = 1; - if( flagByte==(PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF) ){ + if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ + /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an + ** interior table b-tree page. */ + assert( (PTF_LEAFDATA|PTF_INTKEY)==5 ); + /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a + ** leaf table b-tree page. */ + assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); + pPage->intKey = 1; + if( pPage->leaf ){ pPage->intKeyLeaf = 1; - pPage->xCellSize = cellSizePtrTableLeaf; pPage->xParseCell = btreeParseCellPtr; - pPage->intKey = 1; - pPage->maxLocal = pBt->maxLeaf; - pPage->minLocal = pBt->minLeaf; - }else if( flagByte==(PTF_ZERODATA | PTF_LEAF) ){ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtrIdxLeaf; - pPage->xParseCell = btreeParseCellPtrIndex; - pPage->maxLocal = pBt->maxLocal; - pPage->minLocal = pBt->minLocal; - }else{ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtrIdxLeaf; - pPage->xParseCell = btreeParseCellPtrIndex; - return SQLITE_CORRUPT_PAGE(pPage); - } - }else{ - pPage->childPtrSize = 4; - pPage->leaf = 0; - if( flagByte==(PTF_ZERODATA) ){ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtr; - pPage->xParseCell = btreeParseCellPtrIndex; - pPage->maxLocal = pBt->maxLocal; - pPage->minLocal = pBt->minLocal; - }else if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ + }else{ pPage->intKeyLeaf = 0; pPage->xCellSize = cellSizePtrNoPayload; pPage->xParseCell = btreeParseCellPtrNoPayload; - pPage->intKey = 1; - pPage->maxLocal = pBt->maxLeaf; - pPage->minLocal = pBt->minLeaf; - }else{ - pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->xCellSize = cellSizePtr; - pPage->xParseCell = btreeParseCellPtrIndex; - return SQLITE_CORRUPT_PAGE(pPage); - } - } + } + pPage->maxLocal = pBt->maxLeaf; + pPage->minLocal = pBt->minLeaf; + }else if( flagByte==PTF_ZERODATA ){ + /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an + ** interior index b-tree page. */ + assert( (PTF_ZERODATA)==2 ); + /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a + ** leaf index b-tree page. */ + assert( (PTF_ZERODATA|PTF_LEAF)==10 ); + pPage->intKey = 0; + pPage->intKeyLeaf = 0; + pPage->xParseCell = btreeParseCellPtrIndex; + pPage->maxLocal = pBt->maxLocal; + pPage->minLocal = pBt->minLocal; + }else{ + /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is + ** an error. */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; } /* -** Compute the amount of freespace on the page. In other words, fill -** in the pPage->nFree field. +** Initialize the auxiliary information for a disk block. +** +** Return SQLITE_OK on success. If we see that the page does +** not contain a well-formed database page, then return +** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not +** guarantee that the page is well-formed. It only shows that +** we failed to detect any corruption. */ -static int btreeComputeFreeSpace(MemPage *pPage){ +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 */ @@ -72865,55 +61338,108 @@ assert( pPage->pBt->db!=0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - assert( pPage->isInit==1 ); - assert( pPage->nFree<0 ); + assert( pPage->isInit==0 ); - usableSize = pPage->pBt->usableSize; + 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_PGNO(pPage->pgno); + } + 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]); - iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell; + /* 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_PGNO(pPage->pgno); + } + 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_PGNO(pPage->pgno); + } + sz = pPage->xCellSize(pPage, &data[pc]); + testcase( pc+sz==usableSize ); + if( pc+sz>usableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + } + 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 */ if( pc>0 ){ u32 next, size; - if( pcpgno); } while( 1 ){ if( pc>iCellLast ){ /* Freeblock off the end of the page */ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); nFree = nFree + size; if( next<=pc+size+3 ) break; pc = next; } if( next>0 ){ /* Freeblock not in ascending order */ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } if( pc+size>(unsigned int)usableSize ){ /* Last freeblock extends past page end */ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } } /* 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 @@ -72920,108 +61446,15 @@ ** 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 || nFreeusableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } pPage->nFree = (u16)(nFree - iCellFirst); - return SQLITE_OK; -} - -/* -** Do additional sanity check after btreeInitPage() if -** PRAGMA cell_size_check=ON -*/ -static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){ - int iCellFirst; /* First allowable cell or freeblock offset */ - int iCellLast; /* Last possible cell or freeblock offset */ - int i; /* Index into the cell pointer array */ - int sz; /* Size of a cell */ - int pc; /* Address of a freeblock within pPage->aData[] */ - u8 *data; /* Equal to pPage->aData */ - int usableSize; /* Maximum usable space on the page */ - int cellOffset; /* Start of cell content area */ - - iCellFirst = pPage->cellOffset + 2*pPage->nCell; - usableSize = pPage->pBt->usableSize; - iCellLast = usableSize - 4; - data = pPage->aData; - cellOffset = pPage->cellOffset; - if( !pPage->leaf ) iCellLast--; - for(i=0; inCell; i++){ - pc = get2byteAligned(&data[cellOffset+i*2]); - testcase( pc==iCellFirst ); - testcase( pc==iCellLast ); - if( pciCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - sz = pPage->xCellSize(pPage, &data[pc]); - testcase( pc+sz==usableSize ); - if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - } - return SQLITE_OK; -} - -/* -** Initialize the auxiliary information for a disk block. -** -** Return SQLITE_OK on success. If we see that the page does -** not contain a well-formed database page, then return -** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not -** guarantee that the page is well-formed. It only shows that -** we failed to detect any corruption. -*/ -static int btreeInitPage(MemPage *pPage){ - u8 *data; /* Equal to pPage->aData */ - BtShared *pBt; /* The main btree structure */ - - assert( pPage->pBt!=0 ); - assert( pPage->pBt->db!=0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); - assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); - assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - assert( pPage->isInit==0 ); - - pBt = pPage->pBt; - data = pPage->aData + pPage->hdrOffset; - /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating - ** the b-tree page type. */ - if( decodeFlags(pPage, data[0]) ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nOverflow = 0; - pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize; - pPage->aCellIdx = data + pPage->childPtrSize + 8; - pPage->aDataEnd = pPage->aData + pBt->pageSize; - pPage->aDataOfst = pPage->aData + pPage->childPtrSize; - /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the - ** number of cells on the page. */ - pPage->nCell = get2byte(&data[3]); - if( pPage->nCell>MX_CELL(pBt) ){ - /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_PAGE(pPage); - } - testcase( pPage->nCell==MX_CELL(pBt) ); - /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only - ** possible for a root page of a table that contains no rows) then the - ** offset to the cell content area will equal the page size minus the - ** bytes of reserved space. */ - assert( pPage->nCell>0 - || get2byteNotZero(&data[5])==(int)pBt->usableSize - || CORRUPT_DB ); - pPage->nFree = -1; /* Indicate that this value is yet uncomputed */ pPage->isInit = 1; - if( pBt->db->flags & SQLITE_CellSizeCk ){ - return btreeCellSizeCheck(pPage); - } return SQLITE_OK; } /* ** Set up a raw page so that it looks like a database page holding @@ -73031,11 +61464,11 @@ unsigned char *data = pPage->aData; BtShared *pBt = pPage->pBt; u8 hdr = pPage->hdrOffset; u16 first; - assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB ); + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); assert( sqlite3PagerGetData(pPage->pDbPage) == data ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->btsFlags & BTS_FAST_SECURE ){ @@ -73047,11 +61480,11 @@ data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); pPage->nFree = (u16)(pBt->usableSize - first); decodeFlags(pPage, flags); pPage->cellOffset = first; - pPage->aDataEnd = &data[pBt->pageSize]; + pPage->aDataEnd = &data[pBt->usableSize]; pPage->aCellIdx = &data[first]; pPage->aDataOfst = &data[pPage->childPtrSize]; pPage->nOverflow = 0; assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); @@ -73072,11 +61505,11 @@ pPage->pBt = pBt; pPage->pgno = pgno; pPage->hdrOffset = pgno==1 ? 100 : 0; } assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); - return pPage; + return pPage; } /* ** Get a page from the pager. Initialize the MemPage.pBt and ** MemPage.aData elements if needed. See also: btreeGetUnusedPage(). @@ -73125,59 +61558,82 @@ ** error, return ((unsigned int)-1). */ static Pgno btreePagecount(BtShared *pBt){ return pBt->nPage; } -SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree *p){ +SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){ assert( sqlite3BtreeHoldsMutex(p) ); + assert( ((p->pBt->nPage)&0x8000000)==0 ); return btreePagecount(p->pBt); } /* ** Get a page from the pager and initialize it. +** +** If pCur!=0 then the page is being fetched as part of a moveToChild() +** call. Do additional sanity checking on the page in this case. +** And if the fetch fails, this routine must decrement pCur->iPage. +** +** The page is fetched as read-write unless pCur is not NULL and is +** a read-only cursor. +** +** If an error occurs, then *ppPage is undefined. It +** may remain unchanged, or it may be set to an invalid value. */ static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ + BtCursor *pCur, /* Cursor to receive the page, or NULL */ int bReadOnly /* True for a read-only page */ ){ int rc; DbPage *pDbPage; - MemPage *pPage; assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] ); + assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); + assert( pCur==0 || pCur->iPage>0 ); if( pgno>btreePagecount(pBt) ){ - *ppPage = 0; - return SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_BKPT; + goto getAndInitPage_error; } rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); if( rc ){ - *ppPage = 0; - return rc; + goto getAndInitPage_error; } - pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( pPage->isInit==0 ){ + *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); + if( (*ppPage)->isInit==0 ){ btreePageFromDbPage(pDbPage, pgno, pBt); - rc = btreeInitPage(pPage); + rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ - releasePage(pPage); - *ppPage = 0; - return rc; + releasePage(*ppPage); + goto getAndInitPage_error; } } - assert( pPage->pgno==pgno || CORRUPT_DB ); - assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); - *ppPage = pPage; + assert( (*ppPage)->pgno==pgno ); + assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) ); + + /* 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_PGNO(pgno); + releasePage(*ppPage); + goto getAndInitPage_error; + } return SQLITE_OK; + +getAndInitPage_error: + if( pCur ) pCur->iPage--; + testcase( pgno==0 ); + assert( pgno!=0 || rc==SQLITE_CORRUPT ); + return rc; } /* ** 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 ); assert( pPage->pBt ); assert( pPage->pDbPage!=0 ); @@ -73187,20 +61643,10 @@ sqlite3PagerUnrefNotNull(pPage->pDbPage); } 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. ** ** This works just like btreeGetPage() with the addition: @@ -73249,11 +61695,11 @@ /* pPage might not be a btree page; it might be an overflow page ** or ptrmap page or a free page. In those cases, the following ** call to btreeInitPage() will likely return SQLITE_CORRUPT. ** But no harm is done by this. And it is very important that ** btreeInitPage() be called on every btree page so we make - ** the call for every page that comes in for re-initializing. */ + ** the call for every page that comes in for re-initing. */ btreeInitPage(pPage); } } } @@ -73267,15 +61713,15 @@ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); } /* ** Open a database file. -** +** ** zFilename is the name of the database file. If zFilename is NULL ** then an ephemeral database is created. The ephemeral database might ** be exclusively in memory, or it might use a disk-based memory cache. -** Either way, the ephemeral database will be automatically deleted +** Either way, the ephemeral database will be automatically deleted ** when sqlite3BtreeClose() is called. ** ** If zFilename is ":memory:" then an in-memory database is created ** that is automatically destroyed when it is closed. ** @@ -73304,11 +61750,11 @@ unsigned char zDbHeader[100]; /* Database header content */ /* True if opening an ephemeral, temporary database */ const int isTempDb = zFilename==0 || zFilename[0]==0; - /* Set the variable isMemdb to true for an in-memory database, or + /* Set the variable isMemdb to true for an in-memory database, or ** false for a file-based database. */ #ifdef SQLITE_OMIT_MEMORYDB const int isMemdb = 0; #else @@ -73366,23 +61812,19 @@ memcpy(zFullPathname, zFilename, nFilename); }else{ rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); if( rc ){ - if( rc==SQLITE_OK_SYMLINK ){ - rc = SQLITE_OK; - }else{ - sqlite3_free(zFullPathname); - sqlite3_free(p); - return rc; - } + sqlite3_free(zFullPathname); + sqlite3_free(p); + return rc; } } #if SQLITE_THREADSAFE mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN); sqlite3_mutex_enter(mutexOpen); - mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); + mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(mutexShared); #endif for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0)) @@ -73427,14 +61869,11 @@ assert( sizeof(i64)==8 ); assert( sizeof(u64)==8 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); - - /* Suppress false-positive compiler warning from PVS-Studio */ - memset(&zDbHeader[16], 0, 8); - + pBt = sqlite3MallocZero( sizeof(*pBt) ); if( pBt==0 ){ rc = SQLITE_NOMEM_BKPT; goto btree_open_out; } @@ -73447,13 +61886,13 @@ if( rc!=SQLITE_OK ){ goto btree_open_out; } pBt->openFlags = (u8)flags; pBt->db = db; - sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); + sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; - + pBt->pCursor = 0; pBt->pPage1 = 0; if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; #if defined(SQLITE_SECURE_DELETE) pBt->btsFlags |= BTS_SECURE_DELETE; @@ -73493,18 +61932,18 @@ } rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); if( rc ) goto btree_open_out; pBt->usableSize = pBt->pageSize - nReserve; assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ - + #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* Add the new BtShared object to the linked list sharable BtShareds. */ pBt->nRef = 1; if( p->sharable ){ MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);) + MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); if( pBt->mutex==0 ){ rc = SQLITE_NOMEM_BKPT; goto btree_open_out; @@ -73565,11 +62004,11 @@ /* 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. */ if( sqlite3BtreeSchema(p, 0, 0)==0 ){ - sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE); + sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); } pFile = sqlite3PagerFile(pBt->pPager); if( pFile->pMethods ){ sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); @@ -73589,17 +62028,17 @@ ** true if the BtShared.nRef counter reaches zero and return ** false if it is still positive. */ static int removeFromSharingList(BtShared *pBt){ #ifndef SQLITE_OMIT_SHARED_CACHE - MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) + MUTEX_LOGIC( sqlite3_mutex *pMaster; ) BtShared *pList; int removed = 0; assert( sqlite3_mutex_notheld(pBt->mutex) ); - MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(pMainMtx); + MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + sqlite3_mutex_enter(pMaster); pBt->nRef--; if( pBt->nRef<=0 ){ if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext; }else{ @@ -73614,54 +62053,46 @@ if( SQLITE_THREADSAFE ){ sqlite3_mutex_free(pBt->mutex); } removed = 1; } - sqlite3_mutex_leave(pMainMtx); + sqlite3_mutex_leave(pMaster); return removed; #else return 1; #endif } /* -** Make sure pBt->pTmpSpace points to an allocation of +** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child ** pointer. */ -static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ - assert( pBt!=0 ); - assert( pBt->pTmpSpace==0 ); - /* This routine is called only by btreeCursor() when allocating the - ** first write cursor for the BtShared object */ - assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 ); - pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); - if( pBt->pTmpSpace==0 ){ - BtCursor *pCur = pBt->pCursor; - pBt->pCursor = pCur->pNext; /* Unlink the cursor */ - memset(pCur, 0, sizeof(*pCur)); - return SQLITE_NOMEM_BKPT; - } - - /* One of the uses of pBt->pTmpSpace is to format cells before - ** inserting them into a leaf page (function fillInCell()). If - ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes - ** by the various routines that manipulate binary cells. Which - ** can mean that fillInCell() only initializes the first 2 or 3 - ** bytes of pTmpSpace, but that the first 4 bytes are copied from - ** it into a database page. This is not actually a problem, but it - ** does cause a valgrind error when the 1 or 2 bytes of uninitialized - ** data is passed to system call write(). So to avoid this error, - ** zero the first 4 bytes of temp space here. - ** - ** Also: Provide four bytes of initialized space before the - ** beginning of pTmpSpace as an area available to prepend the - ** left-child pointer to the beginning of a cell. - */ - memset(pBt->pTmpSpace, 0, 8); - pBt->pTmpSpace += 4; - return SQLITE_OK; +static void allocateTempSpace(BtShared *pBt){ + if( !pBt->pTmpSpace ){ + pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); + + /* One of the uses of pBt->pTmpSpace is to format cells before + ** inserting them into a leaf page (function fillInCell()). If + ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes + ** by the various routines that manipulate binary cells. Which + ** can mean that fillInCell() only initializes the first 2 or 3 + ** bytes of pTmpSpace, but that the first 4 bytes are copied from + ** it into a database page. This is not actually a problem, but it + ** does cause a valgrind error when the 1 or 2 bytes of unitialized + ** data is passed to system call write(). So to avoid this error, + ** zero the first 4 bytes of temp space here. + ** + ** Also: Provide four bytes of initialized space before the + ** beginning of pTmpSpace as an area available to prepend the + ** left-child pointer to the beginning of a cell. + */ + if( pBt->pTmpSpace ){ + memset(pBt->pTmpSpace, 0, 8); + pBt->pTmpSpace += 4; + } + } } /* ** Free the pBt->pTmpSpace allocation */ @@ -73676,37 +62107,33 @@ /* ** Close an open database and invalidate all cursors. */ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ BtShared *pBt = p->pBt; + BtCursor *pCur; /* Close all cursors opened via this handle. */ assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); - - /* Verify that no other cursors have this Btree open */ -#ifdef SQLITE_DEBUG - { - BtCursor *pCur = pBt->pCursor; - while( pCur ){ - BtCursor *pTmp = pCur; - pCur = pCur->pNext; - assert( pTmp->pBtree!=p ); - + pCur = pBt->pCursor; + while( pCur ){ + BtCursor *pTmp = pCur; + pCur = pCur->pNext; + if( pTmp->pBtree==p ){ + sqlite3BtreeCloseCursor(pTmp); } } -#endif /* Rollback any active transaction and free the handle structure. ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ sqlite3BtreeRollback(p, SQLITE_OK, 0); sqlite3BtreeLeave(p); /* If there are still other outstanding references to the shared-btree - ** structure, return now. The remainder of this procedure cleans + ** structure, return now. The remainder of this procedure cleans ** up the shared-btree. */ assert( p->wantToLock==0 && p->locked==0 ); if( !p->sharable || removeFromSharingList(pBt) ){ /* The pBt is no longer on the sharing list, so we can access @@ -73808,11 +62235,11 @@ } #endif /* ** Change the default pages size and the number of reserved bytes per page. -** Or, if the page size has already been fixed, return SQLITE_READONLY +** Or, if the page size has already been fixed, return SQLITE_READONLY ** without changing anything. ** ** The page size must be a power of 2 between 512 and 65536. If the page ** size supplied does not meet this constraint then the page size is not ** changed. @@ -73828,27 +62255,28 @@ ** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size ** and autovacuum mode can no longer be changed. */ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){ int rc = SQLITE_OK; - int x; BtShared *pBt = p->pBt; - assert( nReserve>=0 && nReserve<=255 ); + assert( nReserve>=-1 && nReserve<=255 ); sqlite3BtreeEnter(p); - pBt->nReserveWanted = nReserve; - x = pBt->pageSize - pBt->usableSize; - if( nReservepBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve; +#endif if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); return SQLITE_READONLY; } + if( nReserve<0 ){ + nReserve = pBt->pageSize - pBt->usableSize; + } assert( nReserve>=0 && nReserve<=255 ); if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); assert( !pBt->pCursor ); - if( nReserve>32 && pageSize==512 ) pageSize = 1024; pBt->pageSize = (u32)pageSize; freeTempSpace(pBt); } rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); pBt->usableSize = pBt->pageSize - (u16)nReserve; @@ -73868,11 +62296,11 @@ ** This function is similar to sqlite3BtreeGetReserve(), except that it ** may only be called if it is guaranteed that the b-tree mutex is already ** held. ** ** This is useful in one special case in the backup API code where it is -** known that the shared b-tree mutex is held, but the mutex on the +** known that the shared b-tree mutex is held, but the mutex on the ** database handle that owns *p is not. In this case if sqlite3BtreeEnter() ** were to be called, it might collide with some other operation on the ** database handle that owns *p, causing undefined behavior. */ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ @@ -73882,34 +62310,36 @@ return n; } /* ** Return the number of bytes of space at the end of every page that -** are intentionally left unused. This is the "reserved" space that is +** are intentually left unused. This is the "reserved" space that is ** sometimes used by extensions. ** -** The value returned is the larger of the current reserve size and -** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES. -** The amount of reserve can only grow - never shrink. +** If SQLITE_HAS_MUTEX is defined then the number returned is the +** greater of the current reserved space and the maximum requested +** reserve space. */ -SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){ - int n1, n2; +SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){ + int n; sqlite3BtreeEnter(p); - n1 = (int)p->pBt->nReserveWanted; - n2 = sqlite3BtreeGetReserveNoMutex(p); + n = sqlite3BtreeGetReserveNoMutex(p); +#ifdef SQLITE_HAS_CODEC + if( npBt->optimalReserve ) n = p->pBt->optimalReserve; +#endif sqlite3BtreeLeave(p); - return n1>n2 ? n1 : n2; + return n; } /* ** Set the maximum page count for a database if mxPage is positive. ** No changes are made if mxPage is 0 or negative. ** Regardless of the value of mxPage, return the maximum page count. */ -SQLITE_PRIVATE Pgno sqlite3BtreeMaxPageCount(Btree *p, Pgno mxPage){ - Pgno n; +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ + int n; sqlite3BtreeEnter(p); n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); sqlite3BtreeLeave(p); return n; } @@ -73948,11 +62378,11 @@ } /* ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it -** is disabled. The default value for the auto-vacuum property is +** is disabled. The default value for the auto-vacuum property is ** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. */ SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ #ifdef SQLITE_OMIT_AUTOVACUUM return SQLITE_READONLY; @@ -73972,11 +62402,11 @@ return rc; #endif } /* -** Return the value of the 'auto-vacuum' property. If auto-vacuum is +** Return the value of the 'auto-vacuum' property. If auto-vacuum is ** enabled 1 is returned. Otherwise 0. */ SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){ #ifdef SQLITE_OMIT_AUTOVACUUM return BTREE_AUTOVACUUM_NONE; @@ -73997,20 +62427,19 @@ ** 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) +#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS 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] + 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)); } @@ -74017,48 +62446,42 @@ } } #else # define setDefaultSyncFlag(pBt,safety_level) #endif - -/* Forward declaration */ -static int newDatabase(BtShared*); - /* ** Get a reference to pPage1 of the database file. This will ** also acquire a readlock on that file. ** ** SQLITE_OK is returned on success. If the file is not a ** well-formed database file, then SQLITE_CORRUPT is returned. ** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM -** is returned if we run out of memory. +** is returned if we run out of memory. */ static int lockBtree(BtShared *pBt){ int rc; /* Result code from subfunctions */ MemPage *pPage1; /* Page 1 of the database file */ - u32 nPage; /* Number of pages in the database */ - u32 nPageFile = 0; /* Number of pages in the database file */ + int nPage; /* Number of pages in the database */ + int nPageFile = 0; /* Number of pages in the database file */ + int nPageHeader; /* Number of pages in the database according to hdr */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( pBt->pPage1==0 ); rc = sqlite3PagerSharedLock(pBt->pPager); if( rc!=SQLITE_OK ) return rc; rc = btreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; /* Do some checking to help insure the file we opened really is - ** a valid database file. + ** a valid database file. */ - nPage = get4byte(28+(u8*)pPage1->aData); - sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile); + nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData); + sqlite3PagerPagecount(pBt->pPager, &nPageFile); if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ nPage = nPageFile; } - if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){ - nPage = 0; - } if( nPage>0 ){ u32 pageSize; u32 usableSize; u8 *page1 = pPage1->aData; rc = SQLITE_NOTADB; @@ -74082,12 +62505,12 @@ } if( page1[19]>2 ){ goto page1_init_failed; } - /* If the read version is set to 2, this database should be accessed - ** in WAL mode. If the log is not already open, open it now. Then + /* If the write version is set to 2, this database should be accessed + ** in WAL mode. If the log is not already open, open it now. Then ** return SQLITE_OK and return without populating BtShared.pPage1. ** The caller detects this and calls this function again. This is ** required as the version of page 1 currently in the page1 buffer ** may not be the latest version - there may be a newer one in the log ** file. @@ -74098,11 +62521,11 @@ if( rc!=SQLITE_OK ){ goto page1_init_failed; }else{ setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1); if( isOpen==0 ){ - releasePageOne(pPage1); + releasePage(pPage1); return SQLITE_OK; } } rc = SQLITE_NOTADB; }else{ @@ -74124,19 +62547,19 @@ ** the beginning of the database file. */ pageSize = (page1[16]<<8) | (page1[17]<<16); /* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two ** between 512 and 65536 inclusive. */ if( ((pageSize-1)&pageSize)!=0 - || pageSize>SQLITE_MAX_PAGE_SIZE - || pageSize<=256 + || pageSize>SQLITE_MAX_PAGE_SIZE + || pageSize<=256 ){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte ** integer at offset 20 is the number of bytes of space at the end of - ** each page to reserve for extensions. + ** each page to reserve for extensions. ** ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is ** determined by the one-byte unsigned integer found at an offset of 20 ** into the database file header. */ usableSize = pageSize - page1[20]; @@ -74145,34 +62568,28 @@ ** of BtShared.pageSize, we have discovered that the page-size is ** actually pageSize. Unlock the database, leave pBt->pPage1 at ** zero and return SQLITE_OK. The caller will call this function ** again with the correct page-size. */ - releasePageOne(pPage1); + releasePage(pPage1); pBt->usableSize = usableSize; pBt->pageSize = pageSize; - pBt->btsFlags |= BTS_PAGESIZE_FIXED; freeTempSpace(pBt); rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, pageSize-usableSize); return rc; } - if( nPage>nPageFile ){ - if( sqlite3WritableSchema(pBt->db)==0 ){ - rc = SQLITE_CORRUPT_BKPT; - goto page1_init_failed; - }else{ - nPage = nPageFile; - } + if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ + rc = SQLITE_CORRUPT_BKPT; + goto page1_init_failed; } /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to ** be less than 480. In other words, if the page size is 512, then the ** reserved space size cannot exceed 32. */ if( usableSize<480 ){ goto page1_init_failed; } - pBt->btsFlags |= BTS_PAGESIZE_FIXED; pBt->pageSize = pageSize; pBt->usableSize = usableSize; #ifndef SQLITE_OMIT_AUTOVACUUM pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); @@ -74205,11 +62622,11 @@ pBt->pPage1 = pPage1; pBt->nPage = nPage; return SQLITE_OK; page1_init_failed: - releasePageOne(pPage1); + releasePage(pPage1); pBt->pPage1 = 0; return rc; } #ifndef NDEBUG @@ -74228,20 +62645,20 @@ static int countValidCursors(BtShared *pBt, int wrOnly){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0) - && pCur->eState!=CURSOR_FAULT ) r++; + && pCur->eState!=CURSOR_FAULT ) r++; } return r; } #endif /* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then -** this routine unrefs the first page of the database file which +** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ @@ -74250,11 +62667,11 @@ if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ MemPage *pPage1 = pBt->pPage1; assert( pPage1->aData ); assert( sqlite3PagerRefcount(pBt->pPager)==1 ); pBt->pPage1 = 0; - releasePageOne(pPage1); + releasePageNotNull(pPage1); } } /* ** If pBt points to an empty file then convert that empty file @@ -74321,12 +62738,12 @@ ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be ** upgraded to exclusive by calling this routine a second time - the ** exclusivity flag only works for a new transaction. ** -** A write-transaction must be started before attempting any -** changes to the database. None of the following routines +** A write-transaction must be started before attempting any +** changes to the database. None of the following routines ** will work unless a transaction is started first: ** ** sqlite3BtreeCreateTable() ** sqlite3BtreeCreateIndex() ** sqlite3BtreeClearTable() @@ -74336,11 +62753,11 @@ ** sqlite3BtreeUpdateMeta() ** ** If an initial attempt to acquire the lock fails because of lock contention ** and the database was previously unlocked, then invoke the busy handler ** if there is one. But if there was previously a read-lock, do not -** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is +** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is ** returned when there is already a read-lock in order to avoid a deadlock. ** ** Suppose there are two processes A and B. A has a read lock and B has ** a reserved lock. B tries to promote to exclusive but is blocked because ** of A's read lock. A tries to promote to reserved but is blocked by B. @@ -74347,17 +62764,12 @@ ** One or the other of the two processes must give way or there can be ** no progress. By returning SQLITE_BUSY and not invoking the busy callback ** when A already has a read lock, we encourage A to give up and let B ** proceed. */ -static SQLITE_NOINLINE int btreeBeginTrans( - Btree *p, /* The btree in which to start the transaction */ - int wrflag, /* True to start a write transaction */ - int *pSchemaVersion /* Put schema version number here, if not NULL */ -){ +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ BtShared *pBt = p->pBt; - Pager *pPager = pBt->pPager; int rc = SQLITE_OK; sqlite3BtreeEnter(p); btreeIntegrity(p); @@ -74368,26 +62780,20 @@ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ goto trans_begun; } assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); - if( (p->db->flags & SQLITE_ResetDatabase) - && sqlite3PagerIsreadonly(pPager)==0 - ){ - pBt->btsFlags &= ~BTS_READ_ONLY; - } - /* Write transactions are not possible on a read-only database */ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ rc = SQLITE_READONLY; goto trans_begun; } #ifndef SQLITE_OMIT_SHARED_CACHE { sqlite3 *pBlock = 0; - /* If another database handle has already opened a write transaction + /* If another database handle has already opened a write transaction ** on this shared-btree structure and a second write transaction is ** requested, return SQLITE_LOCKED. */ if( (wrflag && pBt->inTransaction==TRANS_WRITE) || (pBt->btsFlags & BTS_PENDING)!=0 @@ -74408,66 +62814,44 @@ goto trans_begun; } } #endif - /* Any read-only or read-write transaction implies a read-lock on - ** page 1. So if some other shared-cache client already has a write-lock + /* Any read-only or read-write transaction implies a read-lock on + ** page 1. So if some other shared-cache client already has a write-lock ** on page 1, the transaction cannot be opened. */ - rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); + rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); if( SQLITE_OK!=rc ) goto trans_begun; pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; do { - sqlite3PagerWalDb(pPager, p->db); - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* If transitioning from no transaction directly to a write transaction, - ** block for the WRITER lock first if possible. */ - if( pBt->pPage1==0 && wrflag ){ - assert( pBt->inTransaction==TRANS_NONE ); - rc = sqlite3PagerWalWriteLock(pPager, 1); - if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break; - } -#endif - /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after - ** reading page 1 it discovers that the page-size of the database + ** reading page 1 it discovers that the page-size of the database ** file is not pBt->pageSize. In this case lockBtree() will update ** pBt->pageSize to the page-size of the file on disk. */ while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) ); if( rc==SQLITE_OK && wrflag ){ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){ rc = SQLITE_READONLY; }else{ - rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db)); + rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); - }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){ - /* if there was no transaction opened when this function was - ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error - ** code to SQLITE_BUSY. */ - rc = SQLITE_BUSY; } } } - + if( rc!=SQLITE_OK ){ - (void)sqlite3PagerWalWriteLock(pPager, 0); unlockBtreeIfUnused(pBt); } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); - sqlite3PagerWalDb(pPager, 0); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; -#endif if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ pBt->nTransaction++; #ifndef SQLITE_OMIT_SHARED_CACHE @@ -74492,11 +62876,11 @@ if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE; #endif /* If the db-size header field is incorrect (as it may be if an old ** client has been writing the database file), update it now. Doing - ** this sooner rather than later means the database size can safely + ** this sooner rather than later means the database size can safely ** re-read the database size from page 1 if a savepoint or transaction ** rollback occurs within the transaction. */ if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){ rc = sqlite3PagerWrite(pPage1->pDbPage); @@ -74504,51 +62888,25 @@ put4byte(&pPage1->aData[28], pBt->nPage); } } } } + trans_begun: - if( rc==SQLITE_OK ){ - if( pSchemaVersion ){ - *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); - } - if( wrflag ){ - /* This call makes sure that the pager has the correct number of - ** open savepoints. If the second parameter is greater than 0 and - ** the sub-journal is not already open, then it will be opened here. - */ - rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint); - } + if( rc==SQLITE_OK && wrflag ){ + /* This call makes sure that the pager has the correct number of + ** open savepoints. If the second parameter is greater than 0 and + ** the sub-journal is not already open, then it will be opened here. + */ + rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); } btreeIntegrity(p); sqlite3BtreeLeave(p); return rc; } -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ - BtShared *pBt; - if( p->sharable - || p->inTrans==TRANS_NONE - || (p->inTrans==TRANS_READ && wrflag!=0) - ){ - return btreeBeginTrans(p,wrflag,pSchemaVersion); - } - pBt = p->pBt; - if( pSchemaVersion ){ - *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); - } - if( wrflag ){ - /* This call makes sure that the pager has the correct number of - ** open savepoints. If the second parameter is greater than 0 and - ** the sub-journal is not already open, then it will be opened here. - */ - return sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); - }else{ - return SQLITE_OK; - } -} #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Set the pointer-map entries for all children of page pPage. Also, if @@ -74568,11 +62926,11 @@ nCell = pPage->nCell; for(i=0; ileaf ){ Pgno childPgno = get4byte(pCell); ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); } @@ -74589,11 +62947,11 @@ /* ** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so ** that it points to iTo. Parameter eType describes the type of pointer to ** be modified, as follows: ** -** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child +** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child ** page of pPage. ** ** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow ** page pointed to by one of the cells on pPage. ** @@ -74604,11 +62962,11 @@ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); 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_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } put4byte(pPage->aData, iTo); }else{ int i; int nCell; @@ -74623,46 +62981,43 @@ if( eType==PTRMAP_OVERFLOW1 ){ CellInfo info; pPage->xParseCell(pPage, pCell, &info); if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); break; } } }else{ - if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } if( get4byte(pCell)==iFrom ){ put4byte(pCell, iTo); break; } } } - + if( i==nCell ){ - if( eType!=PTRMAP_BTREE || + if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } } return SQLITE_OK; } /* -** Move the open database page pDbPage to location iFreePage in the +** Move the open database page pDbPage to location iFreePage in the ** database. The pDbPage reference remains valid. ** ** The isCommit flag indicates that there is no need to remember that -** the journal needs to be sync()ed before database page pDbPage->pgno +** the journal needs to be sync()ed before database page pDbPage->pgno ** can be written to. The caller has already promised not to write to that ** page. */ static int relocatePage( BtShared *pBt, /* Btree */ @@ -74675,18 +63030,17 @@ MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ Pgno iDbPage = pDbPage->pgno; Pager *pPager = pBt->pPager; int rc; - assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || + assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3_mutex_held(pBt->mutex) ); assert( pDbPage->pBt==pBt ); - if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; /* Move page iDbPage from its current location to page number iFreePage */ - TRACE(("AUTOVACUUM: Moving %u to free page %u (ptr page %u type %u)\n", + TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType)); rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); if( rc!=SQLITE_OK ){ return rc; } @@ -74741,23 +63095,23 @@ /* Forward declaration required by incrVacuumStep(). */ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); /* ** Perform a single step of an incremental-vacuum. If successful, return -** SQLITE_OK. If there is no work to do (and therefore no point in -** calling this function again), return SQLITE_DONE. Or, if an error +** SQLITE_OK. If there is no work to do (and therefore no point in +** calling this function again), return SQLITE_DONE. Or, if an error ** occurs, return some other error code. ** -** More specifically, this function attempts to re-organize the database so +** More specifically, this function attempts to re-organize the database so ** that the last page of the file currently in use is no longer in use. ** ** Parameter nFin is the number of pages that this database would contain ** were this function called until it returns SQLITE_DONE. ** -** If the bCommit parameter is non-zero, this function assumes that the -** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE -** or an error. bCommit is passed true for an auto-vacuum-on-commit +** If the bCommit parameter is non-zero, this function assumes that the +** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE +** or an error. bCommit is passed true for an auto-vacuum-on-commit ** operation, or false for an incremental vacuum. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ Pgno nFreeList; /* Number of pages still on the free-list */ int rc; @@ -74784,11 +63138,11 @@ if( eType==PTRMAP_FREEPAGE ){ if( bCommit==0 ){ /* Remove the page from the files free-list. This is not required ** if bCommit is non-zero. In that case, the free-list will be - ** truncated to zero after this function returns, so it doesn't + ** truncated to zero after this function returns, so it doesn't ** matter if it still contains some garbage entries. */ Pgno iFreePg; MemPage *pFreePg; rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT); @@ -74820,24 +63174,19 @@ eMode = BTALLOC_LE; iNear = nFin; } do { MemPage *pFreePg; - Pgno dbSize = btreePagecount(pBt); rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); if( rc!=SQLITE_OK ){ releasePage(pLastPg); return rc; } releasePage(pFreePg); - if( iFreePg>dbSize ){ - releasePage(pLastPg); - return SQLITE_CORRUPT_BKPT; - } }while( bCommit && iFreePg>nFin ); assert( iFreePgpBt; @@ -74896,11 +63245,11 @@ }else{ Pgno nOrig = btreePagecount(pBt); Pgno nFree = get4byte(&pBt->pPage1->aData[36]); Pgno nFin = finalDbSize(pBt, nOrig, nFree); - if( nOrig=nOrig ){ + if( nOrig0 ){ rc = saveAllCursors(pBt, 0, 0); if( rc==SQLITE_OK ){ invalidateAllOverflowCache(pBt); @@ -74919,30 +63268,27 @@ } /* ** This routine is called prior to sqlite3PagerCommit when a transaction ** is committed for an auto-vacuum database. +** +** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages +** the database file should be truncated to during the commit process. +** i.e. the database has been reorganized so that only the first *pnTrunc +** pages are in use. */ -static int autoVacuumCommit(Btree *p){ +static int autoVacuumCommit(BtShared *pBt){ int rc = SQLITE_OK; - Pager *pPager; - BtShared *pBt; - sqlite3 *db; - VVA_ONLY( int nRef ); - - assert( p!=0 ); - pBt = p->pBt; - pPager = pBt->pPager; - VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); ) + Pager *pPager = pBt->pPager; + VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); ) assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); assert(pBt->autoVacuum); if( !pBt->incrVacuum ){ Pgno nFin; /* Number of pages in database after autovacuuming */ Pgno nFree; /* Number of pages on the freelist initially */ - Pgno nVac; /* Number of pages to vacuum */ Pgno iFree; /* The next page to be freed */ Pgno nOrig; /* Database size before freeing */ nOrig = btreePagecount(pBt); if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ @@ -74952,46 +63298,22 @@ */ return SQLITE_CORRUPT_BKPT; } nFree = get4byte(&pBt->pPage1->aData[36]); - db = p->db; - if( db->xAutovacPages ){ - int iDb; - for(iDb=0; ALWAYS(iDbnDb); iDb++){ - if( db->aDb[iDb].pBt==p ) break; - } - nVac = db->xAutovacPages( - db->pAutovacPagesArg, - db->aDb[iDb].zDbSName, - nOrig, - nFree, - pBt->pageSize - ); - if( nVac>nFree ){ - nVac = nFree; - } - if( nVac==0 ){ - return SQLITE_OK; - } - }else{ - nVac = nFree; - } - nFin = finalDbSize(pBt, nOrig, nVac); + nFin = finalDbSize(pBt, nOrig, nFree); if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; if( nFinnFin && rc==SQLITE_OK; iFree--){ - rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree); + rc = incrVacuumStep(pBt, nFin, iFree, 1); } if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( nVac==nFree ){ - put4byte(&pBt->pPage1->aData[32], 0); - put4byte(&pBt->pPage1->aData[36], 0); - } + put4byte(&pBt->pPage1->aData[32], 0); + put4byte(&pBt->pPage1->aData[36], 0); put4byte(&pBt->pPage1->aData[28], nFin); pBt->bDoTruncate = 1; pBt->nPage = nFin; } if( rc!=SQLITE_OK ){ @@ -75020,39 +63342,39 @@ ** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the ** commit process. ** ** This call is a no-op if no write-transaction is currently active on pBt. ** -** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to -** the name of a super-journal file that should be written into the -** individual journal file, or is NULL, indicating no super-journal file +** Otherwise, sync the database file for the btree pBt. zMaster points to +** the name of a master journal file that should be written into the +** individual journal file, or is NULL, indicating no master journal file ** (single database transaction). ** -** When this is called, the super-journal should already have been +** When this is called, the master journal should already have been ** created, populated with this journal pointer and synced to disk. ** ** Once this is routine has returned, the only thing required to commit ** the write-transaction for this database file is to delete the journal. */ -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){ +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ int rc = SQLITE_OK; if( p->inTrans==TRANS_WRITE ){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - rc = autoVacuumCommit(p); + rc = autoVacuumCommit(pBt); if( rc!=SQLITE_OK ){ sqlite3BtreeLeave(p); return rc; } } if( pBt->bDoTruncate ){ sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); } #endif - rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zSuperJrnl, 0); + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); sqlite3BtreeLeave(p); } return rc; } @@ -75073,12 +63395,12 @@ ** handle, downgrade to a read-only transaction. The other statements ** may still be reading from the database. */ downgradeAllSharedCacheTableLocks(p); p->inTrans = TRANS_READ; }else{ - /* If the handle had any kind of transaction open, decrement the - ** transaction count of the shared btree. If the transaction count + /* If the handle had any kind of transaction open, decrement the + ** transaction count of the shared btree. If the transaction count ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused() ** call below will unlock the pager. */ if( p->inTrans!=TRANS_NONE ){ clearAllSharedCacheTableLocks(p); pBt->nTransaction--; @@ -75085,11 +63407,11 @@ if( 0==pBt->nTransaction ){ pBt->inTransaction = TRANS_NONE; } } - /* Set the current transaction state to TRANS_NONE and unlock the + /* Set the current transaction state to TRANS_NONE and unlock the ** pager if this call closed the only read or write transaction. */ p->inTrans = TRANS_NONE; unlockBtreeIfUnused(pBt); } @@ -75106,16 +63428,16 @@ ** contents so that they are written onto the disk platter. All this ** routine has to do is delete or truncate or zero the header in the ** the rollback journal (which causes the transaction to commit) and ** drop locks. ** -** Normally, if an error occurs while the pager layer is attempting to +** Normally, if an error occurs while the pager layer is attempting to ** finalize the underlying journal file, this function returns an error and ** the upper layer will attempt a rollback. However, if the second argument -** is non-zero then this b-tree transaction is part of a multi-file -** transaction. In this case, the transaction has already been committed -** (by deleting a super-journal file) and the caller will ignore this +** is non-zero then this b-tree transaction is part of a multi-file +** transaction. In this case, the transaction has already been committed +** (by deleting a master journal file) and the caller will ignore this ** functions return code. So, even if an error occurs in the pager layer, ** reset the b-tree objects internal state to indicate that the write ** transaction has been closed. This is quite safe, as the pager will have ** transitioned to the error state. ** @@ -75126,11 +63448,11 @@ if( p->inTrans==TRANS_NONE ) return SQLITE_OK; sqlite3BtreeEnter(p); btreeIntegrity(p); - /* If the handle has a write-transaction open, commit the shared-btrees + /* If the handle has a write-transaction open, commit the shared-btrees ** transaction and set the shared state to TRANS_READ. */ if( p->inTrans==TRANS_WRITE ){ int rc; BtShared *pBt = p->pBt; @@ -75139,11 +63461,11 @@ rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); if( rc!=SQLITE_OK && bCleanup==0 ){ sqlite3BtreeLeave(p); return rc; } - p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */ + p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ pBt->inTransaction = TRANS_READ; btreeClearHasContent(pBt); } btreeEndTransaction(p); @@ -75175,19 +63497,19 @@ ** that belong to other database connections that happen to be ** sharing the cache with pBtree. ** ** This routine gets called when a rollback occurs. If the writeOnly ** flag is true, then only write-cursors need be tripped - read-only -** cursors save their current positions so that they may continue -** following the rollback. Or, if writeOnly is false, all cursors are +** cursors save their current positions so that they may continue +** following the rollback. Or, if writeOnly is false, all cursors are ** tripped. In general, writeOnly is false if the transaction being ** rolled back modified the database schema. In this case b-tree root ** pages may be moved or deleted from the database altogether, making ** it unsafe for read cursors to continue. ** -** If the writeOnly flag is true and an error is encountered while -** saving the current position of a read-only cursor, all cursors, +** If the writeOnly flag is true and an error is encountered while +** saving the current position of a read-only cursor, all cursors, ** including all read-cursors are tripped. ** ** SQLITE_OK is returned if successful, or if an error occurs while ** saving a cursor position, an SQLite error code. */ @@ -75197,10 +63519,11 @@ assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 ); 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); if( rc!=SQLITE_OK ){ (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); @@ -75210,29 +63533,20 @@ }else{ sqlite3BtreeClearCursor(p); p->eState = CURSOR_FAULT; p->skipNext = errCode; } - btreeReleaseAllCursorPages(p); + for(i=0; i<=p->iPage; i++){ + releasePage(p->apPage[i]); + p->apPage[i] = 0; + } } sqlite3BtreeLeave(pBtree); } return rc; } -/* -** Set the pBt->nPage field correctly, according to the current -** state of the database. Assume pBt->pPage1 is valid. -*/ -static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){ - int nPage = get4byte(&pPage1->aData[28]); - testcase( nPage==0 ); - if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); - testcase( pBt->nPage!=(u32)nPage ); - pBt->nPage = nPage; -} - /* ** Rollback the transaction in progress. ** ** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). ** Only write cursors are tripped if writeOnly is true but all cursors are @@ -75274,12 +63588,16 @@ /* The rollback may have destroyed the pPage1->aData value. So ** call btreeGetPage() on page 1 again to make ** sure pPage1->aData is set correctly. */ if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ - btreeSetNPage(pBt, pPage1); - releasePageOne(pPage1); + int nPage = get4byte(28+(u8*)pPage1->aData); + testcase( nPage==0 ); + if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); + testcase( pBt->nPage!=nPage ); + pBt->nPage = nPage; + releasePage(pPage1); } assert( countValidCursors(pBt, 1)==0 ); pBt->inTransaction = TRANS_READ; btreeClearHasContent(pBt); } @@ -75289,12 +63607,12 @@ return rc; } /* ** Start a statement subtransaction. The subtransaction can be rolled -** back independently of the main transaction. You must start a transaction -** before starting a subtransaction. The subtransaction is ended automatically +** back independently of the main transaction. You must start a transaction +** before starting a subtransaction. The subtransaction is ended automatically ** if the main transaction commits or rolls back. ** ** Statement subtransactions are used around individual SQL statements ** that are contained within a BEGIN...COMMIT block. If a constraint ** error occurs within the statement, the effect of that one statement @@ -75327,15 +63645,15 @@ } /* ** The second argument to this function, op, is always SAVEPOINT_ROLLBACK ** or SAVEPOINT_RELEASE. This function either releases or rolls back the -** savepoint identified by parameter iSavepoint, depending on the value +** savepoint identified by parameter iSavepoint, depending on the value ** of op. ** ** Normally, iSavepoint is greater than or equal to zero. However, if op is -** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the +** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the ** contents of the entire transaction are rolled back. This is different ** from a normal transaction rollback, as no locks are released and the ** transaction remains open. */ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ @@ -75354,15 +63672,16 @@ if( rc==SQLITE_OK ){ if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){ pBt->nPage = 0; } rc = newDatabase(pBt); - btreeSetNPage(pBt, pBt->pPage1); + pBt->nPage = get4byte(28 + pBt->pPage1->aData); - /* pBt->nPage might be zero if the database was corrupt when - ** the transaction was started. Otherwise, it must be at least 1. */ - assert( CORRUPT_DB || pBt->nPage>0 ); + /* The database size was written into the offset 28 of the header + ** when the transaction started, so we know that the value at offset + ** 28 is nonzero. */ + assert( pBt->nPage>0 ); } sqlite3BtreeLeave(p); } return rc; } @@ -75394,14 +63713,14 @@ ** ** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR ** is set. If FORDELETE is set, that is a hint to the implementation that ** this cursor will only be used to seek to and delete entries of an index ** as part of a larger DELETE statement. The FORDELETE hint is not used by -** this implementation. But in a hypothetical alternative storage engine +** this implementation. But in a hypothetical alternative storage engine ** in which index entries are automatically deleted when corresponding table ** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE -** operations on this cursor can be no-ops and all READ operations can +** operations on this cursor can be no-ops and all READ operations can ** return a null row (2-bytes: 0x01 0x00). ** ** No checking is done to make sure that page iTable really is the ** root page of a b-tree. If it is not, then the cursor acquired ** will not work correctly. @@ -75409,100 +63728,84 @@ ** It is assumed that the sqlite3BtreeCursorZero() has been called ** on pCur to initialize the memory space prior to invoking this routine. */ static int btreeCursor( Btree *p, /* The btree */ - Pgno iTable, /* Root page of table to open */ + int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ struct KeyInfo *pKeyInfo, /* First arg to comparison function */ BtCursor *pCur /* Space for new cursor */ ){ BtShared *pBt = p->pBt; /* Shared b-tree handle */ BtCursor *pX; /* Looping over other all cursors */ assert( sqlite3BtreeHoldsMutex(p) ); - assert( wrFlag==0 - || wrFlag==BTREE_WRCSR - || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE) + assert( wrFlag==0 + || wrFlag==BTREE_WRCSR + || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE) ); - /* The following assert statements verify that if this is a sharable - ** b-tree database, the connection is holding the required table locks, - ** and that no other connection has any open cursor that conflicts with - ** this lock. The iTable<1 term disables the check for corrupt schemas. */ - assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) - || iTable<1 ); + /* The following assert statements verify that if this is a sharable + ** b-tree database, the connection is holding the required table locks, + ** and that no other connection has any open cursor that conflicts with + ** this lock. */ + assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) ); assert( wrFlag==0 || !hasReadConflicts(p, iTable) ); /* Assert that the caller has opened the required transaction. */ assert( p->inTrans>TRANS_NONE ); assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); assert( pBt->pPage1 && pBt->pPage1->aData ); assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); - if( iTable<=1 ){ - if( iTable<1 ){ - return SQLITE_CORRUPT_BKPT; - }else if( btreePagecount(pBt)==0 ){ - assert( wrFlag==0 ); - iTable = 0; - } + if( wrFlag ){ + allocateTempSpace(pBt); + if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT; + } + if( iTable==1 && btreePagecount(pBt)==0 ){ + assert( wrFlag==0 ); + iTable = 0; } /* Now that no other errors can occur, finish filling in the BtCursor ** variables and link the cursor into the BtShared list. */ - pCur->pgnoRoot = iTable; + pCur->pgnoRoot = (Pgno)iTable; pCur->iPage = -1; pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; - pCur->curFlags = 0; + pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; + pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY; /* If there are two or more cursors on the same btree, then all such ** cursors *must* have the BTCF_Multiple flag set. */ for(pX=pBt->pCursor; pX; pX=pX->pNext){ - if( pX->pgnoRoot==iTable ){ + if( pX->pgnoRoot==(Pgno)iTable ){ pX->curFlags |= BTCF_Multiple; - pCur->curFlags = BTCF_Multiple; + pCur->curFlags |= BTCF_Multiple; } } - pCur->eState = CURSOR_INVALID; pCur->pNext = pBt->pCursor; pBt->pCursor = pCur; - if( wrFlag ){ - pCur->curFlags |= BTCF_WriteFlag; - pCur->curPagerFlags = 0; - if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt); - }else{ - pCur->curPagerFlags = PAGER_GET_READONLY; - } + pCur->eState = CURSOR_INVALID; return SQLITE_OK; } -static int btreeCursorWithLock( - Btree *p, /* The btree */ - Pgno iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to comparison function */ - BtCursor *pCur /* Space for new cursor */ -){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); - sqlite3BtreeLeave(p); - return rc; -} SQLITE_PRIVATE int sqlite3BtreeCursor( Btree *p, /* The btree */ - Pgno iTable, /* Root page of table to open */ + int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ BtCursor *pCur /* Write new cursor here */ ){ - if( p->sharable ){ - return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur); + int rc; + if( iTable<1 ){ + rc = SQLITE_CORRUPT_BKPT; }else{ - return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); + sqlite3BtreeEnter(p); + rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); + sqlite3BtreeLeave(p); } + return rc; } /* ** Return the size of a BtCursor object in bytes. ** @@ -75513,50 +63816,33 @@ */ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){ return ROUND8(sizeof(BtCursor)); } -#ifdef SQLITE_DEBUG -/* -** Return true if and only if the Btree object will be automatically -** closed with the BtCursor closes. This is used within assert() statements -** only. -*/ -SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor( - Btree *pBtree, /* the btree object */ - BtCursor *pCur /* Corresponding cursor */ -){ - BtShared *pBt = pBtree->pBt; - if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0; - if( pBt->pCursor!=pCur ) return 0; - if( pCur->pNext!=0 ) return 0; - if( pCur->pBtree!=pBtree ) return 0; - return 1; -} -#endif - /* ** Initialize memory that will be converted into a BtCursor object. ** ** The simple approach here would be to memset() the entire object ** to zero. But it turns out that the apPage[] and aiIdx[] arrays ** do not need to be zeroed and they are large, so we can save a lot ** of run-time by skipping the initialization of those elements. */ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ - memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT)); + memset(p, 0, offsetof(BtCursor, iPage)); } /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ 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; }else{ BtCursor *pPrev = pBt->pCursor; @@ -75566,23 +63852,17 @@ break; } pPrev = pPrev->pNext; }while( ALWAYS(pPrev) ); } - btreeReleaseAllCursorPages(pCur); + for(i=0; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); + } unlockBtreeIfUnused(pBt); sqlite3_free(pCur->aOverflow); - sqlite3_free(pCur->pKey); - if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){ - /* Since the BtShared is not sharable, there is no need to - ** worry about the missing sqlite3BtreeLeave() call here. */ - assert( pBtree->sharable==0 ); - sqlite3BtreeClose(pBtree); - }else{ - sqlite3BtreeLeave(pBtree); - } - pCur->pBtree = 0; + /* sqlite3_free(pCur); */ + sqlite3BtreeLeave(pBtree); } return SQLITE_OK; } /* @@ -75592,31 +63872,25 @@ ** ** BtCursor.info is a cache of the information in the current cell. ** Using this cache reduces the number of calls to btreeParseCell(). */ #ifndef NDEBUG - static int cellInfoEqual(CellInfo *a, CellInfo *b){ - if( a->nKey!=b->nKey ) return 0; - if( a->pPayload!=b->pPayload ) return 0; - if( a->nPayload!=b->nPayload ) return 0; - if( a->nLocal!=b->nLocal ) return 0; - if( a->nSize!=b->nSize ) return 0; - return 1; - } static void assertCellInfo(BtCursor *pCur){ CellInfo info; + int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); - btreeParseCell(pCur->pPage, pCur->ix, &info); - assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) ); + btreeParseCell(pCur->apPage[iPage], pCur->ix, &info); + assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else #define assertCellInfo(x) #endif static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){ if( pCur->info.nSize==0 ){ + int iPage = pCur->iPage; pCur->curFlags |= BTCF_ValidNKey; - btreeParseCell(pCur->pPage,pCur->ix,&pCur->info); + btreeParseCell(pCur->apPage[iPage],pCur->ix,&pCur->info); }else{ assertCellInfo(pCur); } } @@ -75647,34 +63921,10 @@ assert( pCur->curIntKey ); getCellInfo(pCur); return pCur->info.nKey; } -/* -** Pin or unpin a cursor. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor *pCur){ - assert( (pCur->curFlags & BTCF_Pinned)==0 ); - pCur->curFlags |= BTCF_Pinned; -} -SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){ - assert( (pCur->curFlags & BTCF_Pinned)!=0 ); - pCur->curFlags &= ~BTCF_Pinned; -} - -/* -** 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); -} - /* ** Return the number of bytes of payload for the entry that pCur is ** currently pointing to. For table btrees, this will be the amount ** of data. For index btrees, this will be the size of the key. ** @@ -75687,40 +63937,21 @@ assert( pCur->eState==CURSOR_VALID ); getCellInfo(pCur); return pCur->info.nPayload; } -/* -** Return an upper bound on the size of any record for the table -** that the cursor is pointing into. -** -** This is an optimization. Everything will still work if this -** routine always returns 2147483647 (which is the largest record -** that SQLite can handle) or more. But returning a smaller value might -** prevent large memory allocations when trying to interpret a -** corrupt database. -** -** The current implementation merely returns the size of the underlying -** database file. -*/ -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage; -} - /* ** Given the page number of an overflow page in the database (parameter -** ovfl), this function finds the page number of the next page in the +** ovfl), this function finds the page number of the next page in the ** linked list of overflow pages. If possible, it uses the auto-vacuum -** pointer-map data instead of reading the content of page ovfl to do so. +** pointer-map data instead of reading the content of page ovfl to do so. ** ** If an error occurs an SQLite error code is returned. Otherwise: ** -** The page number of the next overflow page in the linked list is -** written to *pPgnoNext. If page ovfl is the last page in its linked -** list, *pPgnoNext is set to zero. +** The page number of the next overflow page in the linked list is +** written to *pPgnoNext. If page ovfl is the last page in its linked +** list, *pPgnoNext is set to zero. ** ** If ppPage is not NULL, and a reference to the MemPage object corresponding ** to page number pOvfl was obtained, then *ppPage is set to point to that ** reference. It is the responsibility of the caller to call releasePage() ** on *ppPage to free the reference. In no reference was obtained (because @@ -75740,13 +63971,13 @@ assert( sqlite3_mutex_held(pBt->mutex) ); assert(pPgnoNext); #ifndef SQLITE_OMIT_AUTOVACUUM /* Try to find the next page in the overflow list using the - ** autovacuum pointer-map pages. Guess that the next page in - ** the overflow list is page number (ovfl+1). If that guess turns - ** out to be wrong, fall back to loading the data of page + ** autovacuum pointer-map pages. Guess that the next page in + ** the overflow list is page number (ovfl+1). If that guess turns + ** out to be wrong, fall back to loading the data of page ** number ovfl to determine the next page number. */ if( pBt->autoVacuum ){ Pgno pgno; Pgno iGuess = ovfl+1; @@ -75830,12 +64061,12 @@ ** 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 ** this function may allocate space for and lazily populate -** the overflow page-list cache array (BtCursor.aOverflow). -** Subsequent calls use this cache to make seeking to the supplied offset +** the overflow page-list cache array (BtCursor.aOverflow). +** Subsequent calls use this cache to make seeking to the supplied offset ** more efficient. ** ** Once an overflow page-list cache has been allocated, it must be ** invalidated if some other cursor writes to the same table, or if ** the cursor is moved to a different row. Additionally, in auto-vacuum @@ -75847,28 +64078,26 @@ */ static int accessPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 offset, /* Begin reading this far into payload */ u32 amt, /* Read this many bytes */ - unsigned char *pBuf, /* Write the bytes into this buffer */ + unsigned char *pBuf, /* Write the bytes into this buffer */ int eOp /* zero to read. non-zero to write. */ ){ unsigned char *aPayload; int rc = SQLITE_OK; int iIdx = 0; - MemPage *pPage = pCur->pPage; /* Btree page of current entry */ + MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ #ifdef SQLITE_DIRECT_OVERFLOW_READ unsigned char * const pBufStart = pBuf; /* Start of original out buffer */ #endif assert( pPage ); assert( eOp==0 || eOp==1 ); assert( pCur->eState==CURSOR_VALID ); - if( pCur->ix>=pPage->nCell ){ - return SQLITE_CORRUPT_PAGE(pPage); - } + assert( pCur->ixnCell ); assert( cursorHoldsMutex(pCur) ); getCellInfo(pCur); aPayload = pCur->info.pPayload; assert( offset+amt <= pCur->info.nPayload ); @@ -75878,11 +64107,11 @@ /* Trying to read or write past the end of the data is an error. The ** conditional above is really: ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } /* Check if data must be read/written to/from the btree page itself. */ if( offsetinfo.nLocal ){ int a = amt; @@ -75911,34 +64140,24 @@ ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array ** means "not yet known" (the cache is lazily populated). */ if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; - if( pCur->aOverflow==0 - || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow) - ){ - Pgno *aNew; - if( sqlite3FaultSim(413) ){ - aNew = 0; - }else{ - aNew = (Pgno*)sqlite3Realloc(pCur->aOverflow, nOvfl*2*sizeof(Pgno)); - } + if( nOvfl>pCur->nOvflAlloc ){ + Pgno *aNew = (Pgno*)sqlite3Realloc( + pCur->aOverflow, nOvfl*2*sizeof(Pgno) + ); if( aNew==0 ){ return SQLITE_NOMEM_BKPT; }else{ + pCur->nOvflAlloc = nOvfl*2; pCur->aOverflow = aNew; } } memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); pCur->curFlags |= BTCF_ValidOvfl; }else{ - /* Sanity check the validity of the overflow page cache */ - assert( pCur->aOverflow[0]==nextPage - || pCur->aOverflow[0]==0 - || CORRUPT_DB ); - assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 ); - /* 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] ){ @@ -75949,11 +64168,10 @@ } assert( rc==SQLITE_OK && amt>0 ); while( nextPage ){ /* If required, populate the overflow page-list cache. */ - if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT; assert( pCur->aOverflow[iIdx]==0 || pCur->aOverflow[iIdx]==nextPage || CORRUPT_DB ); pCur->aOverflow[iIdx] = nextPage; @@ -75974,35 +64192,39 @@ offset -= ovflSize; }else{ /* Need to read this page properly. It contains some of the ** range of data that is being read (eOp==0) or written (eOp!=0). */ +#ifdef SQLITE_DIRECT_OVERFLOW_READ + sqlite3_file *fd; /* File from which to do direct overflow read */ +#endif int a = amt; if( a + offset > ovflSize ){ a = ovflSize - offset; } #ifdef SQLITE_DIRECT_OVERFLOW_READ /* If all the following are true: ** - ** 1) this is a read operation, and + ** 1) this is a read operation, and ** 2) data is required from the start of this overflow page, and - ** 3) there are no dirty pages in the page-cache + ** 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 + ** 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==0 /* (1) */ && offset==0 /* (2) */ - && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */ + && pBt->inTransaction==TRANS_READ /* (3) */ + && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */ + && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */ && &pBuf[-4]>=pBufStart /* (6) */ ){ - sqlite3_file *fd = sqlite3PagerFile(pBt->pPager); u8 aSave[4]; u8 *aWrite = &pBuf[-4]; assert( aWrite>=pBufStart ); /* due to (6) */ memcpy(aSave, aWrite, 4); rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); @@ -76033,11 +64255,11 @@ } } if( rc==SQLITE_OK && amt>0 ){ /* Overflow chain ends prematurely */ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } return rc; } /* @@ -76058,11 +64280,12 @@ ** the available payload. */ 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->pPage ); + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + assert( pCur->ixapPage[pCur->iPage]->nCell ); return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } /* ** This variant of sqlite3BtreePayload() works even if the cursor has not @@ -76093,11 +64316,11 @@ } } #endif /* SQLITE_OMIT_INCRBLOB */ /* -** Return a pointer to payload information from the entry that the +** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of ** the key if index btrees (pPage->intKey==0) and is the data for ** table btrees (pPage->intKey==1). The number of bytes of available ** key/data is written into *pAmt. If *pAmt==0, then the value ** returned will not be a valid pointer. @@ -76115,27 +64338,22 @@ */ static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 *pAmt /* Write the number of available bytes here */ ){ - int amt; - assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage); + u32 amt; + assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorOwnsBtShared(pCur) ); - assert( pCur->ixpPage->nCell || CORRUPT_DB ); + assert( pCur->ixapPage[pCur->iPage]->nCell ); assert( pCur->info.nSize>0 ); - 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; + 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; return (void*)pCur->info.pPayload; } /* @@ -76165,41 +64383,30 @@ ** the new child page does not match the flags field of the parent (i.e. ** if an intkey page appears to be the parent of a non-intkey page, or ** vice-versa). */ static int moveToChild(BtCursor *pCur, u32 newPgno){ - int rc; + BtShared *pBt = pCur->pBt; + assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPageiPage>=0 ); if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ return SQLITE_CORRUPT_BKPT; } pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - pCur->aiIdx[pCur->iPage] = pCur->ix; - pCur->apPage[pCur->iPage] = pCur->pPage; + pCur->aiIdx[pCur->iPage++] = pCur->ix; pCur->ix = 0; - pCur->iPage++; - rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags); - assert( pCur->pPage!=0 || rc!=SQLITE_OK ); - if( rc==SQLITE_OK - && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey) - ){ - releasePage(pCur->pPage); - rc = SQLITE_CORRUPT_PGNO(newPgno); - } - if( rc ){ - pCur->pPage = pCur->apPage[--pCur->iPage]; - } - return rc; + return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], + pCur, pCur->curPagerFlags); } #ifdef SQLITE_DEBUG /* -** Page pParent is an internal (non-leaf) tree page. This function +** Page pParent is an internal (non-leaf) tree page. This function ** asserts that page number iChild is the left-child if the iIdx'th ** cell in page pParent. Or, if iIdx is equal to the total number of ** cells in pParent, that page number iChild is the right-child of ** the page. */ @@ -76212,11 +64419,11 @@ }else{ assert( get4byte(findCell(pParent, iIdx))==iChild ); } } #else -# define assertParentIndex(x,y,z) +# define assertParentIndex(x,y,z) #endif /* ** Move the cursor up to the parent page. ** @@ -76224,47 +64431,44 @@ ** to the page we are coming from. If we are coming from the ** right-most child page then pCur->idx is set to one more than ** 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->pPage ); + assert( pCur->apPage[pCur->iPage] ); assertParentIndex( - pCur->apPage[pCur->iPage-1], - pCur->aiIdx[pCur->iPage-1], - pCur->pPage->pgno + pCur->apPage[pCur->iPage-1], + pCur->aiIdx[pCur->iPage-1], + pCur->apPage[pCur->iPage]->pgno ); testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); pCur->ix = pCur->aiIdx[pCur->iPage-1]; - pLeaf = pCur->pPage; - pCur->pPage = pCur->apPage[--pCur->iPage]; - releasePageNotNull(pLeaf); + releasePageNotNull(pCur->apPage[pCur->iPage--]); } /* ** Move the cursor to point to the root page of its b-tree structure. ** ** If the table has a virtual root page, then the cursor is moved to point ** to the virtual root page instead of the actual root page. A table has a -** virtual root page when the actual root page contains no cells and a +** virtual root page when the actual root page contains no cells and a ** single child page. This can only happen with the table rooted at page 1. ** -** If the b-tree structure is empty, the cursor state is set to -** 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 the b-tree structure is empty, the cursor state is set to +** CURSOR_INVALID. Otherwise, the cursor is set to point to the first +** cell located on the root (or virtual root) page and the cursor state +** is set to CURSOR_VALID. ** ** If this function returns successfully, it may be assumed that the -** page-header flags indicate that the [virtual] root-page is the expected +** page-header flags indicate that the [virtual] root-page is the expected ** kind of b-tree page (i.e. if when opening the cursor the caller did not ** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D, -** indicating a table b-tree, or if the caller did specify a KeyInfo +** indicating a table b-tree, or if the caller did specify a KeyInfo ** structure the flags byte is set to 0x02 or 0x0A, indicating an index ** b-tree). */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; @@ -76272,66 +64476,64 @@ assert( cursorOwnsBtShared(pCur) ); assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); - assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 ); - assert( pCur->pgnoRoot>0 || pCur->iPage<0 ); + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + if( pCur->eState==CURSOR_FAULT ){ + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; + } + sqlite3BtreeClearCursor(pCur); + } if( pCur->iPage>=0 ){ if( pCur->iPage ){ - releasePageNotNull(pCur->pPage); - while( --pCur->iPage ){ - releasePageNotNull(pCur->apPage[pCur->iPage]); - } - pRoot = pCur->pPage = pCur->apPage[0]; + do{ + assert( pCur->apPage[pCur->iPage]!=0 ); + releasePageNotNull(pCur->apPage[pCur->iPage--]); + }while( pCur->iPage); goto skip_init; } }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; - return SQLITE_EMPTY; + return SQLITE_OK; }else{ assert( pCur->iPage==(-1) ); - if( pCur->eState>=CURSOR_REQUIRESEEK ){ - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - sqlite3BtreeClearCursor(pCur); - } - rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage, - pCur->curPagerFlags); + rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], + 0, pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; - return rc; + return rc; } pCur->iPage = 0; - pCur->curIntKey = pCur->pPage->intKey; + pCur->curIntKey = pCur->apPage[0]->intKey; } - pRoot = pCur->pPage; - assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB ); + pRoot = pCur->apPage[0]; + assert( pRoot->pgno==pCur->pgnoRoot ); /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is ** NULL, the caller expects a table b-tree. If this is not the case, - ** return an SQLITE_CORRUPT error. + ** return an SQLITE_CORRUPT error. ** ** Earlier versions of SQLite assumed that this test could not fail ** if the root page was already loaded when this function was called (i.e. - ** if pCur->iPage>=0). But this is not so if the database is corrupted - ** in such a way that page pRoot is linked into a second b-tree table + ** if pCur->iPage>=0). But this is not so if the database is corrupted + ** in such a way that page pRoot is linked into a second b-tree table ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - return SQLITE_CORRUPT_PAGE(pCur->pPage); + return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno); } -skip_init: +skip_init: pCur->ix = 0; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); + pRoot = pCur->apPage[0]; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ Pgno subpage; if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; @@ -76338,11 +64540,10 @@ subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); pCur->eState = CURSOR_VALID; rc = moveToChild(pCur, subpage); }else{ pCur->eState = CURSOR_INVALID; - rc = SQLITE_EMPTY; } return rc; } /* @@ -76357,11 +64558,11 @@ int rc = SQLITE_OK; MemPage *pPage; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ assert( pCur->ixnCell ); pgno = get4byte(findCell(pPage, pCur->ix)); rc = moveToChild(pCur, pgno); } return rc; @@ -76382,11 +64583,11 @@ int rc = SQLITE_OK; MemPage *pPage = 0; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( !(pPage = pCur->pPage)->leaf ){ + while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->ix = pPage->nCell; rc = moveToChild(pCur, pgno); if( rc ) return rc; } @@ -76405,553 +64606,332 @@ assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ - assert( pCur->pPage->nCell>0 ); - *pRes = 0; - rc = moveToLeftmost(pCur); - }else if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); - *pRes = 1; - 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); + } } return rc; } -#ifdef SQLITE_DEBUG -/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that -** this flags are true for a consistent database. -** -** This routine is is called from within assert() statements only. -** It is an internal verification routine and does not appear in production -** builds. -*/ -static int cursorIsAtLastEntry(BtCursor *pCur){ - int ii; - for(ii=0; iiiPage; ii++){ - if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0; - } - return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0; -} -#endif - /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ -static SQLITE_NOINLINE int btreeLast(BtCursor *pCur, int *pRes){ - int rc = moveToRoot(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->eState==CURSOR_VALID ); - *pRes = 0; - rc = moveToRightmost(pCur); - if( rc==SQLITE_OK ){ - pCur->curFlags |= BTCF_AtLast; - }else{ - pCur->curFlags &= ~BTCF_AtLast; - } - }else if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); - *pRes = 1; - rc = SQLITE_OK; - } - return rc; -} SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ + int rc; + assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); /* If the cursor already points to the last entry, this is a no-op. */ if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ - assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB ); - *pRes = 0; +#ifdef SQLITE_DEBUG + /* This block serves to assert() that the cursor really does point + ** to the last entry in the b-tree. */ + int ii; + for(ii=0; iiiPage; ii++){ + assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); + } + assert( pCur->ix==pCur->apPage[pCur->iPage]->nCell-1 ); + assert( pCur->apPage[pCur->iPage]->leaf ); +#endif return SQLITE_OK; } - return btreeLast(pCur, pRes); + + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( CURSOR_INVALID==pCur->eState ){ + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); + *pRes = 1; + }else{ + assert( pCur->eState==CURSOR_VALID ); + *pRes = 0; + rc = moveToRightmost(pCur); + if( rc==SQLITE_OK ){ + pCur->curFlags |= BTCF_AtLast; + }else{ + pCur->curFlags &= ~BTCF_AtLast; + } + + } + } + return rc; } -/* Move the cursor so that it points to an entry in a table (a.k.a INTKEY) -** table near the key intKey. Return a success code. +/* Move the cursor so that it points to an entry near the key +** specified by pIdxKey or intKey. Return a success code. +** +** For INTKEY tables, the intKey parameter is used. pIdxKey +** must be NULL. For index tables, pIdxKey is used and intKey +** is ignored. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it ** were present. The cursor might point to an entry that comes ** before or after the key. ** ** An integer is written into *pRes which is the result of -** comparing the key with the entry to which the cursor is +** comparing the key with the entry to which the cursor is ** pointing. The meaning of the integer written into ** *pRes is as follows: ** ** *pRes<0 The cursor is left pointing at an entry that -** is smaller than intKey or if the table is empty +** is smaller than intKey/pIdxKey or if the table is empty ** and the cursor is therefore left point to nothing. ** ** *pRes==0 The cursor is left pointing at an entry that -** exactly matches intKey. +** exactly matches intKey/pIdxKey. ** ** *pRes>0 The cursor is left pointing at an entry that -** is larger than intKey. +** is larger than intKey/pIdxKey. +** +** For index tables, the pIdxKey->eqSeen field is set to 1 if there +** exists an entry in the table that exactly matches pIdxKey. */ -SQLITE_PRIVATE int sqlite3BtreeTableMoveto( +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( BtCursor *pCur, /* The cursor to be moved */ + UnpackedRecord *pIdxKey, /* Unpacked index key */ i64 intKey, /* The table key */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Write search results here */ ){ int rc; + RecordCompare xRecordCompare; assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( pRes ); - assert( pCur->pKeyInfo==0 ); - assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 ); + assert( (pIdxKey==0)==(pCur->pKeyInfo==0) ); + assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) ); /* If the cursor is already positioned at the point we are trying ** to move to, then just return without doing any work */ - if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){ + if( pIdxKey==0 + && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 + ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; } if( pCur->info.nKeycurFlags & BTCF_AtLast)!=0 ){ - assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB ); *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 slowly. */ - if( pCur->info.nKey+1==intKey ){ + ** 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 ){ + }else if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + }else{ return rc; } } } } -#ifdef SQLITE_DEBUG - pCur->pBtree->nSeek++; /* Performance measurement during testing */ -#endif + if( pIdxKey ){ + xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); + pIdxKey->errCode = 0; + assert( pIdxKey->default_rc==1 + || pIdxKey->default_rc==0 + || pIdxKey->default_rc==-1 + ); + }else{ + xRecordCompare = 0; /* All keys are integers */ + } 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->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 ); - + 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->curIntKey || pIdxKey ); for(;;){ int lwr, upr, idx, c; Pgno chldPg; - MemPage *pPage = pCur->pPage; + MemPage *pPage = pCur->apPage[pCur->iPage]; u8 *pCell; /* Pointer to current cell in pPage */ /* pPage->nCell must be greater than zero. If this is the root-page ** the cursor would have been INVALID above and this for(;;) loop ** not run. If this is not the root-page, then the moveToChild() routine ** would have already detected db corruption. Similarly, pPage must ** be the right kind (index or table) of b-tree page. Otherwise ** a moveToChild() or moveToRoot() call would have detected corruption. */ assert( pPage->nCell>0 ); - assert( pPage->intKey ); + assert( pPage->intKey==(pIdxKey==0) ); lwr = 0; upr = pPage->nCell-1; assert( biasRight==0 || biasRight==1 ); idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ - for(;;){ - i64 nCellKey; - pCell = findCellPastPtr(pPage, idx); - if( pPage->intKeyLeaf ){ - while( 0x80 <= *(pCell++) ){ - if( pCell>=pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - } - } - getVarint(pCell, (u64*)&nCellKey); - if( nCellKeyupr ){ c = -1; break; } - }else if( nCellKey>intKey ){ - upr = idx-1; - if( lwr>upr ){ c = +1; break; } - }else{ - assert( nCellKey==intKey ); - pCur->ix = (u16)idx; - if( !pPage->leaf ){ - lwr = idx; - goto moveto_table_next_layer; - }else{ - pCur->curFlags |= BTCF_ValidNKey; - pCur->info.nKey = nCellKey; - pCur->info.nSize = 0; + 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_PGNO(pPage->pgno); + } + } + } + getVarint(pCell, (u64*)&nCellKey); + if( nCellKeyupr ){ c = -1; break; } + }else if( nCellKey>intKey ){ + upr = idx-1; + if( lwr>upr ){ c = +1; break; } + }else{ + assert( nCellKey==intKey ); + 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; + return SQLITE_OK; + } + } + assert( lwr+upr>=0 ); + idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */ + } + }else{ + for(;;){ + int nCell; /* Size of the pCell cell in bytes */ + pCell = findCellPastPtr(pPage, idx); + + /* The maximum supported page-size is 65536 bytes. This means that + ** the maximum number of record bytes stored on an index B-Tree + ** page is less than 16384 bytes and may be stored as a 2-byte + ** varint. This information is used to attempt to avoid parsing + ** the entire cell by checking for the cases where the record is + ** stored entirely within the b-tree page by inspecting the first + ** 2 bytes of the cell. + */ + nCell = pCell[0]; + if( nCell<=pPage->max1bytePayload ){ + /* This branch runs if the record-size field of the cell is a + ** single byte varint and the record fits entirely on the main + ** b-tree page. */ + testcase( pCell+nCell+1==pPage->aDataEnd ); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + }else if( !(pCell[1] & 0x80) + && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal + ){ + /* The record-size field is a 2 byte varint and the record + ** fits entirely on the main b-tree page. */ + testcase( pCell+nCell+2==pPage->aDataEnd ); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + }else{ + /* The record flows over onto one or more overflow pages. In + ** this case the whole cell needs to be parsed, a buffer allocated + ** and accessPayload() used to retrieve the record into the + ** buffer before VdbeRecordCompare() can be called. + ** + ** If the record is corrupt, the xRecordCompare routine may read + ** up to two varints past the end of the buffer. An extra 18 + ** bytes of padding is allocated at the end of the buffer in + ** case this happens. */ + void *pCellKey; + u8 * const pCellBody = pCell - pPage->childPtrSize; + pPage->xParseCell(pPage, pCellBody, &pCur->info); + nCell = (int)pCur->info.nKey; + testcase( nCell<0 ); /* True if key size is 2^32 or more */ + testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */ + testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ + testcase( nCell==2 ); /* Minimum legal index key size */ + if( nCell<2 ){ + rc = SQLITE_CORRUPT_PGNO(pPage->pgno); + goto moveto_finish; + } + pCellKey = sqlite3Malloc( nCell+18 ); + if( pCellKey==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto moveto_finish; + } + 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; + } + c = xRecordCompare(nCell, pCellKey, pIdxKey); + sqlite3_free(pCellKey); + } + assert( + (pIdxKey->errCode!=SQLITE_CORRUPT || c==0) + && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed) + ); + if( c<0 ){ + lwr = idx+1; + }else if( c>0 ){ + upr = idx-1; + }else{ + assert( c==0 ); *pRes = 0; - return SQLITE_OK; + rc = SQLITE_OK; + pCur->ix = (u16)idx; + if( pIdxKey->errCode ) rc = SQLITE_CORRUPT; + goto moveto_finish; } + if( lwr>upr ) break; + assert( lwr+upr>=0 ); + idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */ } - assert( lwr+upr>=0 ); - idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */ } - assert( lwr==upr+1 || !pPage->leaf ); + assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); assert( pPage->isInit ); if( pPage->leaf ){ - assert( pCur->ixpPage->nCell ); + assert( pCur->ixapPage[pCur->iPage]->nCell ); pCur->ix = (u16)idx; *pRes = c; rc = SQLITE_OK; - goto moveto_table_finish; + goto moveto_finish; } -moveto_table_next_layer: +moveto_next_layer: if( lwr>=pPage->nCell ){ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); }else{ chldPg = get4byte(findCell(pPage, lwr)); } pCur->ix = (u16)lwr; rc = moveToChild(pCur, chldPg); if( rc ) break; } -moveto_table_finish: - pCur->info.nSize = 0; - assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); - return rc; -} - -/* -** Compare the "idx"-th cell on the page the cursor pCur is currently -** pointing to to pIdxKey using xRecordCompare. Return negative or -** zero if the cell is less than or equal pIdxKey. Return positive -** if unknown. -** -** Return value negative: Cell at pCur[idx] less than pIdxKey -** -** Return value is zero: Cell at pCur[idx] equals pIdxKey -** -** Return value positive: Nothing is known about the relationship -** of the cell at pCur[idx] and pIdxKey. -** -** This routine is part of an optimization. It is always safe to return -** a positive value as that will cause the optimization to be skipped. -*/ -static int indexCellCompare( - BtCursor *pCur, - int idx, - UnpackedRecord *pIdxKey, - RecordCompare xRecordCompare -){ - MemPage *pPage = pCur->pPage; - int c; - int nCell; /* Size of the pCell cell in bytes */ - u8 *pCell = findCellPastPtr(pPage, idx); - - nCell = pCell[0]; - if( nCell<=pPage->max1bytePayload ){ - /* This branch runs if the record-size field of the cell is a - ** single byte varint and the record fits entirely on the main - ** b-tree page. */ - testcase( pCell+nCell+1==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); - }else if( !(pCell[1] & 0x80) - && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal - ){ - /* The record-size field is a 2 byte varint and the record - ** fits entirely on the main b-tree page. */ - testcase( pCell+nCell+2==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); - }else{ - /* If the record extends into overflow pages, do not attempt - ** the optimization. */ - c = 99; - } - return c; -} - -/* -** Return true (non-zero) if pCur is current pointing to the last -** page of a table. -*/ -static int cursorOnLastPage(BtCursor *pCur){ - int i; - assert( pCur->eState==CURSOR_VALID ); - for(i=0; iiPage; i++){ - MemPage *pPage = pCur->apPage[i]; - if( pCur->aiIdx[i]nCell ) return 0; - } - return 1; -} - -/* Move the cursor so that it points to an entry in an index table -** near the key pIdxKey. Return a success code. -** -** If an exact match is not found, then the cursor is always -** left pointing at a leaf page which would hold the entry if it -** were present. The cursor might point to an entry that comes -** before or after the key. -** -** An integer is written into *pRes which is the result of -** comparing the key with the entry to which the cursor is -** pointing. The meaning of the integer written into -** *pRes is as follows: -** -** *pRes<0 The cursor is left pointing at an entry that -** is smaller than pIdxKey or if the table is empty -** and the cursor is therefore left point to nothing. -** -** *pRes==0 The cursor is left pointing at an entry that -** exactly matches pIdxKey. -** -** *pRes>0 The cursor is left pointing at an entry that -** is larger than pIdxKey. -** -** The pIdxKey->eqSeen field is set to 1 if there -** exists an entry in the table that exactly matches pIdxKey. -*/ -SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( - BtCursor *pCur, /* The cursor to be moved */ - UnpackedRecord *pIdxKey, /* Unpacked index key */ - int *pRes /* Write search results here */ -){ - int rc; - RecordCompare xRecordCompare; - - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( pRes ); - assert( pCur->pKeyInfo!=0 ); - -#ifdef SQLITE_DEBUG - pCur->pBtree->nSeek++; /* Performance measurement during testing */ -#endif - - xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); - pIdxKey->errCode = 0; - assert( pIdxKey->default_rc==1 - || pIdxKey->default_rc==0 - || pIdxKey->default_rc==-1 - ); - - - /* Check to see if we can skip a lot of work. Two cases: - ** - ** (1) If the cursor is already pointing to the very last cell - ** in the table and the pIdxKey search key is greater than or - ** equal to that last cell, then no movement is required. - ** - ** (2) If the cursor is on the last page of the table and the first - ** cell on that last page is less than or equal to the pIdxKey - ** search key, then we can start the search on the current page - ** without needing to go back to root. - */ - if( pCur->eState==CURSOR_VALID - && pCur->pPage->leaf - && cursorOnLastPage(pCur) - ){ - int c; - if( pCur->ix==pCur->pPage->nCell-1 - && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0 - && pIdxKey->errCode==SQLITE_OK - ){ - *pRes = c; - return SQLITE_OK; /* Cursor already pointing at the correct spot */ - } - if( pCur->iPage>0 - && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0 - && pIdxKey->errCode==SQLITE_OK - ){ - pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast); - if( !pCur->pPage->isInit ){ - return SQLITE_CORRUPT_BKPT; - } - goto bypass_moveto_root; /* Start search on the current page */ - } - pIdxKey->errCode = SQLITE_OK; - } - - rc = moveToRoot(pCur); - if( rc ){ - if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); - *pRes = -1; - return SQLITE_OK; - } - return rc; - } - -bypass_moveto_root: - assert( pCur->pPage ); - assert( pCur->pPage->isInit ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->pPage->nCell > 0 ); - assert( pCur->curIntKey==0 ); - assert( pIdxKey!=0 ); - for(;;){ - int lwr, upr, idx, c; - Pgno chldPg; - 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 - ** the cursor would have been INVALID above and this for(;;) loop - ** not run. If this is not the root-page, then the moveToChild() routine - ** would have already detected db corruption. Similarly, pPage must - ** be the right kind (index or table) of b-tree page. Otherwise - ** a moveToChild() or moveToRoot() call would have detected corruption. */ - assert( pPage->nCell>0 ); - assert( pPage->intKey==0 ); - lwr = 0; - upr = pPage->nCell-1; - idx = upr>>1; /* idx = (lwr+upr)/2; */ - for(;;){ - int nCell; /* Size of the pCell cell in bytes */ - pCell = findCellPastPtr(pPage, idx); - - /* The maximum supported page-size is 65536 bytes. This means that - ** the maximum number of record bytes stored on an index B-Tree - ** page is less than 16384 bytes and may be stored as a 2-byte - ** varint. This information is used to attempt to avoid parsing - ** the entire cell by checking for the cases where the record is - ** stored entirely within the b-tree page by inspecting the first - ** 2 bytes of the cell. - */ - nCell = pCell[0]; - if( nCell<=pPage->max1bytePayload ){ - /* This branch runs if the record-size field of the cell is a - ** single byte varint and the record fits entirely on the main - ** b-tree page. */ - testcase( pCell+nCell+1==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); - }else if( !(pCell[1] & 0x80) - && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal - ){ - /* The record-size field is a 2 byte varint and the record - ** fits entirely on the main b-tree page. */ - testcase( pCell+nCell+2==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); - }else{ - /* The record flows over onto one or more overflow pages. In - ** this case the whole cell needs to be parsed, a buffer allocated - ** and accessPayload() used to retrieve the record into the - ** buffer before VdbeRecordCompare() can be called. - ** - ** If the record is corrupt, the xRecordCompare routine may read - ** up to two varints past the end of the buffer. An extra 18 - ** bytes of padding is allocated at the end of the buffer in - ** case this happens. */ - void *pCellKey; - u8 * const pCellBody = pCell - pPage->childPtrSize; - const int nOverrun = 18; /* Size of the overrun padding */ - pPage->xParseCell(pPage, pCellBody, &pCur->info); - nCell = (int)pCur->info.nKey; - testcase( nCell<0 ); /* True if key size is 2^32 or more */ - testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */ - testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ - testcase( nCell==2 ); /* Minimum legal index key size */ - if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){ - rc = SQLITE_CORRUPT_PAGE(pPage); - goto moveto_index_finish; - } - pCellKey = sqlite3Malloc( nCell+nOverrun ); - if( pCellKey==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto moveto_index_finish; - } - pCur->ix = (u16)idx; - rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); - memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */ - pCur->curFlags &= ~BTCF_ValidOvfl; - if( rc ){ - sqlite3_free(pCellKey); - goto moveto_index_finish; - } - c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); - sqlite3_free(pCellKey); - } - assert( - (pIdxKey->errCode!=SQLITE_CORRUPT || c==0) - && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed) - ); - if( c<0 ){ - lwr = idx+1; - }else if( c>0 ){ - upr = idx-1; - }else{ - assert( c==0 ); - *pRes = 0; - rc = SQLITE_OK; - pCur->ix = (u16)idx; - if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT; - goto moveto_index_finish; - } - if( lwr>upr ) break; - assert( lwr+upr>=0 ); - idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */ - } - assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); - assert( pPage->isInit ); - if( pPage->leaf ){ - assert( pCur->ixpPage->nCell || CORRUPT_DB ); - pCur->ix = (u16)idx; - *pRes = c; - rc = SQLITE_OK; - goto moveto_index_finish; - } - if( lwr>=pPage->nCell ){ - chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); - }else{ - chldPg = get4byte(findCell(pPage, lwr)); - } - - /* This block is similar to an in-lined version of: - ** - ** pCur->ix = (u16)lwr; - ** rc = moveToChild(pCur, chldPg); - ** if( rc ) break; - */ - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ - return SQLITE_CORRUPT_BKPT; - } - pCur->aiIdx[pCur->iPage] = (u16)lwr; - pCur->apPage[pCur->iPage] = pCur->pPage; - pCur->ix = 0; - pCur->iPage++; - rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur->curPagerFlags); - if( rc==SQLITE_OK - && (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey) - ){ - releasePage(pCur->pPage); - rc = SQLITE_CORRUPT_PGNO(chldPg); - } - if( rc ){ - pCur->pPage = pCur->apPage[--pCur->iPage]; - break; - } - /* - ***** End of in-lined moveToChild() call */ - } -moveto_index_finish: +moveto_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } @@ -76971,35 +64951,34 @@ return (CURSOR_VALID!=pCur->eState); } /* ** Return an estimate for the number of rows in the table that pCur is -** pointing to. Return a negative number if no estimate is currently +** pointing to. Return a negative number if no estimate is currently ** available. */ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ i64 n; u8 i; assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - /* Currently this interface is only called by the OP_IfSizeBetween - ** opcode and the OP_Count opcode with P3=1. In either case, - ** the cursor will always be valid unless the btree is empty. */ - if( pCur->eState!=CURSOR_VALID ) return 0; - if( NEVER(pCur->pPage->leaf==0) ) return -1; - - n = pCur->pPage->nCell; - for(i=0; iiPage; i++){ + /* 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->apPage[pCur->iPage]->leaf==0) ) return -1; + + for(n=1, i=0; i<=pCur->iPage; i++){ n *= pCur->apPage[i]->nCell; } return n; } /* -** Advance the cursor to the next entry in the database. +** Advance the cursor to the next entry in the database. ** Return value: ** ** SQLITE_OK success ** SQLITE_DONE cursor is already pointing at the last element ** otherwise some kind of error occurred @@ -77020,31 +64999,41 @@ int rc; int idx; MemPage *pPage; assert( cursorOwnsBtShared(pCur) ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); if( pCur->eState!=CURSOR_VALID ){ assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); rc = restoreCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } if( CURSOR_INVALID==pCur->eState ){ return SQLITE_DONE; } - if( pCur->eState==CURSOR_SKIPNEXT ){ + if( pCur->skipNext ){ + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT ); pCur->eState = CURSOR_VALID; - if( pCur->skipNext>0 ) return SQLITE_OK; + if( pCur->skipNext>0 ){ + pCur->skipNext = 0; + return SQLITE_OK; + } + pCur->skipNext = 0; } } - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; idx = ++pCur->ix; - if( sqlite3FaultSim(412) ) pPage->isInit = 0; - if( !pPage->isInit ){ - return SQLITE_CORRUPT_BKPT; - } + assert( pPage->isInit ); + + /* If the database file is corrupt, it is possible for the value of idx + ** to be invalid here. This can only occur if a second cursor modifies + ** the page while cursor pCur is holding a reference to it. Which can + ** only happen if the database is corrupt in such a way as to link the + ** page into more than one b-tree structure. */ + testcase( idx>pPage->nCell ); if( idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); if( rc ) return rc; @@ -77054,11 +65043,11 @@ if( pCur->iPage==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_DONE; } moveToParent(pCur); - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; }while( pCur->ix>=pPage->nCell ); if( pPage->intKey ){ return sqlite3BtreeNext(pCur, 0); }else{ return SQLITE_OK; @@ -77073,14 +65062,15 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){ MemPage *pPage; UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */ assert( cursorOwnsBtShared(pCur) ); assert( flags==0 || flags==1 ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur); - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; if( (++pCur->ix)>=pPage->nCell ){ pCur->ix--; return btreeNext(pCur); } if( pPage->leaf ){ @@ -77113,10 +65103,11 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){ int rc; MemPage *pPage; assert( cursorOwnsBtShared(pCur) ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 ); assert( pCur->info.nSize==0 ); if( pCur->eState!=CURSOR_VALID ){ rc = restoreCursorPosition(pCur); if( rc!=SQLITE_OK ){ @@ -77123,21 +65114,23 @@ return rc; } if( CURSOR_INVALID==pCur->eState ){ return SQLITE_DONE; } - if( CURSOR_SKIPNEXT==pCur->eState ){ + if( pCur->skipNext ){ + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT ); pCur->eState = CURSOR_VALID; - if( pCur->skipNext<0 ) return SQLITE_OK; + if( pCur->skipNext<0 ){ + pCur->skipNext = 0; + return SQLITE_OK; + } + pCur->skipNext = 0; } } - pPage = pCur->pPage; - if( sqlite3FaultSim(412) ) pPage->isInit = 0; - if( !pPage->isInit ){ - return SQLITE_CORRUPT_BKPT; - } + pPage = pCur->apPage[pCur->iPage]; + assert( pPage->isInit ); if( !pPage->leaf ){ int idx = pCur->ix; rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); if( rc ) return rc; rc = moveToRightmost(pCur); @@ -77151,11 +65144,11 @@ } assert( pCur->info.nSize==0 ); assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); pCur->ix--; - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; if( pPage->intKey && !pPage->leaf ){ rc = sqlite3BtreePrevious(pCur, 0); }else{ rc = SQLITE_OK; } @@ -77163,16 +65156,17 @@ return rc; } SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){ assert( cursorOwnsBtShared(pCur) ); assert( flags==0 || flags==1 ); + assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */ pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey); pCur->info.nSize = 0; if( pCur->eState!=CURSOR_VALID || pCur->ix==0 - || pCur->pPage->leaf==0 + || pCur->apPage[pCur->iPage]->leaf==0 ){ return btreePrevious(pCur); } pCur->ix--; return SQLITE_OK; @@ -77187,11 +65181,11 @@ ** sqlite3PagerUnref() on the new page when it is done. ** ** SQLITE_OK is returned on success. Any other return value indicates ** an error. *ppPage is set to NULL in the event of an error. ** -** If the "nearby" parameter is not 0, then an effort is made to +** If the "nearby" parameter is not 0, then an effort is made to ** locate a page close to the page number "nearby". This can be used in an ** attempt to keep related pages close to each other in the database file, ** which in turn can make database access faster. ** ** If the eMode parameter is BTALLOC_EXACT and the nearby page exists @@ -77217,12 +65211,12 @@ assert( sqlite3_mutex_held(pBt->mutex) ); assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); pPage1 = pBt->pPage1; mxPage = btreePagecount(pBt); - /* EVIDENCE-OF: R-21003-45125 The 4-byte big-endian integer at offset 36 - ** stores the total number of pages on the freelist. */ + /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36 + ** stores stores the total number of pages on the freelist. */ n = get4byte(&pPage1->aData[36]); testcase( n==mxPage-1 ); if( n>=mxPage ){ return SQLITE_CORRUPT_BKPT; } @@ -77229,11 +65223,11 @@ if( n>0 ){ /* There are pages on the freelist. Reuse one of those pages. */ Pgno iTrunk; u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ u32 nSearch = 0; /* Count of the number of search attempts */ - + /* If eMode==BTALLOC_EXACT and a query of the pointer-map ** shows that the page 'nearby' is somewhere on the free-list, then ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM @@ -77292,12 +65286,12 @@ assert( pTrunk->aData!=0 ); /* EVIDENCE-OF: R-13523-04394 The second integer on a freelist trunk page ** is the number of leaf page pointers to follow. */ k = get4byte(&pTrunk->aData[4]); if( k==0 && !searchList ){ - /* The trunk has no leaves and the list is not being searched. - ** So extract the trunk page itself and use it as the newly + /* The trunk has no leaves and the list is not being searched. + ** So extract the trunk page itself and use it as the newly ** allocated page */ assert( pPrevTrunk==0 ); rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; @@ -77304,18 +65298,18 @@ } *pPgno = iTrunk; memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; - TRACE(("ALLOCATE: %u trunk - %u free pages left\n", *pPgno, n-1)); + 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_PGNO(iTrunk); goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM - }else if( searchList - && (nearby==iTrunk || (iTrunkaData[0], &pTrunk->aData[0], 4); } }else{ - /* The trunk page is required by the caller but it contains + /* The trunk page is required by the caller but it contains ** pointers to free-list leaves. The first leaf becomes a trunk ** page in this case. */ MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); - if( iNewTrunk>mxPage ){ + if( iNewTrunk>mxPage ){ rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iNewTrunk==mxPage ); rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0); @@ -77370,11 +65364,11 @@ } put4byte(&pPrevTrunk->aData[0], iNewTrunk); } } pTrunk = 0; - TRACE(("ALLOCATE: %u trunk - %u free pages left\n", *pPgno, n-1)); + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); #endif }else if( k>0 ){ /* Extract a leaf from the trunk */ u32 closest; Pgno iPage; @@ -77405,22 +65399,22 @@ closest = 0; } iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); - if( iPage>mxPage || iPage<2 ){ + if( iPage>mxPage ){ rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iPage==mxPage ); - if( !searchList - || (iPage==nearby || (iPagepgno, n-1)); rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ) goto end_allocate_page; if( closestnPage)); + TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); @@ -77495,14 +65489,14 @@ rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); *ppPage = 0; } - TRACE(("ALLOCATE: %u from end of file\n", *pPgno)); + TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); } - assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) ); + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); end_allocate_page: releasePage(pTrunk); releasePage(pPrevTrunk); assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 ); @@ -77509,36 +65503,34 @@ assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 ); return rc; } /* -** This function is used to add page iPage to the database file free-list. +** This function is used to add page iPage to the database file free-list. ** It is assumed that the page is not already a part of the free-list. ** ** The value passed as the second argument to this function is optional. -** If the caller happens to have a pointer to the MemPage object -** corresponding to page iPage handy, it may pass it as the second value. +** If the caller happens to have a pointer to the MemPage object +** corresponding to page iPage handy, it may pass it as the second value. ** Otherwise, it may pass NULL. ** ** If a pointer to a MemPage object is passed as the second argument, ** its reference count is not altered by this function. */ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ MemPage *pTrunk = 0; /* Free-list trunk page */ - Pgno iTrunk = 0; /* Page number of free-list trunk page */ + Pgno iTrunk = 0; /* Page number of free-list trunk page */ MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ MemPage *pPage; /* Page being freed. May be NULL. */ int rc; /* Return Code */ - u32 nFree; /* Initial number of pages on free-list */ + int nFree; /* Initial number of pages on free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( CORRUPT_DB || iPage>1 ); assert( !pMemPage || pMemPage->pgno==iPage ); - if( iPage<2 || iPage>pBt->nPage ){ - return SQLITE_CORRUPT_BKPT; - } + if( iPage<2 ) return SQLITE_CORRUPT_BKPT; if( pMemPage ){ pPage = pMemPage; sqlite3PagerRef(pPage->pDbPage); }else{ pPage = btreePageLookup(pBt, iPage); @@ -77563,11 +65555,11 @@ } /* If the database supports auto-vacuum, write an entry in the pointer-map ** to indicate that the page is free. */ - if( ISAUTOVACUUM(pBt) ){ + if( ISAUTOVACUUM ){ ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); if( rc ) goto freepage_out; } /* Now manipulate the actual database free-list structure. There are two @@ -77579,14 +65571,10 @@ */ if( nFree!=0 ){ u32 nLeaf; /* Initial number of leaf cells on trunk page */ iTrunk = get4byte(&pPage1->aData[32]); - if( iTrunk>btreePagecount(pBt) ){ - rc = SQLITE_CORRUPT_BKPT; - goto freepage_out; - } rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); if( rc!=SQLITE_OK ){ goto freepage_out; } @@ -77623,18 +65611,18 @@ if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){ sqlite3PagerDontWrite(pPage->pDbPage); } rc = btreeSetHasContent(pBt, iPage); } - TRACE(("FREE-PAGE: %u leaf on trunk page %u\n",pPage->pgno,pTrunk->pgno)); + TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); goto freepage_out; } } /* If control flows to this point, then it was not possible to add the ** the page being freed as a leaf page of the first trunk in the free-list. - ** Possibly because the free-list is empty, or possibly because the + ** Possibly because the free-list is empty, or possibly because the ** first trunk in the free-list is full. Either way, the page being freed ** will become the new first trunk page in the free-list. */ if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){ goto freepage_out; @@ -77644,11 +65632,11 @@ goto freepage_out; } put4byte(pPage->aData, iTrunk); put4byte(&pPage->aData[4], 0); put4byte(&pPage1->aData[32], iPage); - TRACE(("FREE-PAGE: %u new trunk page replacing %u\n", pPage->pgno, iTrunk)); + TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk)); freepage_out: if( pPage ){ pPage->isInit = 0; } @@ -77661,45 +65649,47 @@ *pRC = freePage2(pPage->pBt, pPage, pPage->pgno); } } /* -** Free the overflow pages associated with the given Cell. +** Free any overflow pages associated with the given Cell. Write the +** local Cell size (the number of bytes on the original page, omitting +** overflow) into *pnSize. */ -static SQLITE_NOINLINE int clearCellOverflow( +static int clearCell( MemPage *pPage, /* The page that contains the Cell */ unsigned char *pCell, /* First byte of the Cell */ CellInfo *pInfo /* Size information about the cell */ ){ - BtShared *pBt; + BtShared *pBt = pPage->pBt; Pgno ovflPgno; int rc; int nOvfl; u32 ovflPageSize; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pInfo->nLocal!=pInfo->nPayload ); - testcase( pCell + pInfo->nSize == pPage->aDataEnd ); - testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); - if( pCell + pInfo->nSize > pPage->aDataEnd ){ + pPage->xParseCell(pPage, pCell, pInfo); + if( pInfo->nLocal==pInfo->nPayload ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } + if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ /* Cell extends past end of page */ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PGNO(pPage->pgno); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); - pBt = pPage->pBt; assert( pBt->usableSize > 4 ); ovflPageSize = pBt->usableSize - 4; nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize; - assert( nOvfl>0 || + assert( nOvfl>0 || (CORRUPT_DB && (pInfo->nPayload + ovflPageSize)btreePagecount(pBt) ){ - /* 0 is not a legal page number and page 1 cannot be an - ** overflow page. Therefore if ovflPgno<2 or past the end of the + /* 0 is not a legal page number and page 1 cannot be an + ** overflow page. Therefore if ovflPgno<2 or past the end of the ** file the database must be corrupt. */ return SQLITE_CORRUPT_BKPT; } if( nOvfl ){ rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); @@ -77707,15 +65697,15 @@ } if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) ) && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 ){ - /* There is no reason any cursor should have an outstanding reference + /* There is no reason any cursor should have an outstanding reference ** to an overflow page belonging to a cell that is being deleted/updated. - ** So if there exists more than one reference to this page, then it - ** must not really be an overflow page and the database must be corrupt. - ** It is helpful to detect this before calling freePage2(), as + ** So if there exists more than one reference to this page, then it + ** must not really be an overflow page and the database must be corrupt. + ** It is helpful to detect this before calling freePage2(), as ** freePage2() may zero the page contents if secure-delete mode is ** enabled. If this 'overflow' page happens to be a page that the ** caller is iterating through or using in some other way, this ** can be problematic. */ @@ -77730,25 +65720,10 @@ if( rc ) return rc; ovflPgno = iNext; } return SQLITE_OK; } - -/* Call xParseCell to compute the size of a cell. If the cell contains -** overflow, then invoke cellClearOverflow to clear out that overflow. -** Store the result code (SQLITE_OK or some error code) in rc. -** -** Implemented as macro to force inlining for performance. -*/ -#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \ - pPage->xParseCell(pPage, pCell, &sInfo); \ - if( sInfo.nLocal!=sInfo.nPayload ){ \ - rc = clearCellOverflow(pPage, pCell, &sInfo); \ - }else{ \ - rc = SQLITE_OK; \ - } - /* ** Create the byte sequence used to represent a cell on page pPage ** and write that byte sequence into pCell[]. Overflow pages are ** allocated and filled in as necessary. The calling procedure @@ -77766,24 +65741,25 @@ const BtreePayload *pX, /* Payload with which to construct the cell */ int *pnSize /* Write cell size here */ ){ int nPayload; const u8 *pSrc; - int nSrc, n, rc, mn; + int nSrc, n, rc; int spaceLeft; - MemPage *pToRelease; + MemPage *pOvfl = 0; + MemPage *pToRelease = 0; unsigned char *pPrior; unsigned char *pPayload; - BtShared *pBt; - Pgno pgnoOvfl; + BtShared *pBt = pPage->pBt; + Pgno pgnoOvfl = 0; 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[pPage->pBt->pageSize] + assert( pCellaData || pCell>=&pPage->aData[pBt->pageSize] || sqlite3PagerIswriteable(pPage->pDbPage) ); /* Fill in the header. */ nHeader = pPage->childPtrSize; if( pPage->intKey ){ @@ -77797,45 +65773,31 @@ assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); nSrc = nPayload = (int)pX->nKey; pSrc = pX->pKey; nHeader += putVarint32(&pCell[nHeader], nPayload); } - + /* 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; - pPayload[nPayload] = 0; - } + if( n<4 ) n = 4; *pnSize = 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; + 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]; + } + pPayload = &pCell[nHeader]; /* At this point variables should be set as follows: ** ** nPayload Total payload size in bytes ** pPayload Begin writing payload here @@ -77857,56 +65819,29 @@ assert( spaceLeft == info.nLocal ); } #endif /* Write the payload into the local Cell and any extra into overflow pages */ - 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; + while( nPayload>0 ){ if( spaceLeft==0 ){ - MemPage *pOvfl = 0; #ifndef SQLITE_OMIT_AUTOVACUUM Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ if( pBt->autoVacuum ){ do{ pgnoOvfl++; - } while( - PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) + } while( + PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) ); } #endif rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0); #ifndef SQLITE_OMIT_AUTOVACUUM /* If the database supports auto-vacuum, and the second or subsequent ** overflow page is being allocated, add an entry to the pointer-map - ** for that page now. + ** for that page now. ** - ** If this is the first overflow page, then write a partial entry + ** If this is the first overflow page, then write a partial entry ** to the pointer-map. If we write nothing to this pointer-map slot, ** then the optimistic overflow chain processing in clearCell() ** may misinterpret the uninitialized values and delete the ** wrong pages from the database. */ @@ -77938,10 +65873,34 @@ pPrior = pOvfl->aData; put4byte(pPrior, 0); 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; } @@ -77959,24 +65918,21 @@ u8 *ptr; /* Used to move bytes around within data[] */ int rc; /* The return code */ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; - assert( idx>=0 ); - assert( idxnCell ); + assert( idx>=0 && idxnCell ); assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->nFree>=0 ); data = pPage->aData; ptr = &pPage->aCellIdx[2*idx]; - assert( pPage->pBt->usableSize > (u32)(ptr-data) ); pc = get2byte(ptr); hdr = pPage->hdrOffset; - testcase( pc==(u32)get2byte(&data[hdr+5]) ); + testcase( pc==get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); - if( pc+sz > pPage->pBt->usableSize ){ + if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ *pRC = SQLITE_CORRUPT_BKPT; return; } rc = freeSpace(pPage, pc, sz); if( rc ){ @@ -78003,140 +65959,51 @@ ** ** If the cell content will fit on the page, then put it there. If it ** will not fit, then make a copy of the cell content into pTemp if ** pTemp is not null. Regardless of pTemp, allocate a new entry ** in pPage->apOvfl[] and make it point to the cell content (either -** in pTemp or the original pCell) and also record its index. -** Allocating a new entry in pPage->aCell[] implies that +** in pTemp or the original pCell) and also record its index. +** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. ** -** The insertCellFast() routine below works exactly the same as -** insertCell() except that it lacks the pTemp and iChild parameters -** which are assumed zero. Other than that, the two routines are the -** same. -** -** Fixes or enhancements to this routine should be reflected in -** insertCellFast()! +** *pRC must be SQLITE_OK when this routine is called. */ -static int insertCell( +static void insertCell( MemPage *pPage, /* Page into which we are copying */ int i, /* New cell becomes the i-th cell of the page */ u8 *pCell, /* Content of the new cell */ int sz, /* Bytes of content in pCell */ u8 *pTemp, /* Temp storage space for pCell, if needed */ - Pgno iChild /* If non-zero, replace first 4 bytes with this value */ + Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ + int *pRC /* Read and write return code from here */ ){ int idx = 0; /* Where to write new cell content in data[] */ int j; /* Loop counter */ u8 *data; /* The content of the whole page */ u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ + assert( *pRC==SQLITE_OK ); assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( MX_CELL(pPage->pBt)<=10921 ); assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); - assert( pPage->nFree>=0 ); - assert( iChild>0 ); + /* The cell should normally be sized correctly. However, when moving a + ** malformed cell from a leaf page to an interior page, if the cell size + ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size + ** might be less than 8 (leaf-size + pointer) on the interior node. Hence + ** the term after the || in the following assert(). */ + assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp, pCell, sz); pCell = pTemp; } - put4byte(pCell, iChild); - j = pPage->nOverflow++; - /* 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; - - /* When multiple overflows occur, they are always sequential and in - ** sorted order. This invariants arise because multiple overflows can - ** only occur when inserting divider cells into the parent page during - ** balancing, and the dividers are adjacent and sorted. - */ - assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */ - assert( j==0 || i==pPage->aiOvfl[j-1]+1 ); /* Overflows are sequential */ - }else{ - int rc = sqlite3PagerWrite(pPage->pDbPage); - if( NEVER(rc!=SQLITE_OK) ){ - return rc; - } - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - data = pPage->aData; - assert( &data[pPage->cellOffset]==pPage->aCellIdx ); - rc = allocateSpace(pPage, sz, &idx); - if( rc ){ return rc; } - /* The allocateSpace() routine guarantees the following properties - ** if it returns successfully */ - assert( idx >= 0 ); - assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); - assert( idx+sz <= (int)pPage->pBt->usableSize ); - pPage->nFree -= (u16)(2 + sz); - /* In a corrupt database where an entry in the cell index section of - ** a btree page has a value of 3 or less, the pCell value might point - ** as many as 4 bytes in front of the start of the aData buffer for - ** the source page. Make sure this does not cause problems by not - ** reading the first 4 bytes */ - memcpy(&data[idx+4], pCell+4, sz-4); - put4byte(&data[idx], iChild); - pIns = pPage->aCellIdx + i*2; - memmove(pIns+2, pIns, 2*(pPage->nCell - i)); - put2byte(pIns, idx); - pPage->nCell++; - /* increment the cell count */ - if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; - assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pPage->pBt->autoVacuum ){ - int rc2 = SQLITE_OK; - /* The cell may contain a pointer to an overflow page. If so, write - ** the entry for the overflow page into the pointer map. - */ - ptrmapPutOvflPtr(pPage, pPage, pCell, &rc2); - if( rc2 ) return rc2; - } -#endif - } - return SQLITE_OK; -} - -/* -** This variant of insertCell() assumes that the pTemp and iChild -** parameters are both zero. Use this variant in sqlite3BtreeInsert() -** for performance improvement, and also so that this variant is only -** called from that one place, and is thus inlined, and thus runs must -** faster. -** -** Fixes or enhancements to this routine should be reflected into -** the insertCell() routine. -*/ -static int insertCellFast( - MemPage *pPage, /* Page into which we are copying */ - int i, /* New cell becomes the i-th cell of the page */ - u8 *pCell, /* Content of the new cell */ - int sz /* Bytes of content in pCell */ -){ - int idx = 0; /* Where to write new cell content in data[] */ - int j; /* Loop counter */ - u8 *data; /* The content of the whole page */ - u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ - - assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); - assert( MX_CELL(pPage->pBt)<=10921 ); - assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); - assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); - assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); - assert( pPage->nFree>=0 ); - assert( pPage->nOverflow==0 ); - if( sz+2>pPage->nFree ){ + if( iChild ){ + put4byte(pCell, iChild); + } j = pPage->nOverflow++; /* 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 ); @@ -78151,153 +66018,71 @@ assert( j==0 || pPage->aiOvfl[j-1]<(u16)i ); /* Overflows in sorted order */ assert( j==0 || i==pPage->aiOvfl[j-1]+1 ); /* Overflows are sequential */ }else{ int rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ - return rc; + *pRC = rc; + return; } assert( sqlite3PagerIswriteable(pPage->pDbPage) ); data = pPage->aData; assert( &data[pPage->cellOffset]==pPage->aCellIdx ); rc = allocateSpace(pPage, sz, &idx); - if( rc ){ return rc; } + if( rc ){ *pRC = rc; return; } /* The allocateSpace() routine guarantees the following properties ** if it returns successfully */ assert( idx >= 0 ); assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); assert( idx+sz <= (int)pPage->pBt->usableSize ); pPage->nFree -= (u16)(2 + sz); memcpy(&data[idx], pCell, sz); + if( iChild ){ + put4byte(&data[idx], iChild); + } pIns = pPage->aCellIdx + i*2; memmove(pIns+2, pIns, 2*(pPage->nCell - i)); put2byte(pIns, idx); pPage->nCell++; /* increment the cell count */ if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; - assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); + assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell ); #ifndef SQLITE_OMIT_AUTOVACUUM if( pPage->pBt->autoVacuum ){ - int rc2 = SQLITE_OK; /* The cell may contain a pointer to an overflow page. If so, write ** the entry for the overflow page into the pointer map. */ - ptrmapPutOvflPtr(pPage, pPage, pCell, &rc2); - if( rc2 ) return rc2; + ptrmapPutOvflPtr(pPage, pCell, pRC); } #endif } - return SQLITE_OK; -} - -/* -** The following parameters determine how many adjacent pages get involved -** in a balancing operation. NN is the number of neighbors on either side -** of the page that participate in the balancing operation. NB is the -** total number of pages that participate, including the target page and -** NN neighbors on either side. -** -** The minimum value of NN is 1 (of course). Increasing NN above 1 -** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance -** in exchange for a larger degradation in INSERT and UPDATE performance. -** The value of NN appears to give the best results overall. -** -** (Later:) The description above makes it seem as if these values are -** tunable - as if you could change them and recompile and it would all work. -** But that is unlikely. NB has been 3 since the inception of SQLite and -** we have never tested any other value. -*/ -#define NN 1 /* Number of neighbors on either side of pPage */ -#define NB 3 /* (NN*2+1): Total pages involved in the balance */ +} /* ** A CellArray object contains a cache of pointers and sizes for a ** consecutive sequence of cells that might be held on multiple pages. -** -** The cells in this array are the divider cell or cells from the pParent -** page plus up to three child pages. There are a total of nCell cells. -** -** pRef is a pointer to one of the pages that contributes cells. This is -** used to access information such as MemPage.intKey and MemPage.pBt->pageSize -** which should be common to all pages that contribute cells to this array. -** -** apCell[] and szCell[] hold, respectively, pointers to the start of each -** cell and the size of each cell. Some of the apCell[] pointers might refer -** to overflow cells. In other words, some apCel[] pointers might not point -** to content area of the pages. -** -** A szCell[] of zero means the size of that cell has not yet been computed. -** -** The cells come from as many as four different pages: -** -** ----------- -** | Parent | -** ----------- -** / | \ -** / | \ -** --------- --------- --------- -** |Child-1| |Child-2| |Child-3| -** --------- --------- --------- -** -** The order of cells is in the array is for an index btree is: -** -** 1. All cells from Child-1 in order -** 2. The first divider cell from Parent -** 3. All cells from Child-2 in order -** 4. The second divider cell from Parent -** 5. All cells from Child-3 in order -** -** For a table-btree (with rowids) the items 2 and 4 are empty because -** content exists only in leaves and there are no divider cells. -** -** For an index btree, the apEnd[] array holds pointer to the end of page -** for Child-1, the Parent, Child-2, the Parent (again), and Child-3, -** respectively. The ixNx[] array holds the number of cells contained in -** each of these 5 stages, and all stages to the left. Hence: -** -** ixNx[0] = Number of cells in Child-1. -** ixNx[1] = Number of cells in Child-1 plus 1 for first divider. -** ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider. -** ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells -** ixNx[4] = Total number of cells. -** -** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2] -** are used and they point to the leaf pages only, and the ixNx value are: -** -** ixNx[0] = Number of cells in Child-1. -** ixNx[1] = Number of cells in Child-1 and Child-2. -** ixNx[2] = Total number of cells. -** -** Sometimes when deleting, a child page can have zero cells. In those -** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[] -** entries, shift down. The end result is that each ixNx[] entry should -** be larger than the previous */ typedef struct CellArray CellArray; struct CellArray { int nCell; /* Number of cells in apCell[] */ MemPage *pRef; /* Reference page */ u8 **apCell; /* All cells begin balanced */ u16 *szCell; /* Local size of all cells in apCell[] */ - u8 *apEnd[NB*2]; /* MemPage.aDataEnd values */ - int ixNx[NB*2]; /* Index of at which we move to the next apEnd[] */ }; /* ** Make sure the cell sizes at idx, idx+1, ..., idx+N-1 have been ** computed. */ static void populateCellCache(CellArray *p, int idx, int N){ - MemPage *pRef = p->pRef; - u16 *szCell = p->szCell; assert( idx>=0 && idx+N<=p->nCell ); while( N>0 ){ assert( p->apCell[idx]!=0 ); - if( szCell[idx]==0 ){ - szCell[idx] = pRef->xCellSize(pRef, p->apCell[idx]); + if( p->szCell[idx]==0 ){ + p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]); }else{ assert( CORRUPT_DB || - szCell[idx]==pRef->xCellSize(pRef, p->apCell[idx]) ); + p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) ); } idx++; N--; } } @@ -78316,77 +66101,53 @@ if( p->szCell[N] ) return p->szCell[N]; return computeCellSize(p, N); } /* -** Array apCell[] contains pointers to nCell b-tree page cells. The +** Array apCell[] contains pointers to nCell b-tree page cells. The ** szCell[] array contains the size in bytes of each cell. This function ** replaces the current contents of page pPg with the contents of the cell ** array. ** ** Some of the cells in apCell[] may currently be stored in pPg. This -** function works around problems caused by this by making a copy of any +** function works around problems caused by this by making a copy of any ** such cells before overwriting the page data. ** -** The MemPage.nFree field is invalidated by this function. It is the +** The MemPage.nFree field is invalidated by this function. It is the ** responsibility of the caller to set it correctly. */ static int rebuildPage( - CellArray *pCArray, /* Content to be added to page pPg */ - int iFirst, /* First cell in pCArray to use */ + MemPage *pPg, /* Edit this page */ int nCell, /* Final number of cells on page */ - MemPage *pPg /* The page to be reconstructed */ + u8 **apCell, /* Array of cells */ + u16 *szCell /* Array of cell sizes */ ){ const int hdr = pPg->hdrOffset; /* Offset of header on pPg */ u8 * const aData = pPg->aData; /* Pointer to data for pPg */ const int usableSize = pPg->pBt->usableSize; u8 * const pEnd = &aData[usableSize]; - int i = iFirst; /* Which cell to copy from pCArray*/ - u32 j; /* Start of cell content area */ - int iEnd = i+nCell; /* Loop terminator */ + int i; u8 *pCellptr = pPg->aCellIdx; u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); u8 *pData; - int k; /* Current slot in pCArray->apEnd[] */ - u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */ - - assert( nCell>0 ); - assert( i(u32)usableSize ){ j = 0; } - memcpy(&pTmp[j], &aData[j], usableSize - j); - - assert( pCArray->ixNx[NB*2-1]>i ); - for(k=0; pCArray->ixNx[k]<=i; k++){} - pSrcEnd = pCArray->apEnd[k]; + + i = get2byte(&aData[hdr+5]); + memcpy(&pTmp[i], &aData[i], usableSize - i); pData = pEnd; - while( 1/*exit by break*/ ){ - u8 *pCell = pCArray->apCell[i]; - u16 sz = pCArray->szCell[i]; - assert( sz>0 ); - if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){ - if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT; + for(i=0; i(uptr)pSrcEnd - && (uptr)(pCell)<(uptr)pSrcEnd - ){ - return SQLITE_CORRUPT_BKPT; } - - pData -= sz; + pData -= szCell[i]; put2byte(pCellptr, (pData - aData)); pCellptr += 2; if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT; - memmove(pData, pCell, sz); - assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB ); - i++; - if( i>=iEnd ) break; - if( pCArray->ixNx[k]<=i ){ - k++; - pSrcEnd = pCArray->apEnd[k]; - } + memcpy(pData, pCell, szCell[i]); + assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB ); + testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) ); } /* The pPg->nFree field is now set incorrectly. The caller will fix it. */ pPg->nCell = nCell; pPg->nOverflow = 0; @@ -78397,58 +66158,52 @@ aData[hdr+7] = 0x00; return SQLITE_OK; } /* -** The pCArray objects contains pointers to b-tree cells and the cell sizes. -** This function attempts to add the cells stored in the array to page pPg. -** If it cannot (because the page needs to be defragmented before the cells -** will fit), non-zero is returned. Otherwise, if the cells are added -** successfully, zero is returned. +** Array apCell[] contains nCell pointers to b-tree cells. Array szCell +** contains the size in bytes of each such cell. This function attempts to +** add the cells stored in the array to page pPg. If it cannot (because +** the page needs to be defragmented before the cells will fit), non-zero +** is returned. Otherwise, if the cells are added successfully, zero is +** returned. ** ** Argument pCellptr points to the first entry in the cell-pointer array ** (part of page pPg) to populate. After cell apCell[0] is written to the ** page body, a 16-bit offset is written to pCellptr. And so on, for each ** cell in the array. It is the responsibility of the caller to ensure ** that it is safe to overwrite this part of the cell-pointer array. ** -** When this function is called, *ppData points to the start of the +** When this function is called, *ppData points to the start of the ** content area on page pPg. If the size of the content area is extended, ** *ppData is updated to point to the new start of the content area ** before returning. ** ** Finally, argument pBegin points to the byte immediately following the ** end of the space required by this page for the cell-pointer area (for ** all cells - not just those inserted by the current call). If the content -** area must be extended to before this point in order to accommodate all +** area must be extended to before this point in order to accomodate all ** cells in apCell[], then the cells do not fit and non-zero is returned. */ static int pageInsertArray( MemPage *pPg, /* Page to add cells to */ u8 *pBegin, /* End of cell-pointer array */ - u8 **ppData, /* IN/OUT: Page content-area pointer */ + u8 **ppData, /* IN/OUT: Page content -area pointer */ u8 *pCellptr, /* Pointer to cell-pointer area */ int iFirst, /* Index of first cell to add */ int nCell, /* Number of cells to add to pPg */ CellArray *pCArray /* Array of cells */ ){ - int i = iFirst; /* Loop counter - cell index to insert */ - u8 *aData = pPg->aData; /* Complete page */ - u8 *pData = *ppData; /* Content area. A subset of aData[] */ - int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */ - int k; /* Current slot in pCArray->apEnd[] */ - u8 *pEnd; /* Maximum extent of cell data */ + int i; + u8 *aData = pPg->aData; + u8 *pData = *ppData; + int iEnd = iFirst + nCell; assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ - if( iEnd<=iFirst ) return 0; - assert( pCArray->ixNx[NB*2-1]>i ); - for(k=0; pCArray->ixNx[k]<=i ; k++){} - pEnd = pCArray->apEnd[k]; - while( 1 /*Exit by break*/ ){ + for(i=iFirst; iszCell[i]!=0 ); - sz = pCArray->szCell[i]; + sz = cachedCellSize(pCArray, i); if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ if( (pData - pBegin)apCell[i] || pSlot>=(pCArray->apCell[i]+sz) || CORRUPT_DB ); - if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd - && (uptr)(pCArray->apCell[i])<(uptr)pEnd - ){ - assert( CORRUPT_DB ); - (void)SQLITE_CORRUPT_BKPT; - return 1; - } memmove(pSlot, pCArray->apCell[i], sz); put2byte(pCellptr, (pSlot - aData)); pCellptr += 2; - i++; - if( i>=iEnd ) break; - if( pCArray->ixNx[k]<=i ){ - k++; - pEnd = pCArray->apEnd[k]; - } } *ppData = pData; return 0; } /* -** The pCArray object contains pointers to b-tree cells and their sizes. -** -** This function adds the space associated with each cell in the array -** that is currently stored within the body of pPg to the pPg free-list. -** The cell-pointers and other fields of the page are not updated. +** Array apCell[] contains nCell pointers to b-tree cells. Array szCell +** contains the size in bytes of each such cell. This function adds the +** space associated with each cell in the array that is currently stored +** within the body of pPg to the pPg free-list. The cell-pointers and other +** fields of the page are not updated. ** ** This function returns the total number of cells added to the free-list. */ static int pageFreeArray( MemPage *pPg, /* Page to edit */ @@ -78496,62 +66238,49 @@ ){ u8 * const aData = pPg->aData; u8 * const pEnd = &aData[pPg->pBt->usableSize]; u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; int nRet = 0; - int i, j; + int i; int iEnd = iFirst + nCell; - int nFree = 0; - int aOfst[10]; - int aAfter[10]; + u8 *pFree = 0; + int szFree = 0; for(i=iFirst; iapCell[i]; if( SQLITE_WITHIN(pCell, pStart, pEnd) ){ int sz; - int iAfter; - int iOfst; /* No need to use cachedCellSize() here. The sizes of all cells that ** are to be freed have already been computing while deciding which ** cells need freeing */ sz = pCArray->szCell[i]; assert( sz>0 ); - iOfst = (u16)(pCell - aData); - iAfter = iOfst+sz; - for(j=0; j=nFree ){ - if( nFree>=(int)(sizeof(aOfst)/sizeof(aOfst[0])) ){ - for(j=0; jpEnd ) return 0; - nFree++; + if( pFree!=(pCell + sz) ){ + if( pFree ){ + assert( pFree>aData && (pFree - aData)<65536 ); + freeSpace(pPg, (u16)(pFree - aData), szFree); + } + pFree = pCell; + szFree = sz; + if( pFree+sz>pEnd ) return 0; + }else{ + pFree = pCell; + szFree += sz; } nRet++; } } - for(j=0; jaData && (pFree - aData)<65536 ); + freeSpace(pPg, (u16)(pFree - aData), szFree); } return nRet; } /* -** pCArray contains pointers to and sizes of all cells in the page being -** balanced. The current page, pPg, has pPg->nCell cells starting with -** pCArray->apCell[iOld]. After balancing, this page should hold nNew cells +** apCell[] and szCell[] contains pointers to and sizes of all cells in the +** pages being balanced. The current page, pPg, has pPg->nCell cells starting +** with apCell[iOld]. After balancing, this page should hold nNew cells ** starting at apCell[iNew]. ** ** This routine makes the necessary adjustments to pPg so that it contains ** the correct cells after being balanced. ** @@ -78579,32 +66308,26 @@ u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); memcpy(pTmp, aData, pPg->pBt->usableSize); #endif /* Remove cells from the start and end of the page */ - assert( nCell>=0 ); if( iOldnCell) ) return SQLITE_CORRUPT_BKPT; memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2); nCell -= nShift; } if( iNewEnd < iOldEnd ){ - int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); - assert( nCell>=nTail ); - nCell -= nTail; + nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); } - pData = &aData[get2byte(&aData[hdr+5])]; + pData = &aData[get2byteNotZero(&aData[hdr+5])]; if( pDatapPg->aDataEnd) ) goto editpage_fail; /* Add cells to the start of the page */ if( iNew=0 ); pCellptr = pPg->aCellIdx; memmove(&pCellptr[nAdd*2], pCellptr, nCell*2); if( pageInsertArray( pPg, pBegin, &pData, pCellptr, iNew, nAdd, pCArray @@ -78615,24 +66338,20 @@ /* Add any overflow cells */ for(i=0; inOverflow; i++){ int iCell = (iOld + pPg->aiOvfl[i]) - iNew; if( iCell>=0 && iCellaCellIdx[iCell * 2]; - if( nCell>iCell ){ - memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); - } + memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); nCell++; - cachedCellSize(pCArray, iCell+iNew); if( pageInsertArray( pPg, pBegin, &pData, pCellptr, iCell+iNew, 1, pCArray ) ) goto editpage_fail; } } /* Append cells to the end of the page */ - assert( nCell>=0 ); pCellptr = &pPg->aCellIdx[nCell*2]; if( pageInsertArray( pPg, pBegin, &pData, pCellptr, iNew+nCell, nNew-nCell, pCArray ) ) goto editpage_fail; @@ -78656,15 +66375,29 @@ #endif return SQLITE_OK; editpage_fail: /* Unable to edit this page. Rebuild it from scratch instead. */ - if( nNew<1 ) return SQLITE_CORRUPT_BKPT; populateCellCache(pCArray, iNew, nNew); - return rebuildPage(pCArray, iNew, nNew, pPg); + return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]); } +/* +** The following parameters determine how many adjacent pages get involved +** in a balancing operation. NN is the number of neighbors on either side +** of the page that participate in the balancing operation. NB is the +** total number of pages that participate, including the target page and +** NN neighbors on either side. +** +** The minimum value of NN is 1 (of course). Increasing NN above 1 +** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance +** in exchange for a larger degradation in INSERT and UPDATE performance. +** The value of NN appears to give the best results overall. +*/ +#define NN 1 /* Number of neighbors on either side of pPage */ +#define NB (NN*2+1) /* Total pages involved in the balance */ + #ifndef SQLITE_OMIT_QUICKBALANCE /* ** This version of balance() handles the common special case where ** a new entry is being inserted on the extreme right-end of the @@ -78696,15 +66429,14 @@ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); - if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* dbfuzz001.test */ - assert( pPage->nFree>=0 ); - assert( pParent->nFree>=0 ); + /* This error condition is now caught prior to reaching this function */ + if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT; - /* Allocate a new page. This page will become the right-sibling of + /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell ** may be inserted. If both these operations are successful, proceed. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); @@ -78712,52 +66444,41 @@ u8 *pOut = &pSpace[4]; u8 *pCell = pPage->apOvfl[0]; u16 szCell = pPage->xCellSize(pPage, pCell); u8 *pStop; - CellArray b; assert( sqlite3PagerIswriteable(pNew->pDbPage) ); - assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); + assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF); - b.nCell = 1; - b.pRef = pPage; - b.apCell = &pCell; - b.szCell = &szCell; - b.apEnd[0] = pPage->aDataEnd; - b.ixNx[0] = 2; - b.ixNx[NB*2-1] = 0x7fffffff; - rc = rebuildPage(&b, 0, 1, pNew); - if( NEVER(rc) ){ - releasePage(pNew); - return rc; - } + rc = rebuildPage(pNew, 1, &pCell, &szCell); + if( NEVER(rc) ) return rc; pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell; /* If this is an auto-vacuum database, update the pointer map - ** with entries for the new page, and any pointer from the + ** with entries for the new page, and any pointer from the ** cell on the page to an overflow page. If either of these ** operations fails, the return code is set, but the contents - ** of the parent page are still manipulated by the code below. + ** of the parent page are still manipulated by thh code below. ** That is Ok, at this point the parent page is guaranteed to ** be marked as dirty. Returning an error code will cause a ** rollback, undoing any changes made to the parent page. */ - if( ISAUTOVACUUM(pBt) ){ + if( ISAUTOVACUUM ){ ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc); if( szCell>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, pNew, pCell, &rc); + ptrmapPutOvflPtr(pNew, pCell, &rc); } } - + /* Create a divider cell to insert into pParent. The divider cell ** consists of a 4-byte page number (the page number of pPage) and ** a variable length key value (which must be the same value as the ** largest key on pPage). ** - ** To find the largest key value on pPage, first find the right-most - ** cell on pPage. The first two fields of this cell are the + ** To find the largest key value on pPage, first find the right-most + ** cell on pPage. The first two fields of this cell are the ** record-length (a variable length integer at most 32-bits in size) ** and the key value (a variable length integer, may have any value). ** The first of the while(...) loops below skips over the record-length ** field. The second while(...) loop copies the key value from the ** cell on pPage into the pSpace buffer. @@ -78768,17 +66489,17 @@ pStop = &pCell[9]; while( ((*(pOut++) = *(pCell++))&0x80) && pCellnCell, pSpace, (int)(pOut-pSpace), - 0, pPage->pgno); + insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace), + 0, pPage->pgno, &rc); } /* Set the right-child pointer of pParent to point to the new page. */ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); - + /* Release the reference to the new page. */ releasePage(pNew); } return rc; @@ -78786,11 +66507,11 @@ #endif /* SQLITE_OMIT_QUICKBALANCE */ #if 0 /* ** This function does not contribute anything to the operation of SQLite. -** it is sometimes activated temporarily while debugging code responsible +** it is sometimes activated temporarily while debugging code responsible ** for setting pointer-map entries. */ static int ptrmapCheckPages(MemPage **apPage, int nPage){ int i, j; for(i=0; iisInit ); for(j=0; jnCell; j++){ CellInfo info; u8 *z; - + z = findCell(pPage, j); pPage->xParseCell(pPage, z, &info); if( info.nLocalaData; int const iFromHdr = pFrom->hdrOffset; int const iToHdr = ((pTo->pgno==1) ? 100 : 0); int rc; int iData; - - + + assert( pFrom->isInit ); assert( pFrom->nFree>=iToHdr ); assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize ); - + /* Copy the b-tree node content from page pFrom to page pTo. */ iData = get2byte(&aFrom[iFromHdr+5]); memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); - + /* Reinitialize page pTo so that the contents of the MemPage structure ** match the new data. The initialization of pTo can actually fail under - ** fairly obscure circumstances, even though it is a copy of initialized + ** fairly obscure circumstances, even though it is a copy of initialized ** page pFrom. */ pTo->isInit = 0; rc = btreeInitPage(pTo); - if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo); if( rc!=SQLITE_OK ){ *pRC = rc; return; } - + /* If this is an auto-vacuum database, update the pointer-map entries ** for any b-tree or overflow pages that pTo now contains the pointers to. */ - if( ISAUTOVACUUM(pBt) ){ + if( ISAUTOVACUUM ){ *pRC = setChildPtrmaps(pTo); } } } @@ -78889,17 +66609,17 @@ /* ** This routine redistributes cells on the iParentIdx'th child of pParent ** (hereafter "the page") and up to 2 siblings so that all pages have about the ** same amount of free space. Usually a single sibling on either side of the ** page are used in the balancing, though both siblings might come from one -** side if the page is the first or last child of its parent. If the page +** side if the page is the first or last child of its parent. If the page ** has fewer than 2 siblings (something which can only happen if the page ** is a root page or a child of a root page) then all available siblings ** participate in the balancing. ** -** The number of siblings of the page might be increased or decreased by -** one or two in an effort to keep pages nearly full but not over full. +** The number of siblings of the page might be increased or decreased by +** one or two in an effort to keep pages nearly full but not over full. ** ** Note that when this routine is called, some of the cells on the page ** might not actually be stored in MemPage.aData[]. This can happen ** if the page is overfull. This routine ensures that all cells allocated ** to the page and its siblings fit into MemPage.aData[] before returning. @@ -78906,11 +66626,11 @@ ** ** In the course of balancing the page and its siblings, cells may be ** inserted into or removed from the parent page (pParent). Doing so ** may cause the parent page to become overfull or underfull. If this ** happens, it is the responsibility of the caller to invoke the correct -** balancing routine to fix this problem (see the balance() routine). +** balancing routine to fix this problem (see the balance() routine). ** ** If this routine fails for any reason, it might leave the database ** in a corrupted state. So if this routine fails, the database should ** be rolled back. ** @@ -78921,11 +66641,11 @@ ** a maximum of four divider cells into the parent page, and the maximum ** size of a cell stored within an internal node is always less than 1/4 ** of the page-size, the aOvflSpace[] buffer is guaranteed to be large ** enough for all overflow cells. ** -** If aOvflSpace is set to a null pointer, this function returns +** If aOvflSpace is set to a null pointer, this function returns ** SQLITE_NOMEM. */ static int balance_nonroot( MemPage *pParent, /* Parent page of siblings being balanced */ int iParentIdx, /* Index of "the page" in pParent */ @@ -78956,38 +66676,42 @@ int szNew[NB+2]; /* Combined size of cells placed on i-th page */ u8 *aSpace1; /* Space for copies of dividers cells */ Pgno pgno; /* Temp var to store a page number in */ u8 abDone[NB+2]; /* True after i'th new page is populated */ Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */ - CellArray b; /* Parsed information on cells being balanced */ + Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */ + u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */ + CellArray b; /* Parsed information on cells being balanced */ memset(abDone, 0, sizeof(abDone)); - assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) ); - memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0])); - b.ixNx[NB*2-1] = 0x7fffffff; + b.nCell = 0; + b.apCell = 0; pBt = pParent->pBt; assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); +#if 0 + TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); +#endif + /* At this point pParent may have at most one overflow cell. And if - ** this overflow cell is present, it must be the cell with + ** this overflow cell is present, it must be the cell with ** index iParentIdx. This scenario comes about when this function ** is called (indirectly) from sqlite3BtreeDelete(). */ assert( pParent->nOverflow==0 || pParent->nOverflow==1 ); assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx ); if( !aOvflSpace ){ return SQLITE_NOMEM_BKPT; } - assert( pParent->nFree>=0 ); - /* Find the sibling pages to balance. Also locate the cells in pParent - ** that divide the siblings. An attempt is made to find NN siblings on - ** either side of pPage. More siblings are taken from one side, however, + /* Find the sibling pages to balance. Also locate the cells in pParent + ** that divide the siblings. An attempt is made to find NN siblings on + ** either side of pPage. More siblings are taken from one side, however, ** if there are fewer than NN siblings on the other side. If pParent - ** has NB or fewer children then all children of pParent are taken. + ** has NB or fewer children then all children of pParent are taken. ** ** This loop also drops the divider cells from the parent page. This ** way, the remainder of the function does not have to deal with any ** overflow cells in the parent page, since if any existed they will ** have already been removed. @@ -78995,11 +66719,11 @@ i = pParent->nOverflow + pParent->nCell; if( i<2 ){ nxDiv = 0; }else{ assert( bBulk==0 || bBulk==1 ); - if( iParentIdx==0 ){ + if( iParentIdx==0 ){ nxDiv = 0; }else if( iParentIdx==i ){ nxDiv = i-2+bBulk; }else{ nxDiv = iParentIdx-1; @@ -79012,25 +66736,16 @@ }else{ pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); } pgno = get4byte(pRight); while( 1 ){ - if( rc==SQLITE_OK ){ - rc = getAndInitPage(pBt, pgno, &apOld[i], 0); - } + rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0); if( rc ){ memset(apOld, 0, (i+1)*sizeof(MemPage*)); goto balance_cleanup; } - if( apOld[i]->nFree<0 ){ - rc = btreeComputeFreeSpace(apOld[i]); - if( rc ){ - memset(apOld, 0, (i)*sizeof(MemPage*)); - goto balance_cleanup; - } - } - nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl); + nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; if( (i--)==0 ) break; if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); @@ -79044,24 +66759,26 @@ /* Drop the cell from the parent page. apDiv[i] still points to ** the cell within the parent, even though it has been dropped. ** This is safe because dropping a cell only overwrites the first ** four bytes of it, and this function does not need the first ** four bytes of the divider cell. So the pointer is safe to use - ** later on. + ** later on. ** ** But not if we are in secure-delete mode. In secure-delete mode, ** the dropCell() routine will overwrite the entire cell with zeroes. ** 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_FAST_SECURE ){ int iOff; - /* If the following if() condition is not true, the db is corrupted. - ** The call to dropCell() below will detect this. */ iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData); - if( (iOff+szNew[i])<=(int)pBt->usableSize ){ + if( (iOff+szNew[i])>(int)pBt->usableSize ){ + rc = SQLITE_CORRUPT_BKPT; + memset(apOld, 0, (i+1)*sizeof(MemPage*)); + goto balance_cleanup; + }else{ memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]); apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; } } dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); @@ -79078,12 +66795,14 @@ szScratch = nMaxCells*sizeof(u8*) /* b.apCell */ + nMaxCells*sizeof(u16) /* b.szCell */ + pBt->pageSize; /* aSpace1 */ - assert( szScratch<=7*(int)pBt->pageSize ); - b.apCell = sqlite3StackAllocRaw(0, szScratch ); + /* 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 ); if( b.apCell==0 ){ rc = SQLITE_NOMEM_BKPT; goto balance_cleanup; } b.szCell = (u16*)&b.apCell[nMaxCells]; @@ -79114,22 +66833,21 @@ int limit = pOld->nCell; u8 *aData = pOld->aData; u16 maskPage = pOld->maskPage; u8 *piCell = aData + pOld->cellOffset; u8 *piEnd; - VVA_ONLY( int nCellAtStart = b.nCell; ) /* Verify that all sibling pages are of the same "type" (table-leaf, ** table-interior, index-leaf, or index-interior). */ if( pOld->aData[0]!=apOld[0]->aData[0] ){ - rc = SQLITE_CORRUPT_PAGE(pOld); + rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } /* Load b.apCell[] with pointers to all cells in pOld. If pOld - ** contains overflow cells, include them in the b.apCell[] array + ** constains overflow cells, include them in the b.apCell[] array ** in the correct spot. ** ** Note that when there are multiple overflow cells, it is always the ** case that they are sequential and adjacent. This invariant arises ** because multiple overflows can only occurs when inserting divider @@ -79143,14 +66861,10 @@ ** long be able to find the cells if a pointer to each cell is not saved ** first. */ memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow)); if( pOld->nOverflow>0 ){ - if( NEVER(limitaiOvfl[0]) ){ - rc = SQLITE_CORRUPT_PAGE(pOld); - goto balance_cleanup; - } limit = pOld->aiOvfl[0]; for(j=0; jnCell+pOld->nOverflow) ); cntOld[i] = b.nCell; if( ileaf ){ assert( leafCorrection==0 ); - assert( pOld->hdrOffset==0 || CORRUPT_DB ); + assert( pOld->hdrOffset==0 ); /* The right pointer of the child page pOld becomes the left ** pointer of the divider cell */ memcpy(b.apCell[b.nCell], &pOld->aData[8], 4); }else{ assert( leafCorrection==4 ); @@ -79207,36 +66920,25 @@ /* ** Figure out the number of pages needed to hold all b.nCell cells. ** Store this number in "k". Also compute szNew[] which is the total ** size of all cells on the i-th page and cntNew[] which is the index - ** in b.apCell[] of the cell that divides page i from page i+1. + ** in b.apCell[] of the cell that divides page i from page i+1. ** cntNew[k] should equal b.nCell. ** ** Values computed by this block: ** ** k: The total number of sibling pages ** szNew[i]: Spaced used on the i-th sibling page. ** cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to ** the right of the i-th sibling page. ** usableSpace: Number of bytes of space available on each sibling. - ** + ** */ usableSpace = pBt->usableSize - 12 + leafCorrection; - for(i=k=0; iaDataEnd; - b.ixNx[k] = cntOld[i]; - if( k && b.ixNx[k]==b.ixNx[k-1] ){ - k--; /* Omit b.ixNx[] entry for child pages with no cells */ - } - if( !leafData ){ - k++; - b.apEnd[k] = pParent->aDataEnd; - b.ixNx[k] = cntOld[i]+1; - } - assert( p->nFree>=0 ); szNew[i] = usableSpace - p->nFree; for(j=0; jnOverflow; j++){ szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]); } cntNew[i] = cntOld[i]; @@ -79304,21 +67006,19 @@ r = cntNew[i-1] - 1; d = r + 1 - leafData; (void)cachedCellSize(&b, d); do{ - int szR, szD; assert( d szLeft-(szR+(i==k-1?0:2)))){ + && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){ break; } - szRight += szD + 2; - szLeft -= szR + 2; + szRight += b.szCell[d] + 2; + szLeft -= b.szCell[r] + 2; cntNew[i-1] = r; r--; d--; }while( r>=0 ); szNew[i] = szRight; @@ -79327,19 +67027,19 @@ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } } - /* Sanity check: For a non-corrupt database file one of the following + /* Sanity check: For a non-corrupt database file one of the follwing ** must be true: ** (1) We found one or more cells (cntNew[0])>0), or ** (2) pPage is a virtual root page. A virtual root page is when ** the real root page is page 1 and we are the only child of ** that page. */ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); - TRACE(("BALANCE: old: %u(nc=%u) %u(nc=%u) %u(nc=%u)\n", + TRACE(("BALANCE: old: %d(nc=%d) %d(nc=%d) %d(nc=%d)\n", apOld[0]->pgno, apOld[0]->nCell, nOld>=2 ? apOld[1]->pgno : 0, nOld>=2 ? apOld[1]->nCell : 0, nOld>=3 ? apOld[2]->pgno : 0, nOld>=3 ? apOld[2]->nCell : 0 )); @@ -79352,15 +67052,10 @@ if( ipDbPage); nNew++; - if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) - && rc==SQLITE_OK - ){ - rc = SQLITE_CORRUPT_BKPT; - } if( rc ) goto balance_cleanup; }else{ assert( i>0 ); rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); if( rc ) goto balance_cleanup; @@ -79368,63 +67063,66 @@ apNew[i] = pNew; nNew++; cntOld[i] = b.nCell; /* Set the pointer-map entry for the new sibling page. */ - if( ISAUTOVACUUM(pBt) ){ + if( ISAUTOVACUUM ){ ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); if( rc!=SQLITE_OK ){ goto balance_cleanup; } } } } /* - ** Reassign page numbers so that the new pages are in ascending order. + ** Reassign page numbers so that the new pages are in ascending order. ** This helps to keep entries in the disk file in order so that a scan - ** of the table is closer to a linear scan through the file. That in turn + ** of the table is closer to a linear scan through the file. That in turn ** helps the operating system to deliver pages from the disk more rapidly. ** - ** An O(N*N) sort algorithm is used, but since N is never more than NB+2 - ** (5), that is not a performance concern. + ** An O(n^2) insertion sort algorithm is used, but since n is never more + ** than (NB+2) (a small constant), that should not be a problem. ** - ** When NB==3, this one optimization makes the database about 25% faster + ** When NB==3, this one optimization makes the database about 25% faster ** for large insertions and deletions. */ for(i=0; ipgno; - assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE ); - assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY ); - } - for(i=0; ipgno < apNew[iB]->pgno ) iB = j; - } - - /* If apNew[i] has a page number that is bigger than any of the - ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent - ** entry that has the smallest page number (which we know to be - ** entry apNew[iB]). - */ - if( iB!=i ){ - Pgno pgnoA = apNew[i]->pgno; - Pgno pgnoB = apNew[iB]->pgno; - Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1; - u16 fgA = apNew[i]->pDbPage->flags; - u16 fgB = apNew[iB]->pDbPage->flags; - sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB); - sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA); - sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB); - apNew[i]->pgno = pgnoB; - apNew[iB]->pgno = pgnoA; - } - } - - TRACE(("BALANCE: new: %u(%u nc=%u) %u(%u nc=%u) %u(%u nc=%u) " - "%u(%u nc=%u) %u(%u nc=%u)\n", + aPgOrder[i] = aPgno[i] = apNew[i]->pgno; + aPgFlags[i] = apNew[i]->pDbPage->flags; + for(j=0; ji ){ + sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0); + } + sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]); + apNew[i]->pgno = pgno; + } + } + + TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) " + "%d(%d nc=%d) %d(%d nc=%d)\n", apNew[0]->pgno, szNew[0], cntNew[0], nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0, nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0, @@ -79433,23 +67131,21 @@ nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0, nNew>=5 ? cntNew[4] - cntNew[3] - !leafData : 0 )); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - assert( nNew>=1 && nNew<=ArraySize(apNew) ); - assert( apNew[nNew-1]!=0 ); put4byte(pRight, apNew[nNew-1]->pgno); /* If the sibling pages are not leaves, ensure that the right-child pointer - ** of the right-most new sibling page is set to the value that was + ** of the right-most new sibling page is set to the value that was ** originally in the same field of the right-most old sibling page. */ if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1]; memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4); } - /* Make any required updates to pointer map entries associated with + /* Make any required updates to pointer map entries associated with ** cells stored on sibling pages following the balance operation. Pointer ** map entries associated with divider cells are set by the insertCell() ** routine. The associated pointer map entries are: ** ** a) if the cell contains a reference to an overflow chain, the @@ -79456,51 +67152,50 @@ ** entry associated with the first page in the overflow chain, and ** ** b) if the sibling pages are not leaves, the child page associated ** with the cell. ** - ** If the sibling pages are not leaves, then the pointer map entry - ** associated with the right-child of each sibling may also need to be - ** updated. This happens below, after the sibling pages have been + ** If the sibling pages are not leaves, then the pointer map entry + ** associated with the right-child of each sibling may also need to be + ** updated. This happens below, after the sibling pages have been ** populated, not here. */ - if( ISAUTOVACUUM(pBt) ){ - MemPage *pOld; - MemPage *pNew = pOld = apNew[0]; + if( ISAUTOVACUUM ){ + MemPage *pNew = apNew[0]; + u8 *aOld = pNew->aData; int cntOldNext = pNew->nCell + pNew->nOverflow; + int usableSize = pBt->usableSize; int iNew = 0; int iOld = 0; for(i=0; i=0 && iOldnCell + pOld->nOverflow + !leafData; + aOld = pOld->aData; } if( i==cntNew[iNew] ){ pNew = apNew[++iNew]; if( !leafData ) continue; } /* Cell pCell is destined for new sibling page pNew. Originally, it - ** was either part of sibling page iOld (possibly an overflow cell), + ** was either part of sibling page iOld (possibly an overflow cell), ** or else the divider cell to the left of sibling page iOld. So, ** if sibling page iOld had the same page number as pNew, and if ** pCell really was a part of sibling page iOld (not a divider or ** overflow cell), we can skip updating the pointer map entries. */ if( iOld>=nNew || pNew->pgno!=aPgno[iOld] - || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd) + || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize]) ){ if( !leafCorrection ){ ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); } if( cachedCellSize(&b,i)>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, pOld, pCell, &rc); + ptrmapPutOvflPtr(pNew, pCell, &rc); } if( rc ) goto balance_cleanup; } } } @@ -79508,11 +67203,10 @@ /* Insert new divider cells into pParent. */ for(i=0; ileaf ){ memcpy(&pNew->aData[8], pCell, 4); }else if( leafData ){ - /* If the tree is a leaf-data tree, and the siblings are leaves, - ** then there is no divider cell in b.apCell[]. Instead, the divider - ** cell consists of the integer key for the right-most cell of + /* If the tree is a leaf-data tree, and the siblings are leaves, + ** then there is no divider cell in b.apCell[]. Instead, the divider + ** cell consists of the integer key for the right-most cell of ** the sibling-page assembled above only. */ CellInfo info; j--; pNew->xParseCell(pNew, b.apCell[j], &info); @@ -79535,13 +67229,13 @@ pTemp = 0; }else{ pCell -= 4; /* Obscure case for non-leaf-data trees: If the cell at pCell was ** previously stored on a leaf node, and its reported size was 4 - ** bytes, then it may actually be smaller than this + ** bytes, then it may actually be smaller than this ** (see btreeParseCellPtr(), 4 bytes is the minimum size of - ** any cell). But it is important to pass the correct size to + ** any cell). But it is important to pass the correct size to ** insertCell(), so reparse the cell now. ** ** This can only happen for b-trees used to evaluate "IN (SELECT ...)" ** and WITHOUT ROWID tables with exactly one column which is the ** primary key. @@ -79552,18 +67246,11 @@ } } iOvflSpace += sz; assert( sz<=pBt->maxLocal+23 ); assert( iOvflSpace <= (int)pBt->pageSize ); - assert( b.ixNx[NB*2-1]>j ); - for(k=0; b.ixNx[k]<=j; k++){} - pSrcEnd = b.apEnd[k]; - if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } - rc = insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno); + insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc); if( rc!=SQLITE_OK ) goto balance_cleanup; assert( sqlite3PagerIswriteable(pParent->pDbPage) ); } /* Now update the actual sibling pages. The order in which they are updated @@ -79589,12 +67276,10 @@ ** pass. */ for(i=1-nNew; i=0 && iPg=1 || i>=0 ); - assert( iPg=0 /* On the upwards pass, or... */ || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */ ){ int iNew; @@ -79638,12 +67323,12 @@ ** page is the right-child of the parent. Copy the contents of the ** child page into the parent, decreasing the overall height of the ** b-tree structure by one. This is described as the "balance-shallower" ** sub-algorithm in some documentation. ** - ** If this is an auto-vacuum database, the call to copyNodeContent() - ** sets all pointer-map entries corresponding to database image pages + ** If this is an auto-vacuum database, the call to copyNodeContent() + ** sets all pointer-map entries corresponding to database image pages ** for which the pointer is stored within the content being copied. ** ** It is critical that the child page be defragmented before being ** copied into the parent, because if the parent is page 1 then it will ** by smaller than the child due to the database header, and so all the @@ -79650,18 +67335,17 @@ ** free space needs to be up front. */ assert( nNew==1 || CORRUPT_DB ); rc = defragmentPage(apNew[0], -1); testcase( rc!=SQLITE_OK ); - assert( apNew[0]->nFree == - (get2byteNotZero(&apNew[0]->aData[5]) - apNew[0]->cellOffset - - apNew[0]->nCell*2) + assert( apNew[0]->nFree == + (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) || rc!=SQLITE_OK ); copyNodeContent(apNew[0], pParent, &rc); freePage(apNew[0], &rc); - }else if( ISAUTOVACUUM(pBt) && !leafCorrection ){ + }else if( ISAUTOVACUUM && !leafCorrection ){ /* Fix the pointer map entries associated with the right-child of each ** sibling page. All other pointer map entries have already been taken ** care of. */ for(i=0; iaData[8]); @@ -79668,23 +67352,23 @@ ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); } } assert( pParent->isInit ); - TRACE(("BALANCE: finished: old=%u new=%u cells=%u\n", + TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", nOld, nNew, b.nCell)); /* Free any old pages that were not reused as new pages. */ for(i=nNew; iisInit ){ + if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){ /* The ptrmapCheckPages() contains assert() statements that verify that - ** all pointer map pages are set correctly. This is helpful while + ** all pointer map pages are set correctly. This is helpful while ** debugging. This is usually disabled because a corrupt database may ** cause an assert() statement to fail. */ ptrmapCheckPages(apNew, nNew); ptrmapCheckPages(&pParent, 1); } @@ -79692,11 +67376,11 @@ /* ** Cleanup before returning. */ balance_cleanup: - sqlite3StackFree(0, b.apCell); + sqlite3ScratchFree(b.apCell); for(i=0; ipBt; /* The BTree */ assert( pRoot->nOverflow>0 ); assert( sqlite3_mutex_held(pBt->mutex) ); - /* Make pRoot, the root page of the b-tree, writable. Allocate a new + /* Make pRoot, the root page of the b-tree, writable. Allocate a new ** page that will become the new right-child of pPage. Copy the contents ** of the node stored on pRoot into the new child page. */ rc = sqlite3PagerWrite(pRoot->pDbPage); if( rc==SQLITE_OK ){ rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); copyNodeContent(pRoot, pChild, &rc); - if( ISAUTOVACUUM(pBt) ){ + if( ISAUTOVACUUM ){ ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); } } if( rc ){ *ppChild = 0; @@ -79751,13 +67435,13 @@ releasePage(pChild); return rc; } assert( sqlite3PagerIswriteable(pChild->pDbPage) ); assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); + assert( pChild->nCell==pRoot->nCell ); - TRACE(("BALANCE: copy root %u into %u\n", pRoot->pgno, pChild->pgno)); + TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); /* Copy the overflow cells from pRoot to pChild */ memcpy(pChild->aiOvfl, pRoot->aiOvfl, pRoot->nOverflow*sizeof(pRoot->aiOvfl[0])); memcpy(pChild->apOvfl, pRoot->apOvfl, @@ -79770,97 +67454,59 @@ *ppChild = pChild; return SQLITE_OK; } -/* -** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid -** on the same B-tree as pCur. -** -** This can occur if a database is corrupt with two or more SQL tables -** pointing to the same b-tree. If an insert occurs on one SQL table -** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL -** table linked to the same b-tree. If the secondary insert causes a -** rebalance, that can change content out from under the cursor on the -** first SQL table, violating invariants on the first insert. -*/ -static int anotherValidCursor(BtCursor *pCur){ - BtCursor *pOther; - for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){ - if( pOther!=pCur - && pOther->eState==CURSOR_VALID - && pOther->pPage==pCur->pPage - ){ - return SQLITE_CORRUPT_PAGE(pCur->pPage); - } - } - return SQLITE_OK; -} - /* ** The page that pCur currently points to has just been modified in ** some way. This function figures out if this modification means the -** tree needs to be balanced, and if so calls the appropriate balancing +** tree needs to be balanced, and if so calls the appropriate balancing ** routine. Balancing routines are: ** ** balance_quick() ** balance_deeper() ** balance_nonroot() */ static int balance(BtCursor *pCur){ int rc = SQLITE_OK; + const int nMin = pCur->pBt->usableSize * 2 / 3; u8 aBalanceQuickSpace[13]; u8 *pFree = 0; VVA_ONLY( int balance_quick_called = 0 ); VVA_ONLY( int balance_deeper_called = 0 ); do { - int iPage; - MemPage *pPage = pCur->pPage; - - if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break; - if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){ - /* No rebalance required as long as: - ** (1) There are no overflow cells - ** (2) The amount of free space on the page is less than 2/3rds of - ** the total usable space on the page. */ - break; - }else if( (iPage = pCur->iPage)==0 ){ - if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){ + int iPage = pCur->iPage; + MemPage *pPage = pCur->apPage[iPage]; + + if( iPage==0 ){ + if( pPage->nOverflow ){ /* The root page of the b-tree is overfull. In this case call the ** balance_deeper() function to create a new child for the root-page ** and copy the current contents of the root-page to it. The ** next iteration of the do-loop will balance the child page. - */ + */ assert( balance_deeper_called==0 ); VVA_ONLY( balance_deeper_called++ ); rc = balance_deeper(pPage, &pCur->apPage[1]); if( rc==SQLITE_OK ){ pCur->iPage = 1; pCur->ix = 0; pCur->aiIdx[0] = 0; - pCur->apPage[0] = pPage; - pCur->pPage = pCur->apPage[1]; - assert( pCur->pPage->nOverflow ); + assert( pCur->apPage[1]->nOverflow ); } }else{ break; } - }else if( sqlite3PagerPageRefcount(pPage->pDbPage)>1 ){ - /* The page being written is not a root page, and there is currently - ** more than one reference to it. This only happens if the page is one - ** of its own ancestor pages. Corruption. */ - rc = SQLITE_CORRUPT_PAGE(pPage); + }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ + break; }else{ MemPage * const pParent = pCur->apPage[iPage-1]; int const iIdx = pCur->aiIdx[iPage-1]; rc = sqlite3PagerWrite(pParent->pDbPage); - if( rc==SQLITE_OK && pParent->nFree<0 ){ - rc = btreeComputeFreeSpace(pParent); - } if( rc==SQLITE_OK ){ #ifndef SQLITE_OMIT_QUICKBALANCE if( pPage->intKeyLeaf && pPage->nOverflow==1 && pPage->aiOvfl[0]==pPage->nCell @@ -79868,21 +67514,21 @@ && pParent->nCell==iIdx ){ /* Call balance_quick() to create a new sibling of pPage on which ** to store the overflow cell. balance_quick() inserts a new cell ** into pParent, which may cause pParent overflow. If this - ** happens, the next iteration of the do-loop will balance pParent + ** happens, the next iteration of the do-loop will balance pParent ** use either balance_nonroot() or balance_deeper(). Until this ** happens, the overflow cell is stored in the aBalanceQuickSpace[] - ** buffer. + ** buffer. ** ** The purpose of the following assert() is to check that only a ** single call to balance_quick() is made for each call to this ** function. If this were not verified, a subtle bug involving reuse ** of the aBalanceQuickSpace[] might sneak in. */ - assert( balance_quick_called==0 ); + assert( balance_quick_called==0 ); VVA_ONLY( balance_quick_called++ ); rc = balance_quick(pParent, pPage, aBalanceQuickSpace); }else #endif { @@ -79889,29 +67535,29 @@ /* In this case, call balance_nonroot() to redistribute cells ** between pPage and up to 2 of its sibling pages. This involves ** modifying the contents of pParent, which may cause pParent to ** become overfull or underfull. The next iteration of the do-loop ** will balance the parent page to correct this. - ** + ** ** If the parent page becomes overfull, the overflow cell or cells - ** are stored in the pSpace buffer allocated immediately below. + ** are stored in the pSpace buffer allocated immediately below. ** A subsequent iteration of the do-loop will deal with this by ** calling balance_nonroot() (balance_deeper() may be called first, ** but it doesn't deal with overflow cells - just moves them to a - ** different page). Once this subsequent call to balance_nonroot() + ** different page). Once this subsequent call to balance_nonroot() ** has completed, it is safe to release the pSpace buffer used by - ** the previous call, as the overflow cell data will have been + ** the previous call, as the overflow cell data will have been ** copied either into the body of a database page or into the new ** pSpace buffer passed to the latter call to balance_nonroot(). */ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints&BTREE_BULKLOAD); if( pFree ){ - /* If pFree is not NULL, it points to the pSpace buffer used + /* If pFree is not NULL, it points to the pSpace buffer used ** by a previous call to balance_nonroot(). Its contents are - ** now stored either on real database pages or within the + ** now stored either on real database pages or within the ** new pSpace buffer, so it may be safely freed here. */ sqlite3PageFree(pFree); } /* The pSpace buffer will be freed after the next call to @@ -79925,137 +67571,19 @@ /* The next iteration of the do-loop balances the parent page. */ releasePage(pPage); pCur->iPage--; assert( pCur->iPage>=0 ); - pCur->pPage = pCur->apPage[pCur->iPage]; } }while( rc==SQLITE_OK ); if( pFree ){ sqlite3PageFree(pFree); } return rc; } -/* Overwrite content from pX into pDest. Only do the write if the -** content is different from what is already there. -*/ -static int btreeOverwriteContent( - MemPage *pPage, /* MemPage on which writing will occur */ - u8 *pDest, /* Pointer to the place to start writing */ - const BtreePayload *pX, /* Source of data to write */ - int iOffset, /* Offset of first byte to write */ - int iAmt /* Number of bytes to be written */ -){ - int nData = pX->nData - iOffset; - if( nData<=0 ){ - /* Overwriting with zeros */ - int i; - for(i=0; ipDbPage); - if( rc ) return rc; - memset(pDest + i, 0, iAmt - i); - } - }else{ - if( nDatapData) + iOffset, iAmt)!=0 ){ - int rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ) return rc; - /* In a corrupt database, it is possible for the source and destination - ** buffers to overlap. This is harmless since the database is already - ** corrupt but it does cause valgrind and ASAN warnings. So use - ** memmove(). */ - memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt); - } - } - return SQLITE_OK; -} - -/* -** Overwrite the cell that cursor pCur is pointing to with fresh content -** contained in pX. In this variant, pCur is pointing to an overflow -** cell. -*/ -static SQLITE_NOINLINE int btreeOverwriteOverflowCell( - BtCursor *pCur, /* Cursor pointing to cell to overwrite */ - const BtreePayload *pX /* Content to write into the cell */ -){ - int iOffset; /* Next byte of pX->pData to write */ - int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ - int rc; /* Return code */ - MemPage *pPage = pCur->pPage; /* Page being written */ - BtShared *pBt; /* Btree */ - Pgno ovflPgno; /* Next overflow page to write */ - u32 ovflPageSize; /* Size to write on overflow page */ - - assert( pCur->info.nLocalinfo.pPayload, pX, - 0, pCur->info.nLocal); - if( rc ) return rc; - - /* Now overwrite the overflow pages */ - iOffset = pCur->info.nLocal; - assert( nTotal>=0 ); - assert( iOffset>=0 ); - ovflPgno = get4byte(pCur->info.pPayload + iOffset); - pBt = pPage->pBt; - ovflPageSize = pBt->usableSize - 4; - do{ - rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); - if( rc ) return rc; - if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){ - rc = SQLITE_CORRUPT_PAGE(pPage); - }else{ - if( iOffset+ovflPageSize<(u32)nTotal ){ - ovflPgno = get4byte(pPage->aData); - }else{ - ovflPageSize = nTotal - iOffset; - } - rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, - iOffset, ovflPageSize); - } - sqlite3PagerUnref(pPage->pDbPage); - if( rc ) return rc; - iOffset += ovflPageSize; - }while( iOffsetnData + pX->nZero; /* Total bytes of to write */ - MemPage *pPage = pCur->pPage; /* Page being written */ - - if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd - || pCur->info.pPayload < pPage->aData + pPage->cellOffset - ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( pCur->info.nLocal==nTotal ){ - /* The entire cell is local */ - return btreeOverwriteContent(pPage, pCur->info.pPayload, pX, - 0, pCur->info.nLocal); - }else{ - /* The cell contains overflow content */ - return btreeOverwriteOverflowCell(pCur, pX); - } -} - /* ** Insert a new record into the BTree. The content of the new record ** is described by the pX object. The pCur cursor is used only to ** define what table the record should be inserted into, and is left @@ -80065,15 +67593,15 @@ ** the key is used. The pX.pKey value must be NULL. The pX.nKey is the ** rowid or INTEGER PRIMARY KEY of the row. The pX.nData,pData,nZero fields ** hold the content of the row. ** ** For an index btree (used for indexes and WITHOUT ROWID tables), the -** key is an arbitrary byte sequence stored in pX.pKey,nKey. The +** key is an arbitrary byte sequence stored in pX.pKey,nKey. The ** pX.pData,nData,nZero fields must be zero. ** ** If the seekResult parameter is non-zero, then a successful call to -** sqlite3BtreeIndexMoveto() to seek cursor pCur to (pKey,nKey) has already +** 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). @@ -80087,258 +67615,155 @@ */ 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 flags, /* True if this is likely an append */ - int seekResult /* Result of prior IndexMoveto() call */ + int seekResult /* Result of prior MovetoUnpacked() call */ ){ int rc; int loc = seekResult; /* -1: before desired location +1: after */ int szNew = 0; int idx; MemPage *pPage; Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; unsigned char *oldCell; unsigned char *newCell = 0; - assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags ); - assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 ); - - /* Save the positions of any other cursors open on this table. - ** - ** In some cases, the call to btreeMoveto() below is a no-op. For - ** example, when inserting data into a table with auto-generated integer - ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the - ** integer key to use. It then calls this function to actually insert the - ** data into the intkey B-Tree. In this case btreeMoveto() recognizes - ** that the cursor is already where it needs to be and returns without - ** doing any work. To avoid thwarting these optimizations, it is important - ** not to clear the cursor here. - */ - if( pCur->curFlags & BTCF_Multiple ){ - rc = saveAllCursors(p->pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; - if( loc && pCur->iPage<0 ){ - /* This can only happen if the schema is corrupt such that there is more - ** than one table or index with the same root page as used by the cursor. - ** Which can only happen if the SQLITE_NoSchemaError flag was set when - ** the schema was loaded. This cannot be asserted though, as a user might - ** set the flag, load the schema, and then unset the flag. */ - return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot); - } - } - - /* Ensure that the cursor is not in the CURSOR_FAULT state and that it - ** points to a valid cell. - */ - if( pCur->eState>=CURSOR_REQUIRESEEK ){ - testcase( pCur->eState==CURSOR_REQUIRESEEK ); - testcase( pCur->eState==CURSOR_FAULT ); - rc = moveToRoot(pCur); - if( rc && rc!=SQLITE_EMPTY ) return rc; + assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags ); + + if( pCur->eState==CURSOR_FAULT ){ + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; } assert( cursorOwnsBtShared(pCur) ); assert( (pCur->curFlags & BTCF_WriteFlag)!=0 - && p->pBt->inTransaction==TRANS_WRITE - && (p->pBt->btsFlags & BTS_READ_ONLY)==0 ); + && pBt->inTransaction==TRANS_WRITE + && (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); /* Assert that the caller has been consistent. If this cursor was opened ** expecting an index b-tree, then the caller should be inserting blob ** keys with no associated data. If the cursor was opened expecting an ** intkey table, the caller should be inserting integer keys with a ** blob of associated data. */ - assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) ); + assert( (pX->pKey==0)==(pCur->pKeyInfo==0) ); + + /* Save the positions of any other cursors open on this table. + ** + ** In some cases, the call to btreeMoveto() below is a no-op. For + ** example, when inserting data into a table with auto-generated integer + ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the + ** integer key to use. It then calls this function to actually insert the + ** data into the intkey B-Tree. In this case btreeMoveto() recognizes + ** that the cursor is already where it needs to be and returns without + ** doing any work. To avoid thwarting these optimizations, it is important + ** not to clear the cursor here. + */ + if( pCur->curFlags & BTCF_Multiple ){ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + } if( pCur->pKeyInfo==0 ){ assert( pX->pKey==0 ); - /* If this is an insert into a table b-tree, invalidate any incrblob - ** cursors open on the row being replaced */ - if( p->hasIncrblobCur ){ - 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. - */ -#ifdef SQLITE_DEBUG - if( flags & BTREE_SAVEPOSITION ){ - assert( pCur->curFlags & BTCF_ValidNKey ); - assert( pX->nKey==pCur->info.nKey ); - assert( loc==0 ); - } -#endif - - /* On the other hand, BTREE_SAVEPOSITION==0 does not imply - ** that the cursor is not pointing to a row to be overwritten. - ** So do a complete check. - */ - if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ - /* The cursor is pointing to the entry that is to be - ** overwritten */ - assert( pX->nData>=0 && pX->nZero>=0 ); - if( pCur->info.nSize!=0 - && pCur->info.nPayload==(u32)pX->nData+pX->nZero - ){ - /* New entry is the same size as the old. Do an overwrite */ - return btreeOverwriteCell(pCur, pX); - } - assert( loc==0 ); - }else if( loc==0 ){ - /* The cursor is *not* pointing to the cell to be overwritten, nor - ** to an adjacent cell. Move the cursor so that it is pointing either - ** to the cell to be overwritten or an adjacent cell. - */ - rc = sqlite3BtreeTableMoveto(pCur, pX->nKey, - (flags & BTREE_APPEND)!=0, &loc); - if( rc ) return rc; - } - }else{ - /* This is an index or a WITHOUT ROWID table */ - - /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing - ** to a row with the same key as the new entry being inserted. - */ - assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 ); - - /* If the cursor is not already pointing either to the cell to be - ** overwritten, or if a new cell is being inserted, if the cursor is - ** not pointing to an immediately adjacent cell, then move the cursor - ** so that it does. - */ - 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.eqSeen = 0; - rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc); - }else{ - rc = btreeMoveto(pCur, pX->pKey, pX->nKey, - (flags & BTREE_APPEND)!=0, &loc); - } - if( rc ) return rc; - } - - /* If the cursor is currently pointing to an entry to be overwritten - ** and the new content is the same as as the old, then use the - ** overwrite optimization. - */ - if( loc==0 ){ - getCellInfo(pCur); - if( pCur->info.nKey==pX->nKey ){ - BtreePayload x2; - x2.pData = pX->pKey; - x2.nData = pX->nKey; - x2.nZero = 0; - return btreeOverwriteCell(pCur, &x2); - } - } - } - assert( pCur->eState==CURSOR_VALID - || (pCur->eState==CURSOR_INVALID && loc) || CORRUPT_DB ); - - pPage = pCur->pPage; - assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) ); - assert( pPage->leaf || !pPage->intKey ); - if( pPage->nFree<0 ){ - if( NEVER(pCur->eState>CURSOR_INVALID) ){ - /* ^^^^^--- due to the moveToRoot() call above */ - rc = SQLITE_CORRUPT_PAGE(pPage); - }else{ - rc = btreeComputeFreeSpace(pPage); - } - if( rc ) return rc; - } - - TRACE(("INSERT: table=%u nkey=%lld ndata=%u page=%u %s\n", - pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, - loc==0 ? "overwrite" : "new entry")); - assert( pPage->isInit || CORRUPT_DB ); - newCell = p->pBt->pTmpSpace; - assert( newCell!=0 ); - assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); - if( flags & BTREE_PREFORMAT ){ - rc = SQLITE_OK; - szNew = p->pBt->nPreformatSize; - if( szNew<4 ){ - szNew = 4; - newCell[3] = 0; - } - if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){ - CellInfo info; - pPage->xParseCell(pPage, newCell, &info); - if( info.nPayload!=info.nLocal ){ - Pgno ovfl = get4byte(&newCell[szNew-4]); - ptrmapPut(p->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc); - if( NEVER(rc) ) goto end_insert; - } - } - }else{ - rc = fillInCell(pPage, newCell, pX, &szNew); - if( rc ) goto end_insert; - } - assert( szNew==pPage->xCellSize(pPage, newCell) ); - assert( szNew <= MX_CELL_SIZE(p->pBt) ); - idx = pCur->ix; - pCur->info.nSize = 0; - if( loc==0 ){ - CellInfo info; - assert( idx>=0 ); - if( idx>=pPage->nCell ){ - return SQLITE_CORRUPT_PAGE(pPage); - } + /* If this is an insert into a table b-tree, invalidate any incrblob + ** cursors open on the row being replaced */ + invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0); + + /* If 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==pCur->info.nKey ){ + loc = 0; + }else if( loc==0 ){ + rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); + if( rc ) return rc; + } + }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]; + assert( pPage->intKey || pX->nKey>=0 ); + assert( pPage->leaf || !pPage->intKey ); + + TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", + pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, + loc==0 ? "overwrite" : "new entry")); + assert( pPage->isInit ); + newCell = pBt->pTmpSpace; + assert( newCell!=0 ); + rc = fillInCell(pPage, newCell, pX, &szNew); + if( rc ) goto end_insert; + assert( szNew==pPage->xCellSize(pPage, newCell) ); + assert( szNew <= MX_CELL_SIZE(pBt) ); + idx = pCur->ix; + if( loc==0 ){ + CellInfo info; + assert( idxnCell ); rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ){ goto end_insert; } oldCell = findCell(pPage, idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } - BTREE_CLEAR_CELL(rc, pPage, oldCell, info); - testcase( pCur->curFlags & BTCF_ValidOvfl ); - invalidateOverflowCache(pCur); - if( info.nSize==szNew && info.nLocal==info.nPayload - && (!ISAUTOVACUUM(p->pBt) || szNewminLocal) + 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(). + ** 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 < pPage->aData+pPage->hdrOffset+10 ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( oldCell+szNew > pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pPage); - } + 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->ix; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + pCur->curFlags &= ~BTCF_ValidNKey; }else{ assert( pPage->leaf ); } - rc = insertCellFast(pPage, idx, newCell, szNew); + insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); assert( pPage->nOverflow==0 || rc==SQLITE_OK ); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); - /* If no error has occurred and pPage has an overflow cell, call balance() + /* If no error has occurred and pPage has an overflow cell, call balance() ** to redistribute the cells within the tree. Since balance() may move ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey ** variables. ** ** Previous versions of SQLite called moveToRoot() to move the cursor @@ -80354,23 +67779,24 @@ ** the b-tree if possible. If the cursor is left pointing to the last ** entry in the table, and the next row inserted has an integer key ** larger than the largest existing key, it is possible to insert the ** row without seeking the cursor. This can be a big performance boost. */ + pCur->info.nSize = 0; if( pPage->nOverflow ){ assert( rc==SQLITE_OK ); - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + pCur->curFlags &= ~(BTCF_ValidNKey); rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() - ** fails. Internal data structure corruption will result otherwise. + ** fails. Internal data structure corruption will result otherwise. ** Also, set the cursor state to invalid. This stops saveCursorPosition() ** from trying to save the current position of the cursor. */ - pCur->pPage->nOverflow = 0; + pCur->apPage[pCur->iPage]->nOverflow = 0; pCur->eState = CURSOR_INVALID; if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){ - btreeReleaseAllCursorPages(pCur); + rc = moveToRoot(pCur); if( pCur->pKeyInfo ){ assert( pCur->pKey==0 ); pCur->pKey = sqlite3Malloc( pX->nKey ); if( pCur->pKey==0 ){ rc = SQLITE_NOMEM; @@ -80380,130 +67806,18 @@ } pCur->eState = CURSOR_REQUIRESEEK; pCur->nKey = pX->nKey; } } - assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 ); + assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); end_insert: return rc; } /* -** This function is used as part of copying the current row from cursor -** pSrc into cursor pDest. If the cursors are open on intkey tables, then -** parameter iKey is used as the rowid value when the record is copied -** into pDest. Otherwise, the record is copied verbatim. -** -** This function does not actually write the new value to cursor pDest. -** Instead, it creates and populates any required overflow pages and -** writes the data for the new cell into the BtShared.pTmpSpace buffer -** for the destination database. The size of the cell, in bytes, is left -** in BtShared.nPreformatSize. The caller completes the insertion by -** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){ - BtShared *pBt = pDest->pBt; - u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */ - const u8 *aIn; /* Pointer to next input buffer */ - u32 nIn; /* Size of input buffer aIn[] */ - u32 nRem; /* Bytes of data still to copy */ - - getCellInfo(pSrc); - if( pSrc->info.nPayload<0x80 ){ - *(aOut++) = pSrc->info.nPayload; - }else{ - aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload); - } - if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey); - nIn = pSrc->info.nLocal; - aIn = pSrc->info.pPayload; - if( aIn+nIn>pSrc->pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pSrc->pPage); - } - nRem = pSrc->info.nPayload; - if( nIn==nRem && nInpPage->maxLocal ){ - memcpy(aOut, aIn, nIn); - pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace); - return SQLITE_OK; - }else{ - int rc = SQLITE_OK; - Pager *pSrcPager = pSrc->pBt->pPager; - u8 *pPgnoOut = 0; - Pgno ovflIn = 0; - DbPage *pPageIn = 0; - MemPage *pPageOut = 0; - u32 nOut; /* Size of output buffer aOut[] */ - - nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload); - pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace); - if( nOutinfo.nPayload ){ - pPgnoOut = &aOut[nOut]; - pBt->nPreformatSize += 4; - } - - if( nRem>nIn ){ - if( aIn+nIn+4>pSrc->pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pSrc->pPage); - } - ovflIn = get4byte(&pSrc->info.pPayload[nIn]); - } - - do { - nRem -= nOut; - do{ - assert( nOut>0 ); - if( nIn>0 ){ - int nCopy = MIN(nOut, nIn); - memcpy(aOut, aIn, nCopy); - nOut -= nCopy; - nIn -= nCopy; - aOut += nCopy; - aIn += nCopy; - } - if( nOut>0 ){ - sqlite3PagerUnref(pPageIn); - pPageIn = 0; - rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY); - if( rc==SQLITE_OK ){ - aIn = (const u8*)sqlite3PagerGetData(pPageIn); - ovflIn = get4byte(aIn); - aIn += 4; - nIn = pSrc->pBt->usableSize - 4; - } - } - }while( rc==SQLITE_OK && nOut>0 ); - - if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){ - Pgno pgnoNew; - MemPage *pNew = 0; - rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); - put4byte(pPgnoOut, pgnoNew); - if( ISAUTOVACUUM(pBt) && pPageOut ){ - ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc); - } - releasePage(pPageOut); - pPageOut = pNew; - if( pPageOut ){ - pPgnoOut = pPageOut->aData; - put4byte(pPgnoOut, 0); - aOut = &pPgnoOut[4]; - nOut = MIN(pBt->usableSize - 4, nRem); - } - } - }while( nRem>0 && rc==SQLITE_OK ); - - releasePage(pPageOut); - sqlite3PagerUnref(pPageIn); - return rc; - } -} - -/* -** Delete the entry that the cursor is pointing to. +** Delete the entry that the cursor is pointing to. ** ** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then ** the cursor is left pointing at an arbitrary location after the delete. ** But if that bit is set, then the cursor is left in a state such that ** the next call to BtreeNext() or BtreePrev() moves it to the same row @@ -80517,80 +67831,54 @@ ** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, ** but which might be used by alternative storage engines. */ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ Btree *p = pCur->pBtree; - BtShared *pBt = p->pBt; - int rc; /* Return code */ - MemPage *pPage; /* Page to delete cell from */ - unsigned char *pCell; /* Pointer to cell to delete */ - int iCellIdx; /* Index of cell to delete */ - int iCellDepth; /* Depth of node containing pCell */ - CellInfo info; /* Size of the cell being deleted */ - u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */ + BtShared *pBt = p->pBt; + int rc; /* Return code */ + MemPage *pPage; /* Page to delete cell from */ + unsigned char *pCell; /* Pointer to cell to delete */ + int iCellIdx; /* Index of cell to delete */ + int iCellDepth; /* Depth of node containing pCell */ + CellInfo info; /* Size of the cell being deleted */ + int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ + u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ assert( cursorOwnsBtShared(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); - assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); - if( pCur->eState!=CURSOR_VALID ){ - if( pCur->eState>=CURSOR_REQUIRESEEK ){ - rc = btreeRestoreCursorPosition(pCur); - assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID ); - if( rc || pCur->eState!=CURSOR_VALID ) return rc; - }else{ - return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot); - } - } + assert( pCur->ixapPage[pCur->iPage]->nCell ); assert( pCur->eState==CURSOR_VALID ); + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); iCellDepth = pCur->iPage; iCellIdx = pCur->ix; - pPage = pCur->pPage; - if( pPage->nCell<=iCellIdx ){ - return SQLITE_CORRUPT_PAGE(pPage); - } + pPage = pCur->apPage[iCellDepth]; pCell = findCell(pPage, iCellIdx); - if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - if( pCell<&pPage->aCellIdx[pPage->nCell] ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - - /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must + + /* If the bPreserve flag is set to true, then the cursor position must ** be preserved following this delete operation. If the current delete ** will cause a b-tree rebalance, then this is done by saving the cursor - ** key and leaving the cursor in CURSOR_REQUIRESEEK state before - ** returning. + ** key and leaving the cursor in CURSOR_REQUIRESEEK state before + ** returning. ** - ** If the current delete will not cause a rebalance, then the cursor + ** Or, if the current delete will not cause a rebalance, then the cursor ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately - ** before or after the deleted entry. - ** - ** The bPreserve value records which path is required: - ** - ** bPreserve==0 Not necessary to save the cursor position - ** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position - ** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT. - */ - bPreserve = (flags & BTREE_SAVEPOSITION)!=0; + ** before or after the deleted entry. In this case set bSkipnext to true. */ if( bPreserve ){ - if( !pPage->leaf - || (pPage->nFree+pPage->xCellSize(pPage,pCell)+2) > - (int)(pBt->usableSize*2/3) - || pPage->nCell==1 /* See dbfuzz001.test for a test case */ + if( !pPage->leaf + || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) ){ /* A b-tree rebalance will be required after deleting this entry. ** Save the cursor key. */ rc = saveCursorKey(pCur); if( rc ) return rc; }else{ - bPreserve = 2; + bSkipnext = 1; } } /* If the page containing the entry to delete is not a leaf page, move ** the cursor to the largest entry in the tree that is smaller than @@ -80612,52 +67900,43 @@ if( rc ) return rc; } /* 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 && p->hasIncrblobCur ){ + if( pCur->pKeyInfo==0 ){ invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0); } /* Make the page containing the entry to be deleted writable. Then free any ** overflow pages associated with the entry and finally remove the cell ** itself from within the page. */ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; - BTREE_CLEAR_CELL(rc, pPage, pCell, info); + 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 ** is currently pointing to the largest entry in the sub-tree headed ** by the child-page of the cell that was just deleted from an internal ** 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->pPage; + MemPage *pLeaf = pCur->apPage[pCur->iPage]; int nCell; - Pgno n; + Pgno n = pCur->apPage[iCellDepth+1]->pgno; unsigned char *pTmp; - if( pLeaf->nFree<0 ){ - rc = btreeComputeFreeSpace(pLeaf); - if( rc ) return rc; - } - 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_PAGE(pLeaf); + if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; nCell = pLeaf->xCellSize(pLeaf, pCell); assert( MX_CELL_SIZE(pBt) >= nCell ); pTmp = pBt->pTmpSpace; assert( pTmp!=0 ); rc = sqlite3PagerWrite(pLeaf->pDbPage); if( rc==SQLITE_OK ){ - rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n); + insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); } dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); if( rc ) return rc; } @@ -80672,35 +67951,24 @@ ** tricky as the leaf node may be underfull, and the internal node may ** be either under or overfull. In this case run the balancing algorithm ** on the leaf node first. If the balance proceeds far enough up the ** tree that we can be sure that any problem in the internal node has ** been corrected, so be it. Otherwise, after balancing the leaf node, - ** walk the cursor up the tree to the internal node and balance it as + ** walk the cursor up the tree to the internal node and balance it as ** well. */ - assert( pCur->pPage->nOverflow==0 ); - assert( pCur->pPage->nFree>=0 ); - if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){ - /* Optimization: If the free space is less than 2/3rds of the page, - ** then balance() will always be a no-op. No need to invoke it. */ - rc = SQLITE_OK; - }else{ - rc = balance(pCur); - } + 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( bPreserve>1 ){ - assert( (pCur->iPage==iCellDepth || CORRUPT_DB) ); - assert( pPage==pCur->pPage || CORRUPT_DB ); + if( bSkipnext ){ + assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); + assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); pCur->eState = CURSOR_SKIPNEXT; if( iCellIdx>=pPage->nCell ){ pCur->skipNext = -1; pCur->ix = pPage->nCell-1; @@ -80708,14 +67976,12 @@ pCur->skipNext = 1; } }else{ rc = moveToRoot(pCur); if( bPreserve ){ - btreeReleaseAllCursorPages(pCur); pCur->eState = CURSOR_REQUIRESEEK; } - if( rc==SQLITE_EMPTY ) rc = SQLITE_OK; } } return rc; } @@ -80728,16 +67994,16 @@ ** flags might not work: ** ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys ** BTREE_ZERODATA Used for SQL indices */ -static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ +static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){ BtShared *pBt = p->pBt; MemPage *pRoot; Pgno pgnoRoot; int rc; - int ptfFlags; /* Page-type flags for the root page of new table */ + int ptfFlags; /* Page-type flage for the root page of new table */ assert( sqlite3BtreeHoldsMutex(p) ); assert( pBt->inTransaction==TRANS_WRITE ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); @@ -80761,23 +68027,21 @@ /* Read the value of meta[3] from the database to determine where the ** root page of the new table should go. meta[3] is the largest root-page ** created so far, so the new root-page is (meta[3]+1). */ sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot); - if( pgnoRoot>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_PGNO(pgnoRoot); - } pgnoRoot++; /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ pgnoRoot++; } - assert( pgnoRoot>=3 ); + assert( pgnoRoot>=3 || CORRUPT_DB ); + testcase( pgnoRoot<3 ); /* Allocate a page. The page that currently resides at pgnoRoot will ** be moved to the allocated page (unless the allocated page happens ** to reside at pgnoRoot). */ @@ -80810,11 +68074,11 @@ if( rc!=SQLITE_OK ){ return rc; } rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ - rc = SQLITE_CORRUPT_PGNO(pgnoRoot); + rc = SQLITE_CORRUPT_BKPT; } if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; } @@ -80836,11 +68100,11 @@ releasePage(pRoot); return rc; } }else{ pRoot = pPageMove; - } + } /* Update the pointer-map and meta-data with the new root-page number. */ ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc); if( rc ){ releasePage(pRoot); @@ -80870,14 +68134,14 @@ ptfFlags = PTF_ZERODATA | PTF_LEAF; } zeroPage(pRoot, ptfFlags); sqlite3PagerUnref(pRoot->pDbPage); assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 ); - *piTable = pgnoRoot; + *piTable = (int)pgnoRoot; return SQLITE_OK; } -SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){ +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ int rc; sqlite3BtreeEnter(p); rc = btreeCreateTable(p, piTable, flags); sqlite3BtreeLeave(p); return rc; @@ -80889,11 +68153,11 @@ */ static int clearDatabasePage( BtShared *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ int freePageFlag, /* Deallocate page if true */ - i64 *pnChange /* Add number of Cells freed to this counter */ + int *pnChange /* Add number of Cells freed to this counter */ ){ MemPage *pPage; int rc; unsigned char *pCell; int i; @@ -80900,36 +68164,34 @@ int hdr; CellInfo info; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_PGNO(pgno); + return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, 0); + rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); if( rc ) return rc; - if( (pBt->openFlags & BTREE_SINGLE)==0 - && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) - ){ - rc = SQLITE_CORRUPT_PAGE(pPage); + if( pPage->bBusy ){ + rc = SQLITE_CORRUPT_BKPT; goto cleardatabasepage_out; } + pPage->bBusy = 1; hdr = pPage->hdrOffset; for(i=0; inCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } - BTREE_CLEAR_CELL(rc, pPage, pCell, info); + rc = clearCell(pPage, pCell, &info); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; - if( pPage->intKey ) pnChange = 0; - } - if( pnChange ){ + }else if( pnChange ){ + assert( pPage->intKey || CORRUPT_DB ); testcase( !pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ freePage(pPage, &rc); @@ -80936,10 +68198,11 @@ }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF); } cleardatabasepage_out: + pPage->bBusy = 0; releasePage(pPage); return rc; } /* @@ -80949,14 +68212,15 @@ ** ** This routine will fail with SQLITE_LOCKED if there are any open ** read cursors on the table. Open write cursors are moved to the ** root of the table. ** -** If pnChange is not NULL, then the integer value pointed to by pnChange -** is incremented by the number of entries in the table. +** If pnChange is not NULL, then table iTable must be an intkey table. The +** integer value pointed to by pnChange is incremented by the number of +** entries in the table. */ -SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){ +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){ int rc; BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); assert( p->inTrans==TRANS_WRITE ); @@ -80964,13 +68228,11 @@ if( SQLITE_OK==rc ){ /* 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). */ - if( p->hasIncrblobCur ){ - invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1); - } + invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1); rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); } sqlite3BtreeLeave(p); return rc; } @@ -80991,16 +68253,16 @@ ** ** This routine will fail with SQLITE_LOCKED if there are any open ** cursors on the table. ** ** If AUTOVACUUM is enabled and the page at iTable is not the last -** root page in the database file, then the last root page +** root page in the database file, then the last root page ** in the database file is moved into the slot formerly occupied by ** iTable and that last slot formerly occupied by the last root page ** is added to the freelist instead of iTable. In this say, all ** root pages are kept at the beginning of the database file, which -** is necessary for AUTOVACUUM to work right. *piMoved is set to the +** is necessary for AUTOVACUUM to work right. *piMoved is set to the ** page number that used to be the last root page in the file before ** the move. If no page gets moved, *piMoved is set to 0. ** The last root page is recorded in meta[3] and the value of ** meta[3] is updated by this procedure. */ @@ -81010,18 +68272,15 @@ BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); assert( p->inTrans==TRANS_WRITE ); assert( iTable>=2 ); - if( iTable>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_PGNO(iTable); - } + rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); + if( rc ) return rc; rc = sqlite3BtreeClearTable(p, iTable, 0); - if( rc ) return rc; - rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); - if( NEVER(rc) ){ + if( rc ){ releasePage(pPage); return rc; } *piMoved = 0; @@ -81034,20 +68293,20 @@ Pgno maxRootPgno; sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno); if( iTable==maxRootPgno ){ /* If the table being dropped is the table with the largest root-page - ** number in the database, put the root page on the free list. + ** number in the database, put the root page on the free list. */ freePage(pPage, &rc); releasePage(pPage); if( rc!=SQLITE_OK ){ return rc; } }else{ /* The table being dropped does not have the largest root-page - ** number in the database. So move the page that does into the + ** number in the database. So move the page that does into the ** gap left by the deleted root-page. */ MemPage *pMove; releasePage(pPage); rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); @@ -81085,11 +68344,11 @@ }else{ freePage(pPage, &rc); releasePage(pPage); } #endif - return rc; + return rc; } SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ int rc; sqlite3BtreeEnter(p); rc = btreeDropTable(p, iTable, piMoved); @@ -81104,11 +68363,11 @@ ** ** Read the meta-information out of a database file. Meta[0] ** is the number of free pages currently in the database. Meta[1] ** through meta[15] are available for use by higher layers. Meta[0] ** is read-only, the others are read/write. -** +** ** The schema layer numbers meta values differently. At the schema ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. ** ** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead @@ -81121,16 +68380,16 @@ SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); assert( p->inTrans>TRANS_NONE ); - assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) ); + assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); assert( pBt->pPage1 ); assert( idx>=0 && idx<=15 ); if( idx==BTREE_DATA_VERSION ){ - *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion; + *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; }else{ *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); } /* If auto-vacuum is disabled in this build and this is an auto-vacuum @@ -81170,45 +68429,46 @@ } sqlite3BtreeLeave(p); return rc; } +#ifndef SQLITE_OMIT_BTREECOUNT /* ** The first argument, pCur, is a cursor opened on some b-tree. Count the ** number of entries in the b-tree and write the result to *pnEntry. ** -** SQLITE_OK is returned if the operation is successfully executed. +** SQLITE_OK is returned if the operation is successfully executed. ** Otherwise, if an error is encountered (i.e. an IO error or database ** corruption) an SQLite error code is returned. */ -SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){ +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ i64 nEntry = 0; /* Value to return in *pnEntry */ int rc; /* Return code */ - rc = moveToRoot(pCur); - if( rc==SQLITE_EMPTY ){ + if( pCur->pgnoRoot==0 ){ *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). + ** page in the B-Tree structure (not including overflow pages). */ - while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){ + while( rc==SQLITE_OK ){ int iIdx; /* Index of child node in parent */ MemPage *pPage; /* Current page of the b-tree */ - /* If this is a leaf page or the tree is not an int-key tree, then + /* If this is a leaf page or the tree is not an int-key tree, then ** this page contains countable entries. Increment the entry counter ** accordingly. */ - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; if( pPage->leaf || !pPage->intKey ){ nEntry += pPage->nCell; } - /* pPage is a leaf node. This loop navigates the cursor so that it + /* pPage is a leaf node. This loop navigates the cursor so that it ** points to the first interior cell that it points to the parent of ** the next page in the tree that has not yet been visited. The ** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell ** of the page, or to the number of cells in the page if the next page ** to visit is the right-child of its parent. @@ -81222,17 +68482,17 @@ /* All pages of the b-tree have been visited. Return successfully. */ *pnEntry = nEntry; return moveToRoot(pCur); } moveToParent(pCur); - }while ( pCur->ix>=pCur->pPage->nCell ); + }while ( pCur->ix>=pCur->apPage[pCur->iPage]->nCell ); pCur->ix++; - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; } - /* Descend to the child node of the cell that the cursor currently + /* Descend to the child node of the cell that the cursor currently ** points at. This is the right-child if (iIdx==pPage->nCell). */ iIdx = pCur->ix; if( iIdx==pPage->nCell ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); @@ -81242,10 +68502,11 @@ } /* An error has occurred. Return an error code. */ return rc; } +#endif /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ @@ -81252,70 +68513,33 @@ SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){ return p->pBt->pPager; } #ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* -** Record an OOM error during integrity_check -*/ -static void checkOom(IntegrityCk *pCheck){ - pCheck->rc = SQLITE_NOMEM; - pCheck->mxErr = 0; /* Causes integrity_check processing to stop */ - if( pCheck->nErr==0 ) pCheck->nErr++; -} - -/* -** Invoke the progress handler, if appropriate. Also check for an -** interrupt. -*/ -static void checkProgress(IntegrityCk *pCheck){ - sqlite3 *db = pCheck->db; - if( AtomicLoad(&db->u1.isInterrupted) ){ - pCheck->rc = SQLITE_INTERRUPT; - pCheck->nErr++; - pCheck->mxErr = 0; - } -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress ){ - assert( db->nProgressOps>0 ); - pCheck->nStep++; - if( (pCheck->nStep % db->nProgressOps)==0 - && db->xProgress(db->pProgressArg) - ){ - pCheck->rc = SQLITE_INTERRUPT; - pCheck->nErr++; - pCheck->mxErr = 0; - } - } -#endif -} - /* ** Append a message to the error message string. */ static void checkAppendMsg( IntegrityCk *pCheck, const char *zFormat, ... ){ va_list ap; - checkProgress(pCheck); if( !pCheck->mxErr ) return; pCheck->mxErr--; pCheck->nErr++; va_start(ap, zFormat); if( pCheck->errMsg.nChar ){ - sqlite3_str_append(&pCheck->errMsg, "\n", 1); + sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); } if( pCheck->zPfx ){ - sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, - pCheck->v0, pCheck->v1, pCheck->v2); + sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); } - sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); + sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); va_end(ap); - if( pCheck->errMsg.accError==SQLITE_NOMEM ){ - checkOom(pCheck); + if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ + pCheck->mallocFailed = 1; } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK @@ -81323,21 +68547,19 @@ /* ** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that ** corresponds to page iPg is already set. */ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( pCheck->aPgRef!=0 ); - assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); } /* ** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. */ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( pCheck->aPgRef!=0 ); - assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); } /* @@ -81347,25 +68569,26 @@ ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ - if( iPage>pCheck->nCkPage || iPage==0 ){ - checkAppendMsg(pCheck, "invalid page number %u", iPage); + if( iPage==0 ) return 1; + if( iPage>pCheck->nPage ){ + checkAppendMsg(pCheck, "invalid page number %d", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ - checkAppendMsg(pCheck, "2nd reference to page %u", iPage); + checkAppendMsg(pCheck, "2nd reference to page %d", iPage); return 1; } setPageReferenced(pCheck, iPage); return 0; } #ifndef SQLITE_OMIT_AUTOVACUUM /* -** Check that the entry in the pointer-map for page iChild maps to +** Check that the entry in the pointer-map for page iChild maps to ** page iParent, pointer type ptrType. If not, append an error message ** to pCheck. */ static void checkPtrmap( IntegrityCk *pCheck, /* Integrity check context */ @@ -81377,18 +68600,18 @@ u8 ePtrmapType; Pgno iPtrmapParent; rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) checkOom(pCheck); - checkAppendMsg(pCheck, "Failed to read ptrmap key=%u", iChild); + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1; + checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild); return; } if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ checkAppendMsg(pCheck, - "Bad ptr map entry key=%u expected=(%u,%u) got=(%u,%u)", + "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", iChild, eType, iParent, ePtrmapType, iPtrmapParent); } } #endif @@ -81397,39 +68620,44 @@ ** Verify that the number of pages on the list is N. */ static void checkList( IntegrityCk *pCheck, /* Integrity checking context */ int isFreeList, /* True for a freelist. False for overflow page list */ - Pgno iPage, /* Page number for first page in the list */ - u32 N /* Expected number of pages in the list */ + int iPage, /* Page number for first page in the list */ + int N /* Expected number of pages in the list */ ){ int i; - u32 expected = N; - int nErrAtStart = pCheck->nErr; - while( iPage!=0 && pCheck->mxErr ){ + int expected = N; + int iFirst = iPage; + while( N-- > 0 && pCheck->mxErr ){ DbPage *pOvflPage; unsigned char *pOvflData; + if( iPage<1 ){ + checkAppendMsg(pCheck, + "%d of %d pages missing from overflow list starting at %d", + N+1, expected, iFirst); + break; + } if( checkRef(pCheck, iPage) ) break; - N--; if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ - checkAppendMsg(pCheck, "failed to get page %u", iPage); + checkAppendMsg(pCheck, "failed to get page %d", iPage); break; } pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); if( isFreeList ){ - u32 n = (u32)get4byte(&pOvflData[4]); + int n = get4byte(&pOvflData[4]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pCheck->pBt->autoVacuum ){ checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0); } #endif - if( n>pCheck->pBt->usableSize/4-2 ){ + if( n>(int)pCheck->pBt->usableSize/4-2 ){ checkAppendMsg(pCheck, - "freelist leaf count too big on page %u", iPage); + "freelist leaf count too big on page %d", iPage); N--; }else{ - for(i=0; i<(int)n; i++){ + for(i=0; ipBt->autoVacuum ){ checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0); } @@ -81451,16 +68679,14 @@ } } #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); - } - if( N && nErrAtStart==pCheck->nErr ){ - checkAppendMsg(pCheck, - "%s is %u but should be %u", - isFreeList ? "size" : "overflow list length", - expected-N, expected); + + if( isFreeList && N<(iPage!=0) ){ + checkAppendMsg(pCheck, "free-page count in header is too small"); + } } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* @@ -81479,18 +68705,16 @@ ** removes the root element from the heap (the minimum value in the heap) ** and then moves other nodes around as necessary to preserve the heap ** property. ** ** This heap is used for cell overlap and coverage testing. Each u32 -** entry represents the span of a cell or freeblock on a btree page. +** entry represents the span of a cell or freeblock on a btree page. ** The upper 16 bits are the index of the first byte of a range and the ** lower 16 bits are the index of the last byte of that range. */ static void btreeHeapInsert(u32 *aHeap, u32 x){ - u32 j, i; - assert( aHeap!=0 ); - i = ++aHeap[0]; + u32 j, i = ++aHeap[0]; aHeap[i] = x; while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ x = aHeap[j]; aHeap[j] = aHeap[i]; aHeap[i] = x; @@ -81511,19 +68735,19 @@ x = aHeap[i]; aHeap[i] = aHeap[j]; aHeap[j] = x; i = j; } - return 1; + return 1; } #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Do various sanity checks on a single page of a tree. Return ** the tree depth. Root pages return 0. Parents of root pages ** return 1, and so forth. -** +** ** These checks are done: ** ** 1. Make sure that cells and freeblocks do not overlap ** but combine to completely cover the page. ** 2. Make sure integer cell keys are in order. @@ -81531,11 +68755,11 @@ ** 4. Recursively call checkTreePage on all children. ** 5. Verify that the depth of all children is the same. */ static int checkTreePage( IntegrityCk *pCheck, /* Context for the sanity check */ - Pgno iPage, /* Page number of the page to check */ + int iPage, /* Page number of the page to check */ i64 *piMinKey, /* Write minimum integer primary key here */ i64 maxKey /* Error if integer primary key greater than this */ ){ MemPage *pPage = 0; /* The page being analyzed */ int i; /* Loop counter */ @@ -81563,22 +68787,19 @@ int saved_v2 = pCheck->v2; u8 savedIsInit = 0; /* Check that the page exists */ - checkProgress(pCheck); - if( pCheck->mxErr==0 ) goto end_of_check; pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; - pCheck->zPfx = "Tree %u page %u: "; + pCheck->zPfx = "Page %d: "; pCheck->v1 = iPage; - if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){ + if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, "unable to get the page. error code=%d", rc); - if( rc==SQLITE_IOERR_NOMEM ) pCheck->rc = SQLITE_NOMEM; goto end_of_check; } /* Clear MemPage.isInit to make sure the corruption detection code in ** btreeInitPage() is executed. */ @@ -81588,30 +68809,22 @@ assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ checkAppendMsg(pCheck, "btreeInitPage() returns error code %d", rc); goto end_of_check; } - if( (rc = btreeComputeFreeSpace(pPage))!=0 ){ - assert( rc==SQLITE_CORRUPT ); - checkAppendMsg(pCheck, "free space corruption", rc); - goto end_of_check; - } data = pPage->aData; hdr = pPage->hdrOffset; /* Set up for cell analysis */ - pCheck->zPfx = "Tree %u page %u cell %u: "; + pCheck->zPfx = "On tree page %d cell %d: "; contentOffset = get2byteNotZero(&data[hdr+5]); assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ nCell = get2byte(&data[hdr+3]); assert( pPage->nCell==nCell ); - if( pPage->leaf || pPage->intKey==0 ){ - pCheck->nRow += nCell; - } /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page ** immediately follows the b-tree page header. */ cellStart = hdr + 12 - 4*pPage->leaf; assert( pPage->aCellIdx==&data[cellStart] ); @@ -81620,11 +68833,11 @@ if( !pPage->leaf ){ /* Analyze the right-child page of internal pages */ pgno = get4byte(&data[hdr+8]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - pCheck->zPfx = "Tree %u page %u right child: "; + pCheck->zPfx = "On page %d at right child: "; checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); } #endif depth = checkTreePage(pCheck, pgno, &maxKey, maxKey); keyCanBeEqual = 0; @@ -81644,11 +68857,11 @@ pCheck->v2 = i; assert( pCellIdx==&data[cellStart + i*2] ); pc = get2byteAligned(pCellIdx); pCellIdx -= 2; if( pcusableSize-4 ){ - checkAppendMsg(pCheck, "Offset %u out of range %u..%u", + checkAppendMsg(pCheck, "Offset %d out of range %d..%d", pc, contentOffset, usableSize-4); doCoverageCheck = 0; continue; } pCell = &data[pc]; @@ -81668,11 +68881,11 @@ keyCanBeEqual = 0; /* Only the first key on the page may ==maxKey */ } /* Check the content overflow list */ if( info.nPayload>info.nLocal ){ - u32 nPage; /* Number of pages on the overflow chain */ + int nPage; /* Number of pages on the overflow chain */ Pgno pgnoOvfl; /* First page of the overflow chain */ assert( pc + info.nSize - 4 <= usableSize ); nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4); pgnoOvfl = get4byte(&pCell[info.nSize - 4]); #ifndef SQLITE_OMIT_AUTOVACUUM @@ -81719,42 +68932,41 @@ pc = get2byteAligned(&data[cellStart+i*2]); size = pPage->xCellSize(pPage, &data[pc]); btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); } } - assert( heap!=0 ); /* Add the freeblocks to the min-heap ** ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header ** is the offset of the first freeblock, or zero if there are no - ** freeblocks on the page. + ** freeblocks on the page. */ i = get2byte(&data[hdr+1]); while( i>0 ){ int size, j; - assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ + assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */ size = get2byte(&data[i+2]); - assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */ + assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */ btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a ** big-endian integer which is the offset in the b-tree page of the next ** freeblock in the chain, or zero if the freeblock is the last on the ** chain. */ j = get2byte(&data[i]); /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of ** increasing offset. */ - assert( j==0 || j>i+size ); /* Enforced by btreeComputeFreeSpace() */ - assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ + assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */ + assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */ i = j; } - /* Analyze the min-heap looking for overlap between cells and/or + /* Analyze the min-heap looking for overlap between cells and/or ** freeblocks, and counting the number of untracked bytes in nFrag. - ** + ** ** Each min-heap entry is of the form: (start_address<<16)|end_address. ** There is an implied first entry the covers the page header, the cell ** pointer index, and the gap between the cell pointer index and the start - ** of cell content. + ** of cell content. ** ** The loop below pulls entries from the min-heap in order and compares ** the start_address against the previous end_address. If there is an ** overlap, that means bytes are used multiple times. If there is a gap, ** that gap is added to the fragmentation count. @@ -81762,11 +68974,11 @@ nFrag = 0; prev = contentOffset - 1; /* Implied first min-heap entry */ while( btreeHeapPull(heap,&x) ){ if( (prev&0xffff)>=(x>>16) ){ checkAppendMsg(pCheck, - "Multiple uses for byte %u of page %u", x>>16, iPage); + "Multiple uses for byte %u of page %d", x>>16, iPage); break; }else{ nFrag += (x>>16) - (prev&0xffff) - 1; prev = x; } @@ -81777,11 +68989,11 @@ ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the ** number of fragmented free bytes within the cell content area. */ if( heap[0]==0 && nFrag!=data[hdr+7] ){ checkAppendMsg(pCheck, - "Fragmentation of %u bytes reported as %u on page %u", + "Fragmentation of %d bytes reported as %d on page %d", nFrag, data[hdr+7], iPage); } } end_of_check: @@ -81805,168 +69017,120 @@ ** ** Write the number of error seen in *pnErr. Except for some memory ** allocation errors, an error message held in memory obtained from ** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is ** returned. If a memory allocation error occurs, NULL is returned. -** -** If the first entry in aRoot[] is 0, that indicates that the list of -** root pages is incomplete. This is a "partial integrity-check". This -** happens when performing an integrity check on a single table. The -** zero is skipped, of course. But in addition, the freelist checks -** and the checks to make sure every page is referenced are also skipped, -** since obviously it is not possible to know which pages are covered by -** the unverified btrees. Except, if aRoot[1] is 1, then the freelist -** checks are still performed. */ -SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( - sqlite3 *db, /* Database connection that is running the check */ +SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( Btree *p, /* The btree to be checked */ - Pgno *aRoot, /* An array of root pages numbers for individual trees */ - Mem *aCnt, /* Memory cells to write counts for each tree to */ + int *aRoot, /* An array of root pages numbers for individual trees */ int nRoot, /* Number of entries in aRoot[] */ int mxErr, /* Stop reporting errors after this many */ - int *pnErr, /* OUT: Write number of errors seen to this variable */ - char **pzOut /* OUT: Write the error message string here */ + int *pnErr /* Write number of errors seen to this variable */ ){ Pgno i; IntegrityCk sCheck; BtShared *pBt = p->pBt; - u64 savedDbFlags = pBt->db->flags; + int savedDbFlags = pBt->db->flags; char zErr[100]; - int bPartial = 0; /* True if not checking all btrees */ - int bCkFreelist = 1; /* True to scan the freelist */ VVA_ONLY( int nRef ); - assert( nRoot>0 ); - assert( aCnt!=0 ); - - /* aRoot[0]==0 means this is a partial check */ - if( aRoot[0]==0 ){ - assert( nRoot>1 ); - bPartial = 1; - if( aRoot[1]!=1 ) bCkFreelist = 0; - } - sqlite3BtreeEnter(p); assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) ); assert( nRef>=0 ); - memset(&sCheck, 0, sizeof(sCheck)); - sCheck.db = db; sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; - sCheck.nCkPage = btreePagecount(sCheck.pBt); + sCheck.nPage = btreePagecount(sCheck.pBt); sCheck.mxErr = mxErr; + sCheck.nErr = 0; + sCheck.mallocFailed = 0; + sCheck.zPfx = 0; + sCheck.v1 = 0; + sCheck.v2 = 0; + sCheck.aPgRef = 0; + sCheck.heap = 0; sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; - if( sCheck.nCkPage==0 ){ + if( sCheck.nPage==0 ){ goto integrity_ck_cleanup; } - sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); + sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); if( !sCheck.aPgRef ){ - checkOom(&sCheck); + sCheck.mallocFailed = 1; goto integrity_ck_cleanup; } sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); if( sCheck.heap==0 ){ - checkOom(&sCheck); + sCheck.mallocFailed = 1; goto integrity_ck_cleanup; } i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nCkPage ) setPageReferenced(&sCheck, i); + if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); /* Check the integrity of the freelist */ - if( bCkFreelist ){ - sCheck.zPfx = "Freelist: "; - checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), - get4byte(&pBt->pPage1->aData[36])); - sCheck.zPfx = 0; - } + sCheck.zPfx = "Main freelist: "; + checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), + get4byte(&pBt->pPage1->aData[36])); + sCheck.zPfx = 0; /* Check all the tables. */ -#ifndef SQLITE_OMIT_AUTOVACUUM - if( !bPartial ){ - if( pBt->autoVacuum ){ - Pgno mx = 0; - Pgno mxInHdr; - for(i=0; (int)ipPage1->aData[52]); - if( mx!=mxInHdr ){ - checkAppendMsg(&sCheck, - "max rootpage (%u) disagrees with header (%u)", - mx, mxInHdr - ); - } - }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){ - checkAppendMsg(&sCheck, - "incremental_vacuum enabled with a max rootpage of zero" - ); - } - } -#endif testcase( pBt->db->flags & SQLITE_CellSizeCk ); - pBt->db->flags &= ~(u64)SQLITE_CellSizeCk; + pBt->db->flags &= ~SQLITE_CellSizeCk; for(i=0; (int)iautoVacuum && aRoot[i]>1 && !bPartial ){ - checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); - } + if( pBt->autoVacuum && aRoot[i]>1 ){ + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); + } #endif - sCheck.v0 = aRoot[i]; - checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); - } - sqlite3MemSetArrayInt64(aCnt, i, sCheck.nRow); + checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); } pBt->db->flags = savedDbFlags; /* Make sure every page in the file is referenced */ - if( !bPartial ){ - for(i=1; i<=sCheck.nCkPage && sCheck.mxErr; i++){ + for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM - if( getPageReferenced(&sCheck, i)==0 ){ - checkAppendMsg(&sCheck, "Page %u: never used", i); - } + if( getPageReferenced(&sCheck, i)==0 ){ + checkAppendMsg(&sCheck, "Page %d is never used", i); + } #else - /* If the database supports auto-vacuum, make sure no tables contain - ** references to pointer-map pages. - */ - if( getPageReferenced(&sCheck, i)==0 && - (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Page %u: never used", i); - } - if( getPageReferenced(&sCheck, i)!=0 && - (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Page %u: pointer map referenced", i); - } + /* If the database supports auto-vacuum, make sure no tables contain + ** references to pointer-map pages. + */ + if( getPageReferenced(&sCheck, i)==0 && + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, "Page %d is never used", i); + } + if( getPageReferenced(&sCheck, i)!=0 && + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i); + } #endif - } } /* Clean up and report errors. */ integrity_ck_cleanup: sqlite3PageFree(sCheck.heap); sqlite3_free(sCheck.aPgRef); + if( sCheck.mallocFailed ){ + sqlite3StrAccumReset(&sCheck.errMsg); + sCheck.nErr++; + } *pnErr = sCheck.nErr; - if( sCheck.nErr==0 ){ - sqlite3_str_reset(&sCheck.errMsg); - *pzOut = 0; - }else{ - *pzOut = sqlite3StrAccumFinish(&sCheck.errMsg); - } + if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); /* Make sure this analysis did not leave any unref() pages. */ assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); sqlite3BtreeLeave(p); - return sCheck.rc; + return sqlite3StrAccumFinish(&sCheck.errMsg); } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. Return @@ -81992,23 +69156,22 @@ assert( p->pBt->pPager!=0 ); return sqlite3PagerJournalname(p->pBt->pPager); } /* -** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE -** to describe the current transaction state of Btree p. +** Return non-zero if a transaction is active. */ -SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree *p){ +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){ assert( p==0 || sqlite3_mutex_held(p->db->mutex) ); - return p ? p->inTrans : 0; + return (p && (p->inTrans==TRANS_WRITE)); } #ifndef SQLITE_OMIT_WAL /* ** Run a checkpoint on the Btree passed as the first argument. ** -** Return SQLITE_LOCKED if this or any other connection has an open +** Return SQLITE_LOCKED if this or any other connection has an open ** transaction on the shared-cache the argument Btree is connected to. ** ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. */ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){ @@ -82026,35 +69189,41 @@ return rc; } #endif /* -** Return true if there is currently a backup running on Btree p. +** Return non-zero if a read (or write) transaction is active. */ +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){ + assert( p ); + assert( sqlite3_mutex_held(p->db->mutex) ); + return p->inTrans!=TRANS_NONE; +} + SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){ assert( p ); assert( sqlite3_mutex_held(p->db->mutex) ); return p->nBackup!=0; } /* ** This function returns a pointer to a blob of memory associated with ** a single shared-btree. The memory is used by client code for its own -** purposes (for example, to store a high-level schema associated with +** purposes (for example, to store a high-level schema associated with ** the shared-btree). The btree layer manages reference counting issues. ** ** The first time this is called on a shared-btree, nBytes bytes of memory -** are allocated, zeroed, and returned to the caller. For each subsequent +** are allocated, zeroed, and returned to the caller. For each subsequent ** call the nBytes parameter is ignored and a pointer to the same blob -** of memory returned. +** of memory returned. ** ** If the nBytes parameter is 0 and the blob of memory has not yet been ** allocated, a null pointer is returned. If the blob has already been ** allocated, it is returned as normal. ** -** Just before the shared-btree is closed, the function passed as the -** xFree argument when the memory allocation was made is invoked on the +** Just before the shared-btree is closed, the function passed as the +** xFree argument when the memory allocation was made is invoked on the ** blob of allocated memory. The xFree function should not call sqlite3_free() ** on the memory, the btree layer does that. */ SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; @@ -82066,19 +69235,19 @@ sqlite3BtreeLeave(p); return pBt->pSchema; } /* -** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared -** btree as the argument handle holds an exclusive lock on the -** sqlite_schema table. Otherwise SQLITE_OK. +** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared +** btree as the argument handle holds an exclusive lock on the +** sqlite_master table. Otherwise SQLITE_OK. */ SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){ int rc; assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); - rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); + rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE ); sqlite3BtreeLeave(p); return rc; } @@ -82108,15 +69277,15 @@ } #endif #ifndef SQLITE_OMIT_INCRBLOB /* -** Argument pCsr must be a cursor opened for writing on an -** INTKEY table currently pointing at a valid table entry. +** Argument pCsr must be a cursor opened for writing on an +** INTKEY table currently pointing at a valid table entry. ** This function modifies the data stored as part of that entry. ** -** Only the data content may only be modified, it is not possible to +** Only the data content may only be modified, it is not possible to ** change the length of the data stored. If this function is called with ** parameters that attempt to write past the end of the existing data, ** no modifications are made and SQLITE_CORRUPT is returned. */ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ @@ -82143,11 +69312,11 @@ ** saveAllCursors can only return SQLITE_OK. */ VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr); assert( rc==SQLITE_OK ); - /* Check some assumptions: + /* Check some assumptions: ** (a) the cursor is open for writing, ** (b) there is a read/write transaction open, ** (c) the connection holds a write-lock on the table (if required), ** (d) there are no conflicting read-locks, and ** (e) the cursor points at a valid row of an intKey table. @@ -82157,46 +69326,46 @@ } assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0 && pCsr->pBt->inTransaction==TRANS_WRITE ); assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); - assert( pCsr->pPage->intKey ); + assert( pCsr->apPage[pCsr->iPage]->intKey ); return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); } -/* +/* ** Mark this cursor as an incremental blob cursor. */ SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ pCur->curFlags |= BTCF_Incrblob; pCur->pBtree->hasIncrblobCur = 1; } #endif /* -** Set both the "read version" (single byte at byte offset 18) and +** Set both the "read version" (single byte at byte offset 18) and ** "write version" (single byte at byte offset 19) fields in the database ** header to iVersion. */ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ BtShared *pBt = pBtree->pBt; int rc; /* Return code */ - + assert( iVersion==1 || iVersion==2 ); /* If setting the version fields to 1, do not automatically open the ** WAL connection, even if the version fields are currently set to 2. */ pBt->btsFlags &= ~BTS_NO_WAL; if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; - rc = sqlite3BtreeBeginTrans(pBtree, 0, 0); + rc = sqlite3BtreeBeginTrans(pBtree, 0); if( rc==SQLITE_OK ){ u8 *aData = pBt->pPage1->aData; if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ - rc = sqlite3BtreeBeginTrans(pBtree, 2, 0); + rc = sqlite3BtreeBeginTrans(pBtree, 2); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc==SQLITE_OK ){ aData[18] = (u8)iVersion; aData[19] = (u8)iVersion; @@ -82227,21 +69396,10 @@ /* ** Return the size of the header added to each page by this module. */ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } -/* -** If no transaction is active and the database is not a temp-db, clear -** the in-memory pager cache. -*/ -SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree *p){ - BtShared *pBt = p->pBt; - if( pBt->inTransaction==TRANS_NONE ){ - sqlite3PagerClearCache(pBt->pPager); - } -} - #if !defined(SQLITE_OMIT_SHARED_CACHE) /* ** Return true if the Btree passed as the only argument is sharable. */ SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){ @@ -82248,11 +69406,11 @@ return p->sharable; } /* ** Return the number of connections to the BtShared object accessed by -** the Btree handle passed as the only argument. For private caches +** the Btree handle passed as the only argument. For private caches ** this is always 1. For shared caches it may be 1 or greater. */ SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){ testcase( p->sharable ); return p->pBt->nRef; @@ -82270,11 +69428,11 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains the implementation of the sqlite3_backup_XXX() +** This file contains the implementation of the sqlite3_backup_XXX() ** API functions and the related features. */ /* #include "sqliteInt.h" */ /* #include "btreeInt.h" */ @@ -82307,19 +69465,19 @@ ** THREAD SAFETY NOTES: ** ** Once it has been created using backup_init(), a single sqlite3_backup ** structure may be accessed via two groups of thread-safe entry points: ** -** * Via the sqlite3_backup_XXX() API function backup_step() and +** * Via the sqlite3_backup_XXX() API function backup_step() and ** backup_finish(). Both these functions obtain the source database -** handle mutex and the mutex associated with the source BtShared +** handle mutex and the mutex associated with the source BtShared ** structure, in that order. ** ** * Via the BackupUpdate() and BackupRestart() functions, which are ** invoked by the pager layer to report various state changes in ** the page cache associated with the source database. The mutex -** associated with the source database BtShared structure will always +** associated with the source database BtShared structure will always ** be held when either of these functions are invoked. ** ** The other sqlite3_backup_XXX() API functions, backup_remaining() and ** backup_pagecount() are not thread-safe functions. If they are called ** while some other thread is calling backup_step() or backup_finish(), @@ -82336,27 +69494,28 @@ /* ** Return a pointer corresponding to database zDb (i.e. "main", "temp") ** in connection handle pDb. If such a database cannot be found, return ** a NULL pointer and write an error message to pErrorDb. ** -** If the "temp" database is requested, it may need to be opened by this -** function. If an error occurs while doing so, return 0 and write an +** If the "temp" database is requested, it may need to be opened by this +** function. If an error occurs while doing so, return 0 and write an ** error message to pErrorDb. */ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int i = sqlite3FindDbName(pDb, zDb); if( i==1 ){ Parse sParse; int rc = 0; - sqlite3ParseObjectInit(&sParse,pDb); + memset(&sParse, 0, sizeof(sParse)); + sParse.db = pDb; if( sqlite3OpenTempDatabase(&sParse) ){ sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); rc = SQLITE_ERROR; } sqlite3DbFree(pErrorDb, sParse.zErrMsg); - sqlite3ParseObjectReset(&sParse); + sqlite3ParserReset(&sParse); if( rc ){ return 0; } } @@ -82372,22 +69531,22 @@ ** Attempt to set the page size of the destination to match the page size ** of the source. */ static int setDestPgsz(sqlite3_backup *p){ int rc; - rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0); + rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); return rc; } /* ** Check that there is no open read-transaction on the b-tree passed as the ** second argument. If there is not, return SQLITE_OK. Otherwise, if there -** is an open read-transaction, return SQLITE_ERROR and leave an error +** is an open read-transaction, return SQLITE_ERROR and leave an error ** message in database handle db. */ static int checkReadTransaction(sqlite3 *db, Btree *p){ - if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){ + if( sqlite3BtreeIsInReadTrans(p) ){ sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); return SQLITE_ERROR; } return SQLITE_OK; } @@ -82449,17 +69608,17 @@ p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; p->isAttached = 0; - if( 0==p->pSrc || 0==p->pDest - || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK + if( 0==p->pSrc || 0==p->pDest + || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK ){ /* One (or both) of the named databases did not exist or an OOM ** error was hit. Or there is a transaction open on the destination - ** database. The error has already been written into the pDestDb - ** handle. All that is left to do here is free the sqlite3_backup + ** database. The error has already been written into the pDestDb + ** handle. All that is left to do here is free the sqlite3_backup ** structure. */ sqlite3_free(p); p = 0; } } @@ -82471,21 +69630,21 @@ sqlite3_mutex_leave(pSrcDb->mutex); return p; } /* -** Argument rc is an SQLite error code. Return true if this error is +** Argument rc is an SQLite error code. Return true if this error is ** considered fatal if encountered during a backup operation. All errors ** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. */ static int isFatalError(int rc){ return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); } /* -** Parameter zSrcData points to a buffer containing the data for -** page iSrcPg from the source database. Copy this data into the +** Parameter zSrcData points to a buffer containing the data for +** page iSrcPg from the source database. Copy this data into the ** destination database. */ static int backupOnePage( sqlite3_backup *p, /* Backup handle */ Pgno iSrcPg, /* Source database page to backup */ @@ -82495,21 +69654,54 @@ Pager * const pDestPager = sqlite3BtreePager(p->pDest); const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); const int nCopy = MIN(nSrcPgsz, nDestPgsz); const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; +#ifdef SQLITE_HAS_CODEC + /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is + ** guaranteed that the shared-mutex is held by this thread, handle + ** p->pSrc may not actually be the owner. */ + int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); + int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); +#endif int rc = SQLITE_OK; i64 iOff; assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); assert( p->bDestLocked ); assert( !isFatalError(p->rc) ); assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); assert( zSrcData ); - assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 ); - /* This loop runs once for each destination page spanned by the source + /* Catch the case where the destination is an in-memory database and the + ** page sizes of the source and destination differ. + */ + if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ + rc = SQLITE_READONLY; + } + +#ifdef SQLITE_HAS_CODEC + /* Backup is not possible if the page size of the destination is changing + ** and a codec is in use. + */ + if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ + rc = SQLITE_READONLY; + } + + /* Backup is not possible if the number of bytes of reserve space differ + ** between source and destination. If there is a difference, try to + ** fix the destination to agree with the source. If that is not possible, + ** then the backup cannot proceed. + */ + if( nSrcReserve!=nDestReserve ){ + u32 newPgsz = nSrcPgsz; + rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); + if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY; + } +#endif + + /* This loop runs once for each destination page spanned by the source ** page. For each iteration, variable iOff is set to the byte offset ** of the destination page. */ for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOffpSrc) ){ - rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); + if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ + rc = sqlite3BtreeBeginTrans(p->pSrc, 0); bCloseTrans = 1; } /* If the destination database has not yet been locked (i.e. if this ** is the first call to backup_step() for the current backup operation), @@ -82625,28 +69817,25 @@ rc = SQLITE_NOMEM; } /* Lock the destination database, if it is not locked already. */ if( SQLITE_OK==rc && p->bDestLocked==0 - && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2, - (int*)&p->iDestSchema)) + && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) ){ p->bDestLocked = 1; + sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); } /* Do not allow backup if the destination database is in WAL mode ** and the page sizes are different between source and destination */ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); pgszDest = sqlite3BtreeGetPageSize(p->pDest); destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); - if( SQLITE_OK==rc - && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager)) - && pgszSrc!=pgszDest - ){ + if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ rc = SQLITE_READONLY; } - + /* Now that there is a read-lock on the source database, query the ** source pager for the number of pages in the database. */ nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); assert( nSrcPage>=0 ); @@ -82669,11 +69858,11 @@ rc = SQLITE_DONE; }else if( !p->isAttached ){ attachBackupObject(p); } } - + /* Update the schema version field in the destination database. This ** is to make sure that the schema-version really does change in ** the case where the source and destination databases have the ** same schema version. */ @@ -82695,16 +69884,16 @@ } if( rc==SQLITE_OK ){ int nDestTruncate; /* Set nDestTruncate to the final number of pages in the destination ** database. The complication here is that the destination page - ** size may be different to the source page size. + ** size may be different to the source page size. ** - ** If the source page size is smaller than the destination page size, + ** If the source page size is smaller than the destination page size, ** round up. In this case the call to sqlite3OsTruncate() below will ** fix the size of the file. However it is important to call - ** sqlite3PagerTruncateImage() here so that any pages in the + ** sqlite3PagerTruncateImage() here so that any pages in the ** destination file that lie beyond the nDestTruncate page mark are ** journalled by PagerCommitPhaseOne() before they are destroyed ** by the file truncation. */ assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); @@ -82724,11 +69913,11 @@ /* If the source page-size is smaller than the destination page-size, ** two extra things may need to happen: ** ** * The destination may need to be truncated, and ** - ** * Data stored on the pages immediately following the + ** * Data stored on the pages immediately following the ** pending-byte page in the source database may need to be ** copied into the destination database. */ const i64 iSize = (i64)pgszSrc * (i64)nSrcPage; sqlite3_file * const pFile = sqlite3PagerFile(pDestPager); @@ -82736,21 +69925,21 @@ int nDstPage; i64 iOff; i64 iEnd; assert( pFile ); - assert( nDestTruncate==0 + assert( nDestTruncate==0 || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest )); /* This block ensures that all data required to recreate the original ** database has been stored in the journal for pDestPager and the ** journal synced to disk. So at this point we may safely modify ** the database file in any way, knowing that if a power failure - ** occurs, the original database will be reconstructed from the + ** occurs, the original database will be reconstructed from the ** journal file. */ sqlite3PagerPagecount(pDestPager, &nDstPage); for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ DbPage *pPg; @@ -82766,12 +69955,12 @@ } /* Write the extra pages and truncate the database file as required */ iEnd = MIN(PENDING_BYTE + pgszDest, iSize); for( - iOff=PENDING_BYTE+pgszSrc; - rc==SQLITE_OK && iOffpDest, 0)) ){ rc = SQLITE_DONE; } } } - + /* If bCloseTrans is true, then this function opened a read transaction ** on the source database. Close the read transaction here. There is ** no need to check the return values of the btree methods here, as ** "committing" a read-only transaction cannot fail. */ @@ -82812,11 +70001,11 @@ TESTONLY( int rc2 ); TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); assert( rc2==SQLITE_OK ); } - + if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM_BKPT; } p->rc = rc; } @@ -82849,14 +70038,12 @@ if( p->pDestDb ){ p->pSrc->nBackup--; } if( p->isAttached ){ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); - assert( pp!=0 ); while( *pp!=p ){ pp = &(*pp)->pNext; - assert( pp!=0 ); } *pp = p->pNext; } /* If a transaction is still open on the Btree, roll it back. */ @@ -82894,11 +70081,11 @@ #endif return p->nRemaining; } /* -** Return the total number of pages in the source database as of the most +** Return the total number of pages in the source database as of the most ** recent call to sqlite3_backup_step(). */ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ #ifdef SQLITE_ENABLE_API_ARMOR if( p==0 ){ @@ -82909,11 +70096,11 @@ return p->nPagecount; } /* ** This function is called after the contents of page iPage of the -** source database have been modified. If page iPage has already been +** source database have been modified. If page iPage has already been ** copied into the destination database, then the data written to the ** destination is now invalidated. The destination copy of iPage needs ** to be updated with the new data before the backup operation is ** complete. ** @@ -82952,11 +70139,11 @@ /* ** Restart the backup process. This is called when the pager layer ** detects that the database has been modified by an external database ** connection. In this case there is no way of knowing which of the -** pages that have been copied into the destination database are still +** pages that have been copied into the destination database are still ** valid and which are not, so the entire process needs to be restarted. ** ** It is assumed that the mutex associated with the BtShared object ** corresponding to the source database is held when this function is ** called. @@ -82972,22 +70159,22 @@ #ifndef SQLITE_OMIT_VACUUM /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** -** The size of file pTo may be reduced by this operation. If anything -** goes wrong, the transaction on pTo is rolled back. If successful, the +** The size of file pTo may be reduced by this operation. If anything +** goes wrong, the transaction on pTo is rolled back. If successful, the ** transaction is committed before returning. */ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ int rc; sqlite3_file *pFd; /* File descriptor for database pTo */ sqlite3_backup b; sqlite3BtreeEnter(pTo); sqlite3BtreeEnter(pFrom); - assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE ); + assert( sqlite3BtreeIsInTrans(pTo) ); pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); if( pFd->pMethods ){ i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom); rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; @@ -83002,16 +70189,20 @@ memset(&b, 0, sizeof(b)); b.pSrcDb = pFrom->db; b.pSrc = pFrom; b.pDest = pTo; b.iNext = 1; + +#ifdef SQLITE_HAS_CODEC + sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); +#endif /* 0x7FFFFFFF is the hard limit for the number of pages in a database ** file. By passing this as the number of pages to copy to - ** sqlite3_backup_step(), we can guarantee that the copy finishes + ** sqlite3_backup_step(), we can guarantee that the copy finishes ** within a single call (unless an error occurs). The assert() statement - ** checks this assumption - (p->rc) should be set to either SQLITE_DONE + ** checks this assumption - (p->rc) should be set to either SQLITE_DONE ** or an error code. */ sqlite3_backup_step(&b, 0x7FFFFFFF); assert( b.rc!=SQLITE_OK ); rc = sqlite3_backup_finish(&b); @@ -83019,11 +70210,11 @@ pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; }else{ sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); } - assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE ); + assert( sqlite3BtreeIsInTrans(pTo)==0 ); copy_finished: sqlite3BtreeLeave(pFrom); sqlite3BtreeLeave(pTo); return rc; } @@ -83049,70 +70240,39 @@ ** name sqlite_value */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ -/* True if X is a power of two. 0 is considered a power of two here. -** In other words, return true if X has at most one bit set. -*/ -#define ISPOWEROF2(X) (((X)&((X)-1))==0) - #ifdef SQLITE_DEBUG /* ** Check invariants on a Mem object. ** ** This routine is intended for use inside of assert() statements, like ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); */ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ - /* If MEM_Dyn is set then Mem.xDel!=0. - ** Mem.xDel might not be initialized if MEM_Dyn is clear. + /* If MEM_Dyn is set then Mem.xDel!=0. + ** Mem.xDel is might not be initialized if MEM_Dyn is clear. */ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we ** ensure that if Mem.szMalloc>0 then it is safe to do ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn. ** That saves a few cycles in inner loops. */ assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 ); - /* Cannot have more than one of MEM_Int, MEM_Real, or MEM_IntReal */ - assert( ISPOWEROF2(p->flags & (MEM_Int|MEM_Real|MEM_IntReal)) ); - - if( p->flags & MEM_Null ){ - /* Cannot be both MEM_Null and some other type */ - assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|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_FromBind - |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 ); - } + /* Cannot be both MEM_Int and MEM_Real at the same time */ + assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); + + /* Cannot be both MEM_Null and some other type */ + assert( (p->flags & MEM_Null)==0 || + (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob))==0 ); /* The szMalloc field holds the correct memory allocation size */ assert( p->szMalloc==0 - || (p->flags==MEM_Undefined - && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc)) - || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc)); + || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) ); /* If p holds a string or blob, the Mem.z must point to exactly ** one of the following: ** ** (1) Memory in Mem.zMalloc and managed by the Mem object @@ -83119,11 +70279,11 @@ ** (2) Memory to be freed using Mem.xDel ** (3) An ephemeral string or blob ** (4) A static string or blob */ if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){ - assert( + assert( ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 ); @@ -83130,97 +70290,10 @@ } return 1; } #endif -/* -** Render a Mem object which is one of MEM_Int, MEM_Real, or MEM_IntReal -** into a buffer. -*/ -static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ - StrAccum acc; - assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) ); - assert( sz>22 ); - if( p->flags & MEM_Int ){ -#if GCC_VERSION>=7000000 - /* Work-around for GCC bug - ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */ - i64 x; - assert( (p->flags&MEM_Int)*2==sizeof(x) ); - memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2); - p->n = sqlite3Int64ToText(x, zBuf); -#else - p->n = sqlite3Int64ToText(p->u.i, zBuf); -#endif - }else{ - sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0); - sqlite3_str_appendf(&acc, "%!.15g", - (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r); - assert( acc.zText==zBuf && acc.mxAlloc<=0 ); - zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */ - p->n = acc.nChar; - } -} - -#ifdef SQLITE_DEBUG -/* -** Validity checks on pMem. pMem holds a string. -** -** (1) Check that string value of pMem agrees with its integer or real value. -** (2) Check that the string is correctly zero terminated -** -** A single int or real value always converts to the same strings. But -** many different strings can be converted into the same int or real. -** If a table contains a numeric value and an index is based on the -** corresponding string value, then it is important that the string be -** derived from the numeric value, not the other way around, to ensure -** that the index and table are consistent. See ticket -** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for -** an example. -** -** This routine looks at pMem to verify that if it has both a numeric -** representation and a string representation then the string rep has -** been derived from the numeric and not the other way around. It returns -** true if everything is ok and false if there is a problem. -** -** This routine is for use inside of assert() statements only. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){ - Mem tmp; - char zBuf[100]; - char *z; - int i, j, incr; - if( (p->flags & MEM_Str)==0 ) return 1; - if( p->db && p->db->mallocFailed ) return 1; - if( p->flags & MEM_Term ){ - /* Insure that the string is properly zero-terminated. Pay particular - ** attention to the case where p->n is odd */ - if( p->szMalloc>0 && p->z==p->zMalloc ){ - assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 ); - assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 ); - } - assert( p->z[p->n]==0 ); - assert( p->enc==SQLITE_UTF8 || p->z[(p->n+1)&~1]==0 ); - assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 ); - } - if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1; - memcpy(&tmp, p, sizeof(tmp)); - vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp); - z = p->z; - i = j = 0; - incr = 1; - if( p->enc!=SQLITE_UTF8 ){ - incr = 2; - if( p->enc==SQLITE_UTF16BE ) z++; - } - while( zBuf[j] ){ - if( zBuf[j++]!=z[i] ) return 0; - i += incr; - } - return 1; -} -#endif /* SQLITE_DEBUG */ /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. @@ -83235,19 +70308,14 @@ */ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ #ifndef SQLITE_OMIT_UTF16 int rc; #endif - assert( pMem!=0 ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( (pMem->flags&MEM_RowSet)==0 ); assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE || desiredEnc==SQLITE_UTF16BE ); - if( !(pMem->flags&MEM_Str) ){ - pMem->enc = desiredEnc; - return SQLITE_OK; - } - if( pMem->enc==desiredEnc ){ + if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ return SQLITE_OK; } assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); #ifdef SQLITE_OMIT_UTF16 return SQLITE_ERROR; @@ -83263,39 +70331,33 @@ return rc; #endif } /* -** Make sure pMem->z points to a writable allocation of at least n bytes. +** Make sure pMem->z points to a writable allocation of at least +** min(n,32) bytes. ** ** If the bPreserve argument is true, then copy of the content of ** pMem->z into the new allocation. pMem must be either a string or ** blob if bPreserve is true. If bPreserve is false, any prior content ** in pMem->z is discarded. */ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( sqlite3VdbeCheckMemInvariants(pMem) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( (pMem->flags&MEM_RowSet)==0 ); testcase( pMem->db==0 ); /* If the bPreserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); testcase( bPreserve && pMem->z==0 ); assert( pMem->szMalloc==0 - || (pMem->flags==MEM_Undefined - && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc)) - || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc)); - if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){ - if( pMem->db ){ - pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); - }else{ - pMem->zMalloc = sqlite3Realloc(pMem->z, n); - if( pMem->zMalloc==0 ) sqlite3_free(pMem->z); - pMem->z = pMem->zMalloc; - } + || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); + if( n<32 ) n = 32; + if( bPreserve && pMem->szMalloc>0 && 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); } @@ -83306,12 +70368,11 @@ return SQLITE_NOMEM_BKPT; }else{ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); } - if( bPreserve && pMem->z ){ - assert( pMem->z!=pMem->zMalloc ); + if( bPreserve && pMem->z && ALWAYS(pMem->z!=pMem->zMalloc) ){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } if( (pMem->flags&MEM_Dyn)!=0 ){ assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC ); pMem->xDel((void *)(pMem->z)); @@ -83327,79 +70388,25 @@ ** If pMem->zMalloc already meets or exceeds the requested size, this ** routine is a no-op. ** ** Any prior string or blob content in the pMem object may be discarded. ** The pMem->xDel destructor is called, if it exists. Though MEM_Str -** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, MEM_IntReal, -** and MEM_Null values are preserved. +** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null +** values are preserved. ** ** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM) ** if unable to complete the resizing. */ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ - assert( CORRUPT_DB || szNew>0 ); + assert( szNew>0 ); assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 ); if( pMem->szMallocflags & MEM_Dyn)==0 ); pMem->z = pMem->zMalloc; - pMem->flags &= (MEM_Null|MEM_Int|MEM_Real|MEM_IntReal); - return SQLITE_OK; -} - -/* -** If pMem is already a string, detect if it is a zero-terminated -** string, or make it into one if possible, and mark it as such. -** -** This is an optimization. Correct operation continues even if -** this routine is a no-op. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ - if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ - /* pMem must be a string, and it cannot be an ephemeral or static string */ - return; - } - if( pMem->enc!=SQLITE_UTF8 ) return; - if( NEVER(pMem->z==0) ) return; - if( pMem->flags & MEM_Dyn ){ - if( pMem->xDel==sqlite3_free - && sqlite3_msize(pMem->z) >= (u64)(pMem->n+1) - ){ - pMem->z[pMem->n] = 0; - pMem->flags |= MEM_Term; - return; - } - if( pMem->xDel==sqlite3RCStrUnref ){ - /* Blindly assume that all RCStr objects are zero-terminated */ - pMem->flags |= MEM_Term; - return; - } - }else if( pMem->szMalloc >= pMem->n+1 ){ - pMem->z[pMem->n] = 0; - pMem->flags |= MEM_Term; - return; - } -} - -/* -** It is already known that pMem contains an unterminated string. -** Add the zero terminator. -** -** Three bytes of zero are added. In this way, there is guaranteed -** to be a double-zero byte at an even byte boundary in order to -** terminate a UTF16 string, even if the initial size of the buffer -** is an odd number of bytes. -*/ -static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ - if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){ - return SQLITE_NOMEM_BKPT; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->z[pMem->n+2] = 0; - pMem->flags |= MEM_Term; + pMem->flags &= (MEM_Null|MEM_Int|MEM_Real); return SQLITE_OK; } /* ** Change pMem so that its MEM_Str or MEM_Blob value is stored in @@ -83406,18 +70413,21 @@ ** MEM.zMalloc, where it can be safely written. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( (pMem->flags&MEM_RowSet)==0 ); if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ if( ExpandBlob(pMem) ) return SQLITE_NOMEM; if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ - int rc = vdbeMemAddTerminator(pMem); - if( rc ) return rc; + 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; } } pMem->flags &= ~MEM_Ephem; #ifdef SQLITE_DEBUG pMem->pScopyFrom = 0; @@ -83431,41 +70441,49 @@ ** blob stored in dynamically allocated space. */ #ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ int nByte; - assert( pMem!=0 ); assert( pMem->flags & MEM_Zero ); - assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) ); - testcase( sqlite3_value_nochange(pMem) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( pMem->flags&MEM_Blob ); + assert( (pMem->flags&MEM_RowSet)==0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); /* Set nByte to the number of bytes required to store the expanded blob. */ nByte = pMem->n + pMem->u.nZero; if( nByte<=0 ){ - if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK; nByte = 1; } if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ return SQLITE_NOMEM_BKPT; } - assert( pMem->z!=0 ); - assert( sqlite3DbMallocSize(pMem->db,pMem->z) >= nByte ); memset(&pMem->z[pMem->n], 0, pMem->u.nZero); pMem->n += pMem->u.nZero; pMem->flags &= ~(MEM_Zero|MEM_Term); return SQLITE_OK; } #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. */ SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) ); testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 ); if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){ return SQLITE_OK; /* Nothing to do */ @@ -83473,46 +70491,56 @@ return vdbeMemAddTerminator(pMem); } } /* -** Add MEM_Str to the set of representations for the given Mem. This -** routine is only called if pMem is a number of some kind, not a NULL -** or a BLOB. +** Add MEM_Str to the set of representations for the given Mem. Numbers +** are converted using sqlite3_snprintf(). Converting a BLOB to a string +** is a no-op. ** -** Existing representations MEM_Int, MEM_Real, or MEM_IntReal are invalidated -** if bForce is true but are retained if bForce is false. +** Existing representations MEM_Int and MEM_Real are invalidated if +** bForce is true but are retained if bForce is false. ** ** A MEM_Null value will never be passed to this function. This function is ** used for converting values to text for returning to the user (i.e. via ** sqlite3_value_text()), or for ensuring that values to be used as btree ** keys are strings. In the former case a NULL pointer is returned the ** user and the latter is an internal programming error. */ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ + int fg = pMem->flags; const int nByte = 32; - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !(pMem->flags&MEM_Zero) ); - assert( !(pMem->flags&(MEM_Str|MEM_Blob)) ); - assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( !(fg&MEM_Zero) ); + assert( !(fg&(MEM_Str|MEM_Blob)) ); + assert( fg&(MEM_Int|MEM_Real) ); + assert( (pMem->flags&MEM_RowSet)==0 ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ pMem->enc = 0; return SQLITE_NOMEM_BKPT; } - vdbeMemRenderNum(nByte, pMem->z, pMem); - assert( pMem->z!=0 ); - assert( pMem->n==(int)sqlite3Strlen30NN(pMem->z) ); + /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 + ** string representation of the value. Then, if the required encoding + ** is UTF-16le or UTF-16be do a translation. + ** + ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. + */ + if( fg & MEM_Int ){ + sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); + }else{ + assert( fg & MEM_Real ); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); + } + pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; - if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); sqlite3VdbeChangeEncoding(pMem, enc); return SQLITE_OK; } /* @@ -83522,59 +70550,31 @@ ** ** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK ** otherwise. */ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ - sqlite3_context ctx; - Mem t; - assert( pFunc!=0 ); - assert( pMem!=0 ); - assert( pMem->db!=0 ); - assert( pFunc->xFinalize!=0 ); - assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); - assert( 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; - ctx.enc = ENC(t.db); - 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; -} - -/* -** Memory cell pAccum contains the context of an aggregate function. -** This routine calls the xValue method for that function and stores -** the results in memory cell pMem. -** -** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK -** otherwise. -*/ -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ - sqlite3_context ctx; - assert( pFunc!=0 ); - assert( pFunc->xValue!=0 ); - assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef ); - assert( pAccum->db!=0 ); - assert( sqlite3_mutex_held(pAccum->db->mutex) ); - memset(&ctx, 0, sizeof(ctx)); - sqlite3VdbeMemSetNull(pOut); - ctx.pOut = pOut; - ctx.pMem = pAccum; - ctx.pFunc = pFunc; - ctx.enc = ENC(pAccum->db); - pFunc->xValue(&ctx); - return ctx.isError; -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ + 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 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); + memcpy(pMem, &t, sizeof(t)); + rc = ctx.isError; + } + return rc; +} /* ** If the memory cell contains a value that must be freed by ** invoking the external callback in Mem.xDel, then this routine ** will free that value. It also sets Mem.flags to MEM_Null. @@ -83590,12 +70590,19 @@ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); testcase( p->flags & MEM_Dyn ); } if( p->flags&MEM_Dyn ){ + assert( (p->flags&MEM_RowSet)==0 ); assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); p->xDel((void *)p->z); + }else if( p->flags&MEM_RowSet ){ + sqlite3RowSetClear(p->u.pRowSet); + }else if( p->flags&MEM_Frame ){ + VdbeFrame *pFrame = p->u.pFrame; + pFrame->pParent = pFrame->v->pDelFrame; + pFrame->v->pDelFrame = pFrame; } p->flags = MEM_Null; } /* @@ -83632,16 +70639,38 @@ if( VdbeMemDynamic(p) || p->szMalloc ){ vdbeMemClear(p); } } -/* Like sqlite3VdbeMemRelease() but faster for cases where we -** know in advance that the Mem is not MEM_Dyn or MEM_Agg. +/* +** Convert a 64-bit IEEE double into a 64-bit signed integer. +** If the double is out of range of a 64-bit signed integer then +** return the closest available 64-bit signed integer. */ -SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){ - assert( !VdbeMemDynamic(p) ); - if( p->szMalloc ) vdbeMemClear(p); +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; +#else + /* + ** Many compilers we encounter do not define constants for the + ** minimum and maximum 64-bit integers, or they define them + ** inconsistently. And many do not understand the "LL" notation. + ** So we define our own static constants here using nothing + ** larger than a 32-bit integer constant. + */ + static const i64 maxInt = LARGEST_INT64; + static const i64 minInt = SMALLEST_INT64; + + if( r<=(double)minInt ){ + return minInt; + }else if( r>=(double)maxInt ){ + return maxInt; + }else{ + return (i64)r; + } +#endif } /* ** Return some kind of integer value which is the best we can do ** at representing the value that *pMem describes as an integer. @@ -83651,27 +70680,26 @@ ** it into an integer and return that. If pMem represents an ** an SQL-NULL value, return 0. ** ** If pMem represents a string value, its encoding might be changed. */ -static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){ +static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){ i64 value = 0; sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); return value; } -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){ int flags; - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); flags = pMem->flags; - if( flags & (MEM_Int|MEM_IntReal) ){ - testcase( flags & MEM_IntReal ); + if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ - return sqlite3RealToI64(pMem->u.r); - }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){ + return doubleToInt64(pMem->u.r); + }else if( flags & (MEM_Str|MEM_Blob) ){ + assert( pMem->z || pMem->n==0 ); return memIntValue(pMem); }else{ return 0; } } @@ -83687,17 +70715,15 @@ double val = (double)0; sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); return val; } SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( pMem->flags & MEM_Real ){ return pMem->u.r; - }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pMem->flags & MEM_IntReal ); + }else if( pMem->flags & MEM_Int ){ return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ return memRealValue(pMem); }else{ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ @@ -83704,60 +70730,44 @@ return (double)0; } } /* -** Return 1 if pMem represents true, and return 0 if pMem represents false. -** Return the value ifNull if pMem is NULL. -*/ -SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ - testcase( pMem->flags & MEM_IntReal ); - if( pMem->flags & (MEM_Int|MEM_IntReal) ) return pMem->u.i!=0; - if( pMem->flags & MEM_Null ) return ifNull; - return sqlite3VdbeRealValue(pMem)!=0.0; -} - -/* -** The MEM structure is already a MEM_Real or MEM_IntReal. Try to -** make it a MEM_Int if we can. +** The MEM structure is already a MEM_Real. Try to also make it a +** MEM_Int if we can. */ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ - assert( pMem!=0 ); - assert( pMem->flags & (MEM_Real|MEM_IntReal) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + i64 ix; + assert( pMem->flags & MEM_Real ); + assert( (pMem->flags & MEM_RowSet)==0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - if( pMem->flags & MEM_IntReal ){ - MemSetTypeFlag(pMem, MEM_Int); - }else{ - i64 ix = sqlite3RealToI64(pMem->u.r); - - /* Only mark the value as an integer if - ** - ** (1) the round-trip conversion real->int->real is a no-op, and - ** (2) The integer is neither the largest nor the smallest - ** possible integer (ticket #3922) - ** - ** The second and third terms in the following conditional enforces - ** the second condition under the assumption that addition overflow causes - ** values to wrap around. - */ - if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.i = ix; - MemSetTypeFlag(pMem, MEM_Int); - } + ix = doubleToInt64(pMem->u.r); + + /* Only mark the value as an integer if + ** + ** (1) the round-trip conversion real->int->real is a no-op, and + ** (2) The integer is neither the largest nor the smallest + ** possible integer (ticket #3922) + ** + ** The second and third terms in the following conditional enforces + ** the second condition under the assumption that addition overflow causes + ** values to wrap around. + */ + if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.i = ix; + MemSetTypeFlag(pMem, MEM_Int); } } /* ** Convert pMem to type integer. Invalidate any prior representations. */ SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){ - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( (pMem->flags & MEM_RowSet)==0 ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); pMem->u.i = sqlite3VdbeIntValue(pMem); MemSetTypeFlag(pMem, MEM_Int); return SQLITE_OK; @@ -83766,75 +70776,39 @@ /* ** Convert pMem so that it is of type MEM_Real. ** Invalidate any prior representations. */ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); pMem->u.r = sqlite3VdbeRealValue(pMem); MemSetTypeFlag(pMem, MEM_Real); return SQLITE_OK; } -/* Compare a floating point value to an integer. Return true if the two -** values are the same within the precision of the floating point value. -** -** This function assumes that i was obtained by assignment from r1. -** -** For some versions of GCC on 32-bit machines, if you do the more obvious -** comparison of "r1==(double)i" you sometimes get an answer of false even -** though the r1 and (double)i values are bit-for-bit the same. -*/ -SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ - double r2 = (double)i; - return r1==0.0 - || (memcmp(&r1, &r2, sizeof(r1))==0 - && i >= -2251799813685248LL && i < 2251799813685248LL); -} - -/* Convert a floating point value to its closest integer. Do so in -** a way that avoids 'outside the range of representable values' warnings -** from UBSAN. -*/ -SQLITE_PRIVATE i64 sqlite3RealToI64(double r){ - if( r<-9223372036854774784.0 ) return SMALLEST_INT64; - if( r>+9223372036854774784.0 ) return LARGEST_INT64; - return (i64)r; -} - /* -** Convert pMem so that it has type MEM_Real or MEM_Int. +** Convert pMem so that it has types MEM_Real or MEM_Int or both. ** Invalidate any prior representations. ** ** Every effort is made to force the conversion, even if the input ** is a string that does not look completely like a number. Convert ** as much of the string as we can and ignore the rest. */ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ - assert( pMem!=0 ); - testcase( pMem->flags & MEM_Int ); - testcase( pMem->flags & MEM_Real ); - testcase( pMem->flags & MEM_IntReal ); - testcase( pMem->flags & MEM_Null ); - if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){ - int rc; - sqlite3_int64 ix; + if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1) - || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r))) - ){ - pMem->u.i = ix; + if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ MemSetTypeFlag(pMem, MEM_Int); }else{ + pMem->u.r = sqlite3VdbeRealValue(pMem); MemSetTypeFlag(pMem, MEM_Real); + sqlite3VdbeIntegerAffinity(pMem); } } - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))!=0 ); + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero); return SQLITE_OK; } /* @@ -83842,12 +70816,12 @@ ** "aff". Casting is different from applying affinity in that a cast ** is forced. In other words, the value is converted into the desired ** affinity even if that results in loss of data. This routine is ** used (for example) to implement the SQL "cast()" operator. */ -SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ - if( pMem->flags & MEM_Null ) return SQLITE_OK; +SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ + if( pMem->flags & MEM_Null ) return; switch( aff ){ case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ if( (pMem->flags & MEM_Blob)==0 ){ sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); @@ -83868,24 +70842,19 @@ case SQLITE_AFF_REAL: { sqlite3VdbeMemRealify(pMem); break; } default: { - int rc; assert( aff==SQLITE_AFF_TEXT ); assert( MEM_Str==(MEM_Blob>>3) ); pMem->flags |= (pMem->flags&MEM_Blob)>>3; sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero); - if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1; - rc = sqlite3VdbeChangeEncoding(pMem, encoding); - if( rc ) return rc; - sqlite3VdbeMemZeroTerminateIfAble(pMem); + pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); + break; } } - return SQLITE_OK; } /* ** Initialize bulk memory to be a consistent Mem object. ** @@ -83917,42 +70886,26 @@ }else{ pMem->flags = MEM_Null; } } SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){ - sqlite3VdbeMemSetNull((Mem*)p); + sqlite3VdbeMemSetNull((Mem*)p); } /* ** Delete any previous value and set the value to be a BLOB of length ** n containing all zeros. */ -#ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Blob|MEM_Zero; pMem->n = 0; if( n<0 ) n = 0; pMem->u.nZero = n; pMem->enc = SQLITE_UTF8; pMem->z = 0; } -#else -SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ - int nByte = n>0?n:1; - if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){ - return SQLITE_NOMEM_BKPT; - } - assert( pMem->z!=0 ); - assert( sqlite3DbMallocSize(pMem->db, pMem->z)>=nByte ); - memset(pMem->z, 0, nByte); - pMem->n = n>0?n:0; - pMem->flags = MEM_Blob; - pMem->enc = SQLITE_UTF8; - return SQLITE_OK; -} -#endif /* ** The pMem is known to contain content that needs to be destroyed prior ** to a value change. So invoke the destructor, then set the value to ** a 64-bit integer. @@ -83974,37 +70927,19 @@ pMem->u.i = val; pMem->flags = MEM_Int; } } -/* -** Set the iIdx'th entry of array aMem[] to contain integer value val. -*/ -SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val){ - sqlite3VdbeMemSetInt64(&aMem[iIdx], val); -} - -/* A no-op destructor */ -SQLITE_PRIVATE 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*) -){ +SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem *pMem, void *pPtr){ assert( pMem->flags==MEM_Null ); - vdbeMemClear(pMem); - pMem->u.zPType = zPType ? zPType : ""; - pMem->z = pPtr; - pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term; + pMem->flags = MEM_Null|MEM_Subtype; + pMem->u.pPtr = pPtr; 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, @@ -84017,40 +70952,30 @@ pMem->flags = MEM_Real; } } #endif -#ifdef SQLITE_DEBUG -/* -** Return true if the Mem holds a RowSet object. This routine is intended -** for use inside of assert() statements. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem *pMem){ - return (pMem->flags&(MEM_Blob|MEM_Dyn))==(MEM_Blob|MEM_Dyn) - && pMem->xDel==sqlite3RowSetDelete; -} -#endif - /* ** Delete any previous value and set the value of pMem to be an ** empty boolean index. -** -** Return SQLITE_OK on success and SQLITE_NOMEM if a memory allocation -** error occurs. */ -SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem *pMem){ +SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ sqlite3 *db = pMem->db; - RowSet *p; assert( db!=0 ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( (pMem->flags & MEM_RowSet)==0 ); sqlite3VdbeMemRelease(pMem); - p = sqlite3RowSetInit(db); - if( p==0 ) return SQLITE_NOMEM; - pMem->z = (char*)p; - pMem->flags = MEM_Blob|MEM_Dyn; - pMem->xDel = sqlite3RowSetDelete; - return SQLITE_OK; + pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); + if( db->mallocFailed ){ + pMem->flags = MEM_Null; + pMem->szMalloc = 0; + }else{ + assert( pMem->zMalloc ); + pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); + pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); + assert( pMem->u.pRowSet!=0 ); + pMem->flags = MEM_RowSet; + } } /* ** Return true if the Mem object contains a TEXT or BLOB that is ** too large - whose size exceeds SQLITE_MAX_LENGTH. @@ -84062,53 +70987,35 @@ if( p->flags & MEM_Zero ){ n += p->u.nZero; } return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; } - return 0; + return 0; } #ifdef SQLITE_DEBUG /* ** This routine prepares a memory cell for modification by breaking ** its link to a shallow copy and by marking any current shallow ** copies of this cell as invalid. ** -** This is used for testing and debugging only - to help ensure that shallow -** copies (created by OP_SCopy) are not misused. +** This is used for testing and debugging only - to make sure shallow +** copies are not misused. */ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ int i; Mem *pX; - if( pMem->bScopy ){ - for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){ - if( pX->pScopyFrom==pMem ){ - u16 mFlags; - if( pVdbe->db->flags & SQLITE_VdbeTrace ){ - sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n", - (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem)); - } - /* If pX is marked as a shallow copy of pMem, then try to verify that - ** no significant changes have been made to pX since the OP_SCopy. - ** A significant change would indicated a missed call to this - ** function for pX. Minor changes, such as adding or removing a - ** dual type, are allowed, as long as the underlying value is the - ** same. */ - mFlags = pMem->flags & pX->flags & pX->mScopyFlags; - assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i ); - - /* pMem is the register that is changing. But also mark pX as - ** undefined so that we can quickly detect the shallow-copy error */ - pX->flags = MEM_Undefined; - pX->pScopyFrom = 0; - } - } - pMem->bScopy = 0; + for(i=0, pX=pVdbe->aMem; inMem; i++, pX++){ + if( pX->pScopyFrom==pMem ){ + pX->flags |= MEM_Undefined; + pX->pScopyFrom = 0; + } } pMem->pScopyFrom = 0; } #endif /* SQLITE_DEBUG */ + /* ** Make an shallow copy of pFrom into pTo. Prior contents of ** pTo are freed. The pFrom->z field is not duplicated. If ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z @@ -84118,11 +71025,11 @@ vdbeMemClearExternAndSetNull(pTo); assert( !VdbeMemDynamic(pTo) ); sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); } SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ - assert( !sqlite3VdbeMemIsRowSet(pFrom) ); + assert( (pFrom->flags & MEM_RowSet)==0 ); assert( pTo->db==pFrom->db ); if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } memcpy(pTo, pFrom, MEMCELLSIZE); if( (pFrom->flags&MEM_Static)==0 ){ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); @@ -84136,11 +71043,11 @@ ** freed before the copy is made. */ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; - assert( !sqlite3VdbeMemIsRowSet(pFrom) ); + assert( (pFrom->flags & MEM_RowSet)==0 ); if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ @@ -84171,43 +71078,34 @@ /* ** Change the value of a Mem to be a string or a BLOB. ** ** The memory management strategy depends on the value of the xDel -** parameter. If the value passed is SQLITE_TRANSIENT, then the -** string is copied into a (possibly existing) buffer managed by the +** parameter. If the value passed is SQLITE_TRANSIENT, then the +** string is copied into a (possibly existing) buffer managed by the ** Mem structure. Otherwise, any existing buffer is freed and the ** pointer copied. ** ** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH ** size limit) then no memory allocation occurs. If the string can be ** stored without allocating memory, then it is. If a memory allocation ** is required to store the string, then value of pMem is unchanged. In ** either case, SQLITE_TOOBIG is returned. -** -** The "enc" parameter is the text encoding for the string, or zero -** to store a blob. -** -** If n is negative, then the string consists of all bytes up to but -** excluding the first zero character. The n parameter must be -** non-negative for blobs. */ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( Mem *pMem, /* Memory cell to set to string value */ const char *z, /* String pointer */ - i64 n, /* Bytes in string, or negative */ + int n, /* Bytes in string, or negative */ u8 enc, /* Encoding of z. 0 for BLOBs */ void (*xDel)(void*) /* Destructor function */ ){ - i64 nByte = n; /* New value for pMem->n */ + int nByte = n; /* New value for pMem->n */ int iLimit; /* Maximum allowed string or blob size */ - u16 flags; /* New value for pMem->flags */ + u16 flags = 0; /* New value for pMem->flags */ - assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - assert( enc!=0 || n>=0 ); + assert( (pMem->flags & MEM_RowSet)==0 ); /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ if( !z ){ sqlite3VdbeMemSetNull(pMem); return SQLITE_OK; @@ -84216,74 +71114,65 @@ if( pMem->db ){ iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH]; }else{ iLimit = SQLITE_MAX_LENGTH; } + flags = (enc==0?MEM_Blob:MEM_Str); if( nByte<0 ){ assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ - nByte = strlen(z); + nByte = sqlite3Strlen30(z); + if( nByte>iLimit ) nByte = iLimit+1; }else{ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} } - flags= MEM_Str|MEM_Term; - }else if( enc==0 ){ - flags = MEM_Blob; - enc = SQLITE_UTF8; - }else{ - flags = MEM_Str; - } - if( nByte>iLimit ){ - if( xDel && xDel!=SQLITE_TRANSIENT ){ - if( xDel==SQLITE_DYNAMIC ){ - sqlite3DbFree(pMem->db, (void*)z); - }else{ - xDel((void*)z); - } - } - sqlite3VdbeMemSetNull(pMem); - return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); + flags |= MEM_Term; } /* The following block sets the new values of Mem.z and Mem.xDel. It ** also sets a flag in local variable "flags" to indicate the memory ** management (one of MEM_Dyn or MEM_Static). */ if( xDel==SQLITE_TRANSIENT ){ - i64 nAlloc = nByte; + int nAlloc = nByte; if( flags&MEM_Term ){ nAlloc += (enc==SQLITE_UTF8?1:2); } + if( nByte>iLimit ){ + return SQLITE_TOOBIG; + } testcase( nAlloc==0 ); testcase( nAlloc==31 ); testcase( nAlloc==32 ); - if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ + if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){ return SQLITE_NOMEM_BKPT; } memcpy(pMem->z, z, nAlloc); + }else if( xDel==SQLITE_DYNAMIC ){ + sqlite3VdbeMemRelease(pMem); + pMem->zMalloc = pMem->z = (char *)z; + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); }else{ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; - if( xDel==SQLITE_DYNAMIC ){ - pMem->zMalloc = pMem->z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); - }else{ - pMem->xDel = xDel; - flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); - } + pMem->xDel = xDel; + flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); } - pMem->n = (int)(nByte & 0x7fffffff); + pMem->n = nByte; pMem->flags = flags; - pMem->enc = enc; + pMem->enc = (enc==0 ? SQLITE_UTF8 : enc); #ifndef SQLITE_OMIT_UTF16 - if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ + if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ return SQLITE_NOMEM_BKPT; } #endif + if( nByte>iLimit ){ + return SQLITE_TOOBIG; + } return SQLITE_OK; } /* @@ -84299,55 +71188,56 @@ ** destroyed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( +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. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ int rc; pMem->flags = MEM_Null; - if( sqlite3BtreeMaxRecordSize(pCur)z); if( rc==SQLITE_OK ){ - pMem->z[amt] = 0; /* Overrun area used when reading malformed records */ - pMem->flags = MEM_Blob; + pMem->z[amt] = 0; + pMem->z[amt+1] = 0; + pMem->flags = MEM_Blob|MEM_Term; pMem->n = (int)amt; }else{ sqlite3VdbeMemRelease(pMem); } } return rc; } -SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset( +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. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ + char *zData; /* Data from the btree layer */ u32 available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ assert( sqlite3BtreeCursorIsValid(pCur) ); assert( !VdbeMemDynamic(pMem) ); - /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - pMem->z = (char *)sqlite3BtreePayloadFetch(pCur, &available); - assert( pMem->z!=0 ); + assert( (pMem->flags & MEM_RowSet)==0 ); + zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); + assert( zData!=0 ); - if( amt<=available ){ + if( offset+amt<=available ){ + pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; }else{ - rc = sqlite3VdbeMemFromBtree(pCur, 0, amt, pMem); + rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem); } return rc; } @@ -84358,11 +71248,11 @@ */ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert( pVal!=0 ); assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); - assert( !sqlite3VdbeMemIsRowSet(pVal) ); + 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) ){ @@ -84380,11 +71270,10 @@ assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); } assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 || pVal->db->mallocFailed ); if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ - assert( sqlite3VdbeMemValidStrRep(pVal) ); return pVal->z; }else{ return 0; } } @@ -84401,39 +71290,20 @@ */ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ if( !pVal ) return 0; assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); - assert( !sqlite3VdbeMemIsRowSet(pVal) ); + assert( (pVal->flags & MEM_RowSet)==0 ); if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ - assert( sqlite3VdbeMemValidStrRep(pVal) ); return pVal->z; } if( pVal->flags&MEM_Null ){ return 0; } return valueToText(pVal, enc); } -/* Return true if sqlit3_value object pVal is a string or blob value -** that uses the destructor specified in the second argument. -** -** TODO: Maybe someday promote this interface into a published API so -** that third-party extensions can get access to it? -*/ -SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value *pVal, void(*xFree)(void*)){ - if( ALWAYS(pVal!=0) - && ALWAYS((pVal->flags & (MEM_Str|MEM_Blob))!=0) - && (pVal->flags & MEM_Dyn)!=0 - && pVal->xDel==xFree - ){ - return 1; - }else{ - return 0; - } -} - /* ** Create a new sqlite3_value object. */ SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){ Mem *p = sqlite3DbMallocZero(db, sizeof(*p)); @@ -84443,11 +71313,11 @@ } return p; } /* -** Context object passed by sqlite3Stat4ProbeSetValue() through to +** Context object passed by sqlite3Stat4ProbeSetValue() through to ** valueNew(). See comments above valueNew() for details. */ struct ValueNewStat4Ctx { Parse *pParse; Index *pIdx; @@ -84458,33 +71328,33 @@ /* ** Allocate and return a pointer to a new sqlite3_value object. If ** the second argument to this function is NULL, the object is allocated ** by calling sqlite3ValueNew(). ** -** Otherwise, if the second argument is non-zero, then this function is +** Otherwise, if the second argument is non-zero, then this function is ** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not -** already been allocated, allocate the UnpackedRecord structure that +** already been allocated, allocate the UnpackedRecord structure that ** that function will return to its caller here. Then return a pointer to ** an sqlite3_value within the UnpackedRecord.a[] array. */ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( p ){ UnpackedRecord *pRec = p->ppRec[0]; if( pRec==0 ){ Index *pIdx = p->pIdx; /* Index being probed */ int nByte; /* Bytes of space to allocate */ int i; /* Counter variable */ int nCol = pIdx->nColumn; /* Number of index columns including rowid */ - + nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord)); pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte); if( pRec ){ pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx); if( pRec->pKeyInfo ){ - assert( pRec->pKeyInfo->nAllField==nCol ); + assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol ); assert( pRec->pKeyInfo->enc==ENC(db) ); pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); for(i=0; iaMem[i].flags = MEM_Null; pRec->aMem[i].db = db; @@ -84495,18 +71365,17 @@ } } if( pRec==0 ) return 0; p->ppRec[0] = pRec; } - + pRec->nField = p->iVal+1; - sqlite3VdbeMemSetNull(&pRec->aMem[p->iVal]); return &pRec->aMem[p->iVal]; } #else UNUSED_PARAMETER(p); -#endif /* defined(SQLITE_ENABLE_STAT4) */ +#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */ return sqlite3ValueNew(db); } /* ** The expression object indicated by the second argument is guaranteed @@ -84515,25 +71384,25 @@ ** * all function arguments are SQL literals, ** * one of the SQLITE_FUNC_CONSTANT or _SLOCHNG function flags is set, and ** * the SQLITE_FUNC_NEEDCOLL function flag is not set, ** ** then this routine attempts to invoke the SQL function. Assuming no -** error occurs, output parameter (*ppVal) is set to point to a value +** error occurs, output parameter (*ppVal) is set to point to a value ** object containing the result before returning SQLITE_OK. ** ** Affinity aff is applied to the result of the function before returning. -** If the result is a text value, the sqlite3_value object uses encoding +** If the result is a text value, the sqlite3_value object uses encoding ** enc. ** ** If the conditions above are not met, this function returns SQLITE_OK ** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to ** NULL and an SQLite error code returned. */ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 static int valueFromFunction( sqlite3 *db, /* The database connection */ - const Expr *p, /* The expression to evaluate */ + Expr *p, /* The expression to evaluate */ u8 enc, /* Encoding to use */ u8 aff, /* Affinity to use */ sqlite3_value **ppVal, /* Write the new value here */ struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ ){ @@ -84546,21 +71415,16 @@ ExprList *pList = 0; /* Function arguments */ int i; /* Iterator variable */ assert( pCtx!=0 ); assert( (p->flags & EP_TokenOnly)==0 ); - assert( ExprUseXList(p) ); pList = p->x.pList; if( pList ) nVal = pList->nExpr; - assert( !ExprHasProperty(p, EP_IntValue) ); pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pFunc==0 ) return SQLITE_OK; -#endif assert( pFunc ); - if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0 + if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 + || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) ){ return SQLITE_OK; } if( pList ){ @@ -84568,12 +71432,11 @@ if( apVal==0 ){ rc = SQLITE_NOMEM_BKPT; goto value_from_function_out; } for(i=0; ipParse, pList->a[i].pExpr, aff, - &apVal[i]); + rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]); if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out; } } pVal = valueNew(db, pCtx); @@ -84580,32 +71443,32 @@ if( pVal==0 ){ rc = SQLITE_NOMEM_BKPT; goto value_from_function_out; } + assert( pCtx->pParse->rc==SQLITE_OK ); memset(&ctx, 0, sizeof(ctx)); ctx.pOut = pVal; ctx.pFunc = pFunc; - ctx.enc = ENC(db); pFunc->xSFunc(&ctx, nVal, apVal); if( ctx.isError ){ rc = ctx.isError; sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); }else{ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); assert( rc==SQLITE_OK ); rc = sqlite3VdbeChangeEncoding(pVal, enc); - if( NEVER(rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal)) ){ + if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ rc = SQLITE_TOOBIG; pCtx->pParse->nErr++; } } + pCtx->pParse->rc = rc; value_from_function_out: if( rc!=SQLITE_OK ){ pVal = 0; - pCtx->pParse->rc = rc; } if( apVal ){ for(i=0; iop)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; - if( op==TK_REGISTER ) op = pExpr->op2; + if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; /* Compressed expressions only appear when parsing the DEFAULT clause ** on a table column definition, and hence only when pCtx==0. This ** check ensures that an EP_TokenOnly expression is never passed down ** into valueFromFunction(). */ assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); if( op==TK_CAST ){ - u8 aff; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - aff = sqlite3AffinityType(pExpr->u.zToken,0); + u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); testcase( rc!=SQLITE_OK ); if( *ppVal ){ -#ifdef SQLITE_ENABLE_STAT4 - rc = ExpandBlob(*ppVal); -#else - /* zero-blobs only come from functions, not literal values. And - ** functions are only processed under STAT4 */ - assert( (ppVal[0][0].flags & MEM_Zero)==0 ); -#endif - sqlite3VdbeMemCast(*ppVal, aff, enc); - sqlite3ValueApplyAffinity(*ppVal, affinity, enc); + sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8); + sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8); } return rc; } /* Handle negative integers in a single step. This is needed in the - ** case when the value is -9223372036854775808. Except - do not do this - ** for hexadecimal literals. */ - if( op==TK_UMINUS ){ - Expr *pLeft = pExpr->pLeft; - if( (pLeft->op==TK_INTEGER || pLeft->op==TK_FLOAT) ){ - if( ExprHasProperty(pLeft, EP_IntValue) - || pLeft->u.zToken[0]!='0' || (pLeft->u.zToken[1] & ~0x20)!='X' - ){ - pExpr = pLeft; - op = pExpr->op; - negInt = -1; - zNeg = "-"; - } - } + ** case when the value is -9223372036854775808. + */ + if( op==TK_UMINUS + && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){ + pExpr = pExpr->pLeft; + op = pExpr->op; + negInt = -1; + zNeg = "-"; } if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ pVal = valueNew(db, pCtx); if( pVal==0 ) goto no_mem; if( ExprHasProperty(pExpr, EP_IntValue) ){ sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt); }else{ - i64 iVal; - if( op==TK_INTEGER && 0==sqlite3DecOrHexToI64(pExpr->u.zToken, &iVal) ){ - sqlite3VdbeMemSetInt64(pVal, iVal*negInt); - }else{ - zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); - if( zVal==0 ) goto no_mem; - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); - } - } - if( affinity==SQLITE_AFF_BLOB ){ - if( op==TK_FLOAT ){ - assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) ); - sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8); - pVal->flags = MEM_Real; - }else if( op==TK_INTEGER ){ - /* This case is required by -9223372036854775808 and other strings - ** that look like integers but cannot be handled by the - ** sqlite3DecOrHexToI64() call above. */ - sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); - } + zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); + if( zVal==0 ) goto no_mem; + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + } + if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){ + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); }else{ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); } - assert( (pVal->flags & MEM_IntReal)==0 ); - if( pVal->flags & (MEM_Int|MEM_IntReal|MEM_Real) ){ - testcase( pVal->flags & MEM_Int ); - testcase( pVal->flags & MEM_Real ); - pVal->flags &= ~MEM_Str; - } + if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str; if( enc!=SQLITE_UTF8 ){ rc = sqlite3VdbeChangeEncoding(pVal, enc); } }else if( op==TK_UMINUS ) { /* This branch happens for multiple negative signs. Ex: -(-5) */ - if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx) + if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx) && pVal!=0 ){ sqlite3VdbeMemNumerify(pVal); if( pVal->flags & MEM_Real ){ pVal->u.r = -pVal->u.r; }else if( pVal->u.i==SMALLEST_INT64 ){ -#ifndef SQLITE_OMIT_FLOATING_POINT pVal->u.r = -(double)SMALLEST_INT64; -#else - pVal->u.r = LARGEST_INT64; -#endif MemSetTypeFlag(pVal, MEM_Real); }else{ pVal->u.i = -pVal->u.i; } sqlite3ValueApplyAffinity(pVal, affinity, enc); } }else if( op==TK_NULL ){ pVal = valueNew(db, pCtx); if( pVal==0 ) goto no_mem; - sqlite3VdbeMemSetNull(pVal); + sqlite3VdbeMemNumerify(pVal); } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); assert( pExpr->u.zToken[1]=='\'' ); pVal = valueNew(db, pCtx); if( !pVal ) goto no_mem; zVal = &pExpr->u.zToken[2]; @@ -84767,36 +71591,25 @@ assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, 0, SQLITE_DYNAMIC); } #endif -#ifdef SQLITE_ENABLE_STAT4 + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 else if( op==TK_FUNCTION && pCtx!=0 ){ rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); } #endif - else if( op==TK_TRUEFALSE ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pVal = valueNew(db, pCtx); - if( pVal ){ - pVal->flags = MEM_Int; - pVal->u.i = pExpr->u.zToken[4]==0; - sqlite3ValueApplyAffinity(pVal, affinity, enc); - } - } *ppVal = pVal; return rc; no_mem: -#ifdef SQLITE_ENABLE_STAT4 - if( pCtx==0 || NEVER(pCtx->pParse->nErr==0) ) -#endif - sqlite3OomFault(db); + sqlite3OomFault(db); sqlite3DbFree(db, zVal); assert( *ppVal==0 ); -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( pCtx==0 ) sqlite3ValueFree(pVal); #else assert( pCtx==0 ); sqlite3ValueFree(pVal); #endif return SQLITE_NOMEM_BKPT; @@ -84812,19 +71625,68 @@ ** the value by passing it to sqlite3ValueFree() later on. If the expression ** cannot be converted to a value, then *ppVal is set to NULL. */ SQLITE_PRIVATE int sqlite3ValueFromExpr( sqlite3 *db, /* The database connection */ - const Expr *pExpr, /* The expression to evaluate */ + Expr *pExpr, /* The expression to evaluate */ u8 enc, /* Encoding to use */ u8 affinity, /* Affinity to use */ sqlite3_value **ppVal /* Write the new value here */ ){ return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; } -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** The implementation of the sqlite_record() function. This function accepts +** a single argument of any type. The return value is a formatted database +** record (a blob) containing the argument value. +** +** This is used to convert the value stored in the 'sample' column of the +** sqlite_stat3 table to the record format SQLite uses internally. +*/ +static void recordFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const int file_format = 1; + u32 iSerial; /* Serial type */ + int nSerial; /* Bytes of space for iSerial as varint */ + u32 nVal; /* Bytes of space required for argv[0] */ + int nRet; + sqlite3 *db; + u8 *aRet; + + UNUSED_PARAMETER( argc ); + iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); + nSerial = sqlite3VarintLen(iSerial); + db = sqlite3_context_db_handle(context); + + nRet = 1 + nSerial + nVal; + aRet = sqlite3DbMallocRawNN(db, nRet); + if( aRet==0 ){ + sqlite3_result_error_nomem(context); + }else{ + aRet[0] = nSerial+1; + putVarint32(&aRet[1], iSerial); + sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); + sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); + sqlite3DbFreeNN(db, aRet); + } +} + +/* +** Register built-in functions used to help read ANALYZE data. +*/ +SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){ + static FuncDef aAnalyzeTableFuncs[] = { + FUNCTION(sqlite_record, 1, 0, 0, recordFunc), + }; + sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs)); +} + /* ** Attempt to extract a value from pExpr and use it to construct *ppVal. ** ** If pAlloc is not NULL, then an UnpackedRecord object is created for ** pAlloc if one does not exist and the new value is added to the @@ -84881,12 +71743,12 @@ *ppVal = pVal; return rc; } /* -** This function is used to allocate and populate UnpackedRecord -** structures intended to be compared against sample index keys stored +** This function is used to allocate and populate UnpackedRecord +** structures intended to be compared against sample index keys stored ** in the sqlite_stat4 table. ** ** A single call to this function populates zero or more fields of the ** record starting with field iVal (fields are numbered from left to ** right starting with 0). A single field is populated if: @@ -84893,18 +71755,18 @@ ** ** * (pExpr==0). In this case the value is assumed to be an SQL NULL, ** ** * The expression is a bound variable, and this is a reprepare, or ** -** * The sqlite3ValueFromExpr() function is able to extract a value +** * The sqlite3ValueFromExpr() function is able to extract a value ** from the expression (i.e. the expression is a literal value). ** ** Or, if pExpr is a TK_VECTOR, one field is populated for each of the ** vector components that match either of the two latter criteria listed ** above. ** -** Before any value is appended to the record, the affinity of the +** Before any value is appended to the record, the affinity of the ** corresponding column within index pIdx is applied to it. Before ** this function returns, output parameter *pnExtract is set to the ** number of values appended to the record. ** ** When this function is called, *ppRec must either point to an object @@ -84951,13 +71813,13 @@ return rc; } /* ** Attempt to extract a value from expression pExpr using the methods -** as described for sqlite3Stat4ProbeSetValue() above. +** as described for sqlite3Stat4ProbeSetValue() above. ** -** If successful, set *ppVal to point to a new value object and return +** If successful, set *ppVal to point to a new value object and return ** SQLITE_OK. If no value can be extracted, but no other error occurs ** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error ** does occur, return an SQLite error code. The final value of *ppVal ** is undefined in this case. */ @@ -84973,32 +71835,32 @@ /* ** Extract the iCol-th column from the nRec-byte record in pRec. Write ** the column value into *ppVal. If *ppVal is initially NULL then a new ** sqlite3_value object is allocated. ** -** If *ppVal is initially NULL then the caller is responsible for +** If *ppVal is initially NULL then the caller is responsible for ** ensuring that the value written into *ppVal is eventually freed. */ SQLITE_PRIVATE int sqlite3Stat4Column( sqlite3 *db, /* Database handle */ const void *pRec, /* Pointer to buffer containing record */ int nRec, /* Size of buffer pRec in bytes */ int iCol, /* Column to extract */ sqlite3_value **ppVal /* OUT: Extracted value */ ){ - u32 t = 0; /* a column type code */ - u32 nHdr; /* Size of the header in the record */ - u32 iHdr; /* Next unread header byte */ - i64 iField; /* Next unread data byte */ - u32 szField = 0; /* Size of the current data field */ + u32 t; /* a column type code */ + int nHdr; /* Size of the header in the record */ + int iHdr; /* Next unread header byte */ + int iField; /* Next unread data byte */ + int szField; /* Size of the current data field */ int i; /* Column index */ u8 *a = (u8*)pRec; /* Typecast byte array */ Mem *pMem = *ppVal; /* Write result into this Mem object */ assert( iCol>0 ); iHdr = getVarint32(a, nHdr); - if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; + if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; iField = nHdr; for(i=0; i<=iCol; i++){ iHdr += getVarint32(&a[iHdr], t); testcase( iHdr==nHdr ); testcase( iHdr==nHdr+1 ); @@ -85024,11 +71886,11 @@ ** the object. */ SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ if( pRec ){ int i; - int nCol = pRec->pKeyInfo->nAllField; + int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField; Mem *aMem = pRec->aMem; sqlite3 *db = aMem[0].db; for(i=0; iflags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 ); if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){ return p->n; } - if( (p->flags & MEM_Str)!=0 && enc!=SQLITE_UTF8 && pVal->enc!=SQLITE_UTF8 ){ - return p->n; - } if( (p->flags & MEM_Blob)!=0 ){ if( p->flags & MEM_Zero ){ return p->n + p->u.nZero; }else{ return p->n; @@ -85100,19 +71959,15 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used for creating, destroying, and populating -** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) +** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ -/* Forward references */ -static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef); -static void vdbeFreeOpArray(sqlite3 *, Op *, int); - /* ** Create a new virtual database engine. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ sqlite3 *db = pParse->db; @@ -85120,33 +71975,24 @@ p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) ); if( p==0 ) return 0; memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); p->db = db; if( db->pVdbe ){ - db->pVdbe->ppVPrev = &p->pVNext; + db->pVdbe->pPrev = p; } - p->pVNext = db->pVdbe; - p->ppVPrev = &db->pVdbe; + p->pNext = db->pVdbe; + p->pPrev = 0; db->pVdbe = p; - assert( p->eVdbeState==VDBE_INIT_STATE ); + p->magic = VDBE_MAGIC_INIT; p->pParse = pParse; - pParse->pVdbe = p; assert( pParse->aLabel==0 ); assert( pParse->nLabel==0 ); - assert( p->nOpAlloc==0 ); + assert( pParse->nOpAlloc==0 ); assert( pParse->szOpAlloc==0 ); - sqlite3VdbeAddOp2(p, OP_Init, 0, 1); return p; } -/* -** Return the Parse object that owns a Vdbe object. -*/ -SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe *p){ - return p->pParse; -} - /* ** Change the error string stored in Vdbe.zErrMsg */ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){ va_list ap; @@ -85167,180 +72013,90 @@ } assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); } -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** Add a new element to the Vdbe->pDblStr list. -*/ -SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3 *db, Vdbe *p, const char *z){ - if( p ){ - int n = sqlite3Strlen30(z); - DblquoteStr *pStr = sqlite3DbMallocRawNN(db, - sizeof(*pStr)+n+1-sizeof(pStr->z)); - if( pStr ){ - pStr->pNextStr = p->pDblStr; - p->pDblStr = pStr; - memcpy(pStr->z, z, n+1); - } - } -} -#endif - -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** zId of length nId is a double-quoted identifier. Check to see if -** that identifier is really used as a string literal. -*/ -SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString( - Vdbe *pVdbe, /* The prepared statement */ - const char *zId /* The double-quoted identifier, already dequoted */ -){ - DblquoteStr *pStr; - assert( zId!=0 ); - if( pVdbe->pDblStr==0 ) return 0; - for(pStr=pVdbe->pDblStr; pStr; pStr=pStr->pNextStr){ - if( strcmp(zId, pStr->z)==0 ) return 1; - } - return 0; -} -#endif - -/* -** Swap byte-code between two VDBE structures. -** -** This happens after pB was previously run and returned -** SQLITE_SCHEMA. The statement was then reprepared in pA. -** This routine transfers the new bytecode in pA over to pB -** so that pB can be run again. The old pB byte code is -** moved back to pA so that it will be cleaned up when pA is -** finalized. +/* +** Swap all content between two VDBE structures. */ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ - Vdbe tmp, *pTmp, **ppTmp; + Vdbe tmp, *pTmp; char *zTmp; assert( pA->db==pB->db ); tmp = *pA; *pA = *pB; *pB = tmp; - pTmp = pA->pVNext; - pA->pVNext = pB->pVNext; - pB->pVNext = pTmp; - ppTmp = pA->ppVPrev; - pA->ppVPrev = pB->ppVPrev; - pB->ppVPrev = ppTmp; + pTmp = pA->pNext; + pA->pNext = pB->pNext; + pB->pNext = pTmp; + pTmp = pA->pPrev; + pA->pPrev = pB->pPrev; + pB->pPrev = pTmp; zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; -#ifdef SQLITE_ENABLE_NORMALIZE - zTmp = pA->zNormSql; - pA->zNormSql = pB->zNormSql; - pB->zNormSql = zTmp; -#endif pB->expmask = pA->expmask; pB->prepFlags = pA->prepFlags; memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++; } /* -** Resize the Vdbe.aOp array so that it is at least nOp elements larger +** Resize the Vdbe.aOp array so that it is at least nOp elements larger ** than its current size. nOp is guaranteed to be less than or equal ** to 1024/sizeof(Op). ** ** If an out-of-memory error occurs while resizing the array, return -** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain -** unchanged (this is so that any opcodes already allocated can be +** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain +** unchanged (this is so that any opcodes already allocated can be ** correctly deallocated along with the rest of the Vdbe). */ static int growOpArray(Vdbe *v, int nOp){ VdbeOp *pNew; Parse *p = v->pParse; /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force - ** more frequent reallocs and hence provide more opportunities for + ** more frequent reallocs and hence provide more opportunities for ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array ** by the minimum* amount required until the size reaches 512. Normal ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current ** size of the op array or add 1KB of space, whichever is smaller. */ #ifdef SQLITE_TEST_REALLOC_STRESS - sqlite3_int64 nNew = (v->nOpAlloc>=512 ? 2*(sqlite3_int64)v->nOpAlloc - : (sqlite3_int64)v->nOpAlloc+nOp); + int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp); #else - sqlite3_int64 nNew = (v->nOpAlloc ? 2*(sqlite3_int64)v->nOpAlloc - : (sqlite3_int64)(1024/sizeof(Op))); + int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); 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<=(int)(1024/sizeof(Op)) ); - assert( nNew>=(v->nOpAlloc+nOp) ); + assert( nOp<=(1024/sizeof(Op)) ); + assert( nNew>=(p->nOpAlloc+nOp) ); pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); if( pNew ){ p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew); - v->nOpAlloc = p->szOpAlloc/sizeof(Op); + p->nOpAlloc = p->szOpAlloc/sizeof(Op); v->aOp = pNew; } return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT); } #ifdef SQLITE_DEBUG /* This routine is just a convenient place to set a breakpoint that will ** fire after each opcode is inserted and displayed using -** "PRAGMA vdbe_addoptrace=on". Parameters "pc" (program counter) and -** pOp are available to make the breakpoint conditional. -** -** Other useful labels for breakpoints include: -** test_trace_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno) -** sqlite3MisuseError(lineno) -** sqlite3CantopenError(lineno) +** "PRAGMA vdbe_addoptrace=on". */ -static void test_addop_breakpoint(int pc, Op *pOp){ - static u64 n = 0; - (void)pc; - (void)pOp; +static void test_addop_breakpoint(void){ + static int n = 0; n++; - if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */ } #endif - -/* -** Slow paths for sqlite3VdbeAddOp3() and sqlite3VdbeAddOp4Int() for the -** unusual case when we need to increase the size of the Vdbe.aOp[] array -** before adding the new opcode. -*/ -static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ - assert( p->nOpAlloc<=p->nOp ); - if( growOpArray(p, 1) ) return 1; - assert( p->nOpAlloc>p->nOp ); - return sqlite3VdbeAddOp3(p, op, p1, p2, p3); -} -static SQLITE_NOINLINE int addOp4IntSlow( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - int p4 /* The P4 operand as an integer */ -){ - int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - if( p->db->mallocFailed==0 ){ - VdbeOp *pOp = &p->aOp[addr]; - pOp->p4type = P4_INT32; - pOp->p4.i = p4; - } - return addr; -} - /* ** Add a new instruction to the list of instructions current in the ** VDBE. Return the address of the new instruction. ** @@ -85348,115 +72104,76 @@ ** ** p Pointer to the VDBE ** ** op The opcode for this instruction ** -** p1, p2, p3, p4 Operands +** p1, p2, p3 Operands +** +** Use the sqlite3VdbeResolveLabel() function to fix an address and +** the sqlite3VdbeChangeP4() function to change the value of the P4 +** operand. */ +static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ + assert( p->pParse->nOpAlloc<=p->nOp ); + if( growOpArray(p, 1) ) return 1; + assert( p->pParse->nOpAlloc>p->nOp ); + return sqlite3VdbeAddOp3(p, op, p1, p2, p3); +} +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ + int i; + VdbeOp *pOp; + + i = p->nOp; + assert( p->magic==VDBE_MAGIC_INIT ); + assert( op>=0 && op<0xff ); + if( p->pParse->nOpAlloc<=i ){ + return growOp3(p, op, p1, p2, p3); + } + p->nOp++; + pOp = &p->aOp[i]; + pOp->opcode = (u8)op; + pOp->p5 = 0; + pOp->p1 = p1; + pOp->p2 = p2; + pOp->p3 = p3; + pOp->p4.p = 0; + pOp->p4type = P4_NOTUSED; +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + pOp->zComment = 0; +#endif +#ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ + int jj, kk; + Parse *pParse = p->pParse; + for(jj=kk=0; jjnColCache; jj++){ + struct yColCache *x = pParse->aColCache + jj; + printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); + kk++; + } + if( kk ) printf("\n"); + sqlite3VdbePrintOp(0, i, &p->aOp[i]); + test_addop_breakpoint(); + } +#endif +#ifdef VDBE_PROFILE + pOp->cycles = 0; + pOp->cnt = 0; +#endif +#ifdef SQLITE_VDBE_COVERAGE + pOp->iSrcLine = 0; +#endif + return i; +} SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ return sqlite3VdbeAddOp3(p, op, 0, 0, 0); } SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ return sqlite3VdbeAddOp3(p, op, p1, 0, 0); } SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ return sqlite3VdbeAddOp3(p, op, p1, p2, 0); } -SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ - int i; - VdbeOp *pOp; - - i = p->nOp; - assert( p->eVdbeState==VDBE_INIT_STATE ); - assert( op>=0 && op<0xff ); - if( p->nOpAlloc<=i ){ - return growOp3(p, op, p1, p2, p3); - } - assert( p->aOp!=0 ); - p->nOp++; - pOp = &p->aOp[i]; - assert( pOp!=0 ); - pOp->opcode = (u8)op; - pOp->p5 = 0; - pOp->p1 = p1; - pOp->p2 = p2; - pOp->p3 = p3; - pOp->p4.p = 0; - pOp->p4type = P4_NOTUSED; - - /* Replicate this logic in sqlite3VdbeAddOp4Int() - ** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - pOp->zComment = 0; -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - pOp->nExec = 0; - pOp->nCycle = 0; -#endif -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i, &p->aOp[i]); - test_addop_breakpoint(i, &p->aOp[i]); - } -#endif -#ifdef SQLITE_VDBE_COVERAGE - pOp->iSrcLine = 0; -#endif - /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ** Replicate in sqlite3VdbeAddOp4Int() */ - - return i; -} -SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - int p4 /* The P4 operand as an integer */ -){ - int i; - VdbeOp *pOp; - - i = p->nOp; - if( p->nOpAlloc<=i ){ - return addOp4IntSlow(p, op, p1, p2, p3, p4); - } - p->nOp++; - pOp = &p->aOp[i]; - assert( pOp!=0 ); - pOp->opcode = (u8)op; - pOp->p5 = 0; - pOp->p1 = p1; - pOp->p2 = p2; - pOp->p3 = p3; - pOp->p4.i = p4; - pOp->p4type = P4_INT32; - - /* Replicate this logic in sqlite3VdbeAddOp3() - ** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - pOp->zComment = 0; -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - pOp->nExec = 0; - pOp->nCycle = 0; -#endif -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i, &p->aOp[i]); - test_addop_breakpoint(i, &p->aOp[i]); - } -#endif -#ifdef SQLITE_VDBE_COVERAGE - pOp->iSrcLine = 0; -#endif - /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ** Replicate in sqlite3VdbeAddOp3() */ - - return i; -} /* Generate code for an unconditional jump to instruction iDest */ SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe *p, int iDest){ return sqlite3VdbeAddOp3(p, OP_Goto, 0, iDest, 0); @@ -85515,54 +72232,10 @@ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); sqlite3VdbeChangeP4(p, addr, zP4, p4type); return addr; } -/* -** Add an OP_Function or OP_PureFunc opcode. -** -** The eCallCtx argument is information (typically taken from Expr.op2) -** that describes the calling context of the function. 0 means a general -** function call. NC_IsCheck means called by a check constraint, -** NC_IdxExpr means called as part of an index expression. NC_PartIdx -** means in the WHERE clause of a partial index. NC_GenCol means called -** while computing a generated column value. 0 is the usual case. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall( - Parse *pParse, /* Parsing context */ - int p1, /* Constant argument mask */ - int p2, /* First argument register */ - int p3, /* Register into which results are written */ - int nArg, /* Number of argument */ - const FuncDef *pFunc, /* The function to be invoked */ - int eCallCtx /* Calling context */ -){ - Vdbe *v = pParse->pVdbe; - int nByte; - int addr; - sqlite3_context *pCtx; - assert( v ); - nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*); - pCtx = sqlite3DbMallocRawNN(pParse->db, nByte); - if( pCtx==0 ){ - assert( pParse->db->mallocFailed ); - freeEphemeralFunction(pParse->db, (FuncDef*)pFunc); - return 0; - } - pCtx->pOut = 0; - pCtx->pFunc = (FuncDef*)pFunc; - pCtx->pVdbe = 0; - pCtx->isError = 0; - pCtx->argc = nArg; - pCtx->iOp = sqlite3VdbeCurrentAddr(v); - addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function, - p1, p2, p3, (char*)pCtx, P4_FUNCCTX); - sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef); - sqlite3MayAbort(pParse); - return addr; -} - /* ** Add an opcode that includes the p4 value with a P4_INT64 or ** P4_REAL type. */ SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8( @@ -85577,90 +72250,42 @@ char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8); if( p4copy ) memcpy(p4copy, zP4, 8); return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); } -#ifndef SQLITE_OMIT_EXPLAIN -/* -** Return the address of the current EXPLAIN QUERY PLAN baseline. -** 0 means "none". -*/ -SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){ - VdbeOp *pOp; - if( pParse->addrExplain==0 ) return 0; - pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain); - return pOp->p2; -} - -/* -** Set a debugger breakpoint on the following routine in order to -** monitor the EXPLAIN QUERY PLAN code generation. -*/ -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char *z1, const char *z2){ - (void)z1; - (void)z2; -} -#endif - -/* -** Add a new OP_Explain opcode. -** -** If the bPush flag is true, then make this opcode the parent for -** subsequent Explains until sqlite3VdbeExplainPop() is called. -*/ -SQLITE_PRIVATE int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ - int addr = 0; -#if !defined(SQLITE_DEBUG) - /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined. - ** But omit them (for performance) during production builds */ - if( pParse->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) -#endif - { - char *zMsg; - Vdbe *v; - va_list ap; - int iThis; - va_start(ap, zFmt); - zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); - va_end(ap); - v = pParse->pVdbe; - iThis = v->nOp; - addr = sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, - zMsg, P4_DYNAMIC); - sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetLastOp(v)->p4.z); - if( bPush){ - pParse->addrExplain = iThis; - } - sqlite3VdbeScanStatus(v, iThis, -1, -1, 0, 0); - } - return addr; -} - -/* -** Pop the EXPLAIN QUERY PLAN stack one level. -*/ -SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){ - sqlite3ExplainBreakpoint("POP", 0); - pParse->addrExplain = sqlite3VdbeExplainParent(pParse); -} -#endif /* SQLITE_OMIT_EXPLAIN */ - /* ** Add an OP_ParseSchema opcode. This routine is broken out from ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees ** as having been used. ** ** The zWhere string must have been obtained from sqlite3_malloc(). ** This routine will take ownership of the allocated memory. */ -SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){ +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){ int j; sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); - sqlite3VdbeChangeP5(p, p5); for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j); - sqlite3MayAbort(p->pParse); +} + +/* +** Add an opcode that includes the p4 value as an integer. +*/ +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + int p4 /* The P4 operand as an integer */ +){ + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); + if( p->db->mallocFailed==0 ){ + VdbeOp *pOp = &p->aOp[addr]; + pOp->p4type = P4_INT32; + pOp->p4.i = p4; + } + return addr; } /* Insert the end of a co-routine */ SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ @@ -85685,107 +72310,74 @@ ** the label into the resolved address. ** ** The VDBE knows that a P2 value is a label because labels are ** always negative and P2 values are suppose to be non-negative. ** Hence, a negative P2 value is a label that has yet to be resolved. -** (Later:) This is only true for opcodes that have the OPFLG_JUMP -** property. -** -** Variable usage notes: -** -** Parse.aLabel[x] Stores the address that the x-th label resolves -** into. For testing (SQLITE_DEBUG), unresolved -** labels stores -1, but that is not required. -** Parse.nLabelAlloc Number of slots allocated to Parse.aLabel[] -** Parse.nLabel The *negative* of the number of labels that have -** been issued. The negative is stored because -** that gives a performance improvement over storing -** the equivalent positive value. -*/ -SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse *pParse){ - return --pParse->nLabel; +** +** Zero is returned if a malloc() fails. +*/ +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){ + Parse *p = v->pParse; + int i = p->nLabel++; + assert( v->magic==VDBE_MAGIC_INIT ); + if( (i & (i-1))==0 ){ + p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, + (i*2+1)*sizeof(p->aLabel[0])); + } + if( p->aLabel ){ + p->aLabel[i] = -1; + } + return ADDR(i); } /* ** Resolve label "x" to be the address of the next instruction to ** be inserted. The parameter "x" must have been obtained from ** a prior call to sqlite3VdbeMakeLabel(). */ -static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){ - int nNewSize = 10 - p->nLabel; - p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, - nNewSize*sizeof(p->aLabel[0])); - if( p->aLabel==0 ){ - p->nLabelAlloc = 0; - }else{ -#ifdef SQLITE_DEBUG - int i; - for(i=p->nLabelAlloc; iaLabel[i] = -1; -#endif - if( nNewSize>=100 && (nNewSize/100)>(p->nLabelAlloc/100) ){ - sqlite3ProgressCheck(p); - } - p->nLabelAlloc = nNewSize; - p->aLabel[j] = v->nOp; - } -} SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ Parse *p = v->pParse; int j = ADDR(x); - assert( v->eVdbeState==VDBE_INIT_STATE ); - assert( j<-p->nLabel ); + assert( v->magic==VDBE_MAGIC_INIT ); + assert( jnLabel ); assert( j>=0 ); -#ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - printf("RESOLVE LABEL %d to %d\n", x, v->nOp); - } -#endif - if( p->nLabelAlloc + p->nLabel < 0 ){ - resizeResolveLabel(p,v,j); - }else{ - assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */ + if( p->aLabel ){ p->aLabel[j] = v->nOp; } } /* ** Mark the VDBE as one that can only be run one time. */ SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ - sqlite3VdbeAddOp2(p, OP_Expire, 1, 1); + p->runOnlyOnce = 1; } /* -** Mark the VDBE as one that can be run multiple times. +** Mark the VDBE as one that can only be run multiple times. */ SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe *p){ - int i; - for(i=1; ALWAYS(inOp); i++){ - if( ALWAYS(p->aOp[i].opcode==OP_Expire) ){ - p->aOp[1].opcode = OP_Noop; - break; - } - } + p->runOnlyOnce = 0; } #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ /* ** The following type and function are used to iterate through all opcodes -** in a Vdbe main program and each of the sub-programs (triggers) it may +** in a Vdbe main program and each of the sub-programs (triggers) it may ** invoke directly or indirectly. It should be used as follows: ** ** Op *pOp; ** VdbeOpIter sIter; ** ** memset(&sIter, 0, sizeof(sIter)); -** sIter.v = v; // v is of type Vdbe* +** sIter.v = v; // v is of type Vdbe* ** while( (pOp = opIterNext(&sIter)) ){ ** // Do something with pOp ** } ** sqlite3DbFree(v->db, sIter.apSub); -** +** */ typedef struct VdbeOpIter VdbeOpIter; struct VdbeOpIter { Vdbe *v; /* Vdbe to iterate through the opcodes of */ SubProgram **apSub; /* Array of subprograms */ @@ -85814,11 +72406,11 @@ p->iAddr++; if( p->iAddr==nOp ){ p->iSub++; p->iAddr = 0; } - + if( pRet->p4type==P4_SUBPROGRAM ){ int nByte = (p->nSub+1)*sizeof(SubProgram*); int j; for(j=0; jnSub; j++){ if( p->apSub[j]==pRet->p4.pProgram ) break; @@ -85845,15 +72437,13 @@ ** ** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. ** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort. ** * OP_Destroy ** * OP_VUpdate -** * OP_VCreate ** * OP_VRename ** * OP_FkCounter with P2==0 (immediate foreign key constraint) -** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine -** (for CREATE TABLE AS SELECT ...) +** * OP_CreateTable 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 ** match, or false otherwise. This function is intended to be used as ** part of an assert statement in the compiler. Similar to: @@ -85862,41 +72452,26 @@ */ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ int hasAbort = 0; int hasFkCounter = 0; int hasCreateTable = 0; - int hasCreateIndex = 0; int hasInitCoroutine = 0; Op *pOp; VdbeOpIter sIter; - - if( v==0 ) return 0; memset(&sIter, 0, sizeof(sIter)); sIter.v = v; while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; - if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename - || opcode==OP_VDestroy - || opcode==OP_VCreate - || opcode==OP_ParseSchema - || opcode==OP_Function || opcode==OP_PureFunc - || ((opcode==OP_Halt || opcode==OP_HaltIfNull) - && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) + if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename + || ((opcode==OP_Halt || opcode==OP_HaltIfNull) + && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) ){ hasAbort = 1; break; } - if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1; - if( mayAbort ){ - /* hasCreateIndex may also be set for some DELETE statements that use - ** OP_Clear. So this routine may end up returning true in the case - ** where a "DELETE FROM tbl" has a statement-journal but does not - ** require one. This is not so bad - it is an inefficiency, not a bug. */ - if( opcode==OP_CreateBtree && pOp->p3==BTREE_BLOBKEY ) hasCreateIndex = 1; - if( opcode==OP_Clear ) hasCreateIndex = 1; - } + if( opcode==OP_CreateTable ) hasCreateTable = 1; if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; #ifndef SQLITE_OMIT_FOREIGN_KEY if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ hasFkCounter = 1; } @@ -85908,41 +72483,14 @@ ** If malloc failed, then the while() loop above may not have iterated ** through all opcodes and hasAbort may be set incorrectly. Return ** true for this case to prevent the assert() in the callers frame ** from failing. */ return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter - || (hasCreateTable && hasInitCoroutine) || hasCreateIndex - ); + || (hasCreateTable && hasInitCoroutine) ); } #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ -#ifdef SQLITE_DEBUG -/* -** Increment the nWrite counter in the VDBE if the cursor is not an -** ephemeral cursor, or if the cursor argument is NULL. -*/ -SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){ - if( pC==0 - || (pC->eCurType!=CURTYPE_SORTER - && pC->eCurType!=CURTYPE_PSEUDO - && !pC->isEphemeral) - ){ - p->nWrite++; - } -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Assert if an Abort at this point in time might result in a corrupt -** database. -*/ -SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){ - assert( p->nWrite==0 || p->usesStmtJournal ); -} -#endif - /* ** This routine is called after all opcodes have been inserted. It loops ** through all the opcodes and fixes up some details. ** ** (1) For each jump instruction with a negative P2 value (a label) @@ -85952,11 +72500,11 @@ ** and store that value in *pMaxFuncArgs. ** ** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately ** indicate what the prepared statement actually does. ** -** (4) (discontinued) +** (4) Initialize the p4.xAdvance pointer on opcodes that use it. ** ** (5) Reclaim the memory allocated for storing labels. ** ** This routine will only function correctly if the mkopcodeh.tcl generator ** script numbers the opcodes correctly. Changes to this routine must be @@ -85965,17 +72513,15 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int nMaxArgs = *pMaxFuncArgs; Op *pOp; Parse *pParse = p->pParse; int *aLabel = pParse->aLabel; - - assert( pParse->db->mallocFailed==0 ); /* tag-20230419-1 */ p->readOnly = 1; p->bIsReader = 0; pOp = &p->aOp[p->nOp-1]; - assert( p->aOp[0].opcode==OP_Init ); - while( 1 /* Loop terminates when it reaches the OP_Init opcode */ ){ + while(1){ + /* Only JUMP opcodes and the short list of special opcodes in the switch ** below need to be considered. The mkopcodeh.tcl generator script groups ** all these opcodes together near the front of the opcode list. Skip ** any opcode that does not need processing by virtual of the fact that ** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization. @@ -85984,11 +72530,11 @@ /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing ** cases from this switch! */ switch( pOp->opcode ){ case OP_Transaction: { if( pOp->p2!=0 ) p->readOnly = 0; - /* no break */ deliberate_fall_through + /* fall thru */ } case OP_AutoCommit: case OP_Savepoint: { p->bIsReader = 1; break; @@ -86000,14 +72546,10 @@ case OP_JournalMode: { p->readOnly = 0; p->bIsReader = 1; break; } - case OP_Init: { - assert( pOp->p2>=0 ); - goto resolve_p2_values_loop_exit; - } #ifndef SQLITE_OMIT_VIRTUALTABLE case OP_VUpdate: { if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; break; } @@ -86015,147 +72557,47 @@ int n; assert( (pOp - p->aOp) >= 3 ); assert( pOp[-1].opcode==OP_Integer ); n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; - /* Fall through into the default case */ - /* no break */ deliberate_fall_through + break; } #endif - 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)<-pParse->nLabel ); - assert( aLabel!=0 ); /* True because of tag-20230419-1 */ - pOp->p2 = aLabel[ADDR(pOp->p2)]; - } - - /* OPFLG_JUMP opcodes never have P2==0, though OPFLG_JUMP0 opcodes - ** might */ - assert( pOp->p2>0 - || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP0)!=0 ); - - /* Jumps never go off the end of the bytecode array */ - assert( pOp->p2nOp - || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)==0 ); + 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; break; } } - /* 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( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){ + assert( ADDR(pOp->p2)nLabel ); + pOp->p2 = aLabel[ADDR(pOp->p2)]; + } } - assert( pOp>p->aOp ); + if( pOp==p->aOp ) break; pOp--; } -resolve_p2_values_loop_exit: - if( aLabel ){ - sqlite3DbNNFreeNN(p->db, pParse->aLabel); - pParse->aLabel = 0; - } + sqlite3DbFree(p->db, pParse->aLabel); + pParse->aLabel = 0; pParse->nLabel = 0; *pMaxFuncArgs = nMaxArgs; assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) ); } -#ifdef SQLITE_DEBUG -/* -** Check to see if a subroutine contains a jump to a location outside of -** the subroutine. If a jump outside the subroutine is detected, add code -** that will cause the program to halt with an error message. -** -** The subroutine consists of opcodes between iFirst and iLast. Jumps to -** locations within the subroutine are acceptable. iRetReg is a register -** that contains the return address. Jumps to outside the range of iFirst -** through iLast are also acceptable as long as the jump destination is -** an OP_Return to iReturnAddr. -** -** A jump to an unresolved label means that the jump destination will be -** beyond the current address. That is normally a jump to an early -** termination and is consider acceptable. -** -** This routine only runs during debug builds. The purpose is (of course) -** to detect invalid escapes out of a subroutine. The OP_Halt opcode -** is generated rather than an assert() or other error, so that ".eqp full" -** will still work to show the original bytecode, to aid in debugging. -*/ -SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn( - Vdbe *v, /* The byte-code program under construction */ - int iFirst, /* First opcode of the subroutine */ - int iLast, /* Last opcode of the subroutine */ - int iRetReg /* Subroutine return address register */ -){ - VdbeOp *pOp; - Parse *pParse; - int i; - sqlite3_str *pErr = 0; - assert( v!=0 ); - pParse = v->pParse; - assert( pParse!=0 ); - if( pParse->nErr ) return; - assert( iLast>=iFirst ); - assert( iLastnOp ); - pOp = &v->aOp[iFirst]; - for(i=iFirst; i<=iLast; i++, pOp++){ - if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ){ - int iDest = pOp->p2; /* Jump destination */ - if( iDest==0 ) continue; - if( pOp->opcode==OP_Gosub ) continue; - if( pOp->p3==20230325 && pOp->opcode==OP_NotNull ){ - /* This is a deliberately taken illegal branch. tag-20230325-2 */ - continue; - } - if( iDest<0 ){ - int j = ADDR(iDest); - assert( j>=0 ); - if( j>=-pParse->nLabel || pParse->aLabel[j]<0 ){ - continue; - } - iDest = pParse->aLabel[j]; - } - if( iDestiLast ){ - int j = iDest; - for(; jnOp; j++){ - VdbeOp *pX = &v->aOp[j]; - if( pX->opcode==OP_Return ){ - if( pX->p1==iRetReg ) break; - continue; - } - if( pX->opcode==OP_Noop ) continue; - if( pX->opcode==OP_Explain ) continue; - if( pErr==0 ){ - pErr = sqlite3_str_new(0); - }else{ - sqlite3_str_appendchar(pErr, 1, '\n'); - } - sqlite3_str_appendf(pErr, - "Opcode at %d jumps to %d which is outside the " - "subroutine at %d..%d", - i, iDest, iFirst, iLast); - break; - } - } - } - } - if( pErr ){ - char *zErr = sqlite3_str_finish(pErr); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_INTERNAL, OE_Abort, 0, zErr, 0); - sqlite3_free(zErr); - sqlite3MayAbort(pParse); - } -} -#endif /* SQLITE_DEBUG */ - /* ** Return the address of the next instruction to be inserted. */ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){ - assert( p->eVdbeState==VDBE_INIT_STATE ); + assert( p->magic==VDBE_MAGIC_INIT ); return p->nOp; } /* ** Verify that at least N opcode slots are available in p without @@ -86165,11 +72607,11 @@ ** fail due to a OOM fault and hence that the return value from ** sqlite3VdbeAddOpList() will always be non-NULL. */ #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){ - assert( p->nOp + N <= p->nOpAlloc ); + assert( p->nOp + N <= p->pParse->nOpAlloc ); } #endif /* ** Verify that the VM passed as the only argument does not contain @@ -86185,30 +72627,19 @@ assert( p->aOp[i].opcode!=OP_ResultRow ); } } #endif -/* -** Generate code (a single OP_Abortable opcode) that will -** verify that the VDBE program can safely call Abort in the current -** context. -*/ -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){ - if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable); -} -#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 -** to arrange for the returned array to be eventually freed using the +** to arrange for the returned array to be eventually freed using the ** vdbeFreeOpArray() function. ** ** Before returning, *pnOp is set to the number of entries in the returned -** array. Also, *pnMaxArg is set to the larger of its current value and -** the number of entries in the Vdbe.apArg[] array required to execute the +** array. Also, *pnMaxArg is set to the larger of its current value and +** the number of entries in the Vdbe.apArg[] array required to execute the ** returned program. */ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ VdbeOp *aOp = p->aOp; assert( aOp && !p->db->mallocFailed ); @@ -86236,12 +72667,12 @@ int iLineno /* Source-file line number of first opcode */ ){ int i; VdbeOp *pOut, *pFirst; assert( nOp>0 ); - assert( p->eVdbeState==VDBE_INIT_STATE ); - if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){ + assert( p->magic==VDBE_MAGIC_INIT ); + if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){ return 0; } pFirst = pOut = &p->aOp[p->nOp]; for(i=0; iopcode = aOp->opcode; @@ -86278,190 +72709,83 @@ ** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). */ SQLITE_PRIVATE void sqlite3VdbeScanStatus( Vdbe *p, /* VM to add scanstatus() to */ int addrExplain, /* Address of OP_Explain (or 0) */ - int addrLoop, /* Address of loop counter */ + int addrLoop, /* Address of loop counter */ int addrVisit, /* Address of rows visited counter */ LogEst nEst, /* Estimated number of output rows */ const char *zName /* Name of table or index being scanned */ ){ - if( IS_STMT_SCANSTATUS(p->db) ){ - sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus); - ScanStatus *aNew; - aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); - if( aNew ){ - ScanStatus *pNew = &aNew[p->nScan++]; - memset(pNew, 0, sizeof(ScanStatus)); - pNew->addrExplain = addrExplain; - pNew->addrLoop = addrLoop; - pNew->addrVisit = addrVisit; - pNew->nEst = nEst; - pNew->zName = sqlite3DbStrDup(p->db, zName); - p->aScan = aNew; - } - } -} - -/* -** Add the range of instructions from addrStart to addrEnd (inclusive) to -** the set of those corresponding to the sqlite3_stmt_scanstatus() counters -** associated with the OP_Explain instruction at addrExplain. The -** sum of the sqlite3Hwtime() values for each of these instructions -** will be returned for SQLITE_SCANSTAT_NCYCLE requests. -*/ -SQLITE_PRIVATE void sqlite3VdbeScanStatusRange( - Vdbe *p, - int addrExplain, - int addrStart, - int addrEnd -){ - if( IS_STMT_SCANSTATUS(p->db) ){ - ScanStatus *pScan = 0; - int ii; - for(ii=p->nScan-1; ii>=0; ii--){ - pScan = &p->aScan[ii]; - if( pScan->addrExplain==addrExplain ) break; - pScan = 0; - } - if( pScan ){ - if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1; - for(ii=0; iiaAddrRange); ii+=2){ - if( pScan->aAddrRange[ii]==0 ){ - pScan->aAddrRange[ii] = addrStart; - pScan->aAddrRange[ii+1] = addrEnd; - break; - } - } - } - } -} - -/* -** Set the addresses for the SQLITE_SCANSTAT_NLOOP and SQLITE_SCANSTAT_NROW -** counters for the query element associated with the OP_Explain at -** addrExplain. -*/ -SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters( - Vdbe *p, - int addrExplain, - int addrLoop, - int addrVisit -){ - if( IS_STMT_SCANSTATUS(p->db) ){ - ScanStatus *pScan = 0; - int ii; - for(ii=p->nScan-1; ii>=0; ii--){ - pScan = &p->aScan[ii]; - if( pScan->addrExplain==addrExplain ) break; - pScan = 0; - } - if( pScan ){ - if( addrLoop>0 ) pScan->addrLoop = addrLoop; - if( addrVisit>0 ) pScan->addrVisit = addrVisit; - } - } -} -#endif /* defined(SQLITE_ENABLE_STMT_SCANSTATUS) */ + int nByte = (p->nScan+1) * sizeof(ScanStatus); + ScanStatus *aNew; + aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); + if( aNew ){ + ScanStatus *pNew = &aNew[p->nScan++]; + pNew->addrExplain = addrExplain; + pNew->addrLoop = addrLoop; + pNew->addrVisit = addrVisit; + pNew->nEst = nEst; + pNew->zName = sqlite3DbStrDup(p->db, zName); + p->aScan = aNew; + } +} +#endif /* ** Change the value of the opcode, or P1, P2, P3, or P5 operands ** for a specific instruction. */ -SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){ - assert( addr>=0 ); +SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){ sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode; } -SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){ - assert( addr>=0 ); +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p1 = val; } -SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ - assert( addr>=0 || p->db->mallocFailed ); +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p2 = val; } -SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){ - assert( addr>=0 ); +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p3 = val; } 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; } -/* -** If the previous opcode is an OP_Column that delivers results -** into register iDest, then add the OPFLAG_TYPEOFARG flag to that -** opcode. -*/ -SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){ - VdbeOp *pOp = sqlite3VdbeGetLastOp(p); - if( pOp->p3==iDest && pOp->opcode==OP_Column ){ - pOp->p5 |= OPFLAG_TYPEOFARG; - } -} - /* ** Change the P2 operand of instruction addr so that it points to ** the address of the next instruction to be coded. */ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ sqlite3VdbeChangeP2(p, addr, p->nOp); } -/* -** Change the P2 operand of the jump instruction at addr so that -** the jump lands on the next opcode. Or if the jump instruction was -** the previous opcode (and is thus a no-op) then simply back up -** the next instruction counter by one slot so that the jump is -** overwritten by the next inserted opcode. -** -** This routine is an optimization of sqlite3VdbeJumpHere() that -** strives to omit useless byte-code like this: -** -** 7 Once 0 8 0 -** 8 ... -*/ -SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ - if( addr==p->nOp-1 ){ - assert( p->aOp[addr].opcode==OP_Once - || p->aOp[addr].opcode==OP_If - || p->aOp[addr].opcode==OP_FkIfZero ); - assert( p->aOp[addr].p4type==0 ); -#ifdef SQLITE_VDBE_COVERAGE - sqlite3VdbeGetLastOp(p)->iSrcLine = 0; /* Erase VdbeCoverage() macros */ -#endif - p->nOp--; - }else{ - sqlite3VdbeChangeP2(p, addr, p->nOp); - } -} - /* ** If the input FuncDef structure is ephemeral, then free it. If -** the FuncDef is not ephemeral, then do nothing. +** the FuncDef is not ephermal, then do nothing. */ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ - assert( db!=0 ); if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){ - sqlite3DbNNFreeNN(db, pDef); + sqlite3DbFreeNN(db, pDef); } } + +static void vdbeFreeOpArray(sqlite3 *, Op *, int); /* ** Delete a P4 value if necessary. */ static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){ if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); - sqlite3DbNNFreeNN(db, p); + sqlite3DbFreeNN(db, p); } static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){ - assert( db!=0 ); freeEphemeralFunction(db, p->pFunc); - sqlite3DbNNFreeNN(db, p); + sqlite3DbFreeNN(db, p); } static void freeP4(sqlite3 *db, int p4type, void *p4){ assert( db ); switch( p4type ){ case P4_FUNCCTX: { @@ -86470,11 +72794,11 @@ } case P4_REAL: case P4_INT64: case P4_DYNAMIC: case P4_INTARRAY: { - if( p4 ) sqlite3DbNNFreeNN(db, p4); + sqlite3DbFree(db, p4); break; } case P4_KEYINFO: { if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); break; @@ -86499,42 +72823,28 @@ } case P4_VTAB : { if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); break; } - case P4_TABLEREF: { - if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4); - break; - } - case P4_SUBRTNSIG: { - SubrtnSig *pSig = (SubrtnSig*)p4; - sqlite3DbFree(db, pSig->zAff); - sqlite3DbFree(db, pSig); - break; - } } } /* ** Free the space allocated for aOp and any p4 values allocated for the -** opcodes contained within. If aOp is not NULL it is assumed to contain -** nOp entries. +** opcodes contained within. If aOp is not NULL it is assumed to contain +** nOp entries. */ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ - assert( nOp>=0 ); - assert( db!=0 ); if( aOp ){ - Op *pOp = &aOp[nOp-1]; - while(1){ /* Exit via break */ + Op *pOp; + 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 - if( pOp==aOp ) break; - pOp--; +#endif } - sqlite3DbNNFreeNN(db, aOp); + sqlite3DbFreeNN(db, aOp); } } /* ** Link the SubProgram object passed as the second argument into the linked @@ -86544,17 +72854,10 @@ SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ p->pNext = pVdbe->pProgram; pVdbe->pProgram = p; } -/* -** Return true if the given Vdbe has any SubPrograms. -*/ -SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){ - return pVdbe->pProgram!=0; -} - /* ** Change the opcode at addr into OP_Noop */ SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ VdbeOp *pOp; @@ -86578,44 +72881,10 @@ }else{ return 0; } } -#ifdef SQLITE_DEBUG -/* -** Generate an OP_ReleaseReg opcode to indicate that a range of -** registers, except any identified by mask, are no longer in use. -*/ -SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters( - Parse *pParse, /* Parsing context */ - int iFirst, /* Index of first register to be released */ - int N, /* Number of registers to release */ - u32 mask, /* Mask of registers to NOT release */ - int bUndefine /* If true, mark registers as undefined */ -){ - if( N==0 || OptimizationDisabled(pParse->db, SQLITE_ReleaseReg) ) return; - assert( pParse->pVdbe ); - assert( iFirst>=1 ); - assert( iFirst+N-1<=pParse->nMem ); - if( N<=31 && mask!=0 ){ - while( N>0 && (mask&1)!=0 ){ - mask >>= 1; - iFirst++; - N--; - } - while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){ - mask &= ~MASKBIT32(N-1); - N--; - } - } - if( N>0 ){ - sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask); - if( bUndefine ) sqlite3VdbeChangeP5(pParse->pVdbe, 1); - } -} -#endif /* SQLITE_DEBUG */ - /* ** Change the value of the P4 operand for a specific instruction. ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a ** few minor changes to the program. @@ -86622,11 +72891,11 @@ ** ** If n>=0 then the P4 operand is dynamic, meaning that a copy of ** the string is made into memory obtained from sqlite3_malloc(). ** A value of n==0 means copy bytes of zP4 up to and including the ** first null byte. If n>0 then copy n+1 bytes of zP4. -** +** ** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points ** to a string or structure that is guaranteed to exist for the lifetime of ** the Vdbe. In these cases we can just copy the pointer. ** ** If addr<0 then change P4 on the most recently inserted instruction. @@ -86636,11 +72905,11 @@ Op *pOp, const char *zP4, int n ){ if( pOp->p4type ){ - assert( pOp->p4type > P4_FREE_IF_LE ); + freeP4(p->db, pOp->p4type, pOp->p4.p); pOp->p4type = 0; pOp->p4.p = 0; } if( n<0 ){ sqlite3VdbeChangeP4(p, (int)(pOp - p->aOp), zP4, n); @@ -86653,11 +72922,11 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ Op *pOp; sqlite3 *db; assert( p!=0 ); db = p->db; - assert( p->eVdbeState==VDBE_INIT_STATE ); + assert( p->magic==VDBE_MAGIC_INIT ); assert( p->aOp!=0 || db->mallocFailed ); if( db->mallocFailed ){ if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4); return; } @@ -86683,11 +72952,11 @@ if( n==P4_VTAB ) sqlite3VtabLock((VTable*)zP4); } } /* -** Change the P4 operand of the most recently coded instruction +** Change the P4 operand of the most recently coded instruction ** to the value defined by the arguments. This is a high-speed ** version of sqlite3VdbeChangeP4(). ** ** The P4 operand must not have been previously defined. And the new ** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of @@ -86698,11 +72967,11 @@ assert( n!=P4_INT32 && n!=P4_VTAB ); assert( n<=0 ); if( p->db->mallocFailed ){ freeP4(p->db, n, pP4); }else{ - assert( pP4!=0 || n==P4_DYNAMIC ); + 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; @@ -86729,11 +72998,11 @@ ** makes the code easier to read during debugging. None of this happens ** in a production build. */ static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){ assert( p->nOp>0 || p->aOp==0 ); - assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ assert( p->aOp ); sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment); p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap); } @@ -86760,46 +73029,43 @@ #ifdef SQLITE_VDBE_COVERAGE /* ** Set the value if the iSrcLine field for the previously coded instruction. */ SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ - sqlite3VdbeGetLastOp(v)->iSrcLine = iLine; + sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine; } #endif /* SQLITE_VDBE_COVERAGE */ /* -** Return the opcode for a given address. The address must be non-negative. -** See sqlite3VdbeGetLastOp() to get the most recently added opcode. +** Return the opcode for a given address. If the address is -1, then +** return the most recently inserted opcode. ** ** If a memory allocation error has occurred prior to the calling of this ** routine, then a pointer to a dummy VdbeOp will be returned. That opcode ** is readable but not writable, though it is cast to a writable value. ** The return of a dummy opcode allows the call to continue functioning -** after an OOM fault without having to check to see if the return from +** after an OOM fault without having to check to see if the return from ** this routine is a valid pointer. But because the dummy.opcode is 0, ** dummy will never be written to. This is verified by code inspection and ** by running with Valgrind. */ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ /* C89 specifies that the constant "dummy" will be initialized to all ** zeros, which is correct. MSVC generates a warning, nevertheless. */ static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */ - assert( p->eVdbeState==VDBE_INIT_STATE ); + assert( p->magic==VDBE_MAGIC_INIT ); + if( addr<0 ){ + addr = p->nOp - 1; + } assert( (addr>=0 && addrnOp) || p->db->mallocFailed ); if( p->db->mallocFailed ){ return (VdbeOp*)&dummy; }else{ return &p->aOp[addr]; } } -/* Return the most recently added opcode -*/ -SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe *p){ - return sqlite3VdbeGetOp(p, p->nOp - 1); -} - #if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) /* ** Return an integer value for one of the parameters to the opcode pOp ** determined by character c. */ @@ -86822,94 +73088,82 @@ ** "PX" -> "r[X]" ** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1 ** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0 ** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x */ -SQLITE_PRIVATE char *sqlite3VdbeDisplayComment( - sqlite3 *db, /* Optional - Oom error reporting only */ +static int displayComment( const Op *pOp, /* The opcode to be commented */ - const char *zP4 /* Previously obtained value for P4 */ + const char *zP4, /* Previously obtained value for P4 */ + char *zTemp, /* Write result here */ + int nTemp /* Space available in zTemp[] */ ){ const char *zOpName; const char *zSynopsis; int nOpName; - int ii; + int ii, jj; char zAlt[50]; - StrAccum x; - - sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH); zOpName = sqlite3OpcodeName(pOp->opcode); nOpName = sqlite3Strlen30(zOpName); if( zOpName[nOpName+1] ){ int seenCom = 0; char c; - zSynopsis = zOpName + nOpName + 1; + zSynopsis = zOpName += nOpName + 1; if( strncmp(zSynopsis,"IF ",3)==0 ){ - sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3); + if( pOp->p5 & SQLITE_STOREP2 ){ + sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3); + }else{ + sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3); + } zSynopsis = zAlt; } - for(ii=0; (c = zSynopsis[ii])!=0; ii++){ + for(ii=jj=0; jjzComment && pOp->zComment[0] ){ - sqlite3_str_appendall(&x, pOp->zComment); - seenCom = 1; - break; - } + sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment); + seenCom = 1; }else{ int v1 = translateP(c, pOp); int v2; + sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1); if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){ ii += 3; + jj += sqlite3Strlen30(zTemp+jj); v2 = translateP(zSynopsis[ii], pOp); if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){ ii += 2; v2++; } - if( v2<2 ){ - sqlite3_str_appendf(&x, "%d", v1); - }else{ - sqlite3_str_appendf(&x, "%d..%d", v1, v1+v2-1); - } - }else if( strncmp(zSynopsis+ii+1, "@NP", 3)==0 ){ - sqlite3_context *pCtx = pOp->p4.pCtx; - if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){ - sqlite3_str_appendf(&x, "%d", v1); - }else if( pCtx->argc>1 ){ - sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1); - }else if( x.accError==0 ){ - assert( x.nChar>2 ); - x.nChar -= 2; - ii++; - } - ii += 3; - }else{ - sqlite3_str_appendf(&x, "%d", v1); - if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){ - ii += 4; - } - } - } - }else{ - sqlite3_str_appendchar(&x, 1, c); - } - } - if( !seenCom && pOp->zComment ){ - sqlite3_str_appendf(&x, "; %s", pOp->zComment); - } + if( v2>1 ){ + sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1); + } + }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){ + ii += 4; + } + } + jj += sqlite3Strlen30(zTemp+jj); + }else{ + zTemp[jj++] = c; + } + } + if( !seenCom && jjzComment ){ + sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment); + jj += sqlite3Strlen30(zTemp+jj); + } + if( jjzComment ){ - sqlite3_str_appendall(&x, pOp->zComment); - } - if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){ - sqlite3OomFault(db); - } - return sqlite3StrAccumFinish(&x); -} -#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */ + sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment); + jj = sqlite3Strlen30(zTemp); + }else{ + zTemp[0] = 0; + jj = 0; + } + return jj; +} +#endif /* SQLITE_DEBUG */ #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) /* ** Translate the P4.pExpr value for an OP_CursorHint opcode into text ** that can be displayed in the P4 column of EXPLAIN output. @@ -86916,28 +73170,27 @@ */ static void displayP4Expr(StrAccum *p, Expr *pExpr){ const char *zOp = 0; switch( pExpr->op ){ case TK_STRING: - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3_str_appendf(p, "%Q", pExpr->u.zToken); + sqlite3XPrintf(p, "%Q", pExpr->u.zToken); break; case TK_INTEGER: - sqlite3_str_appendf(p, "%d", pExpr->u.iValue); + sqlite3XPrintf(p, "%d", pExpr->u.iValue); break; case TK_NULL: - sqlite3_str_appendf(p, "NULL"); + sqlite3XPrintf(p, "NULL"); break; case TK_REGISTER: { - sqlite3_str_appendf(p, "r[%d]", pExpr->iTable); + sqlite3XPrintf(p, "r[%d]", pExpr->iTable); break; } case TK_COLUMN: { if( pExpr->iColumn<0 ){ - sqlite3_str_appendf(p, "rowid"); + sqlite3XPrintf(p, "rowid"); }else{ - sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn); + sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); } break; } case TK_LT: zOp = "LT"; break; case TK_LE: zOp = "LE"; break; @@ -86965,22 +73218,22 @@ case TK_NOT: zOp = "NOT"; break; case TK_ISNULL: zOp = "ISNULL"; break; case TK_NOTNULL: zOp = "NOTNULL"; break; default: - sqlite3_str_appendf(p, "%s", "expr"); + sqlite3XPrintf(p, "%s", "expr"); break; } if( zOp ){ - sqlite3_str_appendf(p, "%s(", zOp); + sqlite3XPrintf(p, "%s(", zOp); displayP4Expr(p, pExpr->pLeft); if( pExpr->pRight ){ - sqlite3_str_append(p, ",", 1); + sqlite3StrAccumAppend(p, ",", 1); displayP4Expr(p, pExpr->pRight); } - sqlite3_str_append(p, ")", 1); + sqlite3StrAccumAppend(p, ")", 1); } } #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ @@ -86987,77 +73240,73 @@ #if VDBE_DISPLAY_P4 /* ** Compute a string that describes the P4 parameter for an opcode. ** Use zTemp for any required temporary buffer space. */ -SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){ - char *zP4 = 0; +static char *displayP4(Op *pOp, char *zTemp, int nTemp){ + char *zP4 = zTemp; StrAccum x; - - sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH); + assert( nTemp>=20 ); + sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0); switch( pOp->p4type ){ case P4_KEYINFO: { int j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - assert( pKeyInfo->aSortFlags!=0 ); - sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); - for(j=0; jnKeyField; j++){ + assert( pKeyInfo->aSortOrder!=0 ); + sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); + for(j=0; jnField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; const char *zColl = pColl ? pColl->zName : ""; if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; - sqlite3_str_appendf(&x, ",%s%s%s", - (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "", - (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "", - zColl); + sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); } - sqlite3_str_append(&x, ")", 1); + sqlite3StrAccumAppend(&x, ")", 1); break; } #ifdef SQLITE_ENABLE_CURSOR_HINTS case P4_EXPR: { displayP4Expr(&x, pOp->p4.pExpr); break; } #endif case P4_COLLSEQ: { - static const char *const encnames[] = {"?", "8", "16LE", "16BE"}; CollSeq *pColl = pOp->p4.pColl; - assert( pColl->enc<4 ); - sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName, - encnames[pColl->enc]); + sqlite3XPrintf(&x, "(%.20s)", pColl->zName); break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; - sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) case P4_FUNCCTX: { FuncDef *pDef = pOp->p4.pCtx->pFunc; - sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } +#endif case P4_INT64: { - sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64); + sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); break; } case P4_INT32: { - sqlite3_str_appendf(&x, "%d", pOp->p4.i); + sqlite3XPrintf(&x, "%d", pOp->p4.i); break; } case P4_REAL: { - sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal); + sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); break; } case P4_MEM: { Mem *pMem = pOp->p4.pMem; if( pMem->flags & MEM_Str ){ zP4 = pMem->z; - }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){ - sqlite3_str_appendf(&x, "%lld", pMem->u.i); + }else if( pMem->flags & MEM_Int ){ + sqlite3XPrintf(&x, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ - sqlite3_str_appendf(&x, "%.16g", pMem->u.r); + sqlite3XPrintf(&x, "%.16g", pMem->u.r); }else if( pMem->flags & MEM_Null ){ zP4 = "NULL"; }else{ assert( pMem->flags & MEM_Blob ); zP4 = "(blob)"; @@ -87065,47 +73314,49 @@ break; } #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_str_appendf(&x, "vtab:%p", pVtab); + sqlite3XPrintf(&x, "vtab:%p", pVtab); break; } #endif case P4_INTARRAY: { - u32 i; - u32 *ai = pOp->p4.ai; - u32 n = ai[0]; /* The first element of an INTARRAY is always the + int i; + 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; i<=n; i++){ - sqlite3_str_appendf(&x, "%c%u", (i==1 ? '[' : ','), ai[i]); + for(i=1; ip4.pTab->zName; - break; - } - case P4_SUBRTNSIG: { - SubrtnSig *pSig = pOp->p4.pSubrtnSig; - sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff); + sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName); break; } default: { zP4 = pOp->p4.z; + if( zP4==0 ){ + zP4 = zTemp; + zTemp[0] = 0; + } } } - if( zP4 ) sqlite3_str_appendall(&x, zP4); - if( (x.accError & SQLITE_NOMEM)!=0 ){ - sqlite3OomFault(db); - } - return sqlite3StrAccumFinish(&x); + sqlite3StrAccumFinish(&x); + assert( zP4!=0 ); + return zP4; } #endif /* VDBE_DISPLAY_P4 */ /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. @@ -87132,17 +73383,17 @@ ** sets the BtShared.db member of each of the BtShared structures, ensuring ** that the correct busy-handler callback is invoked if required. ** ** If SQLite is not threadsafe but does support shared-cache mode, then ** sqlite3BtreeEnter() is invoked to set the BtShared.db variables -** of all of BtShared structures accessible via the database handle +** of all of BtShared structures accessible via the database handle ** associated with the VM. ** ** If SQLite is not threadsafe and does not support shared-cache mode, this ** function is a no-op. ** -** The p->btreeMask field is a bitmask of all btrees that the prepared +** The p->btreeMask field is a bitmask of all btrees that the prepared ** statement p will ever use. Let N be the number of bits in p->btreeMask ** corresponding to btrees that use shared cache. Then the runtime of ** this routine is N*N. But as N is rarely more than 1, this should not ** be a problem. */ @@ -87189,83 +73440,55 @@ #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Print a single opcode. This routine is used for debugging only. */ -SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){ +SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ char *zP4; - char *zCom; - sqlite3 dummyDb; + char zPtr[50]; + char zCom[100]; static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n"; if( pOut==0 ) pOut = stdout; - sqlite3BeginBenignMalloc(); - dummyDb.mallocFailed = 1; - zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp); + zP4 = displayP4(pOp, zPtr, sizeof(zPtr)); #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - zCom = sqlite3VdbeDisplayComment(0, pOp, zP4); + displayComment(pOp, zP4, zCom, sizeof(zCom)); #else - zCom = 0; + zCom[0] = 0; #endif /* NB: The sqlite3OpcodeName() function is implemented by code created ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the ** information from the vdbe.c source text */ - fprintf(pOut, zFormat1, pc, - sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, - zP4 ? zP4 : "", pOp->p5, - zCom ? zCom : "" + fprintf(pOut, zFormat1, pc, + sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, + zCom ); fflush(pOut); - sqlite3_free(zP4); - sqlite3_free(zCom); - sqlite3EndBenignMalloc(); } #endif /* ** Initialize an array of N Mem element. -** -** This is a high-runner, so only those fields that really do need to -** be initialized are set. The Mem structure is organized so that -** the fields that get initialized are nearby and hopefully on the same -** cache line. -** -** Mem.flags = flags -** Mem.db = db -** Mem.szMalloc = 0 -** -** All other fields of Mem can safely remain uninitialized for now. They -** will be initialized before use. */ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){ - assert( db!=0 ); - if( N>0 ){ - do{ - p->flags = flags; - p->db = db; - p->szMalloc = 0; + while( (N--)>0 ){ + p->db = db; + p->flags = flags; + p->szMalloc = 0; #ifdef SQLITE_DEBUG - p->pScopyFrom = 0; - p->bScopy = 0; + p->pScopyFrom = 0; #endif - p++; - }while( (--N)>0 ); + p++; } } /* -** Release auxiliary memory held in an array of N Mem elements. -** -** After this routine returns, all Mem elements in the array will still -** be valid. Those Mem elements that were not holding auxiliary resources -** will be unchanged. Mem elements which had something freed will be -** set to MEM_Undefined. +** Release an array of N Mem elements */ static void releaseMemArray(Mem *p, int N){ if( p && N ){ Mem *pEnd = &p[N]; sqlite3 *db = p->db; - assert( db!=0 ); if( db->pnBytesFreed ){ do{ if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); }while( (++p)flags & MEM_Agg ); testcase( p->flags & MEM_Dyn ); - if( p->flags&(MEM_Agg|MEM_Dyn) ){ - testcase( (p->flags & MEM_Dyn)!=0 && p->xDel==sqlite3VdbeFrameMemDel ); + testcase( p->flags & MEM_Frame ); + testcase( p->flags & MEM_RowSet ); + if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); - p->flags = MEM_Undefined; }else if( p->szMalloc ){ - sqlite3DbNNFreeNN(db, p->zMalloc); + sqlite3DbFreeNN(db, p->zMalloc); p->szMalloc = 0; - p->flags = MEM_Undefined; } -#ifdef SQLITE_DEBUG - else{ - p->flags = MEM_Undefined; - } -#endif + + p->flags = MEM_Undefined; }while( (++p)iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0; - return 1; -} -#endif - - -/* -** This is a destructor on a Mem object (which is really an sqlite3_value) -** that deletes the Frame object that is attached to it as a blob. -** -** This routine does not delete the Frame right away. It merely adds the -** frame to a list of frames to be deleted when the Vdbe halts. -*/ -SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void *pArg){ - VdbeFrame *pFrame = (VdbeFrame*)pArg; - assert( sqlite3VdbeFrameIsValid(pFrame) ); - pFrame->pParent = pFrame->v->pDelFrame; - pFrame->v->pDelFrame = pFrame; -} - -#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN) -/* -** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN -** QUERY PLAN output. -** -** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no -** more opcodes to be displayed. -*/ -SQLITE_PRIVATE int sqlite3VdbeNextOpcode( - Vdbe *p, /* The statement being explained */ - Mem *pSub, /* Storage for keeping track of subprogram nesting */ - int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */ - int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */ - int *piAddr, /* OUT: Write index into (*paOp)[] here */ - Op **paOp /* OUT: Write the opcode array here */ -){ - int nRow; /* Stop when row count reaches this */ - int nSub = 0; /* Number of sub-vdbes seen so far */ - SubProgram **apSub = 0; /* Array of sub-vdbes */ - int i; /* Next instruction address */ - int rc = SQLITE_OK; /* Result code */ - Op *aOp = 0; /* Opcode array */ - int iPc; /* Rowid. Copy of value in *piPc */ - - /* When the number of output rows reaches nRow, that means the - ** listing has finished and sqlite3_step() should return SQLITE_DONE. - ** nRow is the sum of the number of rows in the main program, plus - ** the sum of the number of rows in all trigger subprograms encountered - ** so far. The nRow value will increase as new trigger subprograms are - ** encountered, but p->pc will eventually catch up to nRow. - */ - nRow = p->nOp; - if( pSub!=0 ){ - if( pSub->flags&MEM_Blob ){ - /* pSub is initiallly NULL. It is initialized to a BLOB by - ** the P4_SUBPROGRAM processing logic below */ - nSub = pSub->n/sizeof(Vdbe*); - apSub = (SubProgram **)pSub->z; - } - for(i=0; inOp; - } - } - iPc = *piPc; - while(1){ /* Loop exits via break */ - i = iPc++; - if( i>=nRow ){ - p->rc = SQLITE_OK; - rc = SQLITE_DONE; - break; - } - if( inOp ){ - /* The rowid is small enough that we are still in the - ** main program. */ - aOp = p->aOp; - }else{ - /* We are currently listing subprograms. Figure out which one and - ** pick up the appropriate opcode. */ - int j; - i -= p->nOp; - assert( apSub!=0 ); - assert( nSub>0 ); - for(j=0; i>=apSub[j]->nOp; j++){ - i -= apSub[j]->nOp; - assert( inOp || j+1aOp; - } - - /* When an OP_Program opcode is encounter (the only opcode that has - ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms - ** kept in p->aMem[9].z to hold the new program - assuming this subprogram - ** has not already been seen. - */ - if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){ - int nByte = (nSub+1)*sizeof(SubProgram*); - int j; - for(j=0; jrc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0); - if( p->rc!=SQLITE_OK ){ - rc = SQLITE_ERROR; - break; - } - apSub = (SubProgram **)pSub->z; - apSub[nSub++] = aOp[i].p4.pProgram; - MemSetTypeFlag(pSub, MEM_Blob); - pSub->n = nSub*sizeof(SubProgram*); - nRow += aOp[i].p4.pProgram->nOp; - } - } - if( eMode==0 ) break; -#ifdef SQLITE_ENABLE_BYTECODE_VTAB - if( eMode==2 ){ - Op *pOp = aOp + i; - if( pOp->opcode==OP_OpenRead ) break; - if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break; - if( pOp->opcode==OP_ReopenIdx ) break; - }else -#endif - { - assert( eMode==1 ); - if( aOp[i].opcode==OP_Explain ) break; - if( aOp[i].opcode==OP_Init && iPc>1 ) break; - } - } - *piPc = iPc; - *piAddr = i; - *paOp = aOp; - return rc; -} -#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */ - /* ** Delete a VdbeFrame object and its contents. VdbeFrame objects are ** allocated by the OP_Program opcode in sqlite3VdbeExec(). */ SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){ int i; Mem *aMem = VdbeFrameMem(p); VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; - assert( sqlite3VdbeFrameIsValid(p) ); for(i=0; inChildCsr; i++){ - if( apCsr[i] ) sqlite3VdbeFreeCursorNN(p->v, apCsr[i]); + sqlite3VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0); sqlite3DbFree(p->v->db, p); } @@ -87477,103 +73551,185 @@ ** ** When p->explain==1, each instruction is listed. When ** p->explain==2, only OP_Explain instructions are listed and these ** are shown in a different format. p->explain==2 is used to implement ** EXPLAIN QUERY PLAN. -** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers -** are also shown, so that the boundaries between the main program and -** each trigger are clear. ** ** When p->explain==1, first the main program is listed, then each of ** the trigger subprograms are listed one by one. */ SQLITE_PRIVATE int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ + int nRow; /* Stop when row count reaches this */ + int nSub = 0; /* Number of sub-vdbes seen so far */ + SubProgram **apSub = 0; /* Array of sub-vdbes */ Mem *pSub = 0; /* Memory cell hold array of subprogs */ sqlite3 *db = p->db; /* The database connection */ int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ Mem *pMem = &p->aMem[1]; /* First Mem of result set */ - int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0); - Op *aOp; /* Array of opcodes */ - Op *pOp; /* Current opcode */ assert( p->explain ); - assert( p->eVdbeState==VDBE_RUN_STATE ); + assert( p->magic==VDBE_MAGIC_RUN ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ releaseMemArray(pMem, 8); + p->pResultSet = 0; - if( p->rc==SQLITE_NOMEM ){ + if( p->rc==SQLITE_NOMEM_BKPT ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ sqlite3OomFault(db); return SQLITE_ERROR; } - if( bListSubprogs ){ + /* When the number of output rows reaches nRow, that means the + ** listing has finished and sqlite3_step() should return SQLITE_DONE. + ** nRow is the sum of the number of rows in the main program, plus + ** the sum of the number of rows in all trigger subprograms encountered + ** so far. The nRow value will increase as new trigger subprograms are + ** encountered, but p->pc will eventually catch up to nRow. + */ + nRow = p->nOp; + if( p->explain==1 ){ /* 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 ** cells. */ assert( p->nMem>9 ); pSub = &p->aMem[9]; - }else{ - pSub = 0; - } - - /* Figure out which opcode is next to display */ - rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp); - - if( rc==SQLITE_OK ){ - pOp = aOp + i; - if( AtomicLoad(&db->u1.isInterrupted) ){ - p->rc = SQLITE_INTERRUPT; - rc = SQLITE_ERROR; - sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); - }else{ - char *zP4 = sqlite3VdbeDisplayP4(db, pOp); - if( p->explain==2 ){ - sqlite3VdbeMemSetInt64(pMem, pOp->p1); - sqlite3VdbeMemSetInt64(pMem+1, pOp->p2); - sqlite3VdbeMemSetInt64(pMem+2, pOp->p3); - sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free); - assert( p->nResColumn==4 ); - }else{ - sqlite3VdbeMemSetInt64(pMem+0, i); - sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode), - -1, SQLITE_UTF8, SQLITE_STATIC); - sqlite3VdbeMemSetInt64(pMem+2, pOp->p1); - sqlite3VdbeMemSetInt64(pMem+3, pOp->p2); - sqlite3VdbeMemSetInt64(pMem+4, pOp->p3); - /* pMem+5 for p4 is done last */ - sqlite3VdbeMemSetInt64(pMem+6, pOp->p5); + if( pSub->flags&MEM_Blob ){ + /* On the first call to sqlite3_step(), pSub will hold a NULL. It is + ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */ + nSub = pSub->n/sizeof(Vdbe*); + apSub = (SubProgram **)pSub->z; + } + for(i=0; inOp; + } + } + + 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( inOp ){ + /* The output line number is small enough that we are still in the + ** main program. */ + pOp = &p->aOp[i]; + }else{ + /* We are currently listing subprograms. Figure out which one and + ** pick up the appropriate opcode. */ + int j; + i -= p->nOp; + for(j=0; i>=apSub[j]->nOp; j++){ + i -= apSub[j]->nOp; + } + pOp = &apSub[j]->aOp[i]; + } + 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*); + } + } + } + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p1; /* P1 */ + pMem++; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p2; /* P2 */ + pMem++; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p3; /* P3 */ + pMem++; + + if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; + zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); + if( zP4!=pMem->z ){ + pMem->n = 0; + sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); + }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 - { - char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4); - sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free); - } + 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 - sqlite3VdbeMemSetNull(pMem+7); + pMem->flags = MEM_Null; /* Comment */ #endif - sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free); - assert( p->nResColumn==8 ); - } - p->pResultRow = pMem; - if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM; - rc = SQLITE_ERROR; - }else{ - p->rc = SQLITE_OK; - rc = SQLITE_ROW; - } - } + } + + p->nResColumn = 8 - 4*(p->explain-1); + p->pResultSet = &p->aMem[1]; + p->rc = SQLITE_OK; + rc = SQLITE_ROW; } return rc; } #endif /* SQLITE_OMIT_EXPLAIN */ @@ -87629,13 +73785,13 @@ /* An instance of this object describes bulk memory available for use ** by subcomponents of a prepared statement. Space is allocated out ** of a ReusableSpace object by the allocSpace() routine below. */ struct ReusableSpace { - u8 *pSpace; /* Available memory */ - sqlite3_int64 nFree; /* Bytes of available memory */ - sqlite3_int64 nNeeded; /* Total bytes that could not be allocated */ + u8 *pSpace; /* Available memory */ + int nFree; /* Bytes of available memory */ + int nNeeded; /* Total bytes that could not be allocated */ }; /* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf ** from the ReusableSpace object. Return a pointer to the allocated ** memory on success. If insufficient memory is available in the @@ -87651,15 +73807,15 @@ ** statement. */ static void *allocSpace( struct ReusableSpace *p, /* Bulk memory available for allocation */ void *pBuf, /* Pointer to a prior allocation */ - sqlite3_int64 nByte /* Bytes of memory needed. */ + int nByte /* Bytes of memory needed */ ){ assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); if( pBuf==0 ){ - nByte = ROUND8P(nByte); + nByte = ROUND8(nByte); if( nByte <= p->nFree ){ p->nFree -= nByte; pBuf = &p->pSpace[p->nFree]; }else{ p->nNeeded += nByte; @@ -87672,23 +73828,22 @@ /* ** Rewind the VDBE back to the beginning in preparation for ** running it. */ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ -#if defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) int i; #endif assert( p!=0 ); - assert( p->eVdbeState==VDBE_INIT_STATE - || p->eVdbeState==VDBE_READY_STATE - || p->eVdbeState==VDBE_HALT_STATE ); + assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET ); /* There should be at least one opcode. */ assert( p->nOp>0 ); - p->eVdbeState = VDBE_READY_STATE; + /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */ + p->magic = VDBE_MAGIC_RUN; #ifdef SQLITE_DEBUG for(i=0; inMem; i++){ assert( p->aMem[i].db==p->db ); } @@ -87701,26 +73856,26 @@ p->minWriteFileFormat = 255; p->iStatement = 0; p->nFkConstraint = 0; #ifdef VDBE_PROFILE for(i=0; inOp; i++){ - p->aOp[i].nExec = 0; - p->aOp[i].nCycle = 0; + p->aOp[i].cnt = 0; + p->aOp[i].cycles = 0; } #endif } /* ** Prepare a virtual machine for execution for the first time after ** creating the virtual machine. This involves things such ** as allocating registers and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more -** calls to sqlite3VdbeExec(). +** calls to sqlite3VdbeExec(). ** ** This function may be called exactly once on each virtual machine. ** After this routine is called the VM has been "packaged" and is ready -** to run. After this routine is called, further calls to +** to run. After this routine is called, further calls to ** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects ** the Vdbe from the Parse object that helped generate it so that the ** the Vdbe becomes an independent entity and the Parse object can be ** destroyed. ** @@ -87740,22 +73895,19 @@ struct ReusableSpace x; /* Reusable bulk memory */ assert( p!=0 ); assert( p->nOp>0 ); assert( pParse!=0 ); - assert( p->eVdbeState==VDBE_INIT_STATE ); + assert( p->magic==VDBE_MAGIC_INIT ); assert( pParse==p->pParse ); - assert( pParse->db==p->db ); - p->pVList = pParse->pVList; - pParse->pVList = 0; db = p->db; assert( db->mallocFailed==0 ); nVar = pParse->nVar; nMem = pParse->nMem; nCursor = pParse->nTab; nArg = pParse->nMaxArg; - + /* Each cursor uses a memory cell. The first cursor (cursor 0) can ** use aMem[0] which is not otherwise used by the VDBE program. Allocate ** space at the end of aMem[] for cursors 1 and greater. ** See also: allocateCursor(). */ @@ -87764,52 +73916,51 @@ /* Figure out how much reusable memory is available at the end of the ** opcode array. This extra memory will be reallocated for other elements ** of the prepared statement. */ - n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ + n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ assert( x.nFree>=0 ); assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); - if( pParse->explain ){ - if( nMem<10 ) nMem = 10; - p->explain = pParse->explain; - p->nResColumn = 12 - 4*p->explain; + if( pParse->explain && nMem<10 ){ + nMem = 10; } p->expired = 0; /* Memory for registers, parameters, cursor, etc, is allocated in one or two - ** passes. On the first pass, we try to reuse unused memory at the + ** passes. On the first pass, we try to reuse unused memory at the ** end of the opcode array. If we are unable to satisfy all memory ** requirements by reusing the opcode array tail, then the second - ** pass will fill in the remainder using a fresh memory allocation. + ** pass will fill in the remainder using a fresh memory allocation. ** ** This two-pass approach that reuses as much memory as possible from ** the leftover memory at the end of the opcode array. This can significantly ** reduce the amount of memory held by a prepared statement. */ - x.nNeeded = 0; - p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem)); - p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem)); - p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*)); - p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*)); - if( x.nNeeded ){ + do { + x.nNeeded = 0; + p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); + p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); + p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); + p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); +#endif + if( x.nNeeded==0 ) break; x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); x.nFree = x.nNeeded; - if( !db->mallocFailed ){ - p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); - p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); - p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); - p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); - } - } - + }while( !db->mallocFailed ); + + p->pVList = pParse->pVList; + pParse->pVList = 0; + p->explain = pParse->explain; if( db->mallocFailed ){ p->nVar = 0; p->nCursor = 0; p->nMem = 0; }else{ @@ -87817,46 +73968,40 @@ p->nVar = (ynVar)nVar; initMemArray(p->aVar, nVar, db, MEM_Null); p->nMem = nMem; initMemArray(p->aMem, nMem, db, MEM_Undefined); memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + memset(p->anExec, 0, p->nOp*sizeof(i64)); +#endif } sqlite3VdbeRewind(p); } /* -** Close a VDBE cursor and release all the resources that cursor +** Close a VDBE cursor and release all the resources that cursor ** happens to hold. */ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ - if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx); -} -static SQLITE_NOINLINE void freeCursorWithCache(Vdbe *p, VdbeCursor *pCx){ - VdbeTxtBlbCache *pCache = pCx->pCache; - assert( pCx->colCache ); - pCx->colCache = 0; - pCx->pCache = 0; - if( pCache->pCValue ){ - sqlite3RCStrUnref(pCache->pCValue); - pCache->pCValue = 0; - } - sqlite3DbFree(p->db, pCache); - sqlite3VdbeFreeCursorNN(p, pCx); -} -SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){ - if( pCx->colCache ){ - freeCursorWithCache(p, pCx); + if( pCx==0 ){ return; } + assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE ); switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); break; } case CURTYPE_BTREE: { - assert( pCx->uc.pCursor!=0 ); - sqlite3BtreeCloseCursor(pCx->uc.pCursor); + if( pCx->isEphemeral ){ + if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx); + /* The pCx->pCursor will be close automatically, if it exists, by + ** the call above. */ + }else{ + assert( pCx->uc.pCursor!=0 ); + sqlite3BtreeCloseCursor(pCx->uc.pCursor); + } break; } #ifndef SQLITE_OMIT_VIRTUALTABLE case CURTYPE_VTAB: { sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur; @@ -87872,16 +74017,18 @@ /* ** Close all cursors in the current frame. */ static void closeCursorsInFrame(Vdbe *p){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursorNN(p, pC); - p->apCsr[i] = 0; + if( p->apCsr ){ + int i; + for(i=0; inCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } } } } /* @@ -87890,10 +74037,13 @@ ** control to the main program. */ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; closeCursorsInFrame(v); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + v->anExec = pFrame->anExec; +#endif v->aOp = pFrame->aOp; v->nOp = pFrame->nOp; v->aMem = pFrame->aMem; v->nMem = pFrame->nMem; v->apCsr = pFrame->apCsr; @@ -87908,11 +74058,11 @@ } /* ** Close all cursors. ** -** Also release any dynamic memory held by the VM in the Vdbe.aMem memory +** Also release any dynamic memory held by the VM in the Vdbe.aMem memory ** cell array. This is necessary as the memory cell array may contain ** pointers to VdbeFrame objects, which may in turn contain pointers to ** open cursors. */ static void closeAllCursors(Vdbe *p){ @@ -87923,11 +74073,13 @@ p->pFrame = 0; p->nFrame = 0; } assert( p->nFrame==0 ); closeCursorsInFrame(p); - releaseMemArray(p->aMem, p->nMem); + if( p->aMem ){ + releaseMemArray(p->aMem, p->nMem); + } while( p->pDelFrame ){ VdbeFrame *pDel = p->pDelFrame; p->pDelFrame = pDel->pParent; sqlite3VdbeFrameDelete(pDel); } @@ -87934,10 +74086,31 @@ /* Delete any auxdata allocations made by the VM */ if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0); 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 ** execution of the vdbe program so that sqlite3_column_count() can @@ -87945,16 +74118,16 @@ */ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ int n; sqlite3 *db = p->db; - if( p->nResAlloc ){ - releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); + if( p->nResColumn ){ + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); sqlite3DbFree(db, p->aColName); } n = nResColumn*COLNAME_N; - p->nResColumn = p->nResAlloc = (u16)nResColumn; + p->nResColumn = (u16)nResColumn; p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; initMemArray(p->aColName, n, db, MEM_Null); } @@ -87975,64 +74148,64 @@ const char *zName, /* Pointer to buffer containing name */ void (*xDel)(void*) /* Memory management strategy for zName */ ){ int rc; Mem *pColName; - assert( idxnResAlloc ); + assert( idxnResColumn ); assert( vardb->mallocFailed ){ assert( !zName || xDel!=SQLITE_DYNAMIC ); return SQLITE_NOMEM_BKPT; } assert( p->aColName!=0 ); - pColName = &(p->aColName[idx+var*p->nResAlloc]); + pColName = &(p->aColName[idx+var*p->nResColumn]); rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); return rc; } /* ** A read or write transaction may or may not be active on database handle ** db. If a transaction is active, commit it. If there is a ** write-transaction spanning more than one database file, this routine -** takes care of the super-journal trickery. +** takes care of the master journal trickery. */ static int vdbeCommit(sqlite3 *db, Vdbe *p){ int i; int nTrans = 0; /* Number of databases with an active write-transaction ** that are candidates for a two-phase commit using a - ** super-journal */ + ** master-journal */ int rc = SQLITE_OK; int needXcommit = 0; #ifdef SQLITE_OMIT_VIRTUALTABLE - /* With this option, sqlite3VtabSync() is defined to be simply - ** SQLITE_OK so p is not used. + /* With this option, sqlite3VtabSync() is defined to be simply + ** SQLITE_OK so p is not used. */ UNUSED_PARAMETER(p); #endif /* Before doing anything else, call the xSync() callback for any ** virtual module tables written in this transaction. This has to - ** be done before determining whether a super-journal file is + ** be done before determining whether a master journal file is ** required, as an xSync() callback may add an attached database ** to the transaction. */ rc = sqlite3VtabSync(db, p); /* This loop determines (a) if the commit hook should be invoked and - ** (b) how many database files have open write transactions, not - ** including the temp database. (b) is important because if more than - ** one database file has an open write transaction, a super-journal + ** (b) how many database files have open write transactions, not + ** including the temp database. (b) is important because if more than + ** one database file has an open write transaction, a master journal ** file is required for an atomic commit. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ + */ + for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){ - /* Whether or not a database might need a super-journal depends upon + if( sqlite3BtreeIsInTrans(pBt) ){ + /* Whether or not a database might need a master journal depends upon ** its journal mode (among other things). This matrix determines which - ** journal modes use a super-journal and which do not */ + ** journal modes use a master journal and which do not */ static const u8 aMJNeeded[] = { /* DELETE */ 1, /* PERSIST */ 1, /* OFF */ 0, /* TRUNCATE */ 1, @@ -88043,12 +74216,11 @@ needXcommit = 1; sqlite3BtreeEnter(pBt); pPager = sqlite3BtreePager(pBt); if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF && aMJNeeded[sqlite3PagerGetJournalMode(pPager)] - && sqlite3PagerIsMemdb(pPager)==0 - ){ + ){ assert( i!=1 ); nTrans++; } rc = sqlite3PagerExclusiveLock(pPager); sqlite3BtreeLeave(pBt); @@ -88066,15 +74238,15 @@ } } /* The simple case - no more than one database file (not counting the ** TEMP database) has a transaction active. There is no need for the - ** super-journal. + ** master-journal. ** ** If the return value of sqlite3BtreeGetFilename() is a zero length - ** string, it means the main database is :memory: or a temp file. In - ** that case we do not support atomic multi-file commits, so use the + ** string, it means the main database is :memory: or a temp file. In + ** that case we do not support atomic multi-file commits, so use the ** simple case then too. */ if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){ @@ -88083,11 +74255,11 @@ if( pBt ){ rc = sqlite3BtreeCommitPhaseOne(pBt, 0); } } - /* Do the commit only if all databases successfully complete phase 1. + /* Do the commit only if all databases successfully complete phase 1. ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an ** IO error while deleting or truncating a journal file. It is unlikely, ** but could happen. In this case abandon processing and return the error. */ for(i=0; rc==SQLITE_OK && inDb; i++){ @@ -88100,129 +74272,128 @@ sqlite3VtabCommit(db); } } /* The complex case - There is a multi-file write-transaction active. - ** This requires a super-journal file to ensure the transaction is + ** This requires a master journal file to ensure the transaction is ** committed atomically. */ #ifndef SQLITE_OMIT_DISKIO else{ sqlite3_vfs *pVfs = db->pVfs; - char *zSuper = 0; /* File-name for the super-journal */ + char *zMaster = 0; /* File-name for the master journal */ char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); - sqlite3_file *pSuperJrnl = 0; + sqlite3_file *pMaster = 0; i64 offset = 0; int res; int retryCount = 0; int nMainFile; - /* Select a super-journal file name */ + /* Select a master journal file name */ nMainFile = sqlite3Strlen30(zMainFile); - zSuper = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0); - if( zSuper==0 ) return SQLITE_NOMEM_BKPT; - zSuper += 4; + zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile); + if( zMaster==0 ) return SQLITE_NOMEM_BKPT; do { u32 iRandom; if( retryCount ){ if( retryCount>100 ){ - sqlite3_log(SQLITE_FULL, "MJ delete: %s", zSuper); - sqlite3OsDelete(pVfs, zSuper, 0); + sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster); + sqlite3OsDelete(pVfs, zMaster, 0); break; }else if( retryCount==1 ){ - sqlite3_log(SQLITE_FULL, "MJ collide: %s", zSuper); + sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster); } } retryCount++; sqlite3_randomness(sizeof(iRandom), &iRandom); - sqlite3_snprintf(13, &zSuper[nMainFile], "-mj%06X9%02X", + sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X", (iRandom>>8)&0xffffff, iRandom&0xff); - /* The antipenultimate character of the super-journal name must + /* The antipenultimate character of the master journal name must ** be "9" to avoid name collisions when using 8+3 filenames. */ - assert( zSuper[sqlite3Strlen30(zSuper)-3]=='9' ); - sqlite3FileSuffix3(zMainFile, zSuper); - rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res); + assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' ); + sqlite3FileSuffix3(zMainFile, zMaster); + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); }while( rc==SQLITE_OK && res ); if( rc==SQLITE_OK ){ - /* Open the super-journal. */ - rc = sqlite3OsOpenMalloc(pVfs, zSuper, &pSuperJrnl, + /* Open the master journal. */ + rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| - SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_SUPER_JOURNAL, 0 + SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0 ); } if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, zSuper-4); + sqlite3DbFree(db, zMaster); return rc; } - + /* Write the name of each database file in the transaction into the new - ** super-journal file. If an error occurs at this point close - ** and delete the super-journal file. All the individual journal files - ** still have 'null' as the super-journal pointer, so they will roll + ** master journal file. If an error occurs at this point close + ** and delete the master journal file. All the individual journal files + ** still have 'null' as the master journal pointer, so they will roll ** back independently if a failure occurs. */ for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){ + if( sqlite3BtreeIsInTrans(pBt) ){ char const *zFile = sqlite3BtreeGetJournalname(pBt); if( zFile==0 ){ continue; /* Ignore TEMP and :memory: databases */ } assert( zFile[0]!=0 ); - rc = sqlite3OsWrite(pSuperJrnl, zFile, sqlite3Strlen30(zFile)+1,offset); - offset += sqlite3Strlen30(zFile)+1; - if( rc!=SQLITE_OK ){ - sqlite3OsCloseFree(pSuperJrnl); - sqlite3OsDelete(pVfs, zSuper, 0); - sqlite3DbFree(db, zSuper-4); - return rc; - } - } - } - - /* Sync the super-journal file. If the IOCAP_SEQUENTIAL device - ** flag is set this is not required. - */ - if( 0==(sqlite3OsDeviceCharacteristics(pSuperJrnl)&SQLITE_IOCAP_SEQUENTIAL) - && SQLITE_OK!=(rc = sqlite3OsSync(pSuperJrnl, SQLITE_SYNC_NORMAL)) - ){ - sqlite3OsCloseFree(pSuperJrnl); - sqlite3OsDelete(pVfs, zSuper, 0); - sqlite3DbFree(db, zSuper-4); - return rc; - } - - /* Sync all the db files involved in the transaction. The same call - ** sets the super-journal pointer in each individual journal. If - ** an error occurs here, do not delete the super-journal file. - ** - ** If the error occurs during the first call to - ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the - ** super-journal file will be orphaned. But we cannot delete it, - ** in case the super-journal file name was written into the journal - ** file before the failure occurred. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseOne(pBt, zSuper); - } - } - sqlite3OsCloseFree(pSuperJrnl); - assert( rc!=SQLITE_BUSY ); - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, zSuper-4); - return rc; - } - - /* Delete the super-journal file. This commits the transaction. After - ** doing this the directory is synced again before any individual - ** transaction files are deleted. - */ - rc = sqlite3OsDelete(pVfs, zSuper, 1); - sqlite3DbFree(db, zSuper-4); - zSuper = 0; + rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset); + offset += sqlite3Strlen30(zFile)+1; + if( rc!=SQLITE_OK ){ + sqlite3OsCloseFree(pMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + sqlite3DbFree(db, zMaster); + return rc; + } + } + } + + /* Sync the master journal file. If the IOCAP_SEQUENTIAL device + ** flag is set this is not required. + */ + if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL) + && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL)) + ){ + sqlite3OsCloseFree(pMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Sync all the db files involved in the transaction. The same call + ** sets the master journal pointer in each individual journal. If + ** an error occurs here, do not delete the master journal file. + ** + ** If the error occurs during the first call to + ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the + ** master journal file will be orphaned. But we cannot delete it, + ** in case the master journal file name was written into the journal + ** file before the failure occurred. + */ + for(i=0; rc==SQLITE_OK && inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); + } + } + sqlite3OsCloseFree(pMaster); + assert( rc!=SQLITE_BUSY ); + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Delete the master journal file. This commits the transaction. After + ** doing this the directory is synced again before any individual + ** transaction files are deleted. + */ + rc = sqlite3OsDelete(pVfs, zMaster, 1); + sqlite3DbFree(db, zMaster); + zMaster = 0; if( rc ){ return rc; } /* All files and directories have already been synced, so the following @@ -88232,11 +74403,11 @@ ** transaction is already guaranteed, but some stray 'cold' journals ** may be lying around. Returning an error code won't help matters. */ disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); - for(i=0; inDb; i++){ + for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ sqlite3BtreeCommitPhaseTwo(pBt, 1); } } @@ -88248,11 +74419,11 @@ #endif return rc; } -/* +/* ** This routine checks that the sqlite3.nVdbeActive count variable ** matches the number of vdbe's in the list sqlite3.pVdbe that are ** currently active. An assertion fails if the two counts do not match. ** This is an internal self-check only - it is not an essential processing ** step. @@ -88270,11 +74441,11 @@ if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){ cnt++; if( p->readOnly==0 ) nWrite++; if( p->bIsReader ) nRead++; } - p = p->pVNext; + p = p->pNext; } assert( cnt==db->nVdbeActive ); assert( nWrite==db->nVdbeWrite ); assert( nRead==db->nVdbeRead ); } @@ -88284,14 +74455,14 @@ /* ** If the Vdbe passed as the first argument opened a statement-transaction, ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement -** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the +** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the ** statement transaction is committed. ** -** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. +** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. ** Otherwise SQLITE_OK. */ static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){ sqlite3 *const db = p->db; int rc = SQLITE_OK; @@ -88300,11 +74471,11 @@ assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); assert( db->nStatement>0 ); assert( p->iStatement==(db->nStatement+db->nSavepoint) ); - for(i=0; inDb; i++){ + for(i=0; inDb; i++){ int rc2 = SQLITE_OK; Btree *pBt = db->aDb[i].pBt; if( pBt ){ if( eOp==SAVEPOINT_ROLLBACK ){ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint); @@ -88327,12 +74498,12 @@ 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 + /* 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; } @@ -88345,30 +74516,29 @@ return SQLITE_OK; } /* -** This function is called when a transaction opened by the database -** handle associated with the VM passed as an argument is about to be +** This function is called when a transaction opened by the database +** handle associated with the VM passed as an argument is about to be ** committed. If there are outstanding deferred foreign key constraint ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. ** -** If there are outstanding FK violations and this function returns +** If there are outstanding FK violations and this function returns ** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY ** and write an error message to it. Then return SQLITE_ERROR. */ #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; - if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) - || (!deferred && p->nFkConstraint>0) + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) + || (!deferred && p->nFkConstraint>0) ){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; p->errorAction = OE_Abort; sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR; - return SQLITE_CONSTRAINT_FOREIGNKEY; + return SQLITE_ERROR; } return SQLITE_OK; } #endif @@ -88375,13 +74545,13 @@ /* ** This routine is called the when a VDBE tries to halt. If the VDBE ** has made changes and is in autocommit mode, then commit those ** changes. If a rollback is needed, then do the rollback. ** -** This routine is the only way to move the sqlite3eOpenState of a VM from -** SQLITE_STATE_RUN to SQLITE_STATE_HALT. It is harmless to -** call this on a VM that is in the SQLITE_STATE_HALT state. +** This routine is the only way to move the state of a VM from +** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to +** call this on a VM that is in the SQLITE_MAGIC_HALT state. ** ** Return an error code. If the commit could not complete because of ** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it ** means the close did not happen and needs to be repeated. */ @@ -88389,11 +74559,11 @@ int rc; /* Used to store transient return codes */ sqlite3 *db = p->db; /* This function contains the logic that determines if a statement or ** transaction will be committed or rolled back as a result of the - ** execution of this virtual machine. + ** execution of this virtual machine. ** ** If any of the following errors occur: ** ** SQLITE_NOMEM ** SQLITE_IOERR @@ -88403,48 +74573,44 @@ ** Then the internal cache might have been left in an inconsistent ** state. We need to rollback the statement transaction, if there is ** one, or the complete transaction if there is no statement transaction. */ - assert( p->eVdbeState==VDBE_RUN_STATE ); + if( p->magic!=VDBE_MAGIC_RUN ){ + return SQLITE_OK; + } if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; } closeAllCursors(p); checkActiveVdbeCnt(db); /* No commit or rollback needed if the program never started or if the ** SQL statement does not read or write a database file. */ - if( p->bIsReader ){ + if( p->pc>=0 && p->bIsReader ){ int mrc; /* Primary error code from p->rc */ int eStatementOp = 0; int isSpecialError; /* Set to true if a 'special' error */ /* Lock all btrees used by the statement */ sqlite3VdbeEnter(p); /* Check for one of the special errors */ - if( p->rc ){ - mrc = p->rc & 0xff; - isSpecialError = mrc==SQLITE_NOMEM - || mrc==SQLITE_IOERR - || mrc==SQLITE_INTERRUPT - || mrc==SQLITE_FULL; - }else{ - mrc = isSpecialError = 0; - } + mrc = p->rc & 0xff; + isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR + || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; if( isSpecialError ){ - /* If the query was read-only and the error code is SQLITE_INTERRUPT, - ** no rollback is necessary. Otherwise, at least a savepoint - ** transaction must be rolled back to restore the database to a + /* If the query was read-only and the error code is SQLITE_INTERRUPT, + ** no rollback is necessary. Otherwise, at least a savepoint + ** transaction must be rolled back to restore the database to a ** consistent state. ** ** Even if the statement is read-only, it is important to perform - ** a statement or transaction rollback operation. If the error + ** a statement or transaction rollback operation. If the error ** occurred while writing to the journal, sub-journal or database ** file as part of an effort to free up cache space (see function - ** pagerStress() in pager.c), the rollback is required to restore + ** pagerStress() in pager.c), the rollback is required to restore ** the pager to a consistent state. */ if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ eStatementOp = SAVEPOINT_ROLLBACK; @@ -88459,58 +74625,52 @@ } } } /* Check for immediate foreign key violations. */ - if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - (void)sqlite3VdbeCheckFk(p, 0); - } - - /* If the auto-commit flag is set and this is the only active writer - ** VM, then we do either a commit or rollback of the current transaction. - ** - ** Note: This block also runs if one of the special errors handled - ** above has occurred. - */ - if( !sqlite3VtabInSync(db) - && db->autoCommit - && db->nVdbeWrite==(p->readOnly==0) + if( p->rc==SQLITE_OK ){ + sqlite3VdbeCheckFk(p, 0); + } + + /* If the auto-commit flag is set and this is the only active writer + ** VM, then we do either a commit or rollback of the current transaction. + ** + ** Note: This block also runs if one of the special errors handled + ** above has occurred. + */ + if( !sqlite3VtabInSync(db) + && db->autoCommit + && db->nVdbeWrite==(p->readOnly==0) ){ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ sqlite3VdbeLeave(p); return SQLITE_ERROR; } rc = SQLITE_CONSTRAINT_FOREIGNKEY; - }else if( db->flags & SQLITE_CorruptRdOnly ){ - rc = SQLITE_CORRUPT; - db->flags &= ~SQLITE_CorruptRdOnly; - }else{ - /* The auto-commit flag is true, the vdbe program was successful + }else{ + /* The auto-commit flag is true, the vdbe program was successful ** or hit an 'OR FAIL' constraint and there are no deferred foreign - ** key constraints to hold up the transaction. This means a commit + ** key constraints to hold up the transaction. This means a commit ** is required. */ rc = vdbeCommit(db, p); } if( rc==SQLITE_BUSY && p->readOnly ){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ - sqlite3SystemError(db, rc); p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; }else{ db->nDeferredCons = 0; db->nDeferredImmCons = 0; - db->flags &= ~(u64)SQLITE_DeferFKs; + db->flags &= ~SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } - }else if( p->rc==SQLITE_SCHEMA && db->nVdbeActive>1 ){ - p->nChange = 0; }else{ sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; } db->nStatement = 0; @@ -88524,11 +74684,11 @@ sqlite3CloseSavepoints(db); db->autoCommit = 1; p->nChange = 0; } } - + /* If eStatementOp is non-zero, then a statement transaction needs to ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to ** do so. If this operation returns an error, and the current statement ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the ** current statement error code. @@ -88545,13 +74705,13 @@ sqlite3CloseSavepoints(db); db->autoCommit = 1; p->nChange = 0; } } - + /* If this was an INSERT, UPDATE or DELETE and no statement transaction - ** has been rolled back, update the database connection change-counter. + ** has been rolled back, update the database connection change-counter. */ if( p->changeCntOn ){ if( eStatementOp!=SAVEPOINT_ROLLBACK ){ sqlite3VdbeSetChanges(db, p->nChange); }else{ @@ -88563,24 +74723,26 @@ /* Release the locks */ sqlite3VdbeLeave(p); } /* We have successfully halted and closed the VM. Record this fact. */ - db->nVdbeActive--; - if( !p->readOnly ) db->nVdbeWrite--; - if( p->bIsReader ) db->nVdbeRead--; - assert( db->nVdbeActive>=db->nVdbeRead ); - assert( db->nVdbeRead>=db->nVdbeWrite ); - assert( db->nVdbeWrite>=0 ); - p->eVdbeState = VDBE_HALT_STATE; + if( p->pc>=0 ){ + db->nVdbeActive--; + if( !p->readOnly ) db->nVdbeWrite--; + if( p->bIsReader ) db->nVdbeRead--; + assert( db->nVdbeActive>=db->nVdbeRead ); + assert( db->nVdbeRead>=db->nVdbeWrite ); + assert( db->nVdbeWrite>=0 ); + } + p->magic = VDBE_MAGIC_HALT; checkActiveVdbeCnt(db); if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; } /* If the auto-commit flag is set to true, then any locks that were held - ** by connection db have now been released. Call sqlite3ConnectionUnlocked() + ** by connection db have now been released. Call sqlite3ConnectionUnlocked() ** to invoke any required unlock-notify callbacks. */ if( db->autoCommit ){ sqlite3ConnectionUnlocked(db); } @@ -88598,11 +74760,11 @@ p->rc = SQLITE_OK; } /* ** Copy the error code and error message belonging to the VDBE passed -** as the first argument to its database handle (so that they will be +** as the first argument to its database handle (so that they will be ** returned by calls to sqlite3_errcode() and sqlite3_errmsg()). ** ** This function does not clear the VDBE error code or message, just ** copies them to the database handle. */ @@ -88618,17 +74780,16 @@ db->bBenignMalloc--; }else if( db->pErr ){ sqlite3ValueSetNull(db->pErr); } db->errCode = rc; - db->errByteOffset = -1; return rc; } #ifdef SQLITE_ENABLE_SQLLOG /* -** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, +** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, ** invoke it. */ static void vdbeInvokeSqllog(Vdbe *v){ if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){ char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql); @@ -88651,66 +74812,55 @@ ** ** After this routine is run, the VDBE should be ready to be executed ** again. ** ** To look at it another way, this routine resets the state of the -** virtual machine from VDBE_RUN_STATE or VDBE_HALT_STATE back to -** VDBE_READY_STATE. +** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to +** VDBE_MAGIC_INIT. */ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) - int i; -#endif - sqlite3 *db; db = p->db; /* If the VM did not run to completion or if it encountered an ** error, then it might not have been halted properly. So halt ** it now. */ - if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); + sqlite3VdbeHalt(p); - /* If the VDBE has been run even partially, then transfer the error code + /* If the VDBE has be run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But ** if the VDBE has just been set to run but has not actually executed any ** instructions yet, leave the main database error information unchanged. */ if( p->pc>=0 ){ vdbeInvokeSqllog(p); - if( db->pErr || p->zErrMsg ){ - sqlite3VdbeTransferError(p); - }else{ - db->errCode = p->rc; - } - } - - /* Reset register contents and reclaim error message memory. - */ -#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 - if( p->zErrMsg ){ + 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 + ** to sqlite3_step(). For consistency (since sqlite3_step() was + ** 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; } - p->pResultRow = 0; -#ifdef SQLITE_DEBUG - p->nWrite = 0; -#endif + + /* Reclaim all memory used by the VDBE + */ + Cleanup(p); /* Save profiling information from this VDBE run. */ #ifdef VDBE_PROFILE { 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); } fprintf(out, "\n"); @@ -88724,37 +74874,33 @@ } if( pc!='\n' ) fprintf(out, "\n"); } for(i=0; inOp; i++){ char zHdr[100]; - i64 cnt = p->aOp[i].nExec; - i64 cycles = p->aOp[i].nCycle; sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", - cnt, - cycles, - cnt>0 ? cycles/cnt : 0 + p->aOp[i].cnt, + p->aOp[i].cycles, + p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 ); fprintf(out, "%s", zHdr); sqlite3VdbePrintOp(out, i, &p->aOp[i]); } fclose(out); } } #endif + p->magic = VDBE_MAGIC_RESET; return p->rc & db->errMask; } - + /* ** Clean up and delete a VDBE after execution. Return an integer which is ** the result code. Write any error message text into *pzErrMsg. */ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ int rc = SQLITE_OK; - assert( VDBE_RUN_STATE>VDBE_READY_STATE ); - assert( VDBE_HALT_STATE>VDBE_READY_STATE ); - assert( VDBE_INIT_STATEeVdbeState>=VDBE_READY_STATE ){ + if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ rc = sqlite3VdbeReset(p); assert( (rc & p->db->errMask)==rc ); } sqlite3VdbeDelete(p); return rc; @@ -88764,12 +74910,12 @@ ** If parameter iOp is less than zero, then invoke the destructor for ** all auxiliary data pointers currently cached by the VM passed as ** the first argument. ** ** Or, if iOp is greater than or equal to zero, then the destructor is -** only invoked for those auxiliary data pointers created by the user -** function invoked by the OP_Function opcode at instruction iOp of +** only invoked for those auxiliary data pointers created by the user +** function invoked by the OP_Function opcode at instruction iOp of ** VM pVdbe, and only then if: ** ** * the associated function parameter is the 32nd or later (counting ** from left to right), or ** @@ -88802,40 +74948,27 @@ ** ** The difference between this function and sqlite3VdbeDelete() is that ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with ** the database connection and frees the object itself. */ -static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ +SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; - assert( db!=0 ); assert( p->db==0 || p->db==db ); - if( p->aColName ){ - releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); - sqlite3DbNNFreeNN(db, p->aColName); - } + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } - if( p->eVdbeState!=VDBE_INIT_STATE ){ + if( p->magic!=VDBE_MAGIC_INIT ){ releaseMemArray(p->aVar, p->nVar); - if( p->pVList ) sqlite3DbNNFreeNN(db, p->pVList); - if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree); + sqlite3DbFree(db, p->pVList); + sqlite3DbFree(db, p->pFree); } vdbeFreeOpArray(db, p->aOp, p->nOp); - if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql); -#ifdef SQLITE_ENABLE_NORMALIZE - sqlite3DbFree(db, p->zNormSql); - { - DblquoteStr *pThis, *pNxt; - for(pThis=p->pDblStr; pThis; pThis=pNxt){ - pNxt = pThis->pNextStr; - sqlite3DbFree(db, pThis); - } - } -#endif + sqlite3DbFree(db, p->aColName); + sqlite3DbFree(db, p->zSql); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS { int i; for(i=0; inScan; i++){ sqlite3DbFree(db, p->aScan[i].zName); @@ -88849,39 +74982,42 @@ ** Delete an entire VDBE. */ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; - assert( p!=0 ); + if( NEVER(p==0) ) return; db = p->db; - assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); sqlite3VdbeClearObject(db, p); - if( db->pnBytesFreed==0 ){ - assert( p->ppVPrev!=0 ); - *p->ppVPrev = p->pVNext; - if( p->pVNext ){ - p->pVNext->ppVPrev = p->ppVPrev; - } - } - sqlite3DbNNFreeNN(db, p); + if( p->pPrev ){ + p->pPrev->pNext = p->pNext; + }else{ + assert( db->pVdbe==p ); + db->pVdbe = p->pNext; + } + if( p->pNext ){ + p->pNext->pPrev = p->pPrev; + } + p->magic = VDBE_MAGIC_DEAD; + p->db = 0; + sqlite3DbFreeNN(db, p); } /* ** The cursor "p" has a pending seek operation that has not yet been ** carried out. Seek the cursor now. If an error occurs, return ** the appropriate error code. */ -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){ +static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){ int res, rc; #ifdef SQLITE_TEST extern int sqlite3_search_count; #endif assert( p->deferredMoveto ); assert( p->isTable ); assert( p->eCurType==CURTYPE_BTREE ); - rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res); + rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res); if( rc ) return rc; if( res!=0 ) return SQLITE_CORRUPT_BKPT; #ifdef SQLITE_TEST sqlite3_search_count++; #endif @@ -88895,11 +75031,11 @@ ** pointed to was deleted out from under it. Or maybe the btree was ** rebalanced. Whatever the cause, try to restore "p" to the place it ** is supposed to be pointing. If the row was deleted out from under the ** cursor, set the cursor to point to a NULL row. */ -SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p){ +static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ int isDifferentRow, rc; assert( p->eCurType==CURTYPE_BTREE ); assert( p->uc.pCursor!=0 ); assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ); rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow); @@ -88911,13 +75047,45 @@ /* ** Check to ensure that the cursor is valid. Restore the cursor ** if need be. Return any I/O error from the restore operation. */ SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ - assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) ); + assert( p->eCurType==CURTYPE_BTREE ); if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return sqlite3VdbeHandleMovedCursor(p); + return handleMovedCursor(p); + } + return SQLITE_OK; +} + +/* +** Make sure the cursor p is ready to read or write the row to which it +** was last positioned. Return an error code if an OOM fault or I/O error +** prevents us from positioning the cursor to its correct position. +** +** If a MoveTo operation is pending on the given cursor, then do that +** MoveTo now. If no move is pending, check to see if the row has been +** deleted out from under the cursor and if it has, mark the row as +** a NULL row. +** +** If the cursor is already pointing to the correct row and that row has +** not been deleted out from under the cursor, then this routine is a no-op. +*/ +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ + 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); + } } return SQLITE_OK; } /* @@ -88924,11 +75092,11 @@ ** The following functions: ** ** sqlite3VdbeSerialType() ** sqlite3VdbeSerialTypeLen() ** sqlite3VdbeSerialLen() -** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02 +** sqlite3VdbeSerialPut() ** sqlite3VdbeSerialGet() ** ** encapsulate the code that serializes values for storage in SQLite ** data and index records. Each serialized value consists of a ** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned @@ -88960,21 +75128,12 @@ ** ** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions ** of SQLite will not understand those serial types. */ -#if 0 /* Inlined into the OP_MakeRecord opcode */ /* ** Return the serial-type for the value stored in pMem. -** -** This routine might convert a large MEM_IntReal value into MEM_Real. -** -** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord -** opcode in the byte-code engine. But by moving this routine in-line, we -** can omit some redundant tests and make that opcode a lot faster. So -** this routine is now only used by the STAT3 logic and STAT3 support has -** ended. The code is kept here for historical reference only. */ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ int flags = pMem->flags; u32 n; @@ -88981,17 +75140,15 @@ assert( pLen!=0 ); if( flags&MEM_Null ){ *pLen = 0; return 0; } - if( flags&(MEM_Int|MEM_IntReal) ){ + if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ # define MAX_6BYTE ((((i64)0x00008000)<<32)-1) i64 i = pMem->u.i; u64 u; - testcase( flags & MEM_Int ); - testcase( flags & MEM_IntReal ); if( i<0 ){ u = ~i; }else{ u = i; } @@ -89007,19 +75164,10 @@ if( u<=32767 ){ *pLen = 2; return 2; } if( u<=8388607 ){ *pLen = 3; return 3; } if( u<=2147483647 ){ *pLen = 4; return 4; } if( u<=MAX_6BYTE ){ *pLen = 6; return 5; } *pLen = 8; - if( flags&MEM_IntReal ){ - /* If the value is IntReal and is going to take up 8 bytes to store - ** as an integer, then we might as well make it an 8-byte floating - ** point value */ - pMem->u.r = (double)pMem->u.i; - pMem->flags &= ~MEM_IntReal; - pMem->flags |= MEM_Real; - return 7; - } return 6; } if( flags&MEM_Real ){ *pLen = 8; return 7; @@ -89031,17 +75179,16 @@ n += pMem->u.nZero; } *pLen = n; return ((n*2) + 12 + ((flags&MEM_Str)!=0)); } -#endif /* inlined into OP_MakeRecord */ /* ** The sizes for serial types less than 128 */ -SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[128] = { - /* 0 1 2 3 4 5 6 7 8 9 */ +static const u8 sqlite3SmallTypeSizes[] = { + /* 0 1 2 3 4 5 6 7 8 9 */ /* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, /* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, /* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, /* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, @@ -89060,23 +75207,23 @@ */ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){ if( serial_type>=128 ){ return (serial_type-12)/2; }else{ - assert( serial_type<12 + assert( serial_type<12 || sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 ); return sqlite3SmallTypeSizes[serial_type]; } } SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){ assert( serial_type<128 ); - return sqlite3SmallTypeSizes[serial_type]; + return sqlite3SmallTypeSizes[serial_type]; } /* -** If we are on an architecture with mixed-endian floating -** points (ex: ARM7) then swap the lower 4 bytes with the +** If we are on an architecture with mixed-endian floating +** points (ex: ARM7) then swap the lower 4 bytes with the ** upper 4 bytes. Return the result. ** ** For most architectures, this is a no-op. ** ** (later): It is reported to me that the mixed-endian problem @@ -89094,11 +75241,11 @@ ** floating point values is correct. ** ** (2007-08-30) Frank van Vugt has studied this problem closely ** and has send his findings to the SQLite developers. Frank ** writes that some Linux kernels offer floating point hardware -** emulation that uses only 32-bit mantissas instead of a full +** emulation that uses only 32-bit mantissas instead of a full ** 48-bits as required by the IEEE standard. (This is the ** CONFIG_FPE_FASTFPE option.) On such systems, floating point ** byte swapping becomes very complicated. To avoid problems, ** the necessary byte swapping is carried out using a 64-bit integer ** rather than a 64-bit float. Frank assures us that the code here @@ -89105,11 +75252,11 @@ ** works for him. We, the developers, have no way to independently ** verify this, but Frank seems to know what he is talking about ** so we trust him. */ #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in){ +static u64 floatSwap(u64 in){ union { u64 r; u32 i[2]; } u; u32 t; @@ -89118,12 +75265,63 @@ t = u.i[0]; u.i[0] = u.i[1]; u.i[1] = t; return u.r; } -#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */ +# define swapMixedEndianFloat(X) X = floatSwap(X) +#else +# define swapMixedEndianFloat(X) +#endif +/* +** Write the serialized data blob for the value stored in pMem into +** buf. It is assumed that the caller has allocated sufficient space. +** Return the number of bytes written. +** +** nBuf is the amount of space left in buf[]. The caller is responsible +** for allocating enough space to buf[] to hold the entire field, exclusive +** of the pMem->u.nZero bytes for a MEM_Zero value. +** +** Return the number of bytes actually written into buf[]. The number +** of bytes in the zero-filled tail is included in the return value only +** if those bytes were zeroed in buf[]. +*/ +SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ + u32 len; + + /* Integer and Real */ + if( serial_type<=7 && serial_type>0 ){ + u64 v; + u32 i; + if( serial_type==7 ){ + assert( sizeof(v)==sizeof(pMem->u.r) ); + memcpy(&v, &pMem->u.r, sizeof(v)); + swapMixedEndianFloat(v); + }else{ + v = pMem->u.i; + } + len = i = sqlite3SmallTypeSizes[serial_type]; + assert( i>0 ); + do{ + buf[--i] = (u8)(v&0xFF); + v >>= 8; + }while( i ); + return len; + } + + /* String or blob */ + if( serial_type>=12 ){ + assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) + == (int)sqlite3VdbeSerialTypeLen(serial_type) ); + len = pMem->n; + if( len>0 ) memcpy(buf, pMem->z, len); + return len; + } + + /* NULL or constants 0 or 1 */ + return 0; +} /* Input "x" is a sequence of unsigned characters that represent a ** big-endian integer. Return the equivalent native integer */ #define ONE_BYTE_INT(x) ((i8)(x)[0]) @@ -89132,18 +75330,18 @@ #define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) #define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) /* ** Deserialize the data blob pointed to by buf as serial type serial_type -** and store the result in pMem. +** and store the result in pMem. Return the number of bytes read. ** ** This function is implemented as two separate routines for performance. ** The few cases that require local variables are broken out into a separate ** routine so that in most cases the overhead of moving the stack pointer ** is avoided. -*/ -static void serialGet( +*/ +static u32 SQLITE_NOINLINE serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ u64 x = FOUR_BYTE_UINT(buf); @@ -89171,107 +75369,84 @@ assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); #endif assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); swapMixedEndianFloat(x); memcpy(&pMem->u.r, &x, sizeof(x)); - pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; - } -} -static int serialGet7( - const unsigned char *buf, /* Buffer to deserialize from */ - Mem *pMem /* Memory cell to write value into */ -){ - u64 x = FOUR_BYTE_UINT(buf); - u32 y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) + y; - assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->u.r, &x, sizeof(x)); - if( IsNaN(x) ){ - pMem->flags = MEM_Null; - return 1; - } - pMem->flags = MEM_Real; - return 0; -} -SQLITE_PRIVATE void sqlite3VdbeSerialGet( + pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real; + } + return 8; +} +SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ switch( serial_type ){ - 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; - return; - } + case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ case 0: { /* Null */ /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ pMem->flags = MEM_Null; - return; + break; } case 1: { /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement ** integer. */ pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return; + return 1; } case 2: { /* 2-byte signed integer */ /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit ** twos-complement integer. */ pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return; + return 2; } case 3: { /* 3-byte signed integer */ /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit ** twos-complement integer. */ pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return; + return 3; } case 4: { /* 4-byte signed integer */ /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit ** twos-complement integer. */ pMem->u.i = FOUR_BYTE_INT(buf); -#ifdef __HP_cc +#ifdef __HP_cc /* Work around a sign-extension bug in the HP compiler for HP/UX */ if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL; #endif pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return; + return 4; } case 5: { /* 6-byte signed integer */ /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit ** twos-complement integer. */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return; + return 6; } case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ /* These use local variables, so do them in a separate routine ** to avoid having to move the frame pointer in the common case */ - serialGet(buf,serial_type,pMem); - return; + return serialGet(buf,serial_type,pMem); } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */ /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */ pMem->u.i = serial_type-8; pMem->flags = MEM_Int; - return; + return 0; } default: { /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in ** length. ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and @@ -89278,24 +75453,24 @@ ** (N-13)/2 bytes in length. */ static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; pMem->z = (char *)buf; pMem->n = (serial_type-12)/2; pMem->flags = aFlag[serial_type&1]; - return; + return pMem->n; } } - return; + return 0; } /* ** This routine is used to allocate sufficient space for an UnpackedRecord ** structure large enough to be used with sqlite3VdbeRecordUnpack() if ** the first argument is a pointer to KeyInfo structure pKeyInfo. ** ** The space is either allocated using sqlite3DbMallocRaw() or from within ** the unaligned buffer passed via the second and third arguments (presumably ** stack space). If the former, then *ppFree is set to a pointer that should -** be eventually freed by the caller using sqlite3DbFree(). Or, if the +** be eventually freed by the caller using sqlite3DbFree(). Or, if the ** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL ** before returning. ** ** If an OOM error occurs, NULL is returned. */ @@ -89302,33 +75477,33 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( KeyInfo *pKeyInfo /* Description of the record */ ){ UnpackedRecord *p; /* Unpacked record to return */ int nByte; /* Number of bytes required for *p */ - nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); + nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; - p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))]; - assert( pKeyInfo->aSortFlags!=0 ); + p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; + assert( pKeyInfo->aSortOrder!=0 ); p->pKeyInfo = pKeyInfo; - p->nField = pKeyInfo->nKeyField + 1; + p->nField = pKeyInfo->nField + 1; return p; } /* -** Given the nKey-byte encoding of a record in pKey[], populate the +** Given the nKey-byte encoding of a record in pKey[], populate the ** UnpackedRecord structure indicated by the fourth argument with the ** contents of the decoded record. -*/ +*/ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( KeyInfo *pKeyInfo, /* Information about the record format */ int nKey, /* Size of the binary record */ const void *pKey, /* The binary record */ UnpackedRecord *p /* Populate this structure before returning. */ ){ const unsigned char *aKey = (const unsigned char *)pKey; - u32 d; + int d; u32 idx; /* Offset in aKey[] to read from */ u16 u; /* Unsigned loop counter */ u32 szHdr; Mem *pMem = p->aMem; @@ -89335,32 +75510,24 @@ p->default_rc = 0; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); idx = getVarint32(aKey, szHdr); d = szHdr; u = 0; - while( idxenc = pKeyInfo->enc; pMem->db = pKeyInfo->db; /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ pMem->szMalloc = 0; pMem->z = 0; - sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); - d += sqlite3VdbeSerialTypeLen(serial_type); + d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; if( (++u)>=p->nField ) break; } - if( d>(u32)nKey && u ){ - assert( CORRUPT_DB ); - /* In a corrupt record entry, the last pMem might have been set up using - ** uninitialized memory. Overwrite its value with NULL, to prevent - ** warnings from MSAN. */ - sqlite3VdbeMemSetNull(pMem-1); - } - assert( u<=pKeyInfo->nKeyField + 1 ); + assert( u<=pKeyInfo->nField + 1 ); p->nField = u; } #ifdef SQLITE_DEBUG /* @@ -89395,23 +75562,23 @@ /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ /* Compilers may complain that mem1.u.i is potentially uninitialized. ** We could initialize it, as shown here, to silence those complaints. - ** But in fact, mem1.u.i will never actually be used uninitialized, and doing + ** But in fact, mem1.u.i will never actually be used uninitialized, and doing ** the unnecessary initialization has a measurable negative performance ** impact, since this routine is a very high runner. And so, we choose ** to ignore the compiler warnings and leave this variable uninitialized. */ /* mem1.u.i = 0; // not needed, here to silence compiler warning */ - + idx1 = getVarint32(aKey1, szHdr1); if( szHdr1>98307 ) return SQLITE_CORRUPT; d1 = szHdr1; - assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); - assert( pKeyInfo->aSortFlags!=0 ); - assert( pKeyInfo->nKeyField>0 ); + assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); + assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->nField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ u32 serial_type1; /* Read the serial types for the next element in each key. */ @@ -89421,42 +75588,26 @@ ** a buffer overread. The "d1+serial_type1+2" subexpression will ** always be greater than or equal to the amount of required key space. ** Use that approximation to avoid the more expensive call to ** sqlite3VdbeSerialTypeLen() in the common case. */ - if( d1+(u64)serial_type1+2>(u64)nKey1 - && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1 - ){ - if( serial_type1>=1 - && serial_type1<=7 - && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)<=(u64)nKey1+8 - && CORRUPT_DB - ){ - return 1; /* corrupt record not detected by - ** sqlite3VdbeRecordCompareWithSkip(). Return true - ** to avoid firing the assert() */ - } + if( d1+serial_type1+2>(u32)nKey1 + && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 + ){ break; } /* Extract the values to be compared. */ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); - d1 += sqlite3VdbeSerialTypeLen(serial_type1); + d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); /* Do the comparison */ - rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], - pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0); + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); if( rc!=0 ){ assert( mem1.szMalloc==0 ); /* See comment below */ - if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) - && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null)) - ){ - rc = -rc; - } - if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){ + if( pKeyInfo->aSortOrder[i] ){ rc = -rc; /* Invert the result for DESC sort order. */ } goto debugCompareEnd; } i++; @@ -89485,20 +75636,20 @@ #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->nAllField. +** limit given by pKeyInfo->nField + pKeyInfo->nXField. ** ** 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.nKeyField or KeyInfo.nAllField values were computed +** that the KeyInfo.nField or KeyInfo.nXField values were computed ** incorrectly. */ static void vdbeAssertFieldCountWithinLimits( - int nKey, const void *pKey, /* The record to verify */ + int nKey, const void *pKey, /* The record to verify */ const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */ ){ int nField = 0; u32 szHdr; u32 idx; @@ -89511,20 +75662,20 @@ assert( szHdr<=(u32)nKey ); while( idxnAllField ); + assert( nField <= pKeyInfo->nField+pKeyInfo->nXField ); } #else # define vdbeAssertFieldCountWithinLimits(A,B,C) #endif /* ** Both *pMem1 and *pMem2 contain string values. Compare the two values ** using the collation sequence pColl. As usual, return a negative , zero -** or positive value if *pMem1 is less than, equal to or greater than +** or positive value if *pMem1 is less than, equal to or greater than ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". */ static int vdbeCompareMemString( const Mem *pMem1, const Mem *pMem2, @@ -89550,12 +75701,12 @@ if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT; rc = 0; }else{ rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2); } - sqlite3VdbeMemReleaseMalloc(&c1); - sqlite3VdbeMemReleaseMalloc(&c2); + sqlite3VdbeMemRelease(&c1); + sqlite3VdbeMemRelease(&c2); return rc; } } /* @@ -89573,11 +75724,11 @@ /* ** Compare two blobs. Return negative, zero, or positive if the first ** is less than, equal to, or greater than the second, respectively. ** If one blob is a prefix of the other, then the shorter is the lessor. */ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ +static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ int c; int n1 = pB1->n; int n2 = pB2->n; /* It is possible to have a Blob value that has some non-zero content @@ -89601,41 +75752,36 @@ c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1); if( c ) return c; return n1 - n2; } -/* The following two functions are used only within testcase() to prove -** test coverage. These functions do no exist for production builds. -** We must use separate SQLITE_NOINLINE functions here, since otherwise -** optimizer code movement causes gcov to become very confused. -*/ -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) -static int SQLITE_NOINLINE doubleLt(double a, double b){ return a8 ){ + LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; + if( xr ) return +1; + return 0; }else{ i64 y; + double s; if( r<-9223372036854775808.0 ) return +1; - if( r>=9223372036854775808.0 ) return -1; + if( r>9223372036854775807.0 ) return -1; y = (i64)r; if( iy ) return +1; - testcase( doubleLt(((double)i),r) ); - testcase( doubleLt(r,((double)i)) ); - testcase( doubleEq(r,((double)i)) ); - return (((double)i)r); + if( i>y ){ + if( y==SMALLEST_INT64 && r>0.0 ) return -1; + return +1; + } + s = (double)i; + if( sr ) return +1; + return 0; } } /* ** Compare the values contained by the two memory cells, returning @@ -89651,54 +75797,41 @@ int combined_flags; f1 = pMem1->flags; f2 = pMem2->flags; combined_flags = f1|f2; - assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) ); - + assert( (combined_flags & MEM_RowSet)==0 ); + /* If one value is NULL, it is less than the other. If both values ** are NULL, return 0. */ if( combined_flags&MEM_Null ){ return (f2&MEM_Null) - (f1&MEM_Null); } /* At least one of the two values is a number */ - if( combined_flags&(MEM_Int|MEM_Real|MEM_IntReal) ){ - testcase( combined_flags & MEM_Int ); - testcase( combined_flags & MEM_Real ); - testcase( combined_flags & MEM_IntReal ); - if( (f1 & f2 & (MEM_Int|MEM_IntReal))!=0 ){ - testcase( f1 & f2 & MEM_Int ); - testcase( f1 & f2 & MEM_IntReal ); + if( combined_flags&(MEM_Int|MEM_Real) ){ + if( (f1 & f2 & MEM_Int)!=0 ){ if( pMem1->u.i < pMem2->u.i ) return -1; if( pMem1->u.i > pMem2->u.i ) return +1; return 0; } if( (f1 & f2 & MEM_Real)!=0 ){ if( pMem1->u.r < pMem2->u.r ) return -1; if( pMem1->u.r > pMem2->u.r ) return +1; return 0; } - if( (f1&(MEM_Int|MEM_IntReal))!=0 ){ - testcase( f1 & MEM_Int ); - testcase( f1 & MEM_IntReal ); + if( (f1&MEM_Int)!=0 ){ if( (f2&MEM_Real)!=0 ){ return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r); - }else if( (f2&(MEM_Int|MEM_IntReal))!=0 ){ - if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return +1; - return 0; }else{ return -1; } } if( (f1&MEM_Real)!=0 ){ - if( (f2&(MEM_Int|MEM_IntReal))!=0 ){ - testcase( f2 & MEM_Int ); - testcase( f2 & MEM_IntReal ); + if( (f2&MEM_Int)!=0 ){ return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r); }else{ return -1; } } @@ -89715,11 +75848,11 @@ if( (f2 & MEM_Str)==0 ){ return -1; } assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed ); - assert( pMem1->enc==SQLITE_UTF8 || + assert( pMem1->enc==SQLITE_UTF8 || pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); /* The collation sequence must be defined at this point, even if ** the user deletes the collation sequence after the vdbe program is ** compiled (this was not always the case). @@ -89730,19 +75863,19 @@ return vdbeCompareMemString(pMem1, pMem2, pColl, 0); } /* If a NULL pointer was passed as the collate function, fall through ** to the blob case and use memcmp(). */ } - + /* Both values must be blobs. Compare using memcmp(). */ return sqlite3BlobCompare(pMem1, pMem2); } /* ** The first argument passed to this function is a serial-type that -** corresponds to an integer - all values between 1 and 9 inclusive +** corresponds to an integer - all values between 1 and 9 inclusive ** except 7. The second points to a buffer containing an integer value ** serialized according to serial_type. This function deserializes ** and returns the value. */ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ @@ -89780,25 +75913,25 @@ } /* ** This function compares the two table rows or index records ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero -** or positive integer if key1 is less than, equal to or +** or positive integer if key1 is less than, equal to or ** greater than key2. The {nKey1, pKey1} key must be a blob ** created by the OP_MakeRecord opcode of the VDBE. The pPKey2 ** key must be a parsed key such as obtained from ** sqlite3VdbeParseRecord. ** ** If argument bSkip is non-zero, it is assumed that the caller has already ** determined that the first fields of the keys are equal. ** -** Key1 and Key2 do not have to contain the same number of fields. If all -** fields that appear in both keys are equal, then pPKey2->default_rc is +** Key1 and Key2 do not have to contain the same number of fields. If all +** fields that appear in both keys are equal, then pPKey2->default_rc is ** returned. ** -** If database corruption is discovered, set pPKey2->errCode to -** SQLITE_CORRUPT and return 0. If an OOM error is encountered, +** If database corruption is discovered, set pPKey2->errCode to +** SQLITE_CORRUPT and return 0. If an OOM error is encountered, ** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the ** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). */ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( int nKey1, const void *pKey1, /* Left key */ @@ -89809,63 +75942,53 @@ int i; /* Index of next field to compare */ u32 szHdr1; /* Size of record header in bytes */ u32 idx1; /* Offset of first type in header */ int rc = 0; /* Return value */ Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ - KeyInfo *pKeyInfo; + KeyInfo *pKeyInfo = pPKey2->pKeyInfo; const unsigned char *aKey1 = (const unsigned char *)pKey1; Mem mem1; /* If bSkip is true, then the caller has already determined that the first ** two elements in the keys are equal. Fix the various stack variables so ** that this routine begins comparing at the second field. */ if( bSkip ){ - u32 s1 = aKey1[1]; - if( s1<0x80 ){ - idx1 = 2; - }else{ - idx1 = 1 + sqlite3GetVarint32(&aKey1[1], &s1); - } + u32 s1; + idx1 = 1 + getVarint32(&aKey1[1], s1); szHdr1 = aKey1[0]; d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1); i = 1; pRhs++; }else{ - if( (szHdr1 = aKey1[0])<0x80 ){ - idx1 = 1; - }else{ - idx1 = sqlite3GetVarint32(aKey1, &szHdr1); - } + idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; + if( d1>(unsigned)nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ + } i = 0; } - if( d1>(unsigned)nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corruption */ - } VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ - assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField + assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); - assert( pPKey2->pKeyInfo->aSortFlags!=0 ); - assert( pPKey2->pKeyInfo->nKeyField>0 ); + assert( pPKey2->pKeyInfo->aSortOrder!=0 ); + assert( pPKey2->pKeyInfo->nField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); - while( 1 /*exit-by-break*/ ){ + do{ u32 serial_type; /* RHS is an integer */ - if( pRhs->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pRhs->flags & MEM_Int ); - testcase( pRhs->flags & MEM_IntReal ); + if( pRhs->flags & MEM_Int ){ serial_type = aKey1[idx1]; testcase( serial_type==12 ); if( serial_type>=10 ){ - rc = serial_type==10 ? -1 : +1; + rc = +1; }else if( serial_type==0 ){ rc = -1; }else if( serial_type==7 ){ - serialGet7(&aKey1[d1], &mem1); + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r); }else{ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); i64 rhs = pRhs->u.i; if( lhsflags & MEM_Real ){ serial_type = aKey1[idx1]; if( serial_type>=10 ){ /* Serial types 12 or greater are strings and blobs (greater than - ** numbers). Types 10 and 11 are currently "reserved for future + ** numbers). Types 10 and 11 are currently "reserved for future ** use", so it doesn't really matter what the results of comparing - ** them to numeric values are. */ - rc = serial_type==10 ? -1 : +1; + ** them to numberic values are. */ + rc = +1; }else if( serial_type==0 ){ rc = -1; }else{ + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); if( serial_type==7 ){ - if( serialGet7(&aKey1[d1], &mem1) ){ - rc = -1; /* mem1 is a NaN */ - }else if( mem1.u.ru.r ){ + if( mem1.u.ru.r ){ rc = -1; }else if( mem1.u.r>pRhs->u.r ){ rc = +1; - }else{ - assert( rc==0 ); } }else{ - sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r); } } } /* RHS is a string */ else if( pRhs->flags & MEM_Str ){ - getVarint32NR(&aKey1[idx1], serial_type); + getVarint32(&aKey1[idx1], serial_type); testcase( serial_type==12 ); if( serial_type<12 ){ rc = -1; }else if( !(serial_type & 0x01) ){ rc = +1; }else{ mem1.n = (serial_type - 12) / 2; testcase( (d1+mem1.n)==(unsigned)nKey1 ); testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); - if( (d1+mem1.n) > (unsigned)nKey1 - || (pKeyInfo = pPKey2->pKeyInfo)->nAllField<=i - ){ + if( (d1+mem1.n) > (unsigned)nKey1 ){ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ }else if( pKeyInfo->aColl[i] ){ mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; @@ -89931,19 +76048,19 @@ &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode ); }else{ int nCmp = MIN(mem1.n, pRhs->n); rc = memcmp(&aKey1[d1], pRhs->z, nCmp); - if( rc==0 ) rc = mem1.n - pRhs->n; + if( rc==0 ) rc = mem1.n - pRhs->n; } } } /* RHS is a blob */ else if( pRhs->flags & MEM_Blob ){ assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 ); - getVarint32NR(&aKey1[idx1], serial_type); + getVarint32(&aKey1[idx1], serial_type); testcase( serial_type==12 ); if( serial_type<12 || (serial_type & 0x01) ){ rc = -1; }else{ int nStr = (serial_type - 12) / 2; @@ -89967,58 +76084,39 @@ } /* RHS is null */ else{ serial_type = aKey1[idx1]; - if( serial_type==0 - || serial_type==10 - || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0) - ){ - assert( rc==0 ); - }else{ - rc = 1; - } + rc = (serial_type!=0); } if( rc!=0 ){ - int sortFlags = pPKey2->pKeyInfo->aSortFlags[i]; - if( sortFlags ){ - if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0 - || ((sortFlags & KEYINFO_ORDER_DESC) - !=(serial_type==0 || (pRhs->flags&MEM_Null))) - ){ - rc = -rc; - } + if( pKeyInfo->aSortOrder[i] ){ + rc = -rc; } assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); assert( mem1.szMalloc==0 ); /* See comment below */ return rc; } i++; - if( i==pPKey2->nField ) break; pRhs++; d1 += sqlite3VdbeSerialTypeLen(serial_type); - if( d1>(unsigned)nKey1 ) break; idx1 += sqlite3VarintLen(serial_type); - if( idx1>=(unsigned)szHdr1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; - return 0; /* Corrupt index */ - } - } + }while( idx1<(unsigned)szHdr1 && inField && d1<=(unsigned)nKey1 ); /* No memory allocation is ever used on mem1. Prove this using ** the following assert(). If the assert() fails, it indicates a ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ assert( mem1.szMalloc==0 ); /* rc==0 here means that one or both of the keys ran out of fields and ** all the fields up to that point were equal. Return the default_rc ** value. */ - assert( CORRUPT_DB - || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) - || pPKey2->pKeyInfo->db->mallocFailed + assert( CORRUPT_DB + || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) + || pKeyInfo->db->mallocFailed ); pPKey2->eqSeen = 1; return pPKey2->default_rc; } SQLITE_PRIVATE int sqlite3VdbeRecordCompare( @@ -90028,12 +76126,12 @@ return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); } /* -** This function is an optimized version of sqlite3VdbeRecordCompare() -** that (a) the first field of pPKey2 is an integer, and (b) the +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is an integer, and (b) the ** size-of-header varint at the start of (pKey1/nKey1) fits in a single ** byte (i.e. is less than 128). ** ** To avoid concerns about buffer overreads, this routine is only used ** on schemas where the maximum valid header size is 63 bytes or less. @@ -90084,38 +76182,37 @@ x = (x<<32) | FOUR_BYTE_UINT(aKey+4); lhs = *(i64*)&x; testcase( lhs<0 ); break; } - case 8: + case 8: lhs = 0; break; case 9: lhs = 1; break; /* This case could be removed without changing the results of running - ** this code. Including it causes gcc to generate a faster switch + ** this code. Including it causes gcc to generate a faster switch ** statement (since the range of switch targets now starts at zero and ** is contiguous) but does not cause any duplicate code to be generated - ** (as gcc is clever enough to combine the two like cases). Other - ** compilers might be similar. */ + ** (as gcc is clever enough to combine the two like cases). Other + ** compilers might be similar. */ case 0: case 7: return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); default: return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); } - assert( pPKey2->u.i == pPKey2->aMem[0].u.i ); - v = pPKey2->u.i; + v = pPKey2->aMem[0].u.i; if( v>lhs ){ res = pPKey2->r1; }else if( vr2; }else if( pPKey2->nField>1 ){ - /* The first fields of the two keys are equal. Compare the trailing + /* The first fields of the two keys are equal. Compare the trailing ** fields. */ res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ @@ -90126,13 +76223,13 @@ assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) ); return res; } /* -** This function is an optimized version of sqlite3VdbeRecordCompare() +** This function is an optimized version of sqlite3VdbeRecordCompare() ** that (a) the first field of pPKey2 is a string, that (b) the first field -** uses the collation sequence BINARY and (c) that the size-of-header varint +** uses the collation sequence BINARY and (c) that the size-of-header varint ** at the start of (pKey1/nKey1) fits in a single byte. */ static int vdbeRecordCompareString( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ @@ -90140,24 +76237,15 @@ const u8 *aKey1 = (const u8*)pKey1; int serial_type; int res; assert( pPKey2->aMem[0].flags & MEM_Str ); - assert( pPKey2->aMem[0].n == pPKey2->n ); - assert( pPKey2->aMem[0].z == pPKey2->u.z ); vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); - serial_type = (signed char)(aKey1[1]); - -vrcs_restart: + getVarint32(&aKey1[1], serial_type); if( serial_type<12 ){ - if( serial_type<0 ){ - sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type); - if( serial_type>=12 ) goto vrcs_restart; - assert( CORRUPT_DB ); - } res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ - }else if( !(serial_type & 0x01) ){ + }else if( !(serial_type & 0x01) ){ res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ }else{ int nCmp; int nStr; int szHdr = aKey1[0]; @@ -90165,19 +76253,15 @@ nStr = (serial_type-12) / 2; if( (szHdr + nStr) > nKey1 ){ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ } - nCmp = MIN( pPKey2->n, nStr ); - res = memcmp(&aKey1[szHdr], pPKey2->u.z, nCmp); - - if( res>0 ){ - res = pPKey2->r2; - }else if( res<0 ){ - res = pPKey2->r1; - }else{ - res = nStr - pPKey2->n; + nCmp = MIN( pPKey2->aMem[0].n, nStr ); + res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); + + if( res==0 ){ + res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; @@ -90186,10 +76270,14 @@ }else if( res>0 ){ res = pPKey2->r2; }else{ res = pPKey2->r1; } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; } } assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) || CORRUPT_DB @@ -90205,45 +76293,37 @@ */ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ /* varintRecordCompareInt() and varintRecordCompareString() both assume ** that the size-of-header varint that occurs at the start of each record ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt() - ** also assumes that it is safe to overread a buffer by at least the + ** also assumes that it is safe to overread a buffer by at least the ** maximum possible legal header size plus 8 bytes. Because there is ** guaranteed to be at least 74 (but not 136) bytes of padding following each ** buffer passed to varintRecordCompareInt() this makes it convenient to ** limit the size of the header to 64 bytes in cases where the first field ** is an integer. ** ** 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->nAllField<=13 ){ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ int flags = p->aMem[0].flags; - if( p->pKeyInfo->aSortFlags[0] ){ - if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){ - return sqlite3VdbeRecordCompare; - } + if( p->pKeyInfo->aSortOrder[0] ){ p->r1 = 1; p->r2 = -1; }else{ p->r1 = -1; p->r2 = 1; } if( (flags & MEM_Int) ){ - p->u.i = p->aMem[0].u.i; return vdbeRecordCompareInt; } testcase( flags & MEM_Real ); testcase( flags & MEM_Null ); testcase( flags & MEM_Blob ); - if( (flags & (MEM_Real|MEM_IntReal|MEM_Null|MEM_Blob))==0 - && p->pKeyInfo->aColl[0]==0 - ){ + if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ assert( flags & MEM_Str ); - p->u.z = p->aMem[0].z; - p->n = p->aMem[0].n; return vdbeRecordCompareString; } } return sqlite3VdbeRecordCompare; @@ -90266,36 +76346,34 @@ Mem m, v; /* Get the size of the index entry. Only indices entries of less ** than 2GiB are support - anything large must be database corruption. ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so - ** this code can safely assume that nCellKey is 32-bits + ** this code can safely assume that nCellKey is 32-bits */ assert( sqlite3BtreeCursorIsValid(pCur) ); nCellKey = sqlite3BtreePayloadSize(pCur); assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m); if( rc ){ return rc; } /* The index entry must begin with a header size */ - getVarint32NR((u8*)m.z, szHdr); + (void)getVarint32((u8*)m.z, szHdr); testcase( szHdr==3 ); - testcase( szHdr==(u32)m.n ); - testcase( szHdr>0x7fffffff ); - assert( m.n>=0 ); - if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){ + testcase( szHdr==m.n ); + if( unlikely(szHdr<3 || (int)szHdr>m.n) ){ goto idx_rowid_corruption; } /* The last field of the index should be an integer - the ROWID. ** Verify that the last entry really is an integer. */ - getVarint32NR((u8*)&m.z[szHdr-1], typeRowid); + (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid); testcase( typeRowid==1 ); testcase( typeRowid==2 ); testcase( typeRowid==3 ); testcase( typeRowid==4 ); testcase( typeRowid==5 ); @@ -90312,18 +76390,18 @@ } /* Fetch the integer off the end of the index record */ sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); *rowid = v.u.i; - sqlite3VdbeMemReleaseMalloc(&m); + sqlite3VdbeMemRelease(&m); return SQLITE_OK; /* Jump here if database corruption is detected after m has been ** allocated. Free the m object and return SQLITE_CORRUPT. */ idx_rowid_corruption: testcase( m.szMalloc!=0 ); - sqlite3VdbeMemReleaseMalloc(&m); + sqlite3VdbeMemRelease(&m); return SQLITE_CORRUPT_BKPT; } /* ** Compare the key of the index entry that cursor pC is pointing to against @@ -90331,11 +76409,11 @@ ** that is negative, zero, or positive if pC is less than, equal to, ** or greater than pUnpacked. Return SQLITE_OK on success. ** ** pUnpacked is either created without a rowid or is truncated so that it ** omits the rowid at the end. The rowid at the end of the index entry -** is ignored as well. Hence, this routine only compares the prefixes +** is ignored as well. Hence, this routine only compares the prefixes ** of the keys prior to the final rowid, not the entire key. */ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( sqlite3 *db, /* Database connection */ VdbeCursor *pC, /* The cursor to compare against */ @@ -90356,24 +76434,24 @@ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; return SQLITE_CORRUPT_BKPT; } sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m); if( rc ){ return rc; } - *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0); - sqlite3VdbeMemReleaseMalloc(&m); + *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); + sqlite3VdbeMemRelease(&m); return SQLITE_OK; } /* ** This routine sets the value to be returned by subsequent calls to -** sqlite3_changes() on the database handle 'db'. +** sqlite3_changes() on the database handle 'db'. */ -SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){ +SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ assert( sqlite3_mutex_held(db->mutex) ); db->nChange = nChange; db->nTotalChange += nChange; } @@ -90392,23 +76470,15 @@ ** An expired statement means that recompilation of the statement is ** recommend. Statements expire when things happen that make their ** programs obsolete. Removing user-defined functions or collating ** sequences, or changing an authorization function are the types of ** things that make prepared statements obsolete. -** -** If iCode is 1, then expiration is advisory. The statement should -** be reprepared before being restarted, but if it is already running -** it is allowed to run to completion. -** -** Internally, this function just sets the Vdbe.expired flag on all -** prepared statements. The flag is set to 1 for an immediate expiration -** and set to 2 for an advisory expiration. */ -SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){ +SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){ Vdbe *p; - for(p = db->pVdbe; p; p=p->pVNext){ - p->expired = iCode+1; + for(p = db->pVdbe; p; p=p->pNext){ + p->expired = 1; } } /* ** Return the database associated with the Vdbe. @@ -90424,22 +76494,21 @@ 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 +** parameter iVar of VM v. Except, if the value is an SQL NULL, return ** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_* ** constants) to the value before returning it. ** ** The returned value must be freed by the caller using sqlite3ValueFree(). */ 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 - || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 ); + assert( (v->db->flags & SQLITE_EnableQPSG)==0 ); if( 0==(pMem->flags & MEM_Null) ){ sqlite3_value *pRet = sqlite3ValueNew(v->db); if( pRet ){ sqlite3VdbeMemCopy((Mem *)pRet, pMem); sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8); @@ -90455,67 +76524,18 @@ ** to sqlite3_reoptimize() that re-preparing the statement may result ** in a better query plan. */ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ assert( iVar>0 ); - assert( (v->db->flags & SQLITE_EnableQPSG)==0 - || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 ); + 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){ - const VdbeOp *pOp; -#ifdef SQLITE_ENABLE_STAT4 - if( pCtx->pVdbe==0 ) return 1; -#endif - pOp = pCtx->pVdbe->aOp + pCtx->iOp; - if( pOp->opcode==OP_PureFunc ){ - const char *zContext; - char *zMsg; - if( pOp->p5 & NC_IsCheck ){ - zContext = "a CHECK constraint"; - }else if( pOp->p5 & NC_GenCol ){ - zContext = "a generated column"; - }else{ - zContext = "an index"; - } - zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s", - pCtx->pFunc->zName, zContext); - sqlite3_result_error(pCtx, zMsg, -1); - sqlite3_free(zMsg); - return 0; - } - return 1; -} - -#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) -/* -** This Walker callback is used to help verify that calls to -** sqlite3BtreeCursorHint() with opcode BTREE_HINT_RANGE have -** byte-code register values correctly initialized. -*/ -SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_REGISTER ){ - assert( (pWalker->u.aMem[pExpr->iTable].flags & MEM_Undefined)==0 ); - } - return WRC_Continue; -} -#endif /* SQLITE_ENABLE_CURSOR_HINTS && SQLITE_DEBUG */ - #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored ** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored ** in memory obtained from sqlite3DbMalloc). @@ -90532,26 +76552,25 @@ #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* -** If the second argument is not NULL, release any allocations associated +** If the second argument is not NULL, release any allocations associated ** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord ** structure itself, using sqlite3DbFree(). ** ** This function is used to free UnpackedRecord structures allocated by ** the vdbeUnpackRecord() function found in vdbeapi.c. */ static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){ - assert( db!=0 ); if( p ){ int i; for(i=0; iaMem[i]; - if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem); + if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); } - sqlite3DbNNFreeNN(db, p); + sqlite3DbFreeNN(db, p); } } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK @@ -90566,28 +76585,17 @@ VdbeCursor *pCsr, /* Cursor to grab old.* values from */ int op, /* SQLITE_INSERT, UPDATE or DELETE */ const char *zDb, /* Database name */ Table *pTab, /* Modified table */ i64 iKey1, /* Initial key value */ - int iReg, /* Register for new.* record */ - int iBlobWrite + int iReg /* Register for new.* record */ ){ sqlite3 *db = v->db; i64 iKey2; PreUpdate preupdate; const char *zTbl = pTab->zName; static const u8 fakeSortOrder = 0; -#ifdef SQLITE_DEBUG - int nRealCol; - if( pTab->tabFlags & TF_WithoutRowid ){ - nRealCol = sqlite3PrimaryKeyIndex(pTab)->nColumn; - }else if( pTab->tabFlags & TF_HasVirtual ){ - nRealCol = pTab->nNVCol; - }else{ - nRealCol = pTab->nCol; - } -#endif assert( db->pPreUpdate==0 ); memset(&preupdate, 0, sizeof(PreUpdate)); if( HasRowid(pTab)==0 ){ iKey1 = iKey2 = 0; @@ -90598,49 +76606,38 @@ }else{ iKey2 = iKey1; } } - assert( pCsr!=0 ); - assert( pCsr->eCurType==CURTYPE_BTREE ); - assert( pCsr->nField==nRealCol - || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1) + assert( pCsr->nField==pTab->nCol + || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) ); preupdate.v = v; preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); - preupdate.keyinfo.nKeyField = pTab->nCol; - preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder; + preupdate.keyinfo.nField = pTab->nCol; + preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; - preupdate.iBlobWrite = iBlobWrite; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); - vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked); - vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked); - sqlite3VdbeMemRelease(&preupdate.oldipk); + vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked); + vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked); if( preupdate.aNew ){ int i; for(i=0; inField; i++){ sqlite3VdbeMemRelease(&preupdate.aNew[i]); } - sqlite3DbNNFreeNN(db, preupdate.aNew); - } - if( preupdate.apDflt ){ - int i; - for(i=0; inCol; i++){ - sqlite3ValueFree(preupdate.apDflt[i]); - } - sqlite3DbFree(db, preupdate.apDflt); + sqlite3DbFreeNN(db, preupdate.aNew); } } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ /************** End of vdbeaux.c *********************************************/ @@ -90660,11 +76657,10 @@ ** This file contains code use to implement APIs that are part of the ** VDBE. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ -/* #include "opcodes.h" */ #ifndef SQLITE_OMIT_DEPRECATED /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the @@ -90708,21 +76704,20 @@ */ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ sqlite3_int64 iNow; sqlite3_int64 iElapse; assert( p->startTime>0 ); + assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 ); assert( db->init.busy==0 ); assert( p->zSql!=0 ); sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); iElapse = (iNow - p->startTime)*1000000; -#ifndef SQLITE_OMIT_DEPRECATED if( db->xProfile ){ db->xProfile(db->pProfileArg, p->zSql, iElapse); } -#endif if( db->mTrace & SQLITE_TRACE_PROFILE ){ - db->trace.xV2(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse); + db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse); } p->startTime = 0; } /* ** The checkProfileCallback(DB,P) macro checks to see if a profile callback @@ -90753,13 +76748,11 @@ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); - assert( v->eVdbeState>=VDBE_READY_STATE ); - rc = sqlite3VdbeReset(v); - sqlite3VdbeDelete(v); + rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); } return rc; } @@ -90796,19 +76789,11 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; #if SQLITE_THREADSAFE - sqlite3_mutex *mutex; -#endif -#ifdef SQLITE_ENABLE_API_ARMOR - if( pStmt==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif -#if SQLITE_THREADSAFE - mutex = p->db->mutex; + sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; inVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; @@ -90856,19 +76841,14 @@ } 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){ +SQLITE_API void *sqlite3_value_pointer(sqlite3_value *pVal){ 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; + if( (p->flags & MEM_TypeMask)==(MEM_Null|MEM_Subtype) && p->eSubtype=='p' ){ + return p->u.pPtr; }else{ return 0; } } SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ @@ -90889,105 +76869,45 @@ ** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating ** point number string BLOB NULL */ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { - SQLITE_BLOB, /* 0x00 (not possible) */ - SQLITE_NULL, /* 0x01 NULL */ - SQLITE_TEXT, /* 0x02 TEXT */ - SQLITE_NULL, /* 0x03 (not possible) */ - SQLITE_INTEGER, /* 0x04 INTEGER */ - SQLITE_NULL, /* 0x05 (not possible) */ - SQLITE_INTEGER, /* 0x06 INTEGER + TEXT */ - SQLITE_NULL, /* 0x07 (not possible) */ - SQLITE_FLOAT, /* 0x08 FLOAT */ - SQLITE_NULL, /* 0x09 (not possible) */ - SQLITE_FLOAT, /* 0x0a FLOAT + TEXT */ - SQLITE_NULL, /* 0x0b (not possible) */ - SQLITE_INTEGER, /* 0x0c (not possible) */ - SQLITE_NULL, /* 0x0d (not possible) */ - SQLITE_INTEGER, /* 0x0e (not possible) */ - SQLITE_NULL, /* 0x0f (not possible) */ - SQLITE_BLOB, /* 0x10 BLOB */ - SQLITE_NULL, /* 0x11 (not possible) */ - SQLITE_TEXT, /* 0x12 (not possible) */ - SQLITE_NULL, /* 0x13 (not possible) */ - SQLITE_INTEGER, /* 0x14 INTEGER + BLOB */ - SQLITE_NULL, /* 0x15 (not possible) */ - SQLITE_INTEGER, /* 0x16 (not possible) */ - SQLITE_NULL, /* 0x17 (not possible) */ - SQLITE_FLOAT, /* 0x18 FLOAT + BLOB */ - SQLITE_NULL, /* 0x19 (not possible) */ - SQLITE_FLOAT, /* 0x1a (not possible) */ - SQLITE_NULL, /* 0x1b (not possible) */ - SQLITE_INTEGER, /* 0x1c (not possible) */ - SQLITE_NULL, /* 0x1d (not possible) */ - SQLITE_INTEGER, /* 0x1e (not possible) */ - SQLITE_NULL, /* 0x1f (not possible) */ - SQLITE_FLOAT, /* 0x20 INTREAL */ - SQLITE_NULL, /* 0x21 (not possible) */ - SQLITE_FLOAT, /* 0x22 INTREAL + TEXT */ - SQLITE_NULL, /* 0x23 (not possible) */ - SQLITE_FLOAT, /* 0x24 (not possible) */ - SQLITE_NULL, /* 0x25 (not possible) */ - SQLITE_FLOAT, /* 0x26 (not possible) */ - SQLITE_NULL, /* 0x27 (not possible) */ - SQLITE_FLOAT, /* 0x28 (not possible) */ - SQLITE_NULL, /* 0x29 (not possible) */ - SQLITE_FLOAT, /* 0x2a (not possible) */ - SQLITE_NULL, /* 0x2b (not possible) */ - SQLITE_FLOAT, /* 0x2c (not possible) */ - SQLITE_NULL, /* 0x2d (not possible) */ - SQLITE_FLOAT, /* 0x2e (not possible) */ - SQLITE_NULL, /* 0x2f (not possible) */ - SQLITE_BLOB, /* 0x30 (not possible) */ - SQLITE_NULL, /* 0x31 (not possible) */ - SQLITE_TEXT, /* 0x32 (not possible) */ - SQLITE_NULL, /* 0x33 (not possible) */ - SQLITE_FLOAT, /* 0x34 (not possible) */ - SQLITE_NULL, /* 0x35 (not possible) */ - SQLITE_FLOAT, /* 0x36 (not possible) */ - SQLITE_NULL, /* 0x37 (not possible) */ - SQLITE_FLOAT, /* 0x38 (not possible) */ - SQLITE_NULL, /* 0x39 (not possible) */ - SQLITE_FLOAT, /* 0x3a (not possible) */ - SQLITE_NULL, /* 0x3b (not possible) */ - SQLITE_FLOAT, /* 0x3c (not possible) */ - SQLITE_NULL, /* 0x3d (not possible) */ - SQLITE_FLOAT, /* 0x3e (not possible) */ - SQLITE_NULL, /* 0x3f (not possible) */ + SQLITE_BLOB, /* 0x00 */ + SQLITE_NULL, /* 0x01 */ + SQLITE_TEXT, /* 0x02 */ + SQLITE_NULL, /* 0x03 */ + SQLITE_INTEGER, /* 0x04 */ + SQLITE_NULL, /* 0x05 */ + SQLITE_INTEGER, /* 0x06 */ + SQLITE_NULL, /* 0x07 */ + SQLITE_FLOAT, /* 0x08 */ + SQLITE_NULL, /* 0x09 */ + SQLITE_FLOAT, /* 0x0a */ + SQLITE_NULL, /* 0x0b */ + SQLITE_INTEGER, /* 0x0c */ + SQLITE_NULL, /* 0x0d */ + SQLITE_INTEGER, /* 0x0e */ + SQLITE_NULL, /* 0x0f */ + SQLITE_BLOB, /* 0x10 */ + SQLITE_NULL, /* 0x11 */ + SQLITE_TEXT, /* 0x12 */ + SQLITE_NULL, /* 0x13 */ + SQLITE_INTEGER, /* 0x14 */ + SQLITE_NULL, /* 0x15 */ + SQLITE_INTEGER, /* 0x16 */ + SQLITE_NULL, /* 0x17 */ + SQLITE_FLOAT, /* 0x18 */ + SQLITE_NULL, /* 0x19 */ + SQLITE_FLOAT, /* 0x1a */ + SQLITE_NULL, /* 0x1b */ + SQLITE_INTEGER, /* 0x1c */ + SQLITE_NULL, /* 0x1d */ + SQLITE_INTEGER, /* 0x1e */ + SQLITE_NULL, /* 0x1f */ }; -#ifdef SQLITE_DEBUG - { - int eType = SQLITE_BLOB; - if( pVal->flags & MEM_Null ){ - eType = SQLITE_NULL; - }else if( pVal->flags & (MEM_Real|MEM_IntReal) ){ - eType = SQLITE_FLOAT; - }else if( pVal->flags & MEM_Int ){ - eType = SQLITE_INTEGER; - }else if( pVal->flags & MEM_Str ){ - eType = SQLITE_TEXT; - } - assert( eType == aType[pVal->flags&MEM_AffMask] ); - } -#endif return aType[pVal->flags&MEM_AffMask]; } -SQLITE_API int sqlite3_value_encoding(sqlite3_value *pVal){ - return pVal->enc; -} - -/* 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); -} - -/* Return true if a parameter value originated from an sqlite3_bind() */ -SQLITE_API int sqlite3_value_frombind(sqlite3_value *pVal){ - return (pVal->flags&MEM_FromBind)!=0; -} /* Make a copy of an sqlite3_value object */ SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ sqlite3_value *pNew; @@ -91003,13 +76923,10 @@ pNew->flags |= MEM_Ephem; if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){ sqlite3ValueFree(pNew); pNew = 0; } - }else if( pNew->flags & MEM_Null ){ - /* Do not duplicate pointer values */ - pNew->flags &= ~(MEM_Term|MEM_Subtype); } return pNew; } /* Destroy an sqlite3_value object previously obtained from @@ -91016,357 +76933,219 @@ ** sqlite3_value_dup(). */ SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ sqlite3ValueFree(pOld); } - + /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify ** the function result. ** ** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the -** result as a string or blob. Appropriate errors are set if the string/blob -** is too big or if an OOM occurs. +** result as a string or blob but if the string or blob is too large, it +** then sets the error code to SQLITE_TOOBIG ** ** The invokeValueDestructor(P,X) routine invokes destructor function X() -** on value P if P is not going to be used and need to be destroyed. +** on value P is not going to be used and need to be destroyed. */ static void setResultStrOrError( sqlite3_context *pCtx, /* Function context */ const char *z, /* String pointer */ int n, /* Bytes in string, or negative */ u8 enc, /* Encoding of z. 0 for BLOBs */ void (*xDel)(void*) /* Destructor function */ ){ - Mem *pOut = pCtx->pOut; - int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); - if( rc ){ - if( rc==SQLITE_TOOBIG ){ - sqlite3_result_error_toobig(pCtx); - }else{ - /* The only errors possible from sqlite3VdbeMemSetStr are - ** SQLITE_TOOBIG and SQLITE_NOMEM */ - assert( rc==SQLITE_NOMEM ); - sqlite3_result_error_nomem(pCtx); - } - return; - } - sqlite3VdbeChangeEncoding(pOut, pCtx->enc); - if( sqlite3VdbeMemTooBig(pOut) ){ + if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(pCtx); } } static int invokeValueDestructor( const void *p, /* Value to destroy */ void (*xDel)(void*), /* The destructor */ - sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if not NULL */ + sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */ ){ assert( xDel!=SQLITE_DYNAMIC ); if( xDel==0 ){ /* noop */ }else if( xDel==SQLITE_TRANSIENT ){ /* noop */ }else{ xDel((void*)p); } -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx!=0 ){ - sqlite3_result_error_toobig(pCtx); - } -#else - assert( pCtx!=0 ); - sqlite3_result_error_toobig(pCtx); -#endif + if( pCtx ) sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } SQLITE_API void sqlite3_result_blob( - sqlite3_context *pCtx, - const void *z, - int n, + sqlite3_context *pCtx, + const void *z, + int n, void (*xDel)(void *) ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 || n<0 ){ - invokeValueDestructor(z, xDel, pCtx); - return; - } -#endif assert( n>=0 ); assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, 0, xDel); } SQLITE_API void sqlite3_result_blob64( - sqlite3_context *pCtx, - const void *z, + sqlite3_context *pCtx, + const void *z, sqlite3_uint64 n, void (*xDel)(void *) ){ - assert( xDel!=SQLITE_DYNAMIC ); -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(z, xDel, 0); - return; - } -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( xDel!=SQLITE_DYNAMIC ); if( n>0x7fffffff ){ (void)invokeValueDestructor(z, xDel, pCtx); }else{ setResultStrOrError(pCtx, z, (int)n, 0, xDel); } } SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); } SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; + pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; + pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); } SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif 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; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(pPtr, xDestructor, 0); - return; - } -#endif - pOut = pCtx->pOut; +SQLITE_API void sqlite3_result_pointer(sqlite3_context *pCtx, void *pPtr){ + Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); - sqlite3VdbeMemRelease(pOut); - pOut->flags = MEM_Null; - sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor); + sqlite3VdbeMemSetNull(pOut); + sqlite3VdbeMemSetPointer(pOut, pPtr); } SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ - Mem *pOut; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif -#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0 - if( pCtx->pFunc!=0 - && (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0 - ){ - char zErr[200]; - sqlite3_snprintf(sizeof(zErr), zErr, - "misuse of sqlite3_result_subtype() by %s()", - pCtx->pFunc->zName); - sqlite3_result_error(pCtx, zErr, -1); - return; - } -#endif /* SQLITE_STRICT_SUBTYPE */ - pOut = pCtx->pOut; + Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; pOut->flags |= MEM_Subtype; } SQLITE_API void sqlite3_result_text( - sqlite3_context *pCtx, - const char *z, + sqlite3_context *pCtx, + const char *z, int n, void (*xDel)(void *) ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(z, xDel, 0); - return; - } -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } SQLITE_API void sqlite3_result_text64( - sqlite3_context *pCtx, - const char *z, + sqlite3_context *pCtx, + const char *z, sqlite3_uint64 n, void (*xDel)(void *), unsigned char enc ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ){ - invokeValueDestructor(z, xDel, 0); - return; - } -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 ){ - if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; - n &= ~(u64)1; - } + if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; if( n>0x7fffffff ){ (void)invokeValueDestructor(z, xDel, pCtx); }else{ setResultStrOrError(pCtx, z, (int)n, enc, xDel); - sqlite3VdbeMemZeroTerminateIfAble(pCtx->pOut); } } #ifndef SQLITE_OMIT_UTF16 SQLITE_API void sqlite3_result_text16( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16NATIVE, xDel); -} -SQLITE_API void sqlite3_result_text16be( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16BE, xDel); -} -SQLITE_API void sqlite3_result_text16le( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16LE, xDel); + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); +} +SQLITE_API void sqlite3_result_text16be( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); +} +SQLITE_API void sqlite3_result_text16le( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - Mem *pOut; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; - if( pValue==0 ){ - sqlite3_result_null(pCtx); - return; - } -#endif - pOut = pCtx->pOut; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemCopy(pOut, pValue); - sqlite3VdbeChangeEncoding(pOut, pCtx->enc); - if( sqlite3VdbeMemTooBig(pOut) ){ - sqlite3_result_error_toobig(pCtx); - } + sqlite3VdbeMemCopy(pCtx->pOut, pValue); } SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ - sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0); + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ - Mem *pOut; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return SQLITE_MISUSE_BKPT; -#endif - pOut = pCtx->pOut; + Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } -#ifndef SQLITE_OMIT_INCRBLOB sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); return SQLITE_OK; -#else - return sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); -#endif } SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - pCtx->isError = errCode ? errCode : -1; + pCtx->isError = errCode; + pCtx->fErrorOrAux = 1; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; #endif if( pCtx->pOut->flags & MEM_Null ){ - setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, - SQLITE_STATIC); + sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, + SQLITE_UTF8, SQLITE_STATIC); } } /* Force an SQLITE_TOOBIG error. */ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; - sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, + pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, SQLITE_UTF8, SQLITE_STATIC); } /* An SQLITE_NOMEM error. */ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM_BKPT; + pCtx->fErrorOrAux = 1; sqlite3OomFault(pCtx->pOut->db); } - -#ifndef SQLITE_UNTESTABLE -/* Force the INT64 value currently stored as the result to be -** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL -** test-control. -*/ -SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - if( pCtx->pOut->flags & MEM_Int ){ - pCtx->pOut->flags &= ~MEM_Int; - pCtx->pOut->flags |= MEM_IntReal; - } -} -#endif - /* -** This function is called after a transaction has been committed. It +** This function is called after a transaction has been committed. It ** invokes callbacks registered with sqlite3_wal_hook() as required. */ static int doWalCallbacks(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_WAL @@ -91376,11 +77155,11 @@ if( pBt ){ int nEntry; sqlite3BtreeEnter(pBt); nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); sqlite3BtreeLeave(pBt); - if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){ + if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); } } } #endif @@ -91391,96 +77170,86 @@ /* ** Execute the statement pStmt, either until a row of data is ready, the ** statement is completely executed or an error occurs. ** ** This routine implements the bulk of the logic behind the sqlite_step() -** API. The only thing omitted is the automatic recompile if a +** API. The only thing omitted is the automatic recompile if a ** schema change has occurred. That detail is handled by the ** outer sqlite3_step() wrapper procedure. */ static int sqlite3Step(Vdbe *p){ sqlite3 *db; int rc; assert(p); + if( p->magic!=VDBE_MAGIC_RUN ){ + /* We used to require that sqlite3_reset() be called before retrying + ** sqlite3_step() after any error or after SQLITE_DONE. But beginning + ** with version 3.7.0, we changed this so that sqlite3_reset() would + ** be called automatically instead of throwing the SQLITE_MISUSE error. + ** This "automatic-reset" change is not technically an incompatibility, + ** since any application that receives an SQLITE_MISUSE is broken by + ** definition. + ** + ** Nevertheless, some published applications that were originally written + ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE + ** returns, and those were broken by the automatic-reset change. As a + ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the + ** legacy behavior of returning SQLITE_MISUSE for cases where the + ** previous sqlite3_step() returned something other than a SQLITE_LOCKED + ** or SQLITE_BUSY error. + */ +#ifdef SQLITE_OMIT_AUTORESET + if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + sqlite3_reset((sqlite3_stmt*)p); + }else{ + return SQLITE_MISUSE_BKPT; + } +#else + sqlite3_reset((sqlite3_stmt*)p); +#endif + } + + /* Check that malloc() has not failed. If it has, return early. */ db = p->db; - if( p->eVdbeState!=VDBE_RUN_STATE ){ - restart_step: - if( p->eVdbeState==VDBE_READY_STATE ){ - if( p->expired ){ - p->rc = SQLITE_SCHEMA; - rc = SQLITE_ERROR; - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){ - /* If this statement was prepared using saved SQL and an - ** error has occurred, then return the error code in p->rc to the - ** caller. Set the error code in the database handle to the same - ** value. - */ - rc = sqlite3VdbeTransferError(p); - } - goto end_of_step; - } - - /* If there are no other statements currently running, then - ** reset the interrupt flag. This prevents a call to sqlite3_interrupt - ** from interrupting a statement that has not yet started. - */ - if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); - } - - assert( db->nVdbeWrite>0 || db->autoCommit==0 - || ((db->nDeferredCons + db->nDeferredImmCons)==0) - ); + if( db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + return SQLITE_NOMEM_BKPT; + } + + if( p->pc<=0 && p->expired ){ + p->rc = SQLITE_SCHEMA; + rc = SQLITE_ERROR; + goto end_of_step; + } + if( p->pc<0 ){ + /* If there are no other statements currently running, then + ** reset the interrupt flag. This prevents a call to sqlite3_interrupt + ** from interrupting a statement that has not yet started. + */ + if( db->nVdbeActive==0 ){ + db->u1.isInterrupted = 0; + } + + assert( db->nVdbeWrite>0 || db->autoCommit==0 + || (db->nDeferredCons==0 && db->nDeferredImmCons==0) + ); #ifndef SQLITE_OMIT_TRACE - if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 - && !db->init.busy && p->zSql ){ - sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); - }else{ - assert( p->startTime==0 ); - } -#endif - - db->nVdbeActive++; - if( p->readOnly==0 ) db->nVdbeWrite++; - if( p->bIsReader ) db->nVdbeRead++; - p->pc = 0; - p->eVdbeState = VDBE_RUN_STATE; - }else - - if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){ - /* We used to require that sqlite3_reset() be called before retrying - ** sqlite3_step() after any error or after SQLITE_DONE. But beginning - ** with version 3.7.0, we changed this so that sqlite3_reset() would - ** be called automatically instead of throwing the SQLITE_MISUSE error. - ** This "automatic-reset" change is not technically an incompatibility, - ** since any application that receives an SQLITE_MISUSE is broken by - ** definition. - ** - ** Nevertheless, some published applications that were originally written - ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE - ** returns, and those were broken by the automatic-reset change. As a - ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the - ** legacy behavior of returning SQLITE_MISUSE for cases where the - ** previous sqlite3_step() returned something other than a SQLITE_LOCKED - ** or SQLITE_BUSY error. - */ -#ifdef SQLITE_OMIT_AUTORESET - if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ - sqlite3_reset((sqlite3_stmt*)p); - }else{ - return SQLITE_MISUSE_BKPT; - } -#else - sqlite3_reset((sqlite3_stmt*)p); -#endif - assert( p->eVdbeState==VDBE_READY_STATE ); - goto restart_step; - } - } - + if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0) + && !db->init.busy && p->zSql ){ + sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); + }else{ + assert( p->startTime==0 ); + } +#endif + + db->nVdbeActive++; + if( p->readOnly==0 ) db->nVdbeWrite++; + if( p->bIsReader ) db->nVdbeRead++; + p->pc = 0; + } #ifdef SQLITE_DEBUG p->rcApp = SQLITE_OK; #endif #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ @@ -91491,48 +77260,49 @@ db->nVdbeExec++; rc = sqlite3VdbeExec(p); db->nVdbeExec--; } - if( rc==SQLITE_ROW ){ - assert( p->rc==SQLITE_OK ); - assert( db->mallocFailed==0 ); - db->errCode = SQLITE_ROW; - return SQLITE_ROW; - }else{ #ifndef SQLITE_OMIT_TRACE - /* If the statement completed successfully, invoke the profile callback */ - checkProfileCallback(db, p); + /* If the statement completed successfully, invoke the profile callback */ + if( rc!=SQLITE_ROW ) checkProfileCallback(db, p); #endif - p->pResultRow = 0; - if( rc==SQLITE_DONE && db->autoCommit ){ - assert( p->rc==SQLITE_OK ); - p->rc = doWalCallbacks(db); - if( p->rc!=SQLITE_OK ){ - rc = SQLITE_ERROR; - } - }else if( rc!=SQLITE_DONE && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){ - /* If this statement was prepared using saved SQL and an - ** error has occurred, then return the error code in p->rc to the - ** caller. Set the error code in the database handle to the same value. - */ - rc = sqlite3VdbeTransferError(p); + + if( rc==SQLITE_DONE ){ + assert( p->rc==SQLITE_OK ); + p->rc = doWalCallbacks(db); + if( p->rc!=SQLITE_OK ){ + rc = SQLITE_ERROR; } } db->errCode = rc; if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){ p->rc = SQLITE_NOMEM_BKPT; - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ) rc = p->rc; } end_of_step: - /* There are only a limited number of result codes allowed from the - ** statements prepared using the legacy sqlite3_prepare() interface */ - assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 - || rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR + /* At this point local variable rc holds the value that should be + ** returned if this statement was compiled using the legacy + ** sqlite3_prepare() interface. According to the docs, this can only + ** be one of the values in the first assert() below. Variable p->rc + ** contains the value that would be returned if sqlite3_finalize() + ** were called on statement p. + */ + assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE ); + assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp ); + if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 + && rc!=SQLITE_ROW + && rc!=SQLITE_DONE + ){ + /* If this statement was prepared using saved SQL and an + ** error has occurred, then return the error code in p->rc to the + ** caller. Set the error code in the database handle to the same value. + */ + rc = sqlite3VdbeTransferError(p); + } return (rc&db->errMask); } /* ** This is the top-level implementation of sqlite3_step(). Call @@ -91539,53 +77309,50 @@ ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ 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 */ if( vdbeSafetyNotNull(v) ){ return SQLITE_MISUSE_BKPT; } db = v->db; sqlite3_mutex_enter(db->mutex); + v->doingRerun = 0; while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ int savedPc = v->pc; - rc = sqlite3Reprepare(v); - if( rc!=SQLITE_OK ){ - /* This case occurs after failing to recompile an sql statement. - ** The error message from the SQL compiler has already been loaded - ** into the database handle. This block copies the error message - ** 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; - } + rc2 = rc = sqlite3Reprepare(v); + if( rc!=SQLITE_OK) break; sqlite3_reset(pStmt); - if( savedPc>=0 ){ - /* Setting minWriteFileFormat to 254 is a signal to the OP_Init and - ** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because it has - ** already been done once on a prior invocation that failed due to - ** SQLITE_SCHEMA. tag-20220401a */ - v->minWriteFileFormat = 254; - } + 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; } @@ -91592,13 +77359,10 @@ /* ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return 0; -#endif assert( p && p->pFunc ); return p->pFunc->pUserData; } /* @@ -91610,133 +77374,24 @@ ** parameter) of the sqlite3_create_function() and ** sqlite3_create_function16() routines that originally registered the ** application defined function. */ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return 0; -#else assert( p && p->pOut ); -#endif 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){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return 0; -#else - assert( p ); -#endif - return sqlite3_value_nochange(p->pOut); -} - -/* -** The destructor function for a ValueList object. This needs to be -** a separate function, unknowable to the application, to ensure that -** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not -** preceded by activation of IN processing via sqlite3_vtab_int() do not -** try to access a fake ValueList object inserted by a hostile extension. -*/ -SQLITE_PRIVATE void sqlite3VdbeValueListFree(void *pToDelete){ - sqlite3_free(pToDelete); -} - -/* -** Implementation of sqlite3_vtab_in_first() (if bNext==0) and -** sqlite3_vtab_in_next() (if bNext!=0). -*/ -static int valueFromValueList( - sqlite3_value *pVal, /* Pointer to the ValueList object */ - sqlite3_value **ppOut, /* Store the next value from the list here */ - int bNext /* 1 for _next(). 0 for _first() */ -){ - int rc; - ValueList *pRhs; - - *ppOut = 0; - if( pVal==0 ) return SQLITE_MISUSE_BKPT; - if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){ - return SQLITE_ERROR; - }else{ - assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == - (MEM_Null|MEM_Term|MEM_Subtype) ); - assert( pVal->eSubtype=='p' ); - assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 ); - pRhs = (ValueList*)pVal->z; - } - if( bNext ){ - rc = sqlite3BtreeNext(pRhs->pCsr, 0); - }else{ - int dummy = 0; - rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy); - assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) ); - if( sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE; - } - if( rc==SQLITE_OK ){ - u32 sz; /* Size of current row in bytes */ - Mem sMem; /* Raw content of current row */ - memset(&sMem, 0, sizeof(sMem)); - sz = sqlite3BtreePayloadSize(pRhs->pCsr); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem); - if( rc==SQLITE_OK ){ - u8 *zBuf = (u8*)sMem.z; - u32 iSerial; - sqlite3_value *pOut = pRhs->pOut; - int iOff = 1 + getVarint32(&zBuf[1], iSerial); - sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut); - pOut->enc = ENC(pOut->db); - if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){ - rc = SQLITE_NOMEM; - }else{ - *ppOut = pOut; - } - } - sqlite3VdbeMemRelease(&sMem); - } - return rc; -} - -/* -** Set the iterator value pVal to point to the first value in the set. -** Set (*ppOut) to point to this value before returning. -*/ -SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){ - return valueFromValueList(pVal, ppOut, 0); -} - -/* -** Set the iterator value pVal to point to the next value in the set. -** Set (*ppOut) to point to this value before returning. -*/ -SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){ - return valueFromValueList(pVal, ppOut, 1); -} - /* ** Return the current time for a statement. If the current time ** is requested more than once within the same run of a single prepared ** statement, the exact same time is returned for each invocation regardless ** of the amount of time that elapses between invocations. In other words, ** the time returned is always the time of the first call. */ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ int rc; -#ifndef SQLITE_ENABLE_STAT4 +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; assert( p->pVdbe!=0 ); #else sqlite3_int64 iTime = 0; sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; @@ -91745,10 +77400,32 @@ rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); if( rc ) *piTime = 0; } return *piTime; } + +/* +** The following is the implementation of an SQL function that always +** fails with an error message stating that the function is used in the +** wrong context. The sqlite3_overload_function() API might construct +** SQL function that use this routine so that the functions will exist +** for name resolution but are actually overloaded by the xFindFunction +** method of virtual tables. +*/ +SQLITE_PRIVATE void sqlite3InvalidFunction( + sqlite3_context *context, /* The function calling context */ + int NotUsed, /* Number of arguments to the function */ + sqlite3_value **NotUsed2 /* Value of each argument */ +){ + const char *zName = context->pFunc->zName; + char *zErr; + UNUSED_PARAMETER2(NotUsed, NotUsed2); + zErr = sqlite3_mprintf( + "unable to use function %s in the requested context", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); +} /* ** Create a new aggregate context for p and return a pointer to ** its pMem->z element. */ @@ -91796,15 +77473,12 @@ ** single prepared statement. The iArg values must match. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return 0; -#endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#if SQLITE_ENABLE_STAT4 +#if SQLITE_ENABLE_STAT3_OR_STAT4 if( pCtx->pVdbe==0 ) return 0; #else assert( pCtx->pVdbe!=0 ); #endif for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){ @@ -91825,24 +77499,20 @@ ** 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, - int iArg, - void *pAux, + sqlite3_context *pCtx, + int iArg, + void *pAux, void (*xDelete)(void*) ){ AuxData *pAuxData; - Vdbe *pVdbe; + Vdbe *pVdbe = pCtx->pVdbe; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCtx==0 ) return; -#endif - pVdbe= pCtx->pVdbe; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( pVdbe==0 ) goto failed; #else assert( pVdbe!=0 ); #endif @@ -91856,11 +77526,14 @@ if( !pAuxData ) goto failed; pAuxData->iAuxOp = pCtx->iOp; pAuxData->iAuxArg = iArg; pAuxData->pNextAux = pVdbe->pAuxData; pVdbe->pAuxData = pAuxData; - if( pCtx->isError==0 ) pCtx->isError = -1; + if( pCtx->fErrorOrAux==0 ){ + pCtx->isError = 0; + pCtx->fErrorOrAux = 1; + } }else if( pAuxData->xDeleteAux ){ pAuxData->xDeleteAux(pAuxData->pAux); } pAuxData->pAux = pAux; @@ -91873,11 +77546,11 @@ } } #ifndef SQLITE_OMIT_DEPRECATED /* -** Return the number of times the Step function of an aggregate has been +** Return the number of times the Step function of an aggregate has been ** called. ** ** This function is deprecated. Do not use it for new code. It is ** provide only to avoid breaking legacy code. New aggregate function ** implementations should keep their own counts within their aggregate @@ -91892,21 +77565,20 @@ /* ** Return the number of columns in the result set for the statement pStmt. */ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; - if( pVm==0 ) return 0; - return pVm->nResColumn; + return pVm ? pVm->nResColumn : 0; } /* ** Return the number of values available from the current row of the ** currently executing statement pStmt. */ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; - if( pVm==0 || pVm->pResultRow==0 ) return 0; + if( pVm==0 || pVm->pResultSet==0 ) return 0; return pVm->nResColumn; } /* ** Return a pointer to static memory containing an SQL NULL value. @@ -91919,30 +77591,29 @@ ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s ** that a Mem structure is located on an 8-byte boundary. To prevent ** these assert()s from failing, when building with SQLITE_DEBUG defined ** using gcc, we force nullMem to be 8-byte aligned using the magical ** __attribute__((aligned(8))) macro. */ - static const Mem nullMem + static const Mem nullMem #if defined(SQLITE_DEBUG) && defined(__GNUC__) - __attribute__((aligned(8))) + __attribute__((aligned(8))) #endif = { /* .u = */ {0}, - /* .z = */ (char*)0, - /* .n = */ (int)0, /* .flags = */ (u16)MEM_Null, /* .enc = */ (u8)0, /* .eSubtype = */ (u8)0, - /* .db = */ (sqlite3*)0, + /* .n = */ (int)0, + /* .z = */ (char*)0, + /* .zMalloc = */ (char*)0, /* .szMalloc = */ (int)0, /* .uTemp = */ (u32)0, - /* .zMalloc = */ (char*)0, + /* .db = */ (sqlite3*)0, /* .xDel = */ (void(*)(void*))0, #ifdef SQLITE_DEBUG /* .pScopyFrom = */ (Mem*)0, - /* .mScopyFlags= */ 0, - /* .bScopy = */ 0, + /* .pFiller = */ (void*)0, #endif }; return &nullMem; } @@ -91958,36 +77629,36 @@ pVm = (Vdbe *)pStmt; if( pVm==0 ) return (Mem*)columnNullValue(); assert( pVm->db ); sqlite3_mutex_enter(pVm->db->mutex); - if( pVm->pResultRow!=0 && inResColumn && i>=0 ){ - pOut = &pVm->pResultRow[i]; + if( pVm->pResultSet!=0 && inResColumn && i>=0 ){ + pOut = &pVm->pResultSet[i]; }else{ sqlite3Error(pVm->db, SQLITE_RANGE); pOut = (Mem*)columnNullValue(); } return pOut; } /* -** This function is called after invoking an sqlite3_value_XXX function on a +** This function is called after invoking an sqlite3_value_XXX function on a ** column value (i.e. a value returned by evaluating an SQL expression in the -** select list of a SELECT statement) that may cause a malloc() failure. If +** select list of a SELECT statement) that may cause a malloc() failure. If ** malloc() has failed, the threads mallocFailed flag is cleared and the result ** code of statement pStmt set to SQLITE_NOMEM. ** ** Specifically, this is called from within: ** ** sqlite3_column_int() ** sqlite3_column_int64() ** sqlite3_column_text() ** sqlite3_column_text16() -** sqlite3_column_double() +** sqlite3_column_real() ** sqlite3_column_bytes() ** sqlite3_column_bytes16() -** sqlite3_column_blob() +** sqiite3_column_blob() */ static void columnMallocFailure(sqlite3_stmt *pStmt) { /* If malloc() failed during an encoding conversion within an ** sqlite3_column_XXX API, then set the return code of the statement to @@ -92009,12 +77680,12 @@ */ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; val = sqlite3_value_blob( columnMem(pStmt,i) ); /* Even though there is no encoding conversion, value_blob() might - ** need to call malloc() to expand the result of a zeroblob() - ** expression. + ** need to call malloc() to expand the result of a zeroblob() + ** expression. */ columnMallocFailure(pStmt); return val; } SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ @@ -92067,36 +77738,10 @@ int iType = sqlite3_value_type( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return iType; } -/* -** Column names appropriate for EXPLAIN or EXPLAIN QUERY PLAN. -*/ -static const char * const azExplainColNames8[] = { - "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", /* EXPLAIN */ - "id", "parent", "notused", "detail" /* EQP */ -}; -static const u16 azExplainColNames16data[] = { - /* 0 */ 'a', 'd', 'd', 'r', 0, - /* 5 */ 'o', 'p', 'c', 'o', 'd', 'e', 0, - /* 12 */ 'p', '1', 0, - /* 15 */ 'p', '2', 0, - /* 18 */ 'p', '3', 0, - /* 21 */ 'p', '4', 0, - /* 24 */ 'p', '5', 0, - /* 27 */ 'c', 'o', 'm', 'm', 'e', 'n', 't', 0, - /* 35 */ 'i', 'd', 0, - /* 38 */ 'p', 'a', 'r', 'e', 'n', 't', 0, - /* 45 */ 'n', 'o', 't', 'u', 's', 'e', 'd', 0, - /* 53 */ 'd', 'e', 't', 'a', 'i', 'l', 0 -}; -static const u8 iExplainColNames16[] = { - 0, 5, 12, 15, 18, 21, 24, 27, - 35, 38, 45, 53 -}; - /* ** Convert the N-th element of pStmt->pColName[] into a string using ** xFunc() then return that string. If N is out of range, return 0. ** ** There are up to 5 names for each column. useType determines which @@ -92110,14 +77755,14 @@ ** ** If the result is not a simple column reference (if it is an expression ** or a constant) then useTypes 2, 3, and 4 return NULL. */ static const void *columnName( - sqlite3_stmt *pStmt, /* The statement */ - int N, /* Which column to get the name for */ - int useUtf16, /* True to return the name as UTF16 */ - int useType /* What type of name */ + sqlite3_stmt *pStmt, + int N, + const void *(*xFunc)(Mem*), + int useType ){ const void *ret; Vdbe *p; int n; sqlite3 *db; @@ -92125,65 +77770,44 @@ if( pStmt==0 ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif - if( N<0 ) return 0; ret = 0; p = (Vdbe *)pStmt; db = p->db; assert( db!=0 ); - sqlite3_mutex_enter(db->mutex); - - if( p->explain ){ - if( useType>0 ) goto columnName_end; - n = p->explain==1 ? 8 : 4; - if( N>=n ) goto columnName_end; - if( useUtf16 ){ - int i = iExplainColNames16[N + 8*p->explain - 8]; - ret = (void*)&azExplainColNames16data[i]; - }else{ - ret = (void*)azExplainColNames8[N + 8*p->explain - 8]; - } - goto columnName_end; - } - n = p->nResColumn; - if( NmallocFailed; + n = sqlite3_column_count(pStmt); + if( N=0 ){ N += useType*n; -#ifndef SQLITE_OMIT_UTF16 - if( useUtf16 ){ - ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); - }else -#endif - { - ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]); - } - /* A malloc may have failed inside of the _text() call. If this + sqlite3_mutex_enter(db->mutex); + assert( db->mallocFailed==0 ); + ret = xFunc(&p->aColName[N]); + /* A malloc may have failed inside of the xFunc() call. If this ** is the case, clear the mallocFailed flag and return NULL. */ - assert( db->mallocFailed==0 || db->mallocFailed==1 ); - if( db->mallocFailed > prior_mallocFailed ){ + if( db->mallocFailed ){ sqlite3OomClear(db); ret = 0; } + sqlite3_mutex_leave(db->mutex); } -columnName_end: - sqlite3_mutex_leave(db->mutex); return ret; } /* ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_NAME); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_NAME); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); } #endif /* ** Constraint: If you have ENABLE_COLUMN_METADATA then you must @@ -92198,15 +77822,17 @@ /* ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt. */ SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_DECLTYPE); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_DECLTYPE); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_OMIT_DECLTYPE */ #ifdef SQLITE_ENABLE_COLUMN_METADATA @@ -92214,101 +77840,97 @@ ** Return the name of the database from which a result column derives. ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_DATABASE); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_DATABASE); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); } #endif /* SQLITE_OMIT_UTF16 */ /* ** Return the name of the table from which a result column derives. ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_TABLE); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_TABLE); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); } #endif /* SQLITE_OMIT_UTF16 */ /* ** Return the name of the table column from which a result column derives. ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unambiguous reference to a database column. */ SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 0, COLNAME_COLUMN); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, 1, COLNAME_COLUMN); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_ENABLE_COLUMN_METADATA */ /******************************* sqlite3_bind_ *************************** -** +** ** Routines used to attach values to wildcards in a compiled SQL statement. */ /* -** Unbind the value bound to variable i in virtual machine p. This is the +** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is -** out of range, then SQLITE_RANGE is returned. Otherwise SQLITE_OK. +** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. ** ** A successful evaluation of this routine acquires the mutex on p. ** the mutex is released if any kind of error occurs. ** ** The error code stored in database p->db is overwritten with the return ** value in any case. -** -** (tag-20240917-01) If vdbeUnbind(p,(u32)(i-1)) returns SQLITE_OK, -** that means all of the the following will be true: -** -** p!=0 -** p->pVar!=0 -** i>0 -** i<=p->nVar -** -** An assert() is normally added after vdbeUnbind() to help static analyzers -** realize this. */ -static int vdbeUnbind(Vdbe *p, unsigned int i){ +static int vdbeUnbind(Vdbe *p, int i){ Mem *pVar; if( vdbeSafetyNotNull(p) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(p->db->mutex); - if( p->eVdbeState!=VDBE_READY_STATE ){ - sqlite3Error(p->db, SQLITE_MISUSE_BKPT); + if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ + sqlite3Error(p->db, SQLITE_MISUSE); sqlite3_mutex_leave(p->db->mutex); - sqlite3_log(SQLITE_MISUSE, + sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); return SQLITE_MISUSE_BKPT; } - if( i>=(unsigned int)p->nVar ){ + if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE); sqlite3_mutex_leave(p->db->mutex); return SQLITE_RANGE; } + i--; pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; - p->db->errCode = SQLITE_OK; + sqlite3Error(p->db, SQLITE_OK); - /* If the bit corresponding to this variable in Vdbe.expmask is set, then + /* If the bit corresponding to this variable in Vdbe.expmask is set, then ** binding a new value to this variable invalidates the current query plan. ** - ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host + ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host ** parameter in the WHERE clause might influence the choice of query plan ** for a statement, then the statement will be automatically recompiled, ** as if there had been a schema change, on the first sqlite3_step() call ** following any change to the bindings of that parameter. */ @@ -92324,21 +77946,20 @@ */ static int bindText( sqlite3_stmt *pStmt, /* The statement to bind against */ int i, /* Index of the parameter to bind */ const void *zData, /* Pointer to the data to be bound */ - i64 nData, /* Number of bytes of data to be bound */ + int nData, /* Number of bytes of data to be bound */ void (*xDel)(void*), /* Destructor for the data */ u8 encoding /* Encoding for the data */ ){ Vdbe *p = (Vdbe *)pStmt; Mem *pVar; int rc; - rc = vdbeUnbind(p, (u32)(i-1)); + rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ if( zData!=0 ){ pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); @@ -92358,37 +77979,40 @@ /* ** Bind a blob value to an SQL statement variable. */ SQLITE_API int sqlite3_bind_blob( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, void (*xDel)(void*) ){ #ifdef SQLITE_ENABLE_API_ARMOR if( nData<0 ) return SQLITE_MISUSE_BKPT; #endif return bindText(pStmt, i, zData, nData, xDel, 0); } SQLITE_API int sqlite3_bind_blob64( - sqlite3_stmt *pStmt, - int i, - const void *zData, - sqlite3_uint64 nData, + sqlite3_stmt *pStmt, + int i, + const void *zData, + sqlite3_uint64 nData, void (*xDel)(void*) ){ assert( xDel!=SQLITE_DYNAMIC ); - return bindText(pStmt, i, zData, nData, xDel, 0); + if( nData>0x7fffffff ){ + return invokeValueDestructor(zData, xDel, 0); + }else{ + return bindText(pStmt, i, zData, (int)nData, xDel, 0); + } } SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); + rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); sqlite3_mutex_leave(p->db->mutex); } return rc; } @@ -92396,80 +78020,70 @@ return sqlite3_bind_int64(p, i, (i64)iValue); } SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); + rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); sqlite3_mutex_leave(p->db->mutex); } return rc; } SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - sqlite3_mutex_leave(p->db->mutex); - } - 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, (u32)(i-1)); - if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ - 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, - const char *zData, - int nData, + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} +SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr); + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} +SQLITE_API int sqlite3_bind_text( + sqlite3_stmt *pStmt, + int i, + const char *zData, + int nData, void (*xDel)(void*) ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } -SQLITE_API int sqlite3_bind_text64( - sqlite3_stmt *pStmt, - int i, - const char *zData, - sqlite3_uint64 nData, +SQLITE_API int sqlite3_bind_text64( + sqlite3_stmt *pStmt, + int i, + const char *zData, + sqlite3_uint64 nData, void (*xDel)(void*), unsigned char enc ){ assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 ){ + if( nData>0x7fffffff ){ + return invokeValueDestructor(zData, xDel, 0); + }else{ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; - nData &= ~(u16)1; + return bindText(pStmt, i, zData, (int)nData, xDel, enc); } - return bindText(pStmt, i, zData, nData, xDel, enc); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API int sqlite3_bind_text16( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int n, + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, void (*xDel)(void*) ){ - return bindText(pStmt, i, zData, n & ~(u64)1, xDel, SQLITE_UTF16NATIVE); + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ @@ -92476,14 +78090,11 @@ case SQLITE_INTEGER: { rc = sqlite3_bind_int64(pStmt, i, pValue->u.i); break; } case SQLITE_FLOAT: { - assert( pValue->flags & (MEM_Real|MEM_IntReal) ); - rc = sqlite3_bind_double(pStmt, i, - (pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i - ); + rc = sqlite3_bind_double(pStmt, i, pValue->u.r); break; } case SQLITE_BLOB: { if( pValue->flags & MEM_Zero ){ rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); @@ -92505,28 +78116,20 @@ return rc; } SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, (u32)(i-1)); + rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ -#ifndef SQLITE_OMIT_INCRBLOB sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); -#else - rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); -#endif sqlite3_mutex_leave(p->db->mutex); } return rc; } SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ int rc; Vdbe *p = (Vdbe *)pStmt; -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(p->db->mutex); if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ rc = SQLITE_TOOBIG; }else{ assert( (n & 0x7FFFFFFF)==n ); @@ -92537,11 +78140,11 @@ return rc; } /* ** Return the number of wildcards that can be potentially bound to. -** This routine is added to support DBD::SQLite. +** This routine is added to support DBD::SQLite. */ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p ? p->nVar : 0; } @@ -92635,60 +78238,16 @@ */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } -/* -** Return 1 if the statement is an EXPLAIN and return 2 if the -** statement is an EXPLAIN QUERY PLAN -*/ -SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ - return pStmt ? ((Vdbe*)pStmt)->explain : 0; -} - -/* -** Set the explain mode for a statement. -*/ -SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){ - Vdbe *v = (Vdbe*)pStmt; - int rc; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pStmt==0 ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(v->db->mutex); - if( ((int)v->explain)==eMode ){ - rc = SQLITE_OK; - }else if( eMode<0 || eMode>2 ){ - rc = SQLITE_ERROR; - }else if( (v->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ - rc = SQLITE_ERROR; - }else if( v->eVdbeState!=VDBE_READY_STATE ){ - rc = SQLITE_BUSY; - }else if( v->nMem>=10 && (eMode!=2 || v->haveEqpOps) ){ - /* No reprepare necessary */ - v->explain = eMode; - rc = SQLITE_OK; - }else{ - v->explain = eMode; - rc = sqlite3Reprepare(v); - v->haveEqpOps = eMode==2; - } - if( v->explain ){ - v->nResColumn = 12 - 4*v->explain; - }else{ - v->nResColumn = v->nResAlloc; - } - sqlite3_mutex_leave(v->db->mutex); - return rc; -} - /* ** Return true if the prepared statement is in need of being reset. */ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->eVdbeState==VDBE_RUN_STATE; + return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; } /* ** Return a pointer to the next prepared statement after pStmt associated ** with database connection pDb. If pStmt is NULL, return the first @@ -92705,11 +78264,11 @@ #endif sqlite3_mutex_enter(pDb->mutex); if( pStmt==0 ){ pNext = (sqlite3_stmt*)pDb->pVdbe; }else{ - pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pVNext; + pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext; } sqlite3_mutex_leave(pDb->mutex); return pNext; } @@ -92718,27 +78277,23 @@ */ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v; #ifdef SQLITE_ENABLE_API_ARMOR - if( !pStmt - || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) - ){ + if( !pStmt ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif if( op==SQLITE_STMTSTATUS_MEMUSED ){ sqlite3 *db = pVdbe->db; sqlite3_mutex_enter(db->mutex); v = 0; db->pnBytesFreed = (int*)&v; - assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); - db->lookaside.pEnd = db->lookaside.pStart; - sqlite3VdbeDelete(pVdbe); + sqlite3VdbeClearObject(db, pVdbe); + sqlite3DbFree(db, pVdbe); db->pnBytesFreed = 0; - db->lookaside.pEnd = db->lookaside.pTrueEnd; sqlite3_mutex_leave(db->mutex); }else{ v = pVdbe->aCounter[op]; if( resetFlag ) pVdbe->aCounter[op] = 0; } @@ -92776,42 +78331,26 @@ } return z; #endif } -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** Return the normalized SQL associated with a prepared statement. -*/ -SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe *)pStmt; - if( p==0 ) return 0; - if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){ - sqlite3_mutex_enter(p->db->mutex); - p->zNormSql = sqlite3Normalize(p, p->zSql); - sqlite3_mutex_leave(p->db->mutex); - } - return p->zNormSql; -} -#endif /* SQLITE_ENABLE_NORMALIZE */ - #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Allocate and populate an UnpackedRecord structure based on the serialized ** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure ** if successful, or a NULL pointer if an OOM error is encountered. */ static UnpackedRecord *vdbeUnpackRecord( - KeyInfo *pKeyInfo, - int nKey, + KeyInfo *pKeyInfo, + int nKey, const void *pKey ){ UnpackedRecord *pRet; /* Return value */ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pRet ){ - memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); } return pRet; } @@ -92818,95 +78357,56 @@ /* ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or deleted. */ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ - PreUpdate *p; + PreUpdate *p = db->pPreUpdate; Mem *pMem; int rc = SQLITE_OK; - int iStore = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( db==0 || ppValue==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - p = db->pPreUpdate; + /* Test that this call is being made from within an SQLITE_DELETE or ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ if( !p || p->op==SQLITE_INSERT ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_old_out; } if( p->pPk ){ - iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); - }else{ - iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); + iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx); } - if( iStore>=p->pCsr->nField || iStore<0 ){ + if( iIdx>=p->pCsr->nField || iIdx<0 ){ rc = SQLITE_RANGE; goto preupdate_old_out; } + /* If the old.* record has not yet been loaded into memory, do so now. */ + if( p->pUnpacked==0 ){ + u32 nRec; + u8 *aRec; + + nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); + aRec = sqlite3DbMallocRaw(db, nRec); + if( !aRec ) goto preupdate_old_out; + 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; + } + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, aRec); + goto preupdate_old_out; + } + p->aRecord = aRec; + } + + pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; if( iIdx==p->pTab->iPKey ){ - *ppValue = pMem = &p->oldipk; sqlite3VdbeMemSetInt64(pMem, p->iKey1); - }else{ - - /* If the old.* record has not yet been loaded into memory, do so now. */ - if( p->pUnpacked==0 ){ - u32 nRec; - u8 *aRec; - - assert( p->pCsr->eCurType==CURTYPE_BTREE ); - nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); - aRec = sqlite3DbMallocRaw(db, nRec); - if( !aRec ) goto preupdate_old_out; - 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; - } - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, aRec); - goto preupdate_old_out; - } - p->aRecord = aRec; - } - - pMem = *ppValue = &p->pUnpacked->aMem[iStore]; - if( iStore>=p->pUnpacked->nField ){ - /* This occurs when the table has been extended using ALTER TABLE - ** ADD COLUMN. The value to return is the default value of the column. */ - Column *pCol = &p->pTab->aCol[iIdx]; - if( pCol->iDflt>0 ){ - if( p->apDflt==0 ){ - int nByte = sizeof(sqlite3_value*)*p->pTab->nCol; - p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte); - if( p->apDflt==0 ) goto preupdate_old_out; - } - if( p->apDflt[iIdx]==0 ){ - sqlite3_value *pVal = 0; - Expr *pDflt; - assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) ); - pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; - rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal); - if( rc==SQLITE_OK && pVal==0 ){ - rc = SQLITE_CORRUPT_BKPT; - } - p->apDflt[iIdx] = pVal; - } - *ppValue = p->apDflt[iIdx]; - }else{ - *ppValue = (sqlite3_value *)columnNullValue(); - } - }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ - if( pMem->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pMem->flags & MEM_Int ); - testcase( pMem->flags & MEM_IntReal ); - sqlite3VdbeMemRealify(pMem); - } + }else if( iIdx>=p->pUnpacked->nField ){ + *ppValue = (sqlite3_value *)columnNullValue(); + }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ + if( pMem->flags & MEM_Int ){ + sqlite3VdbeMemRealify(pMem); } } preupdate_old_out: sqlite3Error(db, rc); @@ -92918,87 +78418,51 @@ /* ** This function is called from within a pre-update callback to retrieve ** the number of columns in the row being updated, deleted or inserted. */ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ - PreUpdate *p; -#ifdef SQLITE_ENABLE_API_ARMOR - p = db!=0 ? db->pPreUpdate : 0; -#else - p = db->pPreUpdate; -#endif - return (p ? p->keyinfo.nKeyField : 0); + PreUpdate *p = db->pPreUpdate; + return (p ? p->keyinfo.nField : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is designed to be called from within a pre-update callback ** only. It returns zero if the change that caused the callback was made ** immediately by a user SQL statement. Or, if the change was made by a ** trigger program, it returns the number of trigger programs currently -** on the stack (1 for a top-level trigger, 2 for a trigger fired by a +** on the stack (1 for a top-level trigger, 2 for a trigger fired by a ** top-level trigger etc.). ** ** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL ** or SET DEFAULT action is considered a trigger. */ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ - PreUpdate *p; -#ifdef SQLITE_ENABLE_API_ARMOR - p = db!=0 ? db->pPreUpdate : 0; -#else - p = db->pPreUpdate; -#endif + PreUpdate *p = db->pPreUpdate; return (p ? p->v->nFrame : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -/* -** This function is designed to be called from within a pre-update callback -** only. -*/ -SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ - PreUpdate *p; -#ifdef SQLITE_ENABLE_API_ARMOR - p = db!=0 ? db->pPreUpdate : 0; -#else - p = db->pPreUpdate; -#endif - return (p ? p->iBlobWrite : -1); -} -#endif - #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or inserted. */ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ - PreUpdate *p; + PreUpdate *p = db->pPreUpdate; int rc = SQLITE_OK; Mem *pMem; - int iStore = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( db==0 || ppValue==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - p = db->pPreUpdate; + if( !p || p->op==SQLITE_DELETE ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_new_out; } if( p->pPk && p->op!=SQLITE_UPDATE ){ - iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); - }else{ - iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); + iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx); } - - if( iStore>=p->pCsr->nField || iStore<0 ){ + if( iIdx>=p->pCsr->nField || iIdx<0 ){ rc = SQLITE_RANGE; goto preupdate_new_out; } if( p->op==SQLITE_INSERT ){ @@ -93014,18 +78478,18 @@ rc = SQLITE_NOMEM; goto preupdate_new_out; } p->pNewUnpacked = pUnpack; } - pMem = &pUnpack->aMem[iStore]; + pMem = &pUnpack->aMem[iIdx]; if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); - }else if( iStore>=pUnpack->nField ){ + }else if( iIdx>=pUnpack->nField ){ pMem = (sqlite3_value *)columnNullValue(); } }else{ - /* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required + /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required ** value. Make a copy of the cell contents and return a pointer to it. ** It is not safe to return a pointer to the memory cell itself as the ** caller may modify the value text encoding. */ assert( p->op==SQLITE_UPDATE ); @@ -93034,17 +78498,17 @@ if( !p->aNew ){ rc = SQLITE_NOMEM; goto preupdate_new_out; } } - assert( iStore>=0 && iStorepCsr->nField ); - pMem = &p->aNew[iStore]; + assert( iIdx>=0 && iIdxpCsr->nField ); + pMem = &p->aNew[iIdx]; if( pMem->flags==0 ){ if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); }else{ - rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iStore]); + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); if( rc!=SQLITE_OK ) goto preupdate_new_out; } } } *ppValue = pMem; @@ -93057,83 +78521,27 @@ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Return status data for a single loop within query pStmt. */ -SQLITE_API int sqlite3_stmt_scanstatus_v2( +SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement being queried */ - int iScan, /* Index of loop to report on */ + int idx, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ - int flags, void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; - VdbeOp *aOp; - int nOp; - ScanStatus *pScan = 0; - int idx; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 || pOut==0 - || iScanStatusOpSQLITE_SCANSTAT_NCYCLE ){ - return 1; - } -#endif - aOp = p->aOp; - nOp = p->nOp; - if( p->pFrame ){ - VdbeFrame *pFrame; - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - aOp = pFrame->aOp; - nOp = pFrame->nOp; - } - - if( iScan<0 ){ - int ii; - if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){ - i64 res = 0; - for(ii=0; iinScan; idx++){ - pScan = &p->aScan[idx]; - if( pScan->zName ){ - iScan--; - if( iScan<0 ) break; - } - } - } - if( idx>=p->nScan ) return 1; - assert( pScan==0 || pScan==&p->aScan[idx] ); - pScan = &p->aScan[idx]; - + ScanStatus *pScan; + if( idx<0 || idx>=p->nScan ) return 1; + pScan = &p->aScan[idx]; switch( iScanStatusOp ){ case SQLITE_SCANSTAT_NLOOP: { - if( pScan->addrLoop>0 ){ - *(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec; - }else{ - *(sqlite3_int64*)pOut = -1; - } + *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop]; break; } case SQLITE_SCANSTAT_NVISIT: { - if( pScan->addrVisit>0 ){ - *(sqlite3_int64*)pOut = aOp[pScan->addrVisit].nExec; - }else{ - *(sqlite3_int64*)pOut = -1; - } + *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit]; break; } case SQLITE_SCANSTAT_EST: { double r = 1.0; LogEst x = pScan->nEst; @@ -93148,93 +78556,37 @@ *(const char**)pOut = pScan->zName; break; } case SQLITE_SCANSTAT_EXPLAIN: { if( pScan->addrExplain ){ - *(const char**)pOut = aOp[ pScan->addrExplain ].p4.z; + *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; }else{ *(const char**)pOut = 0; } break; } case SQLITE_SCANSTAT_SELECTID: { if( pScan->addrExplain ){ - *(int*)pOut = aOp[ pScan->addrExplain ].p1; - }else{ - *(int*)pOut = -1; - } - break; - } - case SQLITE_SCANSTAT_PARENTID: { - if( pScan->addrExplain ){ - *(int*)pOut = aOp[ pScan->addrExplain ].p2; - }else{ - *(int*)pOut = -1; - } - break; - } - case SQLITE_SCANSTAT_NCYCLE: { - i64 res = 0; - if( pScan->aAddrRange[0]==0 ){ - res = -1; - }else{ - int ii; - for(ii=0; iiaAddrRange); ii+=2){ - int iIns = pScan->aAddrRange[ii]; - int iEnd = pScan->aAddrRange[ii+1]; - if( iIns==0 ) break; - if( iIns>0 ){ - while( iIns<=iEnd ){ - res += aOp[iIns].nCycle; - iIns++; - } - }else{ - int iOp; - for(iOp=0; iOpp1!=iEnd ) continue; - if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){ - continue; - } - res += aOp[iOp].nCycle; - } - } - } - } - *(i64*)pOut = res; - break; - } - default: { - return 1; - } - } - return 0; -} - -/* -** Return status data for a single loop within query pStmt. -*/ -SQLITE_API int sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, /* Prepared statement being queried */ - int iScan, /* Index of loop to report on */ - int iScanStatusOp, /* Which metric to return */ - void *pOut /* OUT: Write the answer here */ -){ - return sqlite3_stmt_scanstatus_v2(pStmt, iScan, iScanStatusOp, 0, pOut); + *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; + }else{ + *(int*)pOut = -1; + } + break; + } + default: { + return 1; + } + } + return 0; } /* ** Zero all counters associated with the sqlite3_stmt_scanstatus() data. */ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; - int ii; - for(ii=0; p!=0 && iinOp; ii++){ - Op *pOp = &p->aOp[ii]; - pOp->nExec = 0; - pOp->nCycle = 0; - } + memset(p->anExec, 0, p->nOp * sizeof(i64)); } #endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ /************** End of vdbeapi.c *********************************************/ /************** Begin file vdbetrace.c ***************************************/ @@ -93286,12 +78638,12 @@ } /* ** This function returns a pointer to a nul-terminated string in memory ** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the -** string contains a copy of zRawSql but with host parameters expanded to -** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, +** string contains a copy of zRawSql but with host parameters expanded to +** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, ** then the returned string holds a copy of zRawSql with "-- " prepended ** to each line of text. ** ** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then ** then long strings and blobs are truncated to that many bytes. This @@ -93320,30 +78672,32 @@ int nToken; /* Length of the parameter token */ int i; /* Loop counter */ Mem *pVar; /* Value of a host parameter */ StrAccum out; /* Accumulate the output here */ #ifndef SQLITE_OMIT_UTF16 - Mem utf8; /* Used to convert UTF16 into UTF8 for display */ + Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */ #endif + char zBase[100]; /* Initial working space */ db = p->db; - sqlite3StrAccumInit(&out, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); + sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase), + db->aLimit[SQLITE_LIMIT_LENGTH]); if( db->nVdbeExec>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); - sqlite3_str_append(&out, "-- ", 3); + sqlite3StrAccumAppend(&out, "-- ", 3); assert( (zRawSql - zStart) > 0 ); - sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart)); + sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } }else if( p->nVar==0 ){ - sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql)); + sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); assert( n>0 ); - sqlite3_str_append(&out, zRawSql, n); + sqlite3StrAccumAppend(&out, zRawSql, n); zRawSql += n; assert( zRawSql[0] || nToken==0 ); if( nToken==0 ) break; if( zRawSql[0]=='?' ){ if( nToken>1 ){ @@ -93361,29 +78715,29 @@ testcase( zRawSql[0]=='#' ); idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); assert( idx>0 ); } zRawSql += nToken; - nextIndex = MAX(idx + 1, nextIndex); + nextIndex = idx + 1; assert( idx>0 && idx<=p->nVar ); pVar = &p->aVar[idx-1]; if( pVar->flags & MEM_Null ){ - sqlite3_str_append(&out, "NULL", 4); - }else if( pVar->flags & (MEM_Int|MEM_IntReal) ){ - sqlite3_str_appendf(&out, "%lld", pVar->u.i); + sqlite3StrAccumAppend(&out, "NULL", 4); + }else if( pVar->flags & MEM_Int ){ + sqlite3XPrintf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ - sqlite3_str_appendf(&out, "%!.15g", pVar->u.r); + sqlite3XPrintf(&out, "%!.15g", pVar->u.r); }else if( pVar->flags & MEM_Str ){ int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16 u8 enc = ENC(db); if( enc!=SQLITE_UTF8 ){ memset(&utf8, 0, sizeof(utf8)); utf8.db = db; sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){ - out.accError = SQLITE_NOMEM; + out.accError = STRACCUM_NOMEM; out.nAlloc = 0; } pVar = &utf8; } #endif @@ -93391,43 +78745,43 @@ #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ nOut = SQLITE_TRACE_SIZE_LIMIT; while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } } -#endif - sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z); +#endif + sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOutn ){ - sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); } #endif #ifndef SQLITE_OMIT_UTF16 if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); #endif }else if( pVar->flags & MEM_Zero ){ - sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero); + sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); }else{ int nOut; /* Number of bytes of the blob to include in output */ assert( pVar->flags & MEM_Blob ); - sqlite3_str_append(&out, "x'", 2); + sqlite3StrAccumAppend(&out, "x'", 2); nOut = pVar->n; #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; #endif for(i=0; iz[i]&0xff); + sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); } - sqlite3_str_append(&out, "'", 1); + sqlite3StrAccumAppend(&out, "'", 1); #ifdef SQLITE_TRACE_SIZE_LIMIT if( nOutn ){ - sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); } #endif } } } - if( out.accError ) sqlite3_str_reset(&out); + if( out.accError ) sqlite3StrAccumReset(&out); return sqlite3StrAccumFinish(&out); } #endif /* #ifndef SQLITE_OMIT_TRACE */ @@ -93454,108 +78808,10 @@ ** commenting and indentation practices when changing or adding code. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ -/* -** High-resolution hardware timer used for debugging and testing only. -*/ -#if defined(VDBE_PROFILE) \ - || defined(SQLITE_PERFORMANCE_TRACE) \ - || defined(SQLITE_ENABLE_STMT_SCANSTATUS) -/************** Include hwtime.h in the middle of vdbe.c *********************/ -/************** Begin file hwtime.h ******************************************/ -/* -** 2008 May 27 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains inline asm code for retrieving "high-performance" -** counters for x86 and x86_64 class CPUs. -*/ -#ifndef SQLITE_HWTIME_H -#define SQLITE_HWTIME_H - -/* -** The following routine only works on Pentium-class (or newer) processors. -** It uses the RDTSC opcode to read the cycle count value out of the -** processor and returns that value. This can be used for high-res -** profiling. -*/ -#if !defined(__STRICT_ANSI__) && \ - (defined(__GNUC__) || defined(_MSC_VER)) && \ - (defined(i386) || defined(__i386__) || defined(_M_IX86)) - - #if defined(__GNUC__) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned int lo, hi; - __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); - return (sqlite_uint64)hi << 32 | lo; - } - - #elif defined(_MSC_VER) - - __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ - __asm { - rdtsc - ret ; return value at EDX:EAX - } - } - - #endif - -#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned int lo, hi; - __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); - return (sqlite_uint64)hi << 32 | lo; - } - -#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned long long retval; - unsigned long junk; - __asm__ __volatile__ ("\n\ - 1: mftbu %1\n\ - mftb %L0\n\ - mftbu %0\n\ - cmpw %0,%1\n\ - bne 1b" - : "=r" (retval), "=r" (junk)); - return retval; - } - -#else - - /* - ** asm() is needed for hardware timing support. Without asm(), - ** disable the sqlite3Hwtime() routine. - ** - ** sqlite3Hwtime() is only used for some obscure debugging - ** and analysis configurations, not in any deliverable, so this - ** should not be a great loss. - */ -SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } - -#endif - -#endif /* !defined(SQLITE_HWTIME_H) */ - -/************** End of hwtime.h **********************************************/ -/************** Continuing where we left off in vdbe.c ***********************/ -#endif - /* ** Invoke this macro on memory cells just prior to changing the ** value of the cell. This macro verifies that shallow copies are ** not misused. A shallow copy of a string or blob just copies a ** pointer to the string or blob, not the content. If the original @@ -93648,112 +78904,52 @@ # define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) #else # define UPDATE_MAX_BLOBSIZE(P) #endif -#ifdef SQLITE_DEBUG -/* This routine provides a convenient place to set a breakpoint during -** tracing with PRAGMA vdbe_trace=on. The breakpoint fires right after -** each opcode is printed. Variables "pc" (program counter) and pOp are -** available to add conditionals to the breakpoint. GDB example: -** -** break test_trace_breakpoint if pc=22 -** -** Other useful labels for breakpoints include: -** test_addop_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno) -** sqlite3MisuseError(lineno) -** sqlite3CantopenError(lineno) -*/ -static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ - static u64 n = 0; - (void)pc; - (void)pOp; - (void)v; - n++; - if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */ -} -#endif - /* ** Invoke the VDBE coverage callback, if that callback is defined. This ** feature is used for test suite validation only and does not appear an ** production builds. ** -** M is the type of branch. I is the direction taken for this instance of -** the branch. -** -** M: 2 - two-way branch (I=0: fall-thru 1: jump ) -** 3 - two-way + NULL (I=0: fall-thru 1: jump 2: NULL ) -** 4 - OP_Jump (I=0: jump p1 1: jump p2 2: jump p3) -** -** In other words, if M is 2, then I is either 0 (for fall-through) or -** 1 (for when the branch is taken). If M is 3, the I is 0 for an -** ordinary fall-through, I is 1 if the branch was taken, and I is 2 -** if the result of comparison is NULL. For M=3, I=2 the jump may or -** may not be taken, depending on the SQLITE_JUMPIFNULL flags in p5. -** When M is 4, that means that an OP_Jump is being run. I is 0, 1, or 2 -** depending on if the operands are less than, equal, or greater than. +** M is an integer, 2 or 3, that indices how many different ways the +** branch can go. It is usually 2. "I" is the direction the branch +** goes. 0 means falls through. 1 means branch is taken. 2 means the +** second alternative branch is taken. ** ** iSrcLine is the source code line (from the __LINE__ macro) that -** generated the VDBE instruction combined with flag bits. The source -** code line number is in the lower 24 bits of iSrcLine and the upper -** 8 bytes are flags. The lower three bits of the flags indicate -** values for I that should never occur. For example, if the branch is -** always taken, the flags should be 0x05 since the fall-through and -** alternate branch are never taken. If a branch is never taken then -** flags should be 0x06 since only the fall-through approach is allowed. -** -** Bit 0x08 of the flags indicates an OP_Jump opcode that is only -** interested in equal or not-equal. In other words, I==0 and I==2 -** should be treated as equivalent -** -** Since only a line number is retained, not the filename, this macro -** only works for amalgamation builds. But that is ok, since these macros -** should be no-ops except for special builds used to measure test coverage. +** generated the VDBE instruction. This instrumentation assumes that all +** source code is in a single file (the amalgamation). Special values 1 +** and 2 for the iSrcLine parameter mean that this particular branch is +** always taken or never taken, respectively. */ #if !defined(SQLITE_VDBE_COVERAGE) # define VdbeBranchTaken(I,M) #else # define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) - static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){ - u8 mNever; - assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */ - assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */ - assert( I> 24; - assert( (I & mNever)==0 ); - if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ - /* Invoke the branch coverage callback with three arguments: - ** iSrcLine - the line number of the VdbeCoverage() macro, with - ** flags removed. - ** I - Mask of bits 0x07 indicating which cases are are - ** fulfilled by this instance of the jump. 0x01 means - ** fall-thru, 0x02 means taken, 0x04 means NULL. Any - ** impossible cases (ex: if the comparison is never NULL) - ** are filled in automatically so that the coverage - ** measurement logic does not flag those impossible cases - ** as missed coverage. - ** M - Type of jump. Same as M argument above - */ - I |= mNever; - if( M==2 ) I |= 0x04; - if( M==4 ){ - I |= 0x08; - if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/ - } - sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, - iSrcLine&0xffffff, I, M); + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ + M = iSrcLine; + /* Assert the truth of VdbeCoverageAlwaysTaken() and + ** VdbeCoverageNeverTaken() */ + assert( (M & I)==I ); + }else{ + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, + iSrcLine,I,M); + } } #endif +/* +** Convert the given register into a string if it isn't one +** already. Return non-zero if a malloc() fails. +*/ +#define Stringify(P, enc) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \ + { goto no_mem; } + /* ** An ephemeral string value (signified by the MEM_Ephem flag) contains ** a pointer to a dynamically allocated string where some other entity ** is responsible for deallocating that string. Because the register ** does not control the string, it might be deleted without the register @@ -93776,14 +78972,15 @@ */ static VdbeCursor *allocateCursor( Vdbe *p, /* The virtual machine */ int iCur, /* Index of the new VdbeCursor */ int nField, /* Number of fields in the table or index */ + int iDb, /* Database the cursor belongs to, or -1 */ u8 eCurType /* Type of the new cursor */ ){ /* Find the memory cell that will be used to store the blob of memory - ** required for this VdbeCursor structure. It is convenient to use a + ** required for this VdbeCursor structure. It is convenient to use a ** vdbe memory cell to manage the memory allocation required for a ** VdbeCursor structure for the following reasons: ** ** * Sometimes cursor numbers are used for a couple of different ** purposes in a vdbe program. The different uses might require @@ -93800,68 +78997,35 @@ */ Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem; int nByte; VdbeCursor *pCx = 0; - nByte = - ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + + nByte = + ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); assert( iCur>=0 && iCurnCursor ); if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/ - sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]); + sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } - - /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure - ** the pMem used to hold space for the cursor has enough storage available - ** in pMem->zMalloc. But for the special case of the aMem[] entries used - ** to hold cursors, it is faster to in-line the logic. */ - assert( pMem->flags==MEM_Undefined ); - assert( (pMem->flags & MEM_Dyn)==0 ); - assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc ); - if( pMem->szMallocszMalloc>0 ){ - sqlite3DbFreeNN(pMem->db, pMem->zMalloc); - } - pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte); - if( pMem->zMalloc==0 ){ - pMem->szMalloc = 0; - return 0; - } - pMem->szMalloc = nByte; - } - - p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc; - memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); - pCx->eCurType = eCurType; - pCx->nField = nField; - pCx->aOffset = &pCx->aType[nField]; - if( eCurType==CURTYPE_BTREE ){ - pCx->uc.pCursor = (BtCursor*) - &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; - sqlite3BtreeCursorZero(pCx->uc.pCursor); + if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; + memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); + pCx->eCurType = eCurType; + pCx->iDb = iDb; + pCx->nField = nField; + pCx->aOffset = &pCx->aType[nField]; + if( eCurType==CURTYPE_BTREE ){ + pCx->uc.pCursor = (BtCursor*) + &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; + sqlite3BtreeCursorZero(pCx->uc.pCursor); + } } return pCx; } -/* -** The string in pRec is known to look like an integer and to have a -** floating point value of rValue. Return true and set *piValue to the -** integer value if the string is in range to be an integer. Otherwise, -** return false. -*/ -static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){ - i64 iValue; - iValue = sqlite3RealToI64(rValue); - if( sqlite3RealSameAsInt(rValue,iValue) ){ - *piValue = iValue; - return 1; - } - return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc); -} - /* ** Try to convert a value into a numeric representation if we can ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. @@ -93875,82 +79039,69 @@ ** point or exponential notation, the result is only MEM_Real, even ** if there is an exact integer representation of the quantity. */ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ double rValue; + i64 iValue; u8 enc = pRec->enc; - int rc; - assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); - rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc); - if( rc<=0 ) return; - if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ + assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str ); + if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; + if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ + pRec->u.i = iValue; pRec->flags |= MEM_Int; }else{ pRec->u.r = rValue; pRec->flags |= MEM_Real; if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); } - /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the - ** string representation after computing a numeric equivalent, because the - ** string representation might not be the canonical representation for the - ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */ - pRec->flags &= ~MEM_Str; } /* ** Processing is determine by the affinity parameter: ** ** SQLITE_AFF_INTEGER: ** SQLITE_AFF_REAL: ** SQLITE_AFF_NUMERIC: -** Try to convert pRec to an integer representation or a +** Try to convert pRec to an integer representation or a ** floating-point representation if an integer representation ** is not possible. Note that the integer representation is ** always preferred, even if the affinity is REAL, because ** an integer representation is more space efficient on disk. ** -** SQLITE_AFF_FLEXNUM: -** If the value is text, then try to convert it into a number of -** some kind (integer or real) but do not make any other changes. -** ** SQLITE_AFF_TEXT: ** Convert pRec to a text representation. ** ** SQLITE_AFF_BLOB: -** SQLITE_AFF_NONE: ** No-op. pRec is unchanged. */ static void applyAffinity( Mem *pRec, /* The value to apply affinity to */ char affinity, /* The affinity to be applied */ u8 enc /* Use this text encoding */ ){ if( affinity>=SQLITE_AFF_NUMERIC ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL - || affinity==SQLITE_AFF_NUMERIC || affinity==SQLITE_AFF_FLEXNUM ); + || affinity==SQLITE_AFF_NUMERIC ); if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/ - if( (pRec->flags & (MEM_Real|MEM_IntReal))==0 ){ + if( (pRec->flags & MEM_Real)==0 ){ if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); - }else if( affinity<=SQLITE_AFF_REAL ){ + }else{ sqlite3VdbeIntegerAffinity(pRec); } } }else if( affinity==SQLITE_AFF_TEXT ){ /* Only attempt the conversion to TEXT if there is an integer or real ** representation (blob and NULL do not get converted) but no string - ** representation. It would be harmless to repeat the conversion if + ** representation. It would be harmless to repeat the conversion if ** there is already a string rep, but it is pointless to waste those ** CPU cycles. */ if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/ - if( (pRec->flags&(MEM_Real|MEM_Int|MEM_IntReal)) ){ - testcase( pRec->flags & MEM_Int ); - testcase( pRec->flags & MEM_Real ); - testcase( pRec->flags & MEM_IntReal ); + if( (pRec->flags&(MEM_Real|MEM_Int)) ){ sqlite3VdbeMemStringify(pRec, enc, 1); } } - pRec->flags &= ~(MEM_Real|MEM_Int|MEM_IntReal); + pRec->flags &= ~(MEM_Real|MEM_Int); } } /* ** Try to convert the type of a function argument or a result column @@ -93967,16 +79118,16 @@ } return eType; } /* -** Exported version of applyAffinity(). This one works on sqlite3_value*, +** Exported version of applyAffinity(). This one works on sqlite3_value*, ** not the internal Mem* type. */ SQLITE_PRIVATE void sqlite3ValueApplyAffinity( - sqlite3_value *pVal, - u8 affinity, + sqlite3_value *pVal, + u8 affinity, u8 enc ){ applyAffinity((Mem *)pVal, affinity, enc); } @@ -93985,64 +79136,49 @@ ** interpret as a string if we want to). Compute its corresponding ** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields ** accordingly. */ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ - int rc; - sqlite3_int64 ix; - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ); + assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); - if( ExpandBlob(pMem) ){ - pMem->u.i = 0; - return MEM_Int; - } - rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( rc<=0 ){ - if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){ - pMem->u.i = ix; - return MEM_Int; - }else{ - return MEM_Real; - } - }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){ - pMem->u.i = ix; + 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 ){ return MEM_Int; } return MEM_Real; } /* ** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or -** none. +** none. ** ** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. ** But it does set pMem->u.r and pMem->u.i appropriately. */ static u16 numericType(Mem *pMem){ - assert( (pMem->flags & MEM_Null)==0 - || pMem->db==0 || pMem->db->mallocFailed ); - if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null) ){ - testcase( pMem->flags & MEM_Int ); - testcase( pMem->flags & MEM_Real ); - testcase( pMem->flags & MEM_IntReal ); - return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null); - } - assert( pMem->flags & (MEM_Str|MEM_Blob) ); - testcase( pMem->flags & MEM_Str ); - testcase( pMem->flags & MEM_Blob ); - return computeNumericType(pMem); + if( pMem->flags & (MEM_Int|MEM_Real) ){ + return pMem->flags & (MEM_Int|MEM_Real); + } + if( pMem->flags & (MEM_Str|MEM_Blob) ){ + return computeNumericType(pMem); + } return 0; } #ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem ** into buffer zBuf, length nBuf. */ -SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){ +SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ + char *zCsr = zBuf; int f = pMem->flags; + static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; + if( f&MEM_Blob ){ int i; char c; if( f & MEM_Dyn ){ c = 'z'; @@ -94054,47 +79190,59 @@ c = 'e'; assert( (f & (MEM_Static|MEM_Dyn))==0 ); }else{ c = 's'; } - sqlite3_str_appendf(pStr, "%cx[", c); - for(i=0; i<25 && in; i++){ - sqlite3_str_appendf(pStr, "%02X", ((int)pMem->z[i] & 0xFF)); + *(zCsr++) = c; + sqlite3_snprintf(100, zCsr, "%d[", pMem->n); + zCsr += sqlite3Strlen30(zCsr); + for(i=0; i<16 && in; i++){ + sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); + zCsr += sqlite3Strlen30(zCsr); } - sqlite3_str_appendf(pStr, "|"); - for(i=0; i<25 && in; i++){ + for(i=0; i<16 && in; i++){ char z = pMem->z[i]; - sqlite3_str_appendchar(pStr, 1, (z<32||z>126)?'.':z); + if( z<32 || z>126 ) *zCsr++ = '.'; + else *zCsr++ = z; } - sqlite3_str_appendf(pStr,"]"); + *(zCsr++) = ']'; if( f & MEM_Zero ){ - sqlite3_str_appendf(pStr, "+%dz",pMem->u.nZero); + sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero); + zCsr += sqlite3Strlen30(zCsr); } + *zCsr = '\0'; }else if( f & MEM_Str ){ - int j; - u8 c; + int j, k; + zBuf[0] = ' '; if( f & MEM_Dyn ){ - c = 'z'; + zBuf[1] = 'z'; assert( (f & (MEM_Static|MEM_Ephem))==0 ); }else if( f & MEM_Static ){ - c = 't'; + zBuf[1] = 't'; assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); }else if( f & MEM_Ephem ){ - c = 'e'; + zBuf[1] = 'e'; assert( (f & (MEM_Static|MEM_Dyn))==0 ); }else{ - c = 's'; - } - sqlite3_str_appendf(pStr, " %c%d[", c, pMem->n); - for(j=0; j<25 && jn; j++){ - c = pMem->z[j]; - sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.'); - } - sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]); - if( f & MEM_Term ){ - sqlite3_str_appendf(pStr, "(0-term)"); - } + zBuf[1] = 's'; + } + k = 2; + sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); + k += sqlite3Strlen30(&zBuf[k]); + zBuf[k++] = '['; + for(j=0; j<15 && jn; j++){ + u8 c = pMem->z[j]; + if( c>=0x20 && c<0x7f ){ + zBuf[k++] = c; + }else{ + zBuf[k++] = '.'; + } + } + zBuf[k++] = ']'; + sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]); + k += sqlite3Strlen30(&zBuf[k]); + zBuf[k++] = 0; } } #endif #ifdef SQLITE_DEBUG @@ -94103,74 +79251,149 @@ */ static void memTracePrint(Mem *p){ if( p->flags & MEM_Undefined ){ printf(" undefined"); }else if( p->flags & MEM_Null ){ - printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); + printf(" NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ printf(" si:%lld", p->u.i); - }else if( (p->flags & (MEM_IntReal))!=0 ){ - printf(" ir:%lld", p->u.i); }else if( p->flags & MEM_Int ){ printf(" i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ - printf(" r:%.17g", p->u.r); + printf(" r:%g", p->u.r); #endif - }else if( sqlite3VdbeMemIsRowSet(p) ){ + }else if( p->flags & MEM_RowSet ){ printf(" (rowset)"); }else{ - StrAccum acc; - char zBuf[1000]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3VdbeMemPrettyPrint(p, &acc); - printf(" %s", sqlite3StrAccumFinish(&acc)); + char zBuf[200]; + sqlite3VdbeMemPrettyPrint(p, zBuf); + printf(" %s", zBuf); } if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); } static void registerTrace(int iReg, Mem *p){ - printf("R[%d] = ", iReg); + printf("REG[%d] = ", iReg); memTracePrint(p); - if( p->pScopyFrom ){ - assert( p->pScopyFrom->bScopy ); - printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg])); - } printf("\n"); sqlite3VdbeCheckMemInvariants(p); } -/**/ void sqlite3PrintMem(Mem *pMem){ - memTracePrint(pMem); - printf("\n"); - fflush(stdout); -} #endif - -#ifdef SQLITE_DEBUG -/* -** Show the values of all registers in the virtual machine. Used for -** interactive debugging. -*/ -SQLITE_PRIVATE void sqlite3VdbeRegisterDump(Vdbe *v){ - int i; - for(i=1; inMem; i++) registerTrace(i, v->aMem+i); -} -#endif /* SQLITE_DEBUG */ - #ifdef SQLITE_DEBUG # define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M) #else # define REGISTER_TRACE(R,M) #endif + +#ifdef VDBE_PROFILE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +/************** Include hwtime.h in the middle of vdbe.c *********************/ +/************** Begin file hwtime.h ******************************************/ +/* +** 2008 May 27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +*/ +#ifndef SQLITE_HWTIME_H +#define SQLITE_HWTIME_H + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ +SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(SQLITE_HWTIME_H) */ + +/************** End of hwtime.h **********************************************/ +/************** Continuing where we left off in vdbe.c ***********************/ + +#endif + #ifndef NDEBUG /* ** This function is only called from within an assert() expression. It ** checks that the sqlite3.nTransaction variable is correctly set to -** the number of non-transaction savepoints currently in the +** the number of non-transaction savepoints currently in the ** linked list starting at sqlite3.pSavepoint. -** +** ** Usage: ** ** assert( checkSavepointCount(db) ); */ static int checkSavepointCount(sqlite3 *db){ @@ -94203,198 +79426,69 @@ pOut->flags = MEM_Int; return pOut; } } -/* -** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning -** with pOp->p3. Return the hash. -*/ -static u64 filterHash(const Mem *aMem, const Op *pOp){ - int i, mx; - u64 h = 0; - - assert( pOp->p4type==P4_INT32 ); - for(i=pOp->p3, mx=i+pOp->p4.i; iflags & (MEM_Int|MEM_IntReal) ){ - h += p->u.i; - }else if( p->flags & MEM_Real ){ - h += sqlite3VdbeIntValue(p); - }else if( p->flags & (MEM_Str|MEM_Blob) ){ - /* All strings have the same hash and all blobs have the same hash, - ** though, at least, those hashes are different from each other and - ** from NULL. */ - h += 4093 + (p->flags & (MEM_Str|MEM_Blob)); - } - } - return h; -} - - -/* -** For OP_Column, factor out the case where content is loaded from -** overflow pages, so that the code to implement this case is separate -** the common case where all content fits on the page. Factoring out -** the code reduces register pressure and helps the common case -** to run faster. -*/ -static SQLITE_NOINLINE int vdbeColumnFromOverflow( - VdbeCursor *pC, /* The BTree cursor from which we are reading */ - int iCol, /* The column to read */ - int t, /* The serial-type code for the column value */ - i64 iOffset, /* Offset to the start of the content value */ - u32 cacheStatus, /* Current Vdbe.cacheCtr value */ - u32 colCacheCtr, /* Current value of the column cache counter */ - Mem *pDest /* Store the value into this register. */ -){ - int rc; - sqlite3 *db = pDest->db; - int encoding = pDest->enc; - int len = sqlite3VdbeSerialTypeLen(t); - assert( pC->eCurType==CURTYPE_BTREE ); - if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) return SQLITE_TOOBIG; - if( len > 4000 && pC->pKeyInfo==0 ){ - /* Cache large column values that are on overflow pages using - ** an RCStr (reference counted string) so that if they are reloaded, - ** that do not have to be copied a second time. The overhead of - ** creating and managing the cache is such that this is only - ** profitable for larger TEXT and BLOB values. - ** - ** Only do this on table-btrees so that writes to index-btrees do not - ** need to clear the cache. This buys performance in the common case - ** in exchange for generality. - */ - VdbeTxtBlbCache *pCache; - char *pBuf; - if( pC->colCache==0 ){ - pC->pCache = sqlite3DbMallocZero(db, sizeof(VdbeTxtBlbCache) ); - if( pC->pCache==0 ) return SQLITE_NOMEM; - pC->colCache = 1; - } - pCache = pC->pCache; - if( pCache->pCValue==0 - || pCache->iCol!=iCol - || pCache->cacheStatus!=cacheStatus - || pCache->colCacheCtr!=colCacheCtr - || pCache->iOffset!=sqlite3BtreeOffset(pC->uc.pCursor) - ){ - if( pCache->pCValue ) sqlite3RCStrUnref(pCache->pCValue); - pBuf = pCache->pCValue = sqlite3RCStrNew( len+3 ); - if( pBuf==0 ) return SQLITE_NOMEM; - rc = sqlite3BtreePayload(pC->uc.pCursor, iOffset, len, pBuf); - if( rc ) return rc; - pBuf[len] = 0; - pBuf[len+1] = 0; - pBuf[len+2] = 0; - pCache->iCol = iCol; - pCache->cacheStatus = cacheStatus; - pCache->colCacheCtr = colCacheCtr; - pCache->iOffset = sqlite3BtreeOffset(pC->uc.pCursor); - }else{ - pBuf = pCache->pCValue; - } - assert( t>=12 ); - sqlite3RCStrRef(pBuf); - if( t&1 ){ - rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, encoding, - sqlite3RCStrUnref); - pDest->flags |= MEM_Term; - }else{ - rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, 0, - sqlite3RCStrUnref); - } - }else{ - rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, iOffset, len, pDest); - if( rc ) return rc; - sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); - if( (t&1)!=0 && encoding==SQLITE_UTF8 ){ - pDest->z[len] = 0; - pDest->flags |= MEM_Term; - } - } - pDest->flags &= ~MEM_Ephem; - return rc; -} - - -/* -** Return the symbolic name for the data type of a pMem -*/ -static const char *vdbeMemTypeName(Mem *pMem){ - static const char *azTypes[] = { - /* SQLITE_INTEGER */ "INT", - /* SQLITE_FLOAT */ "REAL", - /* SQLITE_TEXT */ "TEXT", - /* SQLITE_BLOB */ "BLOB", - /* SQLITE_NULL */ "NULL" - }; - return azTypes[sqlite3_value_type(pMem)-1]; -} /* ** Execute as much of a VDBE program as we can. -** This is the core of sqlite3_step(). +** This is the core of sqlite3_step(). */ SQLITE_PRIVATE int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ){ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp = aOp; /* Current operation */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) Op *pOrigOp; /* Value of pOp at the top of the loop */ +#endif +#ifdef SQLITE_DEBUG int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ - u8 iCompareIsInit = 0; /* iCompare is initialized */ #endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ int iCompare = 0; /* Result of last comparison */ - u64 nVmStep = 0; /* Number of virtual machine steps */ + unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u64 nProgressLimit; /* 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 */ - u32 colCacheCtr = 0; /* Column cache counter */ -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) - u64 *pnCycle = 0; - int bStmtScanStatus = IS_STMT_SCANSTATUS(db)!=0; +#ifdef VDBE_PROFILE + u64 start; /* CPU clock count at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ - assert( p->eVdbeState==VDBE_RUN_STATE ); /* sqlite3_step() verifies this */ - if( DbMaskNonZero(p->lockMask) ){ - sqlite3VdbeEnter(p); + assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ + sqlite3VdbeEnter(p); + if( p->rc==SQLITE_NOMEM ){ + /* This happens if a malloc() inside a call to sqlite3_column_text() or + ** sqlite3_column_text16() failed. */ + goto no_mem; } + assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY ); + assert( p->bIsReader || p->readOnly!=0 ); + p->iCurrentTime = 0; + assert( p->explain==0 ); + p->pResultSet = 0; + db->busyHandler.nBusy = 0; + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; + sqlite3VdbeIOTraceSql(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( db->xProgress ){ u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; assert( 0 < db->nProgressOps ); nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); }else{ - nProgressLimit = LARGEST_UINT64; + nProgressLimit = 0xffffffff; } #endif - if( p->rc==SQLITE_NOMEM ){ - /* This happens if a malloc() inside a call to sqlite3_column_text() or - ** sqlite3_column_text16() failed. */ - goto no_mem; - } - assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY ); - testcase( p->rc!=SQLITE_OK ); - p->rc = SQLITE_OK; - assert( p->bIsReader || p->readOnly!=0 ); - p->iCurrentTime = 0; - assert( p->explain==0 ); - db->busyHandler.nBusy = 0; - if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt; - sqlite3VdbeIOTraceSql(p); #ifdef SQLITE_DEBUG sqlite3BeginBenignMalloc(); if( p->pc==0 && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0 ){ @@ -94424,33 +79518,26 @@ /* Errors are detected by individual opcodes, with an immediate ** jumps to abort_due_to_error. */ assert( rc==SQLITE_OK ); assert( pOp>=aOp && pOp<&aOp[p->nOp]); +#ifdef VDBE_PROFILE + start = sqlite3Hwtime(); +#endif nVmStep++; - -#if defined(VDBE_PROFILE) - pOp->nExec++; - pnCycle = &pOp->nCycle; - if( sqlite3NProfileCnt==0 ) *pnCycle -= sqlite3Hwtime(); -#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( bStmtScanStatus ){ - pOp->nExec++; - pnCycle = &pOp->nCycle; - *pnCycle -= sqlite3Hwtime(); - } +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + if( p->anExec ) p->anExec[(int)(pOp-aOp)]++; #endif /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); - test_trace_breakpoint((int)(pOp - aOp),pOp,p); } #endif - + /* Check to see if we need to simulate an interrupt. This only happens ** if we have a special test build. */ #ifdef SQLITE_TEST @@ -94497,14 +79584,14 @@ assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); memAboutToChange(p, &aMem[pOp->p3]); } } #endif -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) pOrigOp = pOp; #endif - + switch( pOp->opcode ){ /***************************************************************************** ** What follows is a massive switch statement where each case implements a ** separate instruction in the virtual machine. If we follow the usual @@ -94541,67 +79628,52 @@ *****************************************************************************/ /* Opcode: Goto * P2 * * * ** ** An unconditional jump to address P2. -** The next instruction executed will be +** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. ** ** The P1 parameter is not actually used by this opcode. However, it ** is sometimes set to 1 instead of 0 as a hint to the command-line shell ** that this Goto is the bottom of a loop and that the lines from P2 down ** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ - -#ifdef SQLITE_DEBUG - /* In debugging mode, when the p5 flags is set on an OP_Goto, that - ** means we should really jump back to the preceding OP_ReleaseReg - ** instruction. */ - if( pOp->p5 ){ - assert( pOp->p2 < (int)(pOp - aOp) ); - assert( pOp->p2 > 1 ); - pOp = &aOp[pOp->p2 - 2]; - assert( pOp[1].opcode==OP_ReleaseReg ); - goto check_for_interrupt; - } -#endif - jump_to_p2_and_check_for_interrupt: pOp = &aOp[pOp->p2 - 1]; /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, or OP_SorterNext) all jump here upon ** completion. Check to see if sqlite3_interrupt() has been called - ** or if the progress callback needs to be invoked. + ** or if the progress callback needs to be invoked. ** ** This code uses unstructured "goto" statements and does not look clean. ** But that is not due to sloppy coding habits. The code is written this ** way for performance, to avoid having to run the interrupt and progress ** checks on every opcode. This helps sqlite3_step() to run about 1.5% ** faster according to "valgrind --tool=cachegrind" */ check_for_interrupt: - if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt; + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Call the progress callback if it is configured and the required number ** of VDBE ops have been executed (either since this invocation of ** sqlite3VdbeExec() or since last time the progress callback was called). ** If the progress callback returns non-zero, exit the virtual machine with ** a return code SQLITE_ABORT. */ - while( nVmStep>=nProgressLimit && db->xProgress!=0 ){ + if( nVmStep>=nProgressLimit && db->xProgress!=0 ){ assert( db->nProgressOps!=0 ); - nProgressLimit += db->nProgressOps; + nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps); if( db->xProgress(db->pProgressArg) ){ - nProgressLimit = LARGEST_UINT64; rc = SQLITE_INTERRUPT; goto abort_due_to_error; } } #endif - + break; } /* Opcode: Gosub P1 P2 * * * ** @@ -94614,43 +79686,28 @@ assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; pIn1->u.i = (int)(pOp-aOp); REGISTER_TRACE(pOp->p1, pIn1); - goto jump_to_p2_and_check_for_interrupt; -} - -/* Opcode: Return P1 P2 P3 * * -** -** Jump to the address stored in register P1. If P1 is a return address -** register, then this accomplishes a return from a subroutine. -** -** If P3 is 1, then the jump is only taken if register P1 holds an integer -** values, otherwise execution falls through to the next opcode, and the -** OP_Return becomes a no-op. If P3 is 0, then register P1 must hold an -** integer or else an assert() is raised. P3 should be set to 1 when -** this opcode is used in combination with OP_BeginSubrtn, and set to 0 -** otherwise. -** -** The value in register P1 is unchanged by this opcode. -** -** P2 is not used by the byte-code engine. However, if P2 is positive -** and also less than the current address, then the "EXPLAIN" output -** formatter in the CLI will indent all opcodes from the P2 opcode up -** to be not including the current Return. P2 should be the first opcode -** in the subroutine from which this opcode is returning. Thus the P2 -** value is a byte-code indentation hint. See tag-20220407a in -** wherecode.c and shell.c. + + /* Most jump operations do a goto to this spot in order to update + ** the pOp pointer. */ +jump_to_p2: + pOp = &aOp[pOp->p2 - 1]; + break; +} + +/* Opcode: Return P1 * * * * +** +** Jump to the next instruction after the address in register P1. After +** the jump, register P1 becomes undefined. */ case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Int ){ - if( pOp->p3 ){ VdbeBranchTaken(1, 2); } - pOp = &aOp[pIn1->u.i]; - }else if( ALWAYS(pOp->p3) ){ - VdbeBranchTaken(0, 2); - } + assert( pIn1->flags==MEM_Int ); + pOp = &aOp[pIn1->u.i]; + pIn1->flags = MEM_Undefined; break; } /* Opcode: InitCoroutine P1 P2 P3 * * ** @@ -94661,36 +79718,27 @@ ** this opcode. So jump over the coroutine implementation to ** address P2. ** ** See also: EndCoroutine */ -case OP_InitCoroutine: { /* jump0 */ +case OP_InitCoroutine: { /* jump */ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2>=0 && pOp->p2nOp ); assert( pOp->p3>=0 && pOp->p3nOp ); pOut = &aMem[pOp->p1]; assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; - if( pOp->p2==0 ) break; - - /* Most jump operations do a goto to this spot in order to update - ** the pOp pointer. */ -jump_to_p2: - assert( pOp->p2>0 ); /* There are never any jumps to instruction 0 */ - assert( pOp->p2nOp ); /* Jumps must be in range */ - pOp = &aOp[pOp->p2 - 1]; + if( pOp->p2 ) goto jump_to_p2; break; } /* Opcode: EndCoroutine P1 * * * * ** ** The instruction at the address in register P1 is a Yield. ** Jump to the P2 parameter of that Yield. -** After the jump, the value register P1 is left with a value -** such that subsequent OP_Yields go back to the this same -** OP_EndCoroutine instruction. +** After the jump, register P1 becomes undefined. ** ** See also: InitCoroutine */ case OP_EndCoroutine: { /* in1 */ VdbeOp *pCaller; @@ -94698,12 +79746,12 @@ assert( pIn1->flags==MEM_Int ); assert( pIn1->u.i>=0 && pIn1->u.inOp ); pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2nOp ); - pIn1->u.i = (int)(pOp - p->aOp) - 1; pOp = &aOp[pCaller->p2 - 1]; + pIn1->flags = MEM_Undefined; break; } /* Opcode: Yield P1 P2 * * * ** @@ -94716,11 +79764,11 @@ ** EndCoroutine, then jump to P2 rather than continuing with the ** next instruction. ** ** See also: InitCoroutine */ -case OP_Yield: { /* in1, jump0 */ +case OP_Yield: { /* in1, jump */ int pcDest; pIn1 = &aMem[pOp->p1]; assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; @@ -94738,19 +79786,15 @@ ** value in register P3 is not NULL, then this routine is a no-op. ** The P5 parameter should be 1. */ case OP_HaltIfNull: { /* in3 */ pIn3 = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } -#endif if( (pIn3->flags & MEM_Null)==0 ) break; /* Fall through into OP_Halt */ - /* no break */ deliberate_fall_through } -/* Opcode: Halt P1 P2 P3 P4 P5 +/* Opcode: Halt P1 P2 * P4 P5 ** ** Exit immediately. All open cursors, etc are closed ** automatically. ** ** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), @@ -94757,58 +79801,43 @@ ** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). ** For errors, it can be some other value. If P1!=0 then P2 will determine ** whether or not to rollback the current transaction. Do not rollback ** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, ** then back out all changes that have occurred during this execution of the -** VDBE, but do not rollback the transaction. -** -** If P3 is not zero and P4 is NULL, then P3 is a register that holds the -** text of an error message. -** -** If P3 is zero and P4 is not null then the error message string is held -** in P4. -** -** P5 is a value between 1 and 4, inclusive, then the P4 error message -** string is modified as follows: -** -** 1: NOT NULL constraint failed: P4 +** VDBE, but do not rollback the transaction. +** +** If P4 is not null then it is an error message string. +** +** P5 is a value between 0 and 4, inclusive, that modifies the P4 string. +** +** 0: (no change) +** 1: NOT NULL contraint failed: P4 ** 2: UNIQUE constraint failed: P4 ** 3: CHECK constraint failed: P4 ** 4: FOREIGN KEY constraint failed: P4 ** -** If P3 is zero and P5 is not zero and P4 is NULL, then everything after -** the ":" is omitted. +** If P5 is not zero and P4 is NULL, then everything after the ":" is +** omitted. ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { VdbeFrame *pFrame; int pcx; -#ifdef SQLITE_DEBUG - if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } -#endif - assert( pOp->p4type==P4_NOTUSED - || pOp->p4type==P4_STATIC - || pOp->p4type==P4_DYNAMIC ); - - /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates - ** something is wrong with the code generator. Raise an assertion in order - ** to bring this to the attention of fuzzers and other testing tools. */ - assert( pOp->p1!=SQLITE_INTERNAL ); - - if( p->pFrame && pOp->p1==SQLITE_OK ){ + pcx = (int)(pOp - aOp); + if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); pcx = sqlite3VdbeFrameRestore(pFrame); if( pOp->p2==OE_Ignore ){ - /* Instruction pcx is the OP_Program that invoked the sub-program + /* Instruction pcx is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified ** as the p2 of the calling OP_Program. */ pcx = p->aOp[pcx].p2-1; @@ -94818,18 +79847,14 @@ pOp = &aOp[pcx]; break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; + p->pc = pcx; assert( pOp->p5<=4 ); if( p->rc ){ - if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){ - const char *zErr; - assert( pOp->p3<=(p->nMem + 1 - p->nCursor) ); - zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8); - sqlite3VdbeError(p, "%s", zErr); - }else if( pOp->p5 ){ + if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", "FOREIGN KEY" }; testcase( pOp->p5==1 ); testcase( pOp->p5==2 ); testcase( pOp->p5==3 ); @@ -94839,11 +79864,10 @@ p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z); } }else{ sqlite3VdbeError(p, "%s", pOp->p4.z); } - pcx = (int)(pOp - aOp); sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); if( rc==SQLITE_BUSY ){ @@ -94897,25 +79921,25 @@ #endif /* Opcode: String8 * P2 * P4 * ** Synopsis: r[P2]='P4' ** -** P4 points to a nul terminated UTF-8 string. This opcode is transformed +** P4 points to a nul terminated UTF-8 string. This opcode is transformed ** into a String opcode before it is executed for the first time. During ** this transformation, the length of string P4 is computed and stored ** as the P1 parameter. */ case OP_String8: { /* same as TK_STRING, out2 */ assert( pOp->p4.z!=0 ); pOut = out2Prerelease(p, pOp); + pOp->opcode = OP_String; pOp->p1 = sqlite3Strlen30(pOp->p4.z); #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG ); - if( rc ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); assert( VdbeMemDynamic(pOut)==0 ); pOut->szMalloc = 0; pOut->flags |= MEM_Static; @@ -94924,20 +79948,19 @@ } pOp->p4type = P4_DYNAMIC; pOp->p4.z = pOut->z; pOp->p1 = pOut->n; } + testcase( rc==SQLITE_TOOBIG ); #endif if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - pOp->opcode = OP_String; assert( rc==SQLITE_OK ); /* Fall through to the next case, OP_String */ - /* no break */ deliberate_fall_through } - + /* Opcode: String P1 P2 P3 P4 P5 ** Synopsis: r[P2]='P4' (len=P1) ** ** The string value P4 of length P1 (bytes) is stored in register P2. ** @@ -94965,32 +79988,10 @@ } #endif break; } -/* Opcode: BeginSubrtn * P2 * * * -** Synopsis: r[P2]=NULL -** -** Mark the beginning of a subroutine that can be entered in-line -** or that can be called using OP_Gosub. The subroutine should -** be terminated by an OP_Return instruction that has a P1 operand that -** is the same as the P2 operand to this opcode and that has P3 set to 1. -** If the subroutine is entered in-line, then the OP_Return will simply -** fall through. But if the subroutine is entered using OP_Gosub, then -** the OP_Return will jump back to the first instruction after the OP_Gosub. -** -** This routine works by loading a NULL into the P2 register. When the -** return address register contains a NULL, the OP_Return instruction is -** a no-op that simply falls through to the next instruction (assuming that -** the OP_Return opcode has a P3 value of 1). Thus if the subroutine is -** entered in-line, then the OP_Return will cause in-line execution to -** continue. But if the subroutine is entered via OP_Gosub, then the -** OP_Return will cause a return to the address following the OP_Gosub. -** -** This opcode is identical to OP_Null. It has a different name -** only to make the byte code easier to read and verify. -*/ /* Opcode: Null P1 P2 P3 * * ** Synopsis: r[P2..P3]=NULL ** ** Write a NULL into registers P2. If P3 greater than P2, then also write ** NULL into register P3 and every register in between P2 and P3. If P3 @@ -94999,22 +80000,18 @@ ** ** If the P1 value is non-zero, then also set the MEM_Cleared flag so that ** NULL values will not compare equal even if SQLITE_NULLEQ is set on ** OP_Ne or OP_Eq. */ -case OP_BeginSubrtn: case OP_Null: { /* out2 */ int cnt; u16 nullFlag; pOut = out2Prerelease(p, pOp); cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; pOut->n = 0; -#ifdef SQLITE_DEBUG - pOut->uTemp = 0; -#endif while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); sqlite3VdbeMemSetNull(pOut); pOut->flags = nullFlag; @@ -95041,45 +80038,40 @@ /* Opcode: Blob P1 P2 * P4 * ** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this -** blob in register P2. If P4 is a NULL pointer, then construct -** a zero-filled blob that is P1 bytes long in P2. +** blob in register P2. */ case OP_Blob: { /* out2 */ assert( pOp->p1 <= SQLITE_MAX_LENGTH ); pOut = out2Prerelease(p, pOp); - if( pOp->p4.z==0 ){ - sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1); - if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem; - }else{ - sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); - } + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; } -/* Opcode: Variable P1 P2 * * * -** Synopsis: r[P2]=parameter(P1) +/* Opcode: Variable P1 P2 * P4 * +** Synopsis: r[P2]=parameter(P1,P4) ** ** Transfer the values of bound parameter P1 into register P2 +** +** If the parameter is named, then its name appears in P4. +** The P4 value is used by sqlite3_bind_parameter_name(). */ 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==sqlite3VListNumToName(p->pVList,pOp->p1) ); pVar = &p->aVar[pOp->p1 - 1]; if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } pOut = &aMem[pOp->p2]; - if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); - memcpy(pOut, pVar, MEMCELLSIZE); - pOut->flags &= ~(MEM_Dyn|MEM_Ephem); - pOut->flags |= MEM_Static|MEM_FromBind; + sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; } /* Opcode: Move P1 P2 P3 * * @@ -95109,18 +80101,12 @@ assert( pIn1<=&aMem[(p->nMem+1 - p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); sqlite3VdbeMemMove(pOut, pIn1); #ifdef SQLITE_DEBUG - pIn1->pScopyFrom = 0; - { int i; - for(i=1; inMem; i++){ - if( aMem[i].pScopyFrom==pIn1 ){ - assert( aMem[i].bScopy ); - aMem[i].pScopyFrom = pOut; - } - } + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrompScopyFrom += pOp->p2 - p1; } #endif Deephemeralize(pOut); REGISTER_TRACE(p2++, pOut); pIn1++; @@ -95127,20 +80113,15 @@ pOut++; }while( --n ); break; } -/* Opcode: Copy P1 P2 P3 * P5 +/* Opcode: Copy P1 P2 P3 * * ** Synopsis: r[P2@P3+1]=r[P1@P3+1] ** ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. ** -** If the 0x0002 bit of P5 is set then also clear the MEM_Subtype flag in the -** destination. The 0x0001 bit of P5 indicates that this Copy opcode cannot -** be merged. The 0x0001 bit is used by the query planner and does not -** come into play during query execution. -** ** This instruction makes a deep copy of the value. A duplicate ** is made of any string or blob constant. See also OP_SCopy. */ case OP_Copy: { int n; @@ -95148,16 +80129,12 @@ n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); while( 1 ){ - memAboutToChange(p, pOut); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); - if( (pOut->flags & MEM_Subtype)!=0 && (pOp->p5 & 0x0002)!=0 ){ - pOut->flags &= ~MEM_Subtype; - } #ifdef SQLITE_DEBUG pOut->pScopyFrom = 0; #endif REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); if( (n--)==0 ) break; @@ -95184,13 +80161,11 @@ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); #ifdef SQLITE_DEBUG - pOut->pScopyFrom = pIn1; - pOut->mScopyFlags = pIn1->flags; - pIn1->bScopy = 1; + if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; #endif break; } /* Opcode: IntCopy P1 P2 * * * @@ -95207,28 +80182,10 @@ pOut = &aMem[pOp->p2]; sqlite3VdbeMemSetInt64(pOut, pIn1->u.i); break; } -/* Opcode: FkCheck * * * * * -** -** Halt with an SQLITE_CONSTRAINT error if there are any unresolved -** foreign key constraint violations. If there are no foreign key -** constraint violations, this is a no-op. -** -** FK constraint violations are also checked when the prepared statement -** exits. This opcode is used to raise foreign key constraint errors prior -** to returning results such as a row change count or the result of a -** RETURNING clause. -*/ -case OP_FkCheck: { - if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){ - goto abort_due_to_error; - } - break; -} - /* Opcode: ResultRow P1 P2 * * * ** Synopsis: output=r[P1@P2] ** ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate @@ -95235,36 +80192,80 @@ ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt ** structure to provide access to the r(P1)..r(P1+P2-1) values as ** the result row. */ case OP_ResultRow: { + Mem *pMem; + int i; assert( p->nResColumn==pOp->p2 ); - assert( pOp->p1>0 || CORRUPT_DB ); + assert( pOp->p1>0 ); assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Run the progress counter just before returning. + */ + if( db->xProgress!=0 + && nVmStep>=nProgressLimit + && db->xProgress(db->pProgressArg)!=0 + ){ + rc = SQLITE_INTERRUPT; + goto abort_due_to_error; + } +#endif + + /* If this statement has violated immediate foreign key constraints, do + ** not return the number of rows modified. And do not RELEASE the statement + ** transaction. It needs to be rolled back. */ + if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){ + assert( db->flags&SQLITE_CountRows ); + assert( p->usesStmtJournal ); + goto abort_due_to_error; + } + + /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then + ** DML statements invoke this opcode to return the number of rows + ** modified to the user. This is the only way that a VM that + ** opens a statement transaction may invoke this opcode. + ** + ** In case this is such a statement, close any statement transaction + ** opened by this VM before returning control to the user. This is to + ** ensure that statement-transactions are always nested, not overlapping. + ** If the open statement-transaction is not closed here, then the user + ** may step another VM that opens its own statement transaction. This + ** may lead to overlapping statement transactions. + ** + ** The statement transaction is never a top-level transaction. Hence + ** the RELEASE call below can never fail. + */ + assert( p->iStatement==0 || db->flags&SQLITE_CountRows ); + rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE); + assert( rc==SQLITE_OK ); + + /* Invalidate all ephemeral cursor row caches */ p->cacheCtr = (p->cacheCtr + 2)|1; - p->pResultRow = &aMem[pOp->p1]; -#ifdef SQLITE_DEBUG - { - Mem *pMem = p->pResultRow; - int i; - for(i=0; ip2; i++){ - assert( memIsValid(&pMem[i]) ); - REGISTER_TRACE(pOp->p1+i, &pMem[i]); - /* The registers in the result will not be used again when the - ** prepared statement restarts. This is because sqlite3_column() - ** APIs might have caused type conversions of made other changes to - ** the register values. Therefore, we can go ahead and break any - ** OP_SCopy dependencies. */ - pMem[i].pScopyFrom = 0; - } - } -#endif + + /* Make sure the results of the current row are \000 terminated + ** and have an assigned type. The results are de-ephemeralized as + ** a side effect. + */ + pMem = p->pResultSet = &aMem[pOp->p1]; + for(i=0; ip2; i++){ + assert( memIsValid(&pMem[i]) ); + Deephemeralize(&pMem[i]); + assert( (pMem[i].flags & MEM_Ephem)==0 + || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 ); + sqlite3VdbeMemNulTerminate(&pMem[i]); + REGISTER_TRACE(pOp->p1+i, &pMem[i]); + } if( db->mallocFailed ) goto no_mem; + if( db->mTrace & SQLITE_TRACE_ROW ){ - db->trace.xV2(SQLITE_TRACE_ROW, db->pTraceArg, p, 0); + db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0); } + + /* Return SQLITE_ROW + */ p->pc = (int)(pOp - aOp) + 1; rc = SQLITE_ROW; goto vdbe_return; } @@ -95280,41 +80281,23 @@ ** It is illegal for P1 and P3 to be the same register. Sometimes, ** if P3 is the same register as P2, the implementation is able ** to avoid a memcpy(). */ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ - i64 nByte; /* Total size of the output string or blob */ - u16 flags1; /* Initial flags for P1 */ - u16 flags2; /* Initial flags for P2 */ + i64 nByte; pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; pOut = &aMem[pOp->p3]; - testcase( pOut==pIn2 ); assert( pIn1!=pOut ); - flags1 = pIn1->flags; - testcase( flags1 & MEM_Null ); - testcase( pIn2->flags & MEM_Null ); - if( (flags1 | pIn2->flags) & MEM_Null ){ + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); break; } - if( (flags1 & (MEM_Str|MEM_Blob))==0 ){ - if( sqlite3VdbeMemStringify(pIn1,encoding,0) ) goto no_mem; - flags1 = pIn1->flags & ~MEM_Str; - }else if( (flags1 & MEM_Zero)!=0 ){ - if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem; - flags1 = pIn1->flags & ~MEM_Str; - } - flags2 = pIn2->flags; - if( (flags2 & (MEM_Str|MEM_Blob))==0 ){ - if( sqlite3VdbeMemStringify(pIn2,encoding,0) ) goto no_mem; - flags2 = pIn2->flags & ~MEM_Str; - }else if( (flags2 & MEM_Zero)!=0 ){ - if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem; - flags2 = pIn2->flags & ~MEM_Str; - } + if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem; + Stringify(pIn1, encoding); + Stringify(pIn2, encoding); nByte = pIn1->n + pIn2->n; if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ @@ -95321,17 +80304,12 @@ goto no_mem; } MemSetTypeFlag(pOut, MEM_Str); if( pOut!=pIn2 ){ memcpy(pOut->z, pIn2->z, pIn2->n); - assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) ); - pIn2->flags = flags2; } memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); - assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); - pIn1->flags = flags1; - if( encoding>SQLITE_UTF8 ) nByte &= ~1; pOut->z[nByte]=0; pOut->z[nByte+1] = 0; pOut->flags |= MEM_Term; pOut->n = (int)nByte; pOut->enc = encoding; @@ -95363,43 +80341,46 @@ */ /* Opcode: Divide P1 P2 P3 * * ** Synopsis: r[P3]=r[P2]/r[P1] ** ** Divide the value in register P1 by the value in register P2 -** and store the result in register P3 (P3=P2/P1). If the value in -** register P1 is zero, then the result is NULL. If either input is +** and store the result in register P3 (P3=P2/P1). If the value in +** register P1 is zero, then the result is NULL. If either input is ** NULL, the result is NULL. */ /* Opcode: Remainder P1 P2 P3 * * ** Synopsis: r[P3]=r[P2]%r[P1] ** -** Compute the remainder after integer register P2 is divided by -** register P1 and store the result in register P3. +** Compute the remainder after integer register P2 is divided by +** register P1 and store the result in register P3. ** If the value in register P1 is zero the result is NULL. ** If either operand is NULL, the result is NULL. */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ + char bIntint; /* Started out as two integer operands */ + u16 flags; /* Combined MEM_* flags from both inputs */ u16 type1; /* Numeric type of left operand */ u16 type2; /* Numeric type of right operand */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ pIn1 = &aMem[pOp->p1]; - type1 = pIn1->flags; + type1 = numericType(pIn1); pIn2 = &aMem[pOp->p2]; - type2 = pIn2->flags; + type2 = numericType(pIn2); pOut = &aMem[pOp->p3]; + flags = pIn1->flags | pIn2->flags; if( (type1 & type2 & MEM_Int)!=0 ){ -int_math: iA = pIn1->u.i; iB = pIn2->u.i; + bIntint = 1; switch( pOp->opcode ){ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; case OP_Divide: { @@ -95415,16 +80396,14 @@ break; } } pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); - }else if( ((type1 | type2) & MEM_Null)!=0 ){ + }else if( (flags & MEM_Null)!=0 ){ goto arithmetic_result_is_null; }else{ - type1 = numericType(pIn1); - type2 = numericType(pIn2); - if( (type1 & type2 & MEM_Int)!=0 ) goto int_math; + bIntint = 0; fp_math: rA = sqlite3VdbeRealValue(pIn1); rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ case OP_Add: rB += rA; break; @@ -95435,12 +80414,12 @@ if( rA==(double)0 ) goto arithmetic_result_is_null; rB /= rA; break; } default: { - iA = sqlite3VdbeIntValue(pIn1); - iB = sqlite3VdbeIntValue(pIn2); + iA = (i64)rA; + iB = (i64)rB; if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 ) iA = 1; rB = (double)(iB % iA); break; } @@ -95452,10 +80431,13 @@ if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } pOut->u.r = rB; MemSetTypeFlag(pOut, MEM_Real); + if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ + sqlite3VdbeIntegerAffinity(pOut); + } #endif } break; arithmetic_result_is_null: @@ -95483,10 +80465,121 @@ if( pOp->p1 ){ sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0); } 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, 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 */ + + /* 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: BitAnd P1 P2 P3 * * ** Synopsis: r[P3]=r[P1]&r[P2] ** ** Take the bit-wise AND of the values in register P1 and P2 and @@ -95568,46 +80661,45 @@ break; } /* Opcode: AddImm P1 P2 * * * ** Synopsis: r[P1]=r[P1]+P2 -** +** ** Add the constant P2 to the value in register P1. ** The result is always an integer. ** ** To force any register to be an integer, just add 0. */ case OP_AddImm: { /* in1 */ pIn1 = &aMem[pOp->p1]; memAboutToChange(p, pIn1); sqlite3VdbeMemIntegerify(pIn1); - *(u64*)&pIn1->u.i += (u64)pOp->p2; + pIn1->u.i += pOp->p2; break; } /* Opcode: MustBeInt P1 P2 * * * -** +** ** Force the value in register P1 to be an integer. If the value ** in P1 is not an integer and cannot be converted into an integer ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. */ -case OP_MustBeInt: { /* jump0, in1 */ +case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); if( (pIn1->flags & MEM_Int)==0 ){ - VdbeBranchTaken(1, 2); if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ goto jump_to_p2; } } } - VdbeBranchTaken(0, 2); MemSetTypeFlag(pIn1, MEM_Int); break; } #ifndef SQLITE_OMIT_FLOATING_POINT @@ -95620,26 +80712,23 @@ ** integers, for space efficiency, but after extraction we want them ** to have only a real value. */ case OP_RealAffinity: { /* in1 */ pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & (MEM_Int|MEM_IntReal) ){ - testcase( pIn1->flags & MEM_Int ); - testcase( pIn1->flags & MEM_IntReal ); + if( pIn1->flags & MEM_Int ){ sqlite3VdbeMemRealify(pIn1); - REGISTER_TRACE(pOp->p1, pIn1); } break; } #endif -#if !defined(SQLITE_OMIT_CAST) || !defined(SQLITE_OMIT_ANALYZE) +#ifndef SQLITE_OMIT_CAST /* Opcode: Cast P1 P2 * * * ** Synopsis: affinity(r[P1]) ** ** Force the value in register P1 to be the type defined by P2. -** +** **
                **
              • P2=='A' → BLOB **
              • P2=='B' → TEXT **
              • P2=='C' → NUMERIC **
              • P2=='D' → INTEGER @@ -95656,34 +80745,33 @@ testcase( pOp->p2==SQLITE_AFF_INTEGER ); testcase( pOp->p2==SQLITE_AFF_REAL ); pIn1 = &aMem[pOp->p1]; memAboutToChange(p, pIn1); rc = ExpandBlob(pIn1); - if( rc ) goto abort_due_to_error; - rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); - if( rc ) goto abort_due_to_error; + sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); UPDATE_MAX_BLOBSIZE(pIn1); - REGISTER_TRACE(pOp->p1, pIn1); + if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_CAST */ /* Opcode: Eq P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]==r[P1] ** ** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then -** jump to address P2. +** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then +** store the result of comparison in register P2. ** ** The SQLITE_AFF_MASK portion of P5 must be an affinity character - -** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made +** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made ** to coerce both inputs according to this affinity before the ** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric ** affinity is used. Note that the affinity conversions are stored ** back into the input registers P1 and P3. So this opcode can cause ** persistent changes to registers P1 and P3. ** -** Once any conversions have taken place, and neither value is NULL, +** Once any conversions have taken place, and neither value is NULL, ** the values are compared. If both values are blobs then memcmp() is ** used to determine the results of the comparison. If both values ** are text, then the appropriate collating function specified in ** P4 is used to do the comparison. If P4 is not specified then ** memcmp() is used to compare text string. If both values are @@ -95695,50 +80783,53 @@ ** true or false and is never NULL. If both operands are NULL then the result ** of comparison is true. If either operand is NULL then the result is false. ** If neither operand is NULL the result is the same as it would be if ** the SQLITE_NULLEQ flag were omitted from P5. ** -** This opcode saves the result of comparison for use by the new -** OP_Jump opcode. +** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the +** content of r[P2] is only changed if the new value is NULL or 0 (false). +** In other words, a prior r[P2] value will not be overwritten by 1 (true). */ /* Opcode: Ne P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]!=r[P1] ** ** This works just like the Eq opcode except that the jump is taken if ** the operands in registers P1 and P3 are not equal. See the Eq opcode for ** additional information. +** +** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the +** content of r[P2] is only changed if the new value is NULL or 1 (true). +** In other words, a prior r[P2] value will not be overwritten by 0 (false). */ /* Opcode: Lt P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]p1]; pIn3 = &aMem[pOp->p3]; flags1 = pIn1->flags; flags3 = pIn3->flags; - if( (flags1 & flags3 & MEM_Int)!=0 ){ - /* Common case of comparison of two integers */ - if( pIn3->u.i > pIn1->u.i ){ - if( sqlite3aGTb[pOp->opcode] ){ - VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); - goto jump_to_p2; - } - iCompare = +1; - VVA_ONLY( iCompareIsInit = 1; ) - }else if( pIn3->u.i < pIn1->u.i ){ - if( sqlite3aLTb[pOp->opcode] ){ - VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); - goto jump_to_p2; - } - iCompare = -1; - VVA_ONLY( iCompareIsInit = 1; ) - }else{ - if( sqlite3aEQb[pOp->opcode] ){ - VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); - goto jump_to_p2; - } - iCompare = 0; - VVA_ONLY( iCompareIsInit = 1; ) - } - VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3); - break; - } if( (flags1 | flags3)&MEM_Null ){ /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ /* If SQLITE_NULLEQ is set (which will only happen if the operator is ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ + assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); - assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB ); - testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 ); + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); if( (flags1&flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 ){ res = 0; /* Operands are equal */ }else{ - res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */ + res = 1; /* Operands are not equal */ } }else{ /* SQLITE_NULLEQ is clear and at least one operand is NULL, ** then the result is always NULL. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. */ - VdbeBranchTaken(2,3); - if( pOp->p5 & SQLITE_JUMPIFNULL ){ - goto jump_to_p2; + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &aMem[pOp->p2]; + iCompare = 1; /* Operands are not equal */ + memAboutToChange(p, pOut); + MemSetTypeFlag(pOut, MEM_Null); + REGISTER_TRACE(pOp->p2, pOut); + }else{ + VdbeBranchTaken(2,3); + if( pOp->p5 & SQLITE_JUMPIFNULL ){ + goto jump_to_p2; + } } - iCompare = 1; /* Operands are not equal */ - VVA_ONLY( iCompareIsInit = 1; ) break; } }else{ - /* Neither operand is NULL and we couldn't do the special high-speed - ** integer comparison case. So do a general-case comparison. */ + /* Neither operand is NULL. Do a comparison. */ affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity>=SQLITE_AFF_NUMERIC ){ if( (flags1 | flags3)&MEM_Str ){ - if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn1,0); - assert( flags3==pIn3->flags || CORRUPT_DB ); + testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */ flags3 = pIn3->flags; } - if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3,0); } } - }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){ - if( (flags1 & MEM_Str)!=0 ){ - pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); - }else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ + /* Handle the common case of integer comparison here, as an + ** optimization, to avoid a call to sqlite3MemCompare() */ + if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){ + if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; } + if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; } + res = 0; + goto compare_op; + } + }else if( affinity==SQLITE_AFF_TEXT ){ + if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); - testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); - if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str; + assert( pIn1!=pIn3 ); } - if( (flags3 & MEM_Str)!=0 ){ - pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); - }else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ + if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_Real ); - testcase( pIn3->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn3, encoding, 1); testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); } } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); } - - /* 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 ){ - res2 = sqlite3aLTb[pOp->opcode]; - }else if( res==0 ){ - res2 = sqlite3aEQb[pOp->opcode]; - }else{ - res2 = sqlite3aGTb[pOp->opcode]; - } - iCompare = res; - VVA_ONLY( iCompareIsInit = 1; ) +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; + } /* Undo any changes made by applyAffinity() to the input registers. */ + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); + pIn1->flags = flags1; assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); pIn3->flags = flags3; - assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); - pIn1->flags = flags1; - - VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); - if( res2 ){ - goto jump_to_p2; - } - break; -} - -/* Opcode: ElseEq * P2 * * * -** -** This opcode must follow an OP_Lt or OP_Gt comparison operator. There -** can be zero or more OP_ReleaseReg opcodes intervening, but no other -** opcodes are allowed to occur between this instruction and the previous -** OP_Lt or OP_Gt. -** -** If the result of an OP_Eq comparison on the same two operands as -** the prior OP_Lt or OP_Gt would have been true, then jump to P2. If -** the result of an OP_Eq comparison on the two previous operands -** would have been false or NULL, then fall through. -*/ -case OP_ElseEq: { /* same as TK_ESCAPE, jump */ - -#ifdef SQLITE_DEBUG - /* Verify the preconditions of this opcode - that it follows an OP_Lt or - ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */ - int iAddr; - for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){ - if( aOp[iAddr].opcode==OP_ReleaseReg ) continue; - assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt ); - break; - } -#endif /* SQLITE_DEBUG */ - assert( iCompareIsInit ); - VdbeBranchTaken(iCompare==0, 2); - if( iCompare==0 ) goto jump_to_p2; + + 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 + ** is only used in contexts where either: + ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0) + ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1) + ** Therefore it is not necessary to check the content of r[P2] for + ** NULL. */ + assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq ); + assert( res2==0 || res2==1 ); + testcase( res2==0 && pOp->opcode==OP_Eq ); + testcase( res2==1 && pOp->opcode==OP_Eq ); + testcase( res2==0 && pOp->opcode==OP_Ne ); + testcase( res2==1 && pOp->opcode==OP_Ne ); + if( (pOp->opcode==OP_Eq)==res2 ) break; + } + memAboutToChange(p, pOut); + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = res2; + REGISTER_TRACE(pOp->p2, pOut); + }else{ + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); + if( res2 ){ + goto jump_to_p2; + } + } + break; +} + +/* Opcode: ElseNotEq * P2 * * * +** +** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator. +** If result of an OP_Eq comparison on the same two operands +** would have be NULL or false (0), then then jump to P2. +** If the result of an OP_Eq comparison on the two previous operands +** would have been true (1), then fall through. +*/ +case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */ + assert( pOp>aOp ); + assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt ); + assert( pOp[-1].p5 & SQLITE_STOREP2 ); + VdbeBranchTaken(iCompare!=0, 2); + if( iCompare!=0 ) goto jump_to_p2; break; } /* Opcode: Permutation * * * 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 for the next opcode which must be -** an OP_Compare that has the OPFLAG_PERMUTE bit set in P5. +** The permutation is only valid until the next OP_Compare that has +** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should +** occur immediately prior to the OP_Compare. ** ** The first integer in the P4 integer array is the length of the array ** and does not become part of the permutation. */ case OP_Permutation: { @@ -95971,23 +81047,21 @@ ** only. The KeyInfo elements are used sequentially. ** ** The comparison is a sort comparison, so NULLs compare equal, ** NULLs are less than numbers, numbers are less than strings, ** and strings are less than blobs. -** -** This opcode must be immediately followed by an OP_Jump opcode. */ case OP_Compare: { int n; int i; int p1; int p2; const KeyInfo *pKeyInfo; - u32 idx; + int idx; CollSeq *pColl; /* Collating sequence to use on this term */ int bRev; /* True for DESCENDING sort order */ - u32 *aPermute; /* The permutation */ + int *aPermute; /* The permutation */ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){ aPermute = 0; }else{ assert( pOp>aOp ); @@ -96003,60 +81077,49 @@ p1 = pOp->p1; p2 = pOp->p2; #ifdef SQLITE_DEBUG if( aPermute ){ int k, mx = 0; - for(k=0; k(u32)mx ) mx = aPermute[k]; + for(k=0; kmx ) mx = aPermute[k]; assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); }else{ assert( p1>0 && p1+n<=(p->nMem+1 - p->nCursor)+1 ); assert( p2>0 && p2+n<=(p->nMem+1 - p->nCursor)+1 ); } #endif /* SQLITE_DEBUG */ for(i=0; inKeyField ); + assert( inField ); pColl = pKeyInfo->aColl[i]; - bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC); + bRev = pKeyInfo->aSortOrder[i]; iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); - VVA_ONLY( iCompareIsInit = 1; ) if( iCompare ){ - if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) - && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null)) - ){ - iCompare = -iCompare; - } if( bRev ) iCompare = -iCompare; break; } } - assert( pOp[1].opcode==OP_Jump ); break; } /* Opcode: Jump P1 P2 P3 * * ** ** Jump to the instruction at address P1, P2, or P3 depending on whether -** in the most recent OP_Compare instruction the P1 vector was less than, +** in the most recent OP_Compare instruction the P1 vector was less than ** equal to, or greater than the P2 vector, respectively. -** -** This opcode must immediately follow an OP_Compare opcode. */ case OP_Jump: { /* jump */ - assert( pOp>aOp && pOp[-1].opcode==OP_Compare ); - assert( iCompareIsInit ); if( iCompare<0 ){ - VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1]; + VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; }else if( iCompare==0 ){ - VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1]; + VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; }else{ - VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1]; + VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; } break; } /* Opcode: And P1 P2 P3 * * @@ -96082,12 +81145,22 @@ case OP_And: /* same as TK_AND, in1, in2, out3 */ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2); - v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2); + pIn1 = &aMem[pOp->p1]; + if( pIn1->flags & MEM_Null ){ + v1 = 2; + }else{ + v1 = sqlite3VdbeIntValue(pIn1)!=0; + } + pIn2 = &aMem[pOp->p2]; + if( pIn2->flags & MEM_Null ){ + v2 = 2; + }else{ + v2 = sqlite3VdbeIntValue(pIn2)!=0; + } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; @@ -96101,59 +81174,30 @@ MemSetTypeFlag(pOut, MEM_Int); } break; } -/* Opcode: IsTrue P1 P2 P3 P4 * -** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 -** -** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and -** IS NOT FALSE operators. -** -** Interpret the value in register P1 as a boolean value. Store that -** boolean (a 0 or 1) in register P2. Or if the value in register P1 is -** NULL, then the P3 is stored in register P2. Invert the answer if P4 -** is 1. -** -** The logic is summarized like this: -** -**
                  -**
                • If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE -**
                • If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE -**
                • If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE -**
                • If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE -**
                -*/ -case OP_IsTrue: { /* in1, out2 */ - assert( pOp->p4type==P4_INT32 ); - assert( pOp->p4.i==0 || pOp->p4.i==1 ); - assert( pOp->p3==0 || pOp->p3==1 ); - sqlite3VdbeMemSetInt64(&aMem[pOp->p2], - sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i); - break; -} - /* Opcode: Not P1 P2 * * * ** Synopsis: r[P2]= !r[P1] ** ** Interpret the value in register P1 as a boolean value. Store the -** boolean complement in register P2. If the value in register P1 is +** boolean complement in register P2. If the value in register P1 is ** NULL, then a NULL is stored in P2. */ case OP_Not: { /* same as TK_NOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; + sqlite3VdbeMemSetNull(pOut); if( (pIn1->flags & MEM_Null)==0 ){ - sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0)); - }else{ - sqlite3VdbeMemSetNull(pOut); + pOut->flags = MEM_Int; + pOut->u.i = !sqlite3VdbeIntValue(pIn1); } break; } /* Opcode: BitNot P1 P2 * * * -** Synopsis: r[P2]= ~r[P1] +** Synopsis: r[P1]= ~r[P1] ** ** Interpret the content of register P1 as an integer. Store the ** ones-complement of the P1 value into register P2. If P1 holds ** a NULL then store a NULL in P2. */ @@ -96210,29 +81254,34 @@ ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value ** in P1 is NULL then take the jump if and only if P3 is non-zero. */ -case OP_If: { /* jump, in1 */ - int c; - c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3); - VdbeBranchTaken(c!=0, 2); - if( c ) goto jump_to_p2; - break; -} - /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered false if it has a numeric value of zero. If the value ** in P1 is NULL then take the jump if and only if P3 is non-zero. */ +case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ int c; - c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3); + pIn1 = &aMem[pOp->p1]; + if( pIn1->flags & MEM_Null ){ + c = pOp->p3; + }else{ +#ifdef SQLITE_OMIT_FLOATING_POINT + c = sqlite3VdbeIntValue(pIn1)!=0; +#else + c = sqlite3VdbeRealValue(pIn1)!=0.0; +#endif + if( pOp->opcode==OP_IfNot ) c = !c; + } VdbeBranchTaken(c!=0, 2); - if( c ) goto jump_to_p2; + if( c ){ + goto jump_to_p2; + } break; } /* Opcode: IsNull P1 P2 * * * ** Synopsis: if r[P1]==NULL goto P2 @@ -96246,125 +81295,14 @@ goto jump_to_p2; } break; } -/* Opcode: IsType P1 P2 P3 P4 P5 -** Synopsis: if typeof(P1.P3) in P5 goto P2 -** -** Jump to P2 if the type of a column in a btree is one of the types specified -** by the P5 bitmask. -** -** P1 is normally a cursor on a btree for which the row decode cache is -** valid through at least column P3. In other words, there should have been -** a prior OP_Column for column P3 or greater. If the cursor is not valid, -** then this opcode might give spurious results. -** The the btree row has fewer than P3 columns, then use P4 as the -** datatype. -** -** If P1 is -1, then P3 is a register number and the datatype is taken -** from the value in that register. -** -** P5 is a bitmask of data types. SQLITE_INTEGER is the least significant -** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04. -** SQLITE_BLOB is 0x08. SQLITE_NULL is 0x10. -** -** WARNING: This opcode does not reliably distinguish between NULL and REAL -** when P1>=0. If the database contains a NaN value, this opcode will think -** that the datatype is REAL when it should be NULL. When P1<0 and the value -** is already stored in register P3, then this opcode does reliably -** distinguish between NULL and REAL. The problem only arises then P1>=0. -** -** Take the jump to address P2 if and only if the datatype of the -** value determined by P1 and P3 corresponds to one of the bits in the -** P5 bitmask. -** -*/ -case OP_IsType: { /* jump */ - VdbeCursor *pC; - u16 typeMask; - u32 serialType; - - assert( pOp->p1>=(-1) && pOp->p1nCursor ); - assert( pOp->p1>=0 || (pOp->p3>=0 && pOp->p3<=(p->nMem+1 - p->nCursor)) ); - if( pOp->p1>=0 ){ - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pOp->p3>=0 ); - if( pOp->p3nHdrParsed ){ - serialType = pC->aType[pOp->p3]; - if( serialType>=12 ){ - if( serialType&1 ){ - typeMask = 0x04; /* SQLITE_TEXT */ - }else{ - typeMask = 0x08; /* SQLITE_BLOB */ - } - }else{ - static const unsigned char aMask[] = { - 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2, - 0x01, 0x01, 0x10, 0x10 - }; - testcase( serialType==0 ); - testcase( serialType==1 ); - testcase( serialType==2 ); - testcase( serialType==3 ); - testcase( serialType==4 ); - testcase( serialType==5 ); - testcase( serialType==6 ); - testcase( serialType==7 ); - testcase( serialType==8 ); - testcase( serialType==9 ); - testcase( serialType==10 ); - testcase( serialType==11 ); - typeMask = aMask[serialType]; - } - }else{ - typeMask = 1 << (pOp->p4.i - 1); - testcase( typeMask==0x01 ); - testcase( typeMask==0x02 ); - testcase( typeMask==0x04 ); - testcase( typeMask==0x08 ); - testcase( typeMask==0x10 ); - } - }else{ - assert( memIsValid(&aMem[pOp->p3]) ); - typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1); - testcase( typeMask==0x01 ); - testcase( typeMask==0x02 ); - testcase( typeMask==0x04 ); - testcase( typeMask==0x08 ); - testcase( typeMask==0x10 ); - } - VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2); - if( typeMask & pOp->p5 ){ - goto jump_to_p2; - } - break; -} - -/* Opcode: ZeroOrNull P1 P2 P3 * * -** Synopsis: r[P2] = 0 OR NULL -** -** If both registers P1 and P3 are NOT NULL, then store a zero in -** register P2. If either registers P1 or P3 are NULL then put -** a NULL in register P2. -*/ -case OP_ZeroOrNull: { /* in1, in2, out2, in3 */ - if( (aMem[pOp->p1].flags & MEM_Null)!=0 - || (aMem[pOp->p3].flags & MEM_Null)!=0 - ){ - sqlite3VdbeMemSetNull(aMem + pOp->p2); - }else{ - sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0); - } - break; -} - /* Opcode: NotNull P1 P2 * * * ** Synopsis: if r[P1]!=NULL goto P2 ** -** Jump to P2 if the value in register P1 is not NULL. +** Jump to P2 if the value in register P1 is not NULL. */ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ @@ -96378,165 +81316,120 @@ ** ** 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. -** -** If P1 is not an open cursor, then this opcode is a no-op. */ case OP_IfNullRow: { /* jump */ - VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - if( pC && pC->nullRow ){ + 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 -** same 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( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ - sqlite3VdbeMemSetNull(pOut); - }else{ - if( pC->deferredMoveto ){ - rc = sqlite3VdbeFinishMoveto(pC); - if( rc ) goto abort_due_to_error; - } - if( sqlite3BtreeEof(pC->uc.pCursor) ){ - 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 cursor P1 column P2 +** Synopsis: r[P3]=PX ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional ** information about the format of the data.) Extract the P2-th column -** from this record. If there are less than (P2+1) +** from this record. If there are less that (P2+1) ** values in the record, extract a NULL. ** ** The value extracted is stored in register P3. ** ** 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. ** -** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed -** to only be used by the length() function or the equivalent. The content -** of large blobs is not loaded, thus saving CPU cycles. If the -** OPFLAG_TYPEOFARG bit is set then the result will only be used by the -** typeof() function or the IS NULL or IS NOT NULL operators or the -** equivalent. In this case, all content loading can be omitted. +** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor, +** then the cache of the cursor is reset prior to extracting the column. +** The first OP_Column against a pseudo-table after the value of the content +** register has changed should have this bit set. +** +** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then +** the result is guaranteed to only be used as the argument of a length() +** or typeof() function, respectively. The loading of large blobs can be +** skipped for length() and all content loading can be skipped for typeof(). */ -case OP_Column: { /* ncycle */ - u32 p2; /* column number to retrieve */ +case OP_Column: { + int p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ - BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */ + BtCursor *pCrsr; /* The BTree cursor */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ 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 */ - assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + p2 = pOp->p2; + + /* If the cursor cache is stale (meaning it is not currently point at + ** the correct row) then bring it up-to-date by doing the necessary + ** B-Tree seek. */ + rc = sqlite3VdbeCursorMoveto(&pC, &p2); + if( rc ) goto abort_due_to_error; + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - pC = p->apCsr[pOp->p1]; - p2 = (u32)pOp->p2; - -op_column_restart: + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); + assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pC!=0 ); - assert( p2<(u32)pC->nField - || (pC->eCurType==CURTYPE_PSEUDO && pC->seekResult==0) ); + assert( p2nField ); aOffset = pC->aOffset; - assert( aOffset==pC->aType+pC->nField ); assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ - if( pC->eCurType==CURTYPE_PSEUDO && pC->seekResult>0 ){ - /* For the special case of as pseudo-cursor, the seekResult field - ** identifies the register that holds the record */ - pReg = &aMem[pC->seekResult]; + if( pC->eCurType==CURTYPE_PSEUDO ){ + assert( pC->uc.pseudoTableReg>0 ); + pReg = &aMem[pC->uc.pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); - pC->payloadSize = pC->szRow = pReg->n; + pC->payloadSize = pC->szRow = avail = pReg->n; pC->aRow = (u8*)pReg->z; }else{ - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); sqlite3VdbeMemSetNull(pDest); goto op_column_out; } }else{ pCrsr = pC->uc.pCursor; - if( pC->deferredMoveto ){ - u32 iMap; - assert( !pC->isEphemeral ); - if( pC->ub.aAltMap && (iMap = pC->ub.aAltMap[1+p2])>0 ){ - pC = pC->pAltCursor; - p2 = iMap - 1; - goto op_column_restart; - } - rc = sqlite3VdbeFinishMoveto(pC); - if( rc ) goto abort_due_to_error; - }else if( sqlite3BtreeCursorHasMoved(pCrsr) ){ - rc = sqlite3VdbeHandleMovedCursor(pC); - if( rc ) goto abort_due_to_error; - goto op_column_restart; - } assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); - pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow); - assert( pC->szRow<=pC->payloadSize ); - assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */ + 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] ){ + goto too_big; + }else{ + pC->szRow = avail; + } } pC->cacheStatus = p->cacheCtr; - if( (aOffset[0] = pC->aRow[0])<0x80 ){ - pC->iHdrOffset = 1; - }else{ - pC->iHdrOffset = sqlite3GetVarint32(pC->aRow, aOffset); - } + pC->iHdrOffset = getVarint32(pC->aRow, offset); pC->nHdrParsed = 0; + aOffset[0] = offset; - if( pC->szRowaRow 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 ** dynamically allocated. */ pC->aRow = 0; @@ -96549,90 +81442,72 @@ ** types use so much data space that there can only be 4096 and 32 of ** them, respectively. So the maximum header length results from a ** 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( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){ - goto op_column_corrupt; - } - }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. + if( offset > 98307 || offset > pC->payloadSize ){ + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } + }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. */ zData = pC->aRow; assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ - testcase( aOffset[0]==0 ); goto op_column_read_header; } - }else if( sqlite3BtreeCursorHasMoved(pC->uc.pCursor) ){ - rc = sqlite3VdbeHandleMovedCursor(pC); - if( rc ) goto abort_due_to_error; - goto op_column_restart; } /* Make sure at least the first p2+1 entries of the header have been ** parsed and valid information is in aOffset[] and pC->aType[]. */ if( pC->nHdrParsed<=p2 ){ /* If there is more header available for parsing in the record, try - ** to extract additional fields up through the p2+1-th field + ** to extract additional fields up through the p2+1-th field */ if( pC->iHdrOffsetaRow==0 ){ memset(&sMem, 0, sizeof(sMem)); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pC->uc.pCursor,aOffset[0],&sMem); + rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem); if( rc!=SQLITE_OK ) goto abort_due_to_error; zData = (u8*)sMem.z; }else{ zData = pC->aRow; } - + /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */ op_column_read_header: i = pC->nHdrParsed; offset64 = aOffset[i]; zHdr = zData + pC->iHdrOffset; zEndHdr = zData + aOffset[0]; - testcase( zHdr>=zEndHdr ); do{ - if( (pC->aType[i] = t = zHdr[0])<0x80 ){ + if( (t = zHdr[0])<0x80 ){ zHdr++; offset64 += sqlite3VdbeOneByteSerialTypeLen(t); }else{ zHdr += sqlite3GetVarint32(zHdr, &t); - pC->aType[i] = t; offset64 += sqlite3VdbeSerialTypeLen(t); } - aOffset[++i] = (u32)(offset64 & 0xffffffff); - }while( (u32)i<=p2 && zHdraType[i++] = t; + aOffset[i] = (u32)(offset64 & 0xffffffff); + }while( i<=p2 && zHdr=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize)) || (offset64 > pC->payloadSize) ){ - if( aOffset[0]==0 ){ - i = 0; - zHdr = zEndHdr; - }else{ - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); - goto op_column_corrupt; - } + if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; } pC->nHdrParsed = i; pC->iHdrOffset = (u32)(zHdr - zData); if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); @@ -96643,12 +81518,10 @@ /* If after trying to extract new entries from the header, nHdrParsed is ** still not up to p2, that means that the record has fewer than p2 ** columns. So the result will be either the default value or a NULL. */ if( pC->nHdrParsed<=p2 ){ - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); if( pOp->p4type==P4_MEM ){ sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); }else{ sqlite3VdbeMemSetNull(pDest); } @@ -96662,12 +81535,10 @@ ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are ** all valid. */ assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); assert( sqlite3VdbeCheckMemInvariants(pDest) ); if( VdbeMemDynamic(pDest) ){ sqlite3VdbeMemSetNull(pDest); } assert( t==pC->aType[p2] ); @@ -96684,11 +81555,10 @@ */ static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term }; pDest->n = len = (t-12)/2; pDest->enc = encoding; if( pDest->szMalloc < len+2 ){ - if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big; pDest->flags = MEM_Null; if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem; }else{ pDest->z = pDest->zMalloc; } @@ -96696,163 +81566,41 @@ pDest->z[len] = 0; pDest->z[len+1] = 0; pDest->flags = aFlag[t&1]; } }else{ - u8 p5; pDest->enc = encoding; - assert( pDest->db==db ); /* This branch happens only when content is on overflow pages */ - if( ((p5 = (pOp->p5 & OPFLAG_BYTELENARG))!=0 - && (p5==OPFLAG_TYPEOFARG - || (t>=12 && ((t&1)==0 || p5==OPFLAG_BYTELENARG)) - ) - ) - || sqlite3VdbeSerialTypeLen(t)==0 + if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 + && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) + || (len = sqlite3VdbeSerialTypeLen(t))==0 ){ /* Content is irrelevant for ** 1. the typeof() function, ** 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. + ** content from disk. ** ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the ** buffer passed to it, debugging function VdbeMemPrettyPrint() may - ** read more. Use the global constant sqlite3CtypeMap[] as the array, - ** as that array is 256 bytes long (plenty for VdbeMemPrettyPrint()) - ** and it begins with a bunch of zeros. + ** read up to 16. So 16 bytes of bogus content is supplied. */ - sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); + static u8 aZero[16]; /* This is the bogus content */ + sqlite3VdbeSerialGet(aZero, t, pDest); }else{ - rc = vdbeColumnFromOverflow(pC, p2, t, aOffset[p2], - p->cacheCtr, colCacheCtr, pDest); - if( rc ){ - if( rc==SQLITE_NOMEM ) goto no_mem; - if( rc==SQLITE_TOOBIG ) goto too_big; - goto abort_due_to_error; - } + 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; } } op_column_out: 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: TypeCheck P1 P2 P3 P4 * -** Synopsis: typecheck(r[P1@P2]) -** -** Apply affinities to the range of P2 registers beginning with P1. -** Take the affinities from the Table object in P4. If any value -** cannot be coerced into the correct type, then raise an error. -** -** This opcode is similar to OP_Affinity except that this opcode -** forces the register type to the Table column type. This is used -** to implement "strict affinity". -** -** GENERATED ALWAYS AS ... STATIC columns are only checked if P3 -** is zero. When P3 is non-zero, no type checking occurs for -** static generated columns. Virtual columns are computed at query time -** and so they are never checked. -** -** Preconditions: -** -**
                  -**
                • P2 should be the number of non-virtual columns in the -** table of P4. -**
                • Table P4 should be a STRICT table. -**
                -** -** If any precondition is false, an assertion fault occurs. -*/ -case OP_TypeCheck: { - Table *pTab; - Column *aCol; - int i; - - assert( pOp->p4type==P4_TABLE ); - pTab = pOp->p4.pTab; - assert( pTab->tabFlags & TF_Strict ); - assert( pTab->nNVCol==pOp->p2 ); - aCol = pTab->aCol; - pIn1 = &aMem[pOp->p1]; - for(i=0; inCol; i++){ - if( aCol[i].colFlags & COLFLAG_GENERATED ){ - if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue; - if( pOp->p3 ){ pIn1++; continue; } - } - assert( pIn1 < &aMem[pOp->p1+pOp->p2] ); - applyAffinity(pIn1, aCol[i].affinity, encoding); - if( (pIn1->flags & MEM_Null)==0 ){ - switch( aCol[i].eCType ){ - case COLTYPE_BLOB: { - if( (pIn1->flags & MEM_Blob)==0 ) goto vdbe_type_error; - break; - } - case COLTYPE_INTEGER: - case COLTYPE_INT: { - if( (pIn1->flags & MEM_Int)==0 ) goto vdbe_type_error; - break; - } - case COLTYPE_TEXT: { - if( (pIn1->flags & MEM_Str)==0 ) goto vdbe_type_error; - break; - } - case COLTYPE_REAL: { - testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real ); - assert( (pIn1->flags & MEM_IntReal)==0 ); - if( pIn1->flags & MEM_Int ){ - /* When applying REAL affinity, if the result is still an MEM_Int - ** that will fit in 6 bytes, then change the type to MEM_IntReal - ** so that we keep the high-resolution integer value but know that - ** the type really wants to be REAL. */ - testcase( pIn1->u.i==140737488355328LL ); - testcase( pIn1->u.i==140737488355327LL ); - testcase( pIn1->u.i==-140737488355328LL ); - testcase( pIn1->u.i==-140737488355329LL ); - if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL){ - pIn1->flags |= MEM_IntReal; - pIn1->flags &= ~MEM_Int; - }else{ - pIn1->u.r = (double)pIn1->u.i; - pIn1->flags |= MEM_Real; - pIn1->flags &= ~MEM_Int; - } - }else if( (pIn1->flags & (MEM_Real|MEM_IntReal))==0 ){ - goto vdbe_type_error; - } - break; - } - default: { - /* COLTYPE_ANY. Accept anything. */ - break; - } - } - } - REGISTER_TRACE((int)(pIn1-aMem), pIn1); - pIn1++; - } - assert( pIn1 == &aMem[pOp->p1+pOp->p2] ); - break; - -vdbe_type_error: - sqlite3VdbeError(p, "cannot store %s value in %s column %s.%s", - vdbeMemTypeName(pIn1), sqlite3StdType[aCol[i].eCType-1], - pTab->zName, aCol[i].zCnName); - rc = SQLITE_CONSTRAINT_DATATYPE; - goto abort_due_to_error; } /* Opcode: Affinity P1 P2 * P4 * ** Synopsis: affinity(r[P1@P2]) ** @@ -96868,37 +81616,16 @@ zAffinity = pOp->p4.z; assert( zAffinity!=0 ); assert( pOp->p2>0 ); assert( zAffinity[pOp->p2]==0 ); pIn1 = &aMem[pOp->p1]; - while( 1 /*exit-by-break*/ ){ + do{ assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] ); - assert( zAffinity[0]==SQLITE_AFF_NONE || memIsValid(pIn1) ); - applyAffinity(pIn1, zAffinity[0], encoding); - if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){ - /* When applying REAL affinity, if the result is still an MEM_Int - ** that will fit in 6 bytes, then change the type to MEM_IntReal - ** so that we keep the high-resolution integer value but know that - ** the type really wants to be REAL. */ - testcase( pIn1->u.i==140737488355328LL ); - testcase( pIn1->u.i==140737488355327LL ); - testcase( pIn1->u.i==-140737488355328LL ); - testcase( pIn1->u.i==-140737488355329LL ); - if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){ - pIn1->flags |= MEM_IntReal; - pIn1->flags &= ~MEM_Int; - }else{ - pIn1->u.r = (double)pIn1->u.i; - pIn1->flags |= MEM_Real; - pIn1->flags &= ~(MEM_Int|MEM_Str); - } - } - REGISTER_TRACE((int)(pIn1-aMem), pIn1); - zAffinity++; - if( zAffinity[0]==0 ) break; + assert( memIsValid(pIn1) ); + applyAffinity(pIn1, *(zAffinity++), encoding); pIn1++; - } + }while( zAffinity[0] ); break; } /* Opcode: MakeRecord P1 P2 P3 P4 * ** Synopsis: r[P3]=mkrec(r[P1@P2]) @@ -96913,23 +81640,13 @@ ** ** The mapping from character to affinity is given by the SQLITE_AFF_ ** macros defined in sqliteInt.h. ** ** If P4 is NULL then all index fields have the affinity BLOB. -** -** The meaning of P5 depends on whether or not the SQLITE_ENABLE_NULL_TRIM -** compile-time option is enabled: -** -** * If SQLITE_ENABLE_NULL_TRIM is enabled, then the P5 is the index -** of the right-most table that can be null-trimmed. -** -** * If SQLITE_ENABLE_NULL_TRIM is omitted, then P5 has the value -** OPFLAG_NOCHNG_MAGIC if the OP_MakeRecord opcode is allowed to -** accept no-change records with serial_type 10. This value is -** only used inside an assert() and does not affect the end result. */ case OP_MakeRecord: { + u8 *zNewRecord; /* A buffer to hold the data for the new record */ Mem *pRec; /* The new record */ u64 nData; /* Number of bytes of data space */ int nHdr; /* Number of bytes of header space */ i64 nByte; /* Data space required for this record */ i64 nZero; /* Number of zero bytes at the end of the record */ @@ -96937,25 +81654,26 @@ u32 serial_type; /* Type field */ Mem *pData0; /* First field to be combined into the record */ Mem *pLast; /* Last field of the record */ int nField; /* Number of fields in the record */ char *zAffinity; /* The affinity string for the record */ + int file_format; /* File format to use for encoding */ + int i; /* Space used in zNewRecord[] header */ + int j; /* Space used in zNewRecord[] content */ u32 len; /* Length of a field */ - u8 *zHdr; /* Where to write next byte of the header */ - u8 *zPayload; /* Where to write next byte of the payload */ /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------------ - ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | + ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | ** ------------------------------------------------------------------------ ** ** Data(0) is taken from register P1. Data(1) comes from register P1+1 ** and so forth. ** - ** Each type field is a varint representing the serial type of the + ** Each type field is a varint representing the serial type of the ** corresponding data element (see sqlite3VdbeSerialType()). The ** hdr-size field is also a varint which is the offset from the beginning ** of the record to data0. */ nData = 0; /* Number of bytes of data space */ @@ -96965,10 +81683,11 @@ zAffinity = pOp->p4.z; assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem+1 - p->nCursor)+1 ); pData0 = &aMem[nField]; nField = pOp->p2; pLast = &pData0[nField-1]; + file_format = p->minWriteFileFormat; /* Identify the output register */ assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); @@ -96977,18 +81696,11 @@ */ assert( pData0<=pLast ); if( zAffinity ){ pRec = pData0; do{ - applyAffinity(pRec, zAffinity[0], encoding); - if( zAffinity[0]==SQLITE_AFF_REAL && (pRec->flags & MEM_Int) ){ - pRec->flags |= MEM_IntReal; - pRec->flags &= ~(MEM_Int); - } - REGISTER_TRACE((int)(pRec-aMem), pRec); - zAffinity++; - pRec++; + applyAffinity(pRec++, *(zAffinity++), encoding); assert( zAffinity[0]==0 || pRec<=pLast ); }while( zAffinity[0] ); } #ifdef SQLITE_ENABLE_NULL_TRIM @@ -97004,126 +81716,28 @@ } } #endif /* Loop through the elements that will make up the record to figure - ** out how much space is required for the new record. After this loop, - ** the Mem.uTemp field of each term should hold the serial-type that will - ** be used for that term in the generated record: - ** - ** Mem.uTemp value type - ** --------------- --------------- - ** 0 NULL - ** 1 1-byte signed integer - ** 2 2-byte signed integer - ** 3 3-byte signed integer - ** 4 4-byte signed integer - ** 5 6-byte signed integer - ** 6 8-byte signed integer - ** 7 IEEE float - ** 8 Integer constant 0 - ** 9 Integer constant 1 - ** 10,11 reserved for expansion - ** N>=12 and even BLOB - ** N>=13 and odd text - ** - ** The following additional values are computed: - ** nHdr Number of bytes needed for the record header - ** nData Number of bytes of data space needed for the record - ** nZero Zero bytes at the end of the record + ** out how much space is required for the new record. */ pRec = pLast; do{ assert( memIsValid(pRec) ); - if( pRec->flags & MEM_Null ){ - if( pRec->flags & MEM_Zero ){ - /* 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(). */ -#ifndef SQLITE_ENABLE_NULL_TRIM - assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB ); -#endif - pRec->uTemp = 10; - }else{ - pRec->uTemp = 0; - } - nHdr++; - }else if( pRec->flags & (MEM_Int|MEM_IntReal) ){ - /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ - i64 i = pRec->u.i; - u64 uu; - testcase( pRec->flags & MEM_Int ); - testcase( pRec->flags & MEM_IntReal ); - if( i<0 ){ - uu = ~i; - }else{ - uu = i; - } - nHdr++; - testcase( uu==127 ); testcase( uu==128 ); - testcase( uu==32767 ); testcase( uu==32768 ); - testcase( uu==8388607 ); testcase( uu==8388608 ); - testcase( uu==2147483647 ); testcase( uu==2147483648LL ); - testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL ); - if( uu<=127 ){ - if( (i&1)==i && p->minWriteFileFormat>=4 ){ - pRec->uTemp = 8+(u32)uu; - }else{ - nData++; - pRec->uTemp = 1; - } - }else if( uu<=32767 ){ - nData += 2; - pRec->uTemp = 2; - }else if( uu<=8388607 ){ - nData += 3; - pRec->uTemp = 3; - }else if( uu<=2147483647 ){ - nData += 4; - pRec->uTemp = 4; - }else if( uu<=140737488355327LL ){ - nData += 6; - pRec->uTemp = 5; - }else{ - nData += 8; - if( pRec->flags & MEM_IntReal ){ - /* If the value is IntReal and is going to take up 8 bytes to store - ** as an integer, then we might as well make it an 8-byte floating - ** point value */ - pRec->u.r = (double)pRec->u.i; - pRec->flags &= ~MEM_IntReal; - pRec->flags |= MEM_Real; - pRec->uTemp = 7; - }else{ - pRec->uTemp = 6; - } - } - }else if( pRec->flags & MEM_Real ){ - nHdr++; - nData += 8; - pRec->uTemp = 7; - }else{ - assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) ); - assert( pRec->n>=0 ); - len = (u32)pRec->n; - serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0); - if( pRec->flags & MEM_Zero ){ - serial_type += pRec->u.nZero*2; - if( nData ){ - if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; - len += pRec->u.nZero; - }else{ - nZero += pRec->u.nZero; - } - } - nData += len; - nHdr += sqlite3VarintLen(serial_type); - pRec->uTemp = serial_type; - } + pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); + if( pRec->flags & MEM_Zero ){ + if( nData ){ + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; + }else{ + nZero += pRec->u.nZero; + len -= pRec->u.nZero; + } + } + nData += len; + testcase( serial_type==127 ); + testcase( serial_type==128 ); + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); if( pRec==pData0 ) break; pRec--; }while(1); /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint @@ -97140,147 +81754,81 @@ nVarint = sqlite3VarintLen(nHdr); nHdr += nVarint; if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } - /* Make sure the output register has a buffer large enough to store + /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to ** be one of the input registers (because the following call to ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). */ - if( nByte+nZero<=pOut->szMalloc ){ - /* The output register is already large enough to hold the record. - ** No error checks or buffer enlargement is required */ - pOut->z = pOut->zMalloc; - }else{ - /* Need to make sure that the output is not too big and then enlarge - ** the output register to hold the full result */ - if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ - goto no_mem; - } - } + if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ + goto no_mem; + } + zNewRecord = (u8 *)pOut->z; + + /* Write the record */ + i = putVarint32(zNewRecord, nHdr); + j = nHdr; + assert( pData0<=pLast ); + pRec = pData0; + do{ + serial_type = pRec->uTemp; + /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more + ** additional varints, one per column. */ + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ + /* EVIDENCE-OF: R-64536-51728 The values for each column in the record + ** immediately follow the header. */ + j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ + }while( (++pRec)<=pLast ); + assert( i==nHdr ); + assert( j==nByte ); + + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pOut->n = (int)nByte; pOut->flags = MEM_Blob; if( nZero ){ pOut->u.nZero = nZero; pOut->flags |= MEM_Zero; } + REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); - zHdr = (u8 *)pOut->z; - zPayload = zHdr + nHdr; - - /* Write the record */ - if( nHdr<0x80 ){ - *(zHdr++) = nHdr; - }else{ - zHdr += sqlite3PutVarint(zHdr,nHdr); - } - assert( pData0<=pLast ); - pRec = pData0; - while( 1 /*exit-by-break*/ ){ - serial_type = pRec->uTemp; - /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more - ** additional varints, one per column. - ** EVIDENCE-OF: R-64536-51728 The values for each column in the record - ** immediately follow the header. */ - if( serial_type<=7 ){ - *(zHdr++) = serial_type; - if( serial_type==0 ){ - /* NULL value. No change in zPayload */ - }else{ - u64 v; - if( serial_type==7 ){ - assert( sizeof(v)==sizeof(pRec->u.r) ); - memcpy(&v, &pRec->u.r, sizeof(v)); - swapMixedEndianFloat(v); - }else{ - v = pRec->u.i; - } - len = sqlite3SmallTypeSizes[serial_type]; - assert( len>=1 && len<=8 && len!=5 && len!=7 ); - switch( len ){ - default: zPayload[7] = (u8)(v&0xff); v >>= 8; - zPayload[6] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 6: zPayload[5] = (u8)(v&0xff); v >>= 8; - zPayload[4] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 4: zPayload[3] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 3: zPayload[2] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 2: zPayload[1] = (u8)(v&0xff); v >>= 8; - /* no break */ deliberate_fall_through - case 1: zPayload[0] = (u8)(v&0xff); - } - zPayload += len; - } - }else if( serial_type<0x80 ){ - *(zHdr++) = serial_type; - if( serial_type>=14 && pRec->n>0 ){ - assert( pRec->z!=0 ); - memcpy(zPayload, pRec->z, pRec->n); - zPayload += pRec->n; - } - }else{ - zHdr += sqlite3PutVarint(zHdr, serial_type); - if( pRec->n ){ - assert( pRec->z!=0 ); - memcpy(zPayload, pRec->z, pRec->n); - zPayload += pRec->n; - } - } - if( pRec==pLast ) break; - pRec++; - } - assert( nHdr==(int)(zHdr - (u8*)pOut->z) ); - assert( nByte==(int)(zPayload - (u8*)pOut->z) ); - - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - REGISTER_TRACE(pOp->p3, pOut); break; } -/* Opcode: Count P1 P2 P3 * * +/* Opcode: Count P1 P2 * * * ** Synopsis: r[P2]=count() ** -** Store the number of entries (an integer value) in the table or index -** opened by cursor P1 in register P2. -** -** If P3==0, then an exact count is obtained, which involves visiting -** every btree page of the table. But if P3 is non-zero, an estimate -** is returned based on the current cursor position. +** Store the number of entries (an integer value) in the table or index +** opened by cursor P1 in register P2 */ +#ifndef SQLITE_OMIT_BTREECOUNT case OP_Count: { /* out2 */ i64 nEntry; BtCursor *pCrsr; assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE ); pCrsr = p->apCsr[pOp->p1]->uc.pCursor; assert( pCrsr ); - if( pOp->p3 ){ - nEntry = sqlite3BtreeRowCountEst(pCrsr); - }else{ - nEntry = 0; /* Not needed. Only used to silence a warning. */ - rc = sqlite3BtreeCount(db, pCrsr, &nEntry); - if( rc ) goto abort_due_to_error; - } + nEntry = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3BtreeCount(pCrsr, &nEntry); + if( rc ) goto abort_due_to_error; pOut = out2Prerelease(p, pOp); pOut->u.i = nEntry; - goto check_for_interrupt; + break; } +#endif /* Opcode: Savepoint P1 * * P4 * ** ** Open, release or rollback the savepoint named by parameter P4, depending -** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN). -** To release (commit) an existing savepoint set P1==1 (SAVEPOINT_RELEASE). -** To rollback an existing savepoint set P1==2 (SAVEPOINT_ROLLBACK). +** on the value of P1. To open a new savepoint, P1==0. To release (commit) an +** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. */ case OP_Savepoint: { int p1; /* Value of P1 operand */ char *zName; /* Name of savepoint */ int nName; @@ -97292,21 +81840,21 @@ p1 = pOp->p1; zName = pOp->p4.z; /* Assert that the p1 parameter is valid. Also that if there is no open - ** transaction, then there cannot be any savepoints. + ** transaction, then there cannot be any savepoints. */ assert( db->pSavepoint==0 || db->autoCommit==0 ); assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); assert( db->pSavepoint || db->isTransactionSavepoint==0 ); assert( checkSavepointCount(db) ); assert( p->bIsReader ); if( p1==SAVEPOINT_BEGIN ){ if( db->nVdbeWrite>0 ){ - /* A new savepoint cannot be created if there are active write + /* A new savepoint cannot be created if there are active write ** statements (i.e. open read/write incremental blob handles). */ sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress"); rc = SQLITE_BUSY; }else{ @@ -97326,11 +81874,11 @@ /* Create a new savepoint structure. */ pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1); if( pNew ){ pNew->zName = (char *)&pNew[1]; memcpy(pNew->zName, zName, nName+1); - + /* If there is no open transaction, then mark this as a special ** "transaction savepoint". */ if( db->autoCommit ){ db->autoCommit = 0; db->isTransactionSavepoint = 1; @@ -97344,37 +81892,36 @@ pNew->nDeferredCons = db->nDeferredCons; pNew->nDeferredImmCons = db->nDeferredImmCons; } } }else{ - assert( p1==SAVEPOINT_RELEASE || p1==SAVEPOINT_ROLLBACK ); iSavepoint = 0; /* Find the named savepoint. If there is no such savepoint, then an ** an error is returned to the user. */ for( - pSavepoint = db->pSavepoint; + pSavepoint = db->pSavepoint; pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); pSavepoint = pSavepoint->pNext ){ iSavepoint++; } if( !pSavepoint ){ sqlite3VdbeError(p, "no such savepoint: %s", zName); rc = SQLITE_ERROR; }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ - /* It is not possible to release (commit) a savepoint if there are + /* It is not possible to release (commit) a savepoint if there are ** active write statements. */ sqlite3VdbeError(p, "cannot release savepoint - " "SQL statements in progress"); rc = SQLITE_BUSY; }else{ /* Determine whether or not this is a transaction savepoint. If so, - ** and this is a RELEASE command, then the current transaction - ** is committed. + ** and this is a RELEASE command, then the current transaction + ** is committed. */ int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; if( isTransaction && p1==SAVEPOINT_RELEASE ){ if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; @@ -97384,56 +81931,50 @@ p->pc = (int)(pOp - aOp); db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } + db->isTransactionSavepoint = 0; rc = p->rc; - if( rc ){ - db->autoCommit = 0; - }else{ - db->isTransactionSavepoint = 0; - } }else{ int isSchemaChange; iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ - isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0; + isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; for(ii=0; iinDb; ii++){ rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT_ROLLBACK, isSchemaChange==0); if( rc!=SQLITE_OK ) goto abort_due_to_error; } }else{ - assert( p1==SAVEPOINT_RELEASE ); isSchemaChange = 0; } for(ii=0; iinDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } if( isSchemaChange ){ - sqlite3ExpirePreparedStatements(db, 0); + sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); - db->mDbFlags |= DBFLAG_SchemaChange; + db->flags = (db->flags | SQLITE_InternChanges); } } - if( rc ) goto abort_due_to_error; - - /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all + + /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all ** savepoints nested inside of the savepoint being operated on. */ while( db->pSavepoint!=pSavepoint ){ pTmp = db->pSavepoint; db->pSavepoint = pTmp->pNext; sqlite3DbFree(db, pTmp); db->nSavepoint--; } - /* If it is a RELEASE, then destroy the savepoint being operated on - ** too. If it is a ROLLBACK TO, then set the number of deferred + /* If it is a RELEASE, then destroy the savepoint being operated on + ** too. If it is a ROLLBACK TO, then set the number of deferred ** constraint violations present in the database to the value stored ** when the savepoint was created. */ if( p1==SAVEPOINT_RELEASE ){ assert( pSavepoint==db->pSavepoint ); db->pSavepoint = pSavepoint->pNext; @@ -97440,11 +81981,10 @@ sqlite3DbFree(db, pSavepoint); if( !isTransaction ){ db->nSavepoint--; } }else{ - assert( p1==SAVEPOINT_ROLLBACK ); db->nDeferredCons = pSavepoint->nDeferredCons; db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ @@ -97452,14 +81992,11 @@ if( rc!=SQLITE_OK ) goto abort_due_to_error; } } } if( rc ) goto abort_due_to_error; - if( p->eVdbeState==VDBE_HALT_STATE ){ - rc = SQLITE_DONE; - goto vdbe_return; - } + break; } /* Opcode: AutoCommit P1 P2 * * * ** @@ -97486,11 +82023,11 @@ assert( desiredAutoCommit==1 ); sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); db->autoCommit = 1; }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ /* If this instruction implements a COMMIT and other VMs are writing - ** return an error indicating that the other VMs must complete first. + ** return an error indicating that the other VMs must complete first. */ sqlite3VdbeError(p, "cannot commit transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; goto abort_due_to_error; @@ -97503,10 +82040,11 @@ p->pc = (int)(pOp - aOp); db->autoCommit = (u8)(1-desiredAutoCommit); p->rc = rc = SQLITE_BUSY; goto vdbe_return; } + assert( db->nStatement==0 ); sqlite3CloseSavepoints(db); if( p->rc==SQLITE_OK ){ rc = SQLITE_DONE; }else{ rc = SQLITE_ERROR; @@ -97515,25 +82053,24 @@ }else{ sqlite3VdbeError(p, (!desiredAutoCommit)?"cannot start a transaction within a transaction":( (iRollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active")); - + rc = SQLITE_ERROR; goto abort_due_to_error; } - /*NOTREACHED*/ assert(0); + break; } /* Opcode: Transaction P1 P2 P3 P4 P5 ** ** Begin a transaction on database P1 if a transaction is not already ** active. -** If P2 is non-zero, then a write-transaction is started, or if a +** If P2 is non-zero, then a write-transaction is started, or if a ** read-transaction is already active, it is upgraded to a write-transaction. -** If P2 is zero, then a read-transaction is started. If P2 is 2 or more -** then an exclusive transaction is started. +** If P2 is zero, then a read-transaction is started. ** ** P1 is the index of the database file on which the transaction is ** started. Index 0 is the main database file and index 1 is the ** file used for temporary tables. Indices of 2 or more are used for ** attached databases. @@ -97559,35 +82096,25 @@ ** halts. The sqlite3_step() wrapper function might then reprepare the ** statement and rerun it from the beginning. */ case OP_Transaction: { Btree *pBt; - Db *pDb; - int iMeta = 0; + int iMeta; + int iGen; assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); - assert( pOp->p2>=0 && pOp->p2<=2 ); assert( pOp->p1>=0 && pOp->p1nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); - assert( rc==SQLITE_OK ); - if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){ - if( db->flags & SQLITE_QueryOnly ){ - /* Writes prohibited by the "PRAGMA query_only=TRUE" statement */ - rc = SQLITE_READONLY; - }else{ - /* Writes prohibited due to a prior SQLITE_CORRUPT in the current - ** transaction */ - rc = SQLITE_CORRUPT; - } + if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ + rc = SQLITE_READONLY; goto abort_due_to_error; } - pDb = &db->aDb[pOp->p1]; - pBt = pDb->pBt; + pBt = db->aDb[pOp->p1].pBt; if( pBt ){ - rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta); + rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); testcase( rc==SQLITE_BUSY_SNAPSHOT ); testcase( rc==SQLITE_BUSY_RECOVERY ); if( rc!=SQLITE_OK ){ if( (rc&0xff)==SQLITE_BUSY ){ p->pc = (int)(pOp - aOp); @@ -97595,18 +82122,17 @@ goto vdbe_return; } goto abort_due_to_error; } - if( p->usesStmtJournal - && pOp->p2 - && (db->autoCommit==0 || db->nVdbeRead>1) + if( pOp->p2 && p->usesStmtJournal + && (db->autoCommit==0 || db->nVdbeRead>1) ){ - assert( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ); + assert( sqlite3BtreeIsInTrans(pBt) ); if( p->iStatement==0 ){ assert( db->nStatement>=0 && db->nSavepoint>=0 ); - db->nStatement++; + db->nStatement++; p->iStatement = db->nSavepoint + db->nStatement; } rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1); if( rc==SQLITE_OK ){ @@ -97617,46 +82143,43 @@ ** counter. If the statement transaction needs to be rolled back, ** the value of this counter needs to be restored too. */ p->nStmtDefCons = db->nDeferredCons; p->nStmtDefImmCons = db->nDeferredImmCons; } - } - assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); - if( rc==SQLITE_OK - && pOp->p5 - && (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i) - ){ - /* + + /* Gather the schema version number for checking: ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema ** version is checked to ensure that the schema has not changed since the ** SQL statement was prepared. */ + sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); + iGen = db->aDb[pOp->p1].pSchema->iGeneration; + }else{ + iGen = iMeta = 0; + } + assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); + if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); - /* If the schema-cookie from the database file matches the cookie + /* If the schema-cookie from the database file matches the cookie ** stored with the in-memory representation of the schema, do ** not reload the schema from the database file. ** ** If virtual-tables are in use, this is not just an optimization. ** Often, v-tables store their data in other SQLite tables, which ** are queried from within xNext() and other v-table methods using ** prepared queries. If such a query is out-of-date, we do not want to ** discard the database schema, as the user code implementing the ** v-table would have to be ready for the sqlite3_vtab structure itself - ** to be invalidated whenever sqlite3_step() is called from within + ** to be invalidated whenever sqlite3_step() is called from within ** a v-table method. */ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ sqlite3ResetOneSchema(db, pOp->p1); } p->expired = 1; rc = SQLITE_SCHEMA; - - /* Set changeCntOn to 0 to prevent the value returned by sqlite3_changes() - ** from being modified in sqlite3VdbeHalt(). If this statement is - ** reprepared, changeCntOn will be set again. */ - p->changeCntOn = 0; } if( rc ) goto abort_due_to_error; break; } @@ -97689,29 +82212,22 @@ pOut = out2Prerelease(p, pOp); pOut->u.i = iMeta; break; } -/* Opcode: SetCookie P1 P2 P3 * P5 +/* Opcode: SetCookie P1 P2 P3 * * ** ** Write the integer value P3 into cookie number P2 of database P1. ** P2==1 is the schema version. P2==2 is the database format. -** P2==3 is the recommended pager cache -** size, and so forth. P1==0 is the main database file and P1==1 is the +** P2==3 is the recommended pager cache +** size, and so forth. P1==0 is the main database file and P1==1 is the ** database file used to store temporary tables. ** ** A transaction must be started before executing this opcode. -** -** If P2 is the SCHEMA_VERSION cookie (cookie number 1) then the internal -** schema version is set to P3-P5. The "PRAGMA schema_version=N" statement -** has P5 set to 1, so that the internal schema version will be different -** from the database schema version, resulting in a schema reset. */ case OP_SetCookie: { Db *pDb; - - sqlite3VdbeIncrWriteCounter(p, 0); assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; @@ -97719,21 +82235,20 @@ assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); /* See note about index shifting on OP_ReadCookie */ rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); if( pOp->p2==BTREE_SCHEMA_VERSION ){ /* When the schema cookie changes, record the new cookie internally */ - *(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5; - db->mDbFlags |= DBFLAG_SchemaChange; - sqlite3FkClearTriggerCache(db, pOp->p1); + pDb->pSchema->schema_cookie = pOp->p3; + db->flags |= SQLITE_InternChanges; }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ pDb->pSchema->file_format = pOp->p3; } if( pOp->p1==1 ){ /* Invalidate all prepared statements whenever the TEMP database ** schema is changed. Ticket #1644 */ - sqlite3ExpirePreparedStatements(db, 0); + sqlite3ExpirePreparedStatements(db); p->expired = 0; } if( rc ) goto abort_due_to_error; break; } @@ -97740,94 +82255,75 @@ /* Opcode: OpenRead P1 P2 P3 P4 P5 ** Synopsis: root=P2 iDb=P3 ** ** Open a read-only cursor for the database table whose root page is -** P2 in a database file. The database file is determined by P3. -** P3==0 means the main database, P3==1 means the database used for +** P2 in a database file. The database file is determined by P3. +** P3==0 means the main database, P3==1 means the database used for ** temporary tables, and P3>1 means used the corresponding attached ** database. Give the new cursor an identifier of P1. The P1 ** values need not be contiguous but all P1 values should be small integers. ** It is an error for P1 to be negative. ** -** Allowed P5 bits: -**
                  -**
                • 0x02 OPFLAG_SEEKEQ: This cursor will only be used for -** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT -** of OP_SeekLE/OP_IdxLT) -**
                +** If P5!=0 then use the content of register P2 as the root page, not +** the value of P2 itself. +** +** There will be a read lock on the database whenever there is an +** open cursor. If the database was unlocked prior to this instruction +** then a read lock is acquired as part of this instruction. A read +** lock allows other processes to read the database but prohibits +** any other process from modifying the database. The read lock is +** released when all cursors are closed. If this instruction attempts +** to get a read lock but fails, the script terminates with an +** SQLITE_BUSY error code. ** ** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** object, then table being opened must be an [index b-tree] where the -** KeyInfo object defines the content and collating -** sequence of that index b-tree. Otherwise, if P4 is an integer -** value, then the table being opened must be a [table b-tree] with a -** number of columns no less than the value of P4. +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +** structure, then said structure defines the content and collating +** sequence of the index being opened. Otherwise, if P4 is an integer +** value, it is set to the number of columns in the table. ** ** See also: OpenWrite, ReopenIdx */ /* Opcode: ReopenIdx P1 P2 P3 P4 P5 ** Synopsis: root=P2 iDb=P3 ** -** The ReopenIdx opcode works like OP_OpenRead except that it first -** checks to see if the cursor on P1 is already open on the same -** b-tree and if it is this opcode becomes a no-op. In other words, +** The ReopenIdx opcode works exactly like ReadOpen except that it first +** checks to see if the cursor on P1 is already open with a root page +** number of P2 and if it is this opcode becomes a no-op. In other words, ** if the cursor is already open, do not reopen it. ** -** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ -** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must -** be the same as every other ReopenIdx or OpenRead for the same cursor -** number. -** -** Allowed P5 bits: -**
                  -**
                • 0x02 OPFLAG_SEEKEQ: This cursor will only be used for -** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT -** of OP_SeekLE/OP_IdxLT) -**
                -** -** See also: OP_OpenRead, OP_OpenWrite +** The ReopenIdx opcode may only be used with P5==0 and with P4 being +** a P4_KEYINFO object. Furthermore, the P3 value must be the same as +** every other ReopenIdx or OpenRead for the same cursor number. +** +** See the OpenRead opcode documentation for additional information. */ /* Opcode: OpenWrite P1 P2 P3 P4 P5 ** Synopsis: root=P2 iDb=P3 ** ** Open a read/write cursor named P1 on the table or index whose root -** page is P2 (or whose root page is held in register P2 if the -** OPFLAG_P2ISREG bit is set in P5 - see below). +** page is P2. Or if P5!=0 use the content of register P2 to find the +** root page. ** ** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** object, then table being opened must be an [index b-tree] where the -** KeyInfo object defines the content and collating -** sequence of that index b-tree. Otherwise, if P4 is an integer -** value, then the table being opened must be a [table b-tree] with a -** number of columns no less than the value of P4. -** -** Allowed P5 bits: -**
                  -**
                • 0x02 OPFLAG_SEEKEQ: This cursor will only be used for -** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT -** of OP_SeekLE/OP_IdxLT) -**
                • 0x08 OPFLAG_FORDELETE: This cursor is used only to seek -** and subsequently delete entries in an index btree. This is a -** hint to the storage engine that the storage engine is allowed to -** ignore. The hint is not used by the official SQLite b*tree storage -** engine, but is used by COMDB2. -**
                • 0x10 OPFLAG_P2ISREG: Use the content of register P2 -** as the root page, not the value of P2 itself. -**
                -** -** This instruction works like OpenRead except that it opens the cursor -** in read/write mode. -** -** See also: OP_OpenRead, OP_ReopenIdx -*/ -case OP_ReopenIdx: { /* ncycle */ +** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +** structure, then said structure defines the content and collating +** sequence of the index being opened. Otherwise, if P4 is an integer +** value, it is set to the number of columns in the table, or to the +** largest index of any column of the table that is actually used. +** +** This instruction works just like OpenRead except that it opens the cursor +** in read/write mode. For a given table, there can be one or more read-only +** cursors or a single read/write cursor but not both. +** +** See also OpenRead. +*/ +case OP_ReopenIdx: { int nField; KeyInfo *pKeyInfo; - u32 p2; + int p2; int iDb; int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; @@ -97835,32 +82331,30 @@ assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); assert( pOp->p4type==P4_KEYINFO ); pCur = p->apCsr[pOp->p1]; if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ - assert( pCur->eCurType==CURTYPE_BTREE ); - sqlite3BtreeClearCursor(pCur->uc.pCursor); goto open_cursor_set_hints; } /* If the cursor is not currently open or is open on a different ** index, then fall through into OP_OpenRead to force a reopen */ -case OP_OpenRead: /* ncycle */ +case OP_OpenRead: case OP_OpenWrite: assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); assert( p->bIsReader ); assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx || p->readOnly==0 ); - if( p->expired==1 ){ + if( p->expired ){ rc = SQLITE_ABORT_ROLLBACK; goto abort_due_to_error; } nField = 0; pKeyInfo = 0; - p2 = (u32)pOp->p2; + p2 = pOp->p2; iDb = pOp->p3; assert( iDb>=0 && iDbnDb ); assert( DbMaskTest(p->btreeMask, iDb) ); pDb = &db->aDb[iDb]; pX = pDb->pBt; @@ -97870,42 +82364,40 @@ wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; } - if( pOp->p5 & OPFLAG_P2ISREG ){ - assert( p2>0 ); - assert( p2<=(u32)(p->nMem+1 - p->nCursor) ); - pIn2 = &aMem[p2]; - assert( memIsValid(pIn2) ); - assert( (pIn2->flags & MEM_Int)!=0 ); - sqlite3VdbeMemIntegerify(pIn2); - p2 = (int)pIn2->u.i; - /* 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. */ - assert( p2>=2 ); - } }else{ wrFlag = 0; - assert( (pOp->p5 & OPFLAG_P2ISREG)==0 ); + } + if( pOp->p5 & OPFLAG_P2ISREG ){ + assert( p2>0 ); + assert( p2<=(p->nMem+1 - p->nCursor) ); + pIn2 = &aMem[p2]; + assert( memIsValid(pIn2) ); + 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 + ** 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. */ + assert( p2>=2 ); } if( pOp->p4type==P4_KEYINFO ){ pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->enc==ENC(db) ); assert( pKeyInfo->db==db ); - nField = pKeyInfo->nAllField; + nField = pKeyInfo->nField+pKeyInfo->nXField; }else if( pOp->p4type==P4_INT32 ){ nField = pOp->p4.i; } assert( pOp->p1>=0 ); assert( nField>=0 ); testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ - pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE); + pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); if( pCur==0 ) goto no_mem; - pCur->iDb = iDb; pCur->nullRow = 1; pCur->isOrdered = 1; pCur->pgnoRoot = p2; #ifdef SQLITE_DEBUG pCur->wrFlag = wrFlag; @@ -97913,18 +82405,20 @@ rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); pCur->pKeyInfo = pKeyInfo; /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has - ** since moved into the btree layer. */ + ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; open_cursor_set_hints: assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); testcase( pOp->p5 & OPFLAG_BULKCSR ); +#ifdef SQLITE_ENABLE_CURSOR_HINTS testcase( pOp->p2 & OPFLAG_SEEKEQ ); +#endif sqlite3BtreeCursorHintFlags(pCur->uc.pCursor, (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); if( rc ) goto abort_due_to_error; break; } @@ -97935,150 +82429,107 @@ ** 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: { /* ncycle */ +case OP_OpenDup: { VdbeCursor *pOrig; /* The original cursor to be duplicated */ VdbeCursor *pCx; /* The new cursor */ pOrig = p->apCsr[pOp->p2]; - assert( pOrig ); - assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */ + assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */ - pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE); + 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; - pCx->pgnoRoot = pOrig->pgnoRoot; - pCx->isOrdered = pOrig->isOrdered; - pCx->ub.pBtx = pOrig->ub.pBtx; - pCx->noReuse = 1; - pOrig->noReuse = 1; - rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, + 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 P3 P4 P5 +/* Opcode: OpenEphemeral P1 P2 * P4 P5 ** Synopsis: nColumn=P2 ** ** Open a new cursor P1 to a transient table. -** The cursor is always opened read/write even if +** The cursor is always opened read/write even if ** the main database is read-only. The ephemeral ** table is deleted automatically when the cursor is closed. ** -** If the cursor P1 is already opened on an ephemeral table, the table -** is cleared (all content is erased). -** ** P2 is the number of columns in the ephemeral table. ** The cursor points to a BTree table if P4==0 and to a BTree index ** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure ** that defines the format of keys in the index. ** ** The P5 parameter can be a mask of the BTREE_* flags defined ** in btree.h. These flags control aspects of the operation of ** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are ** added automatically. -** -** If P3 is positive, then reg[P3] is modified slightly so that it -** can be used as zero-length data for OP_Insert. This is an optimization -** that avoids an extra OP_Blob opcode to initialize that register. */ /* Opcode: OpenAutoindex P1 P2 * P4 * ** Synopsis: nColumn=P2 ** ** This opcode works the same as OP_OpenEphemeral. It has a ** different name to distinguish its use. Tables created using ** by this opcode will be used for automatically created transient ** indices in joins. */ -case OP_OpenAutoindex: /* ncycle */ -case OP_OpenEphemeral: { /* ncycle */ +case OP_OpenAutoindex: +case OP_OpenEphemeral: { VdbeCursor *pCx; KeyInfo *pKeyInfo; - static const int vfsFlags = + static const int vfsFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - if( pOp->p3>0 ){ - /* Make register reg[P3] into a value that can be used as the data - ** form sqlite3BtreeInsert() where the length of the data is zero. */ - assert( pOp->p2==0 ); /* Only used when number of columns is zero */ - assert( pOp->opcode==OP_OpenEphemeral ); - assert( aMem[pOp->p3].flags & MEM_Null ); - aMem[pOp->p3].n = 0; - aMem[pOp->p3].z = ""; - } - pCx = p->apCsr[pOp->p1]; - if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){ - /* If the ephemeral table is already open and has no duplicates from - ** OP_OpenDup, then erase all existing content so that the table is - ** empty again, rather than creating a new table. */ - assert( pCx->isEphemeral ); - pCx->seqCount = 0; - pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0); - }else{ - pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE); - if( pCx==0 ) goto no_mem; - pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, - BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, - vfsFlags); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); - if( rc==SQLITE_OK ){ - /* If a transient index is required, create it by calling - ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before - ** opening it. If a transient table is required, just use the - ** automatically created table with root-page 1 (an BLOB_INTKEY table). - */ - if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ - assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot, - BTREE_BLOBKEY | pOp->p5); - if( rc==SQLITE_OK ){ - assert( pCx->pgnoRoot==SCHEMA_ROOT+1 ); - assert( pKeyInfo->db==db ); - assert( pKeyInfo->enc==ENC(db) ); - rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, - pKeyInfo, pCx->uc.pCursor); - } - pCx->isTable = 0; - }else{ - pCx->pgnoRoot = SCHEMA_ROOT; - rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR, - 0, pCx->uc.pCursor); - pCx->isTable = 1; - } - } - pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); - assert( p->apCsr[pOp->p1]==pCx ); - if( rc ){ - assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) ); - sqlite3BtreeClose(pCx->ub.pBtx); - p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */ - }else{ - assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) ); - } - } - } - if( rc ) goto abort_due_to_error; + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); + if( pCx==0 ) goto no_mem; pCx->nullRow = 1; + pCx->isEphemeral = 1; + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1); + } + if( rc==SQLITE_OK ){ + /* If a transient index is required, create it by calling + ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before + ** opening it. If a transient table is required, just use the + ** automatically created table with root-page 1 (an BLOB_INTKEY table). + */ + if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ + int pgno; + assert( pOp->p4type==P4_KEYINFO ); + 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) ); + rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR, + pKeyInfo, pCx->uc.pCursor); + } + pCx->isTable = 0; + }else{ + rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR, + 0, pCx->uc.pCursor); + pCx->isTable = 1; + } + } + if( rc ) goto abort_due_to_error; + pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); break; } /* Opcode: SorterOpen P1 P2 P3 P4 * ** @@ -98093,11 +82544,11 @@ case OP_SorterOpen: { VdbeCursor *pCx; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER); + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; assert( pCx->pKeyInfo->db==db ); assert( pCx->pKeyInfo->enc==ENC(db) ); rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx); @@ -98126,47 +82577,41 @@ /* Opcode: OpenPseudo P1 P2 P3 * * ** Synopsis: P3 columns in r[P2] ** ** Open a new cursor that points to a fake table that contains a single ** row of data. The content of that one row is the content of memory -** register P2. In other words, cursor P1 becomes an alias for the +** register P2. In other words, cursor P1 becomes an alias for the ** MEM_Blob content contained in register P2. ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. The OP_Column opcode ** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by -** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor -** will return NULL for every column. +** the pseudo-table. */ case OP_OpenPseudo: { VdbeCursor *pCx; assert( pOp->p1>=0 ); assert( pOp->p3>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO); + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; - pCx->seekResult = pOp->p2; + pCx->uc.pseudoTableReg = 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; } /* Opcode: Close P1 * * * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ -case OP_Close: { /* ncycle */ +case OP_Close: { assert( pOp->p1>=0 && pOp->p1nCursor ); sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]); p->apCsr[pOp->p1] = 0; break; } @@ -98192,27 +82637,25 @@ #endif /* Opcode: SeekGE P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as the key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as the key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than or equal to the key value. If there are no records +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than or equal to the key value. If there are no records ** greater than or equal to the key and P2 is not zero, then jump to P2. ** ** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this -** opcode will either land on a record that exactly matches the key, or -** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ, -** this opcode must be followed by an IdxLE opcode with the same arguments. -** The IdxGT opcode will be skipped if this opcode succeeds, but the -** IdxGT opcode will be used on subsequent loop iterations. The -** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this -** is an equality search. +** opcode will always land on a record that equally equals the key, or +** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this +** opcode must be followed by an IdxLE opcode with the same arguments. +** The IdxLE opcode will be skipped if this opcode succeeds, but the +** IdxLE opcode will be used on subsequent loop iterations. ** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. ** @@ -98219,35 +82662,35 @@ ** See also: Found, NotFound, SeekLt, SeekGt, SeekLe */ /* Opcode: SeekGT P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than the key value. If there are no records greater than +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than the key value. If there are no records greater than ** the key and P2 is not zero, then jump to P2. ** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. ** ** See also: Found, NotFound, SeekLt, SeekGe, SeekLe */ -/* Opcode: SeekLT P1 P2 P3 P4 * +/* Opcode: SeekLT P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the largest entry that -** is less than the key value. If there are no records less than +** Reposition cursor P1 so that it points to the largest entry that +** is less than the key value. If there are no records less than ** the key and P2 is not zero, then jump to P2. ** ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. @@ -98255,38 +82698,36 @@ ** See also: Found, NotFound, SeekGt, SeekGe, SeekLe */ /* Opcode: SeekLE P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Reposition cursor P1 so that it points to the largest entry that -** is less than or equal to the key value. If there are no records +** Reposition cursor P1 so that it points to the largest entry that +** is less than or equal to the key value. If there are no records ** less than or equal to the key and P2 is not zero, then jump to P2. ** ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. ** ** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this -** opcode will either land on a record that exactly matches the key, or -** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ, -** this opcode must be followed by an IdxLE opcode with the same arguments. +** opcode will always land on a record that equally equals the key, or +** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this +** opcode must be followed by an IdxGE opcode with the same arguments. ** The IdxGE opcode will be skipped if this opcode succeeds, but the -** IdxGE opcode will be used on subsequent loop iterations. The -** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this -** is an equality search. +** IdxGE opcode will be used on subsequent loop iterations. ** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ -case OP_SeekLT: /* jump0, in3, group, ncycle */ -case OP_SeekLE: /* jump0, in3, group, ncycle */ -case OP_SeekGE: /* jump0, in3, group, ncycle */ -case OP_SeekGT: { /* jump0, in3, group, ncycle */ +case OP_SeekLT: /* jump, in3 */ +case OP_SeekLE: /* jump, in3 */ +case OP_SeekGE: /* jump, in3 */ +case OP_SeekGT: { /* jump, in3 */ int res; /* Comparison result */ int oc; /* Opcode */ VdbeCursor *pC; /* The cursor to seek */ UnpackedRecord r; /* The key to seek for */ int nField; /* Number of columns or fields in the key */ @@ -98308,86 +82749,71 @@ pC->nullRow = 0; #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; if( pC->isTable ){ - u16 flags3, newType; - /* The OPFLAG_SEEKEQ/BTREE_SEEK_EQ flag is only set on index cursors */ + /* The BTREE_SEEK_EQ flag is only set on index cursors */ 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 ** the seek, so convert it. */ pIn3 = &aMem[pOp->p3]; - flags3 = pIn3->flags; - if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ + if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3, 0); } - iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */ - newType = pIn3->flags; /* Record the type after applying numeric affinity */ - pIn3->flags = flags3; /* But convert the type back to its original */ + iKey = sqlite3VdbeIntValue(pIn3); /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ - if( (newType & (MEM_Int|MEM_IntReal))==0 ){ - int c; - if( (newType & MEM_Real)==0 ){ - if( (newType & MEM_Null) || oc>=OP_SeekGE ){ - VdbeBranchTaken(1,2); - goto jump_to_p2; - }else{ - rc = sqlite3BtreeLast(pC->uc.pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - goto seek_not_found; - } - } - c = sqlite3IntFloatCompare(iKey, pIn3->u.r); + if( (pIn3->flags & MEM_Int)==0 ){ + if( (pIn3->flags & MEM_Real)==0 ){ + /* If the P3 value cannot be converted into any kind of a number, + ** then the seek is not possible, so jump to P2 */ + VdbeBranchTaken(1,2); goto jump_to_p2; + break; + } /* If the approximation iKey is larger than the actual real search ** term, substitute >= for > and < for <=. e.g. if the search term ** is 4.9 and the integer approximation 5: ** ** (x > 4.9) -> (x >= 5) ** (x <= 4.9) -> (x < 5) */ - if( c>0 ){ + if( pIn3->u.r<(double)iKey ){ assert( OP_SeekGE==(OP_SeekGT-1) ); assert( OP_SeekLT==(OP_SeekLE-1) ); assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; } /* If the approximation iKey is smaller than the actual real search ** term, substitute <= for < and > for >=. */ - else if( c<0 ){ + else if( pIn3->u.r>(double)iKey ){ assert( OP_SeekLE==(OP_SeekLT+1) ); assert( OP_SeekGT==(OP_SeekGE+1) ); assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } - } - rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res); + } + rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res); pC->movetoTarget = iKey; /* Used by OP_Delete */ if( rc!=SQLITE_OK ){ goto abort_due_to_error; } }else{ - /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the - ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be - ** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively, - ** with the same key. + /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and + ** OP_SeekLE opcodes are allowed, and these must be immediately followed + ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. */ if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){ eqOnly = 1; assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); - assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT ); - assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT ); assert( pOp[1].p1==pOp[0].p1 ); assert( pOp[1].p2==pOp[0].p2 ); assert( pOp[1].p3==pOp[0].p3 ); assert( pOp[1].p4.i==pOp[0].p4.i ); } @@ -98411,28 +82837,24 @@ assert( oc!=OP_SeekGE || r.default_rc==+1 ); assert( oc!=OP_SeekLT || r.default_rc==+1 ); r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG - { - int i; - for(i=0; i0 ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]); - } - } + { int i; for(i=0; iuc.pCursor, &r, &res); + rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( eqOnly && r.eqSeen==0 ){ assert( res!=0 ); goto seek_not_found; } } + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; #ifdef SQLITE_TEST sqlite3_search_count++; #endif if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); if( res<0 || (res==0 && oc==OP_SeekGT) ){ @@ -98479,244 +82901,10 @@ pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ } break; } - -/* Opcode: SeekScan P1 P2 * * P5 -** Synopsis: Scan-ahead up to P1 rows -** -** This opcode is a prefix opcode to OP_SeekGE. In other words, this -** opcode must be immediately followed by OP_SeekGE. This constraint is -** checked by assert() statements. -** -** This opcode uses the P1 through P4 operands of the subsequent -** OP_SeekGE. In the text that follows, the operands of the subsequent -** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only -** the P1, P2 and P5 operands of this opcode are also used, and are called -** This.P1, This.P2 and This.P5. -** -** This opcode helps to optimize IN operators on a multi-column index -** where the IN operator is on the later terms of the index by avoiding -** unnecessary seeks on the btree, substituting steps to the next row -** of the b-tree instead. A correct answer is obtained if this opcode -** is omitted or is a no-op. -** -** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which -** is the desired entry that we want the cursor SeekGE.P1 to be pointing -** to. Call this SeekGE.P3/P4 row the "target". -** -** If the SeekGE.P1 cursor is not currently pointing to a valid row, -** then this opcode is a no-op and control passes through into the OP_SeekGE. -** -** If the SeekGE.P1 cursor is pointing to a valid row, then that row -** might be the target row, or it might be near and slightly before the -** target row, or it might be after the target row. If the cursor is -** currently before the target row, then this opcode attempts to position -** the cursor on or after the target row by invoking sqlite3BtreeStep() -** on the cursor between 1 and This.P1 times. -** -** The This.P5 parameter is a flag that indicates what to do if the -** cursor ends up pointing at a valid row that is past the target -** row. If This.P5 is false (0) then a jump is made to SeekGE.P2. If -** This.P5 is true (non-zero) then a jump is made to This.P2. The P5==0 -** case occurs when there are no inequality constraints to the right of -** the IN constraint. The jump to SeekGE.P2 ends the loop. The P5!=0 case -** occurs when there are inequality constraints to the right of the IN -** operator. In that case, the This.P2 will point either directly to or -** to setup code prior to the OP_IdxGT or OP_IdxGE opcode that checks for -** loop terminate. -** -** Possible outcomes from this opcode:
                  -** -**
                1. If the cursor is initially not pointed to any valid row, then -** fall through into the subsequent OP_SeekGE opcode. -** -**
                2. If the cursor is left pointing to a row that is before the target -** row, even after making as many as This.P1 calls to -** sqlite3BtreeNext(), then also fall through into OP_SeekGE. -** -**
                3. If the cursor is left pointing at the target row, either because it -** was at the target row to begin with or because one or more -** sqlite3BtreeNext() calls moved the cursor to the target row, -** then jump to This.P2.., -** -**
                4. If the cursor started out before the target row and a call to -** to sqlite3BtreeNext() moved the cursor off the end of the index -** (indicating that the target row definitely does not exist in the -** btree) then jump to SeekGE.P2, ending the loop. -** -**
                5. If the cursor ends up on a valid row that is past the target row -** (indicating that the target row does not exist in the btree) then -** jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0. -**
                -*/ -case OP_SeekScan: { /* ncycle */ - VdbeCursor *pC; - int res; - int nStep; - UnpackedRecord r; - - assert( pOp[1].opcode==OP_SeekGE ); - - /* If pOp->p5 is clear, then pOp->p2 points to the first instruction past the - ** OP_IdxGT that follows the OP_SeekGE. Otherwise, it points to the first - ** opcode past the OP_SeekGE itself. */ - assert( pOp->p2>=(int)(pOp-aOp)+2 ); -#ifdef SQLITE_DEBUG - if( pOp->p5==0 ){ - /* There are no inequality constraints following the IN constraint. */ - assert( pOp[1].p1==aOp[pOp->p2-1].p1 ); - assert( pOp[1].p2==aOp[pOp->p2-1].p2 ); - assert( pOp[1].p3==aOp[pOp->p2-1].p3 ); - assert( aOp[pOp->p2-1].opcode==OP_IdxGT - || aOp[pOp->p2-1].opcode==OP_IdxGE ); - testcase( aOp[pOp->p2-1].opcode==OP_IdxGE ); - }else{ - /* There are inequality constraints. */ - assert( pOp->p2==(int)(pOp-aOp)+2 ); - assert( aOp[pOp->p2-1].opcode==OP_SeekGE ); - } -#endif - - assert( pOp->p1>0 ); - pC = p->apCsr[pOp[1].p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( !pC->isTable ); - if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... cursor not valid - fall through\n"); - } -#endif - break; - } - nStep = pOp->p1; - assert( nStep>=1 ); - r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp[1].p4.i; - r.default_rc = 0; - r.aMem = &aMem[pOp[1].p3]; -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; i0 && pOp->p5==0 ){ - seekscan_search_fail: - /* Jump to SeekGE.P2, ending the loop */ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... %d steps and then skip\n", pOp->p1 - nStep); - } -#endif - VdbeBranchTaken(1,3); - pOp++; - goto jump_to_p2; - } - if( res>=0 ){ - /* Jump to This.P2, bypassing the OP_SeekGE opcode */ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... %d steps and then success\n", pOp->p1 - nStep); - } -#endif - VdbeBranchTaken(2,3); - goto jump_to_p2; - break; - } - if( nStep<=0 ){ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("... fall through after %d steps\n", pOp->p1); - } -#endif - VdbeBranchTaken(0,3); - break; - } - nStep--; - pC->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeNext(pC->uc.pCursor, 0); - if( rc ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - goto seekscan_search_fail; - }else{ - goto abort_due_to_error; - } - } - } - - break; -} - - -/* Opcode: SeekHit P1 P2 P3 * * -** Synopsis: set P2<=seekHit<=P3 -** -** Increase or decrease the seekHit value for cursor P1, if necessary, -** so that it is no less than P2 and no greater than P3. -** -** The seekHit integer represents the maximum of terms in an index for which -** there is known to be at least one match. If the seekHit value is smaller -** than the total number of equality terms in an index lookup, then the -** OP_IfNoHope opcode might run to see if the IN loop can be abandoned -** early, thus saving work. This is part of the IN-early-out optimization. -** -** P1 must be a valid b-tree cursor. -*/ -case OP_SeekHit: { /* ncycle */ - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pOp->p3>=pOp->p2 ); - if( pC->seekHitp2 ){ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2); - } -#endif - pC->seekHit = pOp->p2; - }else if( pC->seekHit>pOp->p3 ){ -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3); - } -#endif - pC->seekHit = pOp->p3; - } - break; -} - -/* Opcode: IfNotOpen P1 P2 * * * -** Synopsis: if( !csr[P1] ) goto P2 -** -** If cursor P1 is not open or if P1 is set to a NULL row using the -** OP_NullRow opcode, then jump to instruction P2. Otherwise, fall through. -*/ -case OP_IfNotOpen: { /* jump */ - VdbeCursor *pCur; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pCur = p->apCsr[pOp->p1]; - VdbeBranchTaken(pCur==0 || pCur->nullRow, 2); - if( pCur==0 || pCur->nullRow ){ - goto jump_to_p2_and_check_for_interrupt; - } - break; -} - /* Opcode: Found P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked @@ -98736,61 +82924,30 @@ ** Synopsis: key=r[P3@P4] ** ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked ** record. -** +** ** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** is not the prefix of any entry in P1 then a jump is made to P2. If P1 +** is not the prefix of any entry in P1 then a jump is made to P2. If P1 ** does contain an entry whose prefix matches the P3/P4 record then control ** falls through to the next instruction and P1 is left pointing at the ** matching entry. ** ** This operation leaves the cursor in a state where it cannot be ** advanced in either direction. In other words, the Next and Prev ** opcodes do not work after this operation. ** -** See also: Found, NotExists, NoConflict, IfNoHope -*/ -/* Opcode: IfNoHope P1 P2 P3 P4 * -** Synopsis: key=r[P3@P4] -** -** Register P3 is the first of P4 registers that form an unpacked -** record. Cursor P1 is an index btree. P2 is a jump destination. -** In other words, the operands to this opcode are the same as the -** operands to OP_NotFound and OP_IdxGT. -** -** This opcode is an optimization attempt only. If this opcode always -** falls through, the correct answer is still obtained, but extra work -** is performed. -** -** A value of N in the seekHit flag of cursor P1 means that there exists -** a key P3:N that will match some record in the index. We want to know -** if it is possible for a record P3:P4 to match some record in the -** index. If it is not possible, we can skip some work. So if seekHit -** is less than P4, attempt to find out if a match is possible by running -** OP_NotFound. -** -** This opcode is used in IN clause processing for a multi-column key. -** If an IN clause is attached to an element of the key other than the -** left-most element, and if there are no matches on the most recent -** seek over the whole key, then it might be that one of the key element -** to the left is prohibiting a match, and hence there is "no hope" of -** any match regardless of how many IN clause elements are checked. -** In such a case, we abandon the IN clause search early, using this -** opcode. The opcode name comes from the fact that the -** jump is taken if there is "no hope" of achieving a match. -** -** See also: NotFound, SeekHit +** See also: Found, NotExists, NoConflict */ /* Opcode: NoConflict P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked ** record. -** +** ** Cursor P1 is on an index btree. If the record identified by P3 and P4 ** contains any NULL value, jump immediately to P2. If all terms of the ** record are not-NULL then a check is done to determine if any row in the ** P1 index btree has a matching key prefix. If there are no matches, jump ** immediately to P2. If there is a match, fall through and leave the P1 @@ -98803,30 +82960,19 @@ ** advanced in either direction. In other words, the Next and Prev ** opcodes do not work after this operation. ** ** See also: NotFound, Found, NotExists */ -case OP_IfNoHope: { /* jump, in3, ncycle */ - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - printf("seekHit is %d\n", pC->seekHit); - } -#endif - if( pC->seekHit>=pOp->p4.i ) break; - /* Fall through into OP_NotFound */ - /* no break */ deliberate_fall_through -} -case OP_NoConflict: /* jump, in3, ncycle */ -case OP_NotFound: /* jump, in3, ncycle */ -case OP_Found: { /* jump, in3, ncycle */ +case OP_NoConflict: /* jump, in3 */ +case OP_NotFound: /* jump, in3 */ +case OP_Found: { /* jump, in3 */ int alreadyExists; + int takeJump; int ii; VdbeCursor *pC; + int res; + UnpackedRecord *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; #ifdef SQLITE_TEST if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; @@ -98837,84 +82983,77 @@ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif - r.aMem = &aMem[pOp->p3]; + pIn3 = &aMem[pOp->p3]; assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->isTable==0 ); - r.nField = (u16)pOp->p4.i; - if( r.nField>0 ){ - /* Key values in an array of registers */ + if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; - r.default_rc = 0; + r.nField = (u16)pOp->p4.i; + r.aMem = pIn3; #ifdef SQLITE_DEBUG - (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */ for(ii=0; iip3+ii, &r.aMem[ii]); } #endif - rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult); + pIdxKey = &r; + pFree = 0; }else{ - /* Composite key generated by OP_MakeRecord */ - assert( r.aMem->flags & MEM_Blob ); - assert( pOp->opcode!=OP_NoConflict ); - rc = ExpandBlob(r.aMem); + assert( pIn3->flags & MEM_Blob ); + rc = ExpandBlob(pIn3); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); if( rc ) goto no_mem; - pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); + pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); if( pIdxKey==0 ) goto no_mem; - sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey); - pIdxKey->default_rc = 0; - rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult); - sqlite3DbFreeNN(db, pIdxKey); + sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } + pIdxKey->default_rc = 0; + takeJump = 0; + if( pOp->opcode==OP_NoConflict ){ + /* For the OP_NoConflict opcode, take the jump if any of the + ** input fields are NULL, since any key with a NULL will not + ** conflict */ + for(ii=0; iinField; ii++){ + if( pIdxKey->aMem[ii].flags & MEM_Null ){ + takeJump = 1; + break; + } + } + } + rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res); + if( pFree ) sqlite3DbFreeNN(db, pFree); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - alreadyExists = (pC->seekResult==0); + pC->seekResult = res; + alreadyExists = (res==0); pC->nullRow = 1-alreadyExists; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ VdbeBranchTaken(alreadyExists!=0,2); if( alreadyExists ) goto jump_to_p2; }else{ - if( !alreadyExists ){ - VdbeBranchTaken(1,2); - goto jump_to_p2; - } - if( pOp->opcode==OP_NoConflict ){ - /* For the OP_NoConflict opcode, take the jump if any of the - ** input fields are NULL, since any key with a NULL will not - ** conflict */ - for(ii=0; iiopcode==OP_IfNoHope ){ - pC->seekHit = pOp->p4.i; - } + VdbeBranchTaken(takeJump||alreadyExists==0,2); + if( takeJump || !alreadyExists ) goto jump_to_p2; } break; } /* Opcode: SeekRowid P1 P2 P3 * * ** Synopsis: intkey=r[P3] ** ** P1 is the index of a cursor open on an SQL table btree (with integer ** keys). If register P3 does not contain an integer or if P1 does not -** contain a record with rowid P3 then jump immediately to P2. +** contain a record with rowid P3 then jump immediately to P2. ** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain -** a record with rowid P3 then +** a record with rowid P3 then ** leave the cursor pointing at that record and fall through to the next ** instruction. ** ** The OP_NotExists opcode performs the same operation, but with OP_NotExists ** the P3 register must be guaranteed to contain an integer value. With this @@ -98933,11 +83072,11 @@ ** Synopsis: intkey=r[P3] ** ** P1 is the index of a cursor open on an SQL table btree (with integer ** keys). P3 is an integer rowid. If P1 does not contain a record with ** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an -** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then +** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then ** leave the cursor pointing at that record and fall through to the next ** instruction. ** ** The OP_SeekRowid opcode performs the same operation but also allows the ** P3 register to contain a non-integer value, in which case the jump is @@ -98950,52 +83089,38 @@ ** in either direction. In other words, the Next and Prev opcodes will ** not work following this opcode. ** ** See also: Found, NotFound, NoConflict, SeekRowid */ -case OP_SeekRowid: { /* jump0, in3, ncycle */ +case OP_SeekRowid: { /* jump, in3 */ VdbeCursor *pC; BtCursor *pCrsr; int res; u64 iKey; pIn3 = &aMem[pOp->p3]; - testcase( pIn3->flags & MEM_Int ); - testcase( pIn3->flags & MEM_IntReal ); - testcase( pIn3->flags & MEM_Real ); - testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str ); - if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ - /* If pIn3->u.i does not contain an integer, compute iKey as the - ** integer value of pIn3. Jump to P2 if pIn3 cannot be converted - ** into an integer without loss of information. Take care to avoid - ** changing the datatype of pIn3, however, as it is used by other - ** parts of the prepared statement. */ - Mem x = pIn3[0]; - applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding); - if( (x.flags & MEM_Int)==0 ) goto jump_to_p2; - iKey = x.u.i; - goto notExistsWithKey; + if( (pIn3->flags & MEM_Int)==0 ){ + applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); + if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2; } /* Fall through into OP_NotExists */ - /* no break */ deliberate_fall_through -case OP_NotExists: /* jump, in3, ncycle */ +case OP_NotExists: /* jump, in3 */ pIn3 = &aMem[pOp->p3]; - assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid ); + assert( pIn3->flags & MEM_Int ); assert( pOp->p1>=0 && pOp->p1nCursor ); - iKey = pIn3->u.i; -notExistsWithKey: pC = p->apCsr[pOp->p1]; assert( pC!=0 ); #ifdef SQLITE_DEBUG - if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid; + pC->seekOp = 0; #endif assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); res = 0; - rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res); + iKey = pIn3->u.i; + rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); assert( rc==SQLITE_OK || res==0 ); pC->movetoTarget = iKey; /* Used by OP_Delete */ pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; pC->deferredMoveto = 0; @@ -99017,11 +83142,11 @@ ** Synopsis: r[P2]=cursor[P1].ctr++ ** ** Find the next available sequence number for cursor P1. ** Write the sequence number into register P2. ** The sequence number on the cursor is incremented after this -** instruction. +** instruction. */ case OP_Sequence: { /* out2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( p->apCsr[pOp->p1]!=0 ); assert( p->apCsr[pOp->p1]->eCurType!=CURTYPE_VTAB ); @@ -99037,34 +83162,31 @@ ** Get a new integer record number (a.k.a "rowid") used as the key to a table. ** The record number is not previously used as a key in the database ** table that cursor P1 points to. The new record number is written ** written to register P2. ** -** If P3>0 then P3 is a register in the root frame of this VDBE that holds +** If P3>0 then P3 is a register in the root frame of this VDBE that holds ** the largest previously generated record number. No new record numbers are -** allowed to be less than this value. When this value reaches its maximum, +** allowed to be less than this value. When this value reaches its maximum, ** an SQLITE_FULL error is generated. The P3 register is updated with the ' ** generated record number. This P3 mechanism is used to help implement the ** AUTOINCREMENT feature. */ case OP_NewRowid: { /* out2 */ i64 v; /* The new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */ int res; /* Result of an sqlite3BtreeLast() */ int cnt; /* Counter to limit the number of searches */ -#ifndef SQLITE_OMIT_AUTOINCREMENT Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ VdbeFrame *pFrame; /* Root frame of VDBE */ -#endif v = 0; res = 0; pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); { /* The next rowid or record number (different terms for the same ** thing) is obtained in a two-step algorithm. @@ -99148,11 +83270,11 @@ ** an AUTOINCREMENT table. */ cnt = 0; do{ sqlite3_randomness(sizeof(v), &v); v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */ - }while( ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v, + }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v, 0, &res))==SQLITE_OK) && (res==0) && (++cnt<100)); if( rc ) goto abort_due_to_error; if( res==0 ){ @@ -99190,12 +83312,12 @@ ** 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 ** is part of an INSERT operation. The difference is only important to ** the update hook. ** -** Parameter P4 may point to a Table structure, or may be NULL. If it is -** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked +** Parameter P4 may point to a Table structure, or may be NULL. If it is +** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked ** following a successful insert. ** ** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically ** allocated, then ownership of P2 is transferred to the pseudo-cursor ** and register P2 becomes ephemeral. If the cursor is changed, the @@ -99203,159 +83325,132 @@ ** cause any problems.) ** ** This instruction only works on tables. The equivalent instruction ** for indices is OP_IdxInsert. */ -case OP_Insert: { +/* Opcode: InsertInt P1 P2 P3 P4 P5 +** Synopsis: intkey=P3 data=r[P2] +** +** This works exactly like OP_Insert except that the key is the +** integer value P3, not the value of the integer stored in register P3. +*/ +case OP_Insert: +case OP_InsertInt: { Mem *pData; /* MEM cell holding data for the record to be inserted */ Mem *pKey; /* MEM cell holding key for the record */ VdbeCursor *pC; /* Cursor to table into which insert is written */ 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) ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->deferredMoveto==0 ); assert( pC->uc.pCursor!=0 ); assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable ); assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); REGISTER_TRACE(pOp->p2, pData); - sqlite3VdbeIncrWriteCounter(p, pC); - pKey = &aMem[pOp->p3]; - assert( pKey->flags & MEM_Int ); - assert( memIsValid(pKey) ); - REGISTER_TRACE(pOp->p3, pKey); - x.nKey = pKey->u.i; + if( pOp->opcode==OP_Insert ){ + pKey = &aMem[pOp->p3]; + assert( pKey->flags & MEM_Int ); + assert( memIsValid(pKey) ); + REGISTER_TRACE(pOp->p3, pKey); + x.nKey = pKey->u.i; + }else{ + assert( pOp->opcode==OP_InsertInt ); + x.nKey = pOp->p3; + } if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb>=0 ); zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) ); + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); }else{ - pTab = 0; - zDb = 0; + pTab = 0; /* Not needed. Silence a compiler warning. */ + zDb = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update hook, if any */ - if( pTab ){ - if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){ - sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1); - } - if( db->xUpdateCallback==0 || pTab->aCol==0 ){ - /* Prevent post-update hook from running in cases when it should not */ - pTab = 0; - } + if( db->xPreUpdateCallback + && pOp->p4type==P4_TABLE + && !(pOp->p5 & OPFLAG_ISUPDATE) + ){ + sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2); } if( pOp->p5 & OPFLAG_ISNOOP ) break; #endif - assert( (pOp->p5 & OPFLAG_LASTROWID)==0 || (pOp->p5 & OPFLAG_NCHANGE)!=0 ); - if( pOp->p5 & OPFLAG_NCHANGE ){ - p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; - } - assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 ); - x.pData = pData->z; - x.nData = pData->n; + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + if( pOp->p5 & OPFLAG_LASTROWID ) db->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; + } seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); if( pData->flags & MEM_Zero ){ x.nZero = pData->u.nZero; }else{ x.nZero = 0; } x.pKey = 0; - assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), - seekResult + (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult ); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; - colCacheCtr++; /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; - 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; -} - -/* Opcode: RowCell P1 P2 P3 * * -** -** P1 and P2 are both open cursors. Both must be opened on the same type -** of table - intkey or index. This opcode is used as part of copying -** the current row from P2 into P1. If the cursors are opened on intkey -** tables, register P3 contains the rowid to use with the new record in -** P1. If they are opened on index tables, P3 is not used. -** -** This opcode must be followed by either an Insert or InsertIdx opcode -** with the OPFLAG_PREFORMAT flag set to complete the insert operation. -*/ -case OP_RowCell: { - VdbeCursor *pDest; /* Cursor to write to */ - VdbeCursor *pSrc; /* Cursor to read from */ - i64 iKey; /* Rowid value to insert with */ - assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert ); - assert( pOp[1].opcode==OP_Insert || pOp->p3==0 ); - assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 ); - assert( pOp[1].p5 & OPFLAG_PREFORMAT ); - pDest = p->apCsr[pOp->p1]; - pSrc = p->apCsr[pOp->p2]; - iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0; - rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - break; -}; + if( db->xUpdateCallback && op ){ + db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey); + } + break; +} /* Opcode: Delete P1 P2 P3 P4 P5 ** ** Delete the record at which the P1 cursor is currently pointing. ** ** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then ** the cursor will be left pointing at either the next or the previous ** record in the table. If it is left pointing at the next record, then ** the next Next instruction will be a no-op. As a result, in this case -** it is ok to delete a record from within a Next loop. If +** it is ok to delete a record from within a Next loop. If ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be ** left in an undefined state. ** ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this -** delete is one of several associated with deleting a table row and -** all its associated index entries. Exactly one of those deletes is -** the "primary" delete. The others are all on OPFLAG_FORDELETE -** cursors or else are marked with the AUXDELETE flag. -** -** If the OPFLAG_NCHANGE (0x01) flag of P2 (NB: P2 not P5) is set, then -** the row change count is incremented (otherwise not). -** -** If the OPFLAG_ISNOOP (0x40) flag of P2 (not P5!) is set, then the -** pre-update-hook for deletes is run, but the btree is otherwise unchanged. -** This happens when the OP_Delete is to be shortly followed by an OP_Insert -** with the same key, causing the btree entry to be overwritten. +** delete one of several associated with deleting a table row and all its +** associated index entries. Exactly one of those deletes is the "primary" +** delete. The others are all on OPFLAG_FORDELETE cursors or else are +** marked with the AUXDELETE flag. +** +** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row +** change count is incremented (otherwise not). ** ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. ** -** If P4 is not NULL then it points to a Table object. In this case either +** If P4 is not NULL then it points to a Table object. In this case either ** the update or pre-update hook, or both, may be invoked. The P1 cursor must -** have been positioned using OP_NotFound prior to invoking this opcode in -** this case. Specifically, if one is configured, the pre-update hook is -** invoked if P4 is not NULL. The update-hook is invoked if one is configured, +** have been positioned using OP_NotFound prior to invoking this opcode in +** this case. Specifically, if one is configured, the pre-update hook is +** invoked if P4 is not NULL. The update-hook is invoked if one is configured, ** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. ** ** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address ** of the memory cell that contains the value that the rowid of the row will ** be set to by the update. @@ -99371,30 +83466,25 @@ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->deferredMoveto==0 ); - sqlite3VdbeIncrWriteCounter(p, pC); #ifdef SQLITE_DEBUG - if( pOp->p4type==P4_TABLE - && HasRowid(pOp->p4.pTab) - && pOp->p5==0 - && sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) - ){ + if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ /* If p5 is zero, the seek operation that positioned the cursor prior to ** OP_Delete will have also set the pC->movetoTarget field to the rowid of ** the row that is being deleted */ i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor); - assert( CORRUPT_DB || pC->movetoTarget==iKey ); + assert( pC->movetoTarget==iKey ); } #endif /* If the update-hook or pre-update-hook will be invoked, set zDb to ** the name of the db to pass as to it. Also set local pTab to a copy ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was - ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set + ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set ** VdbeCursor.movetoTarget to the current rowid. */ if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb>=0 ); assert( pOp->p4.pTab!=0 ); zDb = db->aDb[pC->iDb].zDbSName; @@ -99401,32 +83491,31 @@ pTab = pOp->p4.pTab; if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor); } }else{ - zDb = 0; - pTab = 0; + zDb = 0; /* Not needed. Silence a compiler warning. */ + pTab = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update-hook if required. */ - assert( db->xPreUpdateCallback==0 || pTab==pOp->p4.pTab ); - if( db->xPreUpdateCallback && pTab ){ - assert( !(opflags & OPFLAG_ISUPDATE) - || HasRowid(pTab)==0 - || (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, + (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, zDb, pTab, pC->movetoTarget, - pOp->p3, -1 + pOp->p3 ); } if( opflags & OPFLAG_ISNOOP ) break; #endif - - /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ + + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); #ifdef SQLITE_DEBUG @@ -99443,18 +83532,17 @@ } #endif rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; - colCacheCtr++; pC->seekResult = 0; if( rc ) goto abort_due_to_error; /* Invoke the update-hook if required. */ if( opflags & OPFLAG_NCHANGE ){ p->nChange++; - if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){ + if( db->xUpdateCallback && HasRowid(pTab) ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, pC->movetoTarget); assert( pC->iDb>=0 ); } } @@ -99476,11 +83564,11 @@ /* Opcode: SorterCompare P1 P2 P3 P4 ** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 ** ** P1 is a sorter cursor. This instruction compares a prefix of the -** record blob in register P3 against a prefix of the entry that +** record blob in register P3 against a prefix of the entry that ** the sorter cursor currently points to. Only the first P4 fields ** of r[P3] and the sorter record are compared. ** ** If either P3 or the sorter contains a NULL in one of their significant ** fields (not counting the P4 fields at the end which are ignored) then @@ -99511,17 +83599,17 @@ ** Synopsis: r[P2]=data ** ** Write into register P2 the current sorter data for sorter cursor P1. ** Then clear the column header cache on cursor P3. ** -** This opcode is normally used to move a record out of the sorter and into +** This opcode is normally use to move a record out of the sorter and into ** a register that is the source for a pseudo-table cursor created using ** OpenPseudo. That pseudo-table cursor is the one that is identified by ** parameter P3. Clearing the P3 column cache as part of this opcode saves ** us from having to issue a separate NullRow instruction to clear that cache. */ -case OP_SorterData: { /* ncycle */ +case OP_SorterData: { VdbeCursor *pC; pOut = &aMem[pOp->p2]; pC = p->apCsr[pOp->p1]; assert( isSorter(pC) ); @@ -99534,26 +83622,26 @@ } /* Opcode: RowData P1 P2 P3 * * ** Synopsis: r[P2]=data ** -** Write into register P2 the complete row content for the row at +** 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 +** 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. ** -** If P3!=0 then this opcode is allowed to make an ephemeral pointer +** 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 current cursors +** 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 P3!=0 then the content of the P2 register is unsuitable for use @@ -99585,35 +83673,39 @@ ** generator) then the fix would be to insert a call to ** sqlite3VdbeCursorMoveto(). */ assert( pC->deferredMoveto==0 ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); +#if 0 /* Not required due to the previous to assert() statements */ + rc = sqlite3VdbeCursorMoveto(pC); + if( rc!=SQLITE_OK ) goto abort_due_to_error; +#endif n = sqlite3BtreePayloadSize(pCrsr); if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } testcase( n==0 ); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCrsr, n, pOut); + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut); if( rc ) goto abort_due_to_error; if( !pOp->p3 ) Deephemeralize(pOut); UPDATE_MAX_BLOBSIZE(pOut); REGISTER_TRACE(pOp->p2, pOut); break; } /* Opcode: Rowid P1 P2 * * * -** Synopsis: r[P2]=PX rowid of P1 +** Synopsis: r[P2]=rowid ** ** Store in register P2 an integer which is the key of the table entry that ** P1 is currently point to. ** ** P1 can be either an ordinary table or a virtual table. There used to ** be a separate OP_VRowid opcode for use with virtual tables, but this ** one opcode now works for both table types. */ -case OP_Rowid: { /* out2, ncycle */ +case OP_Rowid: { /* out2 */ VdbeCursor *pC; i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; @@ -99655,65 +83747,46 @@ /* Opcode: NullRow P1 * * * * ** ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always ** write a NULL. -** -** If cursor P1 is not previously opened, open it now to a special -** pseudo-cursor that always returns NULL for every column. */ case OP_NullRow: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - if( pC==0 ){ - /* If the cursor is not already open, create a special kind of - ** pseudo-cursor that always gives null rows. */ - pC = allocateCursor(p, pOp->p1, 1, CURTYPE_PSEUDO); - if( pC==0 ) goto no_mem; - pC->seekResult = 0; - pC->isTable = 1; - pC->noReuse = 1; - pC->uc.pCursor = sqlite3BtreeFakeValidCursor(); - } + assert( pC!=0 ); pC->nullRow = 1; pC->cacheStatus = CACHE_STALE; if( pC->eCurType==CURTYPE_BTREE ){ assert( pC->uc.pCursor!=0 ); sqlite3BtreeClearCursor(pC->uc.pCursor); } -#ifdef SQLITE_DEBUG - if( pC->seekOp==0 ) pC->seekOp = OP_NullRow; -#endif break; } -/* 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 +/* Opcode: Last P1 P2 P3 * * +** +** 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. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. ** ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. +** +** If P3 is -1, then the cursor is positioned at the end of the btree +** for the purpose of appending a new entry onto the btree. In that +** case P2 must be 0. 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. */ -case OP_SeekEnd: /* ncycle */ -case OP_Last: { /* jump0, ncycle */ +case OP_Last: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; assert( pOp->p1>=0 && pOp->p1nCursor ); @@ -99721,64 +83794,52 @@ assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); + pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG - pC->seekOp = pOp->opcode; + pC->seekOp = OP_Last; #endif - if( pOp->opcode==OP_SeekEnd ){ + if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + if( rc ) goto abort_due_to_error; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + } + }else{ 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; - if( rc ) goto abort_due_to_error; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; } break; } -/* Opcode: IfSizeBetween P1 P2 P3 P4 * -** -** Let N be the approximate number of rows in the table or index -** with cursor P1 and let X be 10*log2(N) if N is positive or -1 -** if N is zero. -** -** Jump to P2 if X is in between P3 and P4, inclusive. -*/ -case OP_IfSizeBetween: { /* jump */ +/* 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 ); - assert( pOp->p4type==P4_INT32 ); - assert( pOp->p3>=-1 && pOp->p3<=640*2 ); - assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 ); 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 = -1; /* -Infinity encoding */ - }else{ + if( res==0 ){ sz = sqlite3BtreeRowCountEst(pCrsr); - assert( sz>0 ); - sz = sqlite3LogEst((u64)sz); + if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)p3 ) res = 1; } - res = sz>=pOp->p3 && sz<=pOp->p4.i; VdbeBranchTaken(res!=0,2); if( res ) goto jump_to_p2; break; } @@ -99802,44 +83863,37 @@ ** end. We use the OP_Sort opcode instead of OP_Rewind to do the ** rewinding so that the global variable will be incremented and ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ -case OP_SorterSort: /* jump ncycle */ -case OP_Sort: { /* jump ncycle */ +case OP_SorterSort: /* jump */ +case OP_Sort: { /* jump */ #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; #endif p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ - /* no break */ deliberate_fall_through } /* Opcode: Rewind P1 P2 * * * ** -** The next use of the Rowid or Column or Next instruction for P1 +** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty, jump immediately to P2. -** If the table or index is not empty, fall through to the following +** If the table or index is not empty, fall through to the following ** instruction. ** -** If P2 is zero, that is an assertion that the P1 table is never -** empty and hence the jump will never be taken. -** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. */ -case OP_Rewind: { /* jump0, ncycle */ +case OP_Rewind: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5==0 ); - assert( pOp->p2>=0 && pOp->p2nOp ); - pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); res = 1; #ifdef SQLITE_DEBUG @@ -99855,18 +83909,17 @@ pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } if( rc ) goto abort_due_to_error; pC->nullRow = (u8)res; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - } + assert( pOp->p2>0 && pOp->p2nOp ); + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; break; } -/* Opcode: Next P1 P2 P3 * P5 +/* Opcode: Next P1 P2 P3 P4 P5 ** ** Advance cursor P1 so that it points to the next key/data pair in its ** table or index. If there are no more key/value pairs then fall through ** to the following instruction. But if the cursor advance was successful, ** jump immediately to P2. @@ -99880,17 +83933,25 @@ ** ** The P3 value is a hint to the btree implementation. If P3==1, that ** means P1 is an SQL index and that this instruction could have been ** omitted if that index had been unique. P3 is usually 0. P3 is ** always either 0 or 1. +** +** P4 is always of type P4_ADVANCE. The function pointer points to +** sqlite3BtreeNext(). ** ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. ** -** See also: Prev +** See also: Prev, NextIfOpen */ -/* Opcode: Prev P1 P2 P3 * P5 +/* Opcode: NextIfOpen P1 P2 P3 P4 P5 +** +** This opcode works just like Next except that if cursor P1 is not +** open it behaves a no-op. +*/ +/* Opcode: Prev P1 P2 P3 P4 P5 ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. @@ -99905,13 +83966,21 @@ ** ** The P3 value is a hint to the btree implementation. If P3==1, that ** means P1 is an SQL index and that this instruction could have been ** omitted if that index had been unique. P3 is usually 0. P3 is ** always either 0 or 1. +** +** P4 is always of type P4_ADVANCE. The function pointer points to +** sqlite3BtreePrevious(). ** ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. +*/ +/* Opcode: PrevIfOpen P1 P2 P3 P4 P5 +** +** 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 @@ -99923,41 +83992,37 @@ pC = p->apCsr[pOp->p1]; assert( isSorter(pC) ); rc = sqlite3VdbeSorterNext(db, pC); goto next_tail; - -case OP_Prev: /* jump, ncycle */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5==0 - || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP - || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->deferredMoveto==0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE - || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope - || pC->seekOp==OP_NullRow); - rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3); - goto next_tail; - -case OP_Next: /* jump, ncycle */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5==0 - || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP - || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->deferredMoveto==0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE - || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found - || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid - || pC->seekOp==OP_IfNoHope); - rc = sqlite3BtreeNext(pC->uc.pCursor, pOp->p3); - +case OP_PrevIfOpen: /* jump */ +case OP_NextIfOpen: /* jump */ + if( p->apCsr[pOp->p1]==0 ) break; + /* Fall through */ +case OP_Prev: /* jump */ +case OP_Next: /* jump */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p5aCounter) ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->deferredMoveto==0 ); + assert( pC->eCurType==CURTYPE_BTREE ); + 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 ); + assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); + + /* The Next opcode is only used after SeekGT, SeekGE, and Rewind. + ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ + assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen + || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE + || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found); + assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen + || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE + || pC->seekOp==OP_Last ); + + rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); next_tail: pC->cacheStatus = CACHE_STALE; VdbeBranchTaken(rc==SQLITE_OK,2); if( rc==SQLITE_OK ){ pC->nullRow = 0; @@ -99994,84 +84059,62 @@ ** ** 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. +** to P2. ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ -case OP_IdxInsert: { /* in2 */ - VdbeCursor *pC; - BtreePayload x; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - sqlite3VdbeIncrWriteCounter(p, pC); - assert( pC!=0 ); - assert( !isSorter(pC) ); - pIn2 = &aMem[pOp->p2]; - assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) ); - if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->isTable==0 ); - rc = ExpandBlob(pIn2); - if( rc ) goto abort_due_to_error; - x.nKey = pIn2->n; - x.pKey = pIn2->z; - x.aMem = aMem + pOp->p3; - x.nMem = (u16)pOp->p4.i; - rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), - ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) - ); - assert( pC->deferredMoveto==0 ); - pC->cacheStatus = CACHE_STALE; - if( rc) goto abort_due_to_error; - break; -} - /* 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_SorterInsert: /* in2 */ +case OP_IdxInsert: { /* in2 */ VdbeCursor *pC; + BtreePayload x; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - sqlite3VdbeIncrWriteCounter(p, pC); assert( pC!=0 ); - assert( isSorter(pC) ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); pIn2 = &aMem[pOp->p2]; assert( pIn2->flags & MEM_Blob ); + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert ); assert( pC->isTable==0 ); rc = ExpandBlob(pIn2); if( rc ) goto abort_due_to_error; - rc = sqlite3VdbeSorterWrite(pC, pIn2); + if( pOp->opcode==OP_SorterInsert ){ + rc = sqlite3VdbeSorterWrite(pC, pIn2); + }else{ + x.nKey = pIn2->n; + x.pKey = pIn2->z; + 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 ); + pC->cacheStatus = CACHE_STALE; + } if( rc) goto abort_due_to_error; break; } -/* Opcode: IdxDelete P1 P2 P3 * P5 +/* Opcode: IdxDelete P1 P2 P3 * * ** Synopsis: key=r[P2@P3] ** ** The content of P3 registers starting at register P2 form -** an unpacked index key. This opcode removes that entry from the +** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. -** -** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error -** if no matching index entry is found. This happens when running -** an UPDATE or DELETE statement and the index entry to be updated -** or deleted is not found. For some uses of IdxDelete -** (example: the EXCEPT operator) it does not matter that no matching -** entry is found. For those cases, P5 is zero. Also, do not raise -** this (self-correcting and non-critical) error if in writable_schema mode. */ case OP_IdxDelete: { VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -100081,25 +84124,22 @@ assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 ); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3VdbeIncrWriteCounter(p, pC); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); + assert( pOp->p5==0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p3; r.default_rc = 0; r.aMem = &aMem[pOp->p2]; - rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res); + rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); if( rc ) goto abort_due_to_error; if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; - }else if( pOp->p5 && !sqlite3WritableSchema(db) ){ - rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption"); - goto abort_due_to_error; } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; pC->seekResult = 0; break; @@ -100116,12 +84156,12 @@ ** the cursor is used to read a record. That way, if no reads ** occur, no unnecessary I/O happens. ** ** P4 may be an array of integers (type P4_INTARRAY) containing ** one entry for each column in the P3 table. If array entry a(i) -** is non-zero, then reading column a(i)-1 from cursor P3 is -** equivalent to performing the deferred seek and then reading column i +** is non-zero, then reading column a(i)-1 from cursor P3 is +** equivalent to performing the deferred seek and then reading column i ** from P1. This information is stored in P3 and used to redirect ** reads against P3 over to P1, thus possibly avoiding the need to ** seek and read cursor P3. */ /* Opcode: IdxRowid P1 P2 * * * @@ -100131,33 +84171,33 @@ ** the end of the index key pointed to by cursor P1. This integer should be ** the rowid of the table entry to which this index entry points. ** ** See also: Rowid, MakeRecord. */ -case OP_DeferredSeek: /* ncycle */ -case OP_IdxRowid: { /* out2, ncycle */ +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]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) ); + assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); - assert( pC->isTable==0 || IsNullCursor(pC) ); + assert( pC->isTable==0 ); assert( pC->deferredMoveto==0 ); assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); /* The IdxRowid and Seek opcodes are combined because of the commonality ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ rc = sqlite3VdbeCursorRestore(pC); - /* sqlite3VdbeCursorRestore() may fail if the cursor has been disturbed - ** since it was last positioned and an error (e.g. OOM or an IO error) - ** occurs while trying to reposition it. */ - if( rc!=SQLITE_OK ) goto abort_due_to_error; + /* sqlite3VbeCursorRestore() can only fail if the record has been deleted + ** out from under the cursor. That will never happens for an IdxRowid + ** or Seek opcode */ + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; if( !pC->nullRow ){ rowid = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid); if( rc!=SQLITE_OK ){ @@ -100171,15 +84211,12 @@ assert( pTabCur->uc.pCursor!=0 ); assert( pTabCur->isTable ); pTabCur->nullRow = 0; pTabCur->movetoTarget = rowid; pTabCur->deferredMoveto = 1; - pTabCur->cacheStatus = CACHE_STALE; assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); - assert( !pTabCur->isEphemeral ); - pTabCur->ub.aAltMap = pOp->p4.ai; - assert( !pC->isEphemeral ); + pTabCur->aAltMap = pOp->p4.ai; pTabCur->pAltCursor = pC; }else{ pOut = out2Prerelease(p, pOp); pOut->u.i = rowid; } @@ -100188,76 +84225,58 @@ sqlite3VdbeMemSetNull(&aMem[pOp->p2]); } break; } -/* Opcode: FinishSeek P1 * * * * -** -** If cursor P1 was previously moved via OP_DeferredSeek, complete that -** seek operation now, without further delay. If the cursor seek has -** already occurred, this instruction is a no-op. -*/ -case OP_FinishSeek: { /* ncycle */ - VdbeCursor *pC; /* The P1 index cursor */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - if( pC->deferredMoveto ){ - rc = sqlite3VdbeFinishMoveto(pC); - if( rc ) goto abort_due_to_error; - } - break; -} - -/* Opcode: IdxGE P1 P2 P3 P4 * +/* Opcode: IdxGE P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY. Compare this key value against the index -** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID ** fields at the end. ** ** If the P1 index entry is greater than or equal to the key value ** then jump to P2. Otherwise fall through to the next instruction. */ -/* Opcode: IdxGT P1 P2 P3 P4 * +/* Opcode: IdxGT P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the PRIMARY KEY. Compare this key value against the index -** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID ** fields at the end. ** ** If the P1 index entry is greater than the key value ** then jump to P2. Otherwise fall through to the next instruction. */ -/* Opcode: IdxLT P1 P2 P3 P4 * +/* Opcode: IdxLT P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index +** The P4 register values beginning with P3 form an unpacked index ** key that omits the PRIMARY KEY or ROWID. Compare this key value against ** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ** ROWID on the P1 index. ** ** If the P1 index entry is less than the key value then jump to P2. ** Otherwise fall through to the next instruction. */ -/* Opcode: IdxLE P1 P2 P3 P4 * +/* Opcode: IdxLE P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** -** The P4 register values beginning with P3 form an unpacked index +** The P4 register values beginning with P3 form an unpacked index ** key that omits the PRIMARY KEY or ROWID. Compare this key value against ** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ** ROWID on the P1 index. ** ** If the P1 index entry is less than or equal to the key value then jump ** to P2. Otherwise fall through to the next instruction. */ -case OP_IdxLE: /* jump, ncycle */ -case OP_IdxGT: /* jump, ncycle */ -case OP_IdxLT: /* jump, ncycle */ -case OP_IdxGE: { /* jump, ncycle */ +case OP_IdxLE: /* jump */ +case OP_IdxGT: /* jump */ +case OP_IdxLT: /* jump */ +case OP_IdxGE: { /* jump */ VdbeCursor *pC; int res; UnpackedRecord r; assert( pOp->p1>=0 && pOp->p1nCursor ); @@ -100265,10 +84284,11 @@ assert( pC!=0 ); assert( pC->isOrdered ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0); assert( pC->deferredMoveto==0 ); + assert( pOp->p5==0 || pOp->p5==1 ); assert( pOp->p4type==P4_INT32 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); @@ -100277,53 +84297,24 @@ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); r.default_rc = 0; } r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG - { - int i; - for(i=0; ip3+i, &aMem[pOp->p3+i]); - } - } + { int i; for(i=0; ieCurType==CURTYPE_BTREE ); - pCur = pC->uc.pCursor; - assert( sqlite3BtreeCursorIsValid(pCur) ); - nCellKey = sqlite3BtreePayloadSize(pCur); - /* nCellKey will always be between 0 and 0xffffffff because of the way - ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ - if( nCellKey<=0 || nCellKey>0x7fffffff ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); - if( rc ) goto abort_due_to_error; - res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0); - sqlite3VdbeMemReleaseMalloc(&m); - } - /* End of inlined sqlite3VdbeIdxKeyCompare() */ - + res = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); if( (pOp->opcode&1)==(OP_IdxLT&1) ){ assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); res = -res; }else{ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); res++; } VdbeBranchTaken(res>0,2); - assert( rc==SQLITE_OK ); + if( rc ) goto abort_due_to_error; if( res>0 ) goto jump_to_p2; break; } /* Opcode: Destroy P1 P2 P3 * * @@ -100330,36 +84321,35 @@ ** ** Delete an entire database table or index whose root page in the database ** file is given by P1. ** ** The table being destroyed is in the main database file if P3==0. If -** P3==1 then the table to be destroyed is in the auxiliary database file +** P3==1 then the table to be clear is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** If AUTOVACUUM is enabled then it is possible that another root page ** 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 +** 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 +** 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 */ case OP_Destroy: { /* out2 */ int iMoved; int iDb; - sqlite3VdbeIncrWriteCounter(p, 0); assert( p->readOnly==0 ); assert( pOp->p1>1 ); pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Null; if( db->nVdbeRead > db->nVDestroy+1 ){ @@ -100390,29 +84380,31 @@ ** ** Delete all contents of the database table or index whose root page ** in the database file is given by P1. But, unlike Destroy, do not ** remove the table or index from the database file. ** -** The table being cleared is in the main database file if P2==0. If -** P2==1 then the table to be cleared is in the auxiliary database file +** The table being clear is in the main database file if P2==0. If +** P2==1 then the table to be clear is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** -** If the P3 value is non-zero, then the row change count is incremented -** by the number of rows in the table being cleared. If P3 is greater -** than zero, then the value stored in register P3 is also incremented -** by the number of rows in the table being cleared. +** If the P3 value is non-zero, then the table referred to must be an +** intkey table (an SQL table, not an index). In this case the row change +** count is incremented by the number of rows in the table being cleared. +** If P3 is greater than zero, then the value stored in register P3 is +** also incremented by the number of rows in the table being cleared. ** ** See also: Destroy */ case OP_Clear: { - i64 nChange; - - sqlite3VdbeIncrWriteCounter(p, 0); + int nChange; + nChange = 0; assert( p->readOnly==0 ); assert( DbMaskTest(p->btreeMask, pOp->p2) ); - rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange); + rc = sqlite3BtreeClearTable( + db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) + ); if( pOp->p3 ){ p->nChange += nChange; if( pOp->p3>0 ){ assert( memIsValid(&aMem[pOp->p3]) ); memAboutToChange(p, &aMem[pOp->p3]); @@ -100431,11 +84423,11 @@ ** This opcode only works for cursors used for sorting and ** opened with OP_OpenEphemeral or OP_SorterOpen. */ case OP_ResetSorter: { VdbeCursor *pC; - + assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); if( isSorter(pC) ){ sqlite3VdbeSorterReset(db, pC->uc.pSorter); @@ -100446,109 +84438,87 @@ if( rc ) goto abort_due_to_error; } break; } -/* Opcode: CreateBtree P1 P2 P3 * * -** Synopsis: r[P2]=root iDb=P1 flags=P3 +/* Opcode: CreateTable P1 P2 * * * +** Synopsis: r[P2]=root iDb=P1 ** -** 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 an index or WITHOUT ROWID table. -** The root page number of the new b-tree is stored in register P2. +** 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 */ -case OP_CreateBtree: { /* out2 */ - Pgno pgno; +/* 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. +** +** See documentation on OP_CreateTable for additional information. +*/ +case OP_CreateIndex: /* out2 */ +case OP_CreateTable: { /* out2 */ + int pgno; + int flags; Db *pDb; - sqlite3VdbeIncrWriteCounter(p, 0); 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 ); - rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3); + if( pOp->opcode==OP_CreateTable ){ + /* flags = BTREE_INTKEY; */ + flags = BTREE_INTKEY; + }else{ + flags = BTREE_BLOBKEY; + } + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); if( rc ) goto abort_due_to_error; pOut->u.i = pgno; break; } -/* Opcode: SqlExec P1 P2 * P4 * +/* Opcode: SqlExec * * * P4 * ** ** Run the SQL statement or statements specified in the P4 string. -** -** The P1 parameter is a bitmask of options: -** -** 0x0001 Disable Auth and Trace callbacks while the statements -** in P4 are running. -** -** 0x0002 Set db->nAnalysisLimit to P2 while the statements in -** P4 are running. -** */ case OP_SqlExec: { - char *zErr; -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth; -#endif - u8 mTrace; - int savedAnalysisLimit; - - sqlite3VdbeIncrWriteCounter(p, 0); db->nSqlExec++; - zErr = 0; -#ifndef SQLITE_OMIT_AUTHORIZATION - xAuth = db->xAuth; -#endif - mTrace = db->mTrace; - savedAnalysisLimit = db->nAnalysisLimit; - if( pOp->p1 & 0x0001 ){ -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = 0; -#endif - db->mTrace = 0; - } - if( pOp->p1 & 0x0002 ){ - db->nAnalysisLimit = pOp->p2; - } - rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); + rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); db->nSqlExec--; -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - db->mTrace = mTrace; - db->nAnalysisLimit = savedAnalysisLimit; - if( zErr || rc ){ - sqlite3VdbeError(p, "%s", zErr); - sqlite3_free(zErr); - if( rc==SQLITE_NOMEM ) goto no_mem; - goto abort_due_to_error; - } + if( rc ) goto abort_due_to_error; break; } /* Opcode: ParseSchema P1 * * P4 * ** -** Read and parse all entries from the schema table of database P1 -** that match the WHERE clause P4. If P4 is a NULL pointer, then the -** entire schema for P1 is reparsed. +** Read and parse all entries from the SQLITE_MASTER table of database P1 +** that match the WHERE clause P4. ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a re-entrant opcode. */ case OP_ParseSchema: { int iDb; - const char *zSchema; + const char *zMaster; char *zSql; InitData initData; /* Any prepared statement that invokes this opcode will hold mutexes - ** on every btree. This is a prerequisite for invoking + ** on every btree. This is a prerequisite for invoking ** sqlite3InitCallback(). */ #ifdef SQLITE_DEBUG for(iDb=0; iDbnDb; iDb++){ assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); @@ -100555,49 +84525,28 @@ } #endif iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); - assert( DbHasProperty(db, iDb, DB_SchemaLoaded) - || db->mallocFailed - || (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) ); - -#ifndef SQLITE_OMIT_ALTERTABLE - if( pOp->p4.z==0 ){ - sqlite3SchemaClear(db->aDb[iDb].pSchema); - db->mDbFlags &= ~DBFLAG_SchemaKnownOk; - rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5); - db->mDbFlags |= DBFLAG_SchemaChange; - p->expired = 0; - }else -#endif - { - zSchema = LEGACY_SCHEMA_TABLE; + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); + /* Used to be a conditional */ { + zMaster = MASTER_NAME; initData.db = db; - initData.iDb = iDb; + initData.iDb = pOp->p1; initData.pzErrMsg = &p->zErrMsg; - initData.mInitFlags = 0; - initData.mxPage = sqlite3BtreeLastPage(db->aDb[iDb].pBt); zSql = sqlite3MPrintf(db, - "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid", - db->aDb[iDb].zDbSName, zSchema, pOp->p4.z); + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); if( zSql==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ assert( db->init.busy==0 ); db->init.busy = 1; initData.rc = SQLITE_OK; - initData.nInitRow = 0; assert( !db->mallocFailed ); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); if( rc==SQLITE_OK ) rc = initData.rc; - if( rc==SQLITE_OK && initData.nInitRow==0 ){ - /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse - ** at least one SQL statement. Any less than that indicates that - ** the sqlite_schema table is corrupt. */ - rc = SQLITE_CORRUPT_BKPT; - } sqlite3DbFreeNN(db, zSql); db->init.busy = 0; } } if( rc ){ @@ -100605,11 +84554,11 @@ if( rc==SQLITE_NOMEM ){ goto no_mem; } goto abort_due_to_error; } - break; + break; } #if !defined(SQLITE_OMIT_ANALYZE) /* Opcode: LoadAnalysis P1 * * * * ** @@ -100619,24 +84568,23 @@ */ case OP_LoadAnalysis: { assert( pOp->p1>=0 && pOp->p1nDb ); rc = sqlite3AnalysisLoad(db, pOp->p1); if( rc ) goto abort_due_to_error; - break; + break; } #endif /* !defined(SQLITE_OMIT_ANALYZE) */ /* Opcode: DropTable P1 * * P4 * ** ** Remove the internal (in-memory) data structures that describe ** the table named P4 in database P1. This is called after a table -** is dropped from disk (using the Destroy opcode) in order to keep +** is dropped from disk (using the Destroy opcode) in order to keep ** the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTable: { - sqlite3VdbeIncrWriteCounter(p, 0); sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); break; } /* Opcode: DropIndex P1 * * P4 * @@ -100646,40 +84594,38 @@ ** is dropped from disk (using the Destroy opcode) ** in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropIndex: { - sqlite3VdbeIncrWriteCounter(p, 0); sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); break; } /* Opcode: DropTrigger P1 * * P4 * ** ** Remove the internal (in-memory) data structures that describe ** the trigger named P4 in database P1. This is called after a trigger -** is dropped from disk (using the Destroy opcode) in order to keep +** is dropped from disk (using the Destroy opcode) in order to keep ** the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTrigger: { - sqlite3VdbeIncrWriteCounter(p, 0); sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); break; } #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* Opcode: IntegrityCk P1 P2 P3 P4 P5 ** ** Do an analysis of the currently open database. Store in -** register (P1+1) the text of an error message describing any problems. -** If no problems are found, store a NULL in register (P1+1). +** register P1 the text of an error message describing any problems. +** If no problems are found, store a NULL in register P1. ** -** The register (P1) contains one less than the maximum number of allowed -** errors. At most reg(P1) errors will be reported. -** In other words, the analysis stops as soon as reg(P1) errors are +** 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. ** ** The root page numbers of all tables in the database are integers ** stored in P4_INTARRAY argument. ** @@ -100688,44 +84634,41 @@ ** ** This opcode is used to implement the integrity_check pragma. */ case OP_IntegrityCk: { int nRoot; /* Number of tables to check. (Number of root pages.) */ - Pgno *aRoot; /* Array of rootpage numbers for tables to be checked */ + int *aRoot; /* Array of rootpage numbers for tables to be checked */ int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ assert( p->bIsReader ); - assert( pOp->p4type==P4_INTARRAY ); nRoot = pOp->p2; aRoot = pOp->p4.ai; assert( nRoot>0 ); - assert( aRoot!=0 ); - assert( aRoot[0]==(Pgno)nRoot ); - assert( pOp->p1>0 && (pOp->p1+1)<=(p->nMem+1 - p->nCursor) ); - pnErr = &aMem[pOp->p1]; + assert( aRoot[nRoot]==0 ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + pnErr = &aMem[pOp->p3]; assert( (pnErr->flags & MEM_Int)!=0 ); assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); - pIn1 = &aMem[pOp->p1+1]; + pIn1 = &aMem[pOp->p1]; assert( pOp->p5nDb ); assert( DbMaskTest(p->btreeMask, pOp->p5) ); - rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], - &aMem[pOp->p3], nRoot, (int)pnErr->u.i+1, &nErr, &z); + z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, + (int)pnErr->u.i+1, &nErr); sqlite3VdbeMemSetNull(pIn1); if( nErr==0 ){ assert( z==0 ); - }else if( rc ){ - sqlite3_free(z); - goto abort_due_to_error; + }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); sqlite3VdbeChangeEncoding(pIn1, encoding); - goto check_for_interrupt; + break; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: RowSetAdd P1 P2 * * * ** Synopsis: rowset(P1)=r[P2] @@ -100737,15 +84680,15 @@ */ case OP_RowSetAdd: { /* in1, in2 */ pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; assert( (pIn2->flags & MEM_Int)!=0 ); - if( (pIn1->flags & MEM_Blob)==0 ){ - if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; + if( (pIn1->flags & MEM_RowSet)==0 ){ + sqlite3VdbeMemSetRowSet(pIn1); + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; } - assert( sqlite3VdbeMemIsRowSet(pIn1) ); - sqlite3RowSetInsert((RowSet*)pIn1->z, pIn2->u.i); + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i); break; } /* Opcode: RowSetRead P1 P2 P3 * * ** Synopsis: r[P3]=rowset(P1) @@ -100757,13 +84700,12 @@ */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Blob)==0 || sqlite3VdbeMemIsRowSet(pIn1) ); - if( (pIn1->flags & MEM_Blob)==0 - || sqlite3RowSetNext((RowSet*)pIn1->z, &val)==0 + if( (pIn1->flags & MEM_RowSet)==0 + || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); VdbeBranchTaken(1,2); goto jump_to_p2_and_check_for_interrupt; @@ -100808,48 +84750,47 @@ assert( pIn3->flags&MEM_Int ); /* If there is anything other than a rowset object in memory cell P1, ** delete it now and initialize P1 with an empty rowset */ - if( (pIn1->flags & MEM_Blob)==0 ){ - if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; + if( (pIn1->flags & MEM_RowSet)==0 ){ + sqlite3VdbeMemSetRowSet(pIn1); + if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; } - assert( sqlite3VdbeMemIsRowSet(pIn1) ); + assert( pOp->p4type==P4_INT32 ); assert( iSet==-1 || iSet>=0 ); if( iSet ){ - exists = sqlite3RowSetTest((RowSet*)pIn1->z, iSet, pIn3->u.i); + exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); VdbeBranchTaken(exists!=0,2); if( exists ) goto jump_to_p2; } if( iSet>=0 ){ - sqlite3RowSetInsert((RowSet*)pIn1->z, pIn3->u.i); + sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); } break; } #ifndef SQLITE_OMIT_TRIGGER /* Opcode: Program P1 P2 P3 P4 P5 ** -** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). +** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). ** -** P1 contains the address of the memory cell that contains the first memory -** cell in an array of values used as arguments to the sub-program. P2 -** contains the address to jump to if the sub-program throws an IGNORE -** exception using the RAISE() function. P2 might be zero, if there is -** no possibility that an IGNORE exception will be raised. -** Register P3 contains the address -** of a memory cell in this (the parent) VM that is used to allocate the +** P1 contains the address of the memory cell that contains the first memory +** cell in an array of values used as arguments to the sub-program. P2 +** contains the address to jump to if the sub-program throws an IGNORE +** exception using the RAISE() function. Register P3 contains the address +** of a memory cell in this (the parent) VM that is used to allocate the ** memory required by the sub-vdbe at runtime. ** ** P4 is a pointer to the VM containing the trigger program. ** ** If P5 is non-zero, then recursive program invocation is enabled. */ -case OP_Program: { /* jump0 */ +case OP_Program: { /* jump */ int nMem; /* Number of memory registers for sub-program */ int nByte; /* Bytes of runtime space required for sub-program */ Mem *pRt; /* Register to allocate runtime space */ Mem *pMem; /* Used to iterate through memory cells */ Mem *pEnd; /* Last memory cell in new array */ @@ -100858,21 +84799,21 @@ void *t; /* Token identifying trigger */ pProgram = pOp->p4.pProgram; pRt = &aMem[pOp->p3]; assert( pProgram->nOp>0 ); - - /* If the p5 flag is clear, then recursive invocation of triggers is + + /* If the p5 flag is clear, then recursive invocation of triggers is ** disabled for backwards compatibility (p5 is set if this sub-program ** is really a trigger, not a foreign key action, and the flag set ** and cleared by the "PRAGMA recursive_triggers" command is clear). - ** - ** It is recursive invocation of triggers, at the SQL level, that is - ** disabled. In some cases a single trigger may generate more than one - ** SubProgram (if the trigger may be executed with more than one different + ** + ** It is recursive invocation of triggers, at the SQL level, that is + ** disabled. In some cases a single trigger may generate more than one + ** SubProgram (if the trigger may be executed with more than one different ** ON CONFLICT algorithm). SubProgram structures associated with a - ** single trigger all have the same value for the SubProgram.token + ** single trigger all have the same value for the SubProgram.token ** variable. */ if( pOp->p5 ){ t = pProgram->token; for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent); if( pFrame ) break; @@ -100884,14 +84825,14 @@ goto abort_due_to_error; } /* Register pRt is used to store the memory required to save the state ** of the current program, and the memory required at runtime to execute - ** the trigger program. If this trigger has been fired before, then pRt + ** the trigger program. If this trigger has been fired before, then pRt ** is already allocated. Otherwise, it must be initialized. */ - if( (pRt->flags&MEM_Blob)==0 ){ - /* SubProgram.nMem is set to the number of memory cells used by the + if( (pRt->flags&MEM_Frame)==0 ){ + /* SubProgram.nMem is set to the number of memory cells used by the ** program stored in SubProgram.aOp. As well as these, one memory ** cell is required for each cursor used by the program. Set local ** variable nMem (and later, VdbeFrame.nChildMem) to this value. */ nMem = pProgram->nMem + pProgram->nCsr; @@ -100904,14 +84845,12 @@ pFrame = sqlite3DbMallocZero(db, nByte); if( !pFrame ){ goto no_mem; } sqlite3VdbeMemRelease(pRt); - pRt->flags = MEM_Blob|MEM_Dyn; - pRt->z = (char*)pFrame; - pRt->n = nByte; - pRt->xDel = sqlite3VdbeFrameMemDel; + pRt->flags = MEM_Frame; + pRt->u.pFrame = pFrame; pFrame->v = p; pFrame->nChildMem = nMem; pFrame->nChildCsr = pProgram->nCsr; pFrame->pc = (int)(pOp - aOp); @@ -100920,23 +84859,22 @@ pFrame->apCsr = p->apCsr; pFrame->nCursor = p->nCursor; pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; -#ifdef SQLITE_DEBUG - pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + pFrame->anExec = p->anExec; #endif pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ pMem->flags = MEM_Undefined; pMem->db = db; } }else{ - pFrame = (VdbeFrame*)pRt->z; - assert( pRt->xDel==sqlite3VdbeFrameMemDel ); - assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem + pFrame = pRt->u.pFrame; + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); assert( pProgram->nCsr==pFrame->nChildCsr ); assert( (int)(pOp - aOp)==pFrame->pc ); } @@ -100956,31 +84894,24 @@ 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_DEBUG - /* Verify that second and subsequent executions of the same trigger do not - ** try to reuse register values from the first use. */ - { - int i; - for(i=0; inMem; i++){ - aMem[i].pScopyFrom = 0; /* Prevent false-positive AboutToChange() errs */ - MemSetTypeFlag(&aMem[i], MEM_Undefined); /* Fault if this reg is reused */ - } - } +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + p->anExec = 0; #endif pOp = &aOp[-1]; - goto check_for_interrupt; + + break; } /* Opcode: Param P1 P2 * * * ** -** This opcode is only ever present in sub-programs called via the -** OP_Program instruction. Copy a value currently stored in a memory -** cell of the calling (parent) frame to cell P2 in the current frames -** address space. This is used by trigger programs to access the new.* +** This opcode is only ever present in sub-programs called via the +** OP_Program instruction. Copy a value currently stored in a memory +** cell of the calling (parent) frame to cell P2 in the current frames +** address space. This is used by trigger programs to access the new.* ** and old.* values. ** ** The address of the cell in the parent frame is determined by adding ** the value of the P1 argument to the value of the P1 argument to the ** calling OP_Program instruction. @@ -100988,11 +84919,11 @@ case OP_Param: { /* out2 */ VdbeFrame *pFrame; Mem *pIn; pOut = out2Prerelease(p, pOp); pFrame = p->pFrame; - pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; + pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); break; } #endif /* #ifndef SQLITE_OMIT_TRIGGER */ @@ -101000,12 +84931,12 @@ #ifndef SQLITE_OMIT_FOREIGN_KEY /* Opcode: FkCounter P1 P2 * * * ** Synopsis: fkctr[P1]+=P2 ** ** Increment a "constraint counter" by P2 (P2 may be negative or positive). -** If P1 is non-zero, the database constraint counter is incremented -** (deferred foreign key constraints). Otherwise, if P1 is zero, the +** If P1 is non-zero, the database constraint counter is incremented +** (deferred foreign key constraints). Otherwise, if P1 is zero, the ** statement counter is incremented (immediate foreign key constraints). */ case OP_FkCounter: { if( db->flags & SQLITE_DeferFKs ){ db->nDeferredImmCons += pOp->p2; @@ -101019,11 +84950,11 @@ /* Opcode: FkIfZero P1 P2 * * * ** Synopsis: if fkctr[P1]==0 goto P2 ** ** This opcode tests if a foreign key constraint-counter is currently zero. -** If so, jump to instruction P2. Otherwise, fall through to the next +** If so, jump to instruction P2. Otherwise, fall through to the next ** instruction. ** ** If P1 is non-zero, then the jump is taken if the database constraint-counter ** is zero (the one that counts deferred constraint violations). If P1 is ** zero, the jump is taken if the statement constraint-counter is zero @@ -101045,11 +84976,11 @@ /* Opcode: MemMax P1 P2 * * * ** Synopsis: r[P1]=max(r[P1],r[P2]) ** ** P1 is a register in the root frame of this VM (the root frame is ** different from the current frame if this instruction is being executed -** within a sub-program). Set the value of register P1 to the maximum of +** within a sub-program). Set the value of register P1 to the maximum of ** its current value and the value in register P2. ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ @@ -101095,21 +85026,21 @@ /* Opcode: OffsetLimit P1 P2 P3 * * ** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) ** ** This opcode performs a commonly used computation associated with -** LIMIT and OFFSET processing. r[P1] holds the limit counter. r[P3] +** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3] ** holds the offset counter. The opcode computes the combined value ** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2] ** value computed is the total number of rows that will need to be ** visited in order to complete the query. ** ** If r[P3] is zero or negative, that means there is no OFFSET ** and r[P2] is set to be the value of the LIMIT, r[P1]. ** ** if r[P1] is zero or negative, that means there is no LIMIT -** and r[P2] is set to -1. +** and r[P2] is set to -1. ** ** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. */ case OP_OffsetLimit: { /* in1, out2, in3 */ i64 x; @@ -101137,11 +85068,11 @@ /* 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 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 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 ); @@ -101167,39 +85098,28 @@ if( pIn1->u.i==0 ) goto jump_to_p2; break; } -/* Opcode: AggStep * P2 P3 P4 P5 +/* Opcode: AggStep0 * P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** -** Execute the xStep function for an aggregate. -** The function has P5 arguments. P4 is a pointer to the -** FuncDef structure that specifies the function. Register P3 is the +** Execute the step function for an aggregate. The +** function has P5 arguments. P4 is a pointer to the FuncDef +** structure that specifies the function. Register P3 is the ** accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. */ -/* Opcode: AggInverse * P2 P3 P4 P5 -** Synopsis: accum=r[P3] inverse(r[P2@P5]) -** -** Execute the xInverse function for an aggregate. -** The function has P5 arguments. P4 is a pointer to the -** FuncDef structure that specifies the function. Register P3 is the -** accumulator. -** -** The P5 arguments are taken from register P2 and its -** successors. -*/ -/* Opcode: AggStep1 P1 P2 P3 P4 P5 +/* Opcode: AggStep * P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** -** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an -** aggregate. The function has P5 arguments. P4 is a pointer to the -** FuncDef structure that specifies the function. Register P3 is the -** accumulator. +** Execute the step function for an aggregate. The +** function has P5 arguments. P4 is a pointer to an sqlite3_context +** object that is used to run the function. Register P3 is +** as the accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. ** ** This opcode is initially coded as OP_AggStep0. On first evaluation, @@ -101206,78 +85126,45 @@ ** the FuncDef stored in P4 is converted into an sqlite3_context and ** the opcode is changed. In this way, the initialization of the ** sqlite3_context only happens once, instead of on each call to the ** step function. */ -case OP_AggInverse: -case OP_AggStep: { +case OP_AggStep0: { int n; sqlite3_context *pCtx; - u64 nAlloc; 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 ); - - /* Allocate space for (a) the context object and (n-1) extra pointers - ** to append to the sqlite3_context.argv[1] array, and (b) a memory - ** cell in which to store the accumulation. Be careful that the memory - ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits. - ** - ** Note: We could avoid this by using a regular memory cell from aMem[] for - ** the accumulator, instead of allocating one here. */ - nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) ); - pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem)); + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); if( pCtx==0 ) goto no_mem; - pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc); - assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) ); - - sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); pCtx->pMem = 0; pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; - pCtx->skipFlag = 0; - pCtx->isError = 0; - pCtx->enc = encoding; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; - - /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */ - assert( pOp->p1==(pOp->opcode==OP_AggInverse) ); - - pOp->opcode = OP_AggStep1; + pOp->opcode = OP_AggStep; /* Fall through into OP_AggStep */ - /* no break */ deliberate_fall_through } -case OP_AggStep1: { +case OP_AggStep: { int i; sqlite3_context *pCtx; Mem *pMem; + Mem t; assert( pOp->p4type==P4_FUNCCTX ); pCtx = pOp->p4.pCtx; pMem = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - if( pOp->p1 ){ - /* This is an OP_AggInverse call. Verify that xStep has always - ** been called at least once prior to any xInverse call. */ - assert( pMem->uTemp==0x1122e0e3 ); - }else{ - /* This is an OP_AggStep call. Mark it as such. */ - pMem->uTemp = 0x1122e0e3; - } -#endif - /* 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 relevant parts of the sqlite3_context object */ + ** reinitializes the relavant parts of the sqlite3_context object */ if( pCtx->pMem != pMem ){ pCtx->pMem = pMem; for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; } @@ -101287,92 +85174,61 @@ REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); } #endif pMem->n++; - assert( pCtx->pOut->flags==MEM_Null ); - assert( pCtx->isError==0 ); - assert( pCtx->skipFlag==0 ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pOp->p1 ){ - (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv); - }else -#endif + sqlite3VdbeMemInit(&t, db, MEM_Null); + pCtx->pOut = &t; + pCtx->fErrorOrAux = 0; + pCtx->skipFlag = 0; (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ - - if( pCtx->isError ){ - if( pCtx->isError>0 ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); + if( pCtx->fErrorOrAux ){ + if( pCtx->isError ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); rc = pCtx->isError; } - if( pCtx->skipFlag ){ - assert( pOp[-1].opcode==OP_CollSeq ); - i = pOp[-1].p1; - if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); - pCtx->skipFlag = 0; - } - sqlite3VdbeMemRelease(pCtx->pOut); - pCtx->pOut->flags = MEM_Null; - pCtx->isError = 0; + sqlite3VdbeMemRelease(&t); if( rc ) goto abort_due_to_error; + }else{ + assert( t.flags==MEM_Null ); } - assert( pCtx->pOut->flags==MEM_Null ); - assert( pCtx->skipFlag==0 ); + if( pCtx->skipFlag ){ + assert( pOp[-1].opcode==OP_CollSeq ); + i = pOp[-1].p1; + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); + } break; } /* Opcode: AggFinal P1 P2 * P4 * ** Synopsis: accum=r[P1] N=P2 ** -** P1 is the memory location that is the accumulator for an aggregate -** or window function. Execute the finalizer function -** for an aggregate and store the result in P1. -** -** P2 is the number of arguments that the step function takes and -** P4 is a pointer to the FuncDef for this function. The P2 -** argument is not used by this opcode. It is only there to disambiguate -** functions that can take varying numbers of arguments. The -** P4 argument is only needed for the case where -** the step function was not previously called. -*/ -/* Opcode: AggValue * P2 P3 P4 * -** Synopsis: r[P3]=value N=P2 -** -** Invoke the xValue() function and store the result in register P3. -** -** P2 is the number of arguments that the step function takes and -** P4 is a pointer to the FuncDef for this function. The P2 -** argument is not used by this opcode. It is only there to disambiguate -** functions that can take varying numbers of arguments. The -** P4 argument is only needed for the case where -** the step function was not previously called. -*/ -case OP_AggValue: -case OP_AggFinal: { - Mem *pMem; - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - assert( pOp->p3==0 || pOp->opcode==OP_AggValue ); - pMem = &aMem[pOp->p1]; - assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pOp->p3 ){ - memAboutToChange(p, &aMem[pOp->p3]); - rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); - pMem = &aMem[pOp->p3]; - }else -#endif - { - rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); - } - +** Execute the finalizer function for an aggregate. P1 is +** the memory location that is the accumulator for the aggregate. +** +** P2 is the number of arguments that the step function takes and +** P4 is a pointer to the FuncDef for this function. The P2 +** argument is not used by this opcode. It is only there to disambiguate +** functions that can take varying numbers of arguments. The +** P4 argument is only needed for the degenerate case where +** the step function was not previously called. +*/ +case OP_AggFinal: { + Mem *pMem; + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pMem = &aMem[pOp->p1]; + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); + rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); if( rc ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); goto abort_due_to_error; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); - REGISTER_TRACE((int)(pMem-aMem), pMem); + if( sqlite3VdbeMemTooBig(pMem) ){ + goto too_big; + } break; } #ifndef SQLITE_OMIT_WAL /* Opcode: Checkpoint P1 P2 P3 * * @@ -101405,13 +85261,13 @@ rc = SQLITE_OK; aRes[0] = 1; } for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){ sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]); - } + } break; -}; +}; #endif #ifndef SQLITE_OMIT_PRAGMA /* Opcode: JournalMode P1 P2 P3 * * ** @@ -101433,13 +85289,13 @@ const char *zFilename; /* Name of database file for pPager */ #endif pOut = out2Prerelease(p, pOp); eNew = pOp->p3; - assert( eNew==PAGER_JOURNALMODE_DELETE - || eNew==PAGER_JOURNALMODE_TRUNCATE - || eNew==PAGER_JOURNALMODE_PERSIST + assert( eNew==PAGER_JOURNALMODE_DELETE + || eNew==PAGER_JOURNALMODE_TRUNCATE + || eNew==PAGER_JOURNALMODE_PERSIST || eNew==PAGER_JOURNALMODE_OFF || eNew==PAGER_JOURNALMODE_MEMORY || eNew==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_QUERY ); @@ -101448,18 +85304,17 @@ pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); eOld = sqlite3PagerGetJournalMode(pPager); if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; - assert( sqlite3BtreeHoldsMutex(pBt) ); if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; #ifndef SQLITE_OMIT_WAL zFilename = sqlite3PagerFilename(pPager, 1); /* Do not allow a transition to journal_mode=WAL for a database - ** in temporary storage or if the VFS does not support shared memory + ** in temporary storage or if the VFS does not support shared memory */ if( eNew==PAGER_JOURNALMODE_WAL && (sqlite3Strlen30(zFilename)==0 /* Temp file */ || !sqlite3PagerWalSupported(pPager)) /* No shared-memory support */ ){ @@ -101475,16 +85330,16 @@ "cannot change %s wal mode from within a transaction", (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") ); goto abort_due_to_error; }else{ - + if( eOld==PAGER_JOURNALMODE_WAL ){ /* If leaving WAL mode, close the log file. If successful, the call - ** to PagerCloseWal() checkpoints and deletes the write-ahead-log - ** file. An EXCLUSIVE lock may still be held on the database file - ** after a successful return. + ** to PagerCloseWal() checkpoints and deletes the write-ahead-log + ** file. An EXCLUSIVE lock may still be held on the database file + ** after a successful return. */ rc = sqlite3PagerCloseWal(pPager, db); if( rc==SQLITE_OK ){ sqlite3PagerSetJournalMode(pPager, eNew); } @@ -101491,15 +85346,15 @@ }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ /* Cannot transition directly from MEMORY to WAL. Use mode OFF ** as an intermediate */ sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF); } - + /* Open a transaction on the database file. Regardless of the journal ** mode, this transaction always uses a rollback journal. */ - assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ); + assert( sqlite3BtreeIsInTrans(pBt)==0 ); if( rc==SQLITE_OK ){ rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); } } } @@ -101517,23 +85372,18 @@ break; }; #endif /* SQLITE_OMIT_PRAGMA */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* Opcode: Vacuum P1 P2 * * * +/* Opcode: Vacuum P1 * * * * ** ** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more ** for an attached database. The "temp" database may not be vacuumed. -** -** If P2 is not zero, then it is a register holding a string which is -** the file into which the result of vacuum should be written. When -** P2 is zero, the vacuum overwrites the original database. */ case OP_Vacuum: { assert( p->readOnly==0 ); - rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1, - pOp->p2 ? &aMem[pOp->p2] : 0); + rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1); if( rc ) goto abort_due_to_error; break; } #endif @@ -101560,72 +85410,35 @@ } break; } #endif -/* Opcode: Expire P1 P2 * * * +/* Opcode: Expire P1 * * * * ** ** Cause precompiled statements to expire. When an expired statement ** is executed using sqlite3_step() it will either automatically ** reprepare itself (if it was originally created using sqlite3_prepare_v2()) ** or it will fail with SQLITE_SCHEMA. -** +** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, ** then only the currently executing statement is expired. -** -** If P2 is 0, then SQL statements are expired immediately. If P2 is 1, -** then running SQL statements are allowed to continue to run to completion. -** The P2==1 case occurs when a CREATE INDEX or similar schema change happens -** that might help the statement run faster but which does not affect the -** correctness of operation. */ case OP_Expire: { - assert( pOp->p2==0 || pOp->p2==1 ); if( !pOp->p1 ){ - sqlite3ExpirePreparedStatements(db, pOp->p2); + sqlite3ExpirePreparedStatements(db); }else{ - p->expired = pOp->p2+1; - } - break; -} - -/* Opcode: CursorLock P1 * * * * -** -** Lock the btree to which cursor P1 is pointing so that the btree cannot be -** written by an other cursor. -*/ -case OP_CursorLock: { - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3BtreeCursorPin(pC->uc.pCursor); - break; -} - -/* Opcode: CursorUnlock P1 * * * * -** -** Unlock the btree to which cursor P1 is pointing so that it can be -** written by other cursors. -*/ -case OP_CursorUnlock: { - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3BtreeCursorUnpin(pC->uc.pCursor); + p->expired = 1; + } break; } #ifndef SQLITE_OMIT_SHARED_CACHE /* Opcode: TableLock P1 P2 P3 P4 * ** Synopsis: iDb=P1 root=P2 write=P3 ** ** Obtain a lock on a particular table. This instruction is only used when -** the shared-cache feature is enabled. +** the shared-cache feature is enabled. ** ** P1 is the index of the database in sqlite3.aDb[] of the database ** on which the lock is acquired. A readlock is obtained if P3==0 or ** a write lock if P3==1. ** @@ -101635,11 +85448,11 @@ ** used to generate an error message if the lock cannot be obtained. */ case OP_TableLock: { u8 isWriteLock = (u8)pOp->p3; if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){ - int p1 = pOp->p1; + int p1 = pOp->p1; assert( p1>=0 && p1nDb ); assert( DbMaskTest(p->btreeMask, p1) ); assert( isWriteLock==0 || isWriteLock==1 ); rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); if( rc ){ @@ -101655,11 +85468,11 @@ #endif /* SQLITE_OMIT_SHARED_CACHE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VBegin * * * P4 * ** -** P4 may be a pointer to an sqlite3_vtab structure. If so, call the +** P4 may be a pointer to an sqlite3_vtab structure. If so, call the ** xBegin method for that table. ** ** Also, whether or not P4 is set, check that this is not being called from ** within a callback to a virtual table xSync() method. If it is, the error ** code will be set to SQLITE_LOCKED. @@ -101675,11 +85488,11 @@ #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VCreate P1 P2 * * * ** -** P2 is a register that holds the name of a virtual table in database +** P2 is a register that holds the name of a virtual table in database ** P1. Call the xCreate method for that table. */ case OP_VCreate: { Mem sMem; /* For storing the record being decoded */ const char *zTab; /* Name of the virtual table */ @@ -101711,11 +85524,10 @@ */ case OP_VDestroy: { db->nVDestroy++; rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); db->nVDestroy--; - assert( p->errorAction==OE_Abort && p->usesStmtJournal ); if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -101724,11 +85536,11 @@ ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** P1 is a cursor number. This opcode opens a cursor to the virtual ** table and stores that cursor in P1. */ -case OP_VOpen: { /* ncycle */ +case OP_VOpen: { VdbeCursor *pCur; sqlite3_vtab_cursor *pVCur; sqlite3_vtab *pVtab; const sqlite3_module *pModule; @@ -101747,11 +85559,11 @@ /* Initialize sqlite3_vtab_cursor base class */ pVCur->pVtab = pVtab; /* Initialize vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB); + pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB); if( pCur ){ pCur->uc.pVCur = pVCur; pVtab->nRef++; }else{ assert( db->mallocFailed ); @@ -101759,84 +85571,10 @@ goto no_mem; } break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCheck P1 P2 P3 P4 * -** -** P4 is a pointer to a Table object that is a virtual table in schema P1 -** that supports the xIntegrity() method. This opcode runs the xIntegrity() -** method for that virtual table, using P3 as the integer argument. If -** an error is reported back, the table name is prepended to the error -** message and that message is stored in P2. If no errors are seen, -** register P2 is set to NULL. -*/ -case OP_VCheck: { /* out2 */ - Table *pTab; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - char *zErr = 0; - - pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */ - assert( pOp->p4type==P4_TABLEREF ); - pTab = pOp->p4.pTab; - assert( pTab!=0 ); - assert( pTab->nTabRef>0 ); - assert( IsVirtual(pTab) ); - if( pTab->u.vtab.p==0 ) break; - pVtab = pTab->u.vtab.p->pVtab; - assert( pVtab!=0 ); - pModule = pVtab->pModule; - assert( pModule!=0 ); - assert( pModule->iVersion>=4 ); - assert( pModule->xIntegrity!=0 ); - sqlite3VtabLock(pTab->u.vtab.p); - assert( pOp->p1>=0 && pOp->p1nDb ); - rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName, - pOp->p3, &zErr); - sqlite3VtabUnlock(pTab->u.vtab.p); - if( rc ){ - sqlite3_free(zErr); - goto abort_due_to_error; - } - if( zErr ){ - sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free); - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VInitIn P1 P2 P3 * * -** Synopsis: r[P2]=ValueList(P1,P3) -** -** Set register P2 to be a pointer to a ValueList object for cursor P1 -** with cache register P3 and output register P3+1. This ValueList object -** can be used as the first argument to sqlite3_vtab_in_first() and -** sqlite3_vtab_in_next() to extract all of the values stored in the P1 -** cursor. Register P3 is used to hold the values returned by -** sqlite3_vtab_in_first() and sqlite3_vtab_in_next(). -*/ -case OP_VInitIn: { /* out2, ncycle */ - VdbeCursor *pC; /* The cursor containing the RHS values */ - ValueList *pRhs; /* New ValueList object to put in reg[P2] */ - - pC = p->apCsr[pOp->p1]; - pRhs = sqlite3_malloc64( sizeof(*pRhs) ); - if( pRhs==0 ) goto no_mem; - pRhs->pCsr = pC->uc.pCursor; - pRhs->pOut = &aMem[pOp->p3]; - pOut = out2Prerelease(p, pOp); - pOut->flags = MEM_Null; - sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree); - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VFilter P1 P2 P3 P4 * ** Synopsis: iplan=r[P3] zplan='P4' ** @@ -101854,11 +85592,11 @@ ** additional parameters which are passed to ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. ** ** A jump is made to P2 if the result set after filtering would be empty. */ -case OP_VFilter: { /* jump, ncycle */ +case OP_VFilter: { /* jump */ int nArg; int iQuery; const sqlite3_module *pModule; Mem *pQuery; Mem *pArgc; @@ -101872,11 +85610,10 @@ pQuery = &aMem[pOp->p3]; pArgc = &pQuery[1]; pCur = p->apCsr[pOp->p1]; assert( memIsValid(pQuery) ); REGISTER_TRACE(pOp->p3, pQuery); - assert( pCur!=0 ); assert( pCur->eCurType==CURTYPE_VTAB ); pVCur = pCur->uc.pVCur; pVtab = pVCur->pVtab; pModule = pVtab->pModule; @@ -101884,10 +85621,11 @@ assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); nArg = (int)pArgc->u.i; iQuery = (int)pQuery->u.i; /* Invoke the xFilter method */ + res = 0; apArg = p->apArg; for(i = 0; ixFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg); @@ -101900,68 +85638,50 @@ break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VColumn P1 P2 P3 * P5 +/* Opcode: VColumn P1 P2 P3 * * ** Synopsis: r[P3]=vcolumn(P2) ** -** 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 OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange() -** function to return true inside the xColumn method of the virtual -** table implementation. The P5 column might also contain other -** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are -** unused by OP_VColumn. +** 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. */ -case OP_VColumn: { /* ncycle */ +case OP_VColumn: { sqlite3_vtab *pVtab; const sqlite3_module *pModule; Mem *pDest; sqlite3_context sContext; - FuncDef nullFunc; VdbeCursor *pCur = p->apCsr[pOp->p1]; - assert( pCur!=0 ); + assert( pCur->eCurType==CURTYPE_VTAB ); assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); if( pCur->nullRow ){ sqlite3VdbeMemSetNull(pDest); break; } - assert( pCur->eCurType==CURTYPE_VTAB ); pVtab = pCur->uc.pVCur->pVtab; pModule = pVtab->pModule; assert( pModule->xColumn ); memset(&sContext, 0, sizeof(sContext)); sContext.pOut = pDest; - sContext.enc = encoding; - nullFunc.pUserData = 0; - nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE; - sContext.pFunc = &nullFunc; - assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 ); - if( pOp->p5 & OPFLAG_NOCHNG ){ - sqlite3VdbeMemSetNull(pDest); - pDest->flags = MEM_Null|MEM_Zero; - pDest->u.nZero = 0; - }else{ - MemSetTypeFlag(pDest, MEM_Null); - } + MemSetTypeFlag(pDest, MEM_Null); rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2); sqlite3VtabImportErrmsg(p, pVtab); - if( sContext.isError>0 ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest)); + if( sContext.isError ){ rc = sContext.isError; } sqlite3VdbeChangeEncoding(pDest, encoding); REGISTER_TRACE(pOp->p3, pDest); UPDATE_MAX_BLOBSIZE(pDest); + if( sqlite3VdbeMemTooBig(pDest) ){ + goto too_big; + } if( rc ) goto abort_due_to_error; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -101970,18 +85690,18 @@ ** ** Advance virtual table P1 to the next row in its result set and ** jump to instruction P2. Or, if the virtual table has reached ** the end of its result set, then fall through to the next instruction. */ -case OP_VNext: { /* jump, ncycle */ +case OP_VNext: { /* jump */ sqlite3_vtab *pVtab; const sqlite3_module *pModule; int res; VdbeCursor *pCur; + res = 0; pCur = p->apCsr[pOp->p1]; - assert( pCur!=0 ); assert( pCur->eCurType==CURTYPE_VTAB ); if( pCur->nullRow ){ break; } pVtab = pCur->uc.pVCur->pVtab; @@ -101988,11 +85708,11 @@ pModule = pVtab->pModule; assert( pModule->xNext ); /* Invoke the xNext() method of the module. There is no way for the ** underlying implementation to return an error if one occurs during - ** xNext(). Instead, if an error occurs, true is returned (indicating that + ** xNext(). Instead, if an error occurs, true is returned (indicating that ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ rc = pModule->xNext(pCur->uc.pVCur); sqlite3VtabImportErrmsg(p, pVtab); @@ -102015,14 +85735,11 @@ ** in register P1 is passed as the zName argument to the xRename method. */ case OP_VRename: { sqlite3_vtab *pVtab; Mem *pName; - int isLegacy; - isLegacy = (db->flags & SQLITE_LegacyAlter); - db->flags |= SQLITE_LegacyAlter; pVtab = pOp->p4.pVtab->pVtab; pName = &aMem[pOp->p1]; assert( pVtab->pModule->xRename ); assert( memIsValid(pName) ); assert( p->readOnly==0 ); @@ -102032,11 +85749,10 @@ testcase( pName->enc==SQLITE_UTF16BE ); testcase( pName->enc==SQLITE_UTF16LE ); rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); if( rc ) goto abort_due_to_error; rc = pVtab->pModule->xRename(pVtab, pName->z); - if( isLegacy==0 ) db->flags &= ~(u64)SQLITE_LegacyAlter; sqlite3VtabImportErrmsg(p, pVtab); p->expired = 0; if( rc ) goto abort_due_to_error; break; } @@ -102046,27 +85762,27 @@ /* Opcode: VUpdate P1 P2 P3 P4 P5 ** Synopsis: data=r[P3@P2] ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. ** This opcode invokes the corresponding xUpdate method. P2 values -** are contiguous memory cells starting at P3 to pass to the xUpdate -** invocation. The value in register (P3+P2-1) corresponds to the +** are contiguous memory cells starting at P3 to pass to the xUpdate +** invocation. The value in register (P3+P2-1) corresponds to the ** p2th element of the argv array passed to xUpdate. ** ** The xUpdate method will do a DELETE or an INSERT or both. ** The argv[0] element (which corresponds to memory cell P3) -** is the rowid of a row to delete. If argv[0] is NULL then no -** deletion occurs. The argv[1] element is the rowid of the new -** row. This can be NULL to have the virtual table select the new -** rowid for itself. The subsequent elements in the array are +** is the rowid of a row to delete. If argv[0] is NULL then no +** deletion occurs. The argv[1] element is the rowid of the new +** row. This can be NULL to have the virtual table select the new +** rowid for itself. The subsequent elements in the array are ** the values of columns in the new row. ** ** If P2==1 then no insert is performed. argv[0] is the rowid of ** a row to delete. ** ** P1 is a boolean flag. If it is set to true and the xUpdate call -** is successful, then the value returned by sqlite3_last_insert_rowid() +** is successful, then the value returned by sqlite3_last_insert_rowid() ** is set to the value of the rowid for the row just inserted. ** ** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to ** apply in the case of a constraint failure on an insert or update. */ @@ -102073,20 +85789,18 @@ case OP_VUpdate: { sqlite3_vtab *pVtab; const sqlite3_module *pModule; int nArg; int i; - sqlite_int64 rowid = 0; + sqlite_int64 rowid; Mem **apArg; Mem *pX; - assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback + assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); assert( p->readOnly==0 ); - if( db->mallocFailed ) goto no_mem; - sqlite3VdbeIncrWriteCounter(p, 0); pVtab = pOp->p4.pVtab->pVtab; if( pVtab==0 || NEVER(pVtab->pModule==0) ){ rc = SQLITE_LOCKED; goto abort_due_to_error; } @@ -102162,235 +85876,12 @@ pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax); break; } #endif -/* Opcode: Function P1 P2 P3 P4 * -** Synopsis: r[P3]=func(r[P2@NP]) -** -** Invoke a user function (P4 is a pointer to an sqlite3_context object that -** contains a pointer to the function to be run) with arguments taken -** from register P2 and successors. The number of arguments is in -** the sqlite3_context object that P4 points to. -** 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: AggStep, AggFinal, PureFunc -*/ -/* Opcode: PureFunc P1 P2 P3 P4 * -** Synopsis: r[P3]=func(r[P2@NP]) -** -** Invoke a user function (P4 is a pointer to an sqlite3_context object that -** contains a pointer to the function to be run) with arguments taken -** from register P2 and successors. The number of arguments is in -** the sqlite3_context object that P4 points to. -** 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. -** -** This opcode works exactly like OP_Function. The only difference is in -** its name. This opcode is used in places where the function must be -** purely non-deterministic. Some built-in date/time functions can be -** either deterministic of non-deterministic, depending on their arguments. -** When those function are used in a non-deterministic way, they will check -** to see if they were called using OP_PureFunc instead of OP_Function, and -** if they were, they throw an error. -** -** See also: AggStep, AggFinal, Function -*/ -case OP_PureFunc: /* group */ -case OP_Function: { /* group */ - 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 relevant parts of the sqlite3_context object */ - pOut = &aMem[pOp->p3]; - if( pCtx->pOut != pOut ){ - pCtx->pVdbe = p; - pCtx->pOut = pOut; - pCtx->enc = encoding; - for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; - } - assert( pCtx->pVdbe==p ); - - 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); - assert( pCtx->isError==0 ); - (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ - - /* If the function returned an error, throw an exception */ - if( pCtx->isError ){ - if( pCtx->isError>0 ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); - rc = pCtx->isError; - } - sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); - pCtx->isError = 0; - if( rc ) goto abort_due_to_error; - } - - assert( (pOut->flags&MEM_Str)==0 - || pOut->enc==encoding - || db->mallocFailed ); - assert( !sqlite3VdbeMemTooBig(pOut) ); - - REGISTER_TRACE(pOp->p3, pOut); - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: ClrSubtype P1 * * * * -** Synopsis: r[P1].subtype = 0 -** -** Clear the subtype from register P1. -*/ -case OP_ClrSubtype: { /* in1 */ - pIn1 = &aMem[pOp->p1]; - pIn1->flags &= ~MEM_Subtype; - break; -} - -/* Opcode: GetSubtype P1 P2 * * * -** Synopsis: r[P2] = r[P1].subtype -** -** Extract the subtype value from register P1 and write that subtype -** into register P2. If P1 has no subtype, then P1 gets a NULL. -*/ -case OP_GetSubtype: { /* in1 out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( pIn1->flags & MEM_Subtype ){ - sqlite3VdbeMemSetInt64(pOut, pIn1->eSubtype); - }else{ - sqlite3VdbeMemSetNull(pOut); - } - break; -} - -/* Opcode: SetSubtype P1 P2 * * * -** Synopsis: r[P2].subtype = r[P1] -** -** Set the subtype value of register P2 to the integer from register P1. -** If P1 is NULL, clear the subtype from p2. -*/ -case OP_SetSubtype: { /* in1 out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( pIn1->flags & MEM_Null ){ - pOut->flags &= ~MEM_Subtype; - }else{ - assert( pIn1->flags & MEM_Int ); - pOut->flags |= MEM_Subtype; - pOut->eSubtype = (u8)(pIn1->u.i & 0xff); - } - break; -} - -/* Opcode: FilterAdd P1 * P3 P4 * -** Synopsis: filter(P1) += key(P3@P4) -** -** Compute a hash on the P4 registers starting with r[P3] and -** add that hash to the bloom filter contained in r[P1]. -*/ -case OP_FilterAdd: { - u64 h; - - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags & MEM_Blob ); - assert( pIn1->n>0 ); - h = filterHash(aMem, pOp); -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - int ii; - for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ - registerTrace(ii, &aMem[ii]); - } - printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); - } -#endif - h %= (pIn1->n*8); - pIn1->z[h/8] |= 1<<(h&7); - break; -} - -/* Opcode: Filter P1 P2 P3 P4 * -** Synopsis: if key(P3@P4) not in filter(P1) goto P2 -** -** Compute a hash on the key contained in the P4 registers starting -** with r[P3]. Check to see if that hash is found in the -** bloom filter hosted by register P1. If it is not present then -** maybe jump to P2. Otherwise fall through. -** -** False negatives are harmless. It is always safe to fall through, -** even if the value is in the bloom filter. A false negative causes -** more CPU cycles to be used, but it should still yield the correct -** answer. However, an incorrect answer may well arise from a -** false positive - if the jump is taken when it should fall through. -*/ -case OP_Filter: { /* jump */ - u64 h; - - assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); - pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Blob)!=0 ); - assert( pIn1->n >= 1 ); - h = filterHash(aMem, pOp); -#ifdef SQLITE_DEBUG - if( db->flags&SQLITE_VdbeTrace ){ - int ii; - for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ - registerTrace(ii, &aMem[ii]); - } - printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); - } -#endif - h %= (pIn1->n*8); - if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ - VdbeBranchTaken(1, 2); - p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++; - goto jump_to_p2; - }else{ - p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++; - VdbeBranchTaken(0, 2); - } - 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 * + +/* Opcode: Init P1 P2 * P4 * ** Synopsis: Start at P2 ** ** Programs contain a single instance of this opcode as the very first ** opcode. ** @@ -102400,20 +85891,14 @@ ** ** If P2 is not zero, jump to instruction P2. ** ** 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: { /* jump0 */ - int i; -#ifndef SQLITE_OMIT_TRACE +case OP_Init: { /* jump */ char *zTrace; -#endif + int i; /* If the P4 argument is not NULL, then it must be an SQL comment string. ** The "--" string is broken up to prevent false-positives with srcck1.c. ** ** This assert() provides evidence for: @@ -102421,32 +85906,31 @@ ** would have been returned by the legacy sqlite3_trace() interface by ** using the X argument when X begins with "--" and invoking ** sqlite3_expanded_sql(P) otherwise. */ assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); - - /* OP_Init is always instruction 0 */ - assert( pOp==p->aOp || pOp->opcode==OP_Trace ); + assert( pOp==p->aOp ); /* Always instruction 0 */ #ifndef SQLITE_OMIT_TRACE if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 - && p->minWriteFileFormat!=254 /* tag-20220401a */ + && !p->doingRerun && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){ #ifndef SQLITE_OMIT_DEPRECATED if( db->mTrace & SQLITE_TRACE_LEGACY ){ + void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace; char *z = sqlite3VdbeExpandSql(p, zTrace); - db->trace.xLegacy(db->pTraceArg, z); + x(db->pTraceArg, z); sqlite3_free(z); }else #endif if( db->nVdbeExec>1 ){ char *z = sqlite3MPrintf(db, "-- %s", zTrace); - (void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, z); + (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z); sqlite3DbFree(db, z); }else{ - (void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); + (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); } } #ifdef SQLITE_USE_FCNTL_TRACE zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ @@ -102465,11 +85949,10 @@ } #endif /* SQLITE_DEBUG */ #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; } @@ -102499,104 +85982,23 @@ } break; } #endif /* SQLITE_ENABLE_CURSOR_HINTS */ -#ifdef SQLITE_DEBUG -/* Opcode: Abortable * * * * * -** -** Verify that an Abort can happen. Assert if an Abort at this point -** might cause database corruption. This opcode only appears in debugging -** builds. -** -** An Abort is safe if either there have been no writes, or if there is -** an active statement journal. -*/ -case OP_Abortable: { - sqlite3VdbeAssertAbortable(p); - break; -} -#endif - -#ifdef SQLITE_DEBUG -/* Opcode: ReleaseReg P1 P2 P3 * P5 -** Synopsis: release r[P1@P2] mask P3 -** -** Release registers from service. Any content that was in the -** the registers is unreliable after this opcode completes. -** -** The registers released will be the P2 registers starting at P1, -** except if bit ii of P3 set, then do not release register P1+ii. -** In other words, P3 is a mask of registers to preserve. -** -** Releasing a register clears the Mem.pScopyFrom pointer. That means -** that if the content of the released register was set using OP_SCopy, -** a change to the value of the source register for the OP_SCopy will no longer -** generate an assertion fault in sqlite3VdbeMemAboutToChange(). -** -** If P5 is set, then all released registers have their type set -** to MEM_Undefined so that any subsequent attempt to read the released -** register (before it is reinitialized) will generate an assertion fault. -** -** P5 ought to be set on every call to this opcode. -** However, there are places in the code generator will release registers -** before their are used, under the (valid) assumption that the registers -** will not be reallocated for some other purpose before they are used and -** hence are safe to release. -** -** This opcode is only available in testing and debugging builds. It is -** not generated for release builds. The purpose of this opcode is to help -** validate the generated bytecode. This opcode does not actually contribute -** to computing an answer. -*/ -case OP_ReleaseReg: { - Mem *pMem; - int i; - u32 constMask; - assert( pOp->p1>0 ); - assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); - pMem = &aMem[pOp->p1]; - constMask = pOp->p3; - for(i=0; ip2; i++, pMem++){ - if( i>=32 || (constMask & MASKBIT32(i))==0 ){ - pMem->pScopyFrom = 0; - if( i<32 && pOp->p5 ) MemSetTypeFlag(pMem, MEM_Undefined); - } - } - break; -} -#endif - /* Opcode: Noop * * * * * ** -** Do nothing. Continue downward to the next opcode. -*/ -/* Opcode: Explain P1 P2 P3 P4 * -** -** This is the same as OP_Noop during normal query execution. The -** purpose of this opcode is to hold information about the query -** plan for the purpose of EXPLAIN QUERY PLAN output. -** -** The P4 value is human-readable text that describes the query plan -** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1". -** -** The P1 value is the ID of the current element and P2 is the parent -** element for the case of nested query plan elements. If P2 is zero -** then this element is a top-level element. -** -** For loop elements, P3 is the estimated code of each invocation of this -** element. -** -** As with all opcodes, the meanings of the parameters for OP_Explain -** are subject to change from one release to the next. Applications -** should not attempt to interpret or use any of the information -** contained in the OP_Explain opcode. The information provided by this -** opcode is intended for testing and debugging use only. -*/ -default: { /* This is really OP_Noop, OP_Explain */ - assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); - +** Do nothing. This instruction is often useful as a jump +** destination. +*/ +/* +** The magic Explain opcode are only inserted when explain==2 (which +** is to say when the EXPLAIN QUERY PLAN syntax is used.) +** This opcode records information from the optimizer. It is the +** the same as a no-op. This opcodesnever appears in a real VM program. +*/ +default: { /* This is really OP_Noop and OP_Explain */ + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); break; } /***************************************************************************** ** The cases of the switch statement above this line should all be indented @@ -102604,17 +86006,15 @@ ** readability. From this point on down, the normal indentation rules are ** restored. *****************************************************************************/ } -#if defined(VDBE_PROFILE) - *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); - pnCycle = 0; -#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( pnCycle ){ - *pnCycle += sqlite3Hwtime(); - pnCycle = 0; +#ifdef VDBE_PROFILE + { + u64 endTime = sqlite3Hwtime(); + if( endTime>start ) pOrigOp->cycles += endTime - start; + pOrigOp->cnt++; } #endif /* The following code adds nothing to the actual functionality ** of the program. It is only here for testing and debugging. @@ -102632,93 +86032,45 @@ registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); } if( opProperty & OPFLG_OUT3 ){ registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); } - if( opProperty==0xff ){ - /* Never happens. This code exists to avoid a harmless linkage - ** warning about sqlite3VdbeRegisterDump() being defined but not - ** used. */ - sqlite3VdbeRegisterDump(p); - } } #endif /* SQLITE_DEBUG */ #endif /* NDEBUG */ } /* The end of the for(;;) loop the loops through opcodes */ /* If we reach this point, it means that execution is finished with ** an error of some kind. */ abort_due_to_error: - if( db->mallocFailed ){ - rc = SQLITE_NOMEM_BKPT; - }else if( rc==SQLITE_IOERR_CORRUPTFS ){ - rc = SQLITE_CORRUPT_BKPT; - } + if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT; assert( rc ); -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeTrace ){ - const char *zTrace = p->zSql; - if( zTrace==0 ){ - if( aOp[0].opcode==OP_Trace ){ - zTrace = aOp[0].p4.z; - } - if( zTrace==0 ) zTrace = "???"; - } - printf("ABORT-due-to-error (rc=%d): %s\n", rc, zTrace); - } -#endif if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){ sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); } p->rc = rc; sqlite3SystemError(db, rc); testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(rc, "statement aborts at %d: [%s] %s", + sqlite3_log(rc, "statement aborts at %d: [%s] %s", (int)(pOp - aOp), p->zSql, p->zErrMsg); - if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); + sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); - if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){ - db->flags |= SQLITE_CorruptRdOnly; - } rc = SQLITE_ERROR; if( resetSchemaOnFault>0 ){ sqlite3ResetOneSchema(db, resetSchemaOnFault-1); } /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: -#if defined(VDBE_PROFILE) - if( pnCycle ){ - *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); - pnCycle = 0; - } -#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( pnCycle ){ - *pnCycle += sqlite3Hwtime(); - pnCycle = 0; - } -#endif - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - while( nVmStep>=nProgressLimit && db->xProgress!=0 ){ - nProgressLimit += db->nProgressOps; - if( db->xProgress(db->pProgressArg) ){ - nProgressLimit = LARGEST_UINT64; - rc = SQLITE_INTERRUPT; - goto abort_due_to_error; - } - } -#endif + testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; - if( DbMaskNonZero(p->lockMask) ){ - sqlite3VdbeLeave(p); - } - assert( rc!=SQLITE_OK || nExtraDelete==0 - || sqlite3_strlike("DELETE%",p->zSql,0)!=0 + sqlite3VdbeLeave(p); + assert( rc!=SQLITE_OK || nExtraDelete==0 + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 ); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH ** is encountered. @@ -102738,12 +86090,14 @@ /* Jump to here if the sqlite3_interrupt() API sets the interrupt ** flag. */ abort_due_to_interrupt: - assert( AtomicLoad(&db->u1.isInterrupted) ); - rc = SQLITE_INTERRUPT; + assert( db->u1.isInterrupted ); + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; + p->rc = rc; + sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); goto abort_due_to_error; } /************** End of vdbe.c ************************************************/ @@ -102796,40 +86150,37 @@ ** be set to point to a buffer containing an error message. It is the ** responsibility of the caller to free the error message buffer using ** sqlite3DbFree(). ** ** If an error does occur, then the b-tree cursor is closed. All subsequent -** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will +** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will ** immediately return SQLITE_ABORT. */ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ int rc; /* Error code */ char *zErr = 0; /* Error message */ Vdbe *v = (Vdbe *)p->pStmt; - /* Set the value of register r[1] in the SQL statement to integer iRow. + /* Set the value of register r[1] in the SQL statement to integer iRow. ** This is done directly as a performance optimization */ - sqlite3VdbeMemSetInt64(&v->aMem[1], iRow); + v->aMem[1].flags = MEM_Int; + v->aMem[1].u.i = iRow; /* 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 + ** then back it up to the point where it does the OP_SeekRowid. 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 ); + if( v->pc>3 ){ + v->pc = 3; rc = sqlite3VdbeExec(v); }else{ rc = sqlite3_step(p->pStmt); } if( rc==SQLITE_ROW ){ VdbeCursor *pC = v->apCsr[0]; - u32 type; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0; + 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" @@ -102880,61 +86231,60 @@ int nAttempt = 0; int iCol; /* Index of zColumn in row-record */ 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 ){ return SQLITE_MISUSE_BKPT; } #endif *ppBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTable==0 || zColumn==0 ){ + if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ sqlite3_mutex_enter(db->mutex); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); - while(1){ - sqlite3ParseObjectInit(&sParse,db); - if( !pBlob ) goto blob_open_out; + 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; sqlite3DbFree(db, zErr); zErr = 0; sqlite3BtreeEnterAll(db); - pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); + pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); if( pTab && IsVirtual(pTab) ){ pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); + sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); } if( pTab && !HasRowid(pTab) ){ pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); - } - if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){ - pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s", - zTable); - } -#ifndef SQLITE_OMIT_VIEW - if( pTab && IsView(pTab) ){ - pTab = 0; - sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); + sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable); + } +#ifndef SQLITE_OMIT_VIEW + if( pTab && pTab->pSelect ){ + pTab = 0; + sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); } #endif if( !pTab ){ - if( sParse.zErrMsg ){ + if( pParse->zErrMsg ){ sqlite3DbFree(db, zErr); - zErr = sParse.zErrMsg; - sParse.zErrMsg = 0; + zErr = pParse->zErrMsg; + pParse->zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } @@ -102941,11 +86291,11 @@ pBlob->pTab = pTab; pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iColnCol; iCol++) { - if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){ + if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ break; } } if( iCol==pTab->nCol ){ sqlite3DbFree(db, zErr); @@ -102954,24 +86304,23 @@ sqlite3BtreeLeaveAll(db); goto blob_open_out; } /* If the value is being opened for writing, check that the - ** column is not indexed, and that it is not part of a foreign key. + ** column is not indexed, and that it is not part of a foreign key. */ if( wrFlag ){ const char *zFault = 0; Index *pIdx; #ifndef SQLITE_OMIT_FOREIGN_KEY if( db->flags&SQLITE_ForeignKeys ){ /* Check that the column is not part of an FK child key definition. It ** is not necessary to check if it is part of a parent key, as parent - ** key columns must be indexed. The check below will pick up this + ** key columns must be indexed. The check below will pick up this ** case. */ FKey *pFKey; - assert( IsOrdinaryTable(pTab) ); - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ + for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ int j; for(j=0; jnCol; j++){ if( pFKey->aCol[j].iFrom==iCol ){ zFault = "foreign key"; } @@ -102995,27 +86344,27 @@ sqlite3BtreeLeaveAll(db); goto blob_open_out; } } - pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse); + pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse); assert( pBlob->pStmt || db->mallocFailed ); if( pBlob->pStmt ){ - - /* This VDBE program seeks a btree cursor to the identified + + /* This VDBE program seeks a btree cursor to the identified ** db/table/row entry. The reason for using a vdbe program instead ** of writing code to use the b-tree layer directly is that the ** vdbe program will take advantage of the various transaction, ** locking and error handling infrastructure built into the vdbe. ** ** After seeking the cursor, the vdbe executes an OP_ResultRow. ** Code external to the Vdbe then "borrows" the b-tree cursor and - ** uses it to implement the blob_read(), blob_write() and + ** uses it to implement the blob_read(), blob_write() and ** blob_bytes() functions. ** ** The sqlite3_blob_close() function finalizes the vdbe program, - ** which closes the b-tree cursor and (possibly) commits the + ** which closes the b-tree cursor and (possibly) commits the ** transaction. */ static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList openBlob[] = { {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ @@ -103028,19 +86377,18 @@ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); VdbeOp *aOp; - sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, + sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); - sqlite3VdbeChangeP5(v, 1); - assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); + sqlite3VdbeChangeP5(v, 1); aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); /* Make sure a mutex is held on the table to be accessed */ - sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeUsesBtree(v, iDb); if( db->mallocFailed==0 ){ assert( aOp!=0 ); /* Configure the OP_TableLock instruction */ #ifdef SQLITE_OMIT_SHARED_CACHE @@ -103047,60 +86395,59 @@ aOp[0].opcode = OP_Noop; #else aOp[0].p1 = iDb; aOp[0].p2 = pTab->tnum; aOp[0].p3 = wrFlag; - sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); + sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); } if( db->mallocFailed==0 ){ #endif - /* Remove either the OP_OpenWrite or OpenRead. Set the P2 + /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ if( wrFlag ) aOp[1].opcode = OP_OpenWrite; aOp[1].p2 = pTab->tnum; - aOp[1].p3 = iDb; + aOp[1].p3 = iDb; /* Configure the number of columns. Configure the cursor to ** think that the table has one more column than it really ** does. An OP_Column to retrieve this imaginary column will ** always return an SQL NULL. This is useful because it means - ** we can invoke OP_Column to fill in the vdbe cursors type + ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ aOp[1].p4type = P4_INT32; aOp[1].p4.i = pTab->nCol+1; aOp[3].p2 = pTab->nCol; - sParse.nVar = 0; - sParse.nMem = 1; - sParse.nTab = 1; - sqlite3VdbeMakeReady(v, &sParse); + pParse->nVar = 0; + pParse->nMem = 1; + pParse->nTab = 1; + sqlite3VdbeMakeReady(v, pParse); } } - + pBlob->iCol = iCol; pBlob->db = db; sqlite3BtreeLeaveAll(db); if( db->mallocFailed ){ goto blob_open_out; } rc = blobSeekToRow(pBlob, iRow, &zErr); - if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break; - sqlite3ParseObjectReset(&sParse); - } + } while( (++nAttempt)mallocFailed==0 ){ *ppBlob = (sqlite3_blob *)pBlob; }else{ if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); - sqlite3ParseObjectReset(&sParse); + sqlite3ParserReset(pParse); + sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -103112,16 +86459,15 @@ Incrblob *p = (Incrblob *)pBlob; int rc; sqlite3 *db; if( p ){ - sqlite3_stmt *pStmt = p->pStmt; db = p->db; sqlite3_mutex_enter(db->mutex); + rc = sqlite3_finalize(p->pStmt); sqlite3DbFree(db, p); sqlite3_mutex_leave(db->mutex); - rc = sqlite3_finalize(pStmt); }else{ rc = SQLITE_OK; } return rc; } @@ -103128,14 +86474,14 @@ /* ** Perform a read or write operation on a blob */ static int blobReadWrite( - sqlite3_blob *pBlob, - void *z, - int n, - int iOffset, + sqlite3_blob *pBlob, + void *z, + int n, + int iOffset, int (*xCall)(BtCursor*, u32, u32, void*) ){ int rc; Incrblob *p = (Incrblob *)pBlob; Vdbe *v; @@ -103161,29 +86507,27 @@ assert( db == v->db ); sqlite3BtreeEnterCursor(p->pCsr); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){ - /* If a pre-update hook is registered and this is a write cursor, - ** invoke it here. - ** + /* If a pre-update hook is registered and this is a write cursor, + ** invoke it here. + ** ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this ** operation should really be an SQLITE_UPDATE. This is probably - ** incorrect, but is convenient because at this point the new.* values - ** are not easily obtainable. And for the sessions module, an - ** SQLITE_UPDATE where the PK columns do not change is handled in the + ** incorrect, but is convenient because at this point the new.* values + ** are not easily obtainable. And for the sessions module, an + ** SQLITE_UPDATE where the PK columns do not change is handled in the ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually ** slightly more efficient). Since you cannot write to a PK column ** using the incremental-blob API, this works. For the sessions module ** anyhow. */ sqlite3_int64 iKey; iKey = sqlite3BtreeIntegerKey(p->pCsr); - assert( v->apCsr[0]!=0 ); - assert( v->apCsr[0]->eCurType==CURTYPE_BTREE ); sqlite3VdbePreUpdateHook( - v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol + v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1 ); } #endif rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); @@ -103230,12 +86574,12 @@ ** Move an existing blob handle to point to a different row of the same ** database table. ** ** If an error occurs, or if the specified row does not exist or does not ** contain a blob or text value, then an error code is returned and the -** database handle error code and message set. If this happens, then all -** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) +** database handle error code and message set. If this happens, then all +** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) ** immediately return SQLITE_ABORT. */ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ int rc; Incrblob *p = (Incrblob *)pBlob; @@ -103250,14 +86594,13 @@ ** already been invalidated. Return SQLITE_ABORT in this case. */ rc = SQLITE_ABORT; }else{ char *zErr; - ((Vdbe*)p->pStmt)->rc = SQLITE_OK; rc = blobSeekToRow(p, iRow, &zErr); if( rc!=SQLITE_OK ){ - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); } assert( rc!=SQLITE_SCHEMA ); } @@ -103326,41 +86669,41 @@ ** ** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This ** is like Close() followed by Init() only ** much faster. ** -** The interfaces above must be called in a particular order. Write() can +** The interfaces above must be called in a particular order. Write() can ** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and ** Compare() can only occur in between Rewind() and Close()/Reset(). i.e. ** ** Init() ** for each record: Write() ** Rewind() ** Rowkey()/Compare() -** Next() +** Next() ** Close() ** ** Algorithm: ** -** Records passed to the sorter via calls to Write() are initially held +** Records passed to the sorter via calls to Write() are initially held ** unsorted in main memory. Assuming the amount of memory used never exceeds ** a threshold, when Rewind() is called the set of records is sorted using ** an in-memory merge sort. In this case, no temporary files are required -** and subsequent calls to Rowkey(), Next() and Compare() read records +** and subsequent calls to Rowkey(), Next() and Compare() read records ** directly from main memory. ** ** If the amount of space used to store records in main memory exceeds the ** threshold, then the set of records currently in memory are sorted and ** written to a temporary file in "Packed Memory Array" (PMA) format. ** A PMA created at this point is known as a "level-0 PMA". Higher levels ** of PMAs may be created by merging existing PMAs together - for example ** merging two or more level-0 PMAs together creates a level-1 PMA. ** -** The threshold for the amount of main memory to use before flushing +** The threshold for the amount of main memory to use before flushing ** records to a PMA is roughly the same as the limit configured for the -** page-cache of the main database. Specifically, the threshold is set to -** the value returned by "PRAGMA main.page_size" multiplied by +** page-cache of the main database. Specifically, the threshold is set to +** the value returned by "PRAGMA main.page_size" multipled by ** that returned by "PRAGMA main.cache_size", in bytes. ** ** If the sorter is running in single-threaded mode, then all PMAs generated ** are appended to a single temporary file. Or, if the sorter is running in ** multi-threaded mode then up to (N+1) temporary files may be opened, where @@ -103373,32 +86716,32 @@ ** The sorter is running in multi-threaded mode if (a) the library was built ** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater ** than zero, and (b) worker threads have been enabled at runtime by calling ** "PRAGMA threads=N" with some value of N greater than 0. ** -** When Rewind() is called, any data remaining in memory is flushed to a +** When Rewind() is called, any data remaining in memory is flushed to a ** final PMA. So at this point the data is stored in some number of sorted ** PMAs within temporary files on disk. ** ** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the ** sorter is running in single-threaded mode, then these PMAs are merged -** incrementally as keys are retrieved from the sorter by the VDBE. The +** incrementally as keys are retreived from the sorter by the VDBE. The ** MergeEngine object, described in further detail below, performs this ** merge. ** ** Or, if running in multi-threaded mode, then a background thread is ** launched to merge the existing PMAs. Once the background thread has -** merged T bytes of data into a single sorted PMA, the main thread +** merged T bytes of data into a single sorted PMA, the main thread ** begins reading keys from that PMA while the background thread proceeds ** with merging the next T bytes of data. And so on. ** -** Parameter T is set to half the value of the memory threshold used +** Parameter T is set to half the value of the memory threshold used ** by Write() above to determine when to create a new PMA. ** -** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when -** Rewind() is called, then a hierarchy of incremental-merges is used. -** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on +** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when +** Rewind() is called, then a hierarchy of incremental-merges is used. +** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on ** disk are merged together. Then T bytes of data from the second set, and ** so on, such that no operation ever merges more than SORTER_MAX_MERGE_COUNT ** PMAs at a time. This done is to improve locality. ** ** If running in multi-threaded mode and there are more than @@ -103409,11 +86752,11 @@ ** the main thread to read from. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ -/* +/* ** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various ** messages to stderr that may be helpful in understanding the performance ** characteristics of the sorter in multi-threaded mode. */ #if 0 @@ -103438,11 +86781,11 @@ typedef struct SorterFile SorterFile; /* Temporary file object wrapper */ typedef struct SorterList SorterList; /* In-memory list of records */ typedef struct IncrMerger IncrMerger; /* Read & merge multiple PMAs */ /* -** A container for a temp file handle and the current amount of data +** A container for a temp file handle and the current amount of data ** stored in the file. */ struct SorterFile { sqlite3_file *pFd; /* File handle */ i64 iEof; /* Bytes of data stored in pFd */ @@ -103457,11 +86800,11 @@ ** are connected using SorterRecord.u.iNext. */ struct SorterList { SorterRecord *pList; /* Linked list of records */ u8 *aMemory; /* If non-NULL, bulk memory to hold pList */ - i64 szPMA; /* Size of pList as PMA in bytes */ + int szPMA; /* Size of pList as PMA in bytes */ }; /* ** The MergeEngine object is used to combine two or more smaller PMAs into ** one big PMA using a merge operation. Separate PMAs all need to be @@ -103478,21 +86821,21 @@ ** ** The aTree[] array is also N elements in size. The value of N is stored in ** the MergeEngine.nTree variable. ** ** The final (N/2) elements of aTree[] contain the results of comparing -** pairs of PMA keys together. Element i contains the result of +** pairs of PMA keys together. Element i contains the result of ** comparing aReadr[2*i-N] and aReadr[2*i-N+1]. Whichever key is smaller, the -** aTree element is set to the index of it. +** aTree element is set to the index of it. ** ** For the purposes of this comparison, EOF is considered greater than any ** other key value. If the keys are equal (only possible with two EOF ** values), it doesn't matter which index is stored. ** -** The (N/4) elements of aTree[] that precede the final (N/2) described +** The (N/4) elements of aTree[] that precede the final (N/2) described ** above contains the index of the smallest of each block of 4 PmaReaders -** And so on. So that aTree[1] contains the index of the PmaReader that +** And so on. So that aTree[1] contains the index of the PmaReader that ** currently points to the smallest key value. aTree[0] is unused. ** ** Example: ** ** aReadr[0] -> Banana @@ -103504,11 +86847,11 @@ ** aReadr[6] -> Durian ** aReadr[7] -> EOF ** ** aTree[] = { X, 5 0, 5 0, 3, 5, 6 } ** -** The current element is "Apple" (the value of the key indicated by +** The current element is "Apple" (the value of the key indicated by ** PmaReader 5). When the Next() operation is invoked, PmaReader 5 will ** be advanced to the next key in its segment. Say the next key is ** "Eggplant": ** ** aReadr[5] -> Eggplant @@ -103542,15 +86885,15 @@ ** single-threaded operation, there is exactly one instance of this object ** and for multi-threaded operation there are two or more instances. ** ** Essentially, this structure contains all those fields of the VdbeSorter ** structure for which each thread requires a separate instance. For example, -** each thread requeries its own UnpackedRecord object to unpack records in +** each thread requries its own UnpackedRecord object to unpack records in ** as part of comparison operations. ** -** Before a background thread is launched, variable bDone is set to 0. Then, -** right before it exits, the thread itself sets bDone to 1. This is used for +** Before a background thread is launched, variable bDone is set to 0. Then, +** right before it exits, the thread itself sets bDone to 1. This is used for ** two purposes: ** ** 1. When flushing the contents of memory to a level-0 PMA on disk, to ** attempt to select a SortSubtask for which there is not already an ** active background thread (since doing so causes the main thread @@ -103566,22 +86909,22 @@ */ typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int); struct SortSubtask { SQLiteThread *pThread; /* Background thread, if any */ int bDone; /* Set if thread is finished but not joined */ - int nPMA; /* Number of PMAs currently in file */ VdbeSorter *pSorter; /* Sorter that owns this sub-task */ UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ + int nPMA; /* Number of PMAs currently in file */ SorterCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ }; /* -** Main sorter structure. A single instance of this is allocated for each +** Main sorter structure. A single instance of this is allocated for each ** sorter cursor created by the VDBE. ** ** mxKeysize: ** As records are added to the sorter by calls to sqlite3VdbeSorterWrite(), ** this variable is updated so as to be set to the size on disk of the @@ -103614,11 +86957,11 @@ /* ** An instance of the following object is used to read records out of a ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. ** aKey might point into aMap or into aBuffer. If neither of those locations ** contain a contiguous representation of the key, then aAlloc is allocated -** and the key is copied into aAlloc and aKey is made to point to aAlloc. +** and the key is copied into aAlloc and aKey is made to poitn to aAlloc. ** ** pFd==0 at EOF. */ struct PmaReader { i64 iReadOff; /* Current read offset */ @@ -103633,25 +86976,25 @@ u8 *aMap; /* Pointer to mapping of entire file */ IncrMerger *pIncr; /* Incremental merger */ }; /* -** Normally, a PmaReader object iterates through an existing PMA stored +** Normally, a PmaReader object iterates through an existing PMA stored ** within a temp file. However, if the PmaReader.pIncr variable points to ** an object of the following type, it may be used to iterate/merge through ** multiple PMAs simultaneously. ** -** There are two types of IncrMerger object - single (bUseThread==0) and -** multi-threaded (bUseThread==1). +** There are two types of IncrMerger object - single (bUseThread==0) and +** multi-threaded (bUseThread==1). ** -** A multi-threaded IncrMerger object uses two temporary files - aFile[0] -** and aFile[1]. Neither file is allowed to grow to more than mxSz bytes in -** size. When the IncrMerger is initialized, it reads enough data from -** pMerger to populate aFile[0]. It then sets variables within the -** corresponding PmaReader object to read from that file and kicks off -** a background thread to populate aFile[1] with the next mxSz bytes of -** sorted record data from pMerger. +** A multi-threaded IncrMerger object uses two temporary files - aFile[0] +** and aFile[1]. Neither file is allowed to grow to more than mxSz bytes in +** size. When the IncrMerger is initialized, it reads enough data from +** pMerger to populate aFile[0]. It then sets variables within the +** corresponding PmaReader object to read from that file and kicks off +** a background thread to populate aFile[1] with the next mxSz bytes of +** sorted record data from pMerger. ** ** When the PmaReader reaches the end of aFile[0], it blocks until the ** background thread has finished populating aFile[1]. It then exchanges ** the contents of the aFile[0] and aFile[1] variables within this structure, ** sets the PmaReader fields to read from the new aFile[0] and kicks off @@ -103658,11 +87001,11 @@ ** another background thread to populate the new aFile[1]. And so on, until ** the contents of pMerger are exhausted. ** ** A single-threaded IncrMerger does not open any temporary files of its ** own. Instead, it has exclusive access to mxSz bytes of space beginning -** at offset iStartOff of file pTask->file2. And instead of using a +** at offset iStartOff of file pTask->file2. And instead of using a ** background thread to prepare data for the PmaReader, with a single ** threaded IncrMerger the allocate part of pTask->file2 is "refilled" with ** keys from pMerger by the calling thread whenever the PmaReader runs out ** of data. */ @@ -103770,11 +87113,11 @@ return SQLITE_OK; } assert( p->aBuffer ); - /* If there is no more data to be read from the buffer, read the next + /* If there is no more data to be read from the buffer, read the next ** p->nBuffer bytes of data from the file into it. Or, if there are less ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ iBuf = p->iReadOff % p->nBuffer; if( iBuf==0 ){ int nRead; /* Bytes to read from disk */ @@ -103791,15 +87134,15 @@ /* Readr data from the file. Return early if an error occurs. */ rc = sqlite3OsRead(p->pFd, p->aBuffer, nRead, p->iReadOff); assert( rc!=SQLITE_IOERR_SHORT_READ ); if( rc!=SQLITE_OK ) return rc; } - nAvail = p->nBuffer - iBuf; + nAvail = p->nBuffer - iBuf; if( nByte<=nAvail ){ /* The requested data is available in the in-memory buffer. In this - ** case there is no need to make a copy of the data, just return a + ** case there is no need to make a copy of the data, just return a ** pointer into the buffer to the caller. */ *ppOut = &p->aBuffer[iBuf]; p->iReadOff += nByte; }else{ /* The requested data is not all available in the in-memory buffer. @@ -103808,11 +87151,11 @@ int nRem; /* Bytes remaining to copy */ /* Extend the p->aAlloc[] allocation if required. */ if( p->nAllocnAlloc); + int nNew = MAX(128, p->nAlloc*2); while( nByte>nNew ) nNew = nNew*2; aNew = sqlite3Realloc(p->aAlloc, nNew); if( !aNew ) return SQLITE_NOMEM_BKPT; p->nAlloc = nNew; p->aAlloc = aNew; @@ -103827,18 +87170,17 @@ /* The following loop copies up to p->nBuffer bytes per iteration into ** the p->aAlloc[] buffer. */ while( nRem>0 ){ int rc; /* vdbePmaReadBlob() return code */ int nCopy; /* Number of bytes to copy */ - u8 *aNext = 0; /* Pointer to buffer to copy data from */ + u8 *aNext; /* Pointer to buffer to copy data from */ nCopy = nRem; if( nRem>p->nBuffer ) nCopy = p->nBuffer; rc = vdbePmaReadBlob(p, nCopy, &aNext); if( rc!=SQLITE_OK ) return rc; assert( aNext!=p->aAlloc ); - assert( aNext!=0 ); memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); nRem -= nCopy; } *ppOut = p->aAlloc; @@ -103875,11 +87217,11 @@ return SQLITE_OK; } /* ** Attempt to memory map file pFile. If successful, set *pp to point to the -** new mapping and return SQLITE_OK. If the mapping is not attempted +** new mapping and return SQLITE_OK. If the mapping is not attempted ** (because the file is too large or the VFS layer is configured not to use ** mmap), return SQLITE_OK and set *pp to NULL. ** ** Or, if an error occurs, return an SQLite error code. The final value of ** *pp is undefined in this case. @@ -103896,11 +87238,11 @@ return rc; } /* ** Attach PmaReader pReadr to file pFile (if it is not already attached to -** that file) and seek it to offset iOff within the file. Return SQLITE_OK +** that file) and seek it to offset iOff within the file. Return SQLITE_OK ** if successful, or an SQLite error code if an error occurs. */ static int vdbePmaReaderSeek( SortSubtask *pTask, /* Task context */ PmaReader *pReadr, /* Reader whose cursor is to be moved */ @@ -103986,15 +87328,15 @@ return rc; } /* ** Initialize PmaReader pReadr to scan through the PMA stored in file pFile -** starting at offset iStart and ending at offset iEof-1. This function -** leaves the PmaReader pointing to the first key in the PMA (or EOF if the +** starting at offset iStart and ending at offset iEof-1. This function +** leaves the PmaReader pointing to the first key in the PMA (or EOF if the ** PMA is empty). ** -** If the pnByte parameter is NULL, then it is assumed that the file +** If the pnByte parameter is NULL, then it is assumed that the file ** contains a single PMA, and that that PMA omits the initial length varint. */ static int vdbePmaReaderInit( SortSubtask *pTask, /* Task context */ SorterFile *pFile, /* Sorter file to read from */ @@ -104023,11 +87365,11 @@ return rc; } /* ** A version of vdbeSorterCompare() that assumes that it has already been -** determined that the first field of key1 is equal to the first field of +** determined that the first field of key1 is equal to the first field of ** key2. */ static int vdbeSorterCompareTail( SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ @@ -104041,11 +87383,11 @@ } return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); } /* -** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, +** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, ** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences ** used by the comparison. Return the result of the comparison. ** ** If IN/OUT parameter *pbKey2Cached is true when this function is called, ** it is assumed that (pTask->pUnpacked) contains the unpacked version @@ -104087,26 +87429,25 @@ int n1; int n2; int res; - getVarint32NR(&p1[1], n1); - getVarint32NR(&p2[1], 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->nKeyField>1 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } }else{ - assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); - if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ res = res * -1; } } return res; @@ -104165,33 +87506,32 @@ if( *v2 & 0x80 ) res = +1; } } if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } - }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ - assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); + }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ res = res * -1; } return res; } /* ** Initialize the temporary index cursor just opened as a sorter cursor. ** -** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField) +** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField) ** 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 ** is used instead. This is used when sorting records for a CREATE INDEX ** statement. In this case, keys are always delivered to the sorter in -** order of the primary key, which happens to be make up the final part +** order of the primary key, which happens to be make up the final part ** of the records being sorted. So if the sort is stable, there is never ** any reason to compare PK fields and they can be ignored for a small ** performance boost. ** ** The sorter can guarantee a stable sort when running in single-threaded @@ -104232,31 +87572,28 @@ if( nWorker>=SORTER_MAX_MERGE_COUNT ){ nWorker = SORTER_MAX_MERGE_COUNT-1; } #endif - assert( pCsr->pKeyInfo ); - assert( !pCsr->isEphemeral ); + assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); assert( pCsr->eCurType==CURTYPE_SORTER ); - szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*); + szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); pCsr->uc.pSorter = pSorter; if( pSorter==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ - Btree *pBt = db->aDb[0].pBt; pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; if( nField && nWorker==0 ){ - pKeyInfo->nKeyField = nField; + pKeyInfo->nXField += (pKeyInfo->nField - nField); + pKeyInfo->nField = nField; } - sqlite3BtreeEnter(pBt); - pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt); - sqlite3BtreeLeave(pBt); + pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->nTask = nWorker + 1; pSorter->iPrev = (u8)(nWorker - 1); pSorter->bUseThreads = (pSorter->nTask>1); pSorter->db = db; for(i=0; inTask; i++){ @@ -104278,23 +87615,24 @@ mxCache = mxCache * pgsz; } mxCache = MIN(mxCache, SQLITE_MAX_PMASZ); pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache); - /* Avoid large memory allocations if the application has requested - ** SQLITE_CONFIG_SMALL_MALLOC. */ - if( sqlite3GlobalConfig.bSmallMalloc==0 ){ + /* 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 ){ assert( pSorter->iMemory==0 ); pSorter->nMemory = pgsz; pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM_BKPT; } } - if( pKeyInfo->nAllField<13 + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) - && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0 ){ pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; } } @@ -104313,11 +87651,11 @@ sqlite3DbFree(db, p); } } /* -** Free all resources owned by the object indicated by argument pTask. All +** Free all resources owned by the object indicated by argument pTask. All ** fields of *pTask are zeroed before returning. */ static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ sqlite3DbFree(db, pTask->pUnpacked); #if SQLITE_MAX_WORKER_THREADS>0 @@ -104346,13 +87684,12 @@ int iTask = (pTask - pTask->pSorter->aTask); sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent); } static void vdbeSorterRewindDebug(const char *zEvent){ - i64 t = 0; - sqlite3_vfs *pVfs = sqlite3_vfs_find(0); - if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t); + i64 t; + sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t); fprintf(stderr, "%lld:X %s\n", t, zEvent); } static void vdbeSorterPopulateDebug( SortSubtask *pTask, const char *zEvent @@ -104413,23 +87750,23 @@ assert( pTask->pThread==0 && pTask->bDone==0 ); return sqlite3ThreadCreate(&pTask->pThread, xTask, pIn); } /* -** Join all outstanding threads launched by SorterWrite() to create +** Join all outstanding threads launched by SorterWrite() to create ** level-0 PMAs. */ static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){ int rc = rcin; int i; /* This function is always called by the main user thread. ** - ** If this function is being called after SorterRewind() has been called, + ** If this function is being called after SorterRewind() has been called, ** it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread ** is currently attempt to join one of the other threads. To avoid a race - ** condition where this thread also attempts to join the same object, join + ** condition where this thread also attempts to join the same object, join ** thread pSorter->aTask[pSorter->nTask-1].pThread first. */ for(i=pSorter->nTask-1; i>=0; i--){ SortSubtask *pTask = &pSorter->aTask[i]; int rc2 = vdbeSorterJoinThread(pTask); if( rc==SQLITE_OK ) rc = rc2; @@ -104562,11 +87899,11 @@ void *p = 0; int chunksize = 4*1024; sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); sqlite3OsFetch(pFd, 0, (int)nByte, &p); - if( p ) sqlite3OsUnfetch(pFd, 0, p); + sqlite3OsUnfetch(pFd, 0, p); } } #else # define vdbeSorterExtendFile(x,y,z) #endif @@ -104597,19 +87934,19 @@ } return rc; } /* -** If it has not already been allocated, allocate the UnpackedRecord -** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or +** If it has not already been allocated, allocate the UnpackedRecord +** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or ** if no allocation was required), or SQLITE_NOMEM otherwise. */ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pTask->pUnpacked==0 ){ pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo); if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT; - pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField; + pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; } return SQLITE_OK; } @@ -104661,32 +87998,36 @@ */ static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ if( p->typeMask==SORTER_TYPE_INTEGER ){ return vdbeSorterCompareInt; }else if( p->typeMask==SORTER_TYPE_TEXT ){ - return vdbeSorterCompareText; + return vdbeSorterCompareText; } return vdbeSorterCompare; } /* -** Sort the linked list of records headed at pTask->pList. Return -** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if +** Sort the linked list of records headed at pTask->pList. Return +** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if ** an error occurs. */ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ int i; + SorterRecord **aSlot; SorterRecord *p; int rc; - SorterRecord *aSlot[64]; rc = vdbeSortAllocUnpacked(pTask); if( rc!=SQLITE_OK ) return rc; p = pList->pList; pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); - memset(aSlot, 0, sizeof(aSlot)); + + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); + if( !aSlot ){ + return SQLITE_NOMEM_BKPT; + } while( p ){ SorterRecord *pNext; if( pList->aMemory ){ if( (u8*)p==pList->aMemory ){ @@ -104707,18 +88048,19 @@ aSlot[i] = p; p = pNext; } p = 0; - for(i=0; ipList = p; - assert( pTask->pUnpacked->errCode==SQLITE_OK - || pTask->pUnpacked->errCode==SQLITE_NOMEM + sqlite3_free(aSlot); + assert( pTask->pUnpacked->errCode==SQLITE_OK + || pTask->pUnpacked->errCode==SQLITE_NOMEM ); return pTask->pUnpacked->errCode; } /* @@ -104755,12 +88097,12 @@ } memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); p->iBufEnd += nCopy; if( p->iBufEnd==p->nBuffer ){ - p->eFWErr = sqlite3OsWrite(p->pFd, - &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, + p->eFWErr = sqlite3OsWrite(p->pFd, + &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); p->iBufStart = p->iBufEnd = 0; p->iWriteOff += p->nBuffer; } @@ -104771,21 +88113,21 @@ } /* ** Flush any buffered data to disk and clean up the PMA-writer object. ** The results of using the PMA-writer after this call are undefined. -** Return SQLITE_OK if flushing the buffered data succeeds or is not +** Return SQLITE_OK if flushing the buffered data succeeds or is not ** required. Otherwise, return an SQLite error code. ** ** Before returning, set *piEof to the offset immediately following the ** last byte written to the file. */ static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){ int rc; if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ - p->eFWErr = sqlite3OsWrite(p->pFd, - &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, + p->eFWErr = sqlite3OsWrite(p->pFd, + &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); } *piEof = (p->iWriteOff + p->iBufEnd); sqlite3_free(p->aBuffer); @@ -104793,41 +88135,41 @@ memset(p, 0, sizeof(PmaWriter)); return rc; } /* -** Write value iVal encoded as a varint to the PMA. Return +** Write value iVal encoded as a varint to the PMA. Return ** SQLITE_OK if successful, or an SQLite error code if an error occurs. */ static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){ - int nByte; + int nByte; u8 aByte[10]; nByte = sqlite3PutVarint(aByte, iVal); vdbePmaWriteBlob(p, aByte, nByte); } /* ** Write the current contents of in-memory linked-list pList to a level-0 -** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if +** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if ** successful, or an SQLite error code otherwise. ** ** The format of a PMA is: ** ** * A varint. This varint contains the total number of bytes of content ** in the PMA (not including the varint itself). ** -** * One or more records packed end-to-end in order of ascending keys. -** Each record consists of a varint followed by a blob of data (the +** * One or more records packed end-to-end in order of ascending keys. +** Each record consists of a varint followed by a blob of data (the ** key). The varint is the number of bytes in the blob of data. */ static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){ sqlite3 *db = pTask->pSorter->db; int rc = SQLITE_OK; /* Return code */ PmaWriter writer; /* Object used to write to the file */ #ifdef SQLITE_DEBUG - /* Set iSz to the expected size of file pTask->file after writing the PMA. + /* Set iSz to the expected size of file pTask->file after writing the PMA. ** This is used by an assert() statement at the end of this function. */ i64 iSz = pList->szPMA + sqlite3VarintLen(pList->szPMA) + pTask->file.iEof; #endif vdbeSorterWorkDebug(pTask, "enter"); @@ -104976,21 +88318,21 @@ int rc = SQLITE_OK; int i; SortSubtask *pTask = 0; /* Thread context used to create new PMA */ int nWorker = (pSorter->nTask-1); - /* Set the flag to indicate that at least one PMA has been written. + /* Set the flag to indicate that at least one PMA has been written. ** Or will be, anyhow. */ pSorter->bUsePMA = 1; /* Select a sub-task to sort and flush the current list of in-memory ** records to disk. If the sorter is running in multi-threaded mode, ** round-robin between the first (pSorter->nTask-1) tasks. Except, if ** the background thread from a sub-tasks previous turn is still running, ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy, ** fall back to using the final sub-task. The first (pSorter->nTask-1) - ** sub-tasks are preferred as they use background threads - the final + ** sub-tasks are prefered as they use background threads - the final ** sub-task uses the main thread. */ for(i=0; iiPrev + i + 1) % nWorker; pTask = &pSorter->aTask[iTest]; if( pTask->bDone ){ @@ -105003,20 +88345,17 @@ if( i==nWorker ){ /* Use the foreground thread for this operation */ rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list); }else{ /* Launch a background thread for this operation */ - u8 *aMem; - void *pCtx; + u8 *aMem = pTask->list.aMemory; + void *pCtx = (void*)pTask; - assert( pTask!=0 ); assert( pTask->pThread==0 && pTask->bDone==0 ); assert( pTask->list.pList==0 ); assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 ); - aMem = pTask->list.aMemory; - pCtx = (void*)pTask; pSorter->iPrev = (u8)(pTask - pSorter->aTask); pTask->list = pSorter->list; pSorter->list.pList = 0; pSorter->list.szPMA = 0; if( aMem ){ @@ -105044,17 +88383,17 @@ ){ VdbeSorter *pSorter; int rc = SQLITE_OK; /* Return Code */ SorterRecord *pNew; /* New list element */ int bFlush; /* True to flush contents of memory to PMA */ - i64 nReq; /* Bytes of memory required */ - i64 nPMA; /* Bytes of PMA space required */ + int nReq; /* Bytes of memory required */ + int nPMA; /* Bytes of PMA space required */ int t; /* serial type of first record field */ assert( pCsr->eCurType==CURTYPE_SORTER ); pSorter = pCsr->uc.pSorter; - getVarint32NR((const u8*)&pVal->z[1], t); + getVarint32((const u8*)&pVal->z[1], t); if( t>0 && t<10 && t!=7 ){ pSorter->typeMask &= SORTER_TYPE_INTEGER; }else if( t>10 && (t & 0x01) ){ pSorter->typeMask &= SORTER_TYPE_TEXT; }else{ @@ -105067,18 +88406,18 @@ ** flushed to a PMA before continuing. If so, do so. ** ** If using the single large allocation mode (pSorter->aMemory!=0), then ** flush the contents of memory to a new PMA if (a) at least one value is ** already in memory and (b) the new value will not fit in memory. - ** + ** ** Or, if using separate allocations for each record, flush the contents ** of memory to a PMA if either of the following are true: ** - ** * The total memory allocated for the in-memory list is greater + ** * The total memory allocated for the in-memory list is greater ** than (page-size * cache-size), or ** - ** * The total memory allocated for the in-memory list is greater + ** * The total memory allocated for the in-memory list is greater ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. */ nReq = pVal->n + sizeof(SorterRecord); nPMA = pVal->n + sqlite3VarintLen(pVal->n); if( pSorter->mxPmaSize ){ @@ -105106,23 +88445,19 @@ if( pSorter->list.aMemory ){ int nMin = pSorter->iMemory + nReq; if( nMin>pSorter->nMemory ){ u8 *aNew; - sqlite3_int64 nNew = 2 * (sqlite3_int64)pSorter->nMemory; - int iListOff = -1; - if( pSorter->list.pList ){ - iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; - } + int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; + int nNew = pSorter->nMemory * 2; while( nNew < nMin ) nNew = nNew*2; if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; if( nNew < nMin ) nNew = nMin; + aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); if( !aNew ) return SQLITE_NOMEM_BKPT; - if( iListOff>=0 ){ - pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; - } + pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; pSorter->list.aMemory = aNew; pSorter->nMemory = nNew; } pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; @@ -105213,15 +88548,15 @@ ** This function is called when the PmaReader corresponding to pIncr has ** finished reading the contents of aFile[0]. Its purpose is to "refill" ** aFile[0] such that the PmaReader should start rereading it from the ** beginning. ** -** For single-threaded objects, this is accomplished by literally reading -** keys from pIncr->pMerger and repopulating aFile[0]. +** For single-threaded objects, this is accomplished by literally reading +** keys from pIncr->pMerger and repopulating aFile[0]. ** -** For multi-threaded objects, all that is required is to wait until the -** background thread is finished (if it is not already) and then swap +** For multi-threaded objects, all that is required is to wait until the +** background thread is finished (if it is not already) and then swap ** aFile[0] and aFile[1] in place. If the contents of pMerger have not ** been exhausted, this function also launches a new background thread ** to populate the new aFile[1]. ** ** SQLITE_OK is returned on success, or an SQLite error code otherwise. @@ -105280,11 +88615,10 @@ pTask->file2.iEof += pIncr->mxSz; }else{ vdbeMergeEngineFree(pMerger); rc = SQLITE_NOMEM_BKPT; } - assert( *ppOut!=0 || rc!=SQLITE_OK ); return rc; } #if SQLITE_MAX_WORKER_THREADS>0 /* @@ -105358,31 +88692,31 @@ */ #define INCRINIT_NORMAL 0 #define INCRINIT_TASK 1 #define INCRINIT_ROOT 2 -/* +/* ** Forward reference required as the vdbeIncrMergeInit() and ** vdbePmaReaderIncrInit() routines are called mutually recursively when ** building a merge tree. */ static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode); /* ** Initialize the MergeEngine object passed as the second argument. Once this -** function returns, the first key of merged data may be read from the +** function returns, the first key of merged data may be read from the ** MergeEngine object in the usual fashion. ** ** If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge ** objects attached to the PmaReader objects that the merger reads from have ** already been populated, but that they have not yet populated aFile[0] and ** set the PmaReader objects up to read from it. In this case all that is ** required is to call vdbePmaReaderNext() on each PmaReader to point it at ** its first key. ** -** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use -** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data +** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use +** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data ** to pMerger. ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ static int vdbeMergeEngineInit( @@ -105390,24 +88724,19 @@ MergeEngine *pMerger, /* MergeEngine to initialize */ int eMode /* One of the INCRINIT_XXX constants */ ){ int rc = SQLITE_OK; /* Return code */ int i; /* For looping over PmaReader objects */ - int nTree; /* Number of subtrees to merge */ - - /* Failure to allocate the merge would have been detected prior to - ** invoking this routine */ - assert( pMerger!=0 ); + int nTree = pMerger->nTree; /* eMode is always INCRINIT_NORMAL in single-threaded mode */ assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); /* Verify that the MergeEngine is assigned to a single thread */ assert( pMerger->pTask==0 ); pMerger->pTask = pTask; - nTree = pMerger->nTree; for(i=0; i0 && eMode==INCRINIT_ROOT ){ /* PmaReaders should be normally initialized in order, as if they are ** reading from the same temp file this makes for more linear file IO. ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is @@ -105433,23 +88762,23 @@ ** incremental-reader (pReadr->pIncr!=0). This function serves to open ** and/or initialize the temp file related fields of the IncrMerge ** object at (pReadr->pIncr). ** ** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders -** in the sub-tree headed by pReadr are also initialized. Data is then -** loaded into the buffers belonging to pReadr and it is set to point to +** in the sub-tree headed by pReadr are also initialized. Data is then +** loaded into the buffers belonging to pReadr and it is set to point to ** the first key in its range. ** ** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed ** to be a multi-threaded PmaReader and this function is being called in a -** background thread. In this case all PmaReaders in the sub-tree are +** background thread. In this case all PmaReaders in the sub-tree are ** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to ** pReadr is populated. However, pReadr itself is not set up to point ** to its first key. A call to vdbePmaReaderNext() is still required to do -** that. +** that. ** -** The reason this function does not call vdbePmaReaderNext() immediately +** The reason this function does not call vdbePmaReaderNext() immediately ** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has ** to block on thread (pTask->thread) before accessing aFile[1]. But, since ** this entire function is being run by thread (pTask->thread), that will ** lead to the current background thread attempting to join itself. ** @@ -105470,11 +88799,11 @@ /* eMode is always INCRINIT_NORMAL in single-threaded mode */ assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - /* Set up the required files for pIncr. A multi-threaded IncrMerge object + /* Set up the required files for pIncr. A multi-theaded IncrMerge object ** requires two temp files to itself, whereas a single-threaded object ** only requires a region of pTask->file2. */ if( rc==SQLITE_OK ){ int mxSz = pIncr->mxSz; #if SQLITE_MAX_WORKER_THREADS>0 @@ -105501,16 +88830,16 @@ #if SQLITE_MAX_WORKER_THREADS>0 if( rc==SQLITE_OK && pIncr->bUseThread ){ /* Use the current thread to populate aFile[1], even though this ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object, - ** then this function is already running in background thread - ** pIncr->pTask->thread. + ** then this function is already running in background thread + ** pIncr->pTask->thread. ** - ** If this is the INCRINIT_ROOT object, then it is running in the + ** If this is the INCRINIT_ROOT object, then it is running in the ** main VDBE thread. But that is Ok, as that thread cannot return - ** control to the VDBE or proceed with anything useful until the + ** control to the VDBE or proceed with anything useful until the ** first results are ready from this merger object anyway. */ assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); rc = vdbeIncrPopulate(pIncr); } @@ -105523,11 +88852,11 @@ return rc; } #if SQLITE_MAX_WORKER_THREADS>0 /* -** The main routine for vdbePmaReaderIncrMergeInit() operations run in +** The main routine for vdbePmaReaderIncrMergeInit() operations run in ** background threads. */ static void *vdbePmaReaderBgIncrInit(void *pCtx){ PmaReader *pReader = (PmaReader*)pCtx; void *pRet = SQLITE_INT_TO_PTR( @@ -105541,12 +88870,12 @@ /* ** If the PmaReader passed as the first argument is not an incremental-reader ** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes ** the vdbePmaReaderIncrMergeInit() function with the parameters passed to ** this routine to initialize the incremental merge. -** -** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), +** +** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), ** then a background thread is launched to call vdbePmaReaderIncrMergeInit(). ** Or, if the IncrMerger is single threaded, the same function is called ** using the current thread. */ static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){ @@ -105572,11 +88901,11 @@ ** PMAs from pTask->file. If no error occurs, set *ppOut to point to ** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut ** to NULL and return an SQLite error code. ** ** When this function is called, *piOffset is set to the offset of the -** first PMA to read from pTask->file. Assuming no error occurs, it is +** first PMA to read from pTask->file. Assuming no error occurs, it is ** set to the offset immediately following the last byte of the last ** PMA before returning. If an error does occur, then the final value of ** *piOffset is undefined. */ static int vdbeMergeEngineLevel0( @@ -105682,16 +89011,16 @@ } /* ** This function is called as part of a SorterRewind() operation on a sorter ** that has already written two or more level-0 PMAs to one or more temp -** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that +** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that ** can be used to incrementally merge all PMAs on disk. ** ** If successful, SQLITE_OK is returned and *ppOut set to point to the ** MergeEngine object at the root of the tree before returning. Or, if an -** error occurs, an SQLite error code is returned and the final value +** error occurs, an SQLite error code is returned and the final value ** of *ppOut is undefined. */ static int vdbeSorterMergeTreeBuild( VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */ MergeEngine **ppOut /* Write the MergeEngine here */ @@ -105699,12 +89028,12 @@ MergeEngine *pMain = 0; int rc = SQLITE_OK; int iTask; #if SQLITE_MAX_WORKER_THREADS>0 - /* If the sorter uses more than one task, then create the top-level - ** MergeEngine here. This MergeEngine will read data from exactly + /* If the sorter uses more than one task, then create the top-level + ** MergeEngine here. This MergeEngine will read data from exactly ** one PmaReader per sub-task. */ assert( pSorter->bUseThreads || pSorter->nTask==1 ); if( pSorter->nTask>1 ){ pMain = vdbeMergeEngineNew(pSorter->nTask); if( pMain==0 ) rc = SQLITE_NOMEM_BKPT; @@ -105809,11 +89138,11 @@ assert( pIncr->pTask!=pLast ); } } for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ /* Check that: - ** + ** ** a) The incremental merge object is configured to use the ** right task, and ** b) If it is using task (nTask-1), it is configured to run ** in single-threaded mode. This is important, as the ** root merge (INCRINIT_ROOT) will be using the same task @@ -105872,11 +89201,11 @@ *pbEof = 1; } return rc; } - /* Write the current in-memory list to a PMA. When the VdbeSorterWrite() + /* Write the current in-memory list to a PMA. When the VdbeSorterWrite() ** function flushes the contents of memory to disk, it immediately always ** creates a new list consisting of a single key immediately afterwards. ** So the list is never empty at this point. */ assert( pSorter->list.pList ); rc = vdbeSorterFlushPMA(pSorter); @@ -105884,11 +89213,11 @@ /* Join all threads */ rc = vdbeSorterJoinAll(pSorter, rc); vdbeSorterRewindDebug("rewind"); - /* Assuming no errors have occurred, set up a merger structure to + /* Assuming no errors have occurred, set up a merger structure to ** incrementally read and merge all remaining PMAs. */ assert( pSorter->pReader==0 ); if( rc==SQLITE_OK ){ rc = vdbeSorterSetupMerge(pSorter); *pbEof = 0; @@ -105938,11 +89267,11 @@ } return rc; } /* -** Return a pointer to a buffer owned by the sorter that contains the +** Return a pointer to a buffer owned by the sorter that contains the ** current key. */ static void *vdbeSorterRowkey( const VdbeSorter *pSorter, /* Sorter object */ int *pnKey /* OUT: Size of current key in bytes */ @@ -106038,459 +89367,10 @@ *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2); return SQLITE_OK; } /************** End of vdbesort.c ********************************************/ -/************** Begin file vdbevtab.c ****************************************/ -/* -** 2020-03-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 virtual-tables for examining the bytecode content -** of a prepared statement. -*/ -/* #include "sqliteInt.h" */ -#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE) -/* #include "vdbeInt.h" */ - -/* An instance of the bytecode() table-valued function. -*/ -typedef struct bytecodevtab bytecodevtab; -struct bytecodevtab { - sqlite3_vtab base; /* Base class - must be first */ - sqlite3 *db; /* Database connection */ - int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */ -}; - -/* A cursor for scanning through the bytecode -*/ -typedef struct bytecodevtab_cursor bytecodevtab_cursor; -struct bytecodevtab_cursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */ - int iRowid; /* The rowid of the output table */ - int iAddr; /* Address */ - int needFinalize; /* Cursors owns pStmt and must finalize it */ - int showSubprograms; /* Provide a listing of subprograms */ - Op *aOp; /* Operand array */ - char *zP4; /* Rendered P4 value */ - const char *zType; /* tables_used.type */ - const char *zSchema; /* tables_used.schema */ - const char *zName; /* tables_used.name */ - Mem sub; /* Subprograms */ -}; - -/* -** Create a new bytecode() table-valued function. -*/ -static int bytecodevtabConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - bytecodevtab *pNew; - int rc; - int isTabUsed = pAux!=0; - const char *azSchema[2] = { - /* bytecode() schema */ - "CREATE TABLE x(" - "addr INT," - "opcode TEXT," - "p1 INT," - "p2 INT," - "p3 INT," - "p4 TEXT," - "p5 INT," - "comment TEXT," - "subprog TEXT," - "nexec INT," - "ncycle INT," - "stmt HIDDEN" - ");", - - /* Tables_used() schema */ - "CREATE TABLE x(" - "type TEXT," - "schema TEXT," - "name TEXT," - "wr INT," - "subprog TEXT," - "stmt HIDDEN" - ");" - }; - - (void)argc; - (void)argv; - (void)pzErr; - rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]); - if( rc==SQLITE_OK ){ - pNew = sqlite3_malloc( sizeof(*pNew) ); - *ppVtab = (sqlite3_vtab*)pNew; - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); - pNew->db = db; - pNew->bTablesUsed = isTabUsed*2; - } - return rc; -} - -/* -** This method is the destructor for bytecodevtab objects. -*/ -static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){ - bytecodevtab *p = (bytecodevtab*)pVtab; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Constructor for a new bytecodevtab_cursor object. -*/ -static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - bytecodevtab *pVTab = (bytecodevtab*)p; - bytecodevtab_cursor *pCur; - pCur = sqlite3_malloc( sizeof(*pCur) ); - if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); - sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* -** Clear all internal content from a bytecodevtab cursor. -*/ -static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){ - sqlite3_free(pCur->zP4); - pCur->zP4 = 0; - sqlite3VdbeMemRelease(&pCur->sub); - sqlite3VdbeMemSetNull(&pCur->sub); - if( pCur->needFinalize ){ - sqlite3_finalize(pCur->pStmt); - } - pCur->pStmt = 0; - pCur->needFinalize = 0; - pCur->zType = 0; - pCur->zSchema = 0; - pCur->zName = 0; -} - -/* -** Destructor for a bytecodevtab_cursor. -*/ -static int bytecodevtabClose(sqlite3_vtab_cursor *cur){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - bytecodevtabCursorClear(pCur); - sqlite3_free(pCur); - return SQLITE_OK; -} - - -/* -** Advance a bytecodevtab_cursor to its next row of output. -*/ -static int bytecodevtabNext(sqlite3_vtab_cursor *cur){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - bytecodevtab *pTab = (bytecodevtab*)cur->pVtab; - int rc; - if( pCur->zP4 ){ - sqlite3_free(pCur->zP4); - pCur->zP4 = 0; - } - if( pCur->zName ){ - pCur->zName = 0; - pCur->zType = 0; - pCur->zSchema = 0; - } - rc = sqlite3VdbeNextOpcode( - (Vdbe*)pCur->pStmt, - pCur->showSubprograms ? &pCur->sub : 0, - pTab->bTablesUsed, - &pCur->iRowid, - &pCur->iAddr, - &pCur->aOp); - if( rc!=SQLITE_OK ){ - sqlite3VdbeMemSetNull(&pCur->sub); - pCur->aOp = 0; - } - return SQLITE_OK; -} - -/* -** Return TRUE if the cursor has been moved off of the last -** row of output. -*/ -static int bytecodevtabEof(sqlite3_vtab_cursor *cur){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - return pCur->aOp==0; -} - -/* -** Return values of columns for the row at which the bytecodevtab_cursor -** is currently pointing. -*/ -static int bytecodevtabColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ -){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab; - Op *pOp = pCur->aOp + pCur->iAddr; - if( pVTab->bTablesUsed ){ - if( i==4 ){ - i = 8; - }else{ - if( i<=2 && pCur->zType==0 ){ - Schema *pSchema; - HashElem *k; - int iDb = pOp->p3; - Pgno iRoot = (Pgno)pOp->p2; - sqlite3 *db = pVTab->db; - pSchema = db->aDb[iDb].pSchema; - pCur->zSchema = db->aDb[iDb].zDbSName; - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - Table *pTab = (Table*)sqliteHashData(k); - if( !IsVirtual(pTab) && pTab->tnum==iRoot ){ - pCur->zName = pTab->zName; - pCur->zType = "table"; - break; - } - } - if( pCur->zName==0 ){ - for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){ - Index *pIdx = (Index*)sqliteHashData(k); - if( pIdx->tnum==iRoot ){ - pCur->zName = pIdx->zName; - pCur->zType = "index"; - } - } - } - } - i += 20; - } - } - switch( i ){ - case 0: /* addr */ - sqlite3_result_int(ctx, pCur->iAddr); - break; - case 1: /* opcode */ - sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode), - -1, SQLITE_STATIC); - break; - case 2: /* p1 */ - sqlite3_result_int(ctx, pOp->p1); - break; - case 3: /* p2 */ - sqlite3_result_int(ctx, pOp->p2); - break; - case 4: /* p3 */ - sqlite3_result_int(ctx, pOp->p3); - break; - case 5: /* p4 */ - case 7: /* comment */ - if( pCur->zP4==0 ){ - pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp); - } - if( i==5 ){ - sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC); - }else{ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4); - sqlite3_result_text(ctx, zCom, -1, sqlite3_free); -#endif - } - break; - case 6: /* p5 */ - sqlite3_result_int(ctx, pOp->p5); - break; - case 8: { /* subprog */ - Op *aOp = pCur->aOp; - assert( aOp[0].opcode==OP_Init ); - assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 ); - if( pCur->iRowid==pCur->iAddr+1 ){ - break; /* Result is NULL for the main program */ - }else if( aOp[0].p4.z!=0 ){ - sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC); - }else{ - sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC); - } - break; - } - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - case 9: /* nexec */ - sqlite3_result_int64(ctx, pOp->nExec); - break; - case 10: /* ncycle */ - sqlite3_result_int64(ctx, pOp->nCycle); - break; -#else - case 9: /* nexec */ - case 10: /* ncycle */ - sqlite3_result_int(ctx, 0); - break; -#endif - - case 20: /* tables_used.type */ - sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC); - break; - case 21: /* tables_used.schema */ - sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC); - break; - case 22: /* tables_used.name */ - sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC); - break; - case 23: /* tables_used.wr */ - sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite); - break; - } - return SQLITE_OK; -} - -/* -** Return the rowid for the current row. In this implementation, the -** rowid is the same as the output value. -*/ -static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur; - *pRowid = pCur->iRowid; - return SQLITE_OK; -} - -/* -** Initialize a cursor. -** -** idxNum==0 means show all subprograms -** idxNum==1 means show only the main bytecode and omit subprograms. -*/ -static int bytecodevtabFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor; - bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab; - int rc = SQLITE_OK; - (void)idxStr; - - bytecodevtabCursorClear(pCur); - pCur->iRowid = 0; - pCur->iAddr = 0; - pCur->showSubprograms = idxNum==0; - assert( argc==1 ); - if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){ - const char *zSql = (const char*)sqlite3_value_text(argv[0]); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0); - pCur->needFinalize = 1; - } - }else{ - pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer"); - } - if( pCur->pStmt==0 ){ - pVTab->base.zErrMsg = sqlite3_mprintf( - "argument to %s() is not a valid SQL statement", - pVTab->bTablesUsed ? "tables_used" : "bytecode" - ); - rc = SQLITE_ERROR; - }else{ - bytecodevtabNext(pVtabCursor); - } - return rc; -} - -/* -** We must have a single stmt=? constraint that will be passed through -** into the xFilter method. If there is no valid stmt=? constraint, -** then return an SQLITE_CONSTRAINT error. -*/ -static int bytecodevtabBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo -){ - int i; - int rc = SQLITE_CONSTRAINT; - struct sqlite3_index_constraint *p; - bytecodevtab *pVTab = (bytecodevtab*)tab; - int iBaseCol = pVTab->bTablesUsed ? 4 : 10; - pIdxInfo->estimatedCost = (double)100; - pIdxInfo->estimatedRows = 100; - pIdxInfo->idxNum = 0; - for(i=0, p=pIdxInfo->aConstraint; inConstraint; i++, p++){ - if( p->usable==0 ) continue; - if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){ - rc = SQLITE_OK; - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - } - if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){ - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->idxNum = 1; - } - } - return rc; -} - -/* -** This following structure defines all the methods for the -** virtual table. -*/ -static sqlite3_module bytecodevtabModule = { - /* iVersion */ 0, - /* xCreate */ 0, - /* xConnect */ bytecodevtabConnect, - /* xBestIndex */ bytecodevtabBestIndex, - /* xDisconnect */ bytecodevtabDisconnect, - /* xDestroy */ 0, - /* xOpen */ bytecodevtabOpen, - /* xClose */ bytecodevtabClose, - /* xFilter */ bytecodevtabFilter, - /* xNext */ bytecodevtabNext, - /* xEof */ bytecodevtabEof, - /* xColumn */ bytecodevtabColumn, - /* xRowid */ bytecodevtabRowid, - /* xUpdate */ 0, - /* xBegin */ 0, - /* xSync */ 0, - /* xCommit */ 0, - /* xRollback */ 0, - /* xFindMethod */ 0, - /* xRename */ 0, - /* xSavepoint */ 0, - /* xRelease */ 0, - /* xRollbackTo */ 0, - /* xShadowName */ 0, - /* xIntegrity */ 0 -}; - - -SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ - int rc; - rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db); - } - return rc; -} -#elif defined(SQLITE_ENABLE_BYTECODE_VTAB) -SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; } -#endif /* SQLITE_ENABLE_BYTECODE_VTAB */ - -/************** End of vdbevtab.c ********************************************/ /************** Begin file memjournal.c **************************************/ /* ** 2008 October 7 ** ** The author disclaims copyright to this source code. In place of @@ -106560,10 +89440,11 @@ struct MemJournal { const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ int nChunkSize; /* In-memory chunk-size */ int nSpill; /* Bytes of data before flushing */ + int nSize; /* Bytes of data currently in memory */ FileChunk *pFirst; /* Head of in-memory chunk-list */ FilePoint endpoint; /* Pointer to the end of the file */ FilePoint readpoint; /* Pointer to the end of the last xRead() */ int flags; /* xOpen flags */ @@ -106585,17 +89466,21 @@ u8 *zOut = zBuf; int nRead = iAmt; int iChunkOffset; FileChunk *pChunk; +#ifdef SQLITE_ENABLE_ATOMIC_WRITE if( (iAmt+iOfst)>p->endpoint.iOffset ){ return SQLITE_IOERR_SHORT_READ; } +#endif + + assert( (iAmt+iOfst)<=p->endpoint.iOffset ); assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 ); if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ sqlite3_int64 iOff = 0; - for(pChunk=p->pFirst; + for(pChunk=p->pFirst; ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst; pChunk=pChunk->pNext ){ iOff += p->nChunkSize; } @@ -106620,17 +89505,18 @@ } /* ** Free the list of FileChunk structures headed at MemJournal.pFirst. */ -static void memjrnlFreeChunks(FileChunk *pFirst){ +static void memjrnlFreeChunks(MemJournal *p){ FileChunk *pIter; FileChunk *pNext; - for(pIter=pFirst; pIter; pIter=pNext){ + for(pIter=p->pFirst; pIter; pIter=pNext){ pNext = pIter->pNext; sqlite3_free(pIter); - } + } + p->pFirst = 0; } /* ** Flush the contents of memory to a real file on disk. */ @@ -106653,11 +89539,11 @@ if( rc ) break; iOff += nChunk; } if( rc==SQLITE_OK ){ /* No error has occurred. Free the in-memory buffers. */ - memjrnlFreeChunks(copy.pFirst); + memjrnlFreeChunks(©); } } if( rc!=SQLITE_OK ){ /* If an error occurred while creating or writing to the file, restore ** the original before returning. This way, SQLite uses the in-memory @@ -106668,13 +89554,10 @@ } return rc; } -/* Forward reference */ -static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size); - /* ** Write data to the file. */ static int memjrnlWrite( sqlite3_file *pJfd, /* The journal file into which to write */ @@ -106700,25 +89583,26 @@ else{ /* An in-memory journal file should only ever be appended to. Random ** access writes are not required. The only exception to this is when ** the in-memory journal is being used by a connection using the ** 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 ); - if( iOfst>0 && iOfst!=p->endpoint.iOffset ){ - memjrnlTruncate(pJfd, iOfst); - } + ** journal file may be written as part of committing the transaction. */ + assert( iOfst==p->endpoint.iOffset || iOfst==0 ); +#ifdef SQLITE_ENABLE_ATOMIC_WRITE if( iOfst==0 && p->pFirst ){ assert( p->nChunkSize>iAmt ); memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); - }else{ + }else +#else + assert( iOfst>0 || p->pFirst==0 ); +#endif + { while( nWrite>0 ){ FileChunk *pChunk = p->endpoint.pChunk; int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize); int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset); - assert( pChunk!=0 || iChunkOffset==0 ); if( iChunkOffset==0 ){ /* New chunk is required to extend the file. */ FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize)); if( !pNew ){ return SQLITE_IOERR_NOMEM_BKPT; @@ -106729,49 +89613,39 @@ pChunk->pNext = pNew; }else{ assert( !p->pFirst ); p->pFirst = pNew; } - pChunk = p->endpoint.pChunk = pNew; + p->endpoint.pChunk = pNew; } - assert( pChunk!=0 ); - memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace); + memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace); zWrite += iSpace; nWrite -= iSpace; p->endpoint.iOffset += iSpace; } + p->nSize = iAmt + iOfst; } } return SQLITE_OK; } /* -** Truncate the in-memory file. +** Truncate the file. +** +** If the journal file is already on disk, truncate it there. Or, if it +** is still in main memory but is being truncated to zero bytes in size, +** ignore */ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ MemJournal *p = (MemJournal *)pJfd; - assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 ); - if( sizeendpoint.iOffset ){ - FileChunk *pIter = 0; - if( size==0 ){ - memjrnlFreeChunks(p->pFirst); - p->pFirst = 0; - }else{ - i64 iOff = p->nChunkSize; - for(pIter=p->pFirst; ALWAYS(pIter) && iOffpNext){ - iOff += p->nChunkSize; - } - if( ALWAYS(pIter) ){ - memjrnlFreeChunks(pIter->pNext); - pIter->pNext = 0; - } - } - - p->endpoint.pChunk = pIter; - p->endpoint.iOffset = size; + if( ALWAYS(size==0) ){ + memjrnlFreeChunks(p); + p->nSize = 0; + p->endpoint.pChunk = 0; + p->endpoint.iOffset = 0; p->readpoint.pChunk = 0; p->readpoint.iOffset = 0; } return SQLITE_OK; } @@ -106779,19 +89653,19 @@ /* ** Close the file. */ static int memjrnlClose(sqlite3_file *pJfd){ MemJournal *p = (MemJournal *)pJfd; - memjrnlFreeChunks(p->pFirst); + memjrnlFreeChunks(p); return SQLITE_OK; } /* ** Sync the file. ** -** If the real file has been created, call its xSync method. Otherwise, -** syncing an in-memory journal is a no-op. +** If the real file has been created, call its xSync method. Otherwise, +** syncing an in-memory journal is a no-op. */ static int memjrnlSync(sqlite3_file *pJfd, int flags){ UNUSED_PARAMETER2(pJfd, flags); return SQLITE_OK; } @@ -106828,15 +89702,15 @@ 0, /* xShmUnmap */ 0, /* xFetch */ 0 /* xUnfetch */ }; -/* -** Open a journal file. +/* +** Open a journal file. ** -** The behaviour of the journal file depends on the value of parameter -** nSpill. If nSpill is 0, then the journal file is always create and +** The behaviour of the journal file depends on the value of parameter +** nSpill. If nSpill is 0, then the journal file is always create and ** accessed using the underlying VFS. If nSpill is less than zero, then ** all content is always stored in main-memory. Finally, if nSpill is a ** positive value, then the journal file is initially created in-memory ** but may be flushed to disk later on. In this case the journal file is ** flushed to disk either when it grows larger than nSpill bytes in size, @@ -106849,12 +89723,10 @@ int flags, /* Opening flags */ int nSpill /* Bytes buffered before opening the file */ ){ MemJournal *p = (MemJournal*)pJfd; - assert( zName || nSpill<0 || (flags & SQLITE_OPEN_EXCLUSIVE) ); - /* Zero the file-handle object. If nSpill was passed zero, initialize ** it using the sqlite3OsOpen() function of the underlying VFS. In this ** case none of the code in this module is executed as a result of calls ** made on the journal file-handle. */ memset(p, 0, sizeof(MemJournal)); @@ -106867,11 +89739,11 @@ }else{ p->nChunkSize = 8 + MEMJOURNAL_DFLT_FILECHUNKSIZE - sizeof(FileChunk); assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) ); } - pJfd->pMethods = (const sqlite3_io_methods*)&MemJournalMethods; + p->pMethod = (const sqlite3_io_methods*)&MemJournalMethods; p->nSpill = nSpill; p->flags = flags; p->zJournal = zName; p->pVfs = pVfs; return SQLITE_OK; @@ -106882,35 +89754,21 @@ */ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ sqlite3JournalOpen(0, 0, pJfd, 0, -1); } -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) +#ifdef SQLITE_ENABLE_ATOMIC_WRITE /* -** If the argument p points to a MemJournal structure that is not an +** 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 or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying -** file has not yet been created, create it now. +** nSpill parameter), and the underlying file has not yet been created, +** create it now. */ -SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *pJfd){ +SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ int rc = SQLITE_OK; - MemJournal *p = (MemJournal*)pJfd; - if( pJfd->pMethods==&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); + if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){ + rc = memjrnlCreateFile((MemJournal*)p); } return rc; } #endif @@ -106921,11 +89779,11 @@ */ SQLITE_PRIVATE int sqlite3JournalIsInMemory(sqlite3_file *p){ return p->pMethods==&MemJournalMethods; } -/* +/* ** Return the number of bytes required to store a JournalFile that uses vfs ** pVfs to create the underlying on-disk files. */ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ return MAX(pVfs->szOsFile, (int)sizeof(MemJournal)); @@ -106950,35 +89808,10 @@ /* #include "sqliteInt.h" */ /* #include */ /* #include */ -#if !defined(SQLITE_OMIT_WINDOWFUNC) -/* -** Walk all expressions linked into the list of Window objects passed -** as the second argument. -*/ -static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){ - Window *pWin; - for(pWin=pList; pWin; pWin=pWin->pNextWin){ - int rc; - rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExprList(pWalker, pWin->pPartition); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExpr(pWalker, pWin->pFilter); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExpr(pWalker, pWin->pStart); - if( rc ) return WRC_Abort; - rc = sqlite3WalkExpr(pWalker, pWin->pEnd); - if( rc ) return WRC_Abort; - if( bOneOnly ) break; - } - return WRC_Continue; -} -#endif - /* ** Walk an expression tree. Invoke the callback once for each node ** of the expression, while descending. (In other words, the callback ** is invoked before visiting children.) ** @@ -106994,46 +89827,31 @@ ** 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. */ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3WalkExprNN(Walker *pWalker, Expr *pExpr){ +static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ int rc; testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); - while(1){ - rc = pWalker->xExprCallback(pWalker, pExpr); - if( rc ) return rc & WRC_Abort; - if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ - assert( pExpr->x.pList==0 || pExpr->pRight==0 ); - if( pExpr->pLeft && sqlite3WalkExprNN(pWalker, pExpr->pLeft) ){ - return WRC_Abort; - } - if( pExpr->pRight ){ - assert( !ExprHasProperty(pExpr, EP_WinFunc) ); - pExpr = pExpr->pRight; - continue; - }else if( ExprUseXSelect(pExpr) ){ - assert( !ExprHasProperty(pExpr, EP_WinFunc) ); - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else{ - if( pExpr->x.pList ){ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort; - } -#endif - } - } - break; + 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 ){ + if( walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; + }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; + } } return WRC_Continue; } SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ - return pExpr ? sqlite3WalkExprNN(pWalker,pExpr) : WRC_Continue; + return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; } /* ** Call sqlite3WalkExpr() for every expression in list p or until ** an abort request is seen. @@ -107047,20 +89865,10 @@ } } return WRC_Continue; } -/* -** This is a no-op callback for Walker->xSelectCallback2. If this -** callback is set, then the Select->pWinDefn list is traversed. -*/ -SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker *pWalker, Select *p){ - UNUSED_PARAMETER(pWalker); - UNUSED_PARAMETER(p); - /* No-op */ -} - /* ** Walk all expressions associated with SELECT statement p. Do ** not invoke the SELECT callback on p, but do (of course) invoke ** any expr callbacks and SELECT callbacks that come from subqueries. ** Return WRC_Abort or WRC_Continue. @@ -107070,47 +89878,30 @@ if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort; 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 !defined(SQLITE_OMIT_WINDOWFUNC) - if( p->pWinDefn ){ - Parse *pParse; - if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback - || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT) -#ifndef SQLITE_OMIT_CTE - || pWalker->xSelectCallback2==sqlite3SelectPopWith -#endif - ){ - /* The following may return WRC_Abort if there are unresolvable - ** symbols (e.g. a table that does not exist) in a window definition. */ - int rc = walkWindowList(pWalker, p->pWinDefn, 0); - return rc; - } - } -#endif + if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort; return WRC_Continue; } /* ** Walk the parse trees associated with all subqueries in the ** FROM clause of SELECT statement p. Do not invoke the select ** callback on p, but do invoke it on each FROM clause subquery -** and on any subqueries further down in the tree. Return +** and on any subqueries further down in the tree. Return ** WRC_Abort or WRC_Continue; */ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ SrcList *pSrc; int i; - SrcItem *pItem; + struct SrcList_item *pItem; pSrc = p->pSrc; if( ALWAYS(pSrc) ){ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( pItem->fg.isSubquery - && sqlite3WalkSelect(pWalker, pItem->u4.pSubq->pSelect) - ){ + if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){ return WRC_Abort; } if( pItem->fg.isTabFunc && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) ){ @@ -107117,16 +89908,16 @@ return WRC_Abort; } } } return WRC_Continue; -} +} /* ** Call sqlite3WalkExpr() for every expression in Select statement p. ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and -** on the compound select chain, p->pPrior. +** on the compound select chain, p->pPrior. ** ** If it is not NULL, the xSelectCallback() callback is invoked before ** the walk of the expressions and FROM clause. The xSelectCallback2() ** method is invoked following the walk of the expressions and FROM clause, ** but only if both xSelectCallback and xSelectCallback2 are both non-NULL @@ -107156,47 +89947,10 @@ p = p->pPrior; }while( p!=0 ); return WRC_Continue; } -/* Increase the walkerDepth when entering a subquery, and -** decrease when leaving the subquery. -*/ -SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pSelect); - pWalker->walkerDepth++; - return WRC_Continue; -} -SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pSelect); - pWalker->walkerDepth--; -} - - -/* -** No-op routine for the parse-tree walker. -** -** When this routine is the Walker.xExprCallback then expression trees -** are walked without any actions being taken at each node. Presumably, -** when this routine is used for Walker.xExprCallback then -** Walker.xSelectCallback is set to do something useful for every -** subquery in the parser tree. -*/ -SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return WRC_Continue; -} - -/* -** No-op routine for the parse-tree walker for SELECT statements. -** subquery in the parser tree. -*/ -SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return WRC_Continue; -} - /************** End of walker.c **********************************************/ /************** Begin file resolve.c *****************************************/ /* ** 2008 August 18 ** @@ -107213,25 +89967,18 @@ ** resolve all identifiers by associating them with a particular ** table and column. */ /* #include "sqliteInt.h" */ -/* -** Magic table number to mean the EXCLUDED table in an UPSERT statement. -*/ -#define EXCLUDED_TABLE_NUMBER 2 - /* ** Walk the expression tree pExpr and increase the aggregate function ** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. ** This needs to occur when copying a TK_AGG_FUNCTION node from an ** outer query into an inner subquery. ** ** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..) ** is a helper function - a callback for the tree walker. -** -** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c */ static int incrAggDepth(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n; return WRC_Continue; } @@ -107267,77 +90014,78 @@ static void resolveAlias( Parse *pParse, /* Parsing context */ ExprList *pEList, /* A result set */ int iCol, /* A column in the result set. 0..pEList->nExpr-1 */ Expr *pExpr, /* Transform this into an alias to the result set */ + const char *zType, /* "GROUP" or "ORDER" or "" */ int nSubquery /* Number of subqueries that the label is moving */ ){ Expr *pOrig; /* The iCol-th column of the result set */ Expr *pDup; /* Copy of pOrig */ sqlite3 *db; /* The database connection */ assert( iCol>=0 && iColnExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); - assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) ); - if( pExpr->pAggInfo ) return; db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - pDup = 0; - }else{ - Expr temp; - incrAggFunctionDepth(pDup, nSubquery); - if( pExpr->op==TK_COLLATE ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); - } - memcpy(&temp, pDup, sizeof(Expr)); - memcpy(pDup, pExpr, sizeof(Expr)); - memcpy(pExpr, &temp, sizeof(Expr)); - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - if( ALWAYS(pExpr->y.pWin!=0) ){ - pExpr->y.pWin->pOwner = pExpr; - } - } - sqlite3ExprDeferredDelete(pParse, pDup); - } + if( pDup==0 ) return; + if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); + if( pExpr->op==TK_COLLATE ){ + pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); + } + ExprSetProperty(pDup, EP_Alias); + + /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This + ** prevents ExprDelete() from deleting the Expr structure itself, + ** allowing it to be repopulated by the memcpy() on the following line. + ** The pExpr->u.zToken might point into memory that will be freed by the + ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to + ** make a copy of the token before doing the sqlite3DbFree(). + */ + ExprSetProperty(pExpr, EP_Static); + sqlite3ExprDelete(db, pExpr); + memcpy(pExpr, pDup, sizeof(*pExpr)); + if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ + assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); + pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); + pExpr->flags |= EP_MemToken; + } + sqlite3DbFree(db, pDup); +} + + +/* +** Return TRUE if the name zCol occurs anywhere in the USING clause. +** +** Return FALSE if the USING clause is NULL or if it does not contain +** zCol. +*/ +static int nameInUsingClause(IdList *pUsing, const char *zCol){ + if( pUsing ){ + int k; + for(k=0; knId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; + } + } + return 0; } /* -** Subqueries store the original database, table and column names for their -** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN", -** and mark the expression-list item by setting ExprList.a[].fg.eEName -** to ENAME_TAB. -** -** Check to see if the zSpan/eEName of the expression-list item passed to this -** routine matches the zDb, zTab, and zCol. If any of zDb, zTab, and zCol are -** NULL then those fields will match anything. Return true if there is a match, -** or false otherwise. -** -** SF_NestedFrom subqueries also store an entry for the implicit rowid (or -** _rowid_, or oid) column by setting ExprList.a[].fg.eEName to ENAME_ROWID, -** and setting zSpan to "DATABASE.TABLE.". This type of pItem -** argument matches if zCol is a rowid alias. If it is not NULL, (*pbRowid) -** is set to 1 if there is this kind of match. +** Subqueries stores the original database, table and column names for their +** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". +** Check to see if the zSpan given to this routine matches the zDb, zTab, +** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will +** match anything. */ -SQLITE_PRIVATE int sqlite3MatchEName( - const struct ExprList_item *pItem, +SQLITE_PRIVATE int sqlite3MatchSpanName( + const char *zSpan, const char *zCol, const char *zTab, - const char *zDb, - int *pbRowid + const char *zDb ){ int n; - const char *zSpan; - int eEName = pItem->fg.eEName; - if( eEName!=ENAME_TAB && (eEName!=ENAME_ROWID || NEVER(pbRowid==0)) ){ - return 0; - } - assert( pbRowid==0 || *pbRowid==0 ); - zSpan = pItem->zEName; for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ return 0; } zSpan += n+1; @@ -107344,122 +90092,27 @@ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){ return 0; } zSpan += n+1; - if( zCol ){ - if( eEName==ENAME_TAB && sqlite3StrICmp(zSpan, zCol)!=0 ) return 0; - if( eEName==ENAME_ROWID && sqlite3IsRowid(zCol)==0 ) return 0; - } - if( eEName==ENAME_ROWID ) *pbRowid = 1; - return 1; -} - -/* -** Return TRUE if the double-quoted string mis-feature should be supported. -*/ -static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){ - if( db->init.busy ) return 1; /* Always support for legacy schemas */ - if( pTopNC->ncFlags & NC_IsDDL ){ - /* Currently parsing a DDL statement */ - if( sqlite3WritableSchema(db) && (db->flags & SQLITE_DqsDML)!=0 ){ - return 1; - } - return (db->flags & SQLITE_DqsDDL)!=0; - }else{ - /* Currently parsing a DML statement */ - return (db->flags & SQLITE_DqsDML)!=0; - } -} - -/* -** The argument is guaranteed to be a non-NULL Expr node of type TK_COLUMN. -** return the appropriate colUsed mask. -*/ -SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){ - int n; - Table *pExTab; - - n = pExpr->iColumn; - assert( ExprUseYTab(pExpr) ); - pExTab = pExpr->y.pTab; - assert( pExTab!=0 ); - assert( n < pExTab->nCol ); - if( (pExTab->tabFlags & TF_HasGenerated)!=0 - && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 - ){ - testcase( pExTab->nCol==BMS-1 ); - testcase( pExTab->nCol==BMS ); - return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1; - }else{ - testcase( n==BMS-1 ); - testcase( n==BMS ); - if( n>=BMS ) n = BMS-1; - return ((Bitmask)1)<db, TK_COLUMN, 0, 0); - if( pNew ){ - pNew->iTable = pMatch->iCursor; - pNew->iColumn = iColumn; - pNew->y.pTab = pMatch->pSTab; - assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ); - ExprSetProperty(pNew, EP_CanBeNull); - *ppList = sqlite3ExprListAppend(pParse, *ppList, pNew); - } -} - -/* -** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab. -*/ -static SQLITE_NOINLINE int isValidSchemaTableName( - const char *zTab, /* Name as it appears in the SQL */ - Table *pTab, /* The schema table we are trying to match */ - const char *zDb /* non-NULL if a database qualifier is present */ -){ - const char *zLegacy; - assert( pTab!=0 ); - assert( pTab->tnum==1 ); - if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0; - zLegacy = pTab->zName; - if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){ - if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){ - return 1; - } - if( zDb==0 ) return 0; - if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1; - if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1; - }else{ - if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1; - } - return 0; + if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ + return 0; + } + return 1; } /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up -** that name in the set of source tables in pSrcList and make the pExpr +** that name in the set of source tables in pSrcList and make the pExpr ** expression node refer back to that source column. The following changes ** are made to pExpr: ** ** pExpr->iDb Set the index in db->aDb[] of the database X ** (even if X is implied). ** pExpr->iTable Set to the cursor number for the table obtained ** from pSrcList. -** pExpr->y.pTab Points to the Table structure of X.Y (even if +** pExpr->pTab Points to the Table structure of X.Y (even if ** X and/or Y are implied.) ** pExpr->iColumn Set to the column number within the table. ** pExpr->op Set to TK_COLUMN. ** pExpr->pLeft Any expression this points to is deleted ** pExpr->pRight Any expression this points to is deleted. @@ -107476,36 +90129,34 @@ */ static int lookupName( Parse *pParse, /* The parsing context */ const char *zDb, /* Name of the database containing table, or NULL */ const char *zTab, /* Name of table containing column, or NULL */ - const Expr *pRight, /* Name of the column. */ + const char *zCol, /* Name of the column. */ NameContext *pNC, /* The name context used to resolve the name */ Expr *pExpr /* Make this EXPR node point to the selected column */ ){ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ - int cntTab = 0; /* Number of potential "rowid" matches */ + int cntTab = 0; /* Number of matching table names */ int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ - SrcItem *pItem; /* Use for looping over pSrcList items */ - SrcItem *pMatch = 0; /* The matching pSrcList item */ + struct SrcList_item *pItem; /* Use for looping over pSrcList items */ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ - int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ - Table *pTab = 0; /* Table holding the row */ + int isTrigger = 0; /* True if resolved to a trigger column */ + Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ - ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */ - const char *zCol = pRight->u.zToken; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ - assert( zDb==0 || zTab!=0 ); assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; + pExpr->pTab = 0; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Translate the schema name in zDb into a pointer to the corresponding ** schema. If not found, pSchema will remain NULL and nothing will match ** resulting in an appropriate error message toward the end of this routine @@ -107525,16 +90176,10 @@ if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } } - if( i==db->nDb && sqlite3StrICmp("main", zDb)==0 ){ - /* This branch is taken when the main database has been renamed - ** using SQLITE_DBCONFIG_MAINDBNAME. */ - pSchema = db->aDb[0].pSchema; - zDb = db->aDb[0].zDbSName; - } } } /* Start at the inner-most context and move outward until a match is found */ assert( pNC && cnt==0 ); @@ -107542,231 +90187,93 @@ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ - u8 hCol; - pTab = pItem->pSTab; + pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); - assert( pTab->nCol>0 || pParse->nErr ); - assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem)); - if( pItem->fg.isNestedFrom ){ - /* In this case, pItem is a subquery that has been formed from a - ** parenthesized subset of the FROM clause terms. Example: - ** .... FROM t1 LEFT JOIN (t2 RIGHT JOIN t3 USING(x)) USING(y) ... - ** \_________________________/ - ** This pItem -------------^ - */ + assert( pTab->nCol>0 ); + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; - Select *pSel; - assert( pItem->fg.isSubquery ); - assert( pItem->u4.pSubq!=0 ); - pSel = pItem->u4.pSubq->pSelect; - assert( pSel!=0 ); - pEList = pSel->pEList; - assert( pEList!=0 ); - assert( pEList->nExpr==pTab->nCol ); + pEList = pItem->pSelect->pEList; for(j=0; jnExpr; j++){ - int bRowid = 0; /* True if possible rowid match */ - if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, &bRowid) ){ - continue; - } - if( bRowid==0 ){ - if( cnt>0 ){ - if( pItem->fg.isUsing==0 - || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 - ){ - /* Two or more tables have the same column name which is - ** not joined by USING. This is an error. Signal as much - ** by clearing pFJMatch and letting cnt go above 1. */ - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else - if( (pItem->fg.jointype & JT_RIGHT)==0 ){ - /* An INNER or LEFT JOIN. Use the left-most table */ - continue; - }else - if( (pItem->fg.jointype & JT_LEFT)==0 ){ - /* A RIGHT JOIN. Use the right-most table */ - cnt = 0; - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else{ - /* For a FULL JOIN, we must construct a coalesce() func */ - extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); - } - } + if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ cnt++; + cntTab = 2; + pMatch = pItem; + pExpr->iColumn = j; hit = 1; - }else if( cnt>0 ){ - /* This is a potential rowid match, but there has already been - ** a real match found. So this can be ignored. */ - continue; - } - cntTab++; - pMatch = pItem; - pExpr->iColumn = j; - pEList->a[j].fg.bUsed = 1; - - /* rowid cannot be part of a USING clause - assert() this. */ - assert( bRowid==0 || pEList->a[j].fg.bUsingTerm==0 ); - if( pEList->a[j].fg.bUsingTerm ) break; + } } if( hit || zTab==0 ) continue; } - assert( zDb==0 || zTab!=0 ); + if( zDb && pTab->pSchema!=pSchema ){ + continue; + } if( zTab ){ - if( zDb ){ - if( pTab->pSchema!=pSchema ) continue; - if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue; - } - if( pItem->zAlias!=0 ){ - if( sqlite3StrICmp(zTab, pItem->zAlias)!=0 ){ - continue; - } - }else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){ - if( pTab->tnum!=1 ) continue; - if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue; - } - assert( ExprUseYTab(pExpr) ); - if( IN_RENAME_OBJECT && pItem->zAlias ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); - } - } - hCol = sqlite3StrIHash(zCol); + const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; + assert( zTabName!=0 ); + if( sqlite3StrICmp(zTabName, zTab)!=0 ){ + continue; + } + } + if( 0==(cntTab++) ){ + pMatch = pItem; + } for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ - if( pCol->hName==hCol - && sqlite3StrICmp(pCol->zCnName, zCol)==0 - ){ - if( cnt>0 ){ - if( pItem->fg.isUsing==0 - || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 - ){ - /* Two or more tables have the same column name which is - ** not joined by USING. This is an error. Signal as much - ** by clearing pFJMatch and letting cnt go above 1. */ - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else - if( (pItem->fg.jointype & JT_RIGHT)==0 ){ - /* An INNER or LEFT JOIN. Use the left-most table */ - continue; - }else - if( (pItem->fg.jointype & JT_LEFT)==0 ){ - /* A RIGHT JOIN. Use the right-most table */ - cnt = 0; - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - }else{ - /* For a FULL JOIN, we must construct a coalesce() func */ - extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); - } + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + /* If there has been exactly one prior match and this match + ** is for the right-hand table of a NATURAL JOIN or is in a + ** USING clause, then skip this match. + */ + if( cnt==1 ){ + if( pItem->fg.jointype & JT_NATURAL ) continue; + if( nameInUsingClause(pItem->pUsing, zCol) ) continue; } cnt++; pMatch = pItem; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; - if( pItem->fg.isNestedFrom ){ - sqlite3SrcItemColumnUsed(pItem, j); - } break; } - } - if( 0==cnt && VisibleRowid(pTab) ){ - /* pTab is a potential ROWID match. Keep track of it and match - ** the ROWID later if that seems appropriate. (Search for "cntTab" - ** to find related code.) Only allow a ROWID match if there is - ** a single ROWID match candidate. - */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - /* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match - ** if there is a single VIEW candidate or if there is a single - ** non-VIEW candidate plus multiple VIEW candidates. In other - ** words non-VIEW candidate terms take precedence over VIEWs. - */ - if( cntTab==0 - || (cntTab==1 - && pMatch!=0 - && ALWAYS(pMatch->pSTab!=0) - && (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0 - && (pTab->tabFlags & TF_Ephemeral)==0) - ){ - cntTab = 1; - pMatch = pItem; - }else{ - cntTab++; - } -#else - /* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is - ** simpler since we require exactly one candidate, which will - ** always be a non-VIEW - */ - cntTab++; - pMatch = pItem; -#endif } } if( pMatch ){ pExpr->iTable = pMatch->iCursor; - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pMatch->pSTab; - if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){ + pExpr->pTab = pMatch->pTab; + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); + if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } - pSchema = pExpr->y.pTab->pSchema; + pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ -#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) - /* If we have not already resolved the name, then maybe - ** it is a new.* or old.* trigger argument reference. Or - ** maybe it is an excluded.* from an upsert. Or maybe it is - ** a reference in the RETURNING clause to a table being modified. - */ - if( cnt==0 && zDb==0 ){ - pTab = 0; #ifndef SQLITE_OMIT_TRIGGER - if( pParse->pTriggerTab!=0 ){ - int op = pParse->eTriggerOp; - assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); - if( pParse->bReturning ){ - if( (pNC->ncFlags & NC_UBaseReg)!=0 - && ALWAYS(zTab==0 - || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0 - || isValidSchemaTableName(zTab, pParse->pTriggerTab, 0)) - ){ - pExpr->iTable = op!=TK_DELETE; - pTab = pParse->pTriggerTab; - } - }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){ - pExpr->iTable = 1; - pTab = pParse->pTriggerTab; - }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){ - pExpr->iTable = 0; - pTab = pParse->pTriggerTab; - } - } -#endif /* SQLITE_OMIT_TRIGGER */ -#ifndef SQLITE_OMIT_UPSERT - if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){ - Upsert *pUpsert = pNC->uNC.pUpsert; - if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){ - pTab = pUpsert->pUpsertSrc->a[0].pSTab; - pExpr->iTable = EXCLUDED_TABLE_NUMBER; - } - } -#endif /* SQLITE_OMIT_UPSERT */ - - if( pTab ){ - int iCol; - u8 hCol = sqlite3StrIHash(zCol); + /* If we have not already resolved the name, then maybe + ** it is a new.* or old.* trigger argument reference + */ + if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){ + int op = pParse->eTriggerOp; + assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); + if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ + pExpr->iTable = 1; + pTab = pParse->pTriggerTab; + }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ + pExpr->iTable = 0; + pTab = pParse->pTriggerTab; + }else{ + pTab = 0; + } + + if( pTab ){ + int iCol; pSchema = pTab->pSchema; cntTab++; for(iCol=0, pCol=pTab->aCol; iColnCol; iCol++, pCol++){ - if( pCol->hName==hCol - && sqlite3StrICmp(pCol->zCnName, zCol)==0 - ){ + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ if( iCol==pTab->iPKey ){ iCol = -1; } break; } @@ -107775,76 +90282,42 @@ /* IMP: R-51414-32910 */ iCol = -1; } if( iColnCol ){ cnt++; - pMatch = 0; -#ifndef SQLITE_OMIT_UPSERT - if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){ - testcase( iCol==(-1) ); - assert( ExprUseYTab(pExpr) ); - if( IN_RENAME_OBJECT ){ - pExpr->iColumn = iCol; - pExpr->y.pTab = pTab; - eNewExprOp = TK_COLUMN; - }else{ - pExpr->iTable = pNC->uNC.pUpsert->regData + - sqlite3TableColumnToStorage(pTab, iCol); - eNewExprOp = TK_REGISTER; - } - }else -#endif /* SQLITE_OMIT_UPSERT */ - { - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pTab; - if( pParse->bReturning ){ - eNewExprOp = TK_REGISTER; - pExpr->op2 = TK_COLUMN; - pExpr->iColumn = iCol; - pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable + - sqlite3TableColumnToStorage(pTab, iCol) + 1; - }else{ - pExpr->iColumn = (i16)iCol; - eNewExprOp = TK_TRIGGER; -#ifndef SQLITE_OMIT_TRIGGER - if( iCol<0 ){ - pExpr->affExpr = SQLITE_AFF_INTEGER; - }else if( pExpr->iTable==0 ){ - testcase( iCol==31 ); - testcase( iCol==32 ); - pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<affinity = SQLITE_AFF_INTEGER; + }else if( pExpr->iTable==0 ){ + testcase( iCol==31 ); + testcase( iCol==32 ); + pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<iColumn = (i16)iCol; + pExpr->pTab = pTab; + isTrigger = 1; + } + } + } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 - && cntTab>=1 + && cntTab==1 && pMatch - && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 + && (pNC->ncFlags & NC_IdxExpr)==0 && sqlite3IsRowid(zCol) - && ALWAYS(VisibleRowid(pMatch->pSTab) || pMatch->fg.isNestedFrom) + && VisibleRowid(pMatch->pTab) ){ - cnt = cntTab; -#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2 - if( pMatch->pSTab!=0 && IsView(pMatch->pSTab) ){ - eNewExprOp = TK_NULL; - } -#endif - if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; - pExpr->affExpr = SQLITE_AFF_INTEGER; + cnt = 1; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; } /* ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z ** might refer to an result-set alias. This happens, for example, when @@ -107861,50 +90334,37 @@ ** or HAVING clauses, or as part of a larger expression in the ORDER BY ** clause is not standard SQL. This is a (goofy) SQLite extension, that ** is supported for backwards compatibility only. Hence, we issue a warning ** on sqlite3_log() whenever the capability is used. */ - if( cnt==0 - && (pNC->ncFlags & NC_UEList)!=0 + if( (pEList = pNC->pEList)!=0 && zTab==0 + && cnt==0 ){ - pEList = pNC->uNC.pEList; - assert( pEList!=0 ); for(j=0; jnExpr; j++){ - char *zAs = pEList->a[j].zEName; - if( pEList->a[j].fg.eEName==ENAME_NAME - && sqlite3_stricmp(zAs, zCol)==0 - ){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ Expr *pOrig; assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 ); - assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 ); + assert( pExpr->x.pList==0 ); + assert( pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } - if( ExprHasProperty(pOrig, EP_Win) - && ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC ) - ){ - sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs); - return WRC_Abort; - } if( sqlite3ExprVectorSize(pOrig)!=1 ){ sqlite3ErrorMsg(pParse, "row value misused"); return WRC_Abort; } - resolveAlias(pParse, pEList, j, pExpr, nSubquery); + resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); - } goto lookupname_end; } - } + } } /* 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. */ @@ -107922,136 +90382,64 @@ ** pExpr. ** ** Because no reference was made to outer contexts, the pNC->nRef ** fields are not changed in any context. */ - if( cnt==0 && zTab==0 ){ - assert( pExpr->op==TK_ID ); - if( ExprHasProperty(pExpr,EP_DblQuoted) - && areDoubleQuotedStringsEnabled(db, pTopNC) - ){ - /* If a double-quoted identifier does not match any known column name, - ** then treat it as a string. - ** - ** This hack was added in the early days of SQLite in a misguided attempt - ** to be compatible with MySQL 3.x, which used double-quotes for strings. - ** I now sorely regret putting in this hack. The effect of this hack is - ** that misspelled identifier names are silently converted into strings - ** rather than causing an error, to the frustration of countless - ** programmers. To all those frustrated programmers, my apologies. - ** - ** Someday, I hope to get rid of this hack. Unfortunately there is - ** a huge amount of legacy SQL that uses it. So for now, we just - ** issue a warning. - */ - sqlite3_log(SQLITE_WARNING, - "double-quoted string literal: \"%w\"", zCol); -#ifdef SQLITE_ENABLE_NORMALIZE - sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol); -#endif - pExpr->op = TK_STRING; - memset(&pExpr->y, 0, sizeof(pExpr->y)); - return WRC_Prune; - } - if( sqlite3ExprIdToTrueFalse(pExpr) ){ - return WRC_Prune; - } + if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ + pExpr->op = TK_STRING; + pExpr->pTab = 0; + return WRC_Prune; } /* - ** cnt==0 means there was not match. - ** cnt>1 means there were two or more matches. - ** - ** cnt==0 is always an error. cnt>1 is often an error, but might - ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING. + ** cnt==0 means there was not match. cnt>1 means there were two or + ** more matches. Either way, we have an error. */ - assert( pFJMatch==0 || cnt>0 ); - assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); if( cnt!=1 ){ const char *zErr; - if( pFJMatch ){ - if( pFJMatch->nExpr==cnt-1 ){ - if( ExprHasProperty(pExpr,EP_Leaf) ){ - ExprClearProperty(pExpr,EP_Leaf); - }else{ - sqlite3ExprDelete(db, pExpr->pLeft); - pExpr->pLeft = 0; - sqlite3ExprDelete(db, pExpr->pRight); - pExpr->pRight = 0; - } - extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); - pExpr->op = TK_FUNCTION; - pExpr->u.zToken = "coalesce"; - pExpr->x.pList = pFJMatch; - cnt = 1; - goto lookupname_end; - }else{ - sqlite3ExprListDelete(db, pFJMatch); - pFJMatch = 0; - } - } zErr = cnt==0 ? "no such column" : "ambiguous column name"; if( zDb ){ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); }else if( zTab ){ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); - }else if( cnt==0 && ExprHasProperty(pRight,EP_DblQuoted) ){ - sqlite3ErrorMsg(pParse, "%s: \"%s\" - should this be a" - " string literal in single-quotes?", - zErr, zCol); }else{ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); pParse->checkSchema = 1; - pTopNC->nNcErr++; - eNewExprOp = TK_NULL; - } - assert( pFJMatch==0 ); - - /* Remove all substructure from pExpr */ - if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ - sqlite3ExprDelete(db, pExpr->pLeft); - pExpr->pLeft = 0; - sqlite3ExprDelete(db, pExpr->pRight); - pExpr->pRight = 0; - ExprSetProperty(pExpr, EP_Leaf); + pTopNC->nErr++; } /* If a column from a table in pSrcList is referenced, then record ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes - ** bit 0 to be set. Column 1 sets bit 1. And so forth. Bit 63 is - ** set if the 63rd or any subsequent column is used. - ** - ** The colUsed mask is an optimization used to help determine if an - ** index is a covering index. The correct answer is still obtained - ** if the mask contains extra set bits. However, it is important to - ** avoid setting bits beyond the maximum column number of the table. - ** (See ticket [b92e5e8ec2cdbaa1]). - ** - ** If a generated column is referenced, set bits for every column - ** of the table. - */ - if( pMatch ){ - if( pExpr->iColumn>=0 ){ - pMatch->colUsed |= sqlite3ExprColUsed(pExpr); - }else{ - pMatch->fg.rowidUsed = 1; - } - } - - pExpr->op = eNewExprOp; + ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the + ** column number is greater than the number of bits in the bitmask + ** then set the high-order bit of the bitmask. + */ + if( pExpr->iColumn>=0 && pMatch!=0 ){ + int n = pExpr->iColumn; + testcase( n==BMS-1 ); + if( n>=BMS ){ + n = BMS-1; + } + assert( pMatch->iCursor==pExpr->iTable ); + pMatch->colUsed |= ((Bitmask)1)<pLeft); + pExpr->pLeft = 0; + 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 ); -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pParse->db->xAuth - && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) - ){ + if( !ExprHasProperty(pExpr, EP_Alias) ){ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); } -#endif /* Increment the nRef value on all name contexts from TopNC up to ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; @@ -108069,83 +90457,54 @@ ** from datasource iSrc in SrcList pSrc. */ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); if( p ){ - SrcItem *pItem = &pSrc->a[iSrc]; - Table *pTab; - assert( ExprUseYTab(p) ); - pTab = p->y.pTab = pItem->pSTab; + struct SrcList_item *pItem = &pSrc->a[iSrc]; + p->pTab = pItem->pTab; p->iTable = pItem->iCursor; - if( p->y.pTab->iPKey==iCol ){ + if( p->pTab->iPKey==iCol ){ p->iColumn = -1; }else{ p->iColumn = (ynVar)iCol; - if( (pTab->tabFlags & TF_HasGenerated)!=0 - && (pTab->aCol[iCol].colFlags & COLFLAG_GENERATED)!=0 - ){ - testcase( pTab->nCol==63 ); - testcase( pTab->nCol==64 ); - pItem->colUsed = pTab->nCol>=64 ? ALLBITS : MASKBIT(pTab->nCol)-1; - }else{ - testcase( iCol==BMS ); - testcase( iCol==BMS-1 ); - pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); - } + testcase( iCol==BMS ); + testcase( iCol==BMS-1 ); + pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); } } return p; } /* ** Report an error that an expression is not valid for some set of ** pNC->ncFlags values determined by validMask. -** -** static void notValid( -** Parse *pParse, // Leave error message here -** NameContext *pNC, // The name context -** const char *zMsg, // Type of error -** int validMask, // Set of contexts for which prohibited -** Expr *pExpr // Invalidate this expression on error -** ){...} -** -** As an optimization, since the conditional is almost always false -** (because errors are rare), the conditional is moved outside of the -** function call using a macro. */ -static void notValidImpl( - Parse *pParse, /* Leave error message here */ - NameContext *pNC, /* The name context */ - const char *zMsg, /* Type of error */ - Expr *pExpr, /* Invalidate this expression on error */ - Expr *pError /* Associate error with this expression */ +static void notValid( + Parse *pParse, /* Leave error message here */ + NameContext *pNC, /* The name context */ + const char *zMsg, /* Type of error */ + int validMask /* Set of contexts for which prohibited */ ){ - const char *zIn = "partial index WHERE clauses"; - if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions"; + assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 ); + if( (pNC->ncFlags & validMask)!=0 ){ + const char *zIn = "partial index WHERE clauses"; + if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions"; #ifndef SQLITE_OMIT_CHECK - else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints"; -#endif -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns"; -#endif - sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn); - if( pExpr ) pExpr->op = TK_NULL; - sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); -} -#define sqlite3ResolveNotValid(P,N,M,X,E,R) \ - assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \ - if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R); + else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints"; +#endif + sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn); + } +} /* ** Expression p should encode a floating point value between 1.0 and 0.0. ** Return 1024 times this value. Or return -1 if p is not a floating point ** value between 1.0 and 0.0. */ static int exprProbability(Expr *p){ double r = -1.0; if( p->op!=TK_FLOAT ) return -1; - assert( !ExprHasProperty(p, EP_IntValue) ); sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); assert( r>=0.0 ); if( r>1.0 ) return -1; return (int)(r*134217728.0); } @@ -108179,164 +90538,82 @@ } } #endif switch( pExpr->op ){ +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) /* The special operator TK_ROW means use the rowid for the first ** column in the FROM clause. This is used by the LIMIT and ORDER BY - ** clause processing on UPDATE and DELETE statements, and by - ** UPDATE ... FROM statement processing. + ** clause processing on UPDATE and DELETE statements. */ case TK_ROW: { SrcList *pSrcList = pNC->pSrcList; - SrcItem *pItem; - assert( pSrcList && pSrcList->nSrc>=1 ); - pItem = pSrcList->a; + struct SrcList_item *pItem; + assert( pSrcList && pSrcList->nSrc==1 ); + pItem = pSrcList->a; pExpr->op = TK_COLUMN; - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pItem->pSTab; + pExpr->pTab = pItem->pTab; pExpr->iTable = pItem->iCursor; - pExpr->iColumn--; - pExpr->affExpr = SQLITE_AFF_INTEGER; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; break; } - - /* An optimization: Attempt to convert - ** - ** "expr IS NOT NULL" --> "TRUE" - ** "expr IS NULL" --> "FALSE" - ** - ** if we can prove that "expr" is never NULL. Call this the - ** "NOT NULL strength reduction optimization". - ** - ** If this optimization occurs, also restore the NameContext ref-counts - ** to the state they where in before the "column" LHS expression was - ** resolved. This prevents "column" from being counted as having been - ** referenced, which might prevent a SELECT from being erroneously - ** marked as correlated. - ** - ** 2024-03-28: Beware of aggregates. A bare column of aggregated table - ** can still evaluate to NULL even though it is marked as NOT NULL. - ** Example: - ** - ** CREATE TABLE t1(a INT NOT NULL); - ** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1; - ** - ** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized - ** here because at the time this case is hit, we do not yet know whether - ** or not t1 is being aggregated. We have to assume the worst and omit - ** the optimization. The only time it is safe to apply this optimization - ** is within the WHERE clause. - */ - case TK_NOTNULL: - case TK_ISNULL: { - int anRef[8]; - NameContext *p; - int i; - for(i=0, p=pNC; p && ipNext, i++){ - anRef[i] = p->nRef; - } - sqlite3WalkExpr(pWalker, pExpr->pLeft); - if( IN_RENAME_OBJECT ) return WRC_Prune; - if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ - /* The expression can be NULL. So the optimization does not apply */ - return WRC_Prune; - } - - for(i=0, p=pNC; p; p=p->pNext, i++){ - if( (p->ncFlags & NC_Where)==0 ){ - return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */ - } - } - testcase( ExprHasProperty(pExpr, EP_OuterON) ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x80000 ){ - sqlite3DebugPrintf( - "NOT NULL strength reduction converts the following to %d:\n", - pExpr->op==TK_NOTNULL - ); - sqlite3ShowExpr(pExpr); - } -#endif /* TREETRACE_ENABLED */ - pExpr->u.iValue = (pExpr->op==TK_NOTNULL); - pExpr->flags |= EP_IntValue; - pExpr->op = TK_INTEGER; - for(i=0, p=pNC; p && ipNext, i++){ - p->nRef = anRef[i]; - } - sqlite3ExprDelete(pParse->db, pExpr->pLeft); - pExpr->pLeft = 0; - return WRC_Prune; - } +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + && !defined(SQLITE_OMIT_SUBQUERY) */ /* 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 + ** 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( pExpr->op==TK_ID ){ zDb = 0; zTable = 0; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pRight = pExpr; + zColumn = pExpr->u.zToken; }else{ - Expr *pLeft = pExpr->pLeft; - testcase( pNC->ncFlags & NC_IdxExpr ); - testcase( pNC->ncFlags & NC_GenCol ); - sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator", - NC_IdxExpr|NC_GenCol, 0, pExpr); + 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 ); - assert( !ExprHasProperty(pRight, EP_IntValue) ); - zDb = pLeft->u.zToken; - pLeft = pRight->pLeft; - pRight = pRight->pRight; - } - assert( ExprUseUToken(pLeft) && ExprUseUToken(pRight) ); - zTable = pLeft->u.zToken; - assert( ExprUseYTab(pExpr) ); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); - sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); + zDb = pExpr->pLeft->u.zToken; + zTable = pRight->pLeft->u.zToken; + zColumn = pRight->pRight->u.zToken; } } - return lookupName(pParse, zDb, zTable, pRight, pNC, pExpr); + return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); } /* Resolve function names */ case TK_FUNCTION: { - ExprList *pList; /* The argument list */ - int n; /* Number of arguments */ + ExprList *pList = pExpr->x.pList; /* The argument list */ + int n = pList ? pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ + int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ - int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin)); -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0); -#endif - assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); - assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER ); - pList = pExpr->x.pList; - n = pList ? pList->nExpr : 0; + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); zId = pExpr->u.zToken; + nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); if( pDef==0 ){ no_such_func = 1; @@ -108344,18 +90621,18 @@ wrong_num_args = 1; } }else{ is_agg = pDef->xFinalize!=0; if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ - ExprSetProperty(pExpr, EP_Unlikely); + ExprSetProperty(pExpr, EP_Unlikely|EP_Skip); if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ sqlite3ErrorMsg(pParse, - "second argument to %#T() must be a " - "constant between 0.0 and 1.0", pExpr); - pNC->nNcErr++; + "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); + pNC->nErr++; } }else{ /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is ** equivalent to likelihood(X, 0.0625). ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is @@ -108364,278 +90641,116 @@ ** for likelihood(X,0.9375). ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent ** to likelihood(X,0.9375). */ /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; - } + } } #ifndef SQLITE_OMIT_AUTHORIZATION { int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0); if( auth!=SQLITE_OK ){ if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %#T", - pExpr); - pNC->nNcErr++; + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; } pExpr->op = TK_NULL; return WRC_Prune; } } #endif - - /* If the function may call sqlite3_value_subtype(), then set the - ** EP_SubtArg flag on all of its argument expressions. This prevents - ** where.c from replacing the expression with a value read from an - ** index on the same expression, which will not have the correct - ** subtype. Also set the flag if the function expression itself is - ** an EP_SubtArg expression. In this case subtypes are required as - ** the function may return a value with a subtype back to its - ** caller using sqlite3_result_value(). */ - if( (pDef->funcFlags & SQLITE_SUBTYPE) - || ExprHasProperty(pExpr, EP_SubtArg) - ){ - int ii; - for(ii=0; iia[ii].pExpr, EP_SubtArg); - } - } - if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){ /* For the purposes of the EP_ConstFunc flag, date and time ** functions and other functions that change slowly are considered - ** constant because they are constant for the duration of one query. - ** This allows them to be factored out of inner loops. */ + ** constant because they are constant for the duration of one query */ ExprSetProperty(pExpr,EP_ConstFunc); } if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ - /* Clearly non-deterministic functions like random(), but also - ** date/time functions that use 'now', and other functions like + /* Date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used - ** in an index or generated column. Curiously, they can be used - ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all - ** all this. */ - sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions", - NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr); - }else{ - assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */ - pExpr->op2 = pNC->ncFlags & NC_SelfRef; - if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL); - } - if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 - && pParse->nested==0 - && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0 - ){ - /* Internal-use-only functions are disallowed unless the - ** SQL is being compiled using sqlite3NestedParse() or - ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be - ** used to activate internal functions for testing purposes */ - no_such_func = 1; - pDef = 0; - }else - if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 - && !IN_RENAME_OBJECT - ){ - sqlite3ExprFunctionUsable(pParse, pExpr, pDef); - } - } - - if( 0==IN_RENAME_OBJECT ){ -#ifndef SQLITE_OMIT_WINDOWFUNC - assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX) - || (pDef->xValue==0 && pDef->xInverse==0) - || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) - ); - if( pDef && pDef->xValue==0 && pWin ){ - sqlite3ErrorMsg(pParse, - "%#T() may not be used as a window function", pExpr - ); - pNC->nNcErr++; - }else if( - (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) - || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin) - || (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0) - ){ - const char *zType; - if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){ - zType = "window"; - }else{ - zType = "aggregate"; - } - sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr); - pNC->nNcErr++; - is_agg = 0; - } -#else - if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ - sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr); - pNC->nNcErr++; - is_agg = 0; - } -#endif - else if( no_such_func && pParse->db->init.busy==0 + ** in an index. */ + notValid(pParse, pNC, "non-deterministic functions", + NC_IdxExpr|NC_PartIdx); + } + } + if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); + pNC->nErr++; + is_agg = 0; + }else if( no_such_func && pParse->db->init.busy==0 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - && pParse->explain==0 -#endif - ){ - sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr); - pNC->nNcErr++; - }else if( wrong_num_args ){ - sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()", - pExpr); - pNC->nNcErr++; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3ErrorMsg(pParse, - "FILTER may not be used with non-aggregate %#T()", - pExpr - ); - pNC->nNcErr++; - } -#endif - else if( is_agg==0 && pExpr->pLeft ){ - sqlite3ExprOrderByAggregateError(pParse, pExpr); - pNC->nNcErr++; - } - if( is_agg ){ - /* Window functions may not be arguments of aggregate functions. - ** Or arguments of other window functions. But aggregate functions - ** may be arguments for window functions. */ -#ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0)); -#else - pNC->ncFlags &= ~NC_AllowAgg; -#endif - } - } - else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){ - is_agg = 1; - } + && pParse->explain==0 +#endif + ){ + sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + pNC->nErr++; + }else if( wrong_num_args ){ + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", + nId, zId); + pNC->nErr++; + } + if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg; sqlite3WalkExprList(pWalker, pList); if( is_agg ){ - if( pExpr->pLeft ){ - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin && pParse->nErr==0 ){ - Select *pSel = pNC->pWinSelect; - assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin ); - if( IN_RENAME_OBJECT==0 ){ - sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef); - if( pParse->db->mallocFailed ) break; - } - sqlite3WalkExprList(pWalker, pWin->pPartition); - sqlite3WalkExprList(pWalker, pWin->pOrderBy); - sqlite3WalkExpr(pWalker, pWin->pFilter); - sqlite3WindowLink(pSel, pWin); - pNC->ncFlags |= NC_HasWin; - }else -#endif /* SQLITE_OMIT_WINDOWFUNC */ - { - NameContext *pNC2; /* For looping up thru outer contexts */ - pExpr->op = TK_AGG_FUNCTION; - pExpr->op2 = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); - } -#endif - pNC2 = pNC; - while( pNC2 - && sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0 - ){ - pExpr->op2 += (1 + pNC2->nNestedSelect); - pNC2 = pNC2->pNext; - } - assert( pDef!=0 || IN_RENAME_OBJECT ); - if( pNC2 && pDef ){ - pExpr->op2 += pNC2->nNestedSelect; - assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); - assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg ); - testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); - testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 ); - pNC2->ncFlags |= NC_HasAgg - | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER) - & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER)); - } - } - pNC->ncFlags |= savedAllowFlags; + NameContext *pNC2 = pNC; + pExpr->op = TK_AGG_FUNCTION; + pExpr->op2 = 0; + while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ + pExpr->op2++; + pNC2 = pNC2->pNext; + } + assert( pDef!=0 ); + if( pNC2 ){ + assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); + testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); + pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); + + } + pNC->ncFlags |= NC_AllowAgg; } /* FIX ME: Compute pExpr->affinity based on the expected return - ** type of the function + ** type of the function */ return WRC_Prune; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); #endif case TK_IN: { testcase( pExpr->op==TK_IN ); - if( ExprUseXSelect(pExpr) ){ + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ int nRef = pNC->nRef; - testcase( pNC->ncFlags & NC_IsCheck ); - testcase( pNC->ncFlags & NC_PartIdx ); - testcase( pNC->ncFlags & NC_IdxExpr ); - testcase( pNC->ncFlags & NC_GenCol ); - assert( pExpr->x.pSelect ); - if( pNC->ncFlags & NC_SelfRef ){ - notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); - }else{ - sqlite3WalkSelect(pWalker, pExpr->x.pSelect); - } + notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr); + sqlite3WalkSelect(pWalker, pExpr->x.pSelect); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); - pExpr->x.pSelect->selFlags |= SF_Correlated; + pNC->ncFlags |= NC_VarSelect; } - pNC->ncFlags |= NC_Subquery; } break; } case TK_VARIABLE: { - testcase( pNC->ncFlags & NC_IsCheck ); - testcase( pNC->ncFlags & NC_PartIdx ); - testcase( pNC->ncFlags & NC_IdxExpr ); - testcase( pNC->ncFlags & NC_GenCol ); - sqlite3ResolveNotValid(pParse, pNC, "parameters", - NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr); + notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } - case TK_IS: - case TK_ISNOT: { - Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight); - assert( !ExprHasProperty(pExpr, EP_Reduced) ); - /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", - ** and "x IS NOT FALSE". */ - if( ALWAYS(pRight) && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){ - int rc = resolveExprStep(pWalker, pRight); - if( rc==WRC_Abort ) return WRC_Abort; - if( pRight->op==TK_TRUEFALSE ){ - pExpr->op2 = pExpr->op; - pExpr->op = TK_TRUTH; - return WRC_Continue; - } - } - /* no break */ deliberate_fall_through - } case TK_BETWEEN: case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: - case TK_GE: { + case TK_GE: + case TK_IS: + case TK_ISNOT: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; assert( pExpr->pLeft!=0 ); nLeft = sqlite3ExprVectorSize(pExpr->pLeft); if( pExpr->op==TK_BETWEEN ){ - assert( ExprUseXList(pExpr) ); nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); if( nRight==nLeft ){ nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); } }else{ @@ -108651,17 +90766,15 @@ testcase( pExpr->op==TK_GE ); testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); } - break; + break; } } - assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); - return pParse->nErr ? WRC_Abort : WRC_Continue; + return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } /* ** pEList is a list of expressions which are really the result set of the ** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause. @@ -108682,17 +90795,14 @@ int i; /* Loop counter */ UNUSED_PARAMETER(pParse); if( pE->op==TK_ID ){ - const char *zCol; - assert( !ExprHasProperty(pE, EP_IntValue) ); - zCol = pE->u.zToken; + char *zCol = pE->u.zToken; for(i=0; inExpr; i++){ - if( pEList->a[i].fg.eEName==ENAME_NAME - && sqlite3_stricmp(pEList->a[i].zEName, zCol)==0 - ){ + char *zAs = pEList->a[i].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ return i+1; } } } return 0; @@ -108726,21 +90836,21 @@ NameContext nc; /* Name context for resolving pE */ sqlite3 *db; /* Database connection */ int rc; /* Return code from subprocedures */ u8 savedSuppErr; /* Saved value of db->suppressErr */ - assert( sqlite3ExprIsInteger(pE, &i, 0)==0 ); + assert( sqlite3ExprIsInteger(pE, &i)==0 ); pEList = pSelect->pEList; /* Resolve all names in the ORDER BY term expression */ memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; - nc.uNC.pEList = pEList; - nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect; - nc.nNcErr = 0; + nc.pEList = pEList; + nc.ncFlags = NC_AllowAgg; + nc.nErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; db->suppressErr = 1; rc = sqlite3ResolveExprNames(&nc, pE); db->suppressErr = savedSuppErr; @@ -108765,17 +90875,15 @@ */ static void resolveOutOfRangeError( Parse *pParse, /* The error context into which to write the error */ const char *zType, /* "ORDER" or "GROUP" */ int i, /* The index (1-based) of the term out of range */ - int mx, /* Largest permissible value of i */ - Expr *pError /* Associate the error with the expression */ + int mx /* Largest permissible value of i */ ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "%r %s BY term out of range - should be " "between 1 and %d", i, zType, mx); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); } /* ** Analyze the ORDER BY clause in a compound SELECT statement. Modify ** each term of the ORDER BY clause is a constant integer between 1 @@ -108802,16 +90910,18 @@ int moreToDo = 1; 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].fg.done = 0; + pOrderBy->a[i].done = 0; } pSelect->pNext = 0; while( pSelect->pPrior ){ pSelect->pPrior->pNext = pSelect; pSelect = pSelect->pPrior; @@ -108822,72 +90932,55 @@ pEList = pSelect->pEList; assert( pEList!=0 ); for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ int iCol = -1; Expr *pE, *pDup; - if( pItem->fg.done ) continue; - pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr); - if( NEVER(pE==0) ) continue; - if( sqlite3ExprIsInteger(pE, &iCol, 0) ){ + if( pItem->done ) continue; + pE = sqlite3ExprSkipCollate(pItem->pExpr); + if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE); + resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); return 1; } }else{ iCol = resolveAsName(pParse, pEList, pE); if( iCol==0 ){ - /* Now test if expression pE matches one of the values returned - ** by pSelect. In the usual case this is done by duplicating the - ** expression, resolving any symbols in it, and then comparing - ** it against each expression returned by the SELECT statement. - ** Once the comparisons are finished, the duplicate expression - ** is deleted. - ** - ** If this is running as part of an ALTER TABLE operation and - ** the symbols resolve successfully, also resolve the symbols in the - ** actual expression. This allows the code in alter.c to modify - ** column references within the ORDER BY expression as required. */ pDup = sqlite3ExprDup(db, pE, 0); if( !db->mallocFailed ){ assert(pDup); iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); - if( IN_RENAME_OBJECT && iCol>0 ){ - resolveOrderByTermToExprList(pParse, pSelect, pE); - } } sqlite3ExprDelete(db, pDup); } } if( iCol>0 ){ /* Convert the ORDER BY term into an integer column number iCol, - ** taking care to preserve the COLLATE clause if it exists. */ - if( !IN_RENAME_OBJECT ){ - Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); - if( pNew==0 ) return 1; - pNew->flags |= EP_IntValue; - pNew->u.iValue = iCol; - if( pItem->pExpr==pE ){ - pItem->pExpr = pNew; - }else{ - Expr *pParent = pItem->pExpr; - assert( pParent->op==TK_COLLATE ); - while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; - assert( pParent->pLeft==pE ); - pParent->pLeft = pNew; - } - sqlite3ExprDelete(db, pE); - pItem->u.x.iOrderByCol = (u16)iCol; - } - pItem->fg.done = 1; + ** taking care to preserve the COLLATE clause if it exists */ + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); + if( pNew==0 ) return 1; + pNew->flags |= EP_IntValue; + pNew->u.iValue = iCol; + if( pItem->pExpr==pE ){ + pItem->pExpr = pNew; + }else{ + Expr *pParent = pItem->pExpr; + assert( pParent->op==TK_COLLATE ); + while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; + assert( pParent->pLeft==pE ); + pParent->pLeft = pNew; + } + sqlite3ExprDelete(db, pE); + pItem->u.x.iOrderByCol = (u16)iCol; + pItem->done = 1; }else{ moreToDo = 1; } } pSelect = pSelect->pNext; } for(i=0; inExpr; i++){ - if( pOrderBy->a[i].fg.done==0 ){ + if( pOrderBy->a[i].done==0 ){ sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " "column in the result set", i+1); return 1; } } @@ -108913,59 +91006,32 @@ int i; sqlite3 *db = pParse->db; ExprList *pEList; struct ExprList_item *pItem; - if( pOrderBy==0 || pParse->db->mallocFailed || IN_RENAME_OBJECT ) return 0; + 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++){ if( pItem->u.x.iOrderByCol ){ if( pItem->u.x.iOrderByCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0); + resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } - resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0); + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, + zType,0); } } return 0; } -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Walker callback for windowRemoveExprFromSelect(). -*/ -static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ - UNUSED_PARAMETER(pWalker); - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - Window *pWin = pExpr->y.pWin; - sqlite3WindowUnlinkFromSelect(pWin); - } - return WRC_Continue; -} - -/* -** Remove any Window objects owned by the expression pExpr from the -** Select.pWin list of Select object pSelect. -*/ -static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){ - if( pSelect->pWin ){ - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.xExprCallback = resolveRemoveWindowsCb; - sWalker.u.pSelect = pSelect; - sqlite3WalkExpr(&sWalker, pExpr); - } -} -#else -# define windowRemoveExprFromSelect(a, b) -#endif /* SQLITE_OMIT_WINDOWFUNC */ - /* ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. ** The Name context of the SELECT statement is pNC. zType is either ** "ORDER" or "GROUP" depending on which type of clause pOrderBy is. ** @@ -108992,17 +91058,16 @@ int iCol; /* Column number */ struct ExprList_item *pItem; /* A term of the ORDER BY clause */ Parse *pParse; /* Parsing context */ int nResult; /* Number of terms in the result set */ - assert( pOrderBy!=0 ); + if( pOrderBy==0 ) return 0; nResult = pSelect->pEList->nExpr; pParse = pNC->pParse; for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ Expr *pE = pItem->pExpr; - Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE); - if( NEVER(pE2==0) ) continue; + Expr *pE2 = sqlite3ExprSkipCollate(pE); if( zType[0]!='G' ){ iCol = resolveAsName(pParse, pSelect->pEList, pE2); if( iCol>0 ){ /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to @@ -109010,16 +91075,16 @@ ** copy of the iCol-th result-set expression. */ pItem->u.x.iOrderByCol = (u16)iCol; continue; } } - if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){ + if( sqlite3ExprIsInteger(pE2, &iCol) ){ /* The ORDER BY term is an integer constant. Again, set the column ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if( iCol<1 || iCol>0xffff ){ - resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2); + resolveOutOfRangeError(pParse, zType, i+1, nResult); return 1; } pItem->u.x.iOrderByCol = (u16)iCol; continue; } @@ -109029,14 +91094,10 @@ if( sqlite3ResolveExprNames(pNC, pE) ){ return 1; } for(j=0; jpEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ - /* Since this expression is being changed into a reference - ** to an identical expression in the result set, remove all Window - ** objects belonging to the expression from the Select.pWin list. */ - windowRemoveExprFromSelect(pSelect, pE); pItem->u.x.iOrderByCol = j+1; } } } return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType); @@ -109053,11 +91114,11 @@ Parse *pParse; /* Parsing context */ int i; /* Loop counter */ ExprList *pGroupBy; /* The GROUP BY clause */ Select *pLeftmost; /* Left-most of SELECT of a compound */ sqlite3 *db; /* Database connection */ - + assert( p!=0 ); if( p->selFlags & SF_Resolved ){ return WRC_Prune; } @@ -109073,11 +91134,11 @@ ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and ** this routine in the correct order. */ if( (p->selFlags & SF_Expanded)==0 ){ sqlite3SelectPrep(pParse, p, pOuterNC); - return pParse->nErr ? WRC_Abort : WRC_Prune; + return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune; } isCompound = p->pPrior!=0; nCompound = 0; pLeftmost = p; @@ -109089,12 +91150,12 @@ /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; - sNC.pWinSelect = p; - if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ + if( sqlite3ResolveExprNames(&sNC, p->pLimit) || + sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } /* If the SF_Converted flags is set, then this Select object was ** was created by the convertCompoundSelectToSubquery() function. @@ -109101,141 +91162,108 @@ ** In this case the ORDER BY clause (p->pOrderBy) should be resolved ** as if it were part of the sub-query, not the parent. This block ** moves the pOrderBy down to the sub-query. It will be moved back ** after the names have been resolved. */ if( p->selFlags & SF_Converted ){ - Select *pSub; - assert( p->pSrc->a[0].fg.isSubquery ); - assert( p->pSrc->a[0].u4.pSubq!=0 ); - pSub = p->pSrc->a[0].u4.pSubq->pSelect; - assert( pSub!=0 ); + Select *pSub = p->pSrc->a[0].pSelect; assert( p->pSrc->nSrc==1 && p->pOrderBy ); assert( pSub->pPrior && pSub->pOrderBy==0 ); pSub->pOrderBy = p->pOrderBy; p->pOrderBy = 0; } - - /* Recursively resolve names in all subqueries in the FROM clause + + /* Recursively resolve names in all subqueries */ - if( pOuterNC ) pOuterNC->nNestedSelect++; for(i=0; ipSrc->nSrc; i++){ - SrcItem *pItem = &p->pSrc->a[i]; - assert( pItem->zName!=0 - || pItem->fg.isSubquery ); /* Test of tag-20240424-1*/ - if( pItem->fg.isSubquery - && (pItem->u4.pSubq->pSelect->selFlags & SF_Resolved)==0 - ){ - int nRef = pOuterNC ? pOuterNC->nRef : 0; + struct SrcList_item *pItem = &p->pSrc->a[i]; + if( pItem->pSelect ){ + NameContext *pNC; /* Used to iterate name contexts */ + int nRef = 0; /* Refcount for pOuterNC and outer contexts */ const char *zSavedContext = pParse->zAuthContext; + + /* Count the total number of references to pOuterNC and all of its + ** parent contexts. After resolving references to expressions in + ** pItem->pSelect, check if this value has changed. If so, then + ** SELECT statement pItem->pSelect must be correlated. Set the + ** pItem->fg.isCorrelated flag if this is the case. */ + for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef; if( pItem->zName ) pParse->zAuthContext = pItem->zName; - sqlite3ResolveSelectNames(pParse, pItem->u4.pSubq->pSelect, pOuterNC); + sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); pParse->zAuthContext = zSavedContext; - if( pParse->nErr ) return WRC_Abort; - assert( db->mallocFailed==0 ); - - /* If the number of references to the outer context changed when - ** expressions in the sub-select were resolved, the sub-select - ** is correlated. It is not required to check the refcount on any - ** but the innermost outer context object, as lookupName() increments - ** the refcount on all contexts between the current one and the - ** context containing the column when it resolves a name. */ - if( pOuterNC ){ - assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef ); - pItem->fg.isCorrelated = (pOuterNC->nRef>nRef); - } - } - } - if( pOuterNC && ALWAYS(pOuterNC->nNestedSelect>0) ){ - pOuterNC->nNestedSelect--; - } - + if( pParse->nErr || db->mallocFailed ) return WRC_Abort; + + for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; + assert( pItem->fg.isCorrelated==0 && nRef<=0 ); + pItem->fg.isCorrelated = (nRef!=0); + } + } + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ - sNC.ncFlags = NC_AllowAgg|NC_AllowWin; + sNC.ncFlags = NC_AllowAgg; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; - + /* Resolve names in the result set. */ if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; - sNC.ncFlags &= ~NC_AllowWin; - - /* If there are no aggregate functions in the result-set, and no GROUP BY + + /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ assert( NC_MinMaxAgg==SF_MinMaxAgg ); - assert( NC_OrderAgg==SF_OrderByReqd ); - p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg)); + p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg); }else{ sNC.ncFlags &= ~NC_AllowAgg; } - + + /* If a HAVING clause is present, then there must be a GROUP BY clause. + */ + if( p->pHaving && !pGroupBy ){ + sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); + return WRC_Abort; + } + /* Add the output column list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ - assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 ); - sNC.uNC.pEList = p->pEList; - sNC.ncFlags |= NC_UEList; - if( p->pHaving ){ - if( (p->selFlags & SF_Aggregate)==0 ){ - sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query"); - return WRC_Abort; - } - if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; - } - sNC.ncFlags |= NC_Where; - if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; - sNC.ncFlags &= ~NC_Where; - - /* Resolve names in table-valued-function arguments */ - for(i=0; ipSrc->nSrc; i++){ - SrcItem *pItem = &p->pSrc->a[i]; - if( pItem->fg.isTabFunc - && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) - ){ - return WRC_Abort; - } - } - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( IN_RENAME_OBJECT ){ - Window *pWin; - for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){ - if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy) - || sqlite3ResolveExprListNames(&sNC, pWin->pPartition) - ){ - return WRC_Abort; - } - } - } -#endif - - /* The ORDER BY and GROUP BY clauses may not refer to terms in - ** outer queries - */ - sNC.pNext = 0; - sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; - - /* If this is a converted compound query, move the ORDER BY clause from - ** the sub-query back to the parent query. At this point each term - ** within the ORDER BY clause has been transformed to an integer value. - ** These integers will be replaced by copies of the corresponding result - ** set expressions by the call to resolveOrderGroupBy() below. */ - if( p->selFlags & SF_Converted ){ - Select *pSub; - assert( p->pSrc->a[0].fg.isSubquery ); - pSub = p->pSrc->a[0].u4.pSubq->pSelect; - assert( pSub!=0 ); + sNC.pEList = p->pEList; + if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; + if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; + + /* Resolve names in table-valued-function arguments */ + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + if( pItem->fg.isTabFunc + && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) + ){ + return WRC_Abort; + } + } + + /* The ORDER BY and GROUP BY clauses may not refer to terms in + ** outer queries + */ + sNC.pNext = 0; + sNC.ncFlags |= NC_AllowAgg; + + /* If this is a converted compound query, move the ORDER BY clause from + ** the sub-query back to the parent query. At this point each term + ** within the ORDER BY clause has been transformed to an integer value. + ** These integers will be replaced by copies of the corresponding result + ** set expressions by the call to resolveOrderGroupBy() below. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; p->pOrderBy = pSub->pOrderBy; pSub->pOrderBy = 0; } /* Process the ORDER BY clause for singleton SELECT statements. @@ -109246,27 +91274,25 @@ ** If there is an ORDER BY clause on a term of a compound-select other ** than the right-most term, then that is a syntax error. But the error ** is not detected until much later, and so we need to go ahead and ** resolve those symbols on the incorrect ORDER BY for consistency. */ - if( p->pOrderBy!=0 - && isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ + if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ return WRC_Abort; } if( db->mallocFailed ){ return WRC_Abort; } - sNC.ncFlags &= ~NC_AllowWin; - - /* Resolve the GROUP BY clause. At the same time, make sure + + /* Resolve the GROUP BY clause. At the same time, make sure ** the GROUP BY clause does not contain aggregate functions. */ if( pGroupBy ){ struct ExprList_item *pItem; - + if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){ return WRC_Abort; } for(i=0, pItem=pGroupBy->a; inExpr; i++, pItem++){ if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ @@ -109304,11 +91330,11 @@ ** This routine walks an expression tree and resolves references to ** table columns and result-set columns. At the same time, do error ** checking on function usage and set a flag if any aggregate functions ** are seen. ** -** To resolve table columns references we look for nodes (or subtrees) of the +** To resolve table columns references we look for nodes (or subtrees) of the ** form X.Y.Z or Y.Z or just Z where ** ** X: The name of a database. Ex: "main" or "temp" or ** the symbolic name assigned to an ATTACH-ed database. ** @@ -109336,110 +91362,73 @@ ** ** The "x" term of the order by is replaced by "a+b" to render: ** ** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b; ** -** Function calls are checked to make sure that the function is +** Function calls are checked to make sure that the function is ** defined and that the correct number of arguments are specified. ** If the function is an aggregate function, then the NC_HasAgg flag is ** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION. ** If an expression contains aggregate functions then the EP_Agg ** property on the expression is set. ** ** An error message is left in pParse if anything is amiss. The number ** if errors is returned. */ -SQLITE_PRIVATE int sqlite3ResolveExprNames( +SQLITE_PRIVATE int sqlite3ResolveExprNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ - int savedHasAgg; + u16 savedHasAgg; Walker w; if( pExpr==0 ) return SQLITE_OK; - savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); + savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg); + pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg); w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; - w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep; + w.xSelectCallback = resolveSelectStep; w.xSelectCallback2 = 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 - assert( pExpr!=0 ); - sqlite3WalkExprNN(&w, pExpr); + sqlite3WalkExpr(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif - assert( EP_Agg==NC_HasAgg ); - assert( EP_Win==NC_HasWin ); - testcase( pNC->ncFlags & NC_HasAgg ); - testcase( pNC->ncFlags & NC_HasWin ); - ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) ); + if( pNC->ncFlags & NC_HasAgg ){ + ExprSetProperty(pExpr, EP_Agg); + } pNC->ncFlags |= savedHasAgg; - return pNC->nNcErr>0 || w.pParse->nErr>0; + return pNC->nErr>0 || w.pParse->nErr>0; } /* ** Resolve all names for all expression in an expression list. This is ** just like sqlite3ResolveExprNames() except that it works for an expression ** list rather than a single expression. -** -** The return value is SQLITE_OK (0) for success or SQLITE_ERROR (1) for a -** failure. */ -SQLITE_PRIVATE int sqlite3ResolveExprListNames( +SQLITE_PRIVATE int sqlite3ResolveExprListNames( NameContext *pNC, /* Namespace to resolve expressions in. */ ExprList *pList /* The expression list to be analyzed. */ ){ int i; - int savedHasAgg = 0; - Walker w; - if( pList==0 ) return SQLITE_OK; - w.pParse = pNC->pParse; - w.xExprCallback = resolveExprStep; - w.xSelectCallback = resolveSelectStep; - w.xSelectCallback2 = 0; - w.u.pNC = pNC; - savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - if( pExpr==0 ) continue; -#if SQLITE_MAX_EXPR_DEPTH>0 - w.pParse->nHeight += pExpr->nHeight; - if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){ - return SQLITE_ERROR; - } -#endif - sqlite3WalkExprNN(&w, pExpr); -#if SQLITE_MAX_EXPR_DEPTH>0 - w.pParse->nHeight -= pExpr->nHeight; -#endif - assert( EP_Agg==NC_HasAgg ); - assert( EP_Win==NC_HasWin ); - testcase( pNC->ncFlags & NC_HasAgg ); - testcase( pNC->ncFlags & NC_HasWin ); - if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){ - ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) ); - savedHasAgg |= pNC->ncFlags & - (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); - } - if( w.pParse->nErr>0 ) return SQLITE_ERROR; - } - pNC->ncFlags |= savedHasAgg; - return SQLITE_OK; + if( pList ){ + for(i=0; inExpr; i++){ + if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort; + } + } + return WRC_Continue; } /* ** Resolve all names in all expressions of a SELECT and in all -** descendants of the SELECT, including compounds off of p->pPrior, +** decendents of the SELECT, including compounds off of p->pPrior, ** subqueries in expressions, and subqueries used as FROM clause ** terms. ** ** See sqlite3ResolveExprNames() for a description of the kinds of ** transformations that occur. @@ -109462,60 +91451,42 @@ w.u.pNC = pOuterNC; sqlite3WalkSelect(&w, p); } /* -** Resolve names in expressions that can only reference a single table -** or which cannot reference any tables at all. Examples: -** -** "type" flag -** ------------ -** (1) CHECK constraints NC_IsCheck -** (2) WHERE clauses on partial indices NC_PartIdx -** (3) Expressions in indexes on expressions NC_IdxExpr -** (4) Expression arguments to VACUUM INTO. 0 -** (5) GENERATED ALWAYS as expressions NC_GenCol -** -** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN -** nodes of the expression is set to -1 and the Expr.iColumn value is -** set to the column number. In case (4), TK_COLUMN nodes cause an error. +** Resolve names in expressions that can only reference a single table: +** +** * CHECK constraints +** * WHERE clauses on partial indices +** +** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression +** is set to -1 and the Expr.iColumn value is set to the column number. ** ** Any errors cause an error message to be set in pParse. */ -SQLITE_PRIVATE int sqlite3ResolveSelfReference( - Parse *pParse, /* Parsing context */ - Table *pTab, /* The table being referenced, or NULL */ - int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */ - Expr *pExpr, /* Expression to resolve. May be NULL. */ - ExprList *pList /* Expression list to resolve. May be NULL. */ +SQLITE_PRIVATE void sqlite3ResolveSelfReference( + Parse *pParse, /* Parsing context */ + Table *pTab, /* The table being referenced */ + int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */ + Expr *pExpr, /* Expression to resolve. May be NULL. */ + ExprList *pList /* Expression list to resolve. May be NUL. */ ){ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ - int rc; - assert( type==0 || pTab!=0 ); - assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr - || type==NC_GenCol || pTab==0 ); + assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr ); memset(&sNC, 0, sizeof(sNC)); memset(&sSrc, 0, sizeof(sSrc)); - if( pTab ){ - sSrc.nSrc = 1; - sSrc.a[0].zName = pTab->zName; - sSrc.a[0].pSTab = pTab; - sSrc.a[0].iCursor = -1; - if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){ - /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP - ** schema elements */ - type |= NC_FromDDL; - } - } + sSrc.nSrc = 1; + sSrc.a[0].zName = pTab->zName; + sSrc.a[0].pTab = pTab; + sSrc.a[0].iCursor = -1; sNC.pParse = pParse; sNC.pSrcList = &sSrc; - sNC.ncFlags = type | NC_IsDDL; - if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc; - if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList); - return rc; + sNC.ncFlags = type; + if( sqlite3ResolveExprNames(&sNC, pExpr) ) return; + if( pList ) sqlite3ResolveExprListNames(&sNC, pList); } /************** End of resolve.c *********************************************/ /************** Begin file expr.c ********************************************/ /* @@ -109539,20 +91510,20 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree); /* ** Return the affinity character for a single column of a table. */ -SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table *pTab, int iCol){ - if( iCol<0 || NEVER(iCol>=pTab->nCol) ) return SQLITE_AFF_INTEGER; - return pTab->aCol[iCol].affinity; +SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table *pTab, int iCol){ + assert( iColnCol ); + return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER; } /* ** Return the 'affinity' of the expression pExpr if any. ** ** If pExpr is a column, a reference to a column via an 'AS' alias, -** or a sub-select with a column as the return value, then the +** or a sub-select with a column as the return value, then the ** affinity of that column is returned. Otherwise, 0x00 is returned, ** indicating no affinity for the expression. ** ** i.e. the WHERE clause expressions in the following statements all ** have an affinity: @@ -109560,128 +91531,36 @@ ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ -SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){ +SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ int op; + pExpr = sqlite3ExprSkipCollate(pExpr); + if( pExpr->flags & EP_Generic ) return 0; op = pExpr->op; - while( 1 /* exit-by-break */ ){ - if( op==TK_COLUMN || (op==TK_AGG_COLUMN && pExpr->y.pTab!=0) ){ - assert( ExprUseYTab(pExpr) ); - assert( pExpr->y.pTab!=0 ); - return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); - } - if( op==TK_SELECT ){ - assert( ExprUseXSelect(pExpr) ); - assert( pExpr->x.pSelect!=0 ); - assert( pExpr->x.pSelect->pEList!=0 ); - assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 ); - return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); - } + if( op==TK_SELECT ){ + assert( pExpr->flags&EP_xIsSelect ); + return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); + } + if( op==TK_REGISTER ) op = pExpr->op2; #ifndef SQLITE_OMIT_CAST - if( op==TK_CAST ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - return sqlite3AffinityType(pExpr->u.zToken, 0); - } + if( op==TK_CAST ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + return sqlite3AffinityType(pExpr->u.zToken, 0); + } #endif - if( op==TK_SELECT_COLUMN ){ - assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) ); - assert( pExpr->iColumn < pExpr->iTable ); - assert( pExpr->iColumn >= 0 ); - assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); - return sqlite3ExprAffinity( - pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr - ); - } - if( op==TK_VECTOR ){ - assert( ExprUseXList(pExpr) ); - return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); - } - if( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){ - assert( pExpr->op==TK_COLLATE - || pExpr->op==TK_IF_NULL_ROW - || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) ); - pExpr = pExpr->pLeft; - op = pExpr->op; - continue; - } - if( op!=TK_REGISTER ) break; - op = pExpr->op2; - if( NEVER( op==TK_REGISTER ) ) break; - } - return pExpr->affExpr; -} - -/* -** Make a guess at all the possible datatypes of the result that could -** be returned by an expression. Return a bitmask indicating the answer: -** -** 0x01 Numeric -** 0x02 Text -** 0x04 Blob -** -** If the expression must return NULL, then 0x00 is returned. -*/ -SQLITE_PRIVATE int sqlite3ExprDataType(const Expr *pExpr){ - while( pExpr ){ - switch( pExpr->op ){ - case TK_COLLATE: - case TK_IF_NULL_ROW: - case TK_UPLUS: { - pExpr = pExpr->pLeft; - break; - } - case TK_NULL: { - pExpr = 0; - break; - } - case TK_STRING: { - return 0x02; - } - case TK_BLOB: { - return 0x04; - } - case TK_CONCAT: { - return 0x06; - } - case TK_VARIABLE: - case TK_AGG_FUNCTION: - case TK_FUNCTION: { - return 0x07; - } - case TK_COLUMN: - case TK_AGG_COLUMN: - case TK_SELECT: - case TK_CAST: - case TK_SELECT_COLUMN: - case TK_VECTOR: { - int aff = sqlite3ExprAffinity(pExpr); - if( aff>=SQLITE_AFF_NUMERIC ) return 0x05; - if( aff==SQLITE_AFF_TEXT ) return 0x06; - return 0x07; - } - case TK_CASE: { - int res = 0; - int ii; - ExprList *pList = pExpr->x.pList; - assert( ExprUseXList(pExpr) && pList!=0 ); - assert( pList->nExpr > 0); - for(ii=1; iinExpr; ii+=2){ - res |= sqlite3ExprDataType(pList->a[ii].pExpr); - } - if( pList->nExpr % 2 ){ - res |= sqlite3ExprDataType(pList->a[pList->nExpr-1].pExpr); - } - return res; - } - default: { - return 0x01; - } - } /* End of switch(op) */ - } /* End of while(pExpr) */ - return 0x00; + if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ + return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + } + if( op==TK_SELECT_COLUMN ){ + assert( pExpr->pLeft->flags&EP_xIsSelect ); + return sqlite3ExprAffinity( + pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr + ); + } + return pExpr->affinity; } /* ** Set the collating sequence for expression pExpr to be the collating ** sequence named by pToken. Return a pointer to a new Expr node that @@ -109689,11 +91568,11 @@ ** ** If a memory allocation error occurs, that fact is recorded in pParse->db ** and the pExpr parameter is returned unchanged. */ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken( - const Parse *pParse, /* Parsing context */ + Parse *pParse, /* Parsing context */ Expr *pExpr, /* Add the "COLLATE" clause to this expression */ const Token *pCollName, /* Name of collating sequence */ int dequote /* True to dequote pCollName */ ){ if( pCollName->n>0 ){ @@ -109704,110 +91583,86 @@ pExpr = pNew; } } return pExpr; } -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString( - const Parse *pParse, /* Parsing context */ - Expr *pExpr, /* Add the "COLLATE" clause to this expression */ - const char *zC /* The collating sequence name */ -){ +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ Token s; assert( zC!=0 ); sqlite3TokenInit(&s, (char*)zC); return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); } /* -** Skip over any TK_COLLATE operators. +** Skip over any TK_COLLATE operators and any unlikely() +** or likelihood() function at the root of an expression. */ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ - assert( pExpr->op==TK_COLLATE ); - pExpr = pExpr->pLeft; - } - return pExpr; -} - -/* -** Skip over any TK_COLLATE operators and/or any unlikely() -** or likelihood() or likely() functions at the root of an -** expression. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ - while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ - assert( ExprUseXList(pExpr) ); + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; - }else if( pExpr->op==TK_COLLATE ){ + }else{ + assert( pExpr->op==TK_COLLATE ); pExpr = pExpr->pLeft; - }else{ - break; } - } + } return 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 ** precedence over right operands. */ -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ sqlite3 *db = pParse->db; CollSeq *pColl = 0; - const Expr *p = pExpr; + Expr *p = pExpr; while( p ){ int op = p->op; - if( op==TK_REGISTER ) op = p->op2; - if( (op==TK_AGG_COLUMN && p->y.pTab!=0) - || op==TK_COLUMN || op==TK_TRIGGER - ){ - int j; - assert( ExprUseYTab(p) ); - assert( p->y.pTab!=0 ); - if( (j = p->iColumn)>=0 ){ - const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]); - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); - } - break; - } + if( p->flags & EP_Generic ) break; if( op==TK_CAST || op==TK_UPLUS ){ p = p->pLeft; continue; } - if( op==TK_VECTOR ){ - assert( ExprUseXList(p) ); - p = p->x.pList->a[0].pExpr; - continue; - } - if( op==TK_COLLATE ){ - assert( !ExprHasProperty(p, EP_IntValue) ); + if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); break; + } + if( (op==TK_AGG_COLUMN || op==TK_COLUMN + || op==TK_REGISTER || op==TK_TRIGGER) + && p->pTab!=0 + ){ + /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally + ** a TK_COLUMN but was previously evaluated and cached in a register */ + int j = p->iColumn; + if( j>=0 ){ + const char *zColl = p->pTab->aCol[j].zColl; + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); + } + break; } if( p->flags & EP_Collate ){ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ Expr *pNext = p->pRight; /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( !ExprUseXList(p) || p->x.pList==0 || p->pRight==0 ); - if( ExprUseXList(p) && p->x.pList!=0 && !db->mallocFailed ){ + assert( p->x.pList==0 || p->pRight==0 ); + /* p->flags holds EP_Collate and p->pLeft->flags does not. And + ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at + ** least one EP_Collate. Thus the following two ALWAYS. */ + if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ int i; - for(i=0; ix.pList->nExpr; i++){ + for(i=0; ALWAYS(ix.pList->nExpr); i++){ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ pNext = p->x.pList->a[i].pExpr; break; } } @@ -109816,79 +91671,58 @@ } }else{ break; } } - if( sqlite3CheckCollSeq(pParse, pColl) ){ + if( sqlite3CheckCollSeq(pParse, pColl) ){ pColl = 0; } return pColl; } -/* -** Return the collation sequence for the expression pExpr. If -** there is no defined collating sequence, return a pointer to the -** default 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, const 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, const Expr *pE1, const 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 ** type affinity that should be used for the comparison operator. */ -SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2){ +SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); - if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){ + if( aff1 && aff2 ){ /* Both sides of the comparison are columns. If one has numeric ** affinity, use that. Otherwise use no affinity. */ if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ return SQLITE_AFF_NUMERIC; }else{ return SQLITE_AFF_BLOB; } + }else if( !aff1 && !aff2 ){ + /* Neither side of the comparison is a column. Compare the + ** results directly. + */ + return SQLITE_AFF_BLOB; }else{ /* One side is a column, the other is not. Use the columns affinity. */ - assert( aff1<=SQLITE_AFF_NONE || aff2<=SQLITE_AFF_NONE ); - return (aff1<=SQLITE_AFF_NONE ? aff2 : aff1) | SQLITE_AFF_NONE; + assert( aff1==0 || aff2==0 ); + return (aff1 + aff2); } } /* ** pExpr is a comparison operator. Return the type affinity that should ** be applied to both operands prior to doing the comparison. */ -static char comparisonAffinity(const Expr *pExpr){ +static char comparisonAffinity(Expr *pExpr){ char aff; assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT ); assert( pExpr->pLeft ); aff = sqlite3ExprAffinity(pExpr->pLeft); if( pExpr->pRight ){ aff = sqlite3CompareAffinity(pExpr->pRight, aff); - }else if( ExprUseXSelect(pExpr) ){ + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); }else if( aff==0 ){ aff = SQLITE_AFF_BLOB; } return aff; @@ -109898,30 +91732,27 @@ ** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. ** idx_affinity is the affinity of an indexed column. Return true ** if the index with affinity idx_affinity may be used to implement ** the comparison in pExpr. */ -SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity){ +SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); - if( affflags & EP_Collate ){ pColl = sqlite3ExprCollSeq(pParse, pLeft); @@ -109955,26 +91786,10 @@ } } return pColl; } -/* Expression p is a comparison operator. Return a collation sequence -** appropriate for the comparison operator. -** -** This is normally just a wrapper around sqlite3BinaryCompareCollSeq(). -** However, if the OP_Commuted flag is set, then the order of the operands -** is reversed in the sqlite3BinaryCompareCollSeq() call so that the -** correct collating sequence is found. -*/ -SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, const Expr *p){ - if( ExprHasProperty(p, EP_Commuted) ){ - return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft); - }else{ - return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight); - } -} - /* ** Generate code for a comparison operator. */ static int codeCompare( Parse *pParse, /* The parsing (and code generating) context */ @@ -109981,27 +91796,21 @@ Expr *pLeft, /* The left operand */ Expr *pRight, /* The right operand */ int opcode, /* The comparison opcode */ int in1, int in2, /* Register holding operands */ int dest, /* Jump here if true. */ - int jumpIfNull, /* If true, jump if either operand is NULL */ - int isCommuted /* The comparison has been commuted */ + int jumpIfNull /* If true, jump if either operand is NULL */ ){ int p5; int addr; CollSeq *p4; - if( pParse->nErr ) return 0; - if( isCommuted ){ - p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft); - }else{ - p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); - } + p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, (void*)p4, P4_COLLSEQ); - sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5); + sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); return addr; } /* ** Return true if expression pExpr is a vector, or false otherwise. @@ -110010,28 +91819,26 @@ ** columns of result. Every TK_VECTOR node is an vector because the ** parser will not generate a TK_VECTOR with fewer than two entries. ** But a TK_SELECT might be either a vector or a scalar. It is only ** considered a vector if it has two or more result columns. */ -SQLITE_PRIVATE int sqlite3ExprIsVector(const Expr *pExpr){ +SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr){ return sqlite3ExprVectorSize(pExpr)>1; } /* -** If the expression passed as the only argument is of type TK_VECTOR +** If the expression passed as the only argument is of type TK_VECTOR ** return the number of expressions in the vector. Or, if the expression ** is a sub-select, return the number of columns in the sub-select. For ** any other type of expression, return 1. */ -SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr){ +SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr){ u8 op = pExpr->op; if( op==TK_REGISTER ) op = pExpr->op2; if( op==TK_VECTOR ){ - assert( ExprUseXList(pExpr) ); return pExpr->x.pList->nExpr; }else if( op==TK_SELECT ){ - assert( ExprUseXSelect(pExpr) ); return pExpr->x.pSelect->pEList->nExpr; }else{ return 1; } } @@ -110050,18 +91857,16 @@ ** just the expression for the i-th term of the result set, and may ** not be ready for evaluation because the table cursor has not yet ** been positioned. */ SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){ - assert( iop==TK_ERROR ); + assert( iop2==0 || pVector->op==TK_REGISTER ); if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){ - assert( ExprUseXSelect(pVector) ); return pVector->x.pSelect->pEList->a[i].pExpr; }else{ - assert( ExprUseXList(pVector) ); return pVector->x.pList->a[i].pExpr; } } return pVector; } @@ -110069,11 +91874,11 @@ /* ** Compute and return a new Expr object which when passed to ** sqlite3ExprCode() will generate all necessary code to compute ** the iField-th column of the vector expression pVector. ** -** It is ok for pVector to be a scalar (as long as iField==0). +** It is ok for pVector to be a scalar (as long as iField==0). ** In that case, this routine works like sqlite3ExprDup(). ** ** The caller owns the returned Expr object and is responsible for ** ensuring that the returned value eventually gets freed. ** @@ -110088,16 +91893,15 @@ ** of the returned TK_SELECT_COLUMN Expr object. */ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( Parse *pParse, /* Parsing context */ Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ - int iField, /* Which column of the vector to return */ - int nField /* Total number of columns in the vector */ + int iField /* Which column of the vector to return */ ){ Expr *pRet; if( pVector->op==TK_SELECT ){ - assert( ExprUseXSelect(pVector) ); + assert( pVector->flags & EP_xIsSelect ); /* The TK_SELECT_COLUMN Expr node: ** ** pLeft: pVector containing TK_SELECT. Not deleted. ** pRight: not used. But recursively deleted. ** iColumn: Index of a column in pVector @@ -110112,45 +91916,34 @@ ** 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); if( pRet ){ - ExprSetProperty(pRet, EP_FullSize); - pRet->iTable = nField; pRet->iColumn = iField; pRet->pLeft = pVector; } + assert( pRet==0 || pRet->iTable==0 ); }else{ - if( pVector->op==TK_VECTOR ){ - Expr **ppVector; - assert( ExprUseXList(pVector) ); - ppVector = &pVector->x.pList->a[iField].pExpr; - pVector = *ppVector; - if( IN_RENAME_OBJECT ){ - /* This must be a vector UPDATE inside a trigger */ - *ppVector = 0; - return pVector; - } - } + if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr; pRet = sqlite3ExprDup(pParse->db, pVector, 0); } return pRet; } /* ** If expression pExpr is of type TK_SELECT, generate code to evaluate -** it. Return the register in which the result is stored (or, if the +** it. Return the register in which the result is stored (or, if the ** sub-select returns more than one column, the first in an array ** of registers in which the result is stored). ** ** If pExpr is not a TK_SELECT expression, return 0. */ static int exprCodeSubselect(Parse *pParse, Expr *pExpr){ int reg = 0; #ifndef SQLITE_OMIT_SUBQUERY if( pExpr->op==TK_SELECT ){ - reg = sqlite3CodeSubselect(pParse, pExpr); + reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0); } #endif return reg; } @@ -110158,14 +91951,14 @@ ** Argument pVector points to a vector expression - either a TK_VECTOR ** or TK_SELECT that returns more than one column. This function returns ** the register number of a register that contains the value of ** element iField of the vector. ** -** If pVector is a TK_SELECT expression, then code for it must have +** If pVector is a TK_SELECT expression, then code for it must have ** already been generated using the exprCodeSubselect() routine. In this ** case parameter regSelect should be the first in an array of registers -** containing the results of the sub-select. +** containing the results of the sub-select. ** ** If pVector is of type TK_VECTOR, then code for the requested field ** is generated. In this case (*pRegFree) may be set to the number of ** a temporary register to be freed by the caller before returning. ** @@ -110179,26 +91972,21 @@ int regSelect, /* First in array of registers */ Expr **ppExpr, /* OUT: Expression element */ int *pRegFree /* OUT: Temp register to free */ ){ u8 op = pVector->op; - assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR ); + assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT ); if( op==TK_REGISTER ){ *ppExpr = sqlite3VectorFieldSubexpr(pVector, iField); return pVector->iTable+iField; } if( op==TK_SELECT ){ - assert( ExprUseXSelect(pVector) ); *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr; return regSelect+iField; } - if( op==TK_VECTOR ){ - assert( ExprUseXList(pVector) ); - *ppExpr = pVector->x.pList->a[iField].pExpr; - return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); - } - return 0; + *ppExpr = pVector->x.pList->a[iField].pExpr; + return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); } /* ** Expression pExpr is a comparison between two vector values. Compute ** the result of the comparison (1, 0, or NULL) and write that @@ -110223,82 +92011,71 @@ int nLeft = sqlite3ExprVectorSize(pLeft); int i; int regLeft = 0; int regRight = 0; u8 opx = op; - int addrCmp = 0; - int addrDone = sqlite3VdbeMakeLabel(pParse); - int isCommuted = ExprHasProperty(pExpr,EP_Commuted); + int addrDone = sqlite3VdbeMakeLabel(v); - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); - if( pParse->nErr ) return; 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 - || pExpr->op==TK_LE || pExpr->op==TK_GE + 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 + || pExpr->op==TK_LE || pExpr->op==TK_GE ); assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ) || (pExpr->op==TK_ISNOT && op==TK_NE) ); assert( p5==0 || pExpr->op!=op ); assert( p5==SQLITE_NULLEQ || pExpr->op==op ); - if( op==TK_LE ) opx = TK_LT; - if( op==TK_GE ) opx = TK_GT; - if( op==TK_NE ) opx = TK_EQ; + p5 |= SQLITE_STOREP2; + if( opx==TK_LE ) opx = TK_LT; + if( opx==TK_GE ) opx = TK_GT; regLeft = exprCodeSubselect(pParse, pLeft); regRight = exprCodeSubselect(pParse, pRight); - sqlite3VdbeAddOp2(v, OP_Integer, 1, dest); for(i=0; 1 /*Loop exits by "break"*/; i++){ int regFree1 = 0, regFree2 = 0; - Expr *pL = 0, *pR = 0; + Expr *pL, *pR; int r1, r2; assert( i>=0 && i0 ) sqlite3ExprCachePush(pParse); r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); - addrCmp = sqlite3VdbeCurrentAddr(v); - codeCompare(pParse, pL, pR, opx, r1, r2, addrDone, p5, isCommuted); + codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); - if( (opx==TK_LT || opx==TK_GT) && i0 ) sqlite3ExprCachePop(pParse); if( i==nLeft-1 ){ break; } if( opx==TK_EQ ){ - sqlite3VdbeAddOp2(v, OP_NotNull, dest, addrDone); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; + }else if( opx==TK_NE ){ + sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v); + p5 |= SQLITE_KEEPNULL; }else{ assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE ); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone); + sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone); + VdbeCoverageIf(v, op==TK_LT); + VdbeCoverageIf(v, op==TK_GT); + VdbeCoverageIf(v, op==TK_LE); + VdbeCoverageIf(v, op==TK_GE); if( i==nLeft-2 ) opx = op; } } - sqlite3VdbeJumpHere(v, addrCmp); sqlite3VdbeResolveLabel(v, addrDone); - if( op==TK_NE ){ - sqlite3VdbeAddOp2(v, OP_Not, dest, dest); - } } #if SQLITE_MAX_EXPR_DEPTH>0 /* ** Check that argument nHeight is less than or equal to the maximum @@ -110307,11 +92084,11 @@ */ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){ int rc = SQLITE_OK; int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; if( nHeight>mxHeight ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "Expression tree is too large (maximum depth %d)", mxHeight ); rc = SQLITE_ERROR; } return rc; @@ -110324,53 +92101,53 @@ ** ** If this maximum height is greater than the current value pointed ** to by pnHeight, the second parameter, then set *pnHeight to that ** value. */ -static void heightOfExpr(const Expr *p, int *pnHeight){ +static void heightOfExpr(Expr *p, int *pnHeight){ if( p ){ if( p->nHeight>*pnHeight ){ *pnHeight = p->nHeight; } } } -static void heightOfExprList(const ExprList *p, int *pnHeight){ +static void heightOfExprList(ExprList *p, int *pnHeight){ if( p ){ int i; for(i=0; inExpr; i++){ heightOfExpr(p->a[i].pExpr, pnHeight); } } } -static void heightOfSelect(const Select *pSelect, int *pnHeight){ - const Select *p; - for(p=pSelect; p; p=p->pPrior){ +static void heightOfSelect(Select *p, int *pnHeight){ + if( p ){ 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); } } /* -** Set the Expr.nHeight variable in the structure passed as an -** argument. An expression with no children, Expr.pList or +** Set the Expr.nHeight variable in the structure passed as an +** argument. An expression with no children, Expr.pList or ** Expr.pSelect member has a height of 1. Any other expression -** has a height equal to the maximum height of any other +** has a height equal to the maximum height of any other ** referenced Expr plus one. ** ** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, ** if appropriate. */ static void exprSetHeight(Expr *p){ - int nHeight = p->pLeft ? p->pLeft->nHeight : 0; - if( NEVER(p->pRight) && p->pRight->nHeight>nHeight ){ - nHeight = p->pRight->nHeight; - } - if( ExprUseXSelect(p) ){ + int nHeight = 0; + heightOfExpr(p->pLeft, &nHeight); + heightOfExpr(p->pRight, &nHeight); + if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); }else if( p->x.pList ){ heightOfExprList(p->x.pList, &nHeight); p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } @@ -110381,11 +92158,11 @@ ** Set the Expr.nHeight variable using the exprSetHeight() function. If ** the height is greater than the maximum allowed expression depth, ** leave an error in pParse. ** ** Also propagate all EP_Propagate flags from the Expr.x.pList into -** Expr.flags. +** Expr.flags. */ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ if( pParse->nErr ) return; exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); @@ -110393,38 +92170,28 @@ /* ** Return the maximum height of any expression tree referenced ** by the select statement passed as an argument. */ -SQLITE_PRIVATE int sqlite3SelectExprHeight(const Select *p){ +SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){ int nHeight = 0; heightOfSelect(p, &nHeight); return nHeight; } #else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ /* ** Propagate all EP_Propagate flags from the Expr.x.pList into -** Expr.flags. +** Expr.flags. */ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( pParse->nErr ) return; - if( p && ExprUseXList(p) && p->x.pList ){ + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } } #define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ -/* -** Set the error offset for an Expr node, if possible. -*/ -SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr *pExpr, int iOfst){ - if( pExpr==0 ) return; - if( NEVER(ExprUseWJoin(pExpr)) ) return; - pExpr->w.iOfst = iOfst; -} - /* ** This routine is the core allocator for Expr nodes. ** ** Construct a new expression node and return a pointer to it. Memory ** for this node and for the pToken argument is a single allocation @@ -110435,16 +92202,15 @@ ** If dequote is false, no dequoting is performed. The deQuote ** parameter is ignored if pToken is NULL or if the token does not ** appear to be quoted. If the quotes were of the form "..." (double-quotes) ** then the EP_DblQuoted flag is set on the expression node. ** -** Special case (tag-20240227-a): If op==TK_INTEGER and pToken points to -** a string that can be translated into a 32-bit integer, then the token is -** not stored in u.zToken. Instead, the integer values is written -** into u.iValue and the EP_IntValue flag is set. No extra storage +** Special case: If op==TK_INTEGER and pToken points to a string that +** can be translated into a 32-bit integer, then the token is not +** stored in u.zToken. Instead, the integer values is written +** into u.iValue and the EP_IntValue flag is set. No extra storage ** is allocated to hold the integer text and the dequote flag is ignored. -** See also tag-20240227-b. */ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ int op, /* Expression opcode */ const Token *pToken, /* Token argument. Might be NULL */ @@ -110456,11 +92222,11 @@ assert( db!=0 ); if( pToken ){ if( op!=TK_INTEGER || pToken->z==0 || sqlite3GetInt32(pToken->z, &iValue)==0 ){ - nExtra = pToken->n+1; /* tag-20240227-a */ + nExtra = pToken->n+1; assert( iValue>=0 ); } } pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); if( pNew ){ @@ -110467,25 +92233,26 @@ memset(pNew, 0, sizeof(Expr)); pNew->op = (u8)op; pNew->iAgg = -1; if( pToken ){ if( nExtra==0 ){ - pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse); + pNew->flags |= EP_IntValue|EP_Leaf; pNew->u.iValue = iValue; }else{ pNew->u.zToken = (char*)&pNew[1]; assert( pToken->z!=0 || pToken->n==0 ); if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); pNew->u.zToken[pToken->n] = 0; if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ - sqlite3DequoteExpr(pNew); + if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted; + sqlite3Dequote(pNew->u.zToken); } } } #if SQLITE_MAX_EXPR_DEPTH>0 pNew->nHeight = 1; -#endif +#endif } return pNew; } /* @@ -110497,11 +92264,11 @@ int op, /* Expression opcode */ const char *zToken /* Token argument. Might be NULL */ ){ Token x; x.z = zToken; - x.n = sqlite3Strlen30(zToken); + x.n = zToken ? sqlite3Strlen30(zToken) : 0; return sqlite3ExprAlloc(db, op, &x, 0); } /* ** Attach subtrees pLeft and pRight to the Expr node pRoot. @@ -110518,30 +92285,19 @@ if( pRoot==0 ){ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); sqlite3ExprDelete(db, pRight); }else{ - assert( ExprUseXList(pRoot) ); - assert( pRoot->x.pSelect==0 ); if( pRight ){ pRoot->pRight = pRight; pRoot->flags |= EP_Propagate & pRight->flags; -#if SQLITE_MAX_EXPR_DEPTH>0 - pRoot->nHeight = pRight->nHeight+1; - }else{ - pRoot->nHeight = 1; -#endif } if( pLeft ){ pRoot->pLeft = pLeft; pRoot->flags |= EP_Propagate & pLeft->flags; -#if SQLITE_MAX_EXPR_DEPTH>0 - if( pLeft->nHeight>=pRoot->nHeight ){ - pRoot->nHeight = pLeft->nHeight+1; - } -#endif } + exprSetHeight(pRoot); } } /* ** Allocate an Expr node which joins as many as two subtrees. @@ -110555,20 +92311,24 @@ int op, /* Expression opcode */ Expr *pLeft, /* Left operand */ Expr *pRight /* Right operand */ ){ Expr *p; - p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); - if( p ){ - memset(p, 0, sizeof(Expr)); - p->op = op & 0xff; - p->iAgg = -1; + if( op==TK_AND && pParse->nErr==0 ){ + /* Take advantage of short-circuit false optimization for AND */ + p = sqlite3ExprAnd(pParse->db, pLeft, pRight); + }else{ + 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 ) { sqlite3ExprCheckHeight(pParse, p->nHeight); - }else{ - sqlite3ExprDelete(pParse->db, pLeft); - sqlite3ExprDelete(pParse->db, pRight); } return p; } /* @@ -110583,229 +92343,85 @@ }else{ assert( pParse->db->mallocFailed ); sqlite3SelectDelete(pParse->db, pSelect); } } + /* -** Expression list pEList is a list of vector values. This function -** converts the contents of pEList to a VALUES(...) Select statement -** returning 1 row for each element of the list. For example, the -** expression list: -** -** ( (1,2), (3,4) (5,6) ) -** -** is translated to the equivalent of: -** -** VALUES(1,2), (3,4), (5,6) -** -** Each of the vector values in pEList must contain exactly nElem terms. -** If a list element that is not a vector or does not contain nElem terms, -** an error message is left in pParse. -** -** This is used as part of processing IN(...) expressions with a list -** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))". -*/ -SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){ - int ii; - Select *pRet = 0; - assert( nElem>1 ); - for(ii=0; iinExpr; ii++){ - Select *pSel; - Expr *pExpr = pEList->a[ii].pExpr; - int nExprElem; - if( pExpr->op==TK_VECTOR ){ - assert( ExprUseXList(pExpr) ); - nExprElem = pExpr->x.pList->nExpr; - }else{ - nExprElem = 1; - } - if( nExprElem!=nElem ){ - sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d", - nExprElem, nExprElem>1?"s":"", nElem - ); - break; - } - assert( ExprUseXList(pExpr) ); - pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0); - pExpr->x.pList = 0; - if( pSel ){ - if( pRet ){ - pSel->op = TK_ALL; - pSel->pPrior = pRet; - } - pRet = pSel; - } - } - - if( pRet && pRet->pPrior ){ - pRet->selFlags |= SF_MultiValue; - } - sqlite3ExprListDelete(pParse->db, pEList); - return pRet; +** If the expression is always either TRUE or FALSE (respectively), +** then return 1. If one cannot determine the truth value of the +** expression at compile-time return 0. +** +** This is an optimization. If is OK to return 0 here even if +** the expression really is always false or false (a false negative). +** But it is a bug to return 1 if the expression might have different +** boolean values in different circumstances (a false positive.) +** +** Note that if the expression is part of conditional for a +** LEFT JOIN, then we cannot determine at compile-time whether or not +** is it true or false, so always return 0. +*/ +static int exprAlwaysTrue(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v!=0; +} +static int exprAlwaysFalse(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v==0; } /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. ** -** If one side or the other of the AND is known to be false, and neither side -** is part of an ON clause, then instead of returning an AND expression, -** just return a constant expression with a value of false. +** If one side or the other of the AND is known to be false, then instead +** of returning an AND expression, just return a constant expression with +** a value of false. */ -SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ - sqlite3 *db = pParse->db; - if( pLeft==0 ){ +SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ + if( pLeft==0 ){ return pRight; }else if( pRight==0 ){ return pLeft; - }else{ - u32 f = pLeft->flags | pRight->flags; - if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse))==EP_IsFalse - && !IN_RENAME_OBJECT - ){ - sqlite3ExprDeferredDelete(pParse, pLeft); - sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3Expr(db, TK_INTEGER, "0"); - }else{ - return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); - } + }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){ + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0); + }else{ + Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); + sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); + return pNew; } } /* ** Construct a new expression node for a function with multiple ** arguments. */ -SQLITE_PRIVATE Expr *sqlite3ExprFunction( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* Argument list */ - const Token *pToken, /* Name of the function */ - int eDistinct /* SF_Distinct or SF_ALL or 0 */ -){ +SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ Expr *pNew; sqlite3 *db = pParse->db; assert( pToken ); pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); if( pNew==0 ){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } - assert( !ExprHasProperty(pNew, EP_InnerON|EP_OuterON) ); - pNew->w.iOfst = (int)(pToken->z - pParse->zTail); - if( pList - && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] - && !pParse->nested - ){ - sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); - } pNew->x.pList = pList; - ExprSetProperty(pNew, EP_HasFunc); - assert( ExprUseXList(pNew) ); + assert( !ExprHasProperty(pNew, EP_xIsSelect) ); sqlite3ExprSetHeightAndFlags(pParse, pNew); - if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); return pNew; } -/* -** Report an error when attempting to use an ORDER BY clause within -** the arguments of a non-aggregate function. -*/ -SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse *pParse, Expr *p){ - sqlite3ErrorMsg(pParse, - "ORDER BY may not be used with non-aggregate %#T()", p - ); -} - -/* -** Attach an ORDER BY clause to a function call. -** -** functionname( arguments ORDER BY sortlist ) -** \_____________________/ \______/ -** pExpr pOrderBy -** -** The ORDER BY clause is inserted into a new Expr node of type TK_ORDER -** and added to the Expr.pLeft field of the parent TK_FUNCTION node. -*/ -SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The function call to which ORDER BY is to be added */ - ExprList *pOrderBy /* The ORDER BY clause to add */ -){ - Expr *pOB; - sqlite3 *db = pParse->db; - if( NEVER(pOrderBy==0) ){ - assert( db->mallocFailed ); - return; - } - if( pExpr==0 ){ - assert( db->mallocFailed ); - sqlite3ExprListDelete(db, pOrderBy); - return; - } - assert( pExpr->op==TK_FUNCTION ); - assert( pExpr->pLeft==0 ); - assert( ExprUseXList(pExpr) ); - if( pExpr->x.pList==0 || NEVER(pExpr->x.pList->nExpr==0) ){ - /* Ignore ORDER BY on zero-argument aggregates */ - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pOrderBy); - return; - } - if( IsWindowFunc(pExpr) ){ - sqlite3ExprOrderByAggregateError(pParse, pExpr); - sqlite3ExprListDelete(db, pOrderBy); - return; - } - - pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0); - if( pOB==0 ){ - sqlite3ExprListDelete(db, pOrderBy); - return; - } - pOB->x.pList = pOrderBy; - assert( ExprUseXList(pOB) ); - pExpr->pLeft = pOB; - ExprSetProperty(pOB, EP_FullSize); -} - -/* -** Check to see if a function is usable according to current access -** rules: -** -** SQLITE_FUNC_DIRECT - Only usable from top-level SQL -** -** SQLITE_FUNC_UNSAFE - Usable if TRUSTED_SCHEMA or from -** top-level SQL -** -** If the function is not usable, create an error. -*/ -SQLITE_PRIVATE void sqlite3ExprFunctionUsable( - Parse *pParse, /* Parsing and code generating context */ - const Expr *pExpr, /* The function invocation */ - const FuncDef *pDef /* The function being invoked */ -){ - assert( !IN_RENAME_OBJECT ); - assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 ); - if( ExprHasProperty(pExpr, EP_FromDDL) ){ - if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 - || (pParse->db->flags & SQLITE_TrustedSchema)==0 - ){ - /* Functions prohibited in triggers and views if: - ** (1) tagged with SQLITE_DIRECTONLY - ** (2) not tagged with SQLITE_INNOCUOUS (which means it - ** is tagged with SQLITE_FUNC_UNSAFE) and - ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning - ** that the schema is possibly tainted). - */ - sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr); - } - } -} - /* ** Assign a variable number to an expression that encodes a wildcard -** in the original SQL statement. +** in the original SQL statement. ** ** Wildcards consisting of a single "?" are assigned the next sequential ** variable number. ** ** Wildcards of the form "?nnn" are assigned the number "nnn". We make @@ -110850,11 +92466,10 @@ testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); return; } x = (ynVar)i; if( x>pParse->nVar ){ pParse->nVar = (int)x; @@ -110878,120 +92493,54 @@ } } pExpr->iColumn = x; if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); - sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); } } /* ** Recursively delete an expression tree. */ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); - assert( db!=0 ); -exprDeleteRestart: - assert( !ExprUseUValue(p) || p->u.iValue>=0 ); - assert( !ExprUseYWin(p) || !ExprUseYSub(p) ); - assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed ); - assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) ); + /* Sanity check: Assert that the IntValue is non-negative if it exists */ + assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); assert( p->pRight==0 ); - assert( !ExprUseXSelect(p) || p->x.pSelect==0 ); - assert( !ExprUseXList(p) || p->x.pList==0 ); + assert( p->x.pSelect==0 ); } #endif if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 ); + assert( p->x.pList==0 || p->pRight==0 ); + if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); if( p->pRight ){ - assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3ExprDeleteNN(db, p->pRight); - }else if( ExprUseXSelect(p) ){ - assert( !ExprHasProperty(p, EP_WinFunc) ); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_WinFunc) ){ - sqlite3WindowDelete(db, p->y.pWin); - } -#endif - } - if( p->pLeft && p->op!=TK_SELECT_COLUMN ){ - Expr *pLeft = p->pLeft; - if( !ExprHasProperty(p, EP_Static) - && !ExprHasProperty(pLeft, EP_Static) - ){ - /* Avoid unnecessary recursion on unary operators */ - sqlite3DbNNFreeNN(db, p); - p = pLeft; - goto exprDeleteRestart; - }else{ - sqlite3ExprDeleteNN(db, pLeft); - } - } - } + } + } + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( !ExprHasProperty(p, EP_Static) ){ - sqlite3DbNNFreeNN(db, p); + sqlite3DbFreeNN(db, p); } } SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); } -SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3 *db, void *p){ - if( ALWAYS(p) ) sqlite3ExprDeleteNN(db, (Expr*)p); -} - -/* -** Clear both elements of an OnOrUsing object -*/ -SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ - if( p==0 ){ - /* Nothing to clear */ - }else if( p->pOn ){ - sqlite3ExprDeleteNN(db, p->pOn); - }else if( p->pUsing ){ - sqlite3IdListDelete(db, p->pUsing); - } -} - -/* -** Arrange to cause pExpr to be deleted when the pParse is deleted. -** This is similar to sqlite3ExprDelete() except that the delete is -** deferred until the pParse is deleted. -** -** The pExpr might be deleted immediately on an OOM error. -** -** Return 0 if the delete was successfully deferred. Return non-zero -** if the delete happened immediately because of an OOM. -*/ -SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ - return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr); -} - -/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the -** expression. -*/ -SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){ - if( p ){ - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprUnmap(pParse, p); - } - sqlite3ExprDeleteNN(pParse->db, p); - } -} - -/* -** Return the number of bytes allocated for the expression structure + +/* +** Return the number of bytes allocated for the expression structure ** passed as the first argument. This is always one of EXPR_FULLSIZE, ** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. */ -static int exprStructSize(const Expr *p){ +static int exprStructSize(Expr *p){ if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE; if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE; return EXPR_FULLSIZE; } @@ -110998,18 +92547,18 @@ /* ** The dupedExpr*Size() routines each return the number of bytes required ** to store a copy of an expression or expression tree. They differ in ** how much of the tree is measured. ** -** dupedExprStructSize() Size of only the Expr structure +** dupedExprStructSize() Size of only the Expr structure ** dupedExprNodeSize() Size of Expr + space for token ** dupedExprSize() Expr + token + subtree components ** *************************************************************************** ** -** The dupedExprStructSize() function returns two values OR-ed together: -** (1) the space required for a copy of the Expr structure only and +** The dupedExprStructSize() function returns two values OR-ed together: +** (1) the space required for a copy of the Expr structure only and ** (2) the EP_xxx flags that indicate what the structure size should be. ** The return values is always one of: ** ** EXPR_FULLSIZE ** EXPR_REDUCEDSIZE | EP_Reduced @@ -111020,28 +92569,29 @@ ** return value with EP_Reduced|EP_TokenOnly. ** ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size ** (unreduced) Expr objects as they or originally constructed by the parser. ** During expression analysis, extra information is computed and moved into -** later parts of the Expr object and that extra information might get chopped +** later parts of teh Expr object and that extra information might get chopped ** off if the expression is reduced. Note also that it does not work to ** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal ** to reduce a pristine expression tree from the parser. The implementation ** of dupedExprStructSize() contain multiple assert() statements that attempt ** to enforce this constraint. */ -static int dupedExprStructSize(const Expr *p, int flags){ +static int dupedExprStructSize(Expr *p, int flags){ int nSize; 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 || ExprHasProperty(p, EP_FullSize) ){ + if( 0==flags || p->op==TK_SELECT_COLUMN ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); - assert( !ExprHasProperty(p, EP_OuterON) ); - assert( !ExprHasVVAProperty(p, EP_NoReduce) ); + assert( !ExprHasProperty(p, EP_FromJoin) ); + assert( !ExprHasProperty(p, EP_MemToken) ); + assert( !ExprHasProperty(p, EP_NoReduce) ); if( p->pLeft || p->x.pList ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ assert( p->pRight==0 ); nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; @@ -111049,343 +92599,247 @@ } return nSize; } /* -** This function returns the space in bytes required to store the copy +** This function returns the space in bytes required to store the copy ** of the Expr structure and a copy of the Expr.u.zToken string (if that ** string is defined.) */ -static int dupedExprNodeSize(const Expr *p, int flags){ +static int dupedExprNodeSize(Expr *p, int flags){ int nByte = dupedExprStructSize(p, flags) & 0xfff; if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nByte += sqlite3Strlen30NN(p->u.zToken)+1; + nByte += sqlite3Strlen30(p->u.zToken)+1; } return ROUND8(nByte); } /* -** Return the number of bytes required to create a duplicate of the -** expression passed as the first argument. +** Return the number of bytes required to create a duplicate of the +** expression passed as the first argument. The second argument is a +** mask containing EXPRDUP_XXX flags. ** ** The value returned includes space to create a copy of the Expr struct ** itself and the buffer referred to by Expr.u.zToken, if any. ** -** The return value includes space to duplicate all Expr nodes in the -** tree formed by Expr.pLeft and Expr.pRight, but not any other -** substructure such as Expr.x.pList, Expr.x.pSelect, and Expr.y.pWin. +** If the EXPRDUP_REDUCE flag is set, then the return value includes +** space to duplicate all Expr nodes in the tree formed by Expr.pLeft +** and Expr.pRight variables (but not for any structures pointed to or +** descended from the Expr.x.pList or Expr.x.pSelect variables). */ -static int dupedExprSize(const Expr *p){ - int nByte; - assert( p!=0 ); - nByte = dupedExprNodeSize(p, EXPRDUP_REDUCE); - if( p->pLeft ) nByte += dupedExprSize(p->pLeft); - if( p->pRight ) nByte += dupedExprSize(p->pRight); - assert( nByte==ROUND8(nByte) ); +static int dupedExprSize(Expr *p, int flags){ + int nByte = 0; + if( p ){ + nByte = dupedExprNodeSize(p, flags); + if( flags&EXPRDUP_REDUCE ){ + nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); + } + } return nByte; } /* -** An EdupBuf is a memory allocation used to stored multiple Expr objects -** together with their Expr.zToken content. This is used to help implement -** compression while doing sqlite3ExprDup(). The top-level Expr does the -** allocation for itself and many of its decendents, then passes an instance -** of the structure down into exprDup() so that they decendents can have -** access to that memory. -*/ -typedef struct EdupBuf EdupBuf; -struct EdupBuf { - u8 *zAlloc; /* Memory space available for storage */ -#ifdef SQLITE_DEBUG - u8 *zEnd; /* First byte past the end of memory */ -#endif -}; - -/* -** This function is similar to sqlite3ExprDup(), except that if pEdupBuf -** is not NULL then it points to memory that can be used to store a copy -** of the input Expr p together with its p->u.zToken (if any). pEdupBuf -** is updated with the new buffer tail prior to returning. -*/ -static Expr *exprDup( - sqlite3 *db, /* Database connection (for memory allocation) */ - const Expr *p, /* Expr tree to be duplicated */ - int dupFlags, /* EXPRDUP_REDUCE for compression. 0 if not */ - EdupBuf *pEdupBuf /* Preallocated storage space, or NULL */ -){ +** This function is similar to sqlite3ExprDup(), except that if pzBuffer +** is not NULL then *pzBuffer is assumed to point to a buffer large enough +** to store the copy of expression p, the copies of p->u.zToken +** (if applicable), and the copies of the p->pLeft and p->pRight expressions, +** if any. Before returning, *pzBuffer is set to the first byte past the +** portion of the buffer copied into by this function. +*/ +static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ Expr *pNew; /* Value to return */ - EdupBuf sEdupBuf; /* Memory space from which to build Expr object */ + u8 *zAlloc; /* Memory space from which to build Expr object */ u32 staticFlag; /* EP_Static if space not obtained from malloc */ - int nToken = -1; /* Space needed for p->u.zToken. -1 means unknown */ assert( db!=0 ); assert( p ); assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE ); - assert( pEdupBuf==0 || dupFlags==EXPRDUP_REDUCE ); + assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE ); /* Figure out where to write the new Expr structure. */ - if( pEdupBuf ){ - sEdupBuf.zAlloc = pEdupBuf->zAlloc; -#ifdef SQLITE_DEBUG - sEdupBuf.zEnd = pEdupBuf->zEnd; -#endif + if( pzBuffer ){ + zAlloc = *pzBuffer; staticFlag = EP_Static; - assert( sEdupBuf.zAlloc!=0 ); - assert( dupFlags==EXPRDUP_REDUCE ); - }else{ - int nAlloc; - if( dupFlags ){ - nAlloc = dupedExprSize(p); - }else if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30NN(p->u.zToken)+1; - nAlloc = ROUND8(EXPR_FULLSIZE + nToken); - }else{ - nToken = 0; - nAlloc = ROUND8(EXPR_FULLSIZE); - } - assert( nAlloc==ROUND8(nAlloc) ); - sEdupBuf.zAlloc = sqlite3DbMallocRawNN(db, nAlloc); -#ifdef SQLITE_DEBUG - sEdupBuf.zEnd = sEdupBuf.zAlloc ? sEdupBuf.zAlloc+nAlloc : 0; -#endif - + }else{ + zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags)); staticFlag = 0; } - pNew = (Expr *)sEdupBuf.zAlloc; - assert( EIGHT_BYTE_ALIGNMENT(pNew) ); + pNew = (Expr *)zAlloc; if( pNew ){ /* Set nNewSize to the size allocated for the structure pointed to ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed ** by the copy of the p->u.zToken string (if any). */ const unsigned nStructSize = dupedExprStructSize(p, dupFlags); - int nNewSize = nStructSize & 0xfff; - if( nToken<0 ){ - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30(p->u.zToken) + 1; - }else{ - nToken = 0; - } + const int nNewSize = nStructSize & 0xfff; + int nToken; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; + }else{ + nToken = 0; } if( dupFlags ){ - assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= nNewSize+nToken ); assert( ExprHasProperty(p, EP_Reduced)==0 ); - memcpy(sEdupBuf.zAlloc, p, nNewSize); + memcpy(zAlloc, p, nNewSize); }else{ u32 nSize = (u32)exprStructSize(p); - assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= - (int)EXPR_FULLSIZE+nToken ); - memcpy(sEdupBuf.zAlloc, p, nSize); - if( nSizeflags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); pNew->flags |= staticFlag; - ExprClearVVAProperties(pNew); - if( dupFlags ){ - ExprSetVVAProperty(pNew, EP_Immutable); - } /* Copy the p->u.zToken string, if any. */ - assert( nToken>=0 ); - if( nToken>0 ){ - char *zToken = pNew->u.zToken = (char*)&sEdupBuf.zAlloc[nNewSize]; + if( nToken ){ + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; memcpy(zToken, p->u.zToken, nToken); - nNewSize += nToken; } - sEdupBuf.zAlloc += ROUND8(nNewSize); - if( ((p->flags|pNew->flags)&(EP_TokenOnly|EP_Leaf))==0 ){ - + if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ - if( ExprUseXSelect(p) ){ + if( ExprHasProperty(p, EP_xIsSelect) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, - p->op!=TK_ORDER ? dupFlags : 0); - } - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_WinFunc) ){ - pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); - assert( ExprHasProperty(pNew, EP_WinFunc) ); - } -#endif /* SQLITE_OMIT_WINDOWFUNC */ - - /* Fill in pNew->pLeft and pNew->pRight. */ - if( dupFlags ){ - if( p->op==TK_SELECT_COLUMN ){ - pNew->pLeft = p->pLeft; - assert( p->pRight==0 - || p->pRight==p->pLeft - || ExprHasProperty(p->pLeft, EP_Subquery) ); - }else{ - pNew->pLeft = p->pLeft ? - exprDup(db, p->pLeft, EXPRDUP_REDUCE, &sEdupBuf) : 0; - } - pNew->pRight = p->pRight ? - exprDup(db, p->pRight, EXPRDUP_REDUCE, &sEdupBuf) : 0; - }else{ - if( p->op==TK_SELECT_COLUMN ){ - pNew->pLeft = p->pLeft; - assert( p->pRight==0 - || p->pRight==p->pLeft - || ExprHasProperty(p->pLeft, EP_Subquery) ); + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); + } + } + + /* Fill in pNew->pLeft and pNew->pRight. */ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); + if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ + pNew->pLeft = p->pLeft ? + exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; + pNew->pRight = p->pRight ? + exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; + } + if( pzBuffer ){ + *pzBuffer = zAlloc; + } + }else{ + 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); } pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } } - if( pEdupBuf ) memcpy(pEdupBuf, &sEdupBuf, sizeof(sEdupBuf)); - assert( sEdupBuf.zAlloc <= sEdupBuf.zEnd ); return pNew; } /* -** Create and return a deep copy of the object passed as the second +** Create and return a deep copy of the object passed as the second ** argument. If an OOM condition is encountered, NULL is returned ** and the db->mallocFailed flag set. */ #ifndef SQLITE_OMIT_CTE -SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){ +static With *withDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ - sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); + int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; pRet->nCte = p->nCte; for(i=0; inCte; i++){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); - pRet->a[i].eM10d = p->a[i].eM10d; } } } return pRet; } #else -# define sqlite3WithDup(x,y) 0 -#endif - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** The gatherSelectWindows() procedure and its helper routine -** gatherSelectWindowsCallback() are used to scan all the expressions -** an a newly duplicated SELECT statement and gather all of the Window -** objects found there, assembling them onto the linked list at Select->pWin. -*/ -static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){ - Select *pSelect = pWalker->u.pSelect; - Window *pWin = pExpr->y.pWin; - assert( pWin ); - assert( IsWindowFunc(pExpr) ); - assert( pWin->ppThis==0 ); - sqlite3WindowLink(pSelect, pWin); - } - return WRC_Continue; -} -static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){ - return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune; -} -static void gatherSelectWindows(Select *p){ - Walker w; - w.xExprCallback = gatherSelectWindowsCallback; - w.xSelectCallback = gatherSelectWindowsSelectCallback; - w.xSelectCallback2 = 0; - w.pParse = 0; - w.u.pSelect = p; - sqlite3WalkSelect(&w, p); -} -#endif - +# define withDup(x,y) 0 +#endif /* ** The following group of routines make deep copies of expressions, ** expression lists, ID lists, and select statements. The copies can ** be deleted (by being passed to their respective ...Delete() routines) ** without effecting the originals. ** ** The expression list, ID, and source lists return by sqlite3ExprListDup(), -** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded +** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded ** by subsequent calls to sqlite*ListAppend() routines. ** ** Any tables that the SrcList might point to are not duplicated. ** ** The flags parameter contains a combination of the EXPRDUP_XXX flags. ** If the EXPRDUP_REDUCE flag is set, then the structure returned is a ** truncated version of the usual Expr structure that will be stored as ** part of the in-memory representation of the database schema. */ -SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, const Expr *p, int flags){ +SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ assert( flags==0 || flags==EXPRDUP_REDUCE ); return p ? exprDup(db, p, flags, 0) : 0; } -SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){ +SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; - struct ExprList_item *pItem; - const struct ExprList_item *pOldItem; + struct ExprList_item *pItem, *pOldItem; int i; - Expr *pPriorSelectColOld = 0; - Expr *pPriorSelectColNew = 0; + Expr *pPriorSelectCol = 0; assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p)); + pNew = sqlite3DbMallocRawNN(db, + sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) ); if( pNew==0 ) return 0; - pNew->nExpr = p->nExpr; - pNew->nAlloc = p->nAlloc; + pNew->nAlloc = 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 + if( pOldExpr && pOldExpr->op==TK_SELECT_COLUMN - && (pNewExpr = pItem->pExpr)!=0 - ){ - if( pNewExpr->pRight ){ - pPriorSelectColOld = pOldExpr->pRight; - pPriorSelectColNew = pNewExpr->pRight; - pNewExpr->pLeft = pNewExpr->pRight; - }else{ - if( pOldExpr->pLeft!=pPriorSelectColOld ){ - pPriorSelectColOld = pOldExpr->pLeft; - pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags); - pNewExpr->pRight = pPriorSelectColNew; - } - pNewExpr->pLeft = pPriorSelectColNew; - } - } - pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName); - pItem->fg = pOldItem->fg; - pItem->fg.done = 0; + && (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; + pItem->done = 0; + pItem->bSpanIsTab = pOldItem->bSpanIsTab; pItem->u = pOldItem->u; } return pNew; } /* ** If cursors, triggers, views and subqueries are all omitted from -** the build, then none of the following routines, except for +** the build, then none of the following routines, except for ** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes ** called with a NULL argument. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ || !defined(SQLITE_OMIT_SUBQUERY) -SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){ +SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ SrcList *pNew; int i; int nByte; assert( db!=0 ); if( p==0 ) return 0; @@ -111392,83 +92846,69 @@ nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqlite3DbMallocRawNN(db, nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; inSrc; i++){ - SrcItem *pNewItem = &pNew->a[i]; - const SrcItem *pOldItem = &p->a[i]; + struct SrcList_item *pNewItem = &pNew->a[i]; + struct SrcList_item *pOldItem = &p->a[i]; Table *pTab; - pNewItem->fg = pOldItem->fg; - if( pOldItem->fg.isSubquery ){ - Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery)); - if( pNewSubq==0 ){ - assert( db->mallocFailed ); - pNewItem->fg.isSubquery = 0; - }else{ - memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq)); - pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags); - if( pNewSubq->pSelect==0 ){ - sqlite3DbFree(db, pNewSubq); - pNewSubq = 0; - pNewItem->fg.isSubquery = 0; - } - } - pNewItem->u4.pSubq = pNewSubq; - }else if( pOldItem->fg.fixedSchema ){ - pNewItem->u4.pSchema = pOldItem->u4.pSchema; - }else{ - pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase); - } + pNewItem->pSchema = pOldItem->pSchema; + pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); + pNewItem->fg = pOldItem->fg; pNewItem->iCursor = pOldItem->iCursor; + pNewItem->addrFillSub = pOldItem->addrFillSub; + pNewItem->regReturn = pOldItem->regReturn; if( pNewItem->fg.isIndexedBy ){ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); - }else if( pNewItem->fg.isTabFunc ){ - pNewItem->u1.pFuncArg = + } + pNewItem->pIBIndex = pOldItem->pIBIndex; + if( pNewItem->fg.isTabFunc ){ + pNewItem->u1.pFuncArg = sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); - }else{ - pNewItem->u1.nRow = pOldItem->u1.nRow; - } - pNewItem->u2 = pOldItem->u2; - if( pNewItem->fg.isCte ){ - pNewItem->u2.pCteUse->nUse++; - } - pTab = pNewItem->pSTab = pOldItem->pSTab; + } + pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nTabRef++; } - if( pOldItem->fg.isUsing ){ - assert( pNewItem->fg.isUsing ); - pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing); - }else{ - pNewItem->u3.pOn = sqlite3ExprDup(db, pOldItem->u3.pOn, flags); - } + pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); + pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); + pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); pNewItem->colUsed = pOldItem->colUsed; } return pNew; } -SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ +SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ IdList *pNew; int i; assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nId = p->nId; + pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); + if( pNew->a==0 ){ + sqlite3DbFreeNN(db, pNew); + return 0; + } + /* Note that because the size of the allocation for p->a[] is not + ** necessarily a power of two, sqlite3IdListAppend() may not be called + ** on the duplicate created by this function. */ for(i=0; inId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; - const struct IdList_item *pOldItem = &p->a[i]; + struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->idx = pOldItem->idx; } return pNew; } -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){ +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){ Select *pRet = 0; Select *pNext = 0; Select **pp = &pRet; - const Select *p; + Select *p; assert( db!=0 ); for(p=pDup; p; p=p->pPrior){ Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); if( pNew==0 ) break; @@ -111480,39 +92920,28 @@ 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->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 = sqlite3WithDup(db, p->pWith); -#ifndef SQLITE_OMIT_WINDOWFUNC - pNew->pWin = 0; - pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); - if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew); -#endif - pNew->selId = p->selId; - if( db->mallocFailed ){ - /* Any prior OOM might have left the Select object incomplete. - ** Delete the whole thing rather than allow an incomplete Select - ** to be used by the code generator. */ - pNew->pNext = 0; - sqlite3SelectDelete(db, pNew); - break; - } + 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, const Select *p, int flags){ +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ assert( p==0 ); return 0; } #endif @@ -111519,75 +92948,51 @@ /* ** 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(). -** ** 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. */ -static const struct ExprList_item zeroItem = {0}; -SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew( - sqlite3 *db, /* Database handle. Used for memory allocation */ - Expr *pExpr /* Expression to be appended. Might be NULL */ -){ - struct ExprList_item *pItem; - ExprList *pList; - - pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 ); - if( pList==0 ){ - sqlite3ExprDelete(db, pExpr); - return 0; - } - pList->nAlloc = 4; - pList->nExpr = 1; - pItem = &pList->a[0]; - *pItem = zeroItem; - pItem->pExpr = pExpr; - return pList; -} -SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow( - sqlite3 *db, /* Database handle. Used for memory allocation */ - ExprList *pList, /* List to which to append. Might be NULL */ - Expr *pExpr /* Expression to be appended. Might be NULL */ -){ - struct ExprList_item *pItem; - ExprList *pNew; - pList->nAlloc *= 2; - pNew = sqlite3DbRealloc(db, pList, - sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0])); - if( pNew==0 ){ - sqlite3ExprListDelete(db, pList); - sqlite3ExprDelete(db, pExpr); - return 0; - }else{ - pList = pNew; - } - pItem = &pList->a[pList->nExpr++]; - *pItem = zeroItem; - pItem->pExpr = pExpr; - return pList; -} SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( Parse *pParse, /* Parsing context */ 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 ){ - return sqlite3ExprListAppendNew(pParse->db,pExpr); - } - if( pList->nAllocnExpr+1 ){ - return sqlite3ExprListAppendGrow(pParse->db,pList,pExpr); + pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) ); + if( pList==0 ){ + goto no_mem; + } + pList->nExpr = 0; + pList->nAlloc = 1; + }else if( pList->nExpr==pList->nAlloc ){ + ExprList *pNew; + pNew = sqlite3DbRealloc(db, pList, + sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0])); + if( pNew==0 ){ + goto no_mem; + } + pList = pNew; + pList->nAlloc *= 2; } pItem = &pList->a[pList->nExpr++]; - *pItem = zeroItem; + 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: + /* Avoid leaking memory if malloc has failed. */ + sqlite3ExprDelete(db, pExpr); + sqlite3ExprListDelete(db, pList); + return 0; } /* ** pColumns and pExpr form a vector assignment which is part of the SET ** clause of an UPDATE statement. Like this: @@ -111612,12 +93017,12 @@ /* pColumns can only be NULL due to an OOM but an OOM will cause an ** exit prior to this routine being invoked */ if( NEVER(pColumns==0) ) goto vector_append_error; if( pExpr==0 ) goto vector_append_error; - /* 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, + /* 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", @@ -111624,26 +93029,24 @@ pColumns->nId, n); goto vector_append_error; } for(i=0; inId; i++){ - Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId); - assert( pSubExpr!=0 || db->mallocFailed ); - if( pSubExpr==0 ) continue; + Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i); pList = sqlite3ExprListAppend(pParse, pList, pSubExpr); if( pList ){ assert( pList->nExpr==iFirst+i+1 ); - pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName; + pList->a[pList->nExpr-1].zName = pColumns->a[i].zName; pColumns->a[i].zName = 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; @@ -111651,80 +93054,51 @@ ** the RHS and LHS sizes match during code generation. */ pFirst->iTable = pColumns->nId; } vector_append_error: - sqlite3ExprUnmapAndDelete(pParse, pExpr); + sqlite3ExprDelete(db, pExpr); sqlite3IdListDelete(db, pColumns); return pList; } /* ** Set the sort order for the last element on the given ExprList. */ -SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){ - struct ExprList_item *pItem; +SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){ if( p==0 ) return; + assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 ); assert( p->nExpr>0 ); - - assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 ); - assert( iSortOrder==SQLITE_SO_UNDEFINED - || iSortOrder==SQLITE_SO_ASC - || iSortOrder==SQLITE_SO_DESC - ); - assert( eNulls==SQLITE_SO_UNDEFINED - || eNulls==SQLITE_SO_ASC - || eNulls==SQLITE_SO_DESC - ); - - pItem = &p->a[p->nExpr-1]; - assert( pItem->fg.bNulls==0 ); - if( iSortOrder==SQLITE_SO_UNDEFINED ){ - iSortOrder = SQLITE_SO_ASC; - } - pItem->fg.sortFlags = (u8)iSortOrder; - - if( eNulls!=SQLITE_SO_UNDEFINED ){ - pItem->fg.bNulls = 1; - if( iSortOrder!=eNulls ){ - pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL; - } - } + if( iSortOrder<0 ){ + assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC ); + return; + } + p->a[p->nExpr-1].sortOrder = (u8)iSortOrder; } /* -** Set the ExprList.a[].zEName element of the most recently added item +** Set the ExprList.a[].zName element of the most recently added item ** on the expression list. ** ** pList might be NULL following an OOM error. But pName should never be ** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag ** is set. */ SQLITE_PRIVATE void sqlite3ExprListSetName( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to add the span. */ - const Token *pName, /* Name to be added */ + Token *pName, /* Name to be added */ int dequote /* True to cause the name to be dequoted */ ){ assert( pList!=0 || pParse->db->mallocFailed!=0 ); - assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 ); if( pList ){ struct ExprList_item *pItem; assert( pList->nExpr>0 ); pItem = &pList->a[pList->nExpr-1]; - assert( pItem->zEName==0 ); - assert( pItem->fg.eEName==ENAME_NAME ); - pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); - if( dequote ){ - /* If dequote==0, then pName->z does not point to part of a DDL - ** statement handled by the parser. And so no token need be added - ** to the token-map. */ - sqlite3Dequote(pItem->zEName); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (const void*)pItem->zEName, pName); - } - } + assert( pItem->zName==0 ); + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); + if( dequote ) sqlite3Dequote(pItem->zName); } } /* ** Set the ExprList.a[].zSpan element of the most recently added item @@ -111735,22 +93109,21 @@ ** is set. */ SQLITE_PRIVATE void sqlite3ExprListSetSpan( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to add the span. */ - const char *zStart, /* Start of the span */ - const char *zEnd /* End of the span */ + ExprSpan *pSpan /* The span to be added */ ){ 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 ); - if( pItem->zEName==0 ){ - pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd); - pItem->fg.eEName = ENAME_SPAN; - } + assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); + sqlite3DbFree(db, pItem->zSpan); + pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + (int)(pSpan->zEnd - pSpan->zStart)); } } /* ** If the expression list pEList contains more than iLimit elements, @@ -111774,175 +93147,38 @@ */ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){ int i = pList->nExpr; struct ExprList_item *pItem = pList->a; assert( pList->nExpr>0 ); - assert( db!=0 ); do{ sqlite3ExprDelete(db, pItem->pExpr); - if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName); + sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zSpan); pItem++; }while( --i>0 ); - sqlite3DbNNFreeNN(db, pList); + sqlite3DbFreeNN(db, pList); } SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ if( pList ) exprListDeleteNN(db, pList); } -SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3 *db, void *pList){ - if( ALWAYS(pList) ) exprListDeleteNN(db, (ExprList*)pList); -} /* ** Return the bitwise-OR of all Expr.flags fields in the given ** ExprList. */ SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ int i; u32 m = 0; - assert( pList!=0 ); - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - assert( pExpr!=0 ); - m |= pExpr->flags; + if( pList ){ + 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; -} - -/* -** Check the input string to see if it is "true" or "false" (in any case). -** -** If the string is.... Return -** "true" EP_IsTrue -** "false" EP_IsFalse -** anything else 0 -*/ -SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char *zIn){ - if( sqlite3StrICmp(zIn, "true")==0 ) return EP_IsTrue; - if( sqlite3StrICmp(zIn, "false")==0 ) return EP_IsFalse; - return 0; -} - - -/* -** If the input expression is an ID with the name "true" or "false" -** then convert it into an TK_TRUEFALSE term. Return non-zero if -** the conversion happened, and zero if the expression is unaltered. -*/ -SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ - u32 v; - assert( pExpr->op==TK_ID || pExpr->op==TK_STRING ); - if( !ExprHasProperty(pExpr, EP_Quoted|EP_IntValue) - && (v = sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0 - ){ - pExpr->op = TK_TRUEFALSE; - ExprSetProperty(pExpr, v); - return 1; - } - return 0; -} - -/* -** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE -** and 0 if it is FALSE. -*/ -SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ - pExpr = sqlite3ExprSkipCollateAndLikely((Expr*)pExpr); - assert( pExpr->op==TK_TRUEFALSE ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 - || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); - return pExpr->u.zToken[4]==0; -} - -/* -** If pExpr is an AND or OR expression, try to simplify it by eliminating -** terms that are always true or false. Return the simplified expression. -** Or return the original expression if no simplification is possible. -** -** Examples: -** -** (x<10) AND true => (x<10) -** (x<10) AND false => false -** (x<10) AND (y=22 OR false) => (x<10) AND (y=22) -** (x<10) AND (y=22 OR true) => (x<10) -** (y=22) OR true => true -*/ -SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ - assert( pExpr!=0 ); - if( pExpr->op==TK_AND || pExpr->op==TK_OR ){ - Expr *pRight = sqlite3ExprSimplifiedAndOr(pExpr->pRight); - Expr *pLeft = sqlite3ExprSimplifiedAndOr(pExpr->pLeft); - if( ExprAlwaysTrue(pLeft) || ExprAlwaysFalse(pRight) ){ - pExpr = pExpr->op==TK_AND ? pRight : pLeft; - }else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){ - pExpr = pExpr->op==TK_AND ? pLeft : pRight; - } - } - return pExpr; -} - -/* -** pExpr is a TK_FUNCTION node. Try to determine whether or not the -** function is a constant function. A function is constant if all of -** the following are true: -** -** (1) It is a scalar function (not an aggregate or window function) -** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG -** property. -** (3) All of its arguments are constants -** -** This routine sets pWalker->eCode to 0 if pExpr is not a constant. -** It makes no changes to pWalker->eCode if pExpr is constant. In -** every case, it returns WRC_Abort. -** -** Called as a service subroutine from exprNodeIsConstant(). -*/ -static SQLITE_NOINLINE int exprNodeIsConstantFunction( - Walker *pWalker, - Expr *pExpr -){ - int n; /* Number of arguments */ - ExprList *pList; /* List of arguments */ - FuncDef *pDef; /* The function */ - sqlite3 *db; /* The database */ - - assert( pExpr->op==TK_FUNCTION ); - if( ExprHasProperty(pExpr, EP_TokenOnly) - || (pList = pExpr->x.pList)==0 - ){; - n = 0; - }else{ - n = pList->nExpr; - sqlite3WalkExprList(pWalker, pList); - if( pWalker->eCode==0 ) return WRC_Abort; - } - db = pWalker->pParse->db; - pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); - if( pDef==0 - || pDef->xFinalize!=0 - || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || ExprHasProperty(pExpr, EP_WinFunc) - ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Prune; -} - /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The ** Walker.eCode value determines the type of "constant" we are looking @@ -111956,106 +93192,89 @@ ** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5 ** ** In all cases, the callbacks set Walker.eCode=0 and abort if the expression ** is found to not be a constant. ** -** The sqlite3ExprIsConstantOrFunction() is used for evaluating DEFAULT -** expressions in a CREATE TABLE statement. The Walker.eCode value is 5 -** when parsing an existing schema out of the sqlite_schema table and 4 -** when processing a new CREATE TABLE statement. A bound parameter raises -** an error for new statements, but is silently converted -** to NULL for existing schemas. This allows sqlite_schema tables that +** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions +** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing +** an existing schema and 4 when processing a new statement. A bound +** parameter raises an error for new statements, but is silently converted +** to NULL for existing schemas. This allows sqlite_master tables that ** contain a bound parameter because they were generated by older versions ** of SQLite to be parsed by newer versions of SQLite without raising a ** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ - assert( pWalker->eCode>0 ); /* If pWalker->eCode is 2 then any term of the expression that comes from - ** the ON or USING clauses of an outer join disqualifies the expression + ** the ON or USING clauses of a left join disqualifies the expression ** from being considered constant. */ - if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){ + if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){ pWalker->eCode = 0; return WRC_Abort; } switch( pExpr->op ){ /* Consider functions to be constant if all their arguments are constant ** and either pWalker->eCode==4 or 5 or the function has the ** SQLITE_FUNC_CONST flag. */ case TK_FUNCTION: - if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc)) - && !ExprHasProperty(pExpr, EP_WinFunc) - ){ - if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL); + if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ return WRC_Continue; - }else if( pWalker->pParse ){ - return exprNodeIsConstantFunction(pWalker, pExpr); }else{ pWalker->eCode = 0; return WRC_Abort; } case TK_ID: - /* Convert "true" or "false" in a DEFAULT clause into the - ** appropriate TK_TRUEFALSE operator */ - if( sqlite3ExprIdToTrueFalse(pExpr) ){ - return WRC_Prune; - } - /* no break */ deliberate_fall_through case TK_COLUMN: case TK_AGG_FUNCTION: case TK_AGG_COLUMN: testcase( pExpr->op==TK_ID ); testcase( pExpr->op==TK_COLUMN ); testcase( pExpr->op==TK_AGG_FUNCTION ); testcase( pExpr->op==TK_AGG_COLUMN ); - if( ExprHasProperty(pExpr, EP_FixedCol) && pWalker->eCode!=2 ){ - return WRC_Continue; - } if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ return WRC_Continue; } - /* no break */ deliberate_fall_through + /* Fall through */ case TK_IF_NULL_ROW: - case TK_REGISTER: - case TK_DOT: - case TK_RAISE: - testcase( pExpr->op==TK_REGISTER ); testcase( pExpr->op==TK_IF_NULL_ROW ); - testcase( pExpr->op==TK_DOT ); - testcase( pExpr->op==TK_RAISE ); pWalker->eCode = 0; return WRC_Abort; case TK_VARIABLE: if( pWalker->eCode==5 ){ /* Silently convert bound parameters that appear inside of CREATE ** statements into a NULL when parsing the CREATE statement text out - ** of the sqlite_schema table */ + ** of the sqlite_master table */ pExpr->op = TK_NULL; }else if( pWalker->eCode==4 ){ /* A bound parameter in a CREATE statement that originates from ** sqlite3_prepare() causes an error */ pWalker->eCode = 0; return WRC_Abort; } - /* no break */ deliberate_fall_through + /* Fall through */ default: - testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ - testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ + testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ + testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ return WRC_Continue; } } -static int exprIsConst(Parse *pParse, Expr *p, int initFlag){ +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; w.eCode = initFlag; - w.pParse = pParse; w.xExprCallback = exprNodeIsConstant; - w.xSelectCallback = sqlite3SelectWalkFail; + w.xSelectCallback = selectNodeIsConstant; #ifdef SQLITE_DEBUG w.xSelectCallback2 = sqlite3SelectWalkAssert2; #endif + w.u.iCur = iCur; sqlite3WalkExpr(&w, p); return w.eCode; } /* @@ -112063,156 +93282,33 @@ ** and 0 if it involves variables or function calls. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. -** -** The pParse parameter may be NULL. But if it is NULL, there is no way -** to determine if function calls are constant or not, and hence all -** function calls will be considered to be non-constant. If pParse is -** not NULL, then a function call might be constant, depending on the -** function and on its parameters. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 1); -} - -/* -** Walk an expression tree. Return non-zero if -** -** (1) the expression is constant, and -** (2) the expression does originate in the ON or USING clause -** of a LEFT JOIN, and -** (3) the expression does not contain any EP_FixedCol TK_COLUMN -** operands created by the constant propagation optimization. -** -** When this routine returns true, it indicates that the expression -** can be added to the pParse->pConstExpr list and evaluated once when -** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). -*/ -static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 2); -} - -/* -** This routine examines sub-SELECT statements as an expression is being -** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered -** constant as long as they are uncorrelated - meaning that they do not -** contain any terms from outer contexts. -*/ -static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){ - assert( pSelect!=0 ); - assert( pWalker->eCode==3 || pWalker->eCode==0 ); - if( (pSelect->selFlags & SF_Correlated)!=0 ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Prune; +*/ +SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){ + return exprIsConst(p, 1, 0); +} + +/* +** Walk an expression tree. Return non-zero if the expression is constant +** that does no originate from the ON or USING clauses of a join. +** Return 0 if it involves variables or function calls or terms from +** an ON or USING clause. +*/ +SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ + return exprIsConst(p, 2, 0); } /* ** Walk an expression tree. Return non-zero if the expression is constant ** for any single row of the table with cursor iCur. In other words, the ** expression must not refer to any non-deterministic function nor any ** table other than iCur. -** -** Consider uncorrelated subqueries to be constants if the bAllowSubq -** parameter is true. -*/ -static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){ - Walker w; - w.eCode = 3; - w.pParse = 0; - w.xExprCallback = exprNodeIsConstant; - if( bAllowSubq ){ - w.xSelectCallback = exprSelectWalkTableConstant; - }else{ - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - } - w.u.iCur = iCur; - sqlite3WalkExpr(&w, p); - return w.eCode; -} - -/* -** Check pExpr to see if it is an constraint on the single data source -** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr -** constrains pSrc but does not depend on any other tables or data -** sources anywhere else in the query. Return true (non-zero) if pExpr -** is a constraint on pSrc only. -** -** This is an optimization. False negatives will perhaps cause slower -** queries, but false positives will yield incorrect answers. So when in -** doubt, return 0. -** -** To be an single-source constraint, the following must be true: -** -** (1) pExpr cannot refer to any table other than pSrc->iCursor. -** -** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is -** true and the subquery is non-correlated -** -** (2b) pExpr cannot use non-deterministic functions. -** -** (3) pSrc cannot be part of the left operand for a RIGHT JOIN. -** (Is there some way to relax this constraint?) -** -** (4) If pSrc is the right operand of a LEFT JOIN, then... -** (4a) pExpr must come from an ON clause.. -** (4b) and specifically the ON clause associated with the LEFT JOIN. -** -** (5) If pSrc is the right operand of a LEFT JOIN or the left -** operand of a RIGHT JOIN, then pExpr must be from the WHERE -** clause, not an ON clause. -** -** (6) Either: -** -** (6a) pExpr does not originate in an ON or USING clause, or -** -** (6b) The ON or USING clause from which pExpr is derived is -** not to the left of a RIGHT JOIN (or FULL JOIN). -** -** Without this restriction, accepting pExpr as a single-table -** constraint might move the the ON/USING filter expression -** from the left side of a RIGHT JOIN over to the right side, -** which leads to incorrect answers. See also restriction (9) -** on push-down. -*/ -SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint( - Expr *pExpr, /* The constraint */ - const SrcList *pSrcList, /* Complete FROM clause */ - int iSrc, /* Which element of pSrcList to use */ - int bAllowSubq /* Allow non-correlated subqueries */ -){ - const SrcItem *pSrc = &pSrcList->a[iSrc]; - if( pSrc->fg.jointype & JT_LTORJ ){ - return 0; /* rule (3) */ - } - if( pSrc->fg.jointype & JT_LEFT ){ - if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (4a) */ - if( pExpr->w.iJoin!=pSrc->iCursor ) return 0; /* rule (4b) */ - }else{ - if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */ - } - if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) /* (6a) */ - && (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (6b) */ - ){ - int jj; - for(jj=0; jjw.iJoin==pSrcList->a[jj].iCursor ){ - if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){ - return 0; /* restriction (6) */ - } - break; - } - } - } - /* Rules (1), (2a), and (2b) handled by the following: */ - return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq); +*/ +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ + return exprIsConst(p, 3, iCur); } /* ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy(). @@ -112224,29 +93320,29 @@ /* 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( sqlite3IsBinary(pColl) ){ + CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p); + if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){ return WRC_Prune; } } } /* Check if pExpr is a sub-select. If so, consider it variable. */ - if( ExprUseXSelect(pExpr) ){ + 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 +** 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 @@ -112271,33 +93367,21 @@ sqlite3WalkExpr(&w, p); return w.eCode; } /* -** Walk an expression tree for the DEFAULT field of a column definition -** in a CREATE TABLE statement. Return non-zero if the expression is -** acceptable for use as a DEFAULT. That is to say, return non-zero if -** the expression is constant or a function call with constant arguments. -** Return and 0 if there are any variables. -** -** isInit is true when parsing from sqlite_schema. isInit is false when -** processing a new CREATE TABLE statement. When isInit is true, parameters -** (such as ? or $abc) in the expression are converted into NULL. When -** isInit is false, parameters raise an error. Parameters should not be -** allowed in a CREATE TABLE statement, but some legacy versions of SQLite -** allowed it, so we need to support it when reading sqlite_schema for -** backwards compatibility. -** -** If isInit is true, set EP_FromDDL on every TK_FUNCTION node. +** Walk an expression tree. Return non-zero if the expression is constant +** or a function call with constant arguments. Return and 0 if there +** are any variables. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); - return exprIsConst(0, p, 4+isInit); + return exprIsConst(p, 4+isInit, 0); } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* ** Walk an expression tree. Return 1 if the expression contains a @@ -112305,11 +93389,11 @@ */ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){ Walker w; w.eCode = 1; w.xExprCallback = sqlite3ExprWalkNoop; - w.xSelectCallback = sqlite3SelectWalkFail; + w.xSelectCallback = selectNodeIsConstant; #ifdef SQLITE_DEBUG w.xSelectCallback2 = sqlite3SelectWalkAssert2; #endif sqlite3WalkExpr(&w, p); return w.eCode==0; @@ -112319,18 +93403,14 @@ /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. -** -** If the pParse pointer is provided, then allow the expression p to be -** a parameter (TK_VARIABLE) that is bound to an integer. -** But if pParse is NULL, then p must be a pure integer literal. */ -SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){ +SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; - if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */ + 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 */ assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0 || sqlite3GetInt32(p->u.zToken, &rc)==0 ); @@ -112339,40 +93419,20 @@ *pValue = p->u.iValue; return 1; } switch( p->op ){ case TK_UPLUS: { - rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0); + rc = sqlite3ExprIsInteger(p->pLeft, pValue); break; } case TK_UMINUS: { - int v = 0; - if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){ - assert( ((unsigned int)v)!=0x80000000 ); + int v; + if( sqlite3ExprIsInteger(p->pLeft, &v) ){ + assert( v!=(-2147483647-1) ); *pValue = -v; rc = 1; } - break; - } - case TK_VARIABLE: { - sqlite3_value *pVal; - if( pParse==0 ) break; - if( NEVER(pParse->pVdbe==0) ) break; - if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break; - sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn); - pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn, - SQLITE_AFF_BLOB); - if( pVal ){ - if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){ - sqlite3_int64 vv = sqlite3_value_int64(pVal); - if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */ - *pValue = (int)vv; - rc = 1; - } - } - sqlite3ValueFree(pVal); - } break; } default: break; } return rc; @@ -112380,11 +93440,11 @@ /* ** Return FALSE if there is no chance that the expression can be NULL. ** ** If the expression might be NULL or if the expression is too complex -** to tell return TRUE. +** to tell return TRUE. ** ** This routine is used as an optimization, to skip OP_IsNull opcodes ** when we know that a value cannot be NULL. Hence, a false positive ** (returning TRUE when in fact the expression can never be NULL) might ** be a small performance hit but is otherwise harmless. On the other @@ -112392,34 +93452,23 @@ ** will likely result in an incorrect answer. So when in doubt, return ** TRUE. */ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ u8 op; - assert( p!=0 ); - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ - p = p->pLeft; - assert( p!=0 ); - } + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } op = p->op; if( op==TK_REGISTER ) op = p->op2; switch( op ){ case TK_INTEGER: case TK_STRING: case TK_FLOAT: case TK_BLOB: return 0; case TK_COLUMN: - assert( ExprUseYTab(p) ); - return ExprHasProperty(p, EP_CanBeNull) - || NEVER(p->y.pTab==0) /* Reference to column of index on expr */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - || (p->iColumn==XN_ROWID && IsView(p->y.pTab)) -#endif - || (p->iColumn>=0 - && p->y.pTab->aCol!=0 /* Possible due to prior error */ - && ALWAYS(p->iColumny.pTab->nCol) - && p->y.pTab->aCol[p->iColumn].notNull==0); + assert( p->pTab!=0 ); + return ExprHasProperty(p, EP_CanBeNull) || + (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); default: return 1; } } @@ -112433,34 +93482,31 @@ ** is harmless. A false positive, however, can result in the wrong ** answer. */ SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ u8 op; - int unaryMinus = 0; if( aff==SQLITE_AFF_BLOB ) return 1; - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ - if( p->op==TK_UMINUS ) unaryMinus = 1; - p = p->pLeft; - } + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } op = p->op; if( op==TK_REGISTER ) op = p->op2; switch( op ){ case TK_INTEGER: { - return aff>=SQLITE_AFF_NUMERIC; + return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC; } case TK_FLOAT: { - return aff>=SQLITE_AFF_NUMERIC; + return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC; } case TK_STRING: { - return !unaryMinus && aff==SQLITE_AFF_TEXT; + return aff==SQLITE_AFF_TEXT; } case TK_BLOB: { - return !unaryMinus; + return 1; } case TK_COLUMN: { assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */ - return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0; + return p->iColumn<0 + && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC); } default: { return 0; } } @@ -112475,45 +93521,24 @@ if( sqlite3StrICmp(z, "OID")==0 ) return 1; return 0; } /* -** Return a pointer to a buffer containing a usable rowid alias for table -** pTab. An alias is usable if there is not an explicit user-defined column -** of the same name. -*/ -SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab){ - const char *azOpt[] = {"_ROWID_", "ROWID", "OID"}; - int ii; - assert( VisibleRowid(pTab) ); - for(ii=0; iinCol; iCol++){ - if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break; - } - if( iCol==pTab->nCol ){ - return azOpt[ii]; - } - } - return 0; -} - -/* -** pX is the RHS of an IN operator. If pX is a SELECT statement +** pX is the RHS of an IN operator. If pX is a SELECT statement ** that can be simplified to a direct table access, then return ** a pointer to the SELECT statement. If pX is not a SELECT statement, -** or if the SELECT statement needs to be materialized into a transient +** or if the SELECT statement needs to be manifested into a transient ** table, then return NULL. */ #ifndef SQLITE_OMIT_SUBQUERY -static Select *isCandidateForInOpt(const Expr *pX){ +static Select *isCandidateForInOpt(Expr *pX){ Select *p; SrcList *pSrc; ExprList *pEList; Table *pTab; int i; - if( !ExprUseXSelect(pX) ) return 0; /* Not a subquery */ + if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ p = pX->x.pSelect; if( p->pPrior ) return 0; /* Not a compound SELECT */ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); @@ -112520,18 +93545,19 @@ testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); return 0; /* No DISTINCT keyword and no aggregate functions */ } 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 ); if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ - if( pSrc->a[0].fg.isSubquery) return 0;/* FROM is not a subquery or view */ - pTab = pSrc->a[0].pSTab; + if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ + pTab = pSrc->a[0].pTab; assert( pTab!=0 ); - assert( !IsView(pTab) ); /* FROM clause is not a view */ + assert( pTab->pSelect==0 ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; assert( pEList!=0 ); /* All SELECT results must be columns. */ for(i=0; inExpr; i++){ @@ -112562,20 +93588,20 @@ #endif #ifndef SQLITE_OMIT_SUBQUERY /* -** The argument is an IN operator with a list (not a subquery) on the +** The argument is an IN operator with a list (not a subquery) on the ** right-hand side. Return TRUE if that list is constant. */ -static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){ +static int sqlite3InRhsIsConstant(Expr *pIn){ Expr *pLHS; int res; assert( !ExprHasProperty(pIn, EP_xIsSelect) ); pLHS = pIn->pLeft; pIn->pLeft = 0; - res = sqlite3ExprIsConstant(pParse, pIn); + res = sqlite3ExprIsConstant(pIn); pIn->pLeft = pLHS; return res; } #endif @@ -112587,19 +93613,19 @@ ** The job of this routine is to find or create a b-tree object that can ** be used either to test for membership in the RHS set or to iterate through ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that is the RHS of the IN operator -** and the *piTab parameter is set to the index of that cursor. +** and pX->iTable is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** ** IN_INDEX_ROWID - The cursor was opened on a database table. ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. ** IN_INDEX_EPH - The cursor was opened on a specially created and -** populated ephemeral table. +** populated epheremal table. ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be ** implemented as a sequence of comparisons. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: @@ -112607,30 +93633,28 @@ ** SELECT , ... FROM ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then ** pX->iTable made to point to the ephemeral table instead of an -** existing table. In this case, the creation and initialization of the -** ephemeral table might be put inside of a subroutine, the EP_Subrtn flag -** will be set on pX and the pX->y.sub fields will be set to show where -** the subroutine is coded. +** existing table. ** -** 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. +** 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. ** ** 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 ephemeral table will be created unless the selected columns are guaranteed +** An epheremal table must be used 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. ** -** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used -** for fast set membership tests) then an ephemeral table must -** be used unless is a single INTEGER PRIMARY KEY column or an +** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used +** for fast set membership tests) then an epheremal table must +** be used unless is a single INTEGER PRIMARY KEY column or an ** index can be found with the specified as its left-most. ** ** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and ** if the RHS of the IN operator is a list (not a subquery) then this ** routine might decide that creating an ephemeral b-tree for membership @@ -112638,11 +93662,11 @@ ** calling routine should implement the IN operator using a sequence ** of Eq or Ne comparison operations. ** ** When the b-tree is being used for membership tests, the calling function ** might need to know whether or not the RHS side of the IN operator -** contains a NULL. If prRhsHasNull is not a NULL pointer and +** contains a NULL. If prRhsHasNull is not a NULL pointer and ** if there is any chance that the (...) might contain a NULL value at ** runtime, then a register is allocated and the register number written ** to *prRhsHasNull. If there is no chance that the (...) contains a ** NULL value, then *prRhsHasNull is left unchanged. ** @@ -112663,32 +93687,30 @@ ** then aiMap[] is populated with {2, 0, 1}. */ #ifndef SQLITE_OMIT_SUBQUERY SQLITE_PRIVATE int sqlite3FindInIndex( Parse *pParse, /* Parsing context */ - Expr *pX, /* The IN expression */ + Expr *pX, /* The right-hand side (RHS) of the IN operator */ u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */ int *prRhsHasNull, /* Register holding NULL status. See notes */ - int *aiMap, /* Mapping from Index fields to RHS fields */ - int *piTab /* OUT: index to use */ + int *aiMap /* Mapping from Index fields to RHS fields */ ){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ - int iTab; /* Cursor of the RHS table */ + int iTab = pParse->nTab++; /* Cursor of the RHS table */ int mustBeUnique; /* True if RHS must be unique */ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; - iTab = pParse->nTab++; - /* If the RHS of this IN(...) operator is a SELECT, and if it matters + /* If the RHS of this IN(...) operator is a SELECT, and if it matters ** whether or not the SELECT result contains NULL values, check whether - ** or not NULL is actually possible (it may not be, for example, due + ** or not NULL is actually possible (it may not be, for example, due ** to NOT NULL constraints in the schema). If no NULL values are possible, ** set prRhsHasNull to 0 before continuing. */ - if( prRhsHasNull && ExprUseXSelect(pX) ){ + if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){ int i; ExprList *pEList = pX->x.pSelect->pEList; for(i=0; inExpr; i++){ if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break; } @@ -112696,27 +93718,26 @@ prRhsHasNull = 0; } } /* Check to see if an existing table or index can be used to - ** satisfy the query. This is preferable to generating a new + ** satisfy the query. This is preferable to generating a new ** ephemeral table. */ if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table
                . */ - int iDb; /* Database idx for pTab */ + i16 iDb; /* Database idx for pTab */ ExprList *pEList = p->pEList; int nExpr = pEList->nExpr; assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ - pTab = p->pSrc->a[0].pSTab; + pTab = p->pSrc->a[0].pTab; /* Code an OP_Transaction and OP_TableLock for
                . */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 && iDbtnum, 0, pTab->zName); assert(v); /* sqlite3GetVdbe() has always been previously called */ if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ @@ -112724,19 +93745,18 @@ int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); eType = IN_INDEX_ROWID; - ExplainQueryPlan((pParse, 0, - "USING ROWID SEARCH ON TABLE %s FOR IN-OPERATOR",pTab->zName)); + sqlite3VdbeJumpHere(v, iAddr); }else{ Index *pIdx; /* Iterator variable */ int affinity_ok = 1; int i; - /* Check that the affinity that will be used to perform each + /* Check that the affinity that will be used to perform each ** comparison is the same as the affinity of each column in table ** on the RHS of the IN operator. If it not, it is not possible to ** use any index of the RHS table. */ for(i=0; ipLeft, i); @@ -112764,11 +93784,10 @@ /* Search for an existing index that will work for this IN operator */ for(pIdx=pTab->pIndex; pIdx && eType==0; pIdx=pIdx->pNext){ Bitmask colUsed; /* Columns of the index used */ Bitmask mCol; /* Mask for the current column */ if( pIdx->nColumnpPartIdxWhere!=0 ) continue; /* Maximum nColumn is BMS-2, not BMS-1, so that we can compute ** BITMASK(nExpr) without overflowing */ testcase( pIdx->nColumn==BMS-2 ); testcase( pIdx->nColumn==BMS-1 ); if( pIdx->nColumn>=BMS-1 ) continue; @@ -112777,18 +93796,19 @@ ||(pIdx->nColumn>nExpr && !IsUniqueIndex(pIdx)) ){ continue; /* This index is not unique over the IN RHS columns */ } } - + colUsed = 0; /* Columns of index used so far */ for(i=0; ipLeft, i); Expr *pRhs = pEList->a[i].pExpr; CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; - + + assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; assert( pIdx->azColl[j] ); if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ continue; @@ -112799,28 +93819,30 @@ mCol = MASKBIT(j); if( mCol & colUsed ) break; /* Each column used only once */ colUsed |= mCol; if( aiMap ) aiMap[i] = j; } - - assert( nExpr>0 && nExprzName)); +#ifndef SQLITE_OMIT_EXPLAIN + sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, + sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), + P4_DYNAMIC); +#endif sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - + if( prRhsHasNull ){ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK i64 mask = (1<nMem; if( nExpr==1 ){ sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); @@ -112840,15 +93862,13 @@ ** then it is not worth creating an ephemeral table to evaluate ** the IN operator so return IN_INDEX_NOOP. */ if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) - && ExprUseXList(pX) - && (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2) + && !ExprHasProperty(pX, EP_xIsSelect) + && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) ){ - pParse->nTab--; /* Back out the allocation of the unused cursor */ - iTab = -1; /* Cursor is not allocated */ eType = IN_INDEX_NOOP; } if( eType==0 ){ /* Could not find an existing table or index to use as the RHS b-tree. @@ -112857,44 +93877,44 @@ u32 savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; eType = IN_INDEX_EPH; if( inFlags & IN_INDEX_LOOP ){ pParse->nQueryLoop = 0; + if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){ + eType = IN_INDEX_ROWID; + } }else if( prRhsHasNull ){ *prRhsHasNull = rMayHaveNull = ++pParse->nMem; } - assert( pX->op==TK_IN ); - sqlite3CodeRhsOfIN(pParse, pX, iTab); - if( rMayHaveNull ){ - sqlite3SetHasNullFlag(v, iTab, rMayHaveNull); - } + sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); pParse->nQueryLoop = savedNQueryLoop; + }else{ + pX->iTable = iTab; } if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){ int i, n; n = sqlite3ExprVectorSize(pX->pLeft); for(i=0; ipLeft; int nVal = sqlite3ExprVectorSize(pLeft); - Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0; + Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; char *zRet; assert( pExpr->op==TK_IN ); zRet = sqlite3DbMallocRaw(pParse->db, nVal+1); if( zRet ){ @@ -112914,395 +93934,86 @@ } #endif #ifndef SQLITE_OMIT_SUBQUERY /* -** Load the Parse object passed as the first argument with an error +** Load the Parse object passed as the first argument with an error ** message of the form: ** ** "sub-select returns N columns - expected M" -*/ +*/ SQLITE_PRIVATE void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){ - if( pParse->nErr==0 ){ - const char *zFmt = "sub-select returns %d columns - expected %d"; - sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect); - } + const char *zFmt = "sub-select returns %d columns - expected %d"; + sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect); } #endif /* ** Expression pExpr is a vector that has been used in a context where -** it is not permitted. If pExpr is a sub-select vector, this routine +** it is not permitted. If pExpr is a sub-select vector, this routine ** loads the Parse object with a message of the form: ** ** "sub-select returns N columns - expected 1" ** ** Or, if it is a regular scalar vector: ** ** "row value misused" -*/ +*/ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ #ifndef SQLITE_OMIT_SUBQUERY - if( ExprUseXSelect(pExpr) ){ + if( pExpr->flags & EP_xIsSelect ){ sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1); }else #endif { sqlite3ErrorMsg(pParse, "row value misused"); } } -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Scan all previously generated bytecode looking for an OP_BeginSubrtn -** that is compatible with pExpr. If found, add the y.sub values -** to pExpr and return true. If not found, return false. -*/ -static int findCompatibleInRhsSubrtn( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* IN operator with RHS that we want to reuse */ - SubrtnSig *pNewSig /* Signature for the IN operator */ -){ - VdbeOp *pOp, *pEnd; - SubrtnSig *pSig; - Vdbe *v; - - if( pNewSig==0 ) return 0; - if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0; - assert( pExpr->op==TK_IN ); - assert( !ExprUseYSub(pExpr) ); - assert( ExprUseXSelect(pExpr) ); - assert( pExpr->x.pSelect!=0 ); - assert( (pExpr->x.pSelect->selFlags & SF_All)==0 ); - v = pParse->pVdbe; - assert( v!=0 ); - pOp = sqlite3VdbeGetOp(v, 1); - pEnd = sqlite3VdbeGetLastOp(v); - for(; pOpp4type!=P4_SUBRTNSIG ) continue; - assert( pOp->opcode==OP_BeginSubrtn ); - pSig = pOp->p4.pSubrtnSig; - assert( pSig!=0 ); - if( !pSig->bComplete ) continue; - if( pNewSig->selId!=pSig->selId ) continue; - if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue; - pExpr->y.sub.iAddr = pSig->iAddr; - pExpr->y.sub.regReturn = pSig->regReturn; - pExpr->iTable = pSig->iTable; - ExprSetProperty(pExpr, EP_Subrtn); - return 1; - } - return 0; -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code that will construct an ephemeral table containing all terms -** in the RHS of an IN operator. The IN operator can be in either of two -** forms: -** +/* +** Generate code for scalar subqueries used as a subquery expression, EXISTS, +** or IN operators. Examples: +** +** (SELECT a FROM b) -- subquery +** EXISTS (SELECT a FROM b) -- EXISTS subquery ** x IN (4,5,11) -- IN operator with list on right-hand side ** x IN (SELECT a FROM b) -- IN operator with subquery on the right ** -** The pExpr parameter is the IN operator. The cursor number for the -** constructed ephemeral table is returned. The first time the ephemeral -** table is computed, the cursor number is also stored in pExpr->iTable, -** however the cursor number returned might not be the same, as it might -** have been duplicated using OP_OpenDup. -** -** If the LHS expression ("x" in the examples) is a column value, or -** the SELECT statement returns a column value, then the affinity of that -** column is used to build the index keys. If both 'x' and the -** SELECT... statement are columns, then numeric affinity is used -** if either column has NUMERIC or INTEGER affinity. If neither -** 'x' nor the SELECT... statement are columns, then numeric affinity -** is used. -*/ -SQLITE_PRIVATE void sqlite3CodeRhsOfIN( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The IN operator */ - int iTab /* Use this cursor number */ -){ - int addrOnce = 0; /* Address of the OP_Once instruction at top */ - int addr; /* Address of OP_OpenEphemeral instruction */ - Expr *pLeft; /* the LHS of the IN operator */ - KeyInfo *pKeyInfo = 0; /* Key information */ - int nVal; /* Size of vector pLeft */ - Vdbe *v; /* The prepared statement under construction */ - SubrtnSig *pSig = 0; /* Signature for this subroutine */ - - v = pParse->pVdbe; - assert( v!=0 ); - - /* The evaluation of the IN must be repeated every time it - ** is encountered if any of the following is true: - ** - ** * The right-hand side is a correlated subquery - ** * The right-hand side is an expression list containing variables - ** * We are inside a trigger - ** - ** If all of the above are false, then we can compute the RHS just once - ** and reuse it many names. - */ - if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){ - /* Reuse of the RHS is allowed - ** - ** Compute a signature for the RHS of the IN operator to facility - ** finding and reusing prior instances of the same IN operator. - */ - assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 ); - if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){ - pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0])); - if( pSig ){ - pSig->selId = pExpr->x.pSelect->selId; - pSig->zAff = exprINAffinity(pParse, pExpr); - } - } - - /* Check to see if there is a prior materialization of the RHS of - ** this IN operator. If there is, then make use of that prior - ** materialization rather than recomputing it. - */ - if( ExprHasProperty(pExpr, EP_Subrtn) - || findCompatibleInRhsSubrtn(pParse, pExpr, pSig) - ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - if( ExprUseXSelect(pExpr) ){ - ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d", - pExpr->x.pSelect->selId)); - } - assert( ExprUseYSub(pExpr) ); - sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr); - assert( iTab!=pExpr->iTable ); - sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable); - sqlite3VdbeJumpHere(v, addrOnce); - if( pSig ){ - sqlite3DbFree(pParse->db, pSig->zAff); - sqlite3DbFree(pParse->db, pSig); - } - return; - } - - /* Begin coding the subroutine */ - assert( !ExprUseYWin(pExpr) ); - ExprSetProperty(pExpr, EP_Subrtn); - assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); - pExpr->y.sub.regReturn = ++pParse->nMem; - pExpr->y.sub.iAddr = - sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1; - if( pSig ){ - pSig->bComplete = 0; - pSig->iAddr = pExpr->y.sub.iAddr; - pSig->regReturn = pExpr->y.sub.regReturn; - pSig->iTable = iTab; - pParse->mSubrtnSig = 1 << (pSig->selId&7); - sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG); - } - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - - /* Check to see if this is a vector IN operator */ - pLeft = pExpr->pLeft; - nVal = sqlite3ExprVectorSize(pLeft); - - /* Construct the ephemeral table that will contain the content of - ** RHS of the IN operator. - */ - pExpr->iTable = iTab; - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal); -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - if( ExprUseXSelect(pExpr) ){ - VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId)); - }else{ - VdbeComment((v, "RHS of IN operator")); - } -#endif - pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1); - - if( ExprUseXSelect(pExpr) ){ - /* Case 1: expr IN (SELECT ...) - ** - ** Generate code to write the results of the select into the temporary - ** table allocated and opened above. - */ - Select *pSelect = pExpr->x.pSelect; - ExprList *pEList = pSelect->pEList; - - ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d", - addrOnce?"":"CORRELATED ", pSelect->selId - )); - /* If the LHS and RHS of the IN operator do not match, that - ** error will have been caught long before we reach this point. */ - if( ALWAYS(pEList->nExpr==nVal) ){ - Select *pCopy; - SelectDest dest; - int i; - int rc; - int addrBloom = 0; - sqlite3SelectDestInit(&dest, SRT_Set, iTab); - dest.zAffSdst = exprINAffinity(pParse, pExpr); - pSelect->iLimit = 0; - if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ - int regBloom = ++pParse->nMem; - addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom); - VdbeComment((v, "Bloom filter")); - dest.iSDParm2 = regBloom; - } - testcase( pSelect->selFlags & SF_Distinct ); - testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ - pCopy = sqlite3SelectDup(pParse->db, pSelect, 0); - rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest); - sqlite3SelectDelete(pParse->db, pCopy); - sqlite3DbFree(pParse->db, dest.zAffSdst); - if( addrBloom ){ - sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2; - if( dest.iSDParm2==0 ){ - sqlite3VdbeChangeToNoop(v, addrBloom); - }else{ - sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2; - } - } - if( rc ){ - sqlite3KeyInfoUnref(pKeyInfo); - return; - } - assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ - assert( pEList!=0 ); - assert( pEList->nExpr>0 ); - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); - for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( - pParse, p, pEList->a[i].pExpr - ); - } - } - }else if( ALWAYS(pExpr->x.pList!=0) ){ - /* Case 2: expr IN (exprlist) - ** - ** For each expression, build an index key from the evaluation and - ** store it in the temporary table. If is a column, then use - ** that columns affinity when building index keys. If is not - ** a column, use numeric affinity. - */ - char affinity; /* Affinity of the LHS of the IN */ - int i; - ExprList *pList = pExpr->x.pList; - struct ExprList_item *pItem; - int r1, r2; - affinity = sqlite3ExprAffinity(pLeft); - if( affinity<=SQLITE_AFF_NONE ){ - affinity = SQLITE_AFF_BLOB; - }else if( affinity==SQLITE_AFF_REAL ){ - affinity = SQLITE_AFF_NUMERIC; - } - if( pKeyInfo ){ - assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); - pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - } - - /* Loop through each expression in . */ - r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3GetTempReg(pParse); - for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ - Expr *pE2 = pItem->pExpr; - - /* If the expression is not constant then we will need to - ** disable the test that was generated above that makes sure - ** this code only executes once. Because for a non-constant - ** expression we need to rerun this code each time. - */ - if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){ - sqlite3VdbeChangeToNoop(v, addrOnce-1); - sqlite3VdbeChangeToNoop(v, addrOnce); - ExprClearProperty(pExpr, EP_Subrtn); - addrOnce = 0; - } - - /* Evaluate the expression and insert it into the temp table */ - sqlite3ExprCode(pParse, pE2, r1); - sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1); - } - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } - if( pSig ) pSig->bComplete = 1; - if( pKeyInfo ){ - sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); - } - if( addrOnce ){ - sqlite3VdbeAddOp1(v, OP_NullRow, iTab); - sqlite3VdbeJumpHere(v, addrOnce); - /* Subroutine return */ - assert( ExprUseYSub(pExpr) ); - assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn - || pParse->nErr ); - sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr, 1); - VdbeCoverage(v); - sqlite3ClearTempRegCache(pParse); - } -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -/* -** Generate code for scalar subqueries used as a subquery expression -** or EXISTS operator: -** -** (SELECT a FROM b) -- subquery -** EXISTS (SELECT a FROM b) -- EXISTS subquery -** -** The pExpr parameter is the SELECT or EXISTS operator to be coded. -** -** Return the register that holds the result. For a multi-column SELECT, -** the result is stored in a contiguous array of registers and the -** return value is the register of the left-most result column. -** Return 0 if an error occurs. +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. +** +** If parameter isRowid is non-zero, then expression pExpr is guaranteed +** to be of the form " IN (?, ?, ?)", where is a reference +** to some integer key column of a table B-Tree. In this case, use an +** intkey B-Tree to store the set of IN(...) values instead of the usual +** (slower) variable length keys B-Tree. +** +** If rMayHaveNull is non-zero, that means that the operation is an IN +** (not a SELECT or EXISTS) and that the RHS might contains NULLs. +** All this routine does is initialize the register given by rMayHaveNull +** to NULL. Calling routines will take care of changing this register +** value to non-NULL if the RHS is NULL-free. +** +** For a SELECT or EXISTS operator, return the register that holds the +** result. For a multi-column SELECT, the result is stored in a contiguous +** array of registers and the return value is the register of the left-most +** result column. Return 0 for IN operators or if an error occurs. */ #ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ - int addrOnce = 0; /* Address of OP_Once at top of subroutine */ - int rReg = 0; /* Register storing resulting */ - Select *pSel; /* SELECT statement to encode */ - SelectDest dest; /* How to deal with SELECT result */ - int nReg; /* Registers to allocate */ - Expr *pLimit; /* New limit expression */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; /* Address of OP_Explain instruction */ -#endif - - Vdbe *v = pParse->pVdbe; - assert( v!=0 ); - if( pParse->nErr ) return 0; - testcase( pExpr->op==TK_EXISTS ); - testcase( pExpr->op==TK_SELECT ); - assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); - assert( ExprUseXSelect(pExpr) ); - pSel = pExpr->x.pSelect; - - /* If this routine has already been coded, then invoke it as a - ** subroutine. */ - if( ExprHasProperty(pExpr, EP_Subrtn) ){ - ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId)); - assert( ExprUseYSub(pExpr) ); - sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr); - return pExpr->iTable; - } - - /* Begin coding the subroutine */ - assert( !ExprUseYWin(pExpr) ); - assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) ); - ExprSetProperty(pExpr, EP_Subrtn); - pExpr->y.sub.regReturn = ++pParse->nMem; - pExpr->y.sub.iAddr = - sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1; - - /* The evaluation of the EXISTS/SELECT must be repeated every time it +SQLITE_PRIVATE int sqlite3CodeSubselect( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The IN, SELECT, or EXISTS operator */ + int rHasNullFlag, /* Register that records whether NULLs exist in RHS */ + int isRowid /* If true, LHS of IN operator is a rowid */ +){ + int jmpIfDynamic = -1; /* One-time test address */ + int rReg = 0; /* Register storing resulting */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( NEVER(v==0) ) return 0; + sqlite3ExprCachePush(pParse); + + /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it ** is encountered if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger @@ -113309,92 +94020,233 @@ ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - - /* For a SELECT, generate code to put the values for all columns of - ** the first row into an array of registers and return the index of - ** the first register. - ** - ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists) - ** into a register and return that register number. - ** - ** In both cases, the query is augmented with "LIMIT 1". Any - ** preexisting limit is discarded in place of the new LIMIT 1. - */ - ExplainQueryPlan2(addrExplain, (pParse, 1, "%sSCALAR SUBQUERY %d", - addrOnce?"":"CORRELATED ", pSel->selId)); - sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, -1); - nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; - sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); - pParse->nMem += nReg; - if( pExpr->op==TK_SELECT ){ - dest.eDest = SRT_Mem; - dest.iSdst = dest.iSDParm; - dest.nSdst = nReg; - sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1); - VdbeComment((v, "Init subquery result")); - }else{ - dest.eDest = SRT_Exists; - sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); - VdbeComment((v, "Init EXISTS result")); - } - if( pSel->pLimit ){ - /* The subquery already has a limit. If the pre-existing limit is X - ** then make the new limit X<>0 so that the new limit is either 1 or 0 */ - sqlite3 *db = pParse->db; - pLimit = sqlite3Expr(db, TK_INTEGER, "0"); - if( pLimit ){ - pLimit->affExpr = SQLITE_AFF_NUMERIC; - pLimit = sqlite3PExpr(pParse, TK_NE, - sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit); - } - sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft); - pSel->pLimit->pLeft = pLimit; - }else{ - /* If there is no pre-existing limit add a limit of 1 */ - pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); - pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); - } - pSel->iLimit = 0; - if( sqlite3Select(pParse, pSel, &dest) ){ - pExpr->op2 = pExpr->op; - pExpr->op = TK_ERROR; - return 0; - } - pExpr->iTable = rReg = dest.iSDParm; - ExprSetVVAProperty(pExpr, EP_NoReduce); - if( addrOnce ){ - sqlite3VdbeJumpHere(v, addrOnce); - } - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); - - /* Subroutine return */ - assert( ExprUseYSub(pExpr) ); - assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn - || pParse->nErr ); - sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn, - pExpr->y.sub.iAddr, 1); - VdbeCoverage(v); - sqlite3ClearTempRegCache(pParse); + jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } + +#ifndef SQLITE_OMIT_EXPLAIN + if( pParse->explain==2 ){ + char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d", + jmpIfDynamic>=0?"":"CORRELATED ", + pExpr->op==TK_IN?"LIST":"SCALAR", + pParse->iNextSelectId + ); + sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); + } +#endif + + switch( pExpr->op ){ + case TK_IN: { + int addr; /* Address of OP_OpenEphemeral instruction */ + Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ + KeyInfo *pKeyInfo = 0; /* Key information */ + int nVal; /* Size of vector pLeft */ + + nVal = sqlite3ExprVectorSize(pLeft); + assert( !isRowid || nVal==1 ); + + /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' + ** expression it is handled the same way. An ephemeral table is + ** filled with index keys representing the results from the + ** SELECT or the . + ** + ** If the 'x' expression is a column value, or the SELECT... + ** statement returns a column value, then the affinity of that + ** column is used to build the index keys. If both 'x' and the + ** SELECT... statement are columns, then numeric affinity is used + ** if either column has NUMERIC or INTEGER affinity. If neither + ** 'x' nor the SELECT... statement are columns, then numeric affinity + ** is used. + */ + pExpr->iTable = pParse->nTab++; + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, + pExpr->iTable, (isRowid?0:nVal)); + pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1); + + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + /* Case 1: expr IN (SELECT ...) + ** + ** Generate code to write the results of the select into the temporary + ** table allocated and opened above. + */ + Select *pSelect = pExpr->x.pSelect; + ExprList *pEList = pSelect->pEList; + + assert( !isRowid ); + /* If the LHS and RHS of the IN operator do not match, that + ** error will have been caught long before we reach this point. */ + if( ALWAYS(pEList->nExpr==nVal) ){ + SelectDest dest; + int i; + sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); + dest.zAffSdst = exprINAffinity(pParse, pExpr); + pSelect->iLimit = 0; + testcase( pSelect->selFlags & SF_Distinct ); + testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ + if( sqlite3Select(pParse, pSelect, &dest) ){ + sqlite3DbFree(pParse->db, dest.zAffSdst); + sqlite3KeyInfoUnref(pKeyInfo); + return 0; + } + sqlite3DbFree(pParse->db, dest.zAffSdst); + assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ + assert( pEList!=0 ); + assert( pEList->nExpr>0 ); + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); + for(i=0; iaColl[i] = sqlite3BinaryCompareCollSeq( + pParse, p, pEList->a[i].pExpr + ); + } + } + }else if( ALWAYS(pExpr->x.pList!=0) ){ + /* Case 2: expr IN (exprlist) + ** + ** For each expression, build an index key from the evaluation and + ** store it in the temporary table. If is a column, then use + ** that columns affinity when building index keys. If is not + ** a column, use numeric affinity. + */ + char affinity; /* Affinity of the LHS of the IN */ + int i; + ExprList *pList = pExpr->x.pList; + struct ExprList_item *pItem; + int r1, r2, r3; + + affinity = sqlite3ExprAffinity(pLeft); + if( !affinity ){ + affinity = SQLITE_AFF_BLOB; + } + if( pKeyInfo ){ + assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); + pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + } + + /* Loop through each expression in . */ + r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3GetTempReg(pParse); + if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2); + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ + Expr *pE2 = pItem->pExpr; + int iValToIns; + + /* If the expression is not constant then we will need to + ** disable the test that was generated above that makes sure + ** this code only executes once. Because for a non-constant + ** expression we need to rerun this code each time. + */ + if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, jmpIfDynamic); + jmpIfDynamic = -1; + } + + /* Evaluate the expression and insert it into the temp table */ + if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){ + sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); + }else{ + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); + if( isRowid ){ + sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, + sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); + } + } + } + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } + if( pKeyInfo ){ + sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); + } + break; + } + + case TK_EXISTS: + case TK_SELECT: + default: { + /* Case 3: (SELECT ... FROM ...) + ** or: EXISTS(SELECT ... FROM ...) + ** + ** For a SELECT, generate code to put the values for all columns of + ** the first row into an array of registers and return the index of + ** the first register. + ** + ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists) + ** into a register and return that register number. + ** + ** In both cases, the query is augmented with "LIMIT 1". Any + ** preexisting limit is discarded in place of the new LIMIT 1. + */ + Select *pSel; /* SELECT statement to encode */ + SelectDest dest; /* How to deal with SELECT result */ + int nReg; /* Registers to allocate */ + + testcase( pExpr->op==TK_EXISTS ); + testcase( pExpr->op==TK_SELECT ); + assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); + assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + + pSel = pExpr->x.pSelect; + nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; + sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); + pParse->nMem += nReg; + if( pExpr->op==TK_SELECT ){ + dest.eDest = SRT_Mem; + dest.iSdst = dest.iSDParm; + dest.nSdst = nReg; + sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1); + VdbeComment((v, "Init subquery result")); + }else{ + dest.eDest = SRT_Exists; + 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); + pSel->iLimit = 0; + pSel->selFlags &= ~SF_MultiValue; + if( sqlite3Select(pParse, pSel, &dest) ){ + return 0; + } + rReg = dest.iSDParm; + ExprSetVVAProperty(pExpr, EP_NoReduce); + break; + } + } + + if( rHasNullFlag ){ + sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag); + } + + if( jmpIfDynamic>=0 ){ + sqlite3VdbeJumpHere(v, jmpIfDynamic); + } + sqlite3ExprCachePop(pParse); + return rReg; } #endif /* SQLITE_OMIT_SUBQUERY */ #ifndef SQLITE_OMIT_SUBQUERY /* -** Expr pIn is an IN(...) expression. This function checks that the -** sub-select on the RHS of the IN() operator has the same number of -** columns as the vector on the LHS. Or, if the RHS of the IN() is not +** Expr pIn is an IN(...) expression. This function checks that the +** sub-select on the RHS of the IN() operator has the same number of +** columns as the vector on the LHS. Or, if the RHS of the IN() is not ** a sub-query, that the LHS is a vector of size 1. */ SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){ int nVector = sqlite3ExprVectorSize(pIn->pLeft); - if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){ + if( (pIn->flags & EP_xIsSelect) ){ if( nVector!=pIn->x.pSelect->pEList->nExpr ){ sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); return 1; } }else if( nVector!=1 ){ @@ -113410,22 +94262,22 @@ ** Generate code for an IN expression. ** ** x IN (SELECT ...) ** x IN (value, value, ...) ** -** The left-hand side (LHS) is a scalar or vector expression. The +** The left-hand side (LHS) is a scalar or vector expression. The ** right-hand side (RHS) is an array of zero or more scalar values, or a ** subquery. If the RHS is a subquery, the number of result columns must ** match the number of columns in the vector on the LHS. If the RHS is -** a list of values, the LHS must be a scalar. +** a list of values, the LHS must be a scalar. ** ** The IN operator is true if the LHS value is contained within the RHS. -** The result is false if the LHS is definitely not in the RHS. The -** result is NULL if the presence of the LHS in the RHS cannot be +** The result is false if the LHS is definitely not in the RHS. The +** result is NULL if the presence of the LHS in the RHS cannot be ** determined due to NULLs. ** -** This routine generates code that jumps to destIfFalse if the LHS is not +** This routine generates code that jumps to destIfFalse if the LHS is not ** contained within the RHS. If due to NULLs we cannot determine if the LHS ** is contained in the RHS then jump to destIfNull. If the LHS is contained ** within the RHS then fall through. ** ** See the separate in-operator.md documentation file in the canonical @@ -113450,36 +94302,34 @@ int i; /* loop counter */ int destStep2; /* Where to jump when NULLs seen in step 2 */ int destStep6 = 0; /* Start of code for Step 6 */ int addrTruthOp; /* Address of opcode that determines the IN is true */ int destNotNull; /* Jump here if a comparison is not true in step 6 */ - int addrTop; /* Top of the step-6 loop */ - int iTab = 0; /* Index to use */ - u8 okConstFactor = pParse->okConstFactor; + int addrTop; /* Top of the step-6 loop */ - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); pLeft = pExpr->pLeft; if( sqlite3ExprCheckIN(pParse, pExpr) ) return; zAff = exprINAffinity(pParse, pExpr); nVector = sqlite3ExprVectorSize(pExpr->pLeft); - aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int)); + aiMap = (int*)sqlite3DbMallocZero( + pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1 + ); if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error; /* Attempt to compute the RHS. After this step, if anything other than - ** IN_INDEX_NOOP is returned, the table opened with cursor iTab + ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned, ** the RHS has not yet been coded. */ v = pParse->pVdbe; assert( v!=0 ); /* OOM detected prior to this routine */ VdbeNoopComment((v, "begin IN expr")); eType = sqlite3FindInIndex(pParse, pExpr, IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, - destIfFalse==destIfNull ? 0 : &rRhsHasNull, - aiMap, &iTab); + destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap); assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH - || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC + || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC ); #ifdef SQLITE_DEBUG /* Confirm that aiMap[] contains nVector integer values between 0 and ** nVector-1. */ for(i=0; i from " IN (...)". If the LHS is a - ** vector, then it is stored in an array of nVector registers starting + /* Code the LHS, the from " IN (...)". If the LHS is a + ** vector, then it is stored in an array of nVector registers starting ** at r1. ** ** sqlite3FindInIndex() might have reordered the fields of the LHS vector ** so that the fields are in the same order as an existing index. The ** aiMap[] array contains a mapping from the original LHS field order to ** the field order that matches the RHS index. - ** - ** Avoid factoring the LHS of the IN(...) expression out of the loop, - ** even if it is constant, as OP_Affinity may be used on the register - ** by code generated below. */ - assert( pParse->okConstFactor==okConstFactor ); - pParse->okConstFactor = 0; + */ + sqlite3ExprCachePush(pParse); rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); - pParse->okConstFactor = okConstFactor; for(i=0; ix.pList; + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + int labelOk = sqlite3VdbeMakeLabel(v); int r2, regToFree; int regCkNull = 0; int ii; - assert( ExprUseXList(pExpr) ); - pList = pExpr->x.pList; - pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); } for(ii=0; iinExpr; ii++){ r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){ sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); } - sqlite3ReleaseTempReg(pParse, regToFree); if( iinExpr-1 || destIfNull!=destIfFalse ){ - int op = rLhs!=r2 ? OP_Eq : OP_NotNull; - sqlite3VdbeAddOp4(v, op, rLhs, labelOk, r2, + sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2, (void*)pColl, P4_COLLSEQ); - VdbeCoverageIf(v, iinExpr-1 && op==OP_Eq); - VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_Eq); - VdbeCoverageIf(v, iinExpr-1 && op==OP_NotNull); - VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_NotNull); + VdbeCoverageIf(v, iinExpr-1); + VdbeCoverageIf(v, ii==pList->nExpr-1); sqlite3VdbeChangeP5(v, zAff[0]); }else{ - int op = rLhs!=r2 ? OP_Ne : OP_IsNull; assert( destIfNull==destIfFalse ); - sqlite3VdbeAddOp4(v, op, rLhs, destIfFalse, r2, - (void*)pColl, P4_COLLSEQ); - VdbeCoverageIf(v, op==OP_Ne); - VdbeCoverageIf(v, op==OP_IsNull); + sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2, + (void*)pColl, P4_COLLSEQ); VdbeCoverage(v); sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL); } + sqlite3ReleaseTempReg(pParse, regToFree); } if( regCkNull ){ sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v); sqlite3VdbeGoto(v, destIfFalse); } @@ -113576,15 +94413,14 @@ ** We will then skip the binary search of the RHS. */ if( destIfNull==destIfFalse ){ destStep2 = destIfFalse; }else{ - destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse); + destStep2 = destStep6 = sqlite3VdbeMakeLabel(v); } for(i=0; ipLeft, i); - if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error; if( sqlite3ExprCanBeNull(p) ){ sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); VdbeCoverage(v); } } @@ -113595,32 +94431,23 @@ */ if( eType==IN_INDEX_ROWID ){ /* In this case, the RHS is the ROWID of table b-tree and so we also ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 ** into a single opcode. */ - sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs); + sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs); VdbeCoverage(v); addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */ }else{ sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); if( destIfFalse==destIfNull ){ /* Combine Step 3 and Step 5 into a single opcode */ - if( ExprHasProperty(pExpr, EP_Subrtn) ){ - const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr); - assert( pOp->opcode==OP_Once || pParse->nErr ); - if( pOp->opcode==OP_Once && pOp->p3>0 ){ - assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ); - sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse, - rLhs, nVector); VdbeCoverage(v); - } - } - sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse, + sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, rLhs, nVector); VdbeCoverage(v); goto sqlite3ExprCodeIN_finished; } /* Ordinary Step 3, for the case where FALSE and NULL are distinct */ - addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, iTab, 0, + addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rLhs, nVector); VdbeCoverage(v); } /* Step 4. If the RHS is known to be non-NULL and we did not find ** an match on the search above, then the result must be FALSE. @@ -113629,11 +94456,11 @@ sqlite3VdbeAddOp2(v, OP_NotNull, rRhsHasNull, destIfFalse); VdbeCoverage(v); } /* Step 5. If we do not care about the difference between NULL and - ** FALSE, then just return false. + ** FALSE, then just return false. */ if( destIfFalse==destIfNull ) sqlite3VdbeGoto(v, destIfFalse); /* Step 6: Loop through rows of the RHS. Compare each row to the LHS. ** If any comparison is NULL, then the result is NULL. If all @@ -113641,14 +94468,14 @@ ** ** For a scalar LHS, it is sufficient to check just the first row ** of the RHS. */ if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6); - addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse); + addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); VdbeCoverage(v); if( nVector>1 ){ - destNotNull = sqlite3VdbeMakeLabel(pParse); + destNotNull = sqlite3VdbeMakeLabel(v); }else{ /* For nVector==1, combine steps 6 and 7 by immediately returning ** FALSE if the first comparison is not NULL */ destNotNull = destIfFalse; } @@ -113656,20 +94483,20 @@ Expr *p; CollSeq *pColl; int r3 = sqlite3GetTempReg(pParse); p = sqlite3VectorFieldSubexpr(pLeft, i); pColl = sqlite3ExprCollSeq(pParse, p); - sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3); + sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, i, r3); sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3, (void*)pColl, P4_COLLSEQ); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r3); } sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); if( nVector>1 ){ sqlite3VdbeResolveLabel(v, destNotNull); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addrTop+1); + sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1); VdbeCoverage(v); /* Step 7: If we reach this point, we know that the result must ** be false. */ sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); @@ -113678,10 +94505,11 @@ /* Jumps here in order to return true. */ sqlite3VdbeJumpHere(v, addrTruthOp); sqlite3ExprCodeIN_finished: if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); + sqlite3ExprCachePop(pParse); VdbeComment((v, "end IN expr")); sqlite3ExprCodeIN_oom_error: sqlite3DbFree(pParse->db, aiMap); sqlite3DbFree(pParse->db, zAff); } @@ -113690,11 +94518,11 @@ #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Generate an instruction that will put the floating point ** value described by z[0..n-1] into register iMem. ** -** The z[] string will probably not be zero-terminated. But the +** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ if( ALWAYS(z!=0) ){ @@ -113725,31 +94553,169 @@ int c; i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); c = sqlite3DecOrHexToI64(z, &value); - if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){ + if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){ #ifdef SQLITE_OMIT_FLOATING_POINT - sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr); + 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%#T", - negFlag?"-":"",pExpr); + 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; } + if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); } } } +/* +** Erase column-cache entry number i +*/ +static void cacheEntryClear(Parse *pParse, int i){ + if( pParse->aColCache[i].tempReg ){ + if( pParse->nTempRegaTempReg) ){ + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; + } + } + pParse->nColCache--; + if( inColCache ){ + pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; + } +} + + +/* +** Record in the column cache that a particular column from a +** particular table is stored in a particular register. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ + int i; + int minLru; + int idxLru; + struct yColCache *p; + + /* Unless an error has occurred, register numbers are always positive. */ + assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); + assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ + + /* The SQLITE_ColumnCache flag disables the column cache. This is used + ** for testing only - to verify that SQLite always gets the same answer + ** with and without the column cache. + */ + if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return; + + /* First replace any existing entry. + ** + ** Actually, the way the column cache is currently used, we are guaranteed + ** that the object will never already be in cache. Verify this guarantee. + */ +#ifndef NDEBUG + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + assert( p->iTable!=iTab || p->iColumn!=iCol ); + } +#endif + + /* If the cache is already full, delete the least recently used entry */ + if( pParse->nColCache>=SQLITE_N_COLCACHE ){ + minLru = 0x7fffffff; + idxLru = -1; + for(i=0, p=pParse->aColCache; ilrulru; + } + } + p = &pParse->aColCache[idxLru]; + }else{ + p = &pParse->aColCache[pParse->nColCache++]; + } + + /* Add the new entry to the end of the cache */ + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; +} + +/* +** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. +** Purge the range of registers from the column cache. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ + int i = 0; + while( inColCache ){ + struct yColCache *p = &pParse->aColCache[i]; + if( p->iReg >= iReg && p->iReg < iReg+nReg ){ + cacheEntryClear(pParse, i); + }else{ + i++; + } + } +} + +/* +** Remember the current column cache context. Any new entries added +** added to the column cache after this call are removed when the +** corresponding pop occurs. +*/ +SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ + pParse->iCacheLevel++; +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("PUSH to %d\n", pParse->iCacheLevel); + } +#endif +} + +/* +** Remove from the column cache any entries that were added since the +** the previous sqlite3ExprCachePush operation. In other words, restore +** the cache to the state it was in prior the most recent Push. +*/ +SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ + int i = 0; + assert( pParse->iCacheLevel>=1 ); + pParse->iCacheLevel--; +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("POP to %d\n", pParse->iCacheLevel); + } +#endif + while( inColCache ){ + if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ + cacheEntryClear(pParse, i); + }else{ + i++; + } + } +} + +/* +** When a cached column is reused, make sure that its register is +** no longer available as a temp register. ticket #3879: that same +** register might be in the cache in multiple places, so be sure to +** get them all. +*/ +static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + if( p->iReg==iReg ){ + p->tempReg = 0; + } + } +} /* Generate code that will load into register regOut a value that is ** appropriate for the iIdxCol-th column of index pIdx. */ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn( @@ -113761,105 +94727,55 @@ ){ i16 iTabCol = pIdx->aiColumn[iIdxCol]; if( iTabCol==XN_EXPR ){ assert( pIdx->aColExpr ); assert( pIdx->aColExpr->nExpr>iIdxCol ); - pParse->iSelfTab = iTabCur + 1; + pParse->iSelfTab = iTabCur; sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); - pParse->iSelfTab = 0; }else{ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, iTabCol, regOut); } } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* -** Generate code that will compute the value of generated column pCol -** and store the result in register regOut -*/ -SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( - Parse *pParse, /* Parsing context */ - Table *pTab, /* Table containing the generated column */ - Column *pCol, /* The generated column */ - int regOut /* Put the result in this register */ -){ - int iAddr; - Vdbe *v = pParse->pVdbe; - int nErr = pParse->nErr; - assert( v!=0 ); - assert( pParse->iSelfTab!=0 ); - if( pParse->iSelfTab>0 ){ - iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut); - }else{ - iAddr = 0; - } - sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); - if( pCol->affinity>=SQLITE_AFF_TEXT ){ - sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1); - } - if( iAddr ) sqlite3VdbeJumpHere(v, iAddr); - if( pParse->nErr>nErr ) pParse->db->errByteOffset = -1; -} -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - /* ** Generate code to extract the value of the iCol-th column of a table. */ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( - Vdbe *v, /* Parsing context */ + Vdbe *v, /* The VDBE under construction */ Table *pTab, /* The table containing the value */ int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */ int iCol, /* Index of the column to extract */ int regOut /* Extract the value into this register */ ){ - Column *pCol; - assert( v!=0 ); - assert( pTab!=0 ); - assert( iCol!=XN_EXPR ); + if( pTab==0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut); + return; + } if( iCol<0 || iCol==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); - VdbeComment((v, "%s.rowid", pTab->zName)); - }else{ - int op; - int x; - if( IsVirtual(pTab) ){ - op = OP_VColumn; - x = iCol; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){ - Parse *pParse = sqlite3VdbeParser(v); - if( pCol->colFlags & COLFLAG_BUSY ){ - sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", - pCol->zCnName); - }else{ - int savedSelfTab = pParse->iSelfTab; - pCol->colFlags |= COLFLAG_BUSY; - pParse->iSelfTab = iTabCur+1; - sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut); - pParse->iSelfTab = savedSelfTab; - pCol->colFlags &= ~COLFLAG_BUSY; - } - return; -#endif - }else if( !HasRowid(pTab) ){ - testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) ); - x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol); - op = OP_Column; - }else{ - x = sqlite3TableColumnToStorage(pTab,iCol); - testcase( x!=iCol ); - op = OP_Column; + }else{ + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; + int x = iCol; + if( !HasRowid(pTab) && !IsVirtual(pTab) ){ + x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol); } sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut); + } + if( iCol>=0 ){ sqlite3ColumnDefault(v, pTab, iCol, regOut); } } /* ** Generate code that will extract the iColumn-th column from -** table pTab and store the column value in register iReg. +** table pTab and store the column value in a register. +** +** An effort is made to store the column value in register iReg. This +** is not garanteeed for GetColumn() - the result can be stored in +** any register. But the result is guaranteed to land in register iReg +** for GetColumnToReg(). ** ** There must be an open cursor to pTab in iTable when this routine ** is called. If iColumn<0 then code is generated that extracts the rowid. */ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( @@ -113868,51 +94784,116 @@ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg, /* Store results here */ u8 p5 /* P5 value for OP_Column + FLAGS */ ){ - assert( pParse->pVdbe!=0 ); - assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 ); - assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 ); - sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); + Vdbe *v = pParse->pVdbe; + int i; + struct yColCache *p; + + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + if( p->iTable==iTable && p->iColumn==iColumn ){ + p->lru = pParse->iCacheCnt++; + sqlite3ExprCachePinRegister(pParse, p->iReg); + return p->iReg; + } + } + assert( v!=0 ); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); if( p5 ){ - VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); - if( pOp->opcode==OP_Column ) pOp->p5 = p5; - if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG); + sqlite3VdbeChangeP5(v, p5); + }else{ + sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); } return iReg; +} +SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg( + Parse *pParse, /* Parsing and code generating context */ + Table *pTab, /* Description of the table we are reading from */ + int iColumn, /* Index of the table column */ + int iTable, /* The cursor pointing to the table */ + int iReg /* Store results here */ +){ + int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0); + if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg); +} + + +/* +** Clear all column cache entries. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ + int i; + +#ifdef SQLITE_DEBUG + if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ + printf("CLEAR\n"); + } +#endif + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].tempReg + && pParse->nTempRegaTempReg) + ){ + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; + } + } + pParse->nColCache = 0; +} + +/* +** Record the fact that an affinity change has occurred on iCount +** registers starting with iStart. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ + sqlite3ExprCacheRemove(pParse, iStart, iCount); } /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 -** over to iTo..iTo+nReg-1. +** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ + assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); + sqlite3ExprCacheRemove(pParse, iFrom, nReg); } + +#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) +/* +** Return true if any register in the range iFrom..iTo (inclusive) +** is used as part of the column cache. +** +** This routine is used within assert() and testcase() macros only +** and does not appear in a normal build. +*/ +static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + int r = p->iReg; + if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ + } + return 0; +} +#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ + /* ** Convert a scalar expression node to a TK_REGISTER referencing ** register iReg. The caller must ensure that iReg already contains ** the correct value for the expression. */ -SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){ - Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr); - if( NEVER(p==0) ) return; - if( p->op==TK_REGISTER ){ - assert( p->iTable==iReg ); - }else{ - p->op2 = p->op; - p->op = TK_REGISTER; - p->iTable = iReg; - ExprClearProperty(p, EP_Skip); - } +static void exprToRegister(Expr *p, int iReg){ + p->op2 = p->op; + p->op = TK_REGISTER; + p->iTable = iReg; + ExprClearProperty(p, EP_Skip); } /* ** Evaluate an expression (either a vector or a scalar expression) and store -** the result in contiguous temporary registers. Return the index of +** the result in continguous temporary registers. Return the index of ** the first register used to store the result. ** ** If the returned result register is a temporary scalar, then also write ** that register number into *piFreeable. If the returned result register ** is not a temporary or if the expression is a vector set *piFreeable @@ -113927,313 +94908,24 @@ *piFreeable = 0; if( p->op==TK_SELECT ){ #if SQLITE_OMIT_SUBQUERY iResult = 0; #else - iResult = sqlite3CodeSubselect(pParse, p); + iResult = sqlite3CodeSubselect(pParse, p, 0, 0); #endif }else{ int i; iResult = pParse->nMem+1; pParse->nMem += nResult; - assert( ExprUseXList(p) ); for(i=0; ix.pList->a[i].pExpr, i+iResult); } } } return iResult; } -/* -** If the last opcode is a OP_Copy, then set the do-not-merge flag (p5) -** so that a subsequent copy will not be merged into this one. -*/ -static void setDoNotMergeFlagOnCopy(Vdbe *v){ - if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){ - sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergeable */ - } -} - -/* -** Generate code to implement special SQL functions that are implemented -** in-line rather than by using the usual callbacks. -*/ -static int exprCodeInlineFunction( - Parse *pParse, /* Parsing context */ - ExprList *pFarg, /* List of function arguments */ - int iFuncId, /* Function ID. One of the INTFUNC_... values */ - int target /* Store function result in this register */ -){ - int nFarg; - Vdbe *v = pParse->pVdbe; - assert( v!=0 ); - assert( pFarg!=0 ); - nFarg = pFarg->nExpr; - assert( nFarg>0 ); /* All in-line functions have at least one argument */ - switch( iFuncId ){ - case INLINEFUNC_coalesce: { - /* Attempt a direct implementation of the built-in COALESCE() and - ** IFNULL() functions. This avoids unnecessary evaluation of - ** arguments past the first non-NULL argument. - */ - int endCoalesce = sqlite3VdbeMakeLabel(pParse); - int i; - assert( nFarg>=2 ); - sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); - for(i=1; ia[i].pExpr, target); - } - setDoNotMergeFlagOnCopy(v); - sqlite3VdbeResolveLabel(v, endCoalesce); - break; - } - case INLINEFUNC_iif: { - Expr caseExpr; - memset(&caseExpr, 0, sizeof(caseExpr)); - caseExpr.op = TK_CASE; - caseExpr.x.pList = pFarg; - return sqlite3ExprCodeTarget(pParse, &caseExpr, target); - } -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - case INLINEFUNC_sqlite_offset: { - Expr *pArg = pFarg->a[0].pExpr; - if( pArg->op==TK_COLUMN && pArg->iTable>=0 ){ - sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - } - break; - } -#endif - default: { - /* The UNLIKELY() function is a no-op. The result is the value - ** of the first argument. - */ - assert( nFarg==1 || nFarg==2 ); - target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); - break; - } - - /*********************************************************************** - ** Test-only SQL functions that are only usable if enabled - ** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS - */ -#if !defined(SQLITE_UNTESTABLE) - case INLINEFUNC_expr_compare: { - /* Compare two expressions using sqlite3ExprCompare() */ - assert( nFarg==2 ); - sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprCompare(0,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1), - target); - break; - } - - case INLINEFUNC_expr_implies_expr: { - /* Compare two expressions using sqlite3ExprImpliesExpr() */ - assert( nFarg==2 ); - sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprImpliesExpr(pParse,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1), - target); - break; - } - - case INLINEFUNC_implies_nonnull_row: { - /* Result of sqlite3ExprImpliesNonNullRow() */ - Expr *pA1; - assert( nFarg==2 ); - pA1 = pFarg->a[1].pExpr; - if( pA1->op==TK_COLUMN ){ - sqlite3VdbeAddOp2(v, OP_Integer, - sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable,1), - target); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - } - break; - } - - case INLINEFUNC_affinity: { - /* 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. - */ - const char *azAff[] = { "blob", "text", "numeric", "integer", - "real", "flexnum" }; - char aff; - assert( nFarg==1 ); - aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); - assert( aff<=SQLITE_AFF_NONE - || (aff>=SQLITE_AFF_BLOB && aff<=SQLITE_AFF_FLEXNUM) ); - sqlite3VdbeLoadString(v, target, - (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]); - break; - } -#endif /* !defined(SQLITE_UNTESTABLE) */ - } - return target; -} - -/* -** Expression Node callback for sqlite3ExprCanReturnSubtype(). -** -** Only a function call is able to return a subtype. So if the node -** is not a function call, return WRC_Prune immediately. -** -** A function call is able to return a subtype if it has the -** SQLITE_RESULT_SUBTYPE property. -** -** Assume that every function is able to pass-through a subtype from -** one of its argument (using sqlite3_result_value()). Most functions -** are not this way, but we don't have a mechanism to distinguish those -** that are from those that are not, so assume they all work this way. -** That means that if one of its arguments is another function and that -** other function is able to return a subtype, then this function is -** able to return a subtype. -*/ -static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){ - int n; - FuncDef *pDef; - sqlite3 *db; - if( pExpr->op!=TK_FUNCTION ){ - return WRC_Prune; - } - assert( ExprUseXList(pExpr) ); - db = pWalker->pParse->db; - n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0; - pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); - if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ - pWalker->eCode = 1; - return WRC_Prune; - } - return WRC_Continue; -} - -/* -** Return TRUE if expression pExpr is able to return a subtype. -** -** A TRUE return does not guarantee that a subtype will be returned. -** It only indicates that a subtype return is possible. False positives -** are acceptable as they only disable an optimization. False negatives, -** on the other hand, can lead to incorrect answers. -*/ -static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){ - Walker w; - memset(&w, 0, sizeof(w)); - w.pParse = pParse; - w.xExprCallback = exprNodeCanReturnSubtype; - sqlite3WalkExpr(&w, pExpr); - return w.eCode; -} - - -/* -** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr. -** If it is, then resolve the expression by reading from the index and -** return the register into which the value has been read. If pExpr is -** not an indexed expression, then return negative. -*/ -static SQLITE_NOINLINE int sqlite3IndexedExprLookup( - Parse *pParse, /* The parsing context */ - Expr *pExpr, /* The expression to potentially bypass */ - int target /* Where to store the result of the expression */ -){ - IndexedExpr *p; - Vdbe *v; - for(p=pParse->pIdxEpr; p; p=p->pIENext){ - u8 exprAff; - int iDataCur = p->iDataCur; - if( iDataCur<0 ) continue; - if( pParse->iSelfTab ){ - if( p->iDataCur!=pParse->iSelfTab-1 ) continue; - iDataCur = -1; - } - if( sqlite3ExprCompare(0, pExpr, p->pExpr, iDataCur)!=0 ) continue; - assert( p->aff>=SQLITE_AFF_BLOB && p->aff<=SQLITE_AFF_NUMERIC ); - exprAff = sqlite3ExprAffinity(pExpr); - if( (exprAff<=SQLITE_AFF_BLOB && p->aff!=SQLITE_AFF_BLOB) - || (exprAff==SQLITE_AFF_TEXT && p->aff!=SQLITE_AFF_TEXT) - || (exprAff>=SQLITE_AFF_NUMERIC && p->aff!=SQLITE_AFF_NUMERIC) - ){ - /* Affinity mismatch on a generated column */ - continue; - } - - - /* Functions that might set a subtype should not be replaced by the - ** value taken from an expression index if they are themselves an - ** argument to another scalar function or aggregate. - ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */ - if( ExprHasProperty(pExpr, EP_SubtArg) - && sqlite3ExprCanReturnSubtype(pParse, pExpr) - ){ - continue; - } - - v = pParse->pVdbe; - assert( v!=0 ); - if( p->bMaybeNullRow ){ - /* If the index is on a NULL row due to an outer join, then we - ** cannot extract the value from the index. The value must be - ** computed using the original expression. */ - int addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); - VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); - sqlite3VdbeGoto(v, 0); - p = pParse->pIdxEpr; - pParse->pIdxEpr = 0; - sqlite3ExprCode(pParse, pExpr, target); - pParse->pIdxEpr = p; - sqlite3VdbeJumpHere(v, addr+2); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); - VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); - } - return target; - } - return -1; /* Not found */ -} - - -/* -** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This -** function checks the Parse.pIdxPartExpr list to see if this column -** can be replaced with a constant value. If so, it generates code to -** put the constant value in a register (ideally, but not necessarily, -** register iTarget) and returns the register number. -** -** Or, if the TK_COLUMN cannot be replaced by a constant, zero is -** returned. -*/ -static int exprPartidxExprLookup(Parse *pParse, Expr *pExpr, int iTarget){ - IndexedExpr *p; - for(p=pParse->pIdxPartExpr; p; p=p->pIENext){ - if( pExpr->iColumn==p->iIdxCol && pExpr->iTable==p->iDataCur ){ - Vdbe *v = pParse->pVdbe; - int addr = 0; - int ret; - - if( p->bMaybeNullRow ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNullRow, p->iIdxCur); - } - ret = sqlite3ExprCodeTarget(pParse, p->pExpr, iTarget); - sqlite3VdbeAddOp4(pParse->pVdbe, OP_Affinity, ret, 1, 0, - (const char*)&p->aff, 1); - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeChangeP3(v, addr, ret); - } - return ret; - } - } - return 0; -} - /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". ** Return the register where results are stored. @@ -114253,166 +94945,54 @@ int r1, r2; /* Various register numbers */ Expr tempX; /* Temporary expression node */ int p5 = 0; assert( target>0 && target<=pParse->nMem ); - assert( v!=0 ); + if( v==0 ){ + assert( pParse->db->mallocFailed ); + return 0; + } -expr_code_doover: if( pExpr==0 ){ op = TK_NULL; - }else if( pParse->pIdxEpr!=0 - && !ExprHasProperty(pExpr, EP_Leaf) - && (r1 = sqlite3IndexedExprLookup(pParse, pExpr, target))>=0 - ){ - return r1; }else{ - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); op = pExpr->op; } - assert( op!=TK_ORDER ); switch( op ){ case TK_AGG_COLUMN: { AggInfo *pAggInfo = pExpr->pAggInfo; - struct AggInfo_col *pCol; - assert( pAggInfo!=0 ); - assert( pExpr->iAgg>=0 ); - if( pExpr->iAgg>=pAggInfo->nColumn ){ - /* Happens when the left table of a RIGHT JOIN is null and - ** is using an expression index */ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); -#ifdef SQLITE_VDBE_COVERAGE - /* Verify that the OP_Null above is exercised by tests - ** tag-20230325-2 */ - sqlite3VdbeAddOp3(v, OP_NotNull, target, 1, 20230325); - VdbeCoverageNeverTaken(v); -#endif - break; - } - pCol = &pAggInfo->aCol[pExpr->iAgg]; + struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; if( !pAggInfo->directMode ){ - return AggInfoColumnReg(pAggInfo, pExpr->iAgg); + assert( pCol->iMem>0 ); + return pCol->iMem; }else if( pAggInfo->useSortingIdx ){ - Table *pTab = pCol->pTab; sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pCol->iSorterColumn, target); - if( pTab==0 ){ - /* No comment added */ - }else if( pCol->iColumn<0 ){ - VdbeComment((v,"%s.rowid",pTab->zName)); - }else{ - VdbeComment((v,"%s.%s", - pTab->zName, pTab->aCol[pCol->iColumn].zCnName)); - if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, target); - } - } - return target; - }else if( pExpr->y.pTab==0 ){ - /* This case happens when the argument to an aggregate function - ** is rewritten by aggregateConvertIndexedExprRefToColumn() */ - sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, pExpr->iColumn, target); return target; } /* Otherwise, fall thru into the TK_COLUMN case */ - /* no break */ deliberate_fall_through } case TK_COLUMN: { int iTab = pExpr->iTable; - int iReg; - if( ExprHasProperty(pExpr, EP_FixedCol) ){ - /* This COLUMN expression is really a constant due to WHERE clause - ** constraints, and that constant is coded by the pExpr->pLeft - ** expression. However, make sure the constant has the correct - ** datatype by applying the Affinity of the table column to the - ** constant. - */ - int aff; - iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); - assert( ExprUseYTab(pExpr) ); - assert( pExpr->y.pTab!=0 ); - aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); - if( aff>SQLITE_AFF_BLOB ){ - static const char zAff[] = "B\000C\000D\000E\000F"; - assert( SQLITE_AFF_BLOB=='A' ); - assert( SQLITE_AFF_TEXT=='B' ); - sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0, - &zAff[(aff-'B')*2], P4_STATIC); - } - return iReg; - } if( iTab<0 ){ - if( pParse->iSelfTab<0 ){ - /* Other columns in the same row for CHECK constraints or - ** generated columns or for inserting into partial index. - ** The row is unpacked into registers beginning at - ** 0-(pParse->iSelfTab). The rowid (if any) is in a register - ** immediately prior to the first column. - */ - Column *pCol; - Table *pTab; - int iSrc; - int iCol = pExpr->iColumn; - assert( ExprUseYTab(pExpr) ); - pTab = pExpr->y.pTab; - assert( pTab!=0 ); - assert( iCol>=XN_ROWID ); - assert( iColnCol ); - if( iCol<0 ){ - return -1-pParse->iSelfTab; - } - pCol = pTab->aCol + iCol; - testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) ); - iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pCol->colFlags & COLFLAG_GENERATED ){ - if( pCol->colFlags & COLFLAG_BUSY ){ - sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", - pCol->zCnName); - return 0; - } - pCol->colFlags |= COLFLAG_BUSY; - if( pCol->colFlags & COLFLAG_NOTAVAIL ){ - sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc); - } - pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL); - return iSrc; - }else -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - if( pCol->affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target); - sqlite3VdbeAddOp1(v, OP_RealAffinity, target); - return target; - }else{ - return iSrc; - } + if( pParse->ckBase>0 ){ + /* Generating CHECK constraints or inserting into partial index */ + return pExpr->iColumn + pParse->ckBase; }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 - 1; + iTab = pParse->iSelfTab; } } - else if( pParse->pIdxPartExpr - && 0!=(r1 = exprPartidxExprLookup(pParse, pExpr, target)) - ){ - return r1; - } - assert( ExprUseYTab(pExpr) ); - assert( pExpr->y.pTab!=0 ); - iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, iTab, target, pExpr->op2); - return iReg; } case TK_INTEGER: { codeInteger(pParse, pExpr, 0, target); return target; } - case TK_TRUEFALSE: { - sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target); - return target; - } #ifndef SQLITE_OMIT_FLOATING_POINT case TK_FLOAT: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); codeReal(v, pExpr->u.zToken, 0, target); return target; @@ -114421,16 +95001,11 @@ case TK_STRING: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeLoadString(v, target, pExpr->u.zToken); return target; } - default: { - /* Make NULL the default case so that if a bug causes an illegal - ** Expr node to be passed into this function, it will be handled - ** sanely and not crash. But keep the assert() to bring the problem - ** to the attention of the developers. */ - assert( op==TK_NULL || op==TK_ERROR || pParse->db->mallocFailed ); + case TK_NULL: { sqlite3VdbeAddOp2(v, OP_Null, 0, target); return target; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { @@ -114451,23 +95026,33 @@ case TK_VARIABLE: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken!=0 ); assert( pExpr->u.zToken[0]!=0 ); sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); + if( pExpr->u.zToken[1]!=0 ){ + 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; } case TK_REGISTER: { return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ - sqlite3ExprCode(pParse, pExpr->pLeft, target); - assert( inReg==target ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + if( inReg!=target ){ + sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); + inReg = target; + } sqlite3VdbeAddOp2(v, OP_Cast, target, sqlite3AffinityType(pExpr->u.zToken, 0)); + testcase( usedAsColumnCache(pParse, inReg, inReg) ); + sqlite3ExprCacheAffinityChange(pParse, inReg, 1); return inReg; } #endif /* SQLITE_OMIT_CAST */ case TK_IS: case TK_ISNOT: @@ -114484,25 +95069,18 @@ if( sqlite3ExprIsVector(pLeft) ){ codeVectorCompare(pParse, pExpr, target, op, p5); }else{ r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg); - codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2, - sqlite3VdbeCurrentAddr(v)+2, p5, - ExprHasProperty(pExpr,EP_Commuted)); + codeCompare(pParse, pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2 | p5); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); - if( p5==SQLITE_NULLEQ ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg); - }else{ - sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2); - } testcase( regFree1==0 ); testcase( regFree2==0 ); } break; } @@ -114514,11 +95092,11 @@ case TK_REM: case TK_BITAND: case TK_BITOR: case TK_SLASH: case TK_LSHIFT: - case TK_RSHIFT: + case TK_RSHIFT: case TK_CONCAT: { assert( TK_AND==OP_And ); testcase( op==TK_AND ); assert( TK_OR==OP_Or ); testcase( op==TK_OR ); assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); @@ -114550,11 +95128,10 @@ #endif }else{ tempX.op = TK_INTEGER; tempX.flags = EP_IntValue|EP_TokenOnly; tempX.u.iValue = 0; - ExprClearVVAProperties(&tempX); r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); testcase( regFree2==0 ); } @@ -114567,22 +95144,10 @@ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); sqlite3VdbeAddOp2(v, op, r1, inReg); break; } - case TK_TRUTH: { - int isTrue; /* IS TRUE or IS NOT TRUE */ - int bNormal; /* IS TRUE or IS FALSE */ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - testcase( regFree1==0 ); - isTrue = sqlite3ExprTruthValue(pExpr->pRight); - bNormal = pExpr->op2==TK_IS; - testcase( isTrue && bNormal); - testcase( !isTrue && bNormal); - sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal); - break; - } case TK_ISNULL: case TK_NOTNULL: { int addr; assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); @@ -114596,18 +95161,15 @@ sqlite3VdbeJumpHere(v, addr); break; } case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; - if( pInfo==0 - || NEVER(pExpr->iAgg<0) - || NEVER(pExpr->iAgg>=pInfo->nFunc) - ){ + if( pInfo==0 ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); }else{ - return AggInfoFuncReg(pInfo, pExpr->iAgg); + return pInfo->aFunc[pExpr->iAgg].iMem; } break; } case TK_FUNCTION: { ExprList *pFarg; /* List of function arguments */ @@ -114618,26 +95180,21 @@ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* The database connection */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - return pExpr->y.pWin->regResult; - } -#endif - - if( ConstFactorOk(pParse) - && sqlite3ExprIsConstantNotJoin(pParse,pExpr) - ){ - /* SQL functions can be expensive. So try to avoid running them - ** multiple times if we know they always give the same result */ - return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); - } - assert( !ExprHasProperty(pExpr, EP_TokenOnly) ); - assert( ExprUseXList(pExpr) ); - pFarg = pExpr->x.pList; + 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; + }else{ + pFarg = pExpr->x.pList; + } nFarg = pFarg ? pFarg->nExpr : 0; assert( !ExprHasProperty(pExpr, EP_IntValue) ); zId = pExpr->u.zToken; pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0); #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION @@ -114644,24 +95201,60 @@ if( pDef==0 && pParse->explain ){ pDef = sqlite3FindFunction(db, "unknown", nFarg, enc, 0); } #endif if( pDef==0 || pDef->xFinalize!=0 ){ - sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); + sqlite3ErrorMsg(pParse, "unknown function: %s()", zId); break; } - if( (pDef->funcFlags & SQLITE_FUNC_INLINE)!=0 && ALWAYS(pFarg!=0) ){ - assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 ); - assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 ); - return exprCodeInlineFunction(pParse, pFarg, - SQLITE_PTR_TO_INT(pDef->pUserData), target); - }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){ - sqlite3ExprFunctionUsable(pParse, pExpr, pDef); - } + + /* Attempt a direct implementation of the built-in COALESCE() and + ** IFNULL() functions. This avoids unnecessary evaluation of + ** arguments past the first non-NULL argument. + */ + if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ + int endCoalesce = sqlite3VdbeMakeLabel(v); + assert( nFarg>=2 ); + sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); + for(i=1; ia[i].pExpr, target); + sqlite3ExprCachePop(pParse); + } + sqlite3VdbeResolveLabel(v, endCoalesce); + break; + } + + /* The UNLIKELY() function is a no-op. The result is the value + ** of the first argument. + */ + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ + assert( nFarg>=1 ); + 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) ){ + if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); @@ -114673,33 +95266,33 @@ pParse->nMem += nFarg; }else{ r1 = sqlite3GetTempRange(pParse, nFarg); } - /* For length() and typeof() and octet_length() functions, + /* For length() and typeof() functions with a column argument, ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG - ** or OPFLAG_TYPEOFARG or OPFLAG_BYTELENARG respectively, to avoid - ** unnecessary data loading. + ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data + ** loading. */ if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ u8 exprOp; assert( nFarg==1 ); assert( pFarg->a[0].pExpr!=0 ); exprOp = pFarg->a[0].pExpr->op; if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); - assert( SQLITE_FUNC_BYTELEN==OPFLAG_BYTELENARG ); - assert( (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG)==OPFLAG_BYTELENARG ); - testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_LENGTHARG ); - testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_TYPEOFARG ); - testcase( (pDef->funcFlags & OPFLAG_BYTELENARG)==OPFLAG_BYTELENARG); - pFarg->a[0].pExpr->op2 = pDef->funcFlags & OPFLAG_BYTELENARG; + testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); + pFarg->a[0].pExpr->op2 = + pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); } } - sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, SQLITE_ECEL_FACTOR); + sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ + sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, + SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); + sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ }else{ r1 = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* Possibly overload the function if the first argument is @@ -114708,71 +95301,62 @@ ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the ** second argument, not the first, as the argument to test to ** see if it is a column in a virtual table. This is done because ** the left operand of infix functions (the operand we want to ** control overloading) ends up as the second argument to the - ** function. The expression "A glob B" is equivalent to + ** function. The expression "A glob B" is equivalent to ** "glob(B,A). We want to use the A in "A glob B" to test ** for function overloading. But we use the B term in "glob(B,A)". */ - if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ + if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); }else if( nFarg>0 ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); } #endif if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - if( !pColl ) pColl = db->pDfltColl; + if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg, - pDef, pExpr->op2); - if( nFarg ){ - if( constMask==0 ){ - sqlite3ReleaseTempRange(pParse, r1, nFarg); - }else{ - sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask, 1); - } + sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target, + (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nFarg); + if( nFarg && constMask==0 ){ + sqlite3ReleaseTempRange(pParse, r1, nFarg); } return target; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { int nCol; testcase( op==TK_EXISTS ); testcase( op==TK_SELECT ); - if( pParse->db->mallocFailed ){ - return 0; - }else if( op==TK_SELECT - && ALWAYS( ExprUseXSelect(pExpr) ) - && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 - ){ + if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){ sqlite3SubselectError(pParse, nCol, 1); }else{ - return sqlite3CodeSubselect(pParse, pExpr); + return sqlite3CodeSubselect(pParse, pExpr, 0, 0); } break; } case TK_SELECT_COLUMN: { int n; - Expr *pLeft = pExpr->pLeft; - if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){ - pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft); - pLeft->op2 = pParse->withinRJSubrtn; - } - assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR ); - n = sqlite3ExprVectorSize(pLeft); - if( pExpr->iTable!=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 pLeft->iTable + pExpr->iColumn; + return pExpr->pLeft->iTable + pExpr->iColumn; } case TK_IN: { - int destIfFalse = sqlite3VdbeMakeLabel(pParse); - int destIfNull = sqlite3VdbeMakeLabel(pParse); + int destIfFalse = sqlite3VdbeMakeLabel(v); + int destIfNull = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Null, 0, target); sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); sqlite3VdbeResolveLabel(v, destIfFalse); sqlite3VdbeAddOp2(v, OP_AddImm, target, 0); @@ -114795,31 +95379,14 @@ */ case TK_BETWEEN: { exprCodeBetween(pParse, pExpr, target, 0, 0); return target; } - case TK_COLLATE: { - if( !ExprHasProperty(pExpr, EP_Collate) ){ - /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called - ** "SOFT-COLLATE" that is added to constraints that are pushed down - ** from outer queries into sub-queries by the WHERE-clause push-down - ** optimization. Clear subtypes as subtypes may not cross a subquery - ** boundary. - */ - assert( pExpr->pLeft ); - sqlite3ExprCode(pParse, pExpr->pLeft, target); - sqlite3VdbeAddOp1(v, OP_ClrSubtype, target); - return target; - }else{ - pExpr = pExpr->pLeft; - goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */ - } - } case TK_SPAN: + case TK_COLLATE: case TK_UPLUS: { - pExpr = pExpr->pLeft; - goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */ + return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); } case TK_TRIGGER: { /* If the opcode is TK_TRIGGER, then the expression is a reference ** to a column in the new.* or old.* pseudo-tables available to @@ -114828,11 +95395,11 @@ ** is set to the column of the pseudo-table to read, or to -1 to ** read the rowid field. ** ** The expression is implemented using an OP_Param opcode. The p1 ** parameter is set to 0 for an old.rowid reference, or to (i+1) - ** to reference another column of the old.* pseudo-table, where + ** to reference another column of the old.* pseudo-table, where ** i is the index of the column. For a new.rowid reference, p1 is ** set to (n+1), where n is the number of columns in each pseudo-table. ** For a reference to any other column in the new.* pseudo-table, p1 ** is set to (n+2+i), where n and i are as defined previously. For ** example, if the table on which triggers are being fired is @@ -114842,40 +95409,36 @@ ** ** Then p1 is interpreted as follows: ** ** p1==0 -> old.rowid p1==3 -> new.rowid ** p1==1 -> old.a p1==4 -> new.a - ** p1==2 -> old.b p1==5 -> new.b + ** p1==2 -> old.b p1==5 -> new.b */ - Table *pTab; - int iCol; - int p1; - - assert( ExprUseYTab(pExpr) ); - pTab = pExpr->y.pTab; - iCol = pExpr->iColumn; - p1 = pExpr->iTable * (pTab->nCol+1) + 1 - + sqlite3TableColumnToStorage(pTab, iCol); + Table *pTab = pExpr->pTab; + int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; assert( pExpr->iTable==0 || pExpr->iTable==1 ); - assert( iCol>=-1 && iColnCol ); - assert( pTab->iPKey<0 || iCol!=pTab->iPKey ); + assert( pExpr->iColumn>=-1 && pExpr->iColumnnCol ); + assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey ); assert( p1>=0 && p1<(pTab->nCol*2+2) ); sqlite3VdbeAddOp2(v, OP_Param, p1, target); - VdbeComment((v, "r[%d]=%s.%s", target, + VdbeComment((v, "%s.%s -> $%d", (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zCnName) + (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), + target )); #ifndef SQLITE_OMIT_FLOATING_POINT /* If the column has REAL affinity, it may currently be stored as an ** integer. Use OP_RealAffinity to make sure it is really real. ** ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to ** floating point when extracting it from the record. */ - if( iCol>=0 && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){ + if( pExpr->iColumn>=0 + && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL + ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, target); } #endif break; } @@ -114883,47 +95446,18 @@ case TK_VECTOR: { sqlite3ErrorMsg(pParse, "row value misused"); break; } - /* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions - ** that derive from the right-hand table of a LEFT JOIN. The - ** Expr.iTable value is the table number for the right-hand table. - ** The expression is only evaluated if that table is not currently - ** on a LEFT JOIN NULL row. - */ case TK_IF_NULL_ROW: { int addrINR; - u8 okConstFactor = pParse->okConstFactor; - AggInfo *pAggInfo = pExpr->pAggInfo; - if( pAggInfo ){ - assert( pExpr->iAgg>=0 && pExpr->iAggnColumn ); - if( !pAggInfo->directMode ){ - inReg = AggInfoColumnReg(pAggInfo, pExpr->iAgg); - break; - } - if( pExpr->pAggInfo->useSortingIdx ){ - sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, - pAggInfo->aCol[pExpr->iAgg].iSorterColumn, - target); - inReg = target; - break; - } - } - addrINR = sqlite3VdbeAddOp3(v, OP_IfNullRow, pExpr->iTable, 0, target); - /* The OP_IfNullRow opcode above can overwrite the result register with - ** NULL. So we have to ensure that the result register is not a value - ** that is suppose to be a constant. Two defenses are needed: - ** (1) Temporarily disable factoring of constant expressions - ** (2) Make sure the computed value really is stored in register - ** "target" and not someplace else. - */ - pParse->okConstFactor = 0; /* note (1) above */ - sqlite3ExprCode(pParse, pExpr->pLeft, target); - assert( target==inReg ); - pParse->okConstFactor = okConstFactor; + 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: @@ -114944,98 +95478,97 @@ ** ** The result of the expression is the Ri for the first matching Ei, ** or if there is no matching Ei, the ELSE term Y, or if there is ** no ELSE term, NULL. */ - case TK_CASE: { + default: assert( op==TK_CASE ); { int endLabel; /* GOTO label for end of CASE stmt */ int nextCase; /* GOTO label for next WHEN clause */ int nExpr; /* 2x number of WHEN terms */ int i; /* Loop counter */ ExprList *pEList; /* List of WHEN terms */ struct ExprList_item *aListelem; /* Array of WHEN terms */ Expr opCompare; /* The X==Ei expression */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ - Expr *pDel = 0; - sqlite3 *db = pParse->db; + VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) - assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 ); + assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); assert(pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; aListelem = pEList->a; nExpr = pEList->nExpr; - endLabel = sqlite3VdbeMakeLabel(pParse); + endLabel = sqlite3VdbeMakeLabel(v); if( (pX = pExpr->pLeft)!=0 ){ - pDel = sqlite3ExprDup(db, pX, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDel); - break; - } + tempX = *pX; testcase( pX->op==TK_COLUMN ); - sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); + exprToRegister(&tempX, exprCodeVector(pParse, &tempX, ®Free1)); testcase( regFree1==0 ); memset(&opCompare, 0, sizeof(opCompare)); opCompare.op = TK_EQ; - opCompare.pLeft = pDel; + opCompare.pLeft = &tempX; pTest = &opCompare; /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: ** The value in regFree1 might get SCopy-ed into the file result. ** So make sure that the regFree1 register is not reused for other ** purposes and possibly overwritten. */ regFree1 = 0; } for(i=0; iop==TK_COLUMN ); sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3VdbeGoto(v, endLabel); + sqlite3ExprCachePop(pParse); sqlite3VdbeResolveLabel(v, nextCase); } if( (nExpr&1)!=0 ){ + sqlite3ExprCachePush(pParse); sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); + sqlite3ExprCachePop(pParse); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } - sqlite3ExprDelete(db, pDel); - setDoNotMergeFlagOnCopy(v); + assert( pParse->db->mallocFailed || pParse->nErr>0 + || pParse->iCacheLevel==iCacheLevel ); sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { - assert( pExpr->affExpr==OE_Rollback - || pExpr->affExpr==OE_Abort - || pExpr->affExpr==OE_Fail - || pExpr->affExpr==OE_Ignore + assert( pExpr->affinity==OE_Rollback + || pExpr->affinity==OE_Abort + || pExpr->affinity==OE_Fail + || pExpr->affinity==OE_Ignore ); - if( !pParse->pTriggerTab && !pParse->nested ){ + if( !pParse->pTriggerTab ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return 0; } - if( pExpr->affExpr==OE_Abort ){ + if( pExpr->affinity==OE_Abort ){ sqlite3MayAbort(pParse); } assert( !ExprHasProperty(pExpr, EP_IntValue) ); - if( pExpr->affExpr==OE_Ignore ){ - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore); + if( pExpr->affinity==OE_Ignore ){ + sqlite3VdbeAddOp4( + v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); VdbeCoverage(v); }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp3(v, OP_Halt, - pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR, - pExpr->affExpr, r1); + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, + pExpr->affinity, pExpr->u.zToken, 0, 0); } + break; } #endif } sqlite3ReleaseTempReg(pParse, regFree1); @@ -115042,70 +95575,44 @@ sqlite3ReleaseTempReg(pParse, regFree2); return inReg; } /* -** Generate code that will evaluate expression pExpr just one time -** per prepared statement execution. -** -** If the expression uses functions (that might throw an exception) then -** guard them with an OP_Once opcode to ensure that the code is only executed -** once. If no functions are involved, then factor the code out and put it at -** the end of the prepared statement in the initialization section. -** -** 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 wherever it wants. The register where the expression -** is stored is returned. When regDest<0, two identical expressions might -** code to the same register, if they do not contain function calls and hence -** are factored out into the initialization section at the end of the -** prepared statement. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( +** 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 int sqlite3ExprCodeAtInit( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The expression to code when the VDBE initializes */ int regDest /* Store the value in this register */ ){ ExprList *p; assert( ConstFactorOk(pParse) ); - assert( regDest!=0 ); 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->fg.reusable - && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 - ){ + if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){ return pItem->u.iConstExprReg; } } } pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); - if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){ - Vdbe *v = pParse->pVdbe; - int addr; - assert( v ); - addr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - pParse->okConstFactor = 0; - if( !pParse->db->mallocFailed ){ - if( regDest<0 ) regDest = ++pParse->nMem; - sqlite3ExprCode(pParse, pExpr, regDest); - } - pParse->okConstFactor = 1; - sqlite3ExprDelete(pParse->db, pExpr); - sqlite3VdbeJumpHere(v, addr); - }else{ - p = sqlite3ExprListAppend(pParse, p, pExpr); - if( p ){ - struct ExprList_item *pItem = &p->a[p->nExpr-1]; - pItem->fg.reusable = regDest<0; - if( regDest<0 ) regDest = ++pParse->nMem; - pItem->u.iConstExprReg = regDest; - } - pParse->pConstExpr = p; - } + 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; + } + pParse->pConstExpr = p; return regDest; } /* ** Generate code to evaluate an expression and store the results @@ -115120,18 +95627,17 @@ ** code to fill the register in the initialization section of the ** VDBE program, in order to factor it out of the evaluation loop. */ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ int r2; - pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); + pExpr = sqlite3ExprSkipCollate(pExpr); if( ConstFactorOk(pParse) - && ALWAYS(pExpr!=0) && pExpr->op!=TK_REGISTER - && sqlite3ExprIsConstantNotJoin(pParse, pExpr) + && sqlite3ExprIsConstantNotJoin(pExpr) ){ *pReg = 0; - r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); + r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1); }else{ int r1 = sqlite3GetTempReg(pParse); r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( r2==r1 ){ *pReg = r1; @@ -115149,27 +95655,19 @@ ** in register target. */ SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ int inReg; - assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) ); assert( target>0 && target<=pParse->nMem ); - assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); - if( pParse->pVdbe==0 ) return; - inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); - if( inReg!=target ){ - u8 op; - Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr); - testcase( pX!=pExpr ); - if( ALWAYS(pX) - && (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER) - ){ - op = OP_Copy; - }else{ - op = OP_SCopy; - } - sqlite3VdbeAddOp2(pParse->pVdbe, op, inReg, target); + if( pExpr && pExpr->op==TK_REGISTER ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target); + }else{ + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); + if( inReg!=target && pParse->pVdbe ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); + } } } /* ** Make a transient copy of expression pExpr and then code it using @@ -115188,24 +95686,46 @@ ** results in register target. The results are guaranteed to appear ** in register target. If the expression is constant, then this routine ** might choose to code the expression at initialization time. */ SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ - if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ - sqlite3ExprCodeRunJustOnce(pParse, pExpr, target); + if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target); }else{ - sqlite3ExprCodeCopy(pParse, pExpr, target); + sqlite3ExprCode(pParse, pExpr, target); } } + +/* +** Generate code that evaluates the given expression and puts the result +** in register target. +** +** Also make a copy of the expression results into another "cache" register +** and modify the expression so that the next time it is evaluated, +** the result is a copy of the cache register. +** +** This routine is used for expressions that are used multiple +** times. They are evaluated once and the results of the expression +** are reused. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; + int iMem; + + assert( target>0 ); + assert( pExpr->op!=TK_REGISTER ); + sqlite3ExprCode(pParse, pExpr, target); + iMem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, target, iMem); + exprToRegister(pExpr, iMem); +} /* ** 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. The number returned will -** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF -** is defined. +** Return the number of elements evaluated. ** ** The SQLITE_ECEL_DUP flag prevents the arguments from being ** filled using OP_SCopy. OP_Copy must be used instead. ** ** The SQLITE_ECEL_FACTOR argument allows constant arguments to be @@ -115212,12 +95732,10 @@ ** factored out into initialization code. ** ** 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 */ ExprList *pList, /* The expression list to be coded */ int target, /* Where to write results */ @@ -115233,36 +95751,27 @@ assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; ipExpr; -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( pItem->fg.bSorterRef ){ - i--; - n--; - }else -#endif 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 - && sqlite3ExprIsConstantNotJoin(pParse,pExpr) - ){ - sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i); + }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target+i); }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ VdbeOp *pOp; if( copyOp==OP_Copy - && (pOp=sqlite3VdbeGetLastOp(v))->opcode==OP_Copy + && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy && pOp->p1+pOp->p3+1==inReg && pOp->p2+pOp->p3+1==target+i - && pOp->p5==0 /* The do-not-merge flag must be clear */ ){ pOp->p3++; }else{ sqlite3VdbeAddOp2(v, copyOp, inReg, target+i); } @@ -115275,11 +95784,11 @@ /* ** Generate code for a BETWEEN operator. ** ** x BETWEEN y AND z ** -** The above is equivalent to +** The above is equivalent to ** ** x>=y AND x<=z ** ** Code it as such, taking care to do the common subexpression ** elimination of x. @@ -115297,48 +95806,45 @@ Expr *pExpr, /* The BETWEEN expression */ int dest, /* Jump destination or storage location */ void (*xJump)(Parse*,Expr*,int,int), /* Action to take */ int jumpIfNull /* Take the jump if the BETWEEN is NULL */ ){ - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ + Expr exprAnd; /* The AND operator in x>=y AND x<=z */ Expr compLeft; /* The x>=y term */ Expr compRight; /* The x<=z term */ + Expr exprX; /* The x subexpression */ int regFree1 = 0; /* Temporary use register */ - Expr *pDel = 0; - sqlite3 *db = pParse->db; + memset(&compLeft, 0, sizeof(Expr)); memset(&compRight, 0, sizeof(Expr)); memset(&exprAnd, 0, sizeof(Expr)); - assert( ExprUseXList(pExpr) ); - pDel = sqlite3ExprDup(db, pExpr->pLeft, 0); - if( db->mallocFailed==0 ){ - exprAnd.op = TK_AND; - exprAnd.pLeft = &compLeft; - exprAnd.pRight = &compRight; - compLeft.op = TK_GE; - compLeft.pLeft = pDel; - compLeft.pRight = pExpr->x.pList->a[0].pExpr; - compRight.op = TK_LE; - compRight.pLeft = pDel; - compRight.pRight = pExpr->x.pList->a[1].pExpr; - sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1)); - 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_OuterON bit. Bummer. */ - pDel->flags |= EP_OuterON; - sqlite3ExprCodeTarget(pParse, &exprAnd, dest); - } - sqlite3ReleaseTempReg(pParse, regFree1); - } - sqlite3ExprDelete(db, pDel); + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + exprX = *pExpr->pLeft; + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = &exprX; + compLeft.pRight = pExpr->x.pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = &exprX; + compRight.pRight = pExpr->x.pList->a[1].pExpr; + exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); + 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); + } + sqlite3ReleaseTempReg(pParse, regFree1); /* Ensure adequate test coverage */ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1!=0 ); testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1==0 ); @@ -115372,61 +95878,42 @@ int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ if( NEVER(pExpr==0) ) return; /* No way this can happen */ - assert( !ExprHasVVAProperty(pExpr, EP_Immutable) ); op = pExpr->op; switch( op ){ - case TK_AND: + case TK_AND: { + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + sqlite3ExprCachePop(pParse); + break; + } case TK_OR: { - Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); - if( pAlt!=pExpr ){ - sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull); - }else if( op==TK_AND ){ - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, - jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - }else{ - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - } + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3ExprCachePop(pParse); break; } case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_TRUTH: { - int isNot; /* IS NOT TRUE or IS NOT FALSE */ - int isTrue; /* IS TRUE or IS NOT TRUE */ - testcase( jumpIfNull==0 ); - isNot = pExpr->op2==TK_ISNOT; - isTrue = sqlite3ExprTruthValue(pExpr->pRight); - testcase( isTrue && isNot ); - testcase( !isTrue && isNot ); - if( isTrue ^ isNot ){ - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, - isNot ? SQLITE_JUMPIFNULL : 0); - }else{ - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, - isNot ? SQLITE_JUMPIFNULL : 0); - } break; } case TK_IS: case TK_ISNOT: testcase( op==TK_IS ); testcase( op==TK_ISNOT ); op = (op==TK_IS) ? TK_EQ : TK_NE; jumpIfNull = SQLITE_NULLEQ; - /* no break */ deliberate_fall_through + /* Fall thru */ case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: @@ -115434,11 +95921,11 @@ if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted)); + r1, r2, dest, jumpIfNull); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); @@ -115454,11 +95941,10 @@ case TK_ISNULL: case TK_NOTNULL: { assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeTypeofColumn(v, r1); sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverageIf(v, op==TK_ISNULL); VdbeCoverageIf(v, op==TK_NOTNULL); testcase( regFree1==0 ); break; @@ -115468,23 +95954,23 @@ exprCodeBetween(pParse, pExpr, dest, sqlite3ExprIfTrue, jumpIfNull); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_IN: { - int destIfFalse = sqlite3VdbeMakeLabel(pParse); + int destIfFalse = sqlite3VdbeMakeLabel(v); int destIfNull = jumpIfNull ? dest : destIfFalse; sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); sqlite3VdbeGoto(v, dest); sqlite3VdbeResolveLabel(v, destIfFalse); break; } #endif default: { default_expr: - if( ExprAlwaysTrue(pExpr) ){ + if( exprAlwaysTrue(pExpr) ){ sqlite3VdbeGoto(v, dest); - }else if( ExprAlwaysFalse(pExpr) ){ + }else if( exprAlwaysFalse(pExpr) ){ /* No-op */ }else{ r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); VdbeCoverage(v); @@ -115493,11 +95979,11 @@ } break; } } sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); + sqlite3ReleaseTempReg(pParse, regFree2); } /* ** Generate code for a boolean expression such that a jump is made ** to the label "dest" if the expression is false but execution @@ -115515,11 +96001,10 @@ int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ if( pExpr==0 ) return; - assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); /* The value of pExpr->op and op are related as follows: ** ** pExpr->op op ** --------- ---------- @@ -115549,61 +96034,40 @@ assert( pExpr->op!=TK_LE || op==OP_Gt ); assert( pExpr->op!=TK_GT || op==OP_Le ); assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ - case TK_AND: + case TK_AND: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3ExprCachePop(pParse); + break; + } case TK_OR: { - Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); - if( pAlt!=pExpr ){ - sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull); - }else if( pExpr->op==TK_AND ){ - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - }else{ - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, - jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - } + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + sqlite3ExprCachePop(pParse); break; } case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_TRUTH: { - int isNot; /* IS NOT TRUE or IS NOT FALSE */ - int isTrue; /* IS TRUE or IS NOT TRUE */ - testcase( jumpIfNull==0 ); - isNot = pExpr->op2==TK_ISNOT; - isTrue = sqlite3ExprTruthValue(pExpr->pRight); - testcase( isTrue && isNot ); - testcase( !isTrue && isNot ); - if( isTrue ^ isNot ){ - /* IS TRUE and IS NOT FALSE */ - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, - isNot ? 0 : SQLITE_JUMPIFNULL); - - }else{ - /* IS FALSE and IS NOT TRUE */ - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, - isNot ? 0 : SQLITE_JUMPIFNULL); - } break; } case TK_IS: case TK_ISNOT: testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; jumpIfNull = SQLITE_NULLEQ; - /* no break */ deliberate_fall_through + /* Fall thru */ case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: @@ -115611,11 +96075,11 @@ if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted)); + r1, r2, dest, jumpIfNull); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); @@ -115629,11 +96093,10 @@ break; } case TK_ISNULL: case TK_NOTNULL: { r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeTypeofColumn(v, r1); sqlite3VdbeAddOp2(v, op, r1, dest); testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); testcase( regFree1==0 ); break; @@ -115646,22 +96109,22 @@ #ifndef SQLITE_OMIT_SUBQUERY case TK_IN: { if( jumpIfNull ){ sqlite3ExprCodeIN(pParse, pExpr, dest, dest); }else{ - int destIfNull = sqlite3VdbeMakeLabel(pParse); + int destIfNull = sqlite3VdbeMakeLabel(v); sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull); sqlite3VdbeResolveLabel(v, destIfNull); } break; } #endif default: { - default_expr: - if( ExprAlwaysFalse(pExpr) ){ + default_expr: + if( exprAlwaysFalse(pExpr) ){ sqlite3VdbeGoto(v, dest); - }else if( ExprAlwaysTrue(pExpr) ){ + }else if( exprAlwaysTrue(pExpr) ){ /* no-op */ }else{ r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); VdbeCoverage(v); @@ -115699,41 +96162,31 @@ ** ** 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. -** -** If the SQLITE_EnableQPSG flag is set on the database connection, then -** this routine always returns false. */ -static SQLITE_NOINLINE int exprCompareVariable( - const Parse *pParse, - const Expr *pVar, - const Expr *pExpr -){ - int res = 2; +static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){ + int res = 0; int iVar; sqlite3_value *pL, *pR = 0; - - if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){ - return 0; - } - if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2; + 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 = sqlite3MemCompare(pL, pR, 0) ? 2 : 0; + 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 @@ -115755,105 +96208,66 @@ ** can be sure the expressions are the same. In the places where ** this routine is used, it does not hurt to get an extra 2 - that ** 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 and SQLITE_EnableQPSG is off 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 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( - const Parse *pParse, - const Expr *pA, - const 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 ){ - return exprCompareVariable(pParse, pA, pB); + 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 ){ return 0; } return 2; } - if( pA->op!=pB->op || pA->op==TK_RAISE ){ + if( pA->op!=pB->op ){ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){ return 1; } if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){ return 1; } - if( pA->op==TK_AGG_COLUMN && pB->op==TK_COLUMN - && pB->iTable<0 && pA->iTable==iTab - ){ - /* fall through */ - }else{ - return 2; - } - } - assert( !ExprHasProperty(pA, EP_IntValue) ); - assert( !ExprHasProperty(pB, EP_IntValue) ); - if( pA->u.zToken ){ - if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){ + return 2; + } + if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ + if( pA->op==TK_FUNCTION ){ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; -#ifndef SQLITE_OMIT_WINDOWFUNC - assert( pA->op==pB->op ); - if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){ - return 2; - } - if( ExprHasProperty(pA,EP_WinFunc) ){ - if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){ - return 2; - } - } -#endif - }else if( pA->op==TK_NULL ){ - return 0; - }else if( pA->op==TK_COLLATE ){ - if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; - }else - if( pB->u.zToken!=0 - && pA->op!=TK_COLUMN - && pA->op!=TK_AGG_COLUMN - && strcmp(pA->u.zToken,pB->u.zToken)!=0 - ){ - return 2; - } - } - if( (pA->flags & (EP_Distinct|EP_Commuted)) - != (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2; + }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ + return pA->op==TK_COLLATE ? 1 : 2; + } + } + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ if( combinedFlags & EP_xIsSelect ) return 2; - if( (combinedFlags & EP_FixedCol)==0 - && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, 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( pA->op!=TK_STRING - && pA->op!=TK_TRUEFALSE - && ALWAYS((combinedFlags & EP_Reduced)==0) - ){ + if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ if( pA->iColumn!=pB->iColumn ) return 2; - if( pA->op2!=pB->op2 && pA->op==TK_TRUTH ) return 2; - if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){ - return 2; - } + if( pA->iTable!=pB->iTable + && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } } return 0; } /* -** Compare two ExprList objects. Return 0 if they are identical, 1 -** if they are certainly different, or 2 if it is not possible to -** determine if they are identical or not. +** Compare two ExprList objects. Return 0 if they are identical and +** non-zero if they differ in any way. ** ** If any subelement of pB has Expr.iTable==(-1) then it is allowed ** to compare equal to an equivalent element in pA with Expr.iTable==iTab. ** ** This routine might return non-zero for equivalent ExprLists. The @@ -115862,397 +96276,78 @@ ** a malfunction will result. ** ** Two NULL pointers are considered to be the same. But a NULL pointer ** always differs from a non-NULL pointer. */ -SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB, int iTab){ +SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ int i; if( pA==0 && pB==0 ) return 0; if( pA==0 || pB==0 ) return 1; if( pA->nExpr!=pB->nExpr ) return 1; for(i=0; inExpr; i++){ - int res; Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; - if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1; - if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res; + if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) 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){ +SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ return sqlite3ExprCompare(0, sqlite3ExprSkipCollate(pA), sqlite3ExprSkipCollate(pB), iTab); } -/* -** Return non-zero if Expr p can only be true if pNN is not NULL. -** -** Or if seenNot is true, return non-zero if Expr p can only be -** non-NULL if pNN is not NULL -*/ -static int exprImpliesNotNull( - const Parse *pParse,/* Parsing context */ - const Expr *p, /* The expression to be checked */ - const Expr *pNN, /* The expression that is NOT NULL */ - int iTab, /* Table being evaluated */ - int seenNot /* Return true only if p can be any non-NULL value */ -){ - assert( p ); - assert( pNN ); - if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){ - return pNN->op!=TK_NULL; - } - switch( p->op ){ - case TK_IN: { - if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0; - assert( ExprUseXSelect(p) || (p->x.pList!=0 && p->x.pList->nExpr>0) ); - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - case TK_BETWEEN: { - ExprList *pList; - assert( ExprUseXList(p) ); - pList = p->x.pList; - assert( pList!=0 ); - assert( pList->nExpr==2 ); - if( seenNot ) return 0; - if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1) - || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1) - ){ - return 1; - } - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - case TK_EQ: - case TK_NE: - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_PLUS: - case TK_MINUS: - case TK_BITOR: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_CONCAT: - seenNot = 1; - /* no break */ deliberate_fall_through - case TK_STAR: - case TK_REM: - case TK_BITAND: - case TK_SLASH: { - if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1; - /* no break */ deliberate_fall_through - } - case TK_SPAN: - case TK_COLLATE: - case TK_UPLUS: - case TK_UMINUS: { - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); - } - case TK_TRUTH: { - if( seenNot ) return 0; - if( p->op2!=TK_IS ) return 0; - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - case TK_BITNOT: - case TK_NOT: { - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); - } - } - return 0; -} - -/* -** Return true if the boolean value of the expression is always either -** FALSE or NULL. -*/ -static int sqlite3ExprIsNotTrue(Expr *pExpr){ - int v; - if( pExpr->op==TK_NULL ) return 1; - if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1; - v = 1; - if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1; - return 0; -} - -/* -** Return true if the expression is one of the following: -** -** CASE WHEN x THEN y END -** CASE WHEN x THEN y ELSE NULL END -** CASE WHEN x THEN y ELSE false END -** iif(x,y) -** iif(x,y,NULL) -** iif(x,y,false) -*/ -static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){ - ExprList *pList; - if( pExpr->op==TK_FUNCTION ){ - const char *z = pExpr->u.zToken; - FuncDef *pDef; - if( (z[0]!='i' && z[0]!='I') ) return 0; - if( pExpr->x.pList==0 ) return 0; - pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pDef==0 ) return 0; -#else - if( NEVER(pDef==0) ) return 0; -#endif - if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0; - if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0; - }else if( pExpr->op==TK_CASE ){ - if( pExpr->pLeft!=0 ) return 0; - }else{ - return 0; - } - pList = pExpr->x.pList; - assert( pList!=0 ); - if( pList->nExpr==2 ) return 1; - if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1; - return 0; -} - /* ** 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 ** be false. Examples: ** -** pE1: x==5 pE2: x==5 Result: true -** pE1: x>0 pE2: x==5 Result: false -** pE1: x=21 pE2: x=21 OR y=43 Result: true -** pE1: x!=123 pE2: x IS NOT NULL Result: true -** pE1: x!=?1 pE2: x IS NOT NULL Result: true -** pE1: x IS NULL pE2: x IS NOT NULL Result: false -** pE1: x IS ?2 pE2: x IS NOT NULL Result: false -** pE1: iif(x,y) pE2: x Result: true -** PE1: iif(x,y,0) pE2: x Result: true +** pE1: x==5 pE2: x==5 Result: true +** pE1: x>0 pE2: x==5 Result: false +** pE1: x=21 pE2: x=21 OR y=43 Result: true +** pE1: x!=123 pE2: x IS NOT NULL Result: true +** pE1: x!=?1 pE2: x IS NOT NULL Result: true +** pE1: x IS NULL pE2: x IS NOT NULL Result: false +** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false ** ** 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 +** 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 +** 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( - const Parse *pParse, - const Expr *pE1, - const Expr *pE2, - int iTab -){ +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(pParse, pE1, pE2->pLeft, iTab) || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) ) ){ return 1; } - if( pE2->op==TK_NOTNULL - && exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0) - ){ - return 1; - } - if( sqlite3ExprIsIIF(pParse->db, pE1) ){ - return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab); + 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; } -/* This is a helper function to impliesNotNullRow(). In this routine, -** set pWalker->eCode to one only if *both* of the input expressions -** separately have the implies-not-null-row property. -*/ -static void bothImplyNotNullRow(Walker *pWalker, Expr *pE1, Expr *pE2){ - if( pWalker->eCode==0 ){ - sqlite3WalkExpr(pWalker, pE1); - if( pWalker->eCode ){ - pWalker->eCode = 0; - sqlite3WalkExpr(pWalker, pE2); - } - } -} - -/* -** This is the Expr node callback for sqlite3ExprImpliesNonNullRow(). -** If the expression node requires that the table at pWalker->iCur -** have one or more non-NULL column, then set pWalker->eCode to 1 and abort. -** -** pWalker->mWFlags is non-zero if this inquiry is being undertaking on -** behalf of a RIGHT JOIN (or FULL JOIN). That makes a difference when -** evaluating terms in the ON clause of an inner join. -** -** This routine controls an optimization. False positives (setting -** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives -** (never setting pWalker->eCode) is a harmless missed optimization. -*/ -static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ - testcase( pExpr->op==TK_AGG_COLUMN ); - testcase( pExpr->op==TK_AGG_FUNCTION ); - if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune; - if( ExprHasProperty(pExpr, EP_InnerON) && pWalker->mWFlags ){ - /* If iCur is used in an inner-join ON clause to the left of a - ** RIGHT JOIN, that does *not* mean that the table must be non-null. - ** But it is difficult to check for that condition precisely. - ** To keep things simple, any use of iCur from any inner-join is - ** ignored while attempting to simplify a RIGHT JOIN. */ - return WRC_Prune; - } - switch( pExpr->op ){ - case TK_ISNOT: - case TK_ISNULL: - case TK_NOTNULL: - case TK_IS: - case TK_VECTOR: - case TK_FUNCTION: - case TK_TRUTH: - case TK_CASE: - testcase( pExpr->op==TK_ISNOT ); - testcase( pExpr->op==TK_ISNULL ); - testcase( pExpr->op==TK_NOTNULL ); - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_VECTOR ); - testcase( pExpr->op==TK_FUNCTION ); - testcase( pExpr->op==TK_TRUTH ); - testcase( pExpr->op==TK_CASE ); - return WRC_Prune; - - case TK_COLUMN: - if( pWalker->u.iCur==pExpr->iTable ){ - pWalker->eCode = 1; - return WRC_Abort; - } - return WRC_Prune; - - case TK_OR: - case TK_AND: - /* Both sides of an AND or OR must separately imply non-null-row. - ** Consider these cases: - ** 1. NOT (x AND y) - ** 2. x OR y - ** If only one of x or y is non-null-row, then the overall expression - ** can be true if the other arm is false (case 1) or true (case 2). - */ - testcase( pExpr->op==TK_OR ); - testcase( pExpr->op==TK_AND ); - bothImplyNotNullRow(pWalker, pExpr->pLeft, pExpr->pRight); - return WRC_Prune; - - case TK_IN: - /* Beware of "x NOT IN ()" and "x NOT IN (SELECT 1 WHERE false)", - ** both of which can be true. But apart from these cases, if - ** the left-hand side of the IN is NULL then the IN itself will be - ** NULL. */ - if( ExprUseXList(pExpr) && ALWAYS(pExpr->x.pList->nExpr>0) ){ - sqlite3WalkExpr(pWalker, pExpr->pLeft); - } - return WRC_Prune; - - case TK_BETWEEN: - /* In "x NOT BETWEEN y AND z" either x must be non-null-row or else - ** both y and z must be non-null row */ - assert( ExprUseXList(pExpr) ); - assert( pExpr->x.pList->nExpr==2 ); - sqlite3WalkExpr(pWalker, pExpr->pLeft); - bothImplyNotNullRow(pWalker, pExpr->x.pList->a[0].pExpr, - pExpr->x.pList->a[1].pExpr); - return WRC_Prune; - - /* Virtual tables are allowed to use constraints like x=NULL. So - ** a term of the form x=y does not prove that y is not null if x - ** is the column of a virtual table */ - case TK_EQ: - case TK_NE: - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: { - Expr *pLeft = pExpr->pLeft; - Expr *pRight = pExpr->pRight; - testcase( pExpr->op==TK_EQ ); - testcase( pExpr->op==TK_NE ); - testcase( pExpr->op==TK_LT ); - testcase( pExpr->op==TK_LE ); - testcase( pExpr->op==TK_GT ); - testcase( pExpr->op==TK_GE ); - /* The y.pTab=0 assignment in wherecode.c always happens after the - ** impliesNotNullRow() test */ - assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) ); - assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) ); - if( (pLeft->op==TK_COLUMN - && ALWAYS(pLeft->y.pTab!=0) - && IsVirtual(pLeft->y.pTab)) - || (pRight->op==TK_COLUMN - && ALWAYS(pRight->y.pTab!=0) - && IsVirtual(pRight->y.pTab)) - ){ - return WRC_Prune; - } - /* no break */ deliberate_fall_through - } - default: - return WRC_Continue; - } -} - -/* -** Return true (non-zero) if expression p can only be true if at least -** one column of table iTab is non-null. In other words, return true -** if expression p will always be NULL or false if every column of iTab -** is NULL. -** -** False negatives are acceptable. In other words, it is ok to return -** zero even if expression p will never be true of every column of iTab -** is NULL. A false negative is merely a missed optimization opportunity. -** -** False positives are not allowed, however. A false positive may result -** in an incorrect answer. -** -** Terms of p that are marked with EP_OuterON (and hence that come from -** the ON or USING clauses of OUTER JOINS) are excluded from the analysis. -** -** This routine is used to check if a LEFT JOIN can be converted into -** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE -** clause requires that some column of the right table of the LEFT JOIN -** be non-NULL, then the LEFT JOIN can be safely converted into an -** ordinary join. -*/ -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){ - Walker w; - p = sqlite3ExprSkipCollateAndLikely(p); - if( p==0 ) return 0; - if( p->op==TK_NOTNULL ){ - p = p->pLeft; - }else{ - while( p->op==TK_AND ){ - if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1; - p = p->pRight; - } - } - w.xExprCallback = impliesNotNullRow; - w.xSelectCallback = 0; - w.xSelectCallback2 = 0; - w.eCode = 0; - w.mWFlags = isRJ!=0; - w.u.iCur = iTab; - sqlite3WalkExpr(&w, p); - return w.eCode; -} - /* ** An instance of the following structure is used by the tree walker ** to determine if an expression can be evaluated by reference to the ** index only, without having to do a search for the corresponding ** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur @@ -116262,18 +96357,18 @@ Index *pIdx; /* The index to be tested for coverage */ int iCur; /* Cursor number for the table corresponding to the index */ }; /* -** Check to see if there are references to columns in table +** Check to see if there are references to columns in table ** pWalker->u.pIdxCover->iCur can be satisfied using the index ** pWalker->u.pIdxCover->pIdx. */ static int exprIdxCover(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_COLUMN && pExpr->iTable==pWalker->u.pIdxCover->iCur - && sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0 + && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0 ){ pWalker->eCode = 1; return WRC_Abort; } return WRC_Continue; @@ -116304,191 +96399,66 @@ sqlite3WalkExpr(&w, pExpr); return !w.eCode; } -/* Structure used to pass information throughout the Walker in order to -** implement sqlite3ReferencesSrcList(). +/* +** An instance of the following structure is used by the tree walker +** to count references to table columns in the arguments of an +** aggregate function, in order to implement the +** sqlite3FunctionThisSrc() routine. */ -struct RefSrcList { - sqlite3 *db; /* Database connection used for sqlite3DbRealloc() */ - SrcList *pRef; /* Looking for references to these tables */ - i64 nExclude; /* Number of tables to exclude from the search */ - int *aiExclude; /* Cursor IDs for tables to exclude from the search */ +struct SrcCount { + SrcList *pSrc; /* One particular FROM clause in a nested query */ + int nThis; /* Number of references to columns in pSrcList */ + int nOther; /* Number of references to columns in other FROM clauses */ }; /* -** Walker SELECT callbacks for sqlite3ReferencesSrcList(). -** -** When entering a new subquery on the pExpr argument, add all FROM clause -** entries for that subquery to the exclude list. -** -** When leaving the subquery, remove those entries from the exclude list. -*/ -static int selectRefEnter(Walker *pWalker, Select *pSelect){ - struct RefSrcList *p = pWalker->u.pRefSrcList; - SrcList *pSrc = pSelect->pSrc; - i64 i, j; - int *piNew; - if( pSrc->nSrc==0 ) return WRC_Continue; - j = p->nExclude; - p->nExclude += pSrc->nSrc; - piNew = sqlite3DbRealloc(p->db, p->aiExclude, p->nExclude*sizeof(int)); - if( piNew==0 ){ - p->nExclude = 0; - return WRC_Abort; - }else{ - p->aiExclude = piNew; - } - for(i=0; inSrc; i++, j++){ - p->aiExclude[j] = pSrc->a[i].iCursor; - } - return WRC_Continue; -} -static void selectRefLeave(Walker *pWalker, Select *pSelect){ - struct RefSrcList *p = pWalker->u.pRefSrcList; - SrcList *pSrc = pSelect->pSrc; - if( p->nExclude ){ - assert( p->nExclude>=pSrc->nSrc ); - p->nExclude -= pSrc->nSrc; - } -} - -/* This is the Walker EXPR callback for sqlite3ReferencesSrcList(). -** -** Set the 0x01 bit of pWalker->eCode if there is a reference to any -** of the tables shown in RefSrcList.pRef. -** -** Set the 0x02 bit of pWalker->eCode if there is a reference to a -** table is in neither RefSrcList.pRef nor RefSrcList.aiExclude. -*/ -static int exprRefToSrcList(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN - || pExpr->op==TK_AGG_COLUMN - ){ - int i; - struct RefSrcList *p = pWalker->u.pRefSrcList; - SrcList *pSrc = p->pRef; +** Count the number of references to columns. +*/ +static int exprSrcCount(Walker *pWalker, Expr *pExpr){ + /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc() + ** is always called before sqlite3ExprAnalyzeAggregates() and so the + ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If + ** sqlite3FunctionUsesThisSrc() is used differently in the future, the + ** NEVER() will need to be removed. */ + if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){ + int i; + struct SrcCount *p = pWalker->u.pSrcCount; + SrcList *pSrc = p->pSrc; int nSrc = pSrc ? pSrc->nSrc : 0; for(i=0; iiTable==pSrc->a[i].iCursor ){ - pWalker->eCode |= 1; - return WRC_Continue; - } - } - for(i=0; inExclude && p->aiExclude[i]!=pExpr->iTable; i++){} - if( i>=p->nExclude ){ - pWalker->eCode |= 2; + if( pExpr->iTable==pSrc->a[i].iCursor ) break; + } + if( inThis++; + }else{ + p->nOther++; } } return WRC_Continue; } /* -** Check to see if pExpr references any tables in pSrcList. -** Possible return values: -** -** 1 pExpr does references a table in pSrcList. -** -** 0 pExpr references some table that is not defined in either -** pSrcList or in subqueries of pExpr itself. -** -** -1 pExpr only references no tables at all, or it only -** references tables defined in subqueries of pExpr itself. -** -** As currently used, pExpr is always an aggregate function call. That -** fact is exploited for efficiency. +** Determine if any of the arguments to the pExpr Function reference +** pSrcList. Return true if they do. Also return true if the function +** has no arguments or has only constant arguments. Return false if pExpr +** references columns but not columns of tables found in pSrcList. */ -SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList *pSrcList){ +SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ Walker w; - struct RefSrcList x; - assert( pParse->db!=0 ); - memset(&w, 0, sizeof(w)); - memset(&x, 0, sizeof(x)); - w.xExprCallback = exprRefToSrcList; - w.xSelectCallback = selectRefEnter; - w.xSelectCallback2 = selectRefLeave; - w.u.pRefSrcList = &x; - x.db = pParse->db; - x.pRef = pSrcList; + struct SrcCount cnt; assert( pExpr->op==TK_AGG_FUNCTION ); - assert( ExprUseXList(pExpr) ); + w.xExprCallback = exprSrcCount; + w.xSelectCallback = 0; + w.u.pSrcCount = &cnt; + cnt.pSrc = pSrcList; + cnt.nThis = 0; + cnt.nOther = 0; sqlite3WalkExprList(&w, pExpr->x.pList); - if( pExpr->pLeft ){ - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - assert( pExpr->pLeft->x.pList!=0 ); - sqlite3WalkExprList(&w, pExpr->pLeft->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter); - } -#endif - if( x.aiExclude ) sqlite3DbNNFreeNN(pParse->db, x.aiExclude); - if( w.eCode & 0x01 ){ - return 1; - }else if( w.eCode ){ - return 0; - }else{ - return -1; - } -} - -/* -** This is a Walker expression node callback. -** -** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo -** object that is referenced does not refer directly to the Expr. If -** it does, make a copy. This is done because the pExpr argument is -** subject to change. -** -** The copy is scheduled for deletion using the sqlite3ExprDeferredDelete() -** which builds on the sqlite3ParserAddCleanup() mechanism. -*/ -static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ - if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced)) - && pExpr->pAggInfo!=0 - ){ - AggInfo *pAggInfo = pExpr->pAggInfo; - int iAgg = pExpr->iAgg; - Parse *pParse = pWalker->pParse; - sqlite3 *db = pParse->db; - assert( iAgg>=0 ); - if( pExpr->op!=TK_AGG_FUNCTION ){ - if( iAggnColumn - && pAggInfo->aCol[iAgg].pCExpr==pExpr - ){ - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){ - pAggInfo->aCol[iAgg].pCExpr = pExpr; - } - } - }else{ - assert( pExpr->op==TK_AGG_FUNCTION ); - if( ALWAYS(iAggnFunc) - && pAggInfo->aFunc[iAgg].pFExpr==pExpr - ){ - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){ - pAggInfo->aFunc[iAgg].pFExpr = pExpr; - } - } - } - } - return WRC_Continue; -} - -/* -** Initialize a Walker object so that will persist AggInfo entries referenced -** by the tree that is walked. -*/ -SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker *pWalker, Parse *pParse){ - memset(pWalker, 0, sizeof(*pWalker)); - pWalker->pParse = pParse; - pWalker->xExprCallback = agginfoPersistExprCb; - pWalker->xSelectCallback = sqlite3SelectWalkNoop; + return cnt.nThis>0 || cnt.nOther==0; } /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. @@ -116501,95 +96471,27 @@ sizeof(pInfo->aCol[0]), &pInfo->nColumn, &i ); return i; -} +} /* ** Add a new element to the pAggInfo->aFunc[] array. Return the index of ** the new element. Return a negative number if malloc fails. */ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ int i; pInfo->aFunc = sqlite3ArrayAllocate( - db, + db, pInfo->aFunc, sizeof(pInfo->aFunc[0]), &pInfo->nFunc, &i ); return i; -} - -/* -** Search the AggInfo object for an aCol[] entry that has iTable and iColumn. -** Return the index in aCol[] of the entry that describes that column. -** -** If no prior entry is found, create a new one and return -1. The -** new column will have an index of pAggInfo->nColumn-1. -*/ -static void findOrCreateAggInfoColumn( - Parse *pParse, /* Parsing context */ - AggInfo *pAggInfo, /* The AggInfo object to search and/or modify */ - Expr *pExpr /* Expr describing the column to find or insert */ -){ - struct AggInfo_col *pCol; - int k; - - assert( pAggInfo->iFirstReg==0 ); - pCol = pAggInfo->aCol; - for(k=0; knColumn; k++, pCol++){ - if( pCol->pCExpr==pExpr ) return; - if( pCol->iTable==pExpr->iTable - && pCol->iColumn==pExpr->iColumn - && pExpr->op!=TK_IF_NULL_ROW - ){ - goto fix_up_expr; - } - } - k = addAggInfoColumn(pParse->db, pAggInfo); - if( k<0 ){ - /* OOM on resize */ - assert( pParse->db->mallocFailed ); - return; - } - pCol = &pAggInfo->aCol[k]; - assert( ExprUseYTab(pExpr) ); - pCol->pTab = pExpr->y.pTab; - pCol->iTable = pExpr->iTable; - pCol->iColumn = pExpr->iColumn; - pCol->iSorterColumn = -1; - pCol->pCExpr = pExpr; - if( pAggInfo->pGroupBy && pExpr->op!=TK_IF_NULL_ROW ){ - int j, n; - ExprList *pGB = pAggInfo->pGroupBy; - struct ExprList_item *pTerm = pGB->a; - n = pGB->nExpr; - for(j=0; jpExpr; - if( pE->op==TK_COLUMN - && pE->iTable==pExpr->iTable - && pE->iColumn==pExpr->iColumn - ){ - pCol->iSorterColumn = j; - break; - } - } - } - if( pCol->iSorterColumn<0 ){ - pCol->iSorterColumn = pAggInfo->nSortingColumn++; - } -fix_up_expr: - ExprSetVVAProperty(pExpr, EP_NoReduce); - assert( pExpr->pAggInfo==0 || pExpr->pAggInfo==pAggInfo ); - pExpr->pAggInfo = pAggInfo; - if( pExpr->op==TK_COLUMN ){ - pExpr->op = TK_AGG_COLUMN; - } - pExpr->iAgg = (i16)k; -} +} /* ** This is the xExprCallback for a tree walker. It is used to ** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates ** for additional information. @@ -116597,131 +96499,110 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ int i; NameContext *pNC = pWalker->u.pNC; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; - AggInfo *pAggInfo = pNC->uNC.pAggInfo; - - assert( pNC->ncFlags & NC_UAggInfo ); - assert( pAggInfo->iFirstReg==0 ); - switch( pExpr->op ){ - default: { - IndexedExpr *pIEpr; - Expr tmp; - assert( pParse->iSelfTab==0 ); - if( (pNC->ncFlags & NC_InAggFunc)==0 ) break; - if( pParse->pIdxEpr==0 ) break; - for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){ - int iDataCur = pIEpr->iDataCur; - if( iDataCur<0 ) continue; - if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break; - } - if( pIEpr==0 ) break; - if( NEVER(!ExprUseYTab(pExpr)) ) break; - for(i=0; inSrc; i++){ - if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break; - } - if( i>=pSrcList->nSrc ) break; - if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */ - if( pParse->nErr ){ return WRC_Abort; } - - /* If we reach this point, it means that expression pExpr can be - ** translated into a reference to an index column as described by - ** pIEpr. - */ - memset(&tmp, 0, sizeof(tmp)); - tmp.op = TK_AGG_COLUMN; - tmp.iTable = pIEpr->iIdxCur; - tmp.iColumn = pIEpr->iIdxCol; - findOrCreateAggInfoColumn(pParse, pAggInfo, &tmp); - if( pParse->nErr ){ return WRC_Abort; } - assert( pAggInfo->aCol!=0 ); - assert( tmp.iAggnColumn ); - pAggInfo->aCol[tmp.iAgg].pCExpr = pExpr; - pExpr->pAggInfo = pAggInfo; - pExpr->iAgg = tmp.iAgg; - return WRC_Prune; - } - case TK_IF_NULL_ROW: + AggInfo *pAggInfo = pNC->pAggInfo; + + switch( pExpr->op ){ case TK_AGG_COLUMN: case TK_COLUMN: { testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_COLUMN ); - testcase( pExpr->op==TK_IF_NULL_ROW ); /* Check to see if the column is in one of the tables in the FROM ** clause of the aggregate query */ if( ALWAYS(pSrcList!=0) ){ - SrcItem *pItem = pSrcList->a; + struct SrcList_item *pItem = pSrcList->a; for(i=0; inSrc; i++, pItem++){ + struct AggInfo_col *pCol; assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ - findOrCreateAggInfoColumn(pParse, pAggInfo, pExpr); + /* If we reach this point, it means that pExpr refers to a table + ** that is in the FROM clause of the aggregate query. + ** + ** Make an entry for the column in pAggInfo->aCol[] if there + ** is not an entry there already. + */ + int k; + pCol = pAggInfo->aCol; + for(k=0; knColumn; k++, pCol++){ + if( pCol->iTable==pExpr->iTable && + pCol->iColumn==pExpr->iColumn ){ + break; + } + } + if( (k>=pAggInfo->nColumn) + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = ++pParse->nMem; + pCol->iSorterColumn = -1; + pCol->pExpr = pExpr; + if( pAggInfo->pGroupBy ){ + int j, n; + ExprList *pGB = pAggInfo->pGroupBy; + struct ExprList_item *pTerm = pGB->a; + n = pGB->nExpr; + for(j=0; jpExpr; + if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && + pE->iColumn==pExpr->iColumn ){ + pCol->iSorterColumn = j; + break; + } + } + } + if( pCol->iSorterColumn<0 ){ + pCol->iSorterColumn = pAggInfo->nSortingColumn++; + } + } + /* There is now an entry for pExpr in pAggInfo->aCol[] (either + ** because it was there before or because we just created it). + ** Convert the pExpr to be a TK_AGG_COLUMN referring to that + ** pAggInfo->aCol[] entry. + */ + ExprSetVVAProperty(pExpr, EP_NoReduce); + pExpr->pAggInfo = pAggInfo; + pExpr->op = TK_AGG_COLUMN; + pExpr->iAgg = (i16)k; break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } - return WRC_Continue; + return WRC_Prune; } case TK_AGG_FUNCTION: { if( (pNC->ncFlags & NC_InAggFunc)==0 && pWalker->walkerDepth==pExpr->op2 - && pExpr->pAggInfo==0 ){ - /* Check to see if pExpr is a duplicate of another aggregate + /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; inFunc; i++, pItem++){ - if( NEVER(pItem->pFExpr==pExpr) ) break; - if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){ + if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){ break; } } if( i>=pAggInfo->nFunc ){ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ u8 enc = ENC(pParse->db); i = addAggInfoFunc(pParse->db, pAggInfo); if( i>=0 ){ - int nArg; assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); pItem = &pAggInfo->aFunc[i]; - pItem->pFExpr = pExpr; - assert( ExprUseUToken(pExpr) ); - nArg = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; + pItem->pExpr = pExpr; + pItem->iMem = ++pParse->nMem; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->u.zToken, nArg, enc, 0); - assert( pItem->bOBUnique==0 ); - if( pExpr->pLeft - && (pItem->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)==0 - ){ - /* The NEEDCOLL test above causes any ORDER BY clause on - ** aggregate min() or max() to be ignored. */ - ExprList *pOBList; - assert( nArg>0 ); - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - pItem->iOBTab = pParse->nTab++; - pOBList = pExpr->pLeft->x.pList; - assert( pOBList->nExpr>0 ); - assert( pItem->bOBUnique==0 ); - if( pOBList->nExpr==1 - && nArg==1 - && sqlite3ExprCompare(0,pOBList->a[0].pExpr, - pExpr->x.pList->a[0].pExpr,0)==0 - ){ - pItem->bOBPayload = 0; - pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); - }else{ - pItem->bOBPayload = 1; - } - pItem->bUseSubtype = - (pItem->pFunc->funcFlags & SQLITE_SUBTYPE)!=0; - }else{ - pItem->iOBTab = -1; - } - if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){ + pExpr->u.zToken, + pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); + if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; }else{ pItem->iDistinct = -1; } } @@ -116738,10 +96619,19 @@ } } } return WRC_Continue; } +static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ + 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 ** for variables that need to be added to AggInfo object that pNC->pAggInfo ** points to. Additional entries are made on the AggInfo object as @@ -116751,15 +96641,14 @@ ** analyzed by sqlite3ResolveExprNames(). */ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; w.xExprCallback = analyzeAggregate; - w.xSelectCallback = sqlite3WalkerDepthIncrease; - w.xSelectCallback2 = sqlite3WalkerDepthDecrease; + w.xSelectCallback = analyzeAggregatesInSelect; + w.xSelectCallback2 = analyzeAggregatesInSelectEnd; w.walkerDepth = 0; w.u.pNC = pNC; - w.pParse = 0; assert( pNC->pSrcList!=0 ); sqlite3WalkExpr(&w, pExpr); } /* @@ -116789,17 +96678,26 @@ } /* ** Deallocate a register, making available for reuse for some other ** purpose. +** +** If a register is currently being used by the column cache, then +** the deallocation is deferred until the column cache line that uses +** the register becomes stale. */ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ - if( iReg ){ - sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0); - if( pParse->nTempRegaTempReg) ){ - pParse->aTempReg[pParse->nTempReg++] = iReg; + if( iReg && pParse->nTempRegaTempReg) ){ + int i; + struct yColCache *p; + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + if( p->iReg==iReg ){ + p->tempReg = 1; + return; + } } + pParse->aTempReg[pParse->nTempReg++] = iReg; } } /* ** Allocate or deallocate a block of nReg consecutive registers. @@ -116808,10 +96706,11 @@ int i, n; if( nReg==1 ) return sqlite3GetTempReg(pParse); i = pParse->iRangeReg; n = pParse->nRangeReg; if( nReg<=n ){ + assert( !usedAsColumnCache(pParse, i, i+n-1) ); pParse->iRangeReg += nReg; pParse->nRangeReg -= nReg; }else{ i = pParse->nMem+1; pParse->nMem += nReg; @@ -116821,88 +96720,44 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, iReg); return; } - sqlite3VdbeReleaseRegisters(pParse, iReg, nReg, 0, 0); + sqlite3ExprCacheRemove(pParse, iReg, nReg); if( nReg>pParse->nRangeReg ){ pParse->nRangeReg = nReg; pParse->iRangeReg = iReg; } } /* ** Mark all temporary registers as being unavailable for reuse. -** -** Always invoke this procedure after coding a subroutine or co-routine -** that might be invoked from other parts of the code, to ensure that -** the sub/co-routine does not use registers in common with the code that -** invokes the sub/co-routine. */ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ pParse->nTempReg = 0; pParse->nRangeReg = 0; } -/* -** Make sure sufficient registers have been allocated so that -** iReg is a valid register number. -*/ -SQLITE_PRIVATE void sqlite3TouchRegister(Parse *pParse, int iReg){ - if( pParse->nMemnMem = iReg; -} - -#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_DEBUG) -/* -** Return the latest reusable register in the set of all registers. -** The value returned is no less than iMin. If any register iMin or -** greater is in permanent use, then return one more than that last -** permanent register. -*/ -SQLITE_PRIVATE int sqlite3FirstAvailableRegister(Parse *pParse, int iMin){ - const ExprList *pList = pParse->pConstExpr; - if( pList ){ - int i; - for(i=0; inExpr; i++){ - if( pList->a[i].u.iConstExprReg>=iMin ){ - iMin = pList->a[i].u.iConstExprReg + 1; - } - } - } - pParse->nTempReg = 0; - pParse->nRangeReg = 0; - return iMin; -} -#endif /* SQLITE_ENABLE_STAT4 || SQLITE_DEBUG */ - /* ** Validate that no temporary register falls within the range of ** iFirst..iLast, inclusive. This routine is only call from within assert() ** statements. */ #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){ int i; if( pParse->nRangeReg>0 - && pParse->iRangeReg+pParse->nRangeReg > iFirst - && pParse->iRangeReg <= iLast + && pParse->iRangeReg+pParse->nRangeRegiRangeReg>=iFirst ){ return 0; } for(i=0; inTempReg; i++){ if( pParse->aTempReg[i]>=iFirst && pParse->aTempReg[i]<=iLast ){ return 0; } } - if( pParse->pConstExpr ){ - ExprList *pList = pParse->pConstExpr; - for(i=0; inExpr; i++){ - int iReg = pList->a[i].u.iConstExprReg; - if( iReg==0 ) continue; - if( iReg>=iFirst && iReg<=iLast ) return 0; - } - } return 1; } #endif /* SQLITE_DEBUG */ /************** End of expr.c ************************************************/ @@ -116927,163 +96782,431 @@ ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ #ifndef SQLITE_OMIT_ALTERTABLE + +/* +** This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TABLE or +** CREATE INDEX command. The second is a table name. The table name in +** the CREATE TABLE or CREATE INDEX statement is replaced with the third +** argument and the result returned. Examples: +** +** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') +** -> 'CREATE TABLE def(a, b, c)' +** +** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') +** -> 'CREATE INDEX i ON def(a, b, c)' +*/ +static void renameTableFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + + sqlite3 *db = sqlite3_context_db_handle(context); + + UNUSED_PARAMETER(NotUsed); + + /* The principle used to locate the table name in the CREATE TABLE + ** statement is that the table name is the first non-space token that + ** is immediately followed by a TK_LP or TK_USING token. + */ + if( zSql ){ + do { + if( !*zCsr ){ + /* Ran out of input before finding an opening bracket. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = (char*)zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + } while( token==TK_SPACE ); + assert( len>0 ); + } while( token!=TK_LP && token!=TK_USING ); + + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); + } +} + +/* +** This C function implements an SQL user function that is used by SQL code +** generated by the ALTER TABLE ... RENAME command to modify the definition +** of any foreign key constraints that use the table being renamed as the +** parent table. It is passed three arguments: +** +** 1) The complete text of the CREATE TABLE statement being modified, +** 2) The old name of the table being renamed, and +** 3) The new name of the table being renamed. +** +** It returns the new CREATE TABLE statement. For example: +** +** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') +** -> 'CREATE TABLE t1(a REFERENCES t3)' +*/ +#ifndef SQLITE_OMIT_FOREIGN_KEY +static void renameParentFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + char *zOutput = 0; + char *zResult; + unsigned char const *zInput = sqlite3_value_text(argv[0]); + unsigned char const *zOld = sqlite3_value_text(argv[1]); + unsigned char const *zNew = sqlite3_value_text(argv[2]); + + unsigned const char *z; /* Pointer to token */ + int n; /* Length of token z */ + int token; /* Type of token */ + + UNUSED_PARAMETER(NotUsed); + if( zInput==0 || zOld==0 ) return; + for(z=zInput; *z; z=z+n){ + n = sqlite3GetToken(z, &token); + if( token==TK_REFERENCES ){ + char *zParent; + do { + z += n; + n = sqlite3GetToken(z, &token); + }while( token==TK_SPACE ); + + if( token==TK_ILLEGAL ) break; + zParent = sqlite3DbStrNDup(db, (const char *)z, n); + if( zParent==0 ) break; + sqlite3Dequote(zParent); + if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ + char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", + (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew + ); + sqlite3DbFree(db, zOutput); + zOutput = zOut; + zInput = &z[n]; + } + sqlite3DbFree(db, zParent); + } + } + + zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), + sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); + sqlite3DbFree(db, zOutput); +} +#endif + +#ifndef SQLITE_OMIT_TRIGGER +/* This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER +** statement. The second is a table name. The table name in the CREATE +** TRIGGER statement is replaced with the third argument and the result +** returned. This is analagous to renameTableFunc() above, except for CREATE +** TRIGGER, not CREATE INDEX and CREATE TABLE. +*/ +static void renameTriggerFunc( + sqlite3_context *context, + int NotUsed, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + int dist = 3; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + sqlite3 *db = sqlite3_context_db_handle(context); + + UNUSED_PARAMETER(NotUsed); + + /* The principle used to locate the table name in the CREATE TRIGGER + ** statement is that the table name is the first token that is immediately + ** preceded by either TK_ON or TK_DOT and immediately followed by one + ** of TK_WHEN, TK_BEGIN or TK_FOR. + */ + if( zSql ){ + do { + + if( !*zCsr ){ + /* Ran out of input before finding the table name. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = (char*)zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + }while( token==TK_SPACE ); + assert( len>0 ); + + /* Variable 'dist' stores the number of tokens read since the most + ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN + ** token is read and 'dist' equals 2, the condition stated above + ** to be met. + ** + ** Note that ON cannot be a database, table or column name, so + ** there is no need to worry about syntax like + ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. + */ + dist++; + if( token==TK_DOT || token==TK_ON ){ + dist = 0; + } + } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); + + /* Variable tname now contains the token that is the old table-name + ** in the CREATE TRIGGER statement. + */ + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); + } +} +#endif /* !SQLITE_OMIT_TRIGGER */ + +/* +** Register built-in functions used to help implement ALTER TABLE +*/ +SQLITE_PRIVATE void sqlite3AlterFunctions(void){ + static FuncDef aAlterTableFuncs[] = { + FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), +#ifndef SQLITE_OMIT_TRIGGER + FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), +#endif +#ifndef SQLITE_OMIT_FOREIGN_KEY + FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), +#endif + }; + sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); +} + +/* +** This function is used to create the text of expressions of the form: +** +** name= OR name= OR ... +** +** If argument zWhere is NULL, then a pointer string containing the text +** "name=" is returned, where is the quoted version +** of the string passed as argument zConstant. The returned buffer is +** allocated using sqlite3DbMalloc(). It is the responsibility of the +** caller to ensure that it is eventually freed. +** +** If argument zWhere is not NULL, then the string returned is +** " OR name=", where is the contents of zWhere. +** In this case zWhere is passed to sqlite3DbFree() before returning. +** +*/ +static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){ + char *zNew; + if( !zWhere ){ + zNew = sqlite3MPrintf(db, "name=%Q", zConstant); + }else{ + zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant); + sqlite3DbFree(db, zWhere); + } + return zNew; +} + +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +/* +** Generate the text of a WHERE expression which can be used to select all +** tables that have foreign key constraints that refer to table pTab (i.e. +** constraints for which pTab is the parent table) from the sqlite_master +** table. +*/ +static char *whereForeignKeys(Parse *pParse, Table *pTab){ + FKey *p; + char *zWhere = 0; + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ + zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName); + } + return zWhere; +} +#endif + +/* +** Generate the text of a WHERE expression which can be used to select all +** temporary triggers on table pTab from the sqlite_temp_master table. If +** table pTab has no temporary triggers, or is itself stored in the +** temporary database, NULL is returned. +*/ +static char *whereTempTriggers(Parse *pParse, Table *pTab){ + Trigger *pTrig; + char *zWhere = 0; + const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ + + /* If the table is not located in the temp-db (in which case NULL is + ** returned, loop through the tables list of triggers. For each trigger + ** that is not part of the temp-db schema, add a clause to the WHERE + ** expression being built up in zWhere. + */ + if( pTab->pSchema!=pTempSchema ){ + sqlite3 *db = pParse->db; + for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ + if( pTrig->pSchema==pTempSchema ){ + zWhere = whereOrName(db, zWhere, pTrig->zName); + } + } + } + if( zWhere ){ + char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); + sqlite3DbFree(pParse->db, zWhere); + zWhere = zNew; + } + return zWhere; +} + +/* +** Generate code to drop and reload the internal representation of table +** pTab from the database, including triggers and temporary triggers. +** Argument zName is the name of the table in the database schema at +** the time the generated code is executed. This can be different from +** pTab->zName if this function is being called to code part of an +** "ALTER TABLE RENAME TO" statement. +*/ +static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ + Vdbe *v; + char *zWhere; + int iDb; /* Index of database containing pTab */ +#ifndef SQLITE_OMIT_TRIGGER + Trigger *pTrig; +#endif + + v = sqlite3GetVdbe(pParse); + if( NEVER(v==0) ) return; + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); + +#ifndef SQLITE_OMIT_TRIGGER + /* Drop any table triggers from the internal schema. */ + for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + assert( iTrigDb==iDb || iTrigDb==1 ); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); + } +#endif + + /* Drop the table and index from the internal schema. */ + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); + + /* Reload the table, index and permanent trigger schemas. */ + zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); + if( !zWhere ) return; + sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); + +#ifndef SQLITE_OMIT_TRIGGER + /* Now, if the table is not stored in the temp database, reload any temp + ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3VdbeAddParseSchemaOp(v, 1, zWhere); + } +#endif +} + /* ** Parameter zName is the name of a table that is about to be altered ** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). ** If the table is a system table, this function leaves an error message ** in pParse->zErr (system tables may not be altered) and returns non-zero. ** ** Or, if zName is not a system table, zero is returned. */ -static int isAlterableTable(Parse *pParse, Table *pTab){ - if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) -#ifndef SQLITE_OMIT_VIRTUALTABLE - || (pTab->tabFlags & TF_Eponymous)!=0 - || ( (pTab->tabFlags & TF_Shadow)!=0 - && sqlite3ReadOnlyShadowTables(pParse->db) - ) -#endif - ){ - sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); +static int isSystemTable(Parse *pParse, const char *zName){ + if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); return 1; } return 0; } /* -** Generate code to verify that the schemas of database zDb and, if -** bTemp is not true, database "temp", can still be parsed. This is -** called at the end of the generation of an ALTER TABLE ... RENAME ... -** statement to ensure that the operation has not rendered any schema -** objects unusable. -*/ -static void renameTestSchema( - Parse *pParse, /* Parse context */ - const char *zDb, /* Name of db to verify schema of */ - int bTemp, /* True if this is the temp db */ - const char *zWhen, /* "when" part of error message */ - int bNoDQS /* Do not allow DQS in the schema */ -){ - pParse->colNamesSet = 1; - sqlite3NestedParse(pParse, - "SELECT 1 " - "FROM \"%w\"." LEGACY_SCHEMA_TABLE " " - "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" - " AND sql NOT LIKE 'create virtual%%'" - " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ", - zDb, - zDb, bTemp, zWhen, bNoDQS - ); - - if( bTemp==0 ){ - sqlite3NestedParse(pParse, - "SELECT 1 " - "FROM temp." LEGACY_SCHEMA_TABLE " " - "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" - " AND sql NOT LIKE 'create virtual%%'" - " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ", - zDb, zWhen, bNoDQS - ); - } -} - -/* -** Generate VM code to replace any double-quoted strings (but not double-quoted -** identifiers) within the "sql" column of the sqlite_schema table in -** database zDb with their single-quoted equivalents. If argument bTemp is -** not true, similarly update all SQL statements in the sqlite_schema table -** of the temp db. -*/ -static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){ - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE - " SET sql = sqlite_rename_quotefix(%Q, sql)" - "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" - " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb - ); - if( bTemp==0 ){ - sqlite3NestedParse(pParse, - "UPDATE temp." LEGACY_SCHEMA_TABLE - " SET sql = sqlite_rename_quotefix('temp', sql)" - "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" - " AND sql NOT LIKE 'create virtual%%'" - ); - } -} - -/* -** Generate code to reload the schema for database iDb. And, if iDb!=1, for -** the temp database as well. -*/ -static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){ - Vdbe *v = pParse->pVdbe; - if( v ){ - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5); - if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5); - } -} - -/* -** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" -** command. +** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" +** command. */ SQLITE_PRIVATE void sqlite3AlterRenameTable( Parse *pParse, /* Parser context. */ SrcList *pSrc, /* The table to rename. */ Token *pName /* The new table name. */ ){ int iDb; /* Database that contains the table */ char *zDb; /* Name of database iDb */ Table *pTab; /* Table being renamed */ - char *zName = 0; /* NULL-terminated version of pName */ + char *zName = 0; /* NULL-terminated version of pName */ sqlite3 *db = pParse->db; /* Database connection */ int nTabName; /* Number of UTF-8 characters in zTabName */ const char *zTabName; /* Original name of the table */ Vdbe *v; +#ifndef SQLITE_OMIT_TRIGGER + char *zWhere = 0; /* Where clause to locate temp triggers */ +#endif VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ + int savedDbFlags; /* Saved value of db->flags */ + savedDbFlags = db->flags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; + db->flags |= SQLITE_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(db, pName); if( !zName ) goto exit_rename_table; /* Check that a table or index named 'zName' does not already exist ** in database iDb. If so, this is an error. */ - if( sqlite3FindTable(db, zName, zDb) - || sqlite3FindIndex(db, zName, zDb) - || sqlite3IsShadowTableOf(db, pTab, zName) - ){ - sqlite3ErrorMsg(pParse, + if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ + sqlite3ErrorMsg(pParse, "there is already another table or index with this name: %s", zName); goto exit_rename_table; } /* Make sure it is not a system table being altered, or a reserved name ** that the table is being renamed to. */ - if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ + if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ goto exit_rename_table; } - if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){ - goto exit_rename_table; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto + exit_rename_table; } #ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) ){ + if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); goto exit_rename_table; } #endif @@ -117104,77 +97227,21 @@ pVTab = 0; } } #endif - /* Begin a transaction for database iDb. Then modify the schema cookie - ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(), - ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the - ** nested SQL may raise an exception. */ + /* Begin a transaction for database iDb. + ** Then modify the schema cookie (since the ALTER TABLE modifies the + ** schema). Open a statement transaction if the table is a virtual + ** table. + */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } - sqlite3MayAbort(pParse); - - /* figure out how many UTF-8 characters are in zName */ - zTabName = pTab->zName; - nTabName = sqlite3Utf8CharLen(zTabName, -1); - - /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in - ** the schema to use the new table name. */ - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) " - "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" - "AND name NOT LIKE 'sqliteX_%%' ESCAPE 'X'" - , zDb, zDb, zTabName, zName, (iDb==1), zTabName - ); - - /* Update the tbl_name and name columns of the sqlite_schema table - ** as required. */ - sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE " SET " - "tbl_name = %Q, " - "name = CASE " - "WHEN type='table' THEN %Q " - "WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' " - " AND type='index' THEN " - "'sqlite_autoindex_' || %Q || substr(name,%d+18) " - "ELSE name END " - "WHERE tbl_name=%Q COLLATE nocase AND " - "(type='table' OR type='index' OR type='trigger');", - zDb, - zName, zName, zName, - nTabName, zTabName - ); - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* If the sqlite_sequence table exists in this database, then update - ** it with the new table name. - */ - if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ - sqlite3NestedParse(pParse, - "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", - zDb, zName, pTab->zName); - } -#endif - - /* If the table being renamed is not itself part of the temp database, - ** edit view and trigger definitions within the temp database - ** as required. */ - if( iDb!=1 ){ - sqlite3NestedParse(pParse, - "UPDATE sqlite_temp_schema SET " - "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), " - "tbl_name = " - "CASE WHEN tbl_name=%Q COLLATE nocase AND " - " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) " - "THEN %Q ELSE tbl_name END " - "WHERE type IN ('view', 'trigger')" - , zDb, zTabName, zName, zTabName, zDb, zName); - } + sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); + sqlite3ChangeCookie(pParse, iDb); /* If this is a virtual table, invoke the xRename() function if ** one is defined. The xRename() callback will modify the names ** of any resources used by the v-table implementation (including other ** SQLite tables) that are identified by the name of the virtual table. @@ -117182,35 +97249,103 @@ #ifndef SQLITE_OMIT_VIRTUALTABLE if( pVTab ){ int i = ++pParse->nMem; sqlite3VdbeLoadString(v, i, zName); sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); + sqlite3MayAbort(pParse); } #endif - renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); - renameTestSchema(pParse, zDb, iDb==1, "after rename", 0); + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + if( db->flags&SQLITE_ForeignKeys ){ + /* If foreign-key support is enabled, rewrite the CREATE TABLE + ** statements corresponding to all child tables of foreign key constraints + ** for which the renamed table is the parent table. */ + if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ + sqlite3NestedParse(pParse, + "UPDATE \"%w\".%s SET " + "sql = sqlite_rename_parent(sql, %Q, %Q) " + "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere); + sqlite3DbFree(db, zWhere); + } + } +#endif + + /* Modify the sqlite_master table to use the new table name. */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " +#ifdef SQLITE_OMIT_TRIGGER + "sql = sqlite_rename_table(sql, %Q), " +#else + "sql = CASE " + "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" + "ELSE sqlite_rename_table(sql, %Q) END, " +#endif + "tbl_name = %Q, " + "name = CASE " + "WHEN type='table' THEN %Q " + "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " + "'sqlite_autoindex_' || %Q || substr(name,%d+18) " + "ELSE name END " + "WHERE tbl_name=%Q COLLATE nocase AND " + "(type='table' OR type='index' OR type='trigger');", + zDb, MASTER_NAME, zName, zName, zName, +#ifndef SQLITE_OMIT_TRIGGER + zName, +#endif + zName, nTabName, zTabName + ); + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* If the sqlite_sequence table exists in this database, then update + ** it with the new table name. + */ + if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ + sqlite3NestedParse(pParse, + "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", + zDb, zName, pTab->zName); + } +#endif + +#ifndef SQLITE_OMIT_TRIGGER + /* If there are TEMP triggers on this table, modify the sqlite_temp_master + ** table. Don't do this if the table being ALTERed is itself located in + ** the temp database. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3NestedParse(pParse, + "UPDATE sqlite_temp_master SET " + "sql = sqlite_rename_trigger(sql, %Q), " + "tbl_name = %Q " + "WHERE %s;", zName, zName, zWhere); + sqlite3DbFree(db, zWhere); + } +#endif + +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + if( db->flags&SQLITE_ForeignKeys ){ + FKey *p; + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ + Table *pFrom = p->pFrom; + if( pFrom!=pTab ){ + reloadTableSchema(pParse, p->pFrom, pFrom->zName); + } + } + } +#endif + + /* Drop and reload the internal table schema. */ + reloadTableSchema(pParse, pTab, zName); exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); -} - -/* -** Write code that will raise an error if the table described by -** zDb and zTab is not empty. -*/ -static void sqlite3ErrorIfNotEmpty( - Parse *pParse, /* Parsing context */ - const char *zDb, /* Schema holding the table */ - const char *zTab, /* Table to check for empty */ - const char *zErr /* Error message text */ -){ - sqlite3NestedParse(pParse, - "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", - zErr, zDb, zTab - ); + db->flags = savedDbFlags; } /* ** This function is called after an "ALTER TABLE ... ADD" statement ** has been parsed. Argument pColDef contains the text of the new @@ -117227,26 +97362,25 @@ const char *zTab; /* Table name */ char *zCol; /* Null-terminated column definition */ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ - Vdbe *v; /* The prepared statement under construction */ + Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ int r1; /* Temporary registers */ db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nErr ) return; - assert( db->mallocFailed==0 ); + if( pParse->nErr || db->mallocFailed ) return; + assert( v!=0 ); pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; - pDflt = sqlite3ColumnExpr(pNew, pCol); + pDflt = pCol->pDflt; pTab = sqlite3FindTable(db, zTab, zDb); assert( pTab ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ @@ -117253,10 +97387,18 @@ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ return; } #endif + /* If the default value for the new column was specified with a + ** literal NULL, then set pDflt to 0. This simplifies checking + ** for an SQL NULL default below. + */ + assert( pDflt==0 || pDflt->op==TK_SPAN ); + if( pDflt && pDflt->pLeft->op==TK_NULL ){ + pDflt = 0; + } /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. ** If there is a NOT NULL constraint, then the default value for the ** column must not be NULL. */ @@ -117263,137 +97405,99 @@ if( pCol->colFlags & COLFLAG_PRIMKEY ){ sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); return; } if( pNew->pIndex ){ - sqlite3ErrorMsg(pParse, - "Cannot add a UNIQUE column"); - return; - } - if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){ - /* If the default value for the new column was specified with a - ** literal NULL, then set pDflt to 0. This simplifies checking - ** for an SQL NULL default below. - */ - assert( pDflt==0 || pDflt->op==TK_SPAN ); - if( pDflt && pDflt->pLeft->op==TK_NULL ){ - pDflt = 0; - } - assert( IsOrdinaryTable(pNew) ); - if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, - "Cannot add a REFERENCES column with non-NULL default value"); - } - if( pCol->notNull && !pDflt ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, - "Cannot add a NOT NULL column with default value NULL"); - } - - - /* Ensure the default expression is something that sqlite3ValueFromExpr() - ** can handle (i.e. not CURRENT_TIME etc.) - */ - if( pDflt ){ - sqlite3_value *pVal = 0; - int rc; - rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - if( rc!=SQLITE_OK ){ - assert( db->mallocFailed == 1 ); - return; - } - if( !pVal ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, - "Cannot add a column with non-constant default"); - } - sqlite3ValueFree(pVal); - } - }else if( pCol->colFlags & COLFLAG_STORED ){ - sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column"); - } - + sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); + return; + } + if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){ + sqlite3ErrorMsg(pParse, + "Cannot add a REFERENCES column with non-NULL default value"); + return; + } + if( pCol->notNull && !pDflt ){ + sqlite3ErrorMsg(pParse, + "Cannot add a NOT NULL column with default value NULL"); + return; + } + + /* Ensure the default expression is something that sqlite3ValueFromExpr() + ** can handle (i.e. not CURRENT_TIME etc.) + */ + if( pDflt ){ + sqlite3_value *pVal = 0; + int rc; + rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + if( rc!=SQLITE_OK ){ + assert( db->mallocFailed == 1 ); + return; + } + if( !pVal ){ + sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); + return; + } + sqlite3ValueFree(pVal); + } /* Modify the CREATE TABLE statement. */ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; + int savedDbFlags = db->flags; while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ *zEnd-- = '\0'; } - /* substr() operations on characters, but addColOffset is in bytes. So we - ** have to use printf() to translate between these units: */ - assert( IsOrdinaryTable(pTab) ); - assert( IsOrdinaryTable(pNew) ); - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = printf('%%.%ds, ',sql) || %Q" - " || substr(sql,1+length(printf('%%.%ds',sql))) " - "WHERE type = 'table' AND name = %Q", - zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset, + db->flags |= SQLITE_PreferBuiltin; + sqlite3NestedParse(pParse, + "UPDATE \"%w\".%s SET " + "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " + "WHERE type = 'table' AND name = %Q", + zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); sqlite3DbFree(db, zCol); - } - - v = sqlite3GetVdbe(pParse); - if( v ){ - /* Make sure the schema version is at least 3. But do not upgrade - ** from less than 3 to 4, as that will corrupt any preexisting DESC - ** index. - */ - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); - sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); - sqlite3ReleaseTempReg(pParse, r1); - - /* Reload the table definition */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterAdd); - - /* Verify that constraints are still satisfied */ - if( pNew->pCheck!=0 - || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0) - || (pTab->tabFlags & TF_Strict)!=0 - ){ - sqlite3NestedParse(pParse, - "SELECT CASE WHEN quick_check GLOB 'CHECK*'" - " THEN raise(ABORT,'CHECK constraint failed')" - " WHEN quick_check GLOB 'non-* value in*'" - " THEN raise(ABORT,'type mismatch on DEFAULT')" - " ELSE raise(ABORT,'NOT NULL constraint failed')" - " END" - " FROM pragma_quick_check(%Q,%Q)" - " WHERE quick_check GLOB 'CHECK*'" - " OR quick_check GLOB 'NULL*'" - " OR quick_check GLOB 'non-* value in*'", - zTab, zDb - ); - } - } + db->flags = savedDbFlags; + } + + /* Make sure the schema version is at least 3. But do not upgrade + ** from less than 3 to 4, as that will corrupt any preexisting DESC + ** index. + */ + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); + sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); + sqlite3ReleaseTempReg(pParse, r1); + + /* Reload the schema of the modified table. */ + reloadTableSchema(pParse, pTab, pTab->zName); } /* ** This function is called by the parser after the table-name in -** an "ALTER TABLE ADD" statement is parsed. Argument +** an "ALTER TABLE ADD" statement is parsed. Argument ** pSrc is the full-name of the table being altered. ** ** This routine makes a (partial) copy of the Table structure ** for the table being altered and sets Parse.pNewTable to point ** to it. Routines called by the parser as the column definition -** is parsed (i.e. sqlite3AddColumn()) add the new Column data to -** the copy. The copy of the Table structure is deleted by tokenize.c +** is parsed (i.e. sqlite3AddColumn()) add the new Column data to +** the copy. The copy of the Table structure is deleted by tokenize.c ** after parsing is finished. ** ** Routine sqlite3AlterFinishAddColumn() will be called to complete ** coding the "ALTER TABLE ... ADD" statement. */ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ Table *pNew; Table *pTab; + Vdbe *v; int iDb; int i; int nAlloc; sqlite3 *db = pParse->db; @@ -117410,21 +97514,19 @@ goto exit_begin_add_column; } #endif /* Make sure this is not an attempt to ALTER a view. */ - if( IsView(pTab) ){ + if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); goto exit_begin_add_column; } - if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ + if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ goto exit_begin_add_column; } - sqlite3MayAbort(pParse); - assert( IsOrdinaryTable(pTab) ); - assert( pTab->u.tab.addColOffset>0 ); + assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. But modify ** the name by adding an "sqlite_altertab_" prefix. By adding this @@ -117447,1783 +97549,28 @@ goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; inCol; i++){ Column *pCol = &pNew->aCol[i]; - pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName); - pCol->hName = sqlite3StrIHash(pCol->zCnName); + pCol->zName = sqlite3DbStrDup(db, pCol->zName); + pCol->zColl = 0; + pCol->pDflt = 0; } - assert( IsOrdinaryTable(pNew) ); - pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0); pNew->pSchema = db->aDb[iDb].pSchema; - pNew->u.tab.addColOffset = pTab->u.tab.addColOffset; - assert( pNew->nTabRef==1 ); + pNew->addColOffset = pTab->addColOffset; + pNew->nTabRef = 1; + + /* Begin a transaction and increment the schema cookie. */ + sqlite3BeginWriteOperation(pParse, 0, iDb); + v = sqlite3GetVdbe(pParse); + if( !v ) goto exit_begin_add_column; + sqlite3ChangeCookie(pParse, iDb); exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); return; } - -/* -** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN -** command. This function checks if the table is a view or virtual -** table (columns of views or virtual tables may not be renamed). If so, -** it loads an error message into pParse and returns non-zero. -** -** Or, if pTab is not a view or virtual table, zero is returned. -*/ -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) -static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ - const char *zType = 0; -#ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) ){ - zType = "view"; - } -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - zType = "virtual table"; - } -#endif - if( zType ){ - sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"", - (bDrop ? "drop column from" : "rename columns of"), - zType, pTab->zName - ); - return 1; - } - return 0; -} -#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ -# define isRealTable(x,y,z) (0) -#endif - -/* -** Handles the following parser reduction: -** -** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew -*/ -SQLITE_PRIVATE void sqlite3AlterRenameColumn( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ - Token *pOld, /* Name of column being changed */ - Token *pNew /* New column name */ -){ - sqlite3 *db = pParse->db; /* Database connection */ - Table *pTab; /* Table being updated */ - int iCol; /* Index of column being renamed */ - char *zOld = 0; /* Old column name */ - char *zNew = 0; /* New column name */ - const char *zDb; /* Name of schema containing the table */ - int iSchema; /* Index of the schema */ - int bQuote; /* True to quote the new name */ - - /* Locate the table to be altered */ - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_rename_column; - - /* Cannot alter a system table */ - if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column; - if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column; - - /* Which schema holds the table to be altered */ - iSchema = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iSchema>=0 ); - zDb = db->aDb[iSchema].zDbSName; - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ - goto exit_rename_column; - } -#endif - - /* Make sure the old name really is a column name in the table to be - ** altered. Set iCol to be the index of the column being renamed */ - zOld = sqlite3NameFromToken(db, pOld); - if( !zOld ) goto exit_rename_column; - for(iCol=0; iColnCol; iCol++){ - if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break; - } - if( iCol==pTab->nCol ){ - sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld); - goto exit_rename_column; - } - - /* Ensure the schema contains no double-quoted strings */ - renameTestSchema(pParse, zDb, iSchema==1, "", 0); - renameFixQuotes(pParse, zDb, iSchema==1); - - /* Do the rename operation using a recursive UPDATE statement that - ** uses the sqlite_rename_column() SQL function to compute the new - ** CREATE statement text for the sqlite_schema table. - */ - sqlite3MayAbort(pParse); - zNew = sqlite3NameFromToken(db, pNew); - if( !zNew ) goto exit_rename_column; - assert( pNew->n>0 ); - bQuote = sqlite3Isquote(pNew->z[0]); - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) " - "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' " - " AND (type != 'index' OR tbl_name = %Q)", - zDb, - zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, - pTab->zName - ); - - sqlite3NestedParse(pParse, - "UPDATE temp." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) " - "WHERE type IN ('trigger', 'view')", - zDb, pTab->zName, iCol, zNew, bQuote - ); - - /* Drop and reload the database schema. */ - renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename); - renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1); - - exit_rename_column: - sqlite3SrcListDelete(db, pSrc); - sqlite3DbFree(db, zOld); - sqlite3DbFree(db, zNew); - return; -} - -/* -** Each RenameToken object maps an element of the parse tree into -** the token that generated that element. The parse tree element -** might be one of: -** -** * A pointer to an Expr that represents an ID -** * The name of a table column in Column.zName -** -** A list of RenameToken objects can be constructed during parsing. -** Each new object is created by sqlite3RenameTokenMap(). -** As the parse tree is transformed, the sqlite3RenameTokenRemap() -** routine is used to keep the mapping current. -** -** After the parse finishes, renameTokenFind() routine can be used -** to look up the actual token value that created some element in -** the parse tree. -*/ -struct RenameToken { - const void *p; /* Parse tree element created by token t */ - Token t; /* The token that created parse tree element p */ - RenameToken *pNext; /* Next is a list of all RenameToken objects */ -}; - -/* -** The context of an ALTER TABLE RENAME COLUMN operation that gets passed -** down into the Walker. -*/ -typedef struct RenameCtx RenameCtx; -struct RenameCtx { - RenameToken *pList; /* List of tokens to overwrite */ - int nList; /* Number of tokens in pList */ - int iCol; /* Index of column being renamed */ - Table *pTab; /* Table being ALTERed */ - const char *zOld; /* Old column name */ -}; - -#ifdef SQLITE_DEBUG -/* -** This function is only for debugging. It performs two tasks: -** -** 1. Checks that pointer pPtr does not already appear in the -** rename-token list. -** -** 2. Dereferences each pointer in the rename-token list. -** -** The second is most effective when debugging under valgrind or -** address-sanitizer or similar. If any of these pointers no longer -** point to valid objects, an exception is raised by the memory-checking -** tool. -** -** The point of this is to prevent comparisons of invalid pointer values. -** Even though this always seems to work, it is undefined according to the -** C standard. Example of undefined comparison: -** -** sqlite3_free(x); -** if( x==y ) ... -** -** Technically, as x no longer points into a valid object or to the byte -** following a valid object, it may not be used in comparison operations. -*/ -static void renameTokenCheckAll(Parse *pParse, const void *pPtr){ - assert( pParse==pParse->db->pParse ); - assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); - if( pParse->nErr==0 ){ - const RenameToken *p; - u32 i = 1; - for(p=pParse->pRename; p; p=p->pNext){ - if( p->p ){ - assert( p->p!=pPtr ); - i += *(u8*)(p->p) | 1; - } - } - assert( i>0 ); - } -} -#else -# define renameTokenCheckAll(x,y) -#endif - -/* -** Remember that the parser tree element pPtr was created using -** the token pToken. -** -** In other words, construct a new RenameToken object and add it -** to the list of RenameToken objects currently being built up -** in pParse->pRename. -** -** The pPtr argument is returned so that this routine can be used -** with tail recursion in tokenExpr() routine, for a small performance -** improvement. -*/ -SQLITE_PRIVATE const void *sqlite3RenameTokenMap( - Parse *pParse, - const void *pPtr, - const Token *pToken -){ - RenameToken *pNew; - assert( pPtr || pParse->db->mallocFailed ); - renameTokenCheckAll(pParse, pPtr); - if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){ - pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); - if( pNew ){ - pNew->p = pPtr; - pNew->t = *pToken; - pNew->pNext = pParse->pRename; - pParse->pRename = pNew; - } - } - - return pPtr; -} - -/* -** It is assumed that there is already a RenameToken object associated -** with parse tree element pFrom. This function remaps the associated token -** to parse tree element pTo. -*/ -SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom){ - RenameToken *p; - renameTokenCheckAll(pParse, pTo); - for(p=pParse->pRename; p; p=p->pNext){ - if( p->p==pFrom ){ - p->p = pTo; - break; - } - } -} - -/* -** Walker callback used by sqlite3RenameExprUnmap(). -*/ -static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ - Parse *pParse = pWalker->pParse; - sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr); - if( ExprUseYTab(pExpr) ){ - sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab); - } - return WRC_Continue; -} - -/* -** Iterate through the Select objects that are part of WITH clauses attached -** to select statement pSelect. -*/ -static void renameWalkWith(Walker *pWalker, Select *pSelect){ - With *pWith = pSelect->pWith; - if( pWith ){ - Parse *pParse = pWalker->pParse; - int i; - With *pCopy = 0; - assert( pWith->nCte>0 ); - if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){ - /* Push a copy of the With object onto the with-stack. We use a copy - ** here as the original will be expanded and resolved (flags SF_Expanded - ** and SF_Resolved) below. And the parser code that uses the with-stack - ** fails if the Select objects on it have already been expanded and - ** resolved. */ - pCopy = sqlite3WithDup(pParse->db, pWith); - pCopy = sqlite3WithPush(pParse, pCopy, 1); - } - for(i=0; inCte; i++){ - Select *p = pWith->a[i].pSelect; - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC); - if( sNC.pParse->db->mallocFailed ) return; - sqlite3WalkSelect(pWalker, p); - sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols); - } - if( pCopy && pParse->pWith==pCopy ){ - pParse->pWith = pCopy->pOuter; - } - } -} - -/* -** Unmap all tokens in the IdList object passed as the second argument. -*/ -static void unmapColumnIdlistNames( - Parse *pParse, - const IdList *pIdList -){ - int ii; - assert( pIdList!=0 ); - for(ii=0; iinId; ii++){ - sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName); - } -} - -/* -** Walker callback used by sqlite3RenameExprUnmap(). -*/ -static int renameUnmapSelectCb(Walker *pWalker, Select *p){ - Parse *pParse = pWalker->pParse; - int i; - if( pParse->nErr ) return WRC_Abort; - testcase( p->selFlags & SF_View ); - testcase( p->selFlags & SF_CopyCte ); - if( p->selFlags & (SF_View|SF_CopyCte) ){ - return WRC_Prune; - } - if( ALWAYS(p->pEList) ){ - ExprList *pList = p->pEList; - for(i=0; inExpr; i++){ - if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName); - } - } - } - if( ALWAYS(p->pSrc) ){ /* Every Select as a SrcList, even if it is empty */ - SrcList *pSrc = p->pSrc; - for(i=0; inSrc; i++){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName); - if( pSrc->a[i].fg.isUsing==0 ){ - sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn); - }else{ - unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing); - } - } - } - - renameWalkWith(pWalker, p); - return WRC_Continue; -} - -/* -** Remove all nodes that are part of expression pExpr from the rename list. -*/ -SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ - u8 eMode = pParse->eParseMode; - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = pParse; - sWalker.xExprCallback = renameUnmapExprCb; - sWalker.xSelectCallback = renameUnmapSelectCb; - pParse->eParseMode = PARSE_MODE_UNMAP; - sqlite3WalkExpr(&sWalker, pExpr); - pParse->eParseMode = eMode; -} - -/* -** Remove all nodes that are part of expression-list pEList from the -** rename list. -*/ -SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ - if( pEList ){ - int i; - Walker sWalker; - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = pParse; - sWalker.xExprCallback = renameUnmapExprCb; - sqlite3WalkExprList(&sWalker, pEList); - for(i=0; inExpr; i++){ - if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName); - } - } - } -} - -/* -** Free the list of RenameToken objects given in the second argument -*/ -static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ - RenameToken *pNext; - RenameToken *p; - for(p=pToken; p; p=pNext){ - pNext = p->pNext; - sqlite3DbFree(db, p); - } -} - -/* -** Search the Parse object passed as the first argument for a RenameToken -** object associated with parse tree element pPtr. If found, return a pointer -** to it. Otherwise, return NULL. -** -** If the second argument passed to this function is not NULL and a matching -** RenameToken object is found, remove it from the Parse object and add it to -** the list maintained by the RenameCtx object. -*/ -static RenameToken *renameTokenFind( - Parse *pParse, - struct RenameCtx *pCtx, - const void *pPtr -){ - RenameToken **pp; - if( NEVER(pPtr==0) ){ - return 0; - } - for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ - if( (*pp)->p==pPtr ){ - RenameToken *pToken = *pp; - if( pCtx ){ - *pp = pToken->pNext; - pToken->pNext = pCtx->pList; - pCtx->pList = pToken; - pCtx->nList++; - } - return pToken; - } - } - return 0; -} - -/* -** This is a Walker select callback. It does nothing. It is only required -** because without a dummy callback, sqlite3WalkExpr() and similar do not -** descend into sub-select statements. -*/ -static int renameColumnSelectCb(Walker *pWalker, Select *p){ - if( p->selFlags & (SF_View|SF_CopyCte) ){ - testcase( p->selFlags & SF_View ); - testcase( p->selFlags & SF_CopyCte ); - return WRC_Prune; - } - renameWalkWith(pWalker, p); - return WRC_Continue; -} - -/* -** This is a Walker expression callback. -** -** For every TK_COLUMN node in the expression tree, search to see -** if the column being references is the column being renamed by an -** ALTER TABLE statement. If it is, then attach its associated -** RenameToken object to the list of RenameToken objects being -** constructed in RenameCtx object at pWalker->u.pRename. -*/ -static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ - RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_TRIGGER - && pExpr->iColumn==p->iCol - && pWalker->pParse->pTriggerTab==p->pTab - ){ - renameTokenFind(pWalker->pParse, p, (void*)pExpr); - }else if( pExpr->op==TK_COLUMN - && pExpr->iColumn==p->iCol - && ALWAYS(ExprUseYTab(pExpr)) - && p->pTab==pExpr->y.pTab - ){ - renameTokenFind(pWalker->pParse, p, (void*)pExpr); - } - return WRC_Continue; -} - -/* -** The RenameCtx contains a list of tokens that reference a column that -** is being renamed by an ALTER TABLE statement. Return the "last" -** RenameToken in the RenameCtx and remove that RenameToken from the -** RenameContext. "Last" means the last RenameToken encountered when -** the input SQL is parsed from left to right. Repeated calls to this routine -** return all column name tokens in the order that they are encountered -** in the SQL statement. -*/ -static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ - RenameToken *pBest = pCtx->pList; - RenameToken *pToken; - RenameToken **pp; - - for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ - if( pToken->t.z>pBest->t.z ) pBest = pToken; - } - for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); - *pp = pBest->pNext; - - return pBest; -} - -/* -** An error occurred while parsing or otherwise processing a database -** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an -** ALTER TABLE RENAME COLUMN program. The error message emitted by the -** sub-routine is currently stored in pParse->zErrMsg. This function -** adds context to the error message and then stores it in pCtx. -*/ -static void renameColumnParseError( - sqlite3_context *pCtx, - const char *zWhen, - sqlite3_value *pType, - sqlite3_value *pObject, - Parse *pParse -){ - const char *zT = (const char*)sqlite3_value_text(pType); - const char *zN = (const char*)sqlite3_value_text(pObject); - char *zErr; - - zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s", - zT, zN, (zWhen[0] ? " " : ""), zWhen, - pParse->zErrMsg - ); - sqlite3_result_error(pCtx, zErr, -1); - sqlite3DbFree(pParse->db, zErr); -} - -/* -** For each name in the the expression-list pEList (i.e. each -** pEList->a[i].zName) that matches the string in zOld, extract the -** corresponding rename-token from Parse object pParse and add it -** to the RenameCtx pCtx. -*/ -static void renameColumnElistNames( - Parse *pParse, - RenameCtx *pCtx, - const ExprList *pEList, - const char *zOld -){ - if( pEList ){ - int i; - for(i=0; inExpr; i++){ - const char *zName = pEList->a[i].zEName; - if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) - && ALWAYS(zName!=0) - && 0==sqlite3_stricmp(zName, zOld) - ){ - renameTokenFind(pParse, pCtx, (const void*)zName); - } - } - } -} - -/* -** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName) -** that matches the string in zOld, extract the corresponding rename-token -** from Parse object pParse and add it to the RenameCtx pCtx. -*/ -static void renameColumnIdlistNames( - Parse *pParse, - RenameCtx *pCtx, - const IdList *pIdList, - const char *zOld -){ - if( pIdList ){ - int i; - for(i=0; inId; i++){ - const char *zName = pIdList->a[i].zName; - if( 0==sqlite3_stricmp(zName, zOld) ){ - renameTokenFind(pParse, pCtx, (const void*)zName); - } - } - } -} - - -/* -** Parse the SQL statement zSql using Parse object (*p). The Parse object -** is initialized by this function before it is used. -*/ -static int renameParseSql( - Parse *p, /* Memory to use for Parse object */ - const char *zDb, /* Name of schema SQL belongs to */ - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL to parse */ - int bTemp /* True if SQL is from temp schema */ -){ - int rc; - - sqlite3ParseObjectInit(p, db); - if( zSql==0 ){ - return SQLITE_NOMEM; - } - if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){ - return SQLITE_CORRUPT_BKPT; - } - db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); - p->eParseMode = PARSE_MODE_RENAME; - p->db = db; - p->nQueryLoop = 1; - rc = sqlite3RunParser(p, zSql); - if( db->mallocFailed ) rc = SQLITE_NOMEM; - if( rc==SQLITE_OK - && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0) - ){ - rc = SQLITE_CORRUPT_BKPT; - } - -#ifdef SQLITE_DEBUG - /* Ensure that all mappings in the Parse.pRename list really do map to - ** a part of the input string. */ - if( rc==SQLITE_OK ){ - int nSql = sqlite3Strlen30(zSql); - RenameToken *pToken; - for(pToken=p->pRename; pToken; pToken=pToken->pNext){ - assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); - } - } -#endif - - db->init.iDb = 0; - return rc; -} - -/* -** This function edits SQL statement zSql, replacing each token identified -** by the linked list pRename with the text of zNew. If argument bQuote is -** true, then zNew is always quoted first. If no error occurs, the result -** is loaded into context object pCtx as the result. -** -** Or, if an error occurs (i.e. an OOM condition), an error is left in -** pCtx and an SQLite error code returned. -*/ -static int renameEditSql( - sqlite3_context *pCtx, /* Return result here */ - RenameCtx *pRename, /* Rename context */ - const char *zSql, /* SQL statement to edit */ - const char *zNew, /* New token text */ - int bQuote /* True to always quote token */ -){ - i64 nNew = sqlite3Strlen30(zNew); - i64 nSql = sqlite3Strlen30(zSql); - sqlite3 *db = sqlite3_context_db_handle(pCtx); - int rc = SQLITE_OK; - char *zQuot = 0; - char *zOut; - i64 nQuot = 0; - char *zBuf1 = 0; - char *zBuf2 = 0; - - if( zNew ){ - /* Set zQuot to point to a buffer containing a quoted copy of the - ** identifier zNew. If the corresponding identifier in the original - ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to - ** point to zQuot so that all substitutions are made using the - ** quoted version of the new column name. */ - zQuot = sqlite3MPrintf(db, "\"%w\" ", zNew); - if( zQuot==0 ){ - return SQLITE_NOMEM; - }else{ - nQuot = sqlite3Strlen30(zQuot)-1; - } - - assert( nQuot>=nNew ); - zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1); - }else{ - zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3); - if( zOut ){ - zBuf1 = &zOut[nSql*2+1]; - zBuf2 = &zOut[nSql*4+2]; - } - } - - /* At this point pRename->pList contains a list of RenameToken objects - ** corresponding to all tokens in the input SQL that must be replaced - ** with the new column name, or with single-quoted versions of themselves. - ** All that remains is to construct and return the edited SQL string. */ - if( zOut ){ - int nOut = nSql; - memcpy(zOut, zSql, nSql); - while( pRename->pList ){ - int iOff; /* Offset of token to replace in zOut */ - u32 nReplace; - const char *zReplace; - RenameToken *pBest = renameColumnTokenNext(pRename); - - if( zNew ){ - if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){ - nReplace = nNew; - zReplace = zNew; - }else{ - nReplace = nQuot; - zReplace = zQuot; - if( pBest->t.z[pBest->t.n]=='"' ) nReplace++; - } - }else{ - /* Dequote the double-quoted token. Then requote it again, this time - ** using single quotes. If the character immediately following the - ** original token within the input SQL was a single quote ('), then - ** add another space after the new, single-quoted version of the - ** token. This is so that (SELECT "string"'alias') maps to - ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */ - memcpy(zBuf1, pBest->t.z, pBest->t.n); - zBuf1[pBest->t.n] = 0; - sqlite3Dequote(zBuf1); - sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1, - pBest->t.z[pBest->t.n]=='\'' ? " " : "" - ); - zReplace = zBuf2; - nReplace = sqlite3Strlen30(zReplace); - } - - iOff = pBest->t.z - zSql; - if( pBest->t.n!=nReplace ){ - memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], - nOut - (iOff + pBest->t.n) - ); - nOut += nReplace - pBest->t.n; - zOut[nOut] = '\0'; - } - memcpy(&zOut[iOff], zReplace, nReplace); - sqlite3DbFree(db, pBest); - } - - sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT); - sqlite3DbFree(db, zOut); - }else{ - rc = SQLITE_NOMEM; - } - - sqlite3_free(zQuot); - return rc; -} - -/* -** Set all pEList->a[].fg.eEName fields in the expression-list to val. -*/ -static void renameSetENames(ExprList *pEList, int val){ - if( pEList ){ - int i; - for(i=0; inExpr; i++){ - assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME ); - pEList->a[i].fg.eEName = val; - } - } -} - -/* -** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming -** it was read from the schema of database zDb. Return SQLITE_OK if -** successful. Otherwise, return an SQLite error code and leave an error -** message in the Parse object. -*/ -static int renameResolveTrigger(Parse *pParse){ - sqlite3 *db = pParse->db; - Trigger *pNew = pParse->pNewTrigger; - TriggerStep *pStep; - NameContext sNC; - int rc = SQLITE_OK; - - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - assert( pNew->pTabSchema ); - pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, - db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName - ); - pParse->eTriggerOp = pNew->op; - /* ALWAYS() because if the table of the trigger does not exist, the - ** error would have been hit before this point */ - if( ALWAYS(pParse->pTriggerTab) ){ - rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab)!=0; - } - - /* Resolve symbols in WHEN clause */ - if( rc==SQLITE_OK && pNew->pWhen ){ - rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); - } - - for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){ - if( pStep->pSelect ){ - sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); - if( pParse->nErr ) rc = pParse->rc; - } - if( rc==SQLITE_OK && pStep->zTarget ){ - SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); - if( pSrc ){ - Select *pSel = sqlite3SelectNew( - pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 - ); - if( pSel==0 ){ - pStep->pExprList = 0; - pSrc = 0; - rc = SQLITE_NOMEM; - }else{ - /* pStep->pExprList contains an expression-list used for an UPDATE - ** statement. So the a[].zEName values are the RHS of the - ** "= " clauses of the UPDATE statement. So, before - ** running SelectPrep(), change all the eEName values in - ** pStep->pExprList to ENAME_SPAN (from their current value of - ** ENAME_NAME). This is to prevent any ids in ON() clauses that are - ** part of pSrc from being incorrectly resolved against the - ** a[].zEName values as if they were column aliases. */ - renameSetENames(pStep->pExprList, ENAME_SPAN); - sqlite3SelectPrep(pParse, pSel, 0); - renameSetENames(pStep->pExprList, ENAME_NAME); - rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK; - assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList ); - assert( pSrc==pSel->pSrc ); - if( pStep->pExprList ) pSel->pEList = 0; - pSel->pSrc = 0; - sqlite3SelectDelete(db, pSel); - } - if( pStep->pFrom ){ - int i; - for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){ - SrcItem *p = &pStep->pFrom->a[i]; - if( p->fg.isSubquery ){ - assert( p->u4.pSubq!=0 ); - sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0); - } - } - } - - if( db->mallocFailed ){ - rc = SQLITE_NOMEM; - } - sNC.pSrcList = pSrc; - if( rc==SQLITE_OK && pStep->pWhere ){ - rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); - } - if( rc==SQLITE_OK ){ - rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); - } - assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); - if( pStep->pUpsert && rc==SQLITE_OK ){ - Upsert *pUpsert = pStep->pUpsert; - pUpsert->pUpsertSrc = pSrc; - sNC.uNC.pUpsert = pUpsert; - sNC.ncFlags = NC_UUpsert; - rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); - if( rc==SQLITE_OK ){ - ExprList *pUpsertSet = pUpsert->pUpsertSet; - rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); - } - if( rc==SQLITE_OK ){ - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); - } - if( rc==SQLITE_OK ){ - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); - } - sNC.ncFlags = 0; - } - sNC.pSrcList = 0; - sqlite3SrcListDelete(db, pSrc); - }else{ - rc = SQLITE_NOMEM; - } - } - } - return rc; -} - -/* -** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr -** objects that are part of the trigger passed as the second argument. -*/ -static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ - TriggerStep *pStep; - - /* Find tokens to edit in WHEN clause */ - sqlite3WalkExpr(pWalker, pTrigger->pWhen); - - /* Find tokens to edit in trigger steps */ - for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - sqlite3WalkSelect(pWalker, pStep->pSelect); - sqlite3WalkExpr(pWalker, pStep->pWhere); - sqlite3WalkExprList(pWalker, pStep->pExprList); - if( pStep->pUpsert ){ - Upsert *pUpsert = pStep->pUpsert; - sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); - sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); - sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); - sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); - } - if( pStep->pFrom ){ - int i; - SrcList *pFrom = pStep->pFrom; - for(i=0; inSrc; i++){ - if( pFrom->a[i].fg.isSubquery ){ - assert( pFrom->a[i].u4.pSubq!=0 ); - sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect); - } - } - } - } -} - -/* -** Free the contents of Parse object (*pParse). Do not free the memory -** occupied by the Parse object itself. -*/ -static void renameParseCleanup(Parse *pParse){ - sqlite3 *db = pParse->db; - Index *pIdx; - if( pParse->pVdbe ){ - sqlite3VdbeFinalize(pParse->pVdbe); - } - sqlite3DeleteTable(db, pParse->pNewTable); - while( (pIdx = pParse->pNewIndex)!=0 ){ - pParse->pNewIndex = pIdx->pNext; - sqlite3FreeIndex(db, pIdx); - } - sqlite3DeleteTrigger(db, pParse->pNewTrigger); - sqlite3DbFree(db, pParse->zErrMsg); - renameTokenFree(db, pParse->pRename); - sqlite3ParseObjectReset(pParse); -} - -/* -** SQL function: -** -** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP) -** -** 0. zSql: SQL statement to rewrite -** 1. type: Type of object ("table", "view" etc.) -** 2. object: Name of object -** 3. Database: Database name (e.g. "main") -** 4. Table: Table name -** 5. iCol: Index of column to rename -** 6. zNew: New column name -** 7. bQuote: Non-zero if the new column name should be quoted. -** 8. bTemp: True if zSql comes from temp schema -** -** Do a column rename operation on the CREATE statement given in zSql. -** The iCol-th column (left-most is 0) of table zTable is renamed from zCol -** into zNew. The name should be quoted if bQuote is true. -** -** This function is used internally by the ALTER TABLE RENAME COLUMN command. -** It is only accessible to SQL created using sqlite3NestedParse(). It is -** not reachable from ordinary SQL passed into sqlite3_prepare() unless the -** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled. -*/ -static void renameColumnFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - RenameCtx sCtx; - const char *zSql = (const char*)sqlite3_value_text(argv[0]); - const char *zDb = (const char*)sqlite3_value_text(argv[3]); - const char *zTable = (const char*)sqlite3_value_text(argv[4]); - int iCol = sqlite3_value_int(argv[5]); - const char *zNew = (const char*)sqlite3_value_text(argv[6]); - int bQuote = sqlite3_value_int(argv[7]); - int bTemp = sqlite3_value_int(argv[8]); - const char *zOld; - int rc; - Parse sParse; - Walker sWalker; - Index *pIdx; - int i; - Table *pTab; -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; -#endif - - UNUSED_PARAMETER(NotUsed); - if( zSql==0 ) return; - if( zTable==0 ) return; - if( zNew==0 ) return; - if( iCol<0 ) return; - sqlite3BtreeEnterAll(db); - pTab = sqlite3FindTable(db, zTable, zDb); - if( pTab==0 || iCol>=pTab->nCol ){ - sqlite3BtreeLeaveAll(db); - return; - } - zOld = pTab->aCol[iCol].zCnName; - memset(&sCtx, 0, sizeof(sCtx)); - sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); - -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = 0; -#endif - rc = renameParseSql(&sParse, zDb, db, zSql, bTemp); - - /* Find tokens that need to be replaced. */ - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = &sParse; - sWalker.xExprCallback = renameColumnExprCb; - sWalker.xSelectCallback = renameColumnSelectCb; - sWalker.u.pRename = &sCtx; - - sCtx.pTab = pTab; - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; - if( sParse.pNewTable ){ - if( IsView(sParse.pNewTable) ){ - Select *pSelect = sParse.pNewTable->u.view.pSelect; - pSelect->selFlags &= ~SF_View; - sParse.rc = SQLITE_OK; - sqlite3SelectPrep(&sParse, pSelect, 0); - rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); - if( rc==SQLITE_OK ){ - sqlite3WalkSelect(&sWalker, pSelect); - } - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; - }else if( IsOrdinaryTable(sParse.pNewTable) ){ - /* A regular table */ - int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); - FKey *pFKey; - sCtx.pTab = sParse.pNewTable; - if( bFKOnly==0 ){ - if( iColnCol ){ - renameTokenFind( - &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName - ); - } - if( sCtx.iCol<0 ){ - renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); - } - sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); - for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3WalkExprList(&sWalker, pIdx->aColExpr); - } - for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3WalkExprList(&sWalker, pIdx->aColExpr); - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - for(i=0; inCol; i++){ - Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable, - &sParse.pNewTable->aCol[i]); - sqlite3WalkExpr(&sWalker, pExpr); - } -#endif - } - - assert( IsOrdinaryTable(sParse.pNewTable) ); - for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ - for(i=0; inCol; i++){ - if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ - renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); - } - if( 0==sqlite3_stricmp(pFKey->zTo, zTable) - && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld) - ){ - renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol); - } - } - } - } - }else if( sParse.pNewIndex ){ - sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); - sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); - }else{ - /* A trigger */ - TriggerStep *pStep; - rc = renameResolveTrigger(&sParse); - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; - - for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget ){ - Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); - if( pTarget==pTab ){ - if( pStep->pUpsert ){ - ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; - renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); - } - renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); - renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); - } - } - } - - - /* Find tokens to edit in UPDATE OF clause */ - if( sParse.pTriggerTab==pTab ){ - renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); - } - - /* Find tokens to edit in various expressions and selects */ - renameWalkTrigger(&sWalker, sParse.pNewTrigger); - } - - assert( rc==SQLITE_OK ); - rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); - -renameColumnFunc_done: - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ - sqlite3_result_value(context, argv[0]); - }else if( sParse.zErrMsg ){ - renameColumnParseError(context, "", argv[1], argv[2], &sParse); - }else{ - sqlite3_result_error_code(context, rc); - } - } - - renameParseCleanup(&sParse); - renameTokenFree(db, sCtx.pList); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - sqlite3BtreeLeaveAll(db); -} - -/* -** Walker expression callback used by "RENAME TABLE". -*/ -static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ - RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_COLUMN - && ALWAYS(ExprUseYTab(pExpr)) - && p->pTab==pExpr->y.pTab - ){ - renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); - } - return WRC_Continue; -} - -/* -** Walker select callback used by "RENAME TABLE". -*/ -static int renameTableSelectCb(Walker *pWalker, Select *pSelect){ - int i; - RenameCtx *p = pWalker->u.pRename; - SrcList *pSrc = pSelect->pSrc; - if( pSelect->selFlags & (SF_View|SF_CopyCte) ){ - testcase( pSelect->selFlags & SF_View ); - testcase( pSelect->selFlags & SF_CopyCte ); - return WRC_Prune; - } - if( NEVER(pSrc==0) ){ - assert( pWalker->pParse->db->mallocFailed ); - return WRC_Abort; - } - for(i=0; inSrc; i++){ - SrcItem *pItem = &pSrc->a[i]; - if( pItem->pSTab==p->pTab ){ - renameTokenFind(pWalker->pParse, p, pItem->zName); - } - } - renameWalkWith(pWalker, pSelect); - - return WRC_Continue; -} - - -/* -** This C function implements an SQL user function that is used by SQL code -** generated by the ALTER TABLE ... RENAME command to modify the definition -** of any foreign key constraints that use the table being renamed as the -** parent table. It is passed three arguments: -** -** 0: The database containing the table being renamed. -** 1. type: Type of object ("table", "view" etc.) -** 2. object: Name of object -** 3: The complete text of the schema statement being modified, -** 4: The old name of the table being renamed, and -** 5: The new name of the table being renamed. -** 6: True if the schema statement comes from the temp db. -** -** It returns the new schema statement. For example: -** -** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) -** -> 'CREATE TABLE t1(a REFERENCES t3)' -*/ -static void renameTableFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zDb = (const char*)sqlite3_value_text(argv[0]); - const char *zInput = (const char*)sqlite3_value_text(argv[3]); - const char *zOld = (const char*)sqlite3_value_text(argv[4]); - const char *zNew = (const char*)sqlite3_value_text(argv[5]); - int bTemp = sqlite3_value_int(argv[6]); - UNUSED_PARAMETER(NotUsed); - - if( zInput && zOld && zNew ){ - Parse sParse; - int rc; - int bQuote = 1; - RenameCtx sCtx; - Walker sWalker; - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - sqlite3BtreeEnterAll(db); - - memset(&sCtx, 0, sizeof(RenameCtx)); - sCtx.pTab = sqlite3FindTable(db, zOld, zDb); - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = &sParse; - sWalker.xExprCallback = renameTableExprCb; - sWalker.xSelectCallback = renameTableSelectCb; - sWalker.u.pRename = &sCtx; - - rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); - - if( rc==SQLITE_OK ){ - int isLegacy = (db->flags & SQLITE_LegacyAlter); - if( sParse.pNewTable ){ - Table *pTab = sParse.pNewTable; - - if( IsView(pTab) ){ - if( isLegacy==0 ){ - Select *pSelect = pTab->u.view.pSelect; - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sParse; - - assert( pSelect->selFlags & SF_View ); - pSelect->selFlags &= ~SF_View; - sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC); - if( sParse.nErr ){ - rc = sParse.rc; - }else{ - sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect); - } - } - }else{ - /* Modify any FK definitions to point to the new table. */ -#ifndef SQLITE_OMIT_FOREIGN_KEY - if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys)) - && !IsVirtual(pTab) - ){ - FKey *pFKey; - assert( IsOrdinaryTable(pTab) ); - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ - if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ - renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); - } - } - } -#endif - - /* If this is the table being altered, fix any table refs in CHECK - ** expressions. Also update the name that appears right after the - ** "CREATE [VIRTUAL] TABLE" bit. */ - if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ - sCtx.pTab = pTab; - if( isLegacy==0 ){ - sqlite3WalkExprList(&sWalker, pTab->pCheck); - } - renameTokenFind(&sParse, &sCtx, pTab->zName); - } - } - } - - else if( sParse.pNewIndex ){ - renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); - if( isLegacy==0 ){ - sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); - } - } - -#ifndef SQLITE_OMIT_TRIGGER - else{ - Trigger *pTrigger = sParse.pNewTrigger; - TriggerStep *pStep; - if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) - && sCtx.pTab->pSchema==pTrigger->pTabSchema - ){ - renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); - } - - if( isLegacy==0 ){ - rc = renameResolveTrigger(&sParse); - if( rc==SQLITE_OK ){ - renameWalkTrigger(&sWalker, pTrigger); - for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ - renameTokenFind(&sParse, &sCtx, pStep->zTarget); - } - if( pStep->pFrom ){ - int i; - for(i=0; ipFrom->nSrc; i++){ - SrcItem *pItem = &pStep->pFrom->a[i]; - if( 0==sqlite3_stricmp(pItem->zName, zOld) ){ - renameTokenFind(&sParse, &sCtx, pItem->zName); - } - } - } - } - } - } - } -#endif - } - - if( rc==SQLITE_OK ){ - rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); - } - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ - sqlite3_result_value(context, argv[3]); - }else if( sParse.zErrMsg ){ - renameColumnParseError(context, "", argv[1], argv[2], &sParse); - }else{ - sqlite3_result_error_code(context, rc); - } - } - - renameParseCleanup(&sParse); - renameTokenFree(db, sCtx.pList); - sqlite3BtreeLeaveAll(db); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - } - - return; -} - -static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){ - renameTokenFind(pWalker->pParse, pWalker->u.pRename, (const void*)pExpr); - } - return WRC_Continue; -} - -/* SQL function: sqlite_rename_quotefix(DB,SQL) -** -** Rewrite the DDL statement "SQL" so that any string literals that use -** double-quotes use single quotes instead. -** -** Two arguments must be passed: -** -** 0: Database name ("main", "temp" etc.). -** 1: SQL statement to edit. -** -** The returned value is the modified SQL statement. For example, given -** the database schema: -** -** CREATE TABLE t1(a, b, c); -** -** SELECT sqlite_rename_quotefix('main', -** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1' -** ); -** -** returns the string: -** -** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1 -** -** If there is a error in the input SQL, then raise an error, except -** if PRAGMA writable_schema=ON, then just return the input string -** unmodified following an error. -*/ -static void renameQuotefixFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - char const *zDb = (const char*)sqlite3_value_text(argv[0]); - char const *zInput = (const char*)sqlite3_value_text(argv[1]); - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - sqlite3BtreeEnterAll(db); - - UNUSED_PARAMETER(NotUsed); - if( zDb && zInput ){ - int rc; - Parse sParse; - rc = renameParseSql(&sParse, zDb, db, zInput, 0); - - if( rc==SQLITE_OK ){ - RenameCtx sCtx; - Walker sWalker; - - /* Walker to find tokens that need to be replaced. */ - memset(&sCtx, 0, sizeof(RenameCtx)); - memset(&sWalker, 0, sizeof(Walker)); - sWalker.pParse = &sParse; - sWalker.xExprCallback = renameQuotefixExprCb; - sWalker.xSelectCallback = renameColumnSelectCb; - sWalker.u.pRename = &sCtx; - - if( sParse.pNewTable ){ - if( IsView(sParse.pNewTable) ){ - Select *pSelect = sParse.pNewTable->u.view.pSelect; - pSelect->selFlags &= ~SF_View; - sParse.rc = SQLITE_OK; - sqlite3SelectPrep(&sParse, pSelect, 0); - rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); - if( rc==SQLITE_OK ){ - sqlite3WalkSelect(&sWalker, pSelect); - } - }else{ - int i; - sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - for(i=0; inCol; i++){ - sqlite3WalkExpr(&sWalker, - sqlite3ColumnExpr(sParse.pNewTable, - &sParse.pNewTable->aCol[i])); - } -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - } - }else if( sParse.pNewIndex ){ - sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); - sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); - }else{ -#ifndef SQLITE_OMIT_TRIGGER - rc = renameResolveTrigger(&sParse); - if( rc==SQLITE_OK ){ - renameWalkTrigger(&sWalker, sParse.pNewTrigger); - } -#endif /* SQLITE_OMIT_TRIGGER */ - } - - if( rc==SQLITE_OK ){ - rc = renameEditSql(context, &sCtx, zInput, 0, 0); - } - renameTokenFree(db, sCtx.pList); - } - if( rc!=SQLITE_OK ){ - if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){ - sqlite3_result_value(context, argv[1]); - }else{ - sqlite3_result_error_code(context, rc); - } - } - renameParseCleanup(&sParse); - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - - sqlite3BtreeLeaveAll(db); -} - -/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS) -** -** An SQL user function that checks that there are no parse or symbol -** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. -** After an ALTER TABLE .. RENAME operation is performed and the schema -** reloaded, this function is called on each SQL statement in the schema -** to ensure that it is still usable. -** -** 0: Database name ("main", "temp" etc.). -** 1: SQL statement. -** 2: Object type ("view", "table", "trigger" or "index"). -** 3: Object name. -** 4: True if object is from temp schema. -** 5: "when" part of error message. -** 6: True to disable the DQS quirk when parsing SQL. -** -** The return value is computed as follows: -** -** A. If an error is seen and not in PRAGMA writable_schema=ON mode, -** then raise the error. -** B. Else if a trigger is created and the the table that the trigger is -** attached to is in database zDb, then return 1. -** C. Otherwise return NULL. -*/ -static void renameTableTest( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - char const *zDb = (const char*)sqlite3_value_text(argv[0]); - char const *zInput = (const char*)sqlite3_value_text(argv[1]); - int bTemp = sqlite3_value_int(argv[4]); - int isLegacy = (db->flags & SQLITE_LegacyAlter); - char const *zWhen = (const char*)sqlite3_value_text(argv[5]); - int bNoDQS = sqlite3_value_int(argv[6]); - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - UNUSED_PARAMETER(NotUsed); - - if( zDb && zInput ){ - int rc; - Parse sParse; - int flags = db->flags; - if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); - rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); - db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL)); - if( rc==SQLITE_OK ){ - if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){ - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sParse; - sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC); - if( sParse.nErr ) rc = sParse.rc; - } - - else if( sParse.pNewTrigger ){ - if( isLegacy==0 ){ - rc = renameResolveTrigger(&sParse); - } - if( rc==SQLITE_OK ){ - int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); - int i2 = sqlite3FindDbName(db, zDb); - if( i1==i2 ){ - /* Handle output case B */ - sqlite3_result_int(context, 1); - } - } - } - } - - if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){ - /* Output case A */ - renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); - } - renameParseCleanup(&sParse); - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif -} - -/* -** The implementation of internal UDF sqlite_drop_column(). -** -** Arguments: -** -** argv[0]: An integer - the index of the schema containing the table -** argv[1]: CREATE TABLE statement to modify. -** argv[2]: An integer - the index of the column to remove. -** -** The value returned is a string containing the CREATE TABLE statement -** with column argv[2] removed. -*/ -static void dropColumnFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - int iSchema = sqlite3_value_int(argv[0]); - const char *zSql = (const char*)sqlite3_value_text(argv[1]); - int iCol = sqlite3_value_int(argv[2]); - const char *zDb = db->aDb[iSchema].zDbSName; - int rc; - Parse sParse; - RenameToken *pCol; - Table *pTab; - const char *zEnd; - char *zNew = 0; - -#ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth = db->xAuth; - db->xAuth = 0; -#endif - - UNUSED_PARAMETER(NotUsed); - rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1); - if( rc!=SQLITE_OK ) goto drop_column_done; - pTab = sParse.pNewTable; - if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){ - /* This can happen if the sqlite_schema table is corrupt */ - rc = SQLITE_CORRUPT_BKPT; - goto drop_column_done; - } - - pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); - if( iColnCol-1 ){ - RenameToken *pEnd; - pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName); - zEnd = (const char*)pEnd->t.z; - }else{ - assert( IsOrdinaryTable(pTab) ); - zEnd = (const char*)&zSql[pTab->u.tab.addColOffset]; - while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; - } - - zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd); - sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT); - sqlite3_free(zNew); - -drop_column_done: - renameParseCleanup(&sParse); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; -#endif - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(context, rc); - } -} - -/* -** This function is called by the parser upon parsing an -** -** ALTER TABLE pSrc DROP COLUMN pName -** -** statement. Argument pSrc contains the possibly qualified name of the -** table being edited, and token pName the name of the column to drop. -*/ -SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){ - sqlite3 *db = pParse->db; /* Database handle */ - Table *pTab; /* Table to modify */ - int iDb; /* Index of db containing pTab in aDb[] */ - const char *zDb; /* Database containing pTab ("main" etc.) */ - char *zCol = 0; /* Name of column to drop */ - int iCol; /* Index of column zCol in pTab->aCol[] */ - - /* Look up the table being altered. */ - assert( pParse->pNewTable==0 ); - assert( sqlite3BtreeHoldsAllMutexes(db) ); - if( NEVER(db->mallocFailed) ) goto exit_drop_column; - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_drop_column; - - /* Make sure this is not an attempt to ALTER a view, virtual table or - ** system table. */ - if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column; - if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column; - - /* Find the index of the column being dropped. */ - zCol = sqlite3NameFromToken(db, pName); - if( zCol==0 ){ - assert( db->mallocFailed ); - goto exit_drop_column; - } - iCol = sqlite3ColumnIndex(pTab, zCol); - if( iCol<0 ){ - sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName); - goto exit_drop_column; - } - - /* Do not allow the user to drop a PRIMARY KEY column or a column - ** constrained by a UNIQUE constraint. */ - if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){ - sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"", - (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE", - zCol - ); - goto exit_drop_column; - } - - /* Do not allow the number of columns to go to zero */ - if( pTab->nCol<=1 ){ - sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol); - goto exit_drop_column; - } - - /* Edit the sqlite_schema table */ - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 ); - zDb = db->aDb[iDb].zDbSName; -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){ - goto exit_drop_column; - } -#endif - renameTestSchema(pParse, zDb, iDb==1, "", 0); - renameFixQuotes(pParse, zDb, iDb==1); - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_drop_column(%d, sql, %d) " - "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)" - , zDb, iDb, iCol, pTab->zName - ); - - /* Drop and reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop); - renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1); - - /* Edit rows of table on disk */ - if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){ - int i; - int addr; - int reg; - int regRec; - Index *pPk = 0; - int nField = 0; /* Number of non-virtual columns after drop */ - int iCur; - Vdbe *v = sqlite3GetVdbe(pParse); - iCur = pParse->nTab++; - sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); - addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - reg = ++pParse->nMem; - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg); - pParse->nMem += pTab->nCol; - }else{ - pPk = sqlite3PrimaryKeyIndex(pTab); - pParse->nMem += pPk->nColumn; - for(i=0; inKeyCol; i++){ - sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1); - } - nField = pPk->nKeyCol; - } - regRec = ++pParse->nMem; - for(i=0; inCol; i++){ - if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ - int regOut; - if( pPk ){ - int iPos = sqlite3TableColumnToIndex(pPk, i); - int iColPos = sqlite3TableColumnToIndex(pPk, iCol); - if( iPosnKeyCol ) continue; - regOut = reg+1+iPos-(iPos>iColPos); - }else{ - regOut = reg+1+nField; - } - if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); - }else{ - char aff = pTab->aCol[i].affinity; - if( aff==SQLITE_AFF_REAL ){ - pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC; - } - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); - pTab->aCol[i].affinity = aff; - } - nField++; - } - } - if( nField==0 ){ - /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */ - pParse->nMem++; - sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1); - nField = 1; - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec); - if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol); - }else{ - sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg); - } - sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); - - sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr); - } - -exit_drop_column: - sqlite3DbFree(db, zCol); - sqlite3SrcListDelete(db, pSrc); -} - -/* -** Register built-in functions used to help implement ALTER TABLE -*/ -SQLITE_PRIVATE void sqlite3AlterFunctions(void){ - static FuncDef aAlterTableFuncs[] = { - INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), - INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), - INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest), - INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc), - INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc), - }; - sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); -} #endif /* SQLITE_ALTER_TABLE */ /************** End of alter.c ***********************************************/ /************** Begin file analyze.c *****************************************/ /* @@ -119253,17 +97600,17 @@ ** Additional tables might be added in future releases of SQLite. ** The sqlite_stat2 table is not created or used unless the SQLite version ** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled ** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only -** created and used by SQLite versions 3.7.9 through 3.29.0 when +** created and used by SQLite versions 3.7.9 and later and with ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 -** is a superset of sqlite_stat2 and is also now deprecated. The -** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only -** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite -** versions 3.8.1 and later. STAT4 is the only variant that is still -** supported. +** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced +** version of sqlite_stat3 and is only available when compiled with +** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is +** not possible to enable both STAT3 and STAT4 at the same time. If they +** are both enabled, then STAT4 takes precedence. ** ** For most applications, sqlite_stat1 provides all the statistics required ** for the query planner to make good choices. ** ** Format of sqlite_stat1: @@ -119275,21 +97622,21 @@ ** list is the number of rows in the index. (This is the same as the ** number of rows in the table, except for partial indices.) The second ** integer is the average number of rows in the index that have the same ** value in the first column of the index. The third integer is the average ** number of rows in the index that have the same value for the first two -** columns. The N-th integer (for N>1) is the average number of rows in +** columns. The N-th integer (for N>1) is the average number of rows in ** the index which have the same value for the first N-1 columns. For ** a K-column index, there will be K+1 integers in the stat column. If ** the index is unique, then the last integer will be 1. ** ** The list of integers in the stat column can optionally be followed ** by the keyword "unordered". The "unordered" keyword, if it is present, ** must be separated from the last integer by a single space. If the ** "unordered" keyword is present, then the query planner assumes that ** the index is unordered and will not use the index for a range query. -** +** ** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat ** column contains a single integer which is the (estimated) number of ** rows in the table identified by sqlite_stat1.tbl. ** ** Format of sqlite_stat2: @@ -119343,13 +97690,13 @@ ** first two columns match the first two columns of the sample. ** And so forth. nLt is another list of integers that show the approximate ** number of entries that are strictly less than the sample. The first ** integer in nLt contains the number of entries in the index where the ** left-most column is less than the left-most column of the sample. -** The K-th integer in the nLt entry is the number of index entries +** The K-th integer in the nLt entry is the number of index entries ** where the first K columns are less than the first K columns of the -** sample. The nDLt column is like nLt except that it contains the +** sample. The nDLt column is like nLt except that it contains the ** number of distinct entries in the index that are less than the ** sample. ** ** There can be an arbitrary number of sqlite_stat4 entries per index. ** The ANALYZE command will typically generate sqlite_stat4 tables @@ -119370,15 +97717,21 @@ #ifndef SQLITE_OMIT_ANALYZE /* #include "sqliteInt.h" */ #if defined(SQLITE_ENABLE_STAT4) # define IsStat4 1 +# define IsStat3 0 +#elif defined(SQLITE_ENABLE_STAT3) +# define IsStat4 0 +# define IsStat3 1 #else # define IsStat4 0 +# define IsStat3 0 # undef SQLITE_STAT4_SAMPLES # define SQLITE_STAT4_SAMPLES 1 #endif +#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */ /* ** This routine generates code that opens the sqlite_statN tables. ** The sqlite_stat1 table is always relevant. sqlite_stat2 is now ** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when @@ -119403,26 +97756,25 @@ const char *zCols; } aTable[] = { { "sqlite_stat1", "tbl,idx,stat" }, #if defined(SQLITE_ENABLE_STAT4) { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" }, + { "sqlite_stat3", 0 }, +#elif defined(SQLITE_ENABLE_STAT3) + { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" }, + { "sqlite_stat4", 0 }, #else + { "sqlite_stat3", 0 }, { "sqlite_stat4", 0 }, #endif - { "sqlite_stat3", 0 }, }; int i; sqlite3 *db = pParse->db; Db *pDb; Vdbe *v = sqlite3GetVdbe(pParse); - u32 aRoot[ArraySize(aTable)]; + int aRoot[ArraySize(aTable)]; u8 aCreateTbl[ArraySize(aTable)]; -#ifdef SQLITE_ENABLE_STAT4 - const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1; -#else - const int nToOpen = 1; -#endif if( v==0 ) return; assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; @@ -119431,49 +97783,45 @@ ** if they do already exist. */ for(i=0; izDbSName))==0 ){ - if( iregRoot. This is important + if( aTable[i].zCols ){ + /* The sqlite_statN table does not exist. Create it. Note that a + ** side-effect of the CREATE TABLE statement is to leave the rootpage + ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols ); - aRoot[i] = (u32)pParse->regRoot; + aRoot[i] = pParse->regRoot; aCreateTbl[i] = OPFLAG_P2ISREG; } }else{ - /* The table already exists. If zWhere is not NULL, delete all entries + /* The table already exists. If zWhere is not NULL, delete all entries ** associated with the table zWhere. If zWhere is NULL, delete the ** entire contents of the table. */ aRoot[i] = pStat->tnum; + aCreateTbl[i] = 0; sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); if( zWhere ){ sqlite3NestedParse(pParse, "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, (int)aRoot[i], iDb); + sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); } } } /* Open the sqlite_stat[134] tables for writing. */ - for(i=0; inRowid ){ sqlite3DbFree(db, p->u.aRowid); p->nRowid = 0; } @@ -119540,12 +97883,12 @@ } #endif /* Initialize the BLOB value of a ROWID */ -#ifdef SQLITE_ENABLE_STAT4 -static void sampleSetRowid(sqlite3 *db, StatSample *p, int n, const u8 *pData){ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ assert( db!=0 ); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); p->u.aRowid = sqlite3DbMallocRawNN(db, n); if( p->u.aRowid ){ p->nRowid = n; @@ -119556,12 +97899,12 @@ } #endif /* Initialize the INTEGER value of a ROWID. */ -#ifdef SQLITE_ENABLE_STAT4 -static void sampleSetRowidInt64(sqlite3 *db, StatSample *p, i64 iRowid){ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){ assert( db!=0 ); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); p->nRowid = 0; p->u.iRowid = iRowid; } @@ -119569,12 +97912,12 @@ /* ** Copy the contents of object (*pFrom) into (*pTo). */ -#ifdef SQLITE_ENABLE_STAT4 -static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ pTo->isPSample = pFrom->isPSample; pTo->iCol = pFrom->iCol; pTo->iHash = pFrom->iHash; memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol); memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol); @@ -119586,61 +97929,59 @@ } } #endif /* -** Reclaim all memory of a StatAccum structure. +** Reclaim all memory of a Stat4Accum structure. */ -static void statAccumDestructor(void *pOld){ - StatAccum *p = (StatAccum*)pOld; -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ){ - int i; - for(i=0; inCol; i++) sampleClear(p->db, p->aBest+i); - for(i=0; imxSample; i++) sampleClear(p->db, p->a+i); - sampleClear(p->db, &p->current); - } +static void stat4Destructor(void *pOld){ + Stat4Accum *p = (Stat4Accum*)pOld; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int i; + for(i=0; inCol; i++) sampleClear(p->db, p->aBest+i); + for(i=0; imxSample; i++) sampleClear(p->db, p->a+i); + sampleClear(p->db, &p->current); #endif sqlite3DbFree(p->db, p); } /* -** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters +** Implementation of the stat_init(N,K,C) SQL function. The three parameters ** are: ** N: The number of columns in the index including the rowid/pk (note 1) ** K: The number of columns in the index excluding the rowid/pk. -** C: Estimated number of rows in the index -** L: A limit on the number of rows to scan, or 0 for no-limit +** C: The number of rows in the index (note 2) ** ** Note 1: In the special case of the covering index that implements a ** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the ** total number of columns in the table. +** +** Note 2: C is only used for STAT3 and STAT4. ** ** For indexes on ordinary rowid tables, N==K+1. But for indexes on ** WITHOUT ROWID tables, N=K+P where P is the number of columns in the ** PRIMARY KEY of the table. The covering index that implements the ** original WITHOUT ROWID table as N==K as a special case. ** -** This routine allocates the StatAccum object in heap memory. The return -** value is a pointer to the StatAccum object. The datatype of the -** return value is BLOB, but it is really just a pointer to the StatAccum +** This routine allocates the Stat4Accum object in heap memory. The return +** value is a pointer to the Stat4Accum object. The datatype of the +** return value is BLOB, but it is really just a pointer to the Stat4Accum ** object. */ static void statInit( sqlite3_context *context, int argc, sqlite3_value **argv ){ - StatAccum *p; + Stat4Accum *p; int nCol; /* Number of columns in index being sampled */ int nKeyCol; /* Number of key columns */ int nColUp; /* nCol rounded up for alignment */ int n; /* Bytes of space to allocate */ - sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */ -#ifdef SQLITE_ENABLE_STAT4 - /* Maximum number of samples. 0 if STAT4 data is not collected */ - int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0; + sqlite3 *db; /* Database connection */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int mxSample = SQLITE_STAT4_SAMPLES; #endif /* Decode the three function arguments */ UNUSED_PARAMETER(argc); nCol = sqlite3_value_int(argv[0]); @@ -119648,59 +97989,56 @@ nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol; nKeyCol = sqlite3_value_int(argv[1]); assert( nKeyCol<=nCol ); assert( nKeyCol>0 ); - /* Allocate the space required for the StatAccum object */ - n = sizeof(*p) - + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ -#ifdef SQLITE_ENABLE_STAT4 - n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */ - if( mxSample ){ - n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */ - + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */ - + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample); - } + /* Allocate the space required for the Stat4Accum object */ + n = sizeof(*p) + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */ + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */ + + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */ + + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample) #endif + ; + db = sqlite3_context_db_handle(context); p = sqlite3DbMallocZero(db, n); if( p==0 ){ sqlite3_result_error_nomem(context); return; } p->db = db; - p->nEst = sqlite3_value_int64(argv[2]); p->nRow = 0; - p->nLimit = sqlite3_value_int64(argv[3]); p->nCol = nCol; p->nKeyCol = nKeyCol; - p->nSkipAhead = 0; p->current.anDLt = (tRowcnt*)&p[1]; - -#ifdef SQLITE_ENABLE_STAT4 p->current.anEq = &p->current.anDLt[nColUp]; - p->mxSample = p->nLimit==0 ? mxSample : 0; - if( mxSample ){ + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + { u8 *pSpace; /* Allocated space not yet assigned */ int i; /* Used to iterate through p->aSample[] */ p->iGet = -1; - p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1); + p->mxSample = mxSample; + p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); p->current.anLt = &p->current.anEq[nColUp]; p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); - - /* Set up the StatAccum.a[] and aBest[] arrays */ - p->a = (struct StatSample*)&p->current.anLt[nColUp]; + + /* Set up the Stat4Accum.a[] and aBest[] arrays */ + p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; p->aBest = &p->a[mxSample]; pSpace = (u8*)(&p->a[mxSample+nCol]); for(i=0; i<(mxSample+nCol); i++){ p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp); } assert( (pSpace - (u8*)p)==n ); - + for(i=0; iaBest[i].iCol = i; } } #endif @@ -119707,40 +98045,39 @@ /* Return a pointer to the allocated object to the caller. Note that ** only the pointer (the 2nd parameter) matters. The size of the object ** (given by the 3rd parameter) is never used and can be any positive ** value. */ - sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor); + sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor); } static const FuncDef statInitFuncdef = { - 4, /* nArg */ + 2+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statInit, /* xSFunc */ 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ "stat_init", /* zName */ {0} }; #ifdef SQLITE_ENABLE_STAT4 /* -** pNew and pOld are both candidate non-periodic samples selected for -** the same column (pNew->iCol==pOld->iCol). Ignoring this column and +** pNew and pOld are both candidate non-periodic samples selected for +** the same column (pNew->iCol==pOld->iCol). Ignoring this column and ** considering only any trailing columns and the sample hash value, this ** function returns true if sample pNew is to be preferred over pOld. ** In other words, if we assume that the cardinalities of the selected ** column for pNew and pOld are equal, is pNew to be preferred over pOld. ** ** This function assumes that for each argument sample, the contents of -** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. +** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. */ static int sampleIsBetterPost( - StatAccum *pAccum, - StatSample *pNew, - StatSample *pOld + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld ){ int nCol = pAccum->nCol; int i; assert( pNew->iCol==pOld->iCol ); for(i=pNew->iCol+1; iiHash>pOld->iHash ) return 1; return 0; } #endif -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Return true if pNew is to be preferred over pOld. ** ** This function assumes that for each argument sample, the contents of -** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. +** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. */ static int sampleIsBetter( - StatAccum *pAccum, - StatSample *pNew, - StatSample *pOld + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld ){ tRowcnt nEqNew = pNew->anEq[pNew->iCol]; tRowcnt nEqOld = pOld->anEq[pOld->iCol]; assert( pOld->isPSample==0 && pNew->isPSample==0 ); assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); if( (nEqNew>nEqOld) ) return 1; +#ifdef SQLITE_ENABLE_STAT4 if( nEqNew==nEqOld ){ if( pNew->iColiCol ) return 1; return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); } return 0; +#else + return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); +#endif } /* ** Copy the contents of sample *pNew into the p->a[] array. If necessary, ** remove the least desirable sample from p->a[] to make room. */ -static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){ - StatSample *pSample = 0; +static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ + Stat4Sample *pSample = 0; int i; assert( IsStat4 || nEqZero==0 ); - /* StatAccum.nMaxEqZero is set to the maximum number of leading 0 - ** values in the anEq[] array of any sample in StatAccum.a[]. In +#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 StatSample.anEq[m]==0 for (m>=n). */ + ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */ if( nEqZero>p->nMaxEqZero ){ p->nMaxEqZero = nEqZero; } if( pNew->isPSample==0 ){ - StatSample *pUpgrade = 0; + Stat4Sample *pUpgrade = 0; assert( pNew->anEq[pNew->iCol]>0 ); - /* This sample is being added because the prefix that ends in column + /* This sample is being added because the prefix that ends in column ** iCol occurs many times in the table. However, if we have already ** added a sample that shares this prefix, there is no need to add ** this one. Instead, upgrade the priority of the highest priority ** existing sample that shares this prefix. */ for(i=p->nSample-1; i>=0; i--){ - StatSample *pOld = &p->a[i]; + Stat4Sample *pOld = &p->a[i]; if( pOld->anEq[pNew->iCol]==0 ){ if( pOld->isPSample ) return; assert( pOld->iCol>pNew->iCol ); assert( sampleIsBetter(p, pNew, pOld) ); if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){ @@ -119819,14 +98161,15 @@ pUpgrade->iCol = pNew->iCol; pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol]; goto find_new_min; } } +#endif /* If necessary, remove sample iMin to make room for the new sample. */ if( p->nSample>=p->mxSample ){ - StatSample *pMin = &p->a[p->iMin]; + Stat4Sample *pMin = &p->a[p->iMin]; tRowcnt *anEq = pMin->anEq; tRowcnt *anLt = pMin->anLt; tRowcnt *anDLt = pMin->anDLt; sampleClear(p->db, pMin); memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1)); @@ -119839,22 +98182,26 @@ } /* The "rows less-than" for the rowid column must be greater than that ** for the last sample in the p->a[] array. Otherwise, the samples would ** be out of order. */ - assert( p->nSample==0 +#ifdef SQLITE_ENABLE_STAT4 + assert( p->nSample==0 || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] ); +#endif /* Insert the new sample */ pSample = &p->a[p->nSample]; sampleCopy(p, pSample, pNew); p->nSample++; /* Zero the first nEqZero entries in the anEq[] array. */ memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); -find_new_min: +#ifdef SQLITE_ENABLE_STAT4 + find_new_min: +#endif if( p->nSample>=p->mxSample ){ int iMin = -1; for(i=0; imxSample; i++){ if( p->a[i].isPSample ) continue; if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){ @@ -119863,26 +98210,26 @@ } assert( iMin>=0 ); p->iMin = iMin; } } -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ -#ifdef SQLITE_ENABLE_STAT4 /* ** Field iChng of the index being scanned has changed. So at this point ** p->current contains a sample that reflects the previous row of the ** index. The value of anEq[iChng] and subsequent anEq[] elements are ** correct at this point. */ -static void samplePushPrevious(StatAccum *p, int iChng){ +static void samplePushPrevious(Stat4Accum *p, int iChng){ +#ifdef SQLITE_ENABLE_STAT4 int i; /* Check if any samples from the aBest[] array should be pushed ** into IndexSample.a[] at this point. */ for(i=(p->nCol-2); i>=iChng; i--){ - StatSample *pBest = &p->aBest[i]; + Stat4Sample *pBest = &p->aBest[i]; pBest->anEq[i] = p->current.anEq[i]; if( p->nSamplemxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ sampleInsert(p, pBest, i); } } @@ -119902,88 +98249,106 @@ if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; } } p->nMaxEqZero = iChng; } +#endif + +#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) + if( iChng==0 ){ + tRowcnt nLt = p->current.anLt[0]; + tRowcnt nEq = p->current.anEq[0]; + + /* Check if this is to be a periodic sample. If so, add it. */ + if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){ + p->current.isPSample = 1; + sampleInsert(p, &p->current, 0); + p->current.isPSample = 0; + }else + + /* Or if it is a non-periodic sample. Add it in this case too. */ + if( p->nSamplemxSample + || sampleIsBetter(p, &p->current, &p->a[p->iMin]) + ){ + sampleInsert(p, &p->current, 0); + } + } +#endif + +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + UNUSED_PARAMETER( p ); + UNUSED_PARAMETER( iChng ); +#endif } -#endif /* SQLITE_ENABLE_STAT4 */ /* ** Implementation of the stat_push SQL function: stat_push(P,C,R) ** Arguments: ** -** P Pointer to the StatAccum object created by stat_init() +** P Pointer to the Stat4Accum object created by stat_init() ** C Index of left-most column to differ from previous row ** R Rowid for the current row. Might be a key record for ** WITHOUT ROWID tables. ** -** The purpose of this routine is to collect statistical data and/or -** samples from the index being analyzed into the StatAccum object. -** The stat_get() SQL function will be used afterwards to -** retrieve the information gathered. -** -** This SQL function usually returns NULL, but might return an integer -** if it wants the byte-code to do special processing. -** -** The R parameter is only used for STAT4 +** This SQL function always returns NULL. It's purpose it to accumulate +** statistical data and/or samples in the Stat4Accum object about the +** index being analyzed. The stat_get() SQL function will later be used to +** extract relevant information for constructing the sqlite_statN tables. +** +** The R parameter is only used for STAT3 and STAT4 */ static void statPush( sqlite3_context *context, int argc, sqlite3_value **argv ){ int i; /* The three function arguments */ - StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]); + Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); int iChng = sqlite3_value_int(argv[1]); UNUSED_PARAMETER( argc ); UNUSED_PARAMETER( context ); assert( p->nCol>0 ); assert( iChngnCol ); if( p->nRow==0 ){ /* This is the first call to this function. Do initialization. */ -#ifdef SQLITE_ENABLE_STAT4 for(i=0; inCol; i++) p->current.anEq[i] = 1; -#endif }else{ /* Second and subsequent calls get processed here */ -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ) samplePushPrevious(p, iChng); -#endif + samplePushPrevious(p, iChng); /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply ** to the current row of the index. */ -#ifdef SQLITE_ENABLE_STAT4 for(i=0; icurrent.anEq[i]++; } -#endif for(i=iChng; inCol; i++){ p->current.anDLt[i]++; -#ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i]; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + p->current.anLt[i] += p->current.anEq[i]; +#endif p->current.anEq[i] = 1; -#endif } } - p->nRow++; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){ + sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2])); + }else{ + sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]), + sqlite3_value_blob(argv[2])); + } + p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345; +#endif + #ifdef SQLITE_ENABLE_STAT4 - if( p->mxSample ){ - tRowcnt nLt; - if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){ - sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2])); - }else{ - sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]), - sqlite3_value_blob(argv[2])); - } - p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345; - - nLt = p->current.anLt[p->nCol-1]; + { + tRowcnt nLt = p->current.anLt[p->nCol-1]; + /* Check if this is to be a periodic sample. If so, add it. */ if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){ p->current.isPSample = 1; p->current.iCol = 0; sampleInsert(p, &p->current, p->nCol-1); @@ -119995,26 +98360,20 @@ p->current.iCol = i; if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){ sampleCopy(p, &p->aBest[i], &p->current); } } - }else + } #endif - if( p->nLimit && p->nRow>(tRowcnt)p->nLimit*(p->nSkipAhead+1) ){ - p->nSkipAhead++; - sqlite3_result_int(context, p->current.anDLt[0]>0); - } } - static const FuncDef statPushFuncdef = { - 2+IsStat4, /* nArg */ + 2+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statPush, /* xSFunc */ 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ "stat_push", /* zName */ {0} }; #define STAT_GET_STAT1 0 /* "stat" column of stat1 table */ @@ -120024,180 +98383,165 @@ #define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */ /* ** Implementation of the stat_get(P,J) SQL function. This routine is ** used to query statistical information that has been gathered into -** the StatAccum object by prior calls to stat_push(). The P parameter -** has type BLOB but it is really just a pointer to the StatAccum object. +** the Stat4Accum object by prior calls to stat_push(). The P parameter +** has type BLOB but it is really just a pointer to the Stat4Accum object. ** 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 pointer to a StatAccum object, never a +** parameter will always be a poiner to a Stat4Accum object, never a ** NULL. ** -** If STAT4 is not enabled, then J is always +** 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 ** stat1 table entry information. */ static void statGet( sqlite3_context *context, int argc, sqlite3_value **argv ){ - StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]); -#ifdef SQLITE_ENABLE_STAT4 - /* STAT4 has a parameter on this routine. */ + Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* STAT3 and STAT4 have a parameter on this routine. */ int eCall = sqlite3_value_int(argv[1]); assert( argc==2 ); - assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ + assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT - || eCall==STAT_GET_NDLT + || eCall==STAT_GET_NDLT ); - assert( eCall==STAT_GET_STAT1 || p->mxSample ); if( eCall==STAT_GET_STAT1 ) #else assert( argc==1 ); #endif { /* Return the value to store in the "stat" column of the sqlite_stat1 ** table for this index. ** - ** The value is a string composed of a list of integers describing - ** the index. The first integer in the list is the total number of - ** entries in the index. There is one additional integer in the list + ** The value is a string composed of a list of integers describing + ** the index. The first integer in the list is the total number of + ** entries in the index. There is one additional integer in the list ** for each indexed column. This additional integer is an estimate of - ** the number of rows matched by a equality query on the index using + ** the number of rows matched by a stabbing query on the index using ** a key with the corresponding number of fields. In other words, - ** if the index is on columns (a,b) and the sqlite_stat1 value is + ** if the index is on columns (a,b) and the sqlite_stat1 value is ** "100 10 2", then SQLite estimates that: ** ** * the index contains 100 rows, ** * "WHERE a=?" matches 10 rows, and ** * "WHERE a=? AND b=?" matches 2 rows. ** - ** If D is the count of distinct values and K is the total number of - ** rows, then each estimate is usually computed as: + ** If D is the count of distinct values and K is the total number of + ** rows, then each estimate is computed as: ** ** I = (K+D-1)/D - ** - ** In other words, I is K/D rounded up to the next whole integer. - ** However, if I is between 1.0 and 1.1 (in other words if I is - ** close to 1.0 but just a little larger) then do not round up but - ** instead keep the I value at 1.0. */ - sqlite3_str sStat; /* Text of the constructed "stat" line */ - int i; /* Loop counter */ + char *z; + int i; - sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100); - sqlite3_str_appendf(&sStat, "%llu", - p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow); + char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 ); + if( zRet==0 ){ + sqlite3_result_error_nomem(context); + return; + } + + sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); + z = zRet + sqlite3Strlen30(zRet); for(i=0; inKeyCol; i++){ u64 nDistinct = p->current.anDLt[i] + 1; u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; - if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1; - sqlite3_str_appendf(&sStat, " %llu", iVal); -#ifdef SQLITE_ENABLE_STAT4 - assert( p->current.anEq[i] || p->nRow==0 ); -#endif - } - sqlite3ResultStrAccum(context, &sStat); - } -#ifdef SQLITE_ENABLE_STAT4 + sqlite3_snprintf(24, z, " %llu", iVal); + z += sqlite3Strlen30(z); + assert( p->current.anEq[i] ); + } + assert( z[0]=='\0' && z>zRet ); + + sqlite3_result_text(context, zRet, -1, sqlite3_free); + } +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 else if( eCall==STAT_GET_ROWID ){ if( p->iGet<0 ){ samplePushPrevious(p, 0); p->iGet = 0; } if( p->iGetnSample ){ - StatSample *pS = p->a + p->iGet; + Stat4Sample *pS = p->a + p->iGet; if( pS->nRowid==0 ){ sqlite3_result_int64(context, pS->u.iRowid); }else{ sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid, SQLITE_TRANSIENT); } } }else{ tRowcnt *aCnt = 0; - sqlite3_str sStat; - int i; assert( p->iGetnSample ); switch( eCall ){ case STAT_GET_NEQ: aCnt = p->a[p->iGet].anEq; break; case STAT_GET_NLT: aCnt = p->a[p->iGet].anLt; break; default: { - aCnt = p->a[p->iGet].anDLt; + aCnt = p->a[p->iGet].anDLt; p->iGet++; break; } } - sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100); - for(i=0; inCol; i++){ - sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]); - } - if( sStat.nChar ) sStat.nChar--; - sqlite3ResultStrAccum(context, &sStat); - } -#endif /* SQLITE_ENABLE_STAT4 */ + + if( IsStat3 ){ + sqlite3_result_int64(context, (i64)aCnt[0]); + }else{ + char *zRet = sqlite3MallocZero(p->nCol * 25); + if( zRet==0 ){ + sqlite3_result_error_nomem(context); + }else{ + int i; + char *z = zRet; + for(i=0; inCol; i++){ + sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]); + z += sqlite3Strlen30(z); + } + assert( z[0]=='\0' && z>zRet ); + z[-1] = '\0'; + sqlite3_result_text(context, zRet, -1, sqlite3_free); + } + } + } +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( argc ); #endif } static const FuncDef statGetFuncdef = { - 1+IsStat4, /* nArg */ + 1+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statGet, /* xSFunc */ 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ "stat_get", /* zName */ {0} }; -static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){ -#ifdef SQLITE_ENABLE_STAT4 - sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1); +static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ + assert( regOut!=regStat4 && regOut!=regStat4+1 ); +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1); #elif SQLITE_DEBUG assert( iParam==STAT_GET_STAT1 ); #else UNUSED_PARAMETER( iParam ); #endif - assert( regOut!=regStat && regOut!=regStat+1 ); - sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4, - &statGetFuncdef, 0); -} - -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS -/* Add a comment to the most recent VDBE opcode that is the name -** of the k-th column of the pIdx index. -*/ -static void analyzeVdbeCommentIndexWithColumnName( - Vdbe *v, /* Prepared statement under construction */ - Index *pIdx, /* Index whose column is being loaded */ - int k /* Which column index */ -){ - int i; /* Index of column in the table */ - assert( k>=0 && knColumn ); - i = pIdx->aiColumn[k]; - if( NEVER(i==XN_ROWID) ){ - VdbeComment((v,"%s.rowid",pIdx->zName)); - }else if( i==XN_EXPR ){ - assert( pIdx->bHasExpr ); - VdbeComment((v,"%s.expr(%d)",pIdx->zName, k)); - }else{ - VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName)); - } -} -#else -# define analyzeVdbeCommentIndexWithColumnName(a,b,c) -#endif /* SQLITE_DEBUG */ + sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut, + (char*)&statGetFuncdef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, 1 + IsStat34); +} /* ** Generate code to do an analysis of all indices associated with ** a single table. */ @@ -120217,37 +98561,31 @@ int i; /* Loop counter */ int jZeroRows = -1; /* Jump from here if number of rows is zero */ int iDb; /* Index of database containing pTab */ u8 needTableCnt = 1; /* True to count the table */ int regNewRowid = iMem++; /* Rowid for the inserted record */ - int regStat = iMem++; /* Register to hold StatAccum object */ + int regStat4 = iMem++; /* Register to hold Stat4Accum object */ int regChng = iMem++; /* Index of changed index field */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int regRowid = iMem++; /* Rowid argument passed to stat_push() */ +#endif int regTemp = iMem++; /* Temporary use register */ - int regTemp2 = iMem++; /* Second temporary use register */ int regTabname = iMem++; /* Register containing table name */ 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_STAT4 - int doOnce = 1; /* Flag for a one-time computation */ -#endif -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - Table *pStat1 = 0; -#endif - - sqlite3TouchRegister(pParse, iMem); - assert( sqlite3NoTempsInRange(pParse, regNewRowid, iMem) ); + + pParse->nMem = MAX(pParse->nMem, iMem); v = sqlite3GetVdbe(pParse); if( v==0 || NEVER(pTab==0) ){ return; } - if( !IsOrdinaryTable(pTab) ){ + if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } - if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ + if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){ /* Do not gather statistics on system tables */ return; } assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -120258,23 +98596,11 @@ db->aDb[iDb].zDbSName ) ){ return; } #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_DYNAMIC); - } -#endif - - /* Establish a read-lock on the table at the shared-cache level. + /* 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 ** this time though. */ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); iTabCur = iTab++; @@ -120283,11 +98609,11 @@ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regTabname, pTab->zName); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int nCol; /* Number of columns in pIdx. "N" */ - int addrGotoEnd; /* Address of "OP_Rewind iIdxCur" */ + int addrRewind; /* Address of "OP_Rewind iIdxCur" */ int addrNextRow; /* Address of "next_row:" */ const char *zIdxName; /* Name of the index */ int nColTest; /* Number of columns to test for changes */ if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; @@ -120307,18 +98633,13 @@ VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName)); /* ** Pseudo-code for loop that calls stat_push(): ** - ** regChng = 0 ** Rewind csr - ** if eof(csr){ - ** stat_init() with count = 0; - ** goto end_of_scan; - ** } - ** count() - ** stat_init() + ** if eof(csr) goto end_of_scan; + ** regChng = 0 ** goto chng_addr_0; ** ** next_row: ** regChng = 0 ** if( idx(0) != regPrev(0) ) goto chng_addr_0 @@ -120341,57 +98662,56 @@ ** if !eof(csr) goto next_row; ** ** end_of_scan: */ - /* Make sure there are enough memory cells allocated to accommodate + /* Make sure there are enough memory cells allocated to accommodate ** the regPrev array and a trailing rowid (the rowid slot is required - ** when building a record to insert into the sample column of + ** when building a record to insert into the sample column of ** the sqlite_stat4 table. */ - sqlite3TouchRegister(pParse, regPrev+nColTest); + pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); /* Open a read-only cursor on the index being analyzed. */ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); - /* Implementation of the following: - ** - ** regChng = 0 - ** Rewind csr - ** if eof(csr){ - ** stat_init() with count = 0; - ** goto end_of_scan; - ** } - ** count() - ** stat_init() - ** goto chng_addr_0; - */ - assert( regTemp2==regStat+4 ); - sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2); - - /* Arguments to stat_init(): + /* Invoke the stat_init() function. The arguments are: + ** ** (1) the number of columns in the index including the rowid ** (or for a WITHOUT ROWID table, the number of PK columns), ** (2) the number of columns in the key without the rowid/pk - ** (3) estimated number of rows in the index. */ - sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1); - assert( regRowid==regStat+2 ); - sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid); - sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, - OptimizationDisabled(db, SQLITE_Stat4)); - sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4, - &statInitFuncdef, 0); - addrGotoEnd = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); + ** (3) the number of rows in the index, + ** + ** + ** The third argument is only used for STAT3 and STAT4 + */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3); +#endif + sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2); + sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4, + (char*)&statInitFuncdef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, 2+IsStat34); + + /* Implementation of the following: + ** + ** Rewind csr + ** if eof(csr) goto end_of_scan; + ** regChng = 0 + ** goto next_push_0; + ** + */ + addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); addrNextRow = sqlite3VdbeCurrentAddr(v); if( nColTest>0 ){ - int endDistinctTest = sqlite3VdbeMakeLabel(pParse); + int endDistinctTest = sqlite3VdbeMakeLabel(v); int *aGotoChng; /* Array of jump instruction addresses */ aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest); if( aGotoChng==0 ) continue; /* @@ -120406,29 +98726,28 @@ */ sqlite3VdbeAddOp0(v, OP_Goto); addrNextRow = sqlite3VdbeCurrentAddr(v); if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){ /* For a single-column UNIQUE index, once we have found a non-NULL - ** row, we know that all the rest will be distinct, so skip + ** row, we know that all the rest will be distinct, so skip ** subsequent distinctness tests. */ sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest); VdbeCoverage(v); } for(i=0; iazColl[i]); sqlite3VdbeAddOp2(v, OP_Integer, i, regChng); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp); - analyzeVdbeCommentIndexWithColumnName(v,pIdx,i); - aGotoChng[i] = + aGotoChng[i] = sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng); sqlite3VdbeGoto(v, endDistinctTest); - - + + /* ** chng_addr_0: ** regPrev(0) = idx(0) ** chng_addr_1: ** regPrev(1) = idx(1) @@ -120436,82 +98755,57 @@ */ sqlite3VdbeJumpHere(v, addrNextRow-1); for(i=0; ipTable); - int j, k, regKey; - regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol); - for(j=0; jnKeyCol; j++){ - k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]); - assert( k>=0 && knColumn ); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j); - analyzeVdbeCommentIndexWithColumnName(v,pIdx,k); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid); - sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol); - } +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + assert( regRowid==(regStat4+2) ); + if( HasRowid(pTab) ){ + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); + int j, k, regKey; + regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol); + for(j=0; jnKeyCol; j++){ + k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); + assert( k>=0 && knColumn ); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j); + VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName)); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid); + sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol); } #endif - assert( regChng==(regStat+1) ); - { - sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4, - &statPushFuncdef, 0); - if( db->nAnalysisLimit ){ - int j1, j2, j3; - j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v); - j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v); - j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, j2); - sqlite3VdbeJumpHere(v, j3); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); - } - } + assert( regChng==(regStat4+1) ); + sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp, + (char*)&statPushFuncdef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, 2+IsStat34); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); /* Add the entry to the stat1 table. */ - if( pIdx->pPartIdxWhere ){ - /* Partial indexes might get a zero-entry in sqlite_stat1. But - ** an empty table is omitted from sqlite_stat1. */ - sqlite3VdbeJumpHere(v, addrGotoEnd); - addrGotoEnd = 0; - } - callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1); + callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); assert( "BBB"[0]==SQLITE_AFF_TEXT ); 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 stat4 table. */ -#ifdef SQLITE_ENABLE_STAT4 - if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){ + /* Add the entries to the stat3 or stat4 table. */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + { int regEq = regStat1; int regLt = regStat1+1; int regDLt = regStat1+2; int regSample = regStat1+3; int regCol = regStat1+4; @@ -120518,70 +98812,42 @@ int regSampleRowid = regCol + nCol; int addrNext; int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - /* No STAT4 data is generated if the number of rows is zero */ - if( addrGotoEnd==0 ){ - sqlite3VdbeAddOp2(v, OP_Cast, regStat1, SQLITE_AFF_INTEGER); - addrGotoEnd = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); - VdbeCoverage(v); - } - - if( doOnce ){ - int mxCol = nCol; - Index *pX; - - /* Compute the maximum number of columns in any index */ - for(pX=pTab->pIndex; pX; pX=pX->pNext){ - int nColX; /* Number of columns in pX */ - if( !HasRowid(pTab) && IsPrimaryKeyIndex(pX) ){ - nColX = pX->nKeyCol; - }else{ - nColX = pX->nColumn; - } - if( nColX>mxCol ) mxCol = nColX; - } - - /* Allocate space to compute results for the largest index */ - sqlite3TouchRegister(pParse, regCol+mxCol); - doOnce = 0; -#ifdef SQLITE_DEBUG - /* Verify that the call to sqlite3ClearTempRegCache() below - ** really is needed. - ** https://sqlite.org/forum/forumpost/83cb4a95a0 (2023-03-25) - */ - testcase( !sqlite3NoTempsInRange(pParse, regEq, regCol+mxCol) ); -#endif - sqlite3ClearTempRegCache(pParse); /* tag-20230325-1 */ - assert( sqlite3NoTempsInRange(pParse, regEq, regCol+mxCol) ); - } - assert( sqlite3NoTempsInRange(pParse, regEq, regCol+nCol) ); + pParse->nMem = MAX(pParse->nMem, regCol+nCol); addrNext = sqlite3VdbeCurrentAddr(v); - callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid); + callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); VdbeCoverage(v); - callStatGet(pParse, regStat, STAT_GET_NEQ, regEq); - callStatGet(pParse, regStat, STAT_GET_NLT, regLt); - callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt); + callStatGet(v, regStat4, STAT_GET_NEQ, regEq); + callStatGet(v, regStat4, STAT_GET_NLT, regLt); + callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); - VdbeCoverage(v); + /* We know that the regSampleRowid row exists because it was read by + ** the previous loop. Thus the not-found jump of seekOp will never + ** be taken */ + VdbeCoverageNeverTaken(v); +#ifdef SQLITE_ENABLE_STAT3 + sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample); +#else for(i=0; inTab; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); -#ifdef SQLITE_ENABLE_STAT4 - iMem = sqlite3FirstAvailableRegister(pParse, iMem); -#else - assert( iMem==sqlite3FirstAvailableRegister(pParse,iMem) ); -#endif } loadAnalysis(pParse, iDb); } /* @@ -120754,11 +99012,11 @@ char *z = zIntArray; int c; int i; tRowcnt v; -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; #else assert( z!=0 ); #endif for(i=0; *z && i='0' && c<='9' ){ v = v*10 + c - '0'; z++; } -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( aOut ) aOut[i] = v; if( aLog ) aLog[i] = sqlite3LogEst(v); #else assert( aOut==0 ); UNUSED_PARAMETER(aOut); @@ -120776,11 +99034,11 @@ assert( aLog!=0 ); aLog[i] = sqlite3LogEst(v); #endif if( *z==' ' ) z++; } -#ifndef SQLITE_ENABLE_STAT4 +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 assert( pIndex!=0 ); { #else if( pIndex ){ #endif pIndex->bUnordered = 0; @@ -120787,13 +99045,11 @@ pIndex->noSkipScan = 0; while( z[0] ){ if( sqlite3_strglob("unordered*", z)==0 ){ pIndex->bUnordered = 1; }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ - int sz = sqlite3Atoi(z+3); - if( sz<2 ) sz = 2; - pIndex->szIdxRow = sqlite3LogEst(sz); + pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3)); }else if( sqlite3_strglob("noskipscan*", z)==0 ){ pIndex->noSkipScan = 1; } #ifdef SQLITE_ENABLE_COSTMULT else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){ @@ -120801,26 +99057,16 @@ } #endif while( z[0]!=0 && z[0]!=' ' ) z++; while( z[0]==' ' ) z++; } - - /* Set the bLowQual flag if the peak number of rows obtained - ** from a full equality match is so large that a full table scan - ** seems likely to be faster than using the index. - */ - if( aLog[0] > 66 /* Index has more than 100 rows */ - && aLog[0] <= aLog[nOut-1] /* And only a single value seen */ - ){ - pIndex->bLowQual = 1; - } } } /* ** This callback is invoked once for each index when reading the -** sqlite_stat1 table. +** sqlite_stat1 table. ** ** argv[0] = name of the table ** argv[1] = name of the index (might be NULL) ** argv[2] = results of analysis - on integer for each column ** @@ -120853,12 +99099,12 @@ z = argv[2]; if( pIndex ){ tRowcnt *aiRowEst = 0; int nCol = pIndex->nKeyCol+1; -#ifdef SQLITE_ENABLE_STAT4 - /* Index.aiRowEst may already be set here if there are duplicate +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* Index.aiRowEst may already be set here if there are duplicate ** sqlite_stat1 entries for this index. In that case just clobber ** the old data with the new instead of allocating a new array. */ if( pIndex->aiRowEst==0 ){ pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db); @@ -120889,35 +99135,33 @@ /* ** If the Index.aSample variable is not NULL, delete the aSample[] array ** and its contents. */ SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ - assert( db!=0 ); - assert( pIdx!=0 ); -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( pIdx->aSample ){ int j; for(j=0; jnSample; j++){ IndexSample *p = &pIdx->aSample[j]; sqlite3DbFree(db, p->p); } sqlite3DbFree(db, pIdx->aSample); } - if( db->pnBytesFreed==0 ){ + if( db && db->pnBytesFreed==0 ){ pIdx->nSample = 0; pIdx->aSample = 0; } #else UNUSED_PARAMETER(db); UNUSED_PARAMETER(pIdx); -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ } -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Populate the pIdx->aAvgEq[] array based on the samples currently -** stored in pIdx->aSample[]. +** stored in pIdx->aSample[]. */ static void initAvgEq(Index *pIdx){ if( pIdx ){ IndexSample *aSample = pIdx->aSample; IndexSample *pFinal = &aSample[pIdx->nSample-1]; @@ -120949,16 +99193,16 @@ nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1]; } pIdx->nRowEst0 = nRow; /* Set nSum to the number of distinct (iCol+1) field prefixes that - ** occur in the stat4 table for this index. Set sumEq to the sum of - ** the nEq values for column iCol for the same set (adding the value + ** occur in the stat4 table for this index. Set sumEq to the sum of + ** the nEq values for column iCol for the same set (adding the value ** only once where there exist duplicate prefixes). */ for(i=0; inSample-1) - || aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] + || aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){ sumEq += aSample[i].anEq[iCol]; nSum100 += 100; } } @@ -120988,23 +99232,25 @@ } return pIdx; } /* -** Load the content from either the sqlite_stat4 +** Load the content from either the sqlite_stat4 or sqlite_stat3 table ** into the relevant Index.aSample[] arrays. ** ** Arguments zSql1 and zSql2 must point to SQL statements that return -** data equivalent to the following: +** data equivalent to the following (statements are different for stat3, +** see the caller of this function for details): ** ** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx ** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4 ** ** where %Q is replaced with the database name before the SQL is executed. */ static int loadStatTbl( sqlite3 *db, /* Database handle */ + int bStat3, /* Assume single column records only */ const char *zSql1, /* SQL statement 1 (see above) */ const char *zSql2, /* SQL statement 2 (see above) */ const char *zDb /* Database name (e.g. "main") */ ){ int rc; /* Result codes from subroutines */ @@ -121023,51 +99269,45 @@ if( rc ) return rc; while( sqlite3_step(pStmt)==SQLITE_ROW ){ int nIdxCol = 1; /* Number of columns in stat4 records */ - char *zIndex; /* Index name */ - Index *pIdx; /* Pointer to the index object */ - int nSample; /* Number of samples */ - i64 nByte; /* Bytes of space required */ - i64 i; /* Bytes of space required */ - tRowcnt *pSpace; /* Available allocated memory space */ - u8 *pPtr; /* Available memory as a u8 for easier manipulation */ + char *zIndex; /* Index name */ + Index *pIdx; /* Pointer to the index object */ + int nSample; /* Number of samples */ + int nByte; /* Bytes of space required */ + int i; /* Bytes of space required */ + tRowcnt *pSpace; zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; nSample = sqlite3_column_int(pStmt, 1); pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); - assert( pIdx==0 || pIdx->nSample==0 ); - if( pIdx==0 ) continue; - if( pIdx->aSample!=0 ){ - /* The same index appears in sqlite_stat4 under multiple names */ - continue; - } - assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); - if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ - nIdxCol = pIdx->nKeyCol; - }else{ - nIdxCol = pIdx->nColumn; + assert( pIdx==0 || bStat3 || pIdx->nSample==0 ); + /* Index.nSample is non-zero at this point if data has already been + ** loaded from the stat4 table. In this case ignore stat3 data. */ + if( pIdx==0 || pIdx->nSample ) continue; + if( bStat3==0 ){ + assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); + if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ + nIdxCol = pIdx->nKeyCol; + }else{ + nIdxCol = pIdx->nColumn; + } } pIdx->nSampleCol = nIdxCol; - pIdx->mxSample = nSample; - nByte = ROUND8(sizeof(IndexSample) * nSample); + nByte = sizeof(IndexSample) * nSample; nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ pIdx->aSample = sqlite3DbMallocZero(db, nByte); if( pIdx->aSample==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; } - pPtr = (u8*)pIdx->aSample; - pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0])); - pSpace = (tRowcnt*)pPtr; - assert( EIGHT_BYTE_ALIGNMENT( pSpace ) ); + pSpace = (tRowcnt*)&pIdx->aSample[nSample]; pIdx->aAvgEq = pSpace; pSpace += nIdxCol; - pIdx->pTable->tabFlags |= TF_HasStat4; for(i=0; iaSample[i].anEq = pSpace; pSpace += nIdxCol; pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; } @@ -121091,36 +99331,31 @@ zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); if( pIdx==0 ) continue; - if( pIdx->nSample>=pIdx->mxSample ){ - /* Too many slots used because the same index appears in - ** sqlite_stat4 using multiple names */ - continue; - } - /* This next condition is true if data has already been loaded from - ** the sqlite_stat4 table. */ + /* This next condition is true if data has already been loaded from + ** the sqlite_stat4 table. In this case ignore stat3 data. */ nCol = pIdx->nSampleCol; + if( bStat3 && nCol>1 ) continue; if( pIdx!=pPrevIdx ){ initAvgEq(pPrevIdx); pPrevIdx = pIdx; } pSample = &pIdx->aSample[pIdx->nSample]; decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); - /* Take a copy of the sample. Add 8 extra 0x00 bytes the end of the buffer. + /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer. ** This is in case the sample record is corrupted. In that case, the ** sqlite3VdbeRecordCompare() may read up to two varints past the ** end of the allocated buffer before it realizes it is dealing with - ** a corrupt record. Or it might try to read a large integer from the - ** buffer. In any case, eight 0x00 bytes prevents this from causing + ** a corrupt record. Adding the two 0x00 bytes prevents this from causing ** a buffer overread. */ pSample->n = sqlite3_column_bytes(pStmt, 4); - pSample->p = sqlite3DbMallocZero(db, pSample->n + 8); + pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); if( pSample->p==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; } if( pSample->n ){ @@ -121132,44 +99367,49 @@ if( rc==SQLITE_OK ) initAvgEq(pPrevIdx); return rc; } /* -** Load content from the sqlite_stat4 table into +** Load content from the sqlite_stat4 and sqlite_stat3 tables into ** the Index.aSample[] arrays of all indices. */ static int loadStat4(sqlite3 *db, const char *zDb){ int rc = SQLITE_OK; /* Result codes from subroutines */ - const Table *pStat4; assert( db->lookaside.bDisable ); - if( OptimizationEnabled(db, SQLITE_Stat4) - && (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0 - && IsOrdinaryTable(pStat4) - ){ - rc = loadStatTbl(db, - "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx COLLATE nocase", + if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ + rc = loadStatTbl(db, 0, + "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", zDb ); } + + if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){ + rc = loadStatTbl(db, 1, + "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", + "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3", + zDb + ); + } + return rc; } -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* -** Load the content of the sqlite_stat1 and sqlite_stat4 tables. The +** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The ** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] -** arrays. The contents of sqlite_stat4 are used to populate the +** arrays. The contents of sqlite_stat3/4 are used to populate the ** Index.aSample[] arrays. ** ** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR -** is returned. In this case, even if SQLITE_ENABLE_STAT4 was defined -** during compilation and the sqlite_stat4 table is present, no data is +** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined +** during compilation and the sqlite_stat3/4 table is present, no data is ** read from it. ** -** If SQLITE_ENABLE_STAT4 was defined during compilation and the +** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the ** sqlite_stat4 table is not present in the database, SQLITE_ERROR is ** returned. However, in this case, data is read from the sqlite_stat1 ** table (if it is present) before returning. ** ** If an OOM error occurs, this function always sets db->mallocFailed. @@ -121180,11 +99420,10 @@ analysisInfo sInfo; HashElem *i; char *zSql; int rc = SQLITE_OK; Schema *pSchema = db->aDb[iDb].pSchema; - const Table *pStat1; assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); /* Clear any prior statistics */ @@ -121194,23 +99433,21 @@ pTab->tabFlags &= ~TF_HasStat1; } for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); pIdx->hasStat1 = 0; -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3DeleteIndexSamples(db, pIdx); pIdx->aSample = 0; #endif } /* Load new statistics out of the sqlite_stat1 table */ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zDbSName; - if( (pStat1 = sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)) - && IsOrdinaryTable(pStat1) - ){ - zSql = sqlite3MPrintf(db, + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){ + zSql = sqlite3MPrintf(db, "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); if( zSql==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); @@ -121224,15 +99461,15 @@ Index *pIdx = sqliteHashData(i); if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx); } /* Load the statistics from the sqlite_stat4 table. */ -#ifdef SQLITE_ENABLE_STAT4 - if( rc==SQLITE_OK ){ - DisableLookaside; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ + db->lookaside.bDisable++; rc = loadStat4(db, sInfo.zDatabase); - EnableLookaside; + db->lookaside.bDisable--; } for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3_free(pIdx->aiRowEst); pIdx->aiRowEst = 0; @@ -121295,21 +99532,10 @@ } } return rc; } -/* -** Return true if zName points to a name that may be used to refer to -** database iDb attached to handle db. -*/ -SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){ - return ( - sqlite3StrICmp(db->aDb[iDb].zDbSName, zName)==0 - || (iDb==0 && sqlite3StrICmp("main", zName)==0) - ); -} - /* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: ** ** ATTACH DATABASE x AS y KEY z @@ -121316,14 +99542,10 @@ ** ** SELECT sqlite_attach(x, y, z) ** ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the ** third argument. -** -** If the db->init.reopenMemdb flags is set, then instead of attaching a -** new database, close the database on db->init.iDb and reopen it as an -** empty MemDB. */ static void attachFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv @@ -121335,123 +99557,89 @@ const char *zFile; char *zPath = 0; char *zErr = 0; unsigned int flags; Db *aNew; /* New array of Db pointers */ - Db *pNew = 0; /* Db object for the newly attached database */ + Db *pNew; /* Db object for the newly attached database */ char *zErrDyn = 0; sqlite3_vfs *pVfs; UNUSED_PARAMETER(NotUsed); + zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; -#ifndef SQLITE_OMIT_DESERIALIZE -# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) -#else -# define REOPEN_AS_MEMDB(db) (0) -#endif - - if( REOPEN_AS_MEMDB(db) ){ - /* This is not a real ATTACH. Instead, this routine is being called - ** from sqlite3_deserialize() to close database db->init.iDb and - ** reopen it as a MemDB */ - Btree *pNewBt = 0; - pVfs = sqlite3_vfs_find("memdb"); - if( pVfs==0 ) return; - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); - if( rc==SQLITE_OK ){ - Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); - if( pNewSchema ){ - /* Both the Btree and the new Schema were allocated successfully. - ** Close the old db and update the aDb[] slot with the new memdb - ** values. */ - pNew = &db->aDb[db->init.iDb]; - if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt); - pNew->pBt = pNewBt; - pNew->pSchema = pNewSchema; - }else{ - sqlite3BtreeClose(pNewBt); - rc = SQLITE_NOMEM; - } - } - if( rc ) goto attach_error; - }else{ - /* This is a real ATTACH - ** - ** Check for the following errors: - ** - ** * Too many attached databases, - ** * Transaction currently open - ** * Specified database name already being used. - */ - if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", - db->aLimit[SQLITE_LIMIT_ATTACHED] - ); - goto attach_error; - } - for(i=0; inDb; i++){ - assert( zName ); - if( sqlite3DbIsNamed(db, i, zName) ){ - zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); - goto attach_error; - } - } - - /* Allocate the new entry in the db->aDb[] array and initialize the schema - ** hash tables. - */ - if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); - if( aNew==0 ) return; - } - db->aDb = 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 - ** or may not be initialized. - */ - flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - if( (db->flags & SQLITE_AttachWrite)==0 ){ - flags &= ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE); - flags |= SQLITE_OPEN_READONLY; - }else if( (db->flags & SQLITE_AttachCreate)==0 ){ - flags &= ~SQLITE_OPEN_CREATE; - } - assert( pVfs ); - flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); - db->nDb++; - pNew->zDbSName = sqlite3DbStrDup(db, zName); - } - db->noSharedCache = 0; + /* Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ + zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", + db->aLimit[SQLITE_LIMIT_ATTACHED] + ); + 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 ); + if( sqlite3StrICmp(z, zName)==0 ){ + zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); + goto attach_error; + } + } + + /* Allocate the new entry in the db->aDb[] array and initialize the schema + ** hash tables. + */ + if( db->aDb==db->aDbStatic ){ + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); + if( aNew==0 ) return; + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ) return; + } + db->aDb = 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 + ** or may not be initialized. + */ + flags = db->openFlags; + rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + assert( pVfs ); + flags |= SQLITE_OPEN_MAIN_DB; + 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; pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt); if( !pNew->pSchema ){ rc = SQLITE_NOMEM_BKPT; }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){ - zErrDyn = sqlite3MPrintf(db, + zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } sqlite3BtreeEnter(pNew->pBt); pPager = sqlite3BtreePager(pNew->pBt); @@ -121463,52 +99651,87 @@ PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); #endif sqlite3BtreeLeave(pNew->pBt); } pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; + pNew->zDbSName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } - sqlite3_free_filename( zPath ); + + +#ifdef SQLITE_HAS_CODEC + if( rc==SQLITE_OK ){ + extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); + int nKey; + char *zKey; + int t = sqlite3_value_type(argv[2]); + switch( t ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); + rc = SQLITE_ERROR; + break; + + case SQLITE_TEXT: + case SQLITE_BLOB: + nKey = sqlite3_value_bytes(argv[2]); + zKey = (char *)sqlite3_value_blob(argv[2]); + rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; + + case SQLITE_NULL: + /* No key specified. Use the key from the main database */ + sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ + rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + } + break; + } + } +#endif /* If the file was opened successfully, read the schema for the new database. - ** If this fails, or if opening the file failed, then close the file and - ** remove the entry from the db->aDb[] array. i.e. put everything back the - ** way we found it. + ** If this fails, or if opening the file failed, then close the file and + ** remove the entry from the db->aDb[] array. i.e. put everything back the way + ** we found it. */ if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); - db->init.iDb = 0; - db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); - if( !REOPEN_AS_MEMDB(db) ){ - rc = sqlite3Init(db, &zErrDyn); - } + rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); - assert( zErrDyn==0 || rc!=SQLITE_OK ); } +#ifdef SQLITE_USER_AUTHENTICATION + if( rc==SQLITE_OK ){ + u8 newAuth = 0; + rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth); + if( newAuthauth.authLevel ){ + rc = SQLITE_AUTH_USER; + } + } +#endif if( rc ){ - if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){ - int iDb = db->nDb - 1; - assert( iDb>=2 ); - if( db->aDb[iDb].pBt ){ - sqlite3BtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - db->aDb[iDb].pSchema = 0; - } - sqlite3ResetAllSchemasOfConnection(db); - db->nDb = iDb; - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - sqlite3DbFree(db, zErrDyn); - zErrDyn = sqlite3MPrintf(db, "out of memory"); - }else if( zErrDyn==0 ){ - zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); - } + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; + } + sqlite3ResetAllSchemasOfConnection(db); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + sqlite3DbFree(db, zErrDyn); + zErrDyn = sqlite3MPrintf(db, "out of memory"); + }else if( zErrDyn==0 ){ + zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); } goto attach_error; } - + return; attach_error: /* Return an error if we get here */ if( zErrDyn ){ @@ -121533,20 +99756,19 @@ ){ const char *zName = (const char *)sqlite3_value_text(argv[0]); sqlite3 *db = sqlite3_context_db_handle(context); int i; Db *pDb = 0; - HashElem *pEntry; char zErr[128]; UNUSED_PARAMETER(NotUsed); if( zName==0 ) zName = ""; for(i=0; inDb; i++){ pDb = &db->aDb[i]; if( pDb->pBt==0 ) continue; - if( sqlite3DbIsNamed(db, i, zName) ) break; + if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break; } if( i>=db->nDb ){ sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); goto detach_error; @@ -121553,27 +99775,18 @@ } if( i<2 ){ sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); goto detach_error; } - if( sqlite3BtreeTxnState(pDb->pBt)!=SQLITE_TXN_NONE - || sqlite3BtreeIsInBackup(pDb->pBt) - ){ - sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot DETACH database within transaction"); goto detach_error; } - - /* If any TEMP triggers reference the schema being detached, move those - ** triggers to reference the TEMP schema itself. */ - assert( db->aDb[1].pSchema ); - pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash); - while( pEntry ){ - Trigger *pTrig = (Trigger*)sqliteHashData(pEntry); - if( pTrig->pTabSchema==pDb->pSchema ){ - pTrig->pTabSchema = pTrig->pSchema; - } - pEntry = sqliteHashNext(pEntry); + if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){ + sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + goto detach_error; } sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; @@ -121601,29 +99814,26 @@ NameContext sName; Vdbe *v; sqlite3* db = pParse->db; int regArgs; - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end; - if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; - if( - SQLITE_OK!=resolveAttachExpr(&sName, pFilename) || - SQLITE_OK!=resolveAttachExpr(&sName, pDbname) || - SQLITE_OK!=resolveAttachExpr(&sName, pKey) + if( + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) ){ goto attach_end; } #ifndef SQLITE_OMIT_AUTHORIZATION - if( ALWAYS(pAuthArg) ){ + if( pAuthArg ){ char *zAuthArg; if( pAuthArg->op==TK_STRING ){ - assert( !ExprHasProperty(pAuthArg, EP_IntValue) ); zAuthArg = pAuthArg->u.zToken; }else{ zAuthArg = 0; } rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); @@ -121640,19 +99850,22 @@ sqlite3ExprCode(pParse, pDbname, regArgs+1); sqlite3ExprCode(pParse, pKey, regArgs+2); assert( v || db->mallocFailed ); if( v ){ - sqlite3VdbeAddFunctionCall(pParse, 0, regArgs+3-pFunc->nArg, regArgs+3, - pFunc->nArg, pFunc, 0); + sqlite3VdbeAddOp4(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3, + (char *)pFunc, P4_FUNCDEF); + assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg ); + sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg)); + /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this ** statement only). For DETACH, set it to false (expire all existing ** statements). */ sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); } - + attach_end: sqlite3ExprDelete(db, pFilename); sqlite3ExprDelete(db, pDbname); sqlite3ExprDelete(db, pKey); } @@ -121668,11 +99881,10 @@ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ detachFunc, /* xSFunc */ 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ "sqlite_detach", /* zName */ {0} }; codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); } @@ -121688,82 +99900,17 @@ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ attachFunc, /* xSFunc */ 0, /* xFinalize */ - 0, 0, /* xValue, xInverse */ "sqlite_attach", /* zName */ {0} }; codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); } #endif /* SQLITE_OMIT_ATTACH */ -/* -** Expression callback used by sqlite3FixAAAA() routines. -*/ -static int fixExprCb(Walker *p, Expr *pExpr){ - DbFixer *pFix = p->u.pFix; - if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL); - if( pExpr->op==TK_VARIABLE ){ - if( pFix->pParse->db->init.busy ){ - pExpr->op = TK_NULL; - }else{ - sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); - return WRC_Abort; - } - } - return WRC_Continue; -} - -/* -** Select callback used by sqlite3FixAAAA() routines. -*/ -static int fixSelectCb(Walker *p, Select *pSelect){ - DbFixer *pFix = p->u.pFix; - int i; - SrcItem *pItem; - sqlite3 *db = pFix->pParse->db; - int iDb = sqlite3FindDbName(db, pFix->zDb); - SrcList *pList = pSelect->pSrc; - - if( NEVER(pList==0) ) return WRC_Continue; - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pFix->bTemp==0 && pItem->fg.isSubquery==0 ){ - if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){ - if( iDb!=sqlite3FindDbName(db, pItem->u4.zDatabase) ){ - sqlite3ErrorMsg(pFix->pParse, - "%s %T cannot reference objects in database %s", - pFix->zType, pFix->pName, pItem->u4.zDatabase); - return WRC_Abort; - } - sqlite3DbFree(db, pItem->u4.zDatabase); - pItem->fg.notCte = 1; - pItem->fg.hadSchema = 1; - } - pItem->u4.pSchema = pFix->pSchema; - pItem->fg.fromDDL = 1; - pItem->fg.fixedSchema = 1; - } -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) - if( pList->a[i].fg.isUsing==0 - && sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn) - ){ - return WRC_Abort; - } -#endif - } - if( pSelect->pWith ){ - for(i=0; ipWith->nCte; i++){ - if( sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){ - return WRC_Abort; - } - } - } - return WRC_Continue; -} - /* ** Initialize a DbFixer structure. This routine must be called prior ** to passing the structure to one of the sqliteFixAAAA() routines below. */ SQLITE_PRIVATE void sqlite3FixInit( @@ -121771,25 +99918,20 @@ Parse *pParse, /* Error messages will be written here */ int iDb, /* This is the database that must be used */ const char *zType, /* "view", "trigger", or "index" */ const Token *pName /* Name of the view, trigger, or index */ ){ - sqlite3 *db = pParse->db; + sqlite3 *db; + + db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zDbSName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; - pFix->bTemp = (iDb==1); - pFix->w.pParse = pParse; - pFix->w.xExprCallback = fixExprCb; - pFix->w.xSelectCallback = fixSelectCb; - pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback; - pFix->w.walkerDepth = 0; - pFix->w.eCode = 0; - pFix->w.u.pFix = pFix; + pFix->bVarOnly = (iDb==1); } /* ** The following set of routines walk through the parse tree and assign ** a specific database to all table references where the database name @@ -121806,64 +99948,128 @@ */ SQLITE_PRIVATE int sqlite3FixSrcList( DbFixer *pFix, /* Context of the fixation */ SrcList *pList /* The Source list to check and modify */ ){ - int res = 0; - if( pList ){ - Select s; - memset(&s, 0, sizeof(s)); - s.pSrc = pList; - res = sqlite3WalkSelect(&pFix->w, &s); - } - return res; + int i; + const char *zDb; + struct SrcList_item *pItem; + + if( NEVER(pList==0) ) return 0; + zDb = pFix->zDb; + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pFix->bVarOnly==0 ){ + if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ + sqlite3ErrorMsg(pFix->pParse, + "%s %T cannot reference objects in database %s", + pFix->zType, pFix->pName, pItem->zDatabase); + return 1; + } + sqlite3DbFree(pFix->pParse->db, pItem->zDatabase); + pItem->zDatabase = 0; + pItem->pSchema = pFix->pSchema; + } +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) + if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; + if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; +#endif + } + return 0; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) SQLITE_PRIVATE int sqlite3FixSelect( DbFixer *pFix, /* Context of the fixation */ Select *pSelect /* The SELECT statement to be fixed to one database */ ){ - return sqlite3WalkSelect(&pFix->w, pSelect); + while( pSelect ){ + if( sqlite3FixExprList(pFix, pSelect->pEList) ){ + return 1; + } + if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pOffset) ){ + return 1; + } + pSelect = pSelect->pPrior; + } + return 0; } SQLITE_PRIVATE int sqlite3FixExpr( DbFixer *pFix, /* Context of the fixation */ Expr *pExpr /* The expression to be fixed to one database */ ){ - return sqlite3WalkExpr(&pFix->w, pExpr); + while( pExpr ){ + if( pExpr->op==TK_VARIABLE ){ + if( pFix->pParse->db->init.busy ){ + pExpr->op = TK_NULL; + }else{ + sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); + return 1; + } + } + if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; + }else{ + if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; + } + if( sqlite3FixExpr(pFix, pExpr->pRight) ){ + return 1; + } + pExpr = pExpr->pLeft; + } + return 0; +} +SQLITE_PRIVATE int sqlite3FixExprList( + DbFixer *pFix, /* Context of the fixation */ + ExprList *pList /* The expression to be fixed to one database */ +){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return 0; + for(i=0, pItem=pList->a; inExpr; i++, pItem++){ + if( sqlite3FixExpr(pFix, pItem->pExpr) ){ + return 1; + } + } + return 0; } #endif #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE int sqlite3FixTriggerStep( DbFixer *pFix, /* Context of the fixation */ TriggerStep *pStep /* The trigger step be fixed to one database */ ){ while( pStep ){ - if( sqlite3WalkSelect(&pFix->w, pStep->pSelect) - || sqlite3WalkExpr(&pFix->w, pStep->pWhere) - || sqlite3WalkExprList(&pFix->w, pStep->pExprList) - || sqlite3FixSrcList(pFix, pStep->pFrom) - ){ - return 1; - } -#ifndef SQLITE_OMIT_UPSERT - { - Upsert *pUp; - for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){ - if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget) - || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere) - || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet) - || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere) - ){ - return 1; - } - } - } -#endif + if( sqlite3FixSelect(pFix, pStep->pSelect) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pStep->pWhere) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pStep->pExprList) ){ + return 1; + } pStep = pStep->pNext; } - return 0; } #endif /************** End of attach.c **********************************************/ @@ -121946,11 +100152,11 @@ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); db->xAuth = (sqlite3_xauth)xAuth; db->pAuthArg = pArg; - if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1); + sqlite3ExpirePreparedStatements(db); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } /* @@ -121980,77 +100186,83 @@ sqlite3 *db = pParse->db; /* Database handle */ char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */ int rc; /* Auth callback return code */ if( db->init.busy ) return SQLITE_OK; - rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext); + rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext +#ifdef SQLITE_USER_AUTHENTICATION + ,db->auth.zAuthUser +#endif + ); if( rc==SQLITE_DENY ){ - 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); + 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); + } pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){ sqliteAuthBadReturnCode(pParse); } return rc; } /* ** The pExpr should be a TK_COLUMN expression. The table referred to -** is in pTabList or else it is the NEW or OLD table of a trigger. +** is in pTabList or else it is the NEW or OLD table of a trigger. ** Check to see if it is OK to read this particular column. ** -** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN +** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN ** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, ** then generate an error. */ SQLITE_PRIVATE void sqlite3AuthRead( Parse *pParse, /* The parser context */ Expr *pExpr, /* The expression to check authorization on */ Schema *pSchema, /* The schema of the expression */ SrcList *pTabList /* All table that pExpr might refer to */ ){ + sqlite3 *db = pParse->db; Table *pTab = 0; /* The table being read */ const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ int iDb; /* The index of the database the expression refers to */ int iCol; /* Index of column in table */ - assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); - assert( !IN_RENAME_OBJECT ); - assert( pParse->db->xAuth!=0 ); + if( db->xAuth==0 ) return; iDb = sqlite3SchemaToIndex(pParse->db, pSchema); if( iDb<0 ){ /* An attempt to read a column out of a subquery or other ** temporary table. */ return; } + assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); if( pExpr->op==TK_TRIGGER ){ pTab = pParse->pTriggerTab; }else{ assert( pTabList ); - for(iSrc=0; iSrcnSrc; iSrc++){ + for(iSrc=0; ALWAYS(iSrcnSrc); iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ){ - pTab = pTabList->a[iSrc].pSTab; + pTab = pTabList->a[iSrc].pTab; break; } } } iCol = pExpr->iColumn; - if( pTab==0 ) return; + if( NEVER(pTab==0) ) return; if( iCol>=0 ){ assert( iColnCol ); - zCol = pTab->aCol[iCol].zCnName; + zCol = pTab->aCol[iCol].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKeynCol ); - zCol = pTab->aCol[pTab->iPKey].zCnName; + zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } - assert( iDb>=0 && iDbdb->nDb ); + assert( iDb>=0 && iDbnDb ); if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){ pExpr->op = TK_NULL; } } @@ -122068,15 +100280,18 @@ const char *zArg3 ){ sqlite3 *db = pParse->db; int rc; - /* Don't do any authorization checks if the database is initializing + /* Don't do any authorization checks if the database is initialising ** or if the parser is being invoked from within sqlite3_declare_vtab. */ - assert( !IN_RENAME_OBJECT || db->xAuth==0 ); - if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){ + if( db->init.busy || IN_DECLARE_VTAB ){ + return SQLITE_OK; + } + + 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 @@ -122087,11 +100302,15 @@ testcase( zArg1==0 ); testcase( zArg2==0 ); testcase( zArg3==0 ); testcase( pParse->zAuthContext==0 ); - rc = db->xAuth(db->pAuthArg,code,zArg1,zArg2,zArg3,pParse->zAuthContext); + rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext +#ifdef SQLITE_USER_AUTHENTICATION + ,db->auth.zAuthUser +#endif + ); if( rc==SQLITE_DENY ){ sqlite3ErrorMsg(pParse, "not authorized"); pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ rc = SQLITE_DENY; @@ -122105,11 +100324,11 @@ ** zArg3 argument to authorization callbacks will be zContext until ** popped. Or if pParse==0, this routine is a no-op. */ SQLITE_PRIVATE void sqlite3AuthContextPush( Parse *pParse, - AuthContext *pContext, + AuthContext *pContext, const char *zContext ){ assert( pParse ); pContext->pParse = pParse; pContext->zAuthContext = pParse->zAuthContext; @@ -122162,39 +100381,40 @@ ** The TableLock structure is only used by the sqlite3TableLock() and ** codeTableLocks() functions. */ struct TableLock { int iDb; /* The database containing the table to be locked */ - Pgno iTab; /* The root page of 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 */ }; /* -** Record the fact that we want to lock a table at run-time. +** Record the fact that we want to lock a table at run-time. ** ** The table to be locked has root page iTab and is found in database iDb. ** A read or a write lock can be taken depending on isWritelock. ** ** This routine just records the fact that the lock is desired. The ** code to make the lock occur is generated by a later call to ** codeTableLocks() which occurs during sqlite3FinishCoding(). */ -static SQLITE_NOINLINE void lockTable( +SQLITE_PRIVATE void sqlite3TableLock( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database containing the table to lock */ - Pgno iTab, /* Root page number of the table to be locked */ + int iTab, /* Root page number of the table to be locked */ u8 isWriteLock, /* True for a write lock */ const char *zName /* Name of the table to be locked */ ){ - Parse *pToplevel; + Parse *pToplevel = sqlite3ParseToplevel(pParse); int i; int nBytes; TableLock *p; assert( iDb>=0 ); - pToplevel = sqlite3ParseToplevel(pParse); + 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 ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; @@ -122213,30 +100433,21 @@ }else{ pToplevel->nTableLock = 0; sqlite3OomFault(pToplevel->db); } } -SQLITE_PRIVATE void sqlite3TableLock( - Parse *pParse, /* Parsing context */ - int iDb, /* Index of the database containing the table to lock */ - Pgno iTab, /* Root page number of the table to be locked */ - u8 isWriteLock, /* True for a write lock */ - const char *zName /* Name of the table to be locked */ -){ - if( iDb==1 ) return; - if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return; - lockTable(pParse, iDb, iTab, isWriteLock, zName); -} /* ** Code an OP_TableLock instruction for each table locked by the ** statement (configured by calls to sqlite3TableLock()). */ static void codeTableLocks(Parse *pParse){ int i; - Vdbe *pVdbe = pParse->pVdbe; - assert( pVdbe!=0 ); + Vdbe *pVdbe; + + pVdbe = sqlite3GetVdbe(pParse); + assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */ for(i=0; inTableLock; i++){ TableLock *p = &pParse->aTableLock[i]; int p1 = p->iDb; sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, @@ -122271,135 +100482,107 @@ ** no VDBE code was generated. */ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; - int iDb, i; assert( pParse->pToplevel==0 ); db = pParse->db; - assert( db->pParse==pParse ); if( pParse->nested ) return; - if( pParse->nErr ){ - if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM; + if( db->mallocFailed || pParse->nErr ){ + if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR; return; } - assert( db->mallocFailed==0 ); /* Begin by generating some termination code at the end of the ** vdbe program */ - v = pParse->pVdbe; - if( v==0 ){ - if( db->init.busy ){ - pParse->rc = SQLITE_DONE; - return; - } - v = sqlite3GetVdbe(pParse); - if( v==0 ) pParse->rc = SQLITE_ERROR; - } - assert( !pParse->isMultiWrite + v = sqlite3GetVdbe(pParse); + assert( !pParse->isMultiWrite || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); if( v ){ - if( pParse->bReturning ){ - Returning *pReturning = pParse->u1.pReturning; - int addrRewind; - int reg; - - if( pReturning->nRetCol ){ - sqlite3VdbeAddOp0(v, OP_FkCheck); - addrRewind = - sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); - VdbeCoverage(v); - reg = pReturning->iRetReg; - for(i=0; inRetCol; i++){ - sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i); - } - sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i); - sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrRewind); - } - } sqlite3VdbeAddOp0(v, OP_Halt); + +#if SQLITE_USER_AUTHENTICATION + if( pParse->nTableLock>0 && db->init.busy==0 ){ + sqlite3UserAuthInit(db); + if( db->auth.authLevelrc = SQLITE_AUTH_USER; + return; + } + } +#endif /* The cookie mask contains one bit for each database file open. ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ - assert( pParse->nErr>0 || sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); - sqlite3VdbeJumpHere(v, 0); - assert( db->nDb>0 ); - iDb = 0; - do{ - Schema *pSchema; - if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; - sqlite3VdbeUsesBtree(v, iDb); - pSchema = db->aDb[iDb].pSchema; - sqlite3VdbeAddOp4Int(v, - OP_Transaction, /* Opcode */ - iDb, /* P1 */ - DbMaskTest(pParse->writeMask,iDb), /* P2 */ - pSchema->schema_cookie, /* P3 */ - pSchema->iGeneration /* P4 */ - ); - if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); - VdbeComment((v, - "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); - }while( ++iDbnDb ); + if( db->mallocFailed==0 + && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr) + ){ + int iDb, i; + assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); + sqlite3VdbeJumpHere(v, 0); + for(iDb=0; iDbnDb; iDb++){ + Schema *pSchema; + if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; + sqlite3VdbeUsesBtree(v, iDb); + pSchema = db->aDb[iDb].pSchema; + sqlite3VdbeAddOp4Int(v, + OP_Transaction, /* Opcode */ + iDb, /* P1 */ + DbMaskTest(pParse->writeMask,iDb), /* P2 */ + pSchema->schema_cookie, /* P3 */ + pSchema->iGeneration /* P4 */ + ); + if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); + VdbeComment((v, + "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); + } #ifndef SQLITE_OMIT_VIRTUALTABLE - for(i=0; inVtabLock; i++){ - char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); - sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); - } - pParse->nVtabLock = 0; -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE - /* Once all the cookies have been verified and transactions opened, - ** obtain the required table-locks. This is a no-op unless the - ** shared-cache feature is enabled. - */ - if( pParse->nTableLock ) codeTableLocks(pParse); -#endif - - /* Initialize any AUTOINCREMENT data structures required. - */ - if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse); - - /* Code constant expressions that were factored out of inner loops. - */ - if( pParse->pConstExpr ){ - ExprList *pEL = pParse->pConstExpr; - pParse->okConstFactor = 0; - for(i=0; inExpr; i++){ - assert( pEL->a[i].u.iConstExprReg>0 ); - sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); - } - } - - if( pParse->bReturning ){ - Returning *pRet = pParse->u1.pReturning; - if( pRet->nRetCol ){ - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol); - } - } - - /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeGoto(v, 1); - } + for(i=0; inVtabLock; i++){ + char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); + sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); + } + pParse->nVtabLock = 0; +#endif + + /* Once all the cookies have been verified and transactions opened, + ** obtain the required table-locks. This is a no-op unless the + ** shared-cache feature is enabled. + */ + codeTableLocks(pParse); + + /* Initialize any AUTOINCREMENT data structures required. + */ + sqlite3AutoincrementBegin(pParse); + + /* Code constant expressions that where factored out of inner loops */ + if( pParse->pConstExpr ){ + ExprList *pEL = pParse->pConstExpr; + pParse->okConstFactor = 0; + for(i=0; inExpr; i++){ + sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); + } + } + + /* Finally, jump back to the beginning of the executable code. */ + sqlite3VdbeGoto(v, 1); + } + } + /* Get the VDBE program ready for execution */ - assert( v!=0 || pParse->nErr ); - assert( db->mallocFailed==0 || pParse->nErr ); - if( pParse->nErr==0 ){ + if( v && pParse->nErr==0 && !db->mallocFailed ){ + assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ - assert( pParse->pAinc==0 || pParse->nTab>0 ); + if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; sqlite3VdbeMakeReady(v, pParse); pParse->rc = SQLITE_DONE; }else{ pParse->rc = SQLITE_ERROR; } @@ -122406,51 +100589,53 @@ } /* ** Run the parser and code generator recursively in order to generate ** code for the SQL statement given onto the end of the pParse context -** currently under construction. Notes: -** -** * The final OP_Halt is not appended and other initialization -** and finalization steps are omitted because those are handling by the -** outermost parser. -** -** * Built-in SQL functions always take precedence over application-defined -** SQL functions. In other words, it is not possible to override a -** built-in function. +** currently under construction. When the parser is run recursively +** this way, the final OP_Halt is not appended and other initialization +** and finalization steps are omitted because those are handling by the +** outermost parser. +** +** Not everything is nestable. This facility is designed to permit +** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use +** care if you decide to try to use this routine for some other purposes. */ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; + char *zErrMsg = 0; sqlite3 *db = pParse->db; - u32 savedDbFlags = db->mDbFlags; char saveBuf[PARSE_TAIL_SZ]; if( pParse->nErr ) return; - if( pParse->eParseMode ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ va_start(ap, zFormat); zSql = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( zSql==0 ){ - /* This can result either from an OOM or because the formatted string - ** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set - ** an error */ - if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG; - pParse->nErr++; - return; + return; /* A malloc must have failed */ } pParse->nested++; memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); - db->mDbFlags |= DBFLAG_PreferBuiltin; - sqlite3RunParser(pParse, zSql); - db->mDbFlags = savedDbFlags; + sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3DbFree(db, zErrMsg); sqlite3DbFree(db, zSql); memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; } + +#if SQLITE_USER_AUTHENTICATION +/* +** Return TRUE if zTable is the name of the system table that stores the +** list of users and their access credentials. +*/ +SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){ + return sqlite3_stricmp(zTable, "sqlite_user")==0; +} +#endif /* ** Locate the in-memory structure that describes a particular database ** table given the name of that table and (optionally) the name of the ** database containing the table. Return NULL if not found. @@ -122466,63 +100651,33 @@ Table *p = 0; int i; /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - if( zDatabase ){ - for(i=0; inDb; i++){ - if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break; - } - if( i>=db->nDb ){ - /* No match against the official names. But always match "main" - ** to schema 0 as a legacy fallback. */ - if( sqlite3StrICmp(zDatabase,"main")==0 ){ - i = 0; - }else{ - return 0; - } - } - p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName); - if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){ - if( i==1 ){ - if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 - || sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 - || sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 - ){ - p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, - LEGACY_TEMP_SCHEMA_TABLE); - } - }else{ - if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){ - p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, - LEGACY_SCHEMA_TABLE); - } - } - } - }else{ - /* Match against TEMP first */ - p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName); - if( p ) return p; - /* The main database is second */ - p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName); - if( p ) return p; - /* Attached databases are in order of attachment */ - for(i=2; inDb; i++){ - assert( sqlite3SchemaMutexHeld(db, i, 0) ); - p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName); - if( p ) break; - } - if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){ - if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){ - p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE); - }else if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){ - p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, - LEGACY_TEMP_SCHEMA_TABLE); - } - } - } - return p; +#if SQLITE_USER_AUTHENTICATION + /* Only the admin user is allowed to know that the sqlite_user table + ** exists */ + if( db->auth.authLevelnDb; 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 0; } /* ** Locate the in-memory structure that describes a particular database ** table given the name of that table and (optionally) the name of the @@ -122538,52 +100693,42 @@ u32 flags, /* LOCATE_VIEW or LOCATE_NOERR */ const char *zName, /* Name of the table we are looking for */ const char *zDbase /* Name of the database. Might be NULL */ ){ Table *p; - sqlite3 *db = pParse->db; /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ - if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 - && SQLITE_OK!=sqlite3ReadSchema(pParse) - ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return 0; } - p = sqlite3FindTable(db, zName, zDbase); + p = sqlite3FindTable(pParse->db, zName, zDbase); if( p==0 ){ + const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; #ifndef SQLITE_OMIT_VIRTUALTABLE - /* If zName is the not the name of a table in the schema created using - ** CREATE, then check to see if it is the name of an virtual table that - ** can be an eponymous virtual table. */ - if( (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)==0 && db->init.busy==0 ){ - Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); + if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ + /* If zName is the not the name of a table in the schema created using + ** 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(db, zName); + pMod = sqlite3PragmaVtabRegister(pParse->db, zName); } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ - testcase( pMod->pEpoTab==0 ); return pMod->pEpoTab; } } #endif - if( flags & LOCATE_NOERR ) return 0; - pParse->checkSchema = 1; - }else if( IsVirtual(p) && (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)!=0 ){ - p = 0; - } - - if( p==0 ){ - const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; - if( zDbase ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); - }else{ - sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); - } - }else{ - assert( HasRowid(p) || p->iPKey<0 ); + if( (flags & LOCATE_NOERR)==0 ){ + if( zDbase ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); + } + pParse->checkSchema = 1; + } } return p; } @@ -122595,43 +100740,27 @@ ** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be ** non-NULL if it is part of a view or trigger program definition. See ** sqlite3FixSrcList() for details. */ SQLITE_PRIVATE Table *sqlite3LocateTableItem( - Parse *pParse, + Parse *pParse, u32 flags, - SrcItem *p + struct SrcList_item *p ){ const char *zDb; - if( p->fg.fixedSchema ){ - int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema); + assert( p->pSchema==0 || p->zDatabase==0 ); + if( p->pSchema ){ + int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); zDb = pParse->db->aDb[iDb].zDbSName; }else{ - assert( !p->fg.isSubquery ); - zDb = p->u4.zDatabase; + zDb = p->zDatabase; } return sqlite3LocateTable(pParse, flags, p->zName, zDb); } /* -** Return the preferred table name for system tables. Translate legacy -** names into the new preferred names, as appropriate. -*/ -SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char *zName){ - if( sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){ - if( sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 ){ - return PREFERRED_SCHEMA_TABLE; - } - if( sqlite3StrICmp(zName+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){ - return PREFERRED_TEMP_SCHEMA_TABLE; - } - } - return zName; -} - -/* -** Locate the in-memory structure that describes +** Locate the in-memory structure that describes ** a particular index given the name of that index ** and the name of the database that contains the index. ** Return NULL if not found. ** ** If zDatabase is 0, all databases are searched for the @@ -122647,11 +100776,11 @@ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; assert( pSchema ); - if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue; + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&pSchema->idxHash, zName); if( p ) break; } return p; @@ -122658,19 +100787,19 @@ } /* ** Reclaim the memory used by an index */ -SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3 *db, Index *p){ +static void freeIndex(sqlite3 *db, Index *p){ #ifndef SQLITE_OMIT_ANALYZE sqlite3DeleteIndexSamples(db, p); #endif sqlite3ExprDelete(db, p->pPartIdxWhere); sqlite3ExprListDelete(db, p->aColExpr); sqlite3DbFree(db, p->zColAff); if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl); -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3_free(p->aiRowEst); #endif sqlite3DbFree(db, p); } @@ -122698,13 +100827,13 @@ while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; } if( ALWAYS(p && p->pNext==pIndex) ){ p->pNext = pIndex->pNext; } } - sqlite3FreeIndex(db, pIndex); + freeIndex(db, pIndex); } - db->mDbFlags |= DBFLAG_SchemaChange; + db->flags |= SQLITE_InternChanges; } /* ** Look through the list of open database files in db->aDb[] and if ** any have been closed, remove them from the list. Reallocate the @@ -122735,31 +100864,32 @@ } } /* ** Reset the schema for the database at index iDb. Also reset the -** TEMP schema. The reset is deferred if db->nSchemaLock is not zero. -** Deferred resets may be run by calling with iDb<0. +** TEMP schema. */ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ - int i; + Db *pDb; assert( iDbnDb ); - if( iDb>=0 ){ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - DbSetProperty(db, iDb, DB_ResetWanted); - DbSetProperty(db, 1, DB_ResetWanted); - db->mDbFlags &= ~DBFLAG_SchemaKnownOk; - } - - if( db->nSchemaLock==0 ){ - for(i=0; inDb; i++){ - if( DbHasProperty(db, i, DB_ResetWanted) ){ - sqlite3SchemaClear(db->aDb[i].pSchema); - } - } - } + /* 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 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); + } + return; } /* ** Erase all schema information from all attached databases (including ** "main" and "temp") for a single database connection. @@ -122768,108 +100898,24 @@ int i; sqlite3BtreeEnterAll(db); for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ - if( db->nSchemaLock==0 ){ - sqlite3SchemaClear(pDb->pSchema); - }else{ - DbSetProperty(db, i, DB_ResetWanted); - } + sqlite3SchemaClear(pDb->pSchema); } } - db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); + db->flags &= ~SQLITE_InternChanges; sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); - if( db->nSchemaLock==0 ){ - sqlite3CollapseDatabaseArray(db); - } + sqlite3CollapseDatabaseArray(db); } /* ** This routine is called when a commit occurs. */ SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ - db->mDbFlags &= ~DBFLAG_SchemaChange; -} - -/* -** Set the expression associated with a column. This is usually -** the DEFAULT value, but might also be the expression that computes -** the value for a generated column. -*/ -SQLITE_PRIVATE void sqlite3ColumnSetExpr( - Parse *pParse, /* Parsing context */ - Table *pTab, /* The table containing the column */ - Column *pCol, /* The column to receive the new DEFAULT expression */ - Expr *pExpr /* The new default expression */ -){ - ExprList *pList; - assert( IsOrdinaryTable(pTab) ); - pList = pTab->u.tab.pDfltList; - if( pCol->iDflt==0 - || NEVER(pList==0) - || NEVER(pList->nExpriDflt) - ){ - pCol->iDflt = pList==0 ? 1 : pList->nExpr+1; - pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr); - }else{ - sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr); - pList->a[pCol->iDflt-1].pExpr = pExpr; - } -} - -/* -** Return the expression associated with a column. The expression might be -** the DEFAULT clause or the AS clause of a generated column. -** Return NULL if the column has no associated expression. -*/ -SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){ - if( pCol->iDflt==0 ) return 0; - if( !IsOrdinaryTable(pTab) ) return 0; - if( NEVER(pTab->u.tab.pDfltList==0) ) return 0; - if( NEVER(pTab->u.tab.pDfltList->nExpriDflt) ) return 0; - return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; -} - -/* -** Set the collating sequence name for a column. -*/ -SQLITE_PRIVATE void sqlite3ColumnSetColl( - sqlite3 *db, - Column *pCol, - const char *zColl -){ - i64 nColl; - i64 n; - char *zNew; - assert( zColl!=0 ); - n = sqlite3Strlen30(pCol->zCnName) + 1; - if( pCol->colFlags & COLFLAG_HASTYPE ){ - n += sqlite3Strlen30(pCol->zCnName+n) + 1; - } - nColl = sqlite3Strlen30(zColl) + 1; - zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n); - if( zNew ){ - pCol->zCnName = zNew; - memcpy(pCol->zCnName + n, zColl, nColl); - pCol->colFlags |= COLFLAG_HASCOLL; - } -} - -/* -** Return the collating sequence name for a column -*/ -SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){ - const char *z; - if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0; - z = pCol->zCnName; - while( *z ){ z++; } - if( pCol->colFlags & COLFLAG_HASTYPE ){ - do{ z++; }while( *z ); - } - return z+1; + db->flags &= ~SQLITE_InternChanges; } /* ** Delete memory allocated for the column names of a table or view (the ** Table.aCol[] array). @@ -122876,113 +100922,85 @@ */ SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); - assert( db!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; inCol; i++, pCol++){ - assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) ); - sqlite3DbFree(db, pCol->zCnName); - } - sqlite3DbNNFreeNN(db, pTable->aCol); - if( IsOrdinaryTable(pTable) ){ - sqlite3ExprListDelete(db, pTable->u.tab.pDfltList); - } - if( db->pnBytesFreed==0 ){ - pTable->aCol = 0; - pTable->nCol = 0; - if( IsOrdinaryTable(pTable) ){ - pTable->u.tab.pDfltList = 0; - } - } + sqlite3DbFree(db, pCol->zName); + sqlite3ExprDelete(db, pCol->pDflt); + sqlite3DbFree(db, pCol->zColl); + } + sqlite3DbFree(db, pTable->aCol); } } /* ** Remove the memory data structures associated with the given ** Table. No changes are made to disk by this routine. ** ** This routine just deletes the data structure. It does not unlink ** the table data structure from the hash table. But it does destroy -** memory structures of the indices and foreign keys associated with +** memory structures of the indices and foreign keys associated with ** the table. ** -** The db parameter is optional. It is needed if the Table object +** The db parameter is optional. It is needed if the Table object ** contains lookaside memory. (Table objects in the schema do not use ** lookaside memory, but some ephemeral Table objects do.) Or the ** db parameter can be used with db->pnBytesFreed to measure the memory ** used by the Table object. */ 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. - ** - ** If malloc has already failed, it may be that it failed while allocating - ** a Table object that was going to be marked ephemeral. So do not check - ** that no lookaside memory is used in this case either. */ - int nLookaside = 0; - assert( db!=0 ); - if( !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){ - nLookaside = sqlite3LookasideUsed(db, 0); - } -#endif + ** 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 ); /* Delete all indices associated with this table. */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->pSchema==pTable->pSchema || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) ); - if( db->pnBytesFreed==0 && !IsVirtual(pTable) ){ - char *zName = pIndex->zName; + if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){ + char *zName = pIndex->zName; TESTONLY ( Index *pOld = ) sqlite3HashInsert( &pIndex->pSchema->idxHash, zName, 0 ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); } - sqlite3FreeIndex(db, pIndex); - } - - if( IsOrdinaryTable(pTable) ){ - sqlite3FkDelete(db, pTable); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( IsVirtual(pTable) ){ - sqlite3VtabClear(db, pTable); - } -#endif - else{ - assert( IsView(pTable) ); - sqlite3SelectDelete(db, pTable->u.view.pSelect); - } + freeIndex(db, pIndex); + } + + /* Delete any foreign keys attached to this table. */ + sqlite3FkDelete(db, pTable); /* Delete the Table structure itself. */ sqlite3DeleteColumnNames(db, pTable); sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zColAff); + sqlite3SelectDelete(db, pTable->pSelect); sqlite3ExprListDelete(db, pTable->pCheck); +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3VtabClear(db, pTable); +#endif sqlite3DbFree(db, pTable); /* Verify that no lookaside memory was used by schema tables */ - assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) ); + assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); } SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Do not delete the table until the reference count reaches zero. */ - assert( db!=0 ); if( !pTable ) return; - if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return; + if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return; deleteTable(db, pTable); } -SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){ - sqlite3DeleteTable(db, (Table*)pTable); -} /* ** Unlink the given table from the hash tables and the delete the ** table structure with all its indices and foreign keys. @@ -122997,11 +101015,11 @@ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); sqlite3DeleteTable(db, p); - db->mDbFlags |= DBFLAG_SchemaChange; + db->flags |= SQLITE_InternChanges; } /* ** Given a token, return a string that consists of the text of that ** token. Space to hold the returned string @@ -123013,29 +101031,29 @@ ** ** Tokens are often just pointers into the original SQL text and so ** are not \000 terminated and are not persistent. The returned string ** is \000 terminated and is persistent. */ -SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, const Token *pName){ +SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ char *zName; if( pName ){ - zName = sqlite3DbStrNDup(db, (const char*)pName->z, pName->n); + zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n); sqlite3Dequote(zName); }else{ zName = 0; } return zName; } /* -** Open the sqlite_schema table stored in database number iDb for +** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ -SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *p, int iDb){ +SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ Vdbe *v = sqlite3GetVdbe(p); - sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, LEGACY_SCHEMA_TABLE); - sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME); + sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5); if( p->nTab==0 ){ p->nTab = 1; } } @@ -123060,11 +101078,11 @@ } /* ** The token *pName contains the name of a database (either "main" or ** "temp" or the name of an attached db). This routine returns the -** index of the named database in db->aDb[], or -1 if the named db +** index of the named database in db->aDb[], or -1 if the named db ** does not exist. */ SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){ int i; /* Database number */ char *zName; /* Name we are searching for */ @@ -123076,11 +101094,11 @@ /* The table or view or trigger name is passed to this routine via tokens ** pName1 and pName2. If the table name was fully qualified, for example: ** ** CREATE TABLE xxx.yyy (...); -** +** ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if ** the table name is not fully qualified, i.e.: ** ** CREATE TABLE yyy(...); ** @@ -123110,74 +101128,30 @@ if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); return -1; } }else{ - assert( db->init.iDb==0 || db->init.busy || IN_SPECIAL_PARSE - || (db->mDbFlags & DBFLAG_Vacuum)!=0); + assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0); iDb = db->init.iDb; *pUnqual = pName1; } return iDb; } -/* -** True if PRAGMA writable_schema is ON -*/ -SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){ - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 ); - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== - SQLITE_WriteSchema ); - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== - SQLITE_Defensive ); - testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== - (SQLITE_WriteSchema|SQLITE_Defensive) ); - return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; -} - /* ** This routine is used to check if the UTF-8 string zName is a legal ** unqualified name for a new schema object (table, index, view or ** trigger). All names are legal except those that begin with the string ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace ** is reserved for internal use. -** -** When parsing the sqlite_schema table, this routine also checks to -** make sure the "type", "name", and "tbl_name" columns are consistent -** with the SQL. */ -SQLITE_PRIVATE int sqlite3CheckObjectName( - Parse *pParse, /* Parsing context */ - const char *zName, /* Name of the object to check */ - const char *zType, /* Type of this object */ - const char *zTblName /* Parent table name for triggers and indexes */ -){ - sqlite3 *db = pParse->db; - if( sqlite3WritableSchema(db) - || db->init.imposterTable - || !sqlite3Config.bExtraSchemaChecks - ){ - /* Skip these error checks for writable_schema=ON */ - return SQLITE_OK; - } - if( db->init.busy ){ - if( sqlite3_stricmp(zType, db->init.azInit[0]) - || sqlite3_stricmp(zName, db->init.azInit[1]) - || sqlite3_stricmp(zTblName, db->init.azInit[2]) - ){ - sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */ - return SQLITE_ERROR; - } - }else{ - if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7)) - || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName)) - ){ - sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", - zName); - return SQLITE_ERROR; - } - +SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; } return SQLITE_OK; } /* @@ -123188,118 +101162,21 @@ for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){} return p; } /* -** Convert an table column number into a index column number. That is, -** for the column iCol in the table (as defined by the CREATE TABLE statement) -** find the (first) offset of that column in index pIdx. Or return -1 -** if column iCol is not used in index pIdx. +** Return the column of index pIdx that corresponds to table +** column iCol. Return -1 if not found. */ -SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){ +SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){ int i; for(i=0; inColumn; i++){ if( iCol==pIdx->aiColumn[i] ) return i; } return -1; } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* Convert a storage column number into a table column number. -** -** The storage column number (0,1,2,....) is the index of the value -** as it appears in the record on disk. The true column number -** is the index (0,1,2,...) of the column in the CREATE TABLE statement. -** -** The storage column number is less than the table column number if -** and only there are VIRTUAL columns to the left. -** -** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro. -*/ -SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){ - if( pTab->tabFlags & TF_HasVirtual ){ - int i; - for(i=0; i<=iCol; i++){ - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++; - } - } - return iCol; -} -#endif - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* Convert a table column number into a storage column number. -** -** The storage column number (0,1,2,....) is the index of the value -** as it appears in the record on disk. Or, if the input column is -** the N-th virtual column (zero-based) then the storage number is -** the number of non-virtual columns in the table plus N. -** -** The true column number is the index (0,1,2,...) of the column in -** the CREATE TABLE statement. -** -** If the input column is a VIRTUAL column, then it should not appear -** in storage. But the value sometimes is cached in registers that -** follow the range of registers used to construct storage. This -** avoids computing the same VIRTUAL column multiple times, and provides -** values for use by OP_Param opcodes in triggers. Hence, if the -** input column is a VIRTUAL table, put it after all the other columns. -** -** In the following, N means "normal column", S means STORED, and -** V means VIRTUAL. Suppose the CREATE TABLE has columns like this: -** -** CREATE TABLE ex(N,S,V,N,S,V,N,S,V); -** -- 0 1 2 3 4 5 6 7 8 -** -** Then the mapping from this function is as follows: -** -** INPUTS: 0 1 2 3 4 5 6 7 8 -** OUTPUTS: 0 1 6 2 3 7 4 5 8 -** -** So, in other words, this routine shifts all the virtual columns to -** the end. -** -** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and -** this routine is a no-op macro. If the pTab does not have any virtual -** columns, then this routine is no-op that always return iCol. If iCol -** is negative (indicating the ROWID column) then this routine return iCol. -*/ -SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){ - int i; - i16 n; - assert( iColnCol ); - if( (pTab->tabFlags & TF_HasVirtual)==0 || iCol<0 ) return iCol; - for(i=0, n=0; iaCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++; - } - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){ - /* iCol is a virtual column itself */ - return pTab->nNVCol + i - n; - }else{ - /* iCol is a normal or stored column */ - return n; - } -} -#endif - -/* -** Insert a single OP_JournalMode query opcode in order to force the -** prepared statement to return false for sqlite3_stmt_readonly(). This -** is used by CREATE TABLE IF NOT EXISTS and similar if the table already -** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS -** will return false for sqlite3_stmt_readonly() even if that statement -** is a read-only no-op. -*/ -static void sqlite3ForceNotReadOnly(Parse *pParse){ - int iReg = ++pParse->nMem; - Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY); - sqlite3VdbeUsesBtree(v, 0); - } -} - /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response ** to a CREATE TABLE statement. In particular, this routine is called ** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp @@ -123329,33 +101206,30 @@ Vdbe *v; int iDb; /* Database number to create the table in */ Token *pName; /* Unqualified name of the table to create */ if( db->init.busy && db->init.newTnum==1 ){ - /* Special case: Parsing the sqlite_schema or sqlite_temp_schema schema */ + /* Special case: Parsing the sqlite_master or sqlite_temp_master schema */ iDb = db->init.iDb; zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb)); pName = pName1; }else{ /* The common case */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( iDb<0 ) return; if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){ - /* If creating a temp table, the name may not be qualified. Unless + /* If creating a temp table, the name may not be qualified. Unless ** the database name is "temp" anyway. */ sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); return; } if( !OMIT_TEMPDB && isTemp ) iDb = 1; zName = sqlite3NameFromToken(db, pName); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)zName, pName); - } } pParse->sNameToken = *pName; if( zName==0 ) return; - if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){ + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto begin_table_error; } if( db->init.iDb==1 ) isTemp = 1; #ifndef SQLITE_OMIT_AUTHORIZATION assert( isTemp==0 || isTemp==1 ); @@ -123383,24 +101257,22 @@ ** it does. The exception is if the statement being parsed was passed ** to an sqlite3_declare_vtab() call. In that case only the column names ** and types will be used, so there is no need to test for namespace ** collisions. */ - if( !IN_SPECIAL_PARSE ){ + if( !IN_DECLARE_VTAB ){ char *zDb = db->aDb[iDb].zDbSName; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto begin_table_error; } pTable = sqlite3FindTable(db, zName, zDb); if( pTable ){ if( !noErr ){ - sqlite3ErrorMsg(pParse, "%s %T already exists", - (IsView(pTable)? "view" : "table"), pName); + sqlite3ErrorMsg(pParse, "table %T already exists", pName); }else{ assert( !db->init.busy || CORRUPT_DB ); sqlite3CodeVerifySchema(pParse, iDb); - sqlite3ForceNotReadOnly(pParse); } goto begin_table_error; } if( sqlite3FindIndex(db, zName, zDb)!=0 ){ sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); @@ -123424,16 +101296,27 @@ #else pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #endif assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; + + /* If this is the magic sqlite_sequence table used by autoincrement, + ** then record a pointer to this table in the main database structure + ** so that INSERT can find the table easily. + */ +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + pTable->pSchema->pSeqTab = pTable; + } +#endif /* Begin generating the code that will insert the table record into - ** the schema table. Note in particular that we must go ahead + ** the SQLITE_MASTER table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause - ** indices to be created and the table record must come before the + ** indices to be created and the table record must come before the ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ int addr1; @@ -123447,11 +101330,11 @@ if( isVirtual ){ sqlite3VdbeAddOp0(v, OP_VBegin); } #endif - /* If the file format and encoding in the database have not been set, + /* If the file format and encoding in the database have not been set, ** set them now. */ reg1 = pParse->regRowid = ++pParse->nMem; reg2 = pParse->regRoot = ++pParse->nMem; reg3 = ++pParse->nMem; @@ -123462,11 +101345,11 @@ 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db)); sqlite3VdbeJumpHere(v, addr1); - /* This just creates a place-holder record in the sqlite_schema table. + /* This just creates a place-holder record in the sqlite_master table. ** The record created does not contain anything yet. It will be replaced ** by the real entry in code generated at sqlite3EndTable(). ** ** The rowid for the new entry is left in register pParse->regRowid. ** The root page number of the new table is left in reg pParse->regRoot. @@ -123477,15 +101360,13 @@ if( isView || isVirtual ){ sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); }else #endif { - assert( !pParse->bReturning ); - pParse->u1.addrCrTab = - sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY); + pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2); } - sqlite3OpenSchemaTable(pParse, iDb); + sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeAddOp0(v, OP_Close); @@ -123494,211 +101375,90 @@ /* Normal (non-error) return. */ return; /* If an error occurs, we jump here */ begin_table_error: - pParse->checkSchema = 1; sqlite3DbFree(db, zName); return; } /* Set properties of a table column based on the (magical) ** name of the column. */ #if SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ - if( sqlite3_strnicmp(pCol->zCnName, "__hidden__", 10)==0 ){ + if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){ pCol->colFlags |= COLFLAG_HIDDEN; - if( pTab ) pTab->tabFlags |= TF_HasHidden; }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){ pTab->tabFlags |= TF_OOOHidden; } } #endif -/* -** Clean up the data structures associated with the RETURNING clause. -*/ -static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){ - Returning *pRet = (Returning*)pArg; - Hash *pHash; - pHash = &(db->aDb[1].pSchema->trigHash); - sqlite3HashInsert(pHash, pRet->zName, 0); - sqlite3ExprListDelete(db, pRet->pReturnEL); - sqlite3DbFree(db, pRet); -} - -/* -** Add the RETURNING clause to the parse currently underway. -** -** This routine creates a special TEMP trigger that will fire for each row -** of the DML statement. That TEMP trigger contains a single SELECT -** statement with a result set that is the argument of the RETURNING clause. -** The trigger has the Trigger.bReturning flag and an opcode of -** TK_RETURNING instead of TK_SELECT, so that the trigger code generator -** knows to handle it specially. The TEMP trigger is automatically -** removed at the end of the parse. -** -** When this routine is called, we do not yet know if the RETURNING clause -** is attached to a DELETE, INSERT, or UPDATE, so construct it as a -** RETURNING trigger instead. It will then be converted into the appropriate -** type on the first call to sqlite3TriggersExist(). -*/ -SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ - Returning *pRet; - Hash *pHash; - sqlite3 *db = pParse->db; - if( pParse->pNewTrigger ){ - sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger"); - }else{ - assert( pParse->bReturning==0 || pParse->ifNotExists ); - } - pParse->bReturning = 1; - pRet = sqlite3DbMallocZero(db, sizeof(*pRet)); - if( pRet==0 ){ - sqlite3ExprListDelete(db, pList); - return; - } - pParse->u1.pReturning = pRet; - pRet->pParse = pParse; - pRet->pReturnEL = pList; - sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet); - testcase( pParse->earlyCleanup ); - if( db->mallocFailed ) return; - sqlite3_snprintf(sizeof(pRet->zName), pRet->zName, - "sqlite_returning_%p", pParse); - pRet->retTrig.zName = pRet->zName; - pRet->retTrig.op = TK_RETURNING; - pRet->retTrig.tr_tm = TRIGGER_AFTER; - pRet->retTrig.bReturning = 1; - pRet->retTrig.pSchema = db->aDb[1].pSchema; - pRet->retTrig.pTabSchema = db->aDb[1].pSchema; - pRet->retTrig.step_list = &pRet->retTStep; - pRet->retTStep.op = TK_RETURNING; - pRet->retTStep.pTrig = &pRet->retTrig; - pRet->retTStep.pExprList = pList; - pHash = &(db->aDb[1].pSchema->trigHash); - assert( sqlite3HashFind(pHash, pRet->zName)==0 - || pParse->nErr || pParse->ifNotExists ); - if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) - ==&pRet->retTrig ){ - sqlite3OomFault(db); - } -} /* ** Add a new column to the table currently being constructed. ** ** The parser calls this routine once for each column declaration ** in a CREATE TABLE statement. sqlite3StartTable() gets called ** first to get things going. Then this routine is called for each ** column. */ -SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){ +SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ Table *p; int i; char *z; char *zType; Column *pCol; sqlite3 *db = pParse->db; - u8 hName; - Column *aNew; - u8 eType = COLTYPE_CUSTOM; - u8 szEst = 1; - char affinity = SQLITE_AFF_BLOB; - 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; } - if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName); - - /* Because keywords GENERATE ALWAYS can be converted into identifiers - ** by the parser, we can sometimes end up with a typename that ends - ** with "generated always". Check for this case and omit the surplus - ** text. */ - if( sType.n>=16 - && sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0 - ){ - sType.n -= 6; - while( ALWAYS(sType.n>0) && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--; - if( sType.n>=9 - && sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0 - ){ - sType.n -= 9; - while( sType.n>0 && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--; - } - } - - /* Check for standard typenames. For standard typenames we will - ** set the Column.eType field rather than storing the typename after - ** the column name, in order to save space. */ - if( sType.n>=3 ){ - sqlite3DequoteToken(&sType); - for(i=0; i0) ); +#endif + z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); if( z==0 ) return; - if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName); - memcpy(z, sName.z, sName.n); - z[sName.n] = 0; + memcpy(z, pName->z, pName->n); + z[pName->n] = 0; sqlite3Dequote(z); - hName = sqlite3StrIHash(z); for(i=0; inCol; i++){ - if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){ + if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); sqlite3DbFree(db, z); return; } } - aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0])); - if( aNew==0 ){ - sqlite3DbFree(db, z); - return; + if( (p->nCol & 0x7)==0 ){ + Column *aNew; + aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0])); + if( aNew==0 ){ + sqlite3DbFree(db, z); + return; + } + p->aCol = aNew; } - p->aCol = aNew; pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); - pCol->zCnName = z; - pCol->hName = hName; + pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); - - if( sType.n==0 ){ + + if( pType->n==0 ){ /* If there is no type specified, columns have the default affinity - ** 'BLOB' with a default size of 4 bytes. */ - pCol->affinity = affinity; - pCol->eCType = eType; - pCol->szEst = szEst; -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( affinity==SQLITE_AFF_BLOB ){ - if( 4>=sqlite3GlobalConfig.szSorterRef ){ - pCol->colFlags |= COLFLAG_SORTERREF; - } - } -#endif + ** 'BLOB'. */ + pCol->affinity = SQLITE_AFF_BLOB; + pCol->szEst = 1; }else{ zType = z + sqlite3Strlen30(z) + 1; - memcpy(zType, sType.z, sType.n); - zType[sType.n] = 0; + memcpy(zType, pType->z, pType->n); + zType[pType->n] = 0; sqlite3Dequote(zType); - pCol->affinity = sqlite3AffinityType(zType, pCol); + pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); pCol->colFlags |= COLFLAG_HASTYPE; } p->nCol++; - p->nNVCol++; pParse->constraintName.n = 0; } /* ** This routine is called by the parser while in the middle of @@ -123706,39 +101466,25 @@ ** been seen on a column. This routine sets the notNull flag on ** the column currently under construction. */ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ Table *p; - Column *pCol; p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; - pCol = &p->aCol[p->nCol-1]; - pCol->notNull = (u8)onError; + p->aCol[p->nCol-1].notNull = (u8)onError; p->tabFlags |= TF_HasNotNull; - - /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created - ** on this column. */ - if( pCol->colFlags & COLFLAG_UNIQUE ){ - Index *pIdx; - for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None ); - if( pIdx->aiColumn[0]==p->nCol-1 ){ - pIdx->uniqNotNull = 1; - } - } - } } /* ** Scan the column type name zType (length nType) and return the ** associated affinity type. ** -** This routine does a case-independent search of zType for the +** This routine does a case-independent search of zType for the ** substrings in the following table. If one of the substrings is ** found, the corresponding affinity is returned. If zType contains -** more than one of the substrings, entries toward the top of -** the table take priority. For example, if zType is 'BLOBINT', +** more than one of the substrings, entries toward the top of +** the table take priority. For example, if zType is 'BLOBINT', ** SQLITE_AFF_INTEGER is returned. ** ** Substring | Affinity ** -------------------------------- ** 'INT' | SQLITE_AFF_INTEGER @@ -123751,19 +101497,18 @@ ** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ -SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ +SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; const char *zChar = 0; assert( zIn!=0 ); while( zIn[0] ){ - u8 x = *(u8*)zIn; - h = (h<<8) + sqlite3UpperToLower[x]; + h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ aff = SQLITE_AFF_TEXT; zChar = zIn; }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ @@ -123789,36 +101534,31 @@ aff = SQLITE_AFF_INTEGER; break; } } - /* If pCol is not NULL, store an estimate of the field size. The + /* If pszEst is not NULL, store an estimate of the field size. The ** estimate is scaled so that the size of an integer is 1. */ - if( pCol ){ - int v = 0; /* default size is approx 4 bytes */ + if( pszEst ){ + *pszEst = 1; /* default size is approx 4 bytes */ if( aff r=(k/4+1) */ + int v = 0; sqlite3GetInt32(zChar, &v); + v = v/4 + 1; + if( v>255 ) v = 255; + *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ break; } zChar++; } }else{ - v = 16; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ + *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ } } -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( v>=sqlite3GlobalConfig.szSorterRef ){ - pCol->colFlags |= COLFLAG_SORTERREF; - } -#endif - v = v/4 + 1; - if( v>255 ) v = 255; - pCol->szEst = v; } return aff; } /* @@ -123829,56 +101569,43 @@ ** is not the case. ** ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ -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 default value text */ -){ +SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ Table *p; Column *pCol; sqlite3 *db = pParse->db; p = pParse->pNewTable; if( p!=0 ){ - int isInit = db->init.busy && db->init.iDb!=1; pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){ + if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", - pCol->zCnName); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - }else if( pCol->colFlags & COLFLAG_GENERATED ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column"); -#endif + pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains - ** tokens that point to volatile memory. + ** tokens that point to volatile memory. The 'span' of the expression + ** is required by pragma table_info. */ - Expr x, *pDfltExpr; + Expr x; + sqlite3ExprDelete(db, pCol->pDflt); memset(&x, 0, sizeof(x)); x.op = TK_SPAN; - x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); - x.pLeft = pExpr; + x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart, + (int)(pSpan->zEnd - pSpan->zStart)); + x.pLeft = pSpan->pExpr; x.flags = EP_Skip; - pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); + pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); sqlite3DbFree(db, x.u.zToken); - sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr); } } - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprUnmap(pParse, pExpr); - } - sqlite3ExprDelete(db, pExpr); + sqlite3ExprDelete(db, pSpan->pExpr); } /* ** Backwards Compatibility Hack: -** +** ** Historical versions of SQLite accepted strings as column names in ** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example: ** ** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim) ** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC); @@ -123885,11 +101612,11 @@ ** ** This is goofy. But to preserve backwards compatibility we continue to ** accept it. This routine does the necessary conversion. It converts ** the expression given in its argument from a TK_STRING into a TK_ID ** if the expression is just a TK_STRING with an optional COLLATE clause. -** If the expression is anything other than TK_STRING, the expression is +** If the epxression is anything other than TK_STRING, the expression is ** unchanged. */ static void sqlite3StringToId(Expr *p){ if( p->op==TK_STRING ){ p->op = TK_ID; @@ -123897,26 +101624,11 @@ p->pLeft->op = TK_ID; } } /* -** Tag the given column as being part of the PRIMARY KEY -*/ -static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){ - pCol->colFlags |= COLFLAG_PRIMKEY; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pCol->colFlags & COLFLAG_GENERATED ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - sqlite3ErrorMsg(pParse, - "generated columns cannot be part of the PRIMARY KEY"); - } -#endif -} - -/* -** Designate the PRIMARY KEY for the table. pList is a list of names +** Designate the PRIMARY KEY for the table. pList is a list of names ** of columns that form the primary key. If pList is NULL, then the ** most recently added column of the table is the primary key. ** ** A table can have at most one primary key. If the table already has ** a primary key (and this is the second primary key) then create an @@ -123942,55 +101654,48 @@ Column *pCol = 0; int iCol = -1, i; int nTerm; if( pTab==0 ) goto primary_key_exit; if( pTab->tabFlags & TF_HasPrimaryKey ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); goto primary_key_exit; } pTab->tabFlags |= TF_HasPrimaryKey; if( pList==0 ){ iCol = pTab->nCol - 1; pCol = &pTab->aCol[iCol]; - makeColumnPartOfPrimaryKey(pParse, pCol); + pCol->colFlags |= COLFLAG_PRIMKEY; nTerm = 1; }else{ nTerm = pList->nExpr; for(i=0; ia[i].pExpr); assert( pCExpr!=0 ); sqlite3StringToId(pCExpr); if( pCExpr->op==TK_ID ){ - const char *zCName; - assert( !ExprHasProperty(pCExpr, EP_IntValue) ); - zCName = pCExpr->u.zToken; + const char *zCName = pCExpr->u.zToken; for(iCol=0; iColnCol; iCol++){ - if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){ + if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){ pCol = &pTab->aCol[iCol]; - makeColumnPartOfPrimaryKey(pParse, pCol); + pCol->colFlags |= COLFLAG_PRIMKEY; break; } } } } } if( nTerm==1 && pCol - && pCol->eCType==COLTYPE_INTEGER + && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0 && sortOrder!=SQLITE_SO_DESC ){ - if( IN_RENAME_OBJECT && pList ){ - Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr); - sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr); - } pTab->iPKey = iCol; pTab->keyConf = (u8)onError; assert( autoInc==0 || autoInc==1 ); pTab->tabFlags |= autoInc*TF_Autoincrement; - if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags; - (void)sqlite3HasExplicitNulls(pParse, pList); + if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder; }else if( autoInc ){ #ifndef SQLITE_OMIT_AUTOINCREMENT sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " "INTEGER PRIMARY KEY"); #endif @@ -124007,14 +101712,12 @@ /* ** Add a new CHECK constraint to the table currently under construction. */ SQLITE_PRIVATE void sqlite3AddCheckConstraint( - Parse *pParse, /* Parsing context */ - Expr *pCheckExpr, /* The check expression */ - const char *zStart, /* Opening "(" */ - const char *zEnd /* Closing ")" */ + Parse *pParse, /* Parsing context */ + Expr *pCheckExpr /* The check expression */ ){ #ifndef SQLITE_OMIT_CHECK Table *pTab = pParse->pNewTable; sqlite3 *db = pParse->db; if( pTab && !IN_DECLARE_VTAB @@ -124021,17 +101724,10 @@ && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt) ){ pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr); if( pParse->constraintName.n ){ sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1); - }else{ - Token t; - for(zStart++; sqlite3Isspace(zStart[0]); zStart++){} - while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; } - t.z = zStart; - t.n = (int)(zEnd - t.z); - sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1); } }else #endif { sqlite3ExprDelete(pParse->db, pCheckExpr); @@ -124046,93 +101742,70 @@ Table *p; int i; char *zColl; /* Dequoted name of collation sequence */ sqlite3 *db; - if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return; + if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; db = pParse->db; zColl = sqlite3NameFromToken(db, pToken); if( !zColl ) return; if( sqlite3LocateCollSeq(pParse, zColl) ){ Index *pIdx; - sqlite3ColumnSetColl(db, &p->aCol[i], zColl); - + sqlite3DbFree(db, p->aCol[i].zColl); + p->aCol[i].zColl = zColl; + /* If the column is declared as " PRIMARY KEY COLLATE ", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nKeyCol==1 ); if( pIdx->aiColumn[0]==i ){ - pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]); - } - } - } - sqlite3DbFree(db, zColl); -} - -/* Change the most recently parsed column to be a GENERATED ALWAYS AS -** column. -*/ -SQLITE_PRIVATE void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){ -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - u8 eType = COLFLAG_VIRTUAL; - Table *pTab = pParse->pNewTable; - Column *pCol; - if( pTab==0 ){ - /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */ - goto generated_done; - } - pCol = &(pTab->aCol[pTab->nCol-1]); - if( IN_DECLARE_VTAB ){ - sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns"); - goto generated_done; - } - if( pCol->iDflt>0 ) goto generated_error; - if( pType ){ - if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){ - /* no-op */ - }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){ - eType = COLFLAG_STORED; - }else{ - goto generated_error; - } - } - if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--; - pCol->colFlags |= eType; - assert( TF_HasVirtual==COLFLAG_VIRTUAL ); - assert( TF_HasStored==COLFLAG_STORED ); - pTab->tabFlags |= eType; - if( pCol->colFlags & COLFLAG_PRIMKEY ){ - makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */ - } - if( ALWAYS(pExpr) && pExpr->op==TK_ID ){ - /* The value of a generated column needs to be a real expression, not - ** just a reference to another column, in order for covering index - ** optimizations to work correctly. So if the value is not an expression, - ** turn it into one by adding a unary "+" operator. */ - pExpr = sqlite3PExpr(pParse, TK_UPLUS, pExpr, 0); - } - if( pExpr && pExpr->op!=TK_RAISE ) pExpr->affExpr = pCol->affinity; - sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr); - pExpr = 0; - goto generated_done; - -generated_error: - sqlite3ErrorMsg(pParse, "error in generated column \"%s\"", - pCol->zCnName); -generated_done: - sqlite3ExprDelete(pParse->db, pExpr); -#else - /* Throw and error for the GENERATED ALWAYS AS clause if the - ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */ - sqlite3ErrorMsg(pParse, "generated columns not supported"); - sqlite3ExprDelete(pParse->db, pExpr); -#endif -} + pIdx->azColl[0] = p->aCol[i].zColl; + } + } + }else{ + sqlite3DbFree(db, zColl); + } +} + +/* +** This function returns the collation sequence for database native text +** encoding identified by the string zName, length nName. +** +** If the requested collation sequence is not available, or not available +** in the database native encoding, the collation factory is invoked to +** request it. If the collation factory does not supply such a sequence, +** and the sequence is available in another text encoding, then that is +** returned instead. +** +** If no versions of the requested collations sequence are available, or +** another error occurs, NULL is returned and an error message written into +** pParse. +** +** This routine is a wrapper around sqlite3FindCollSeq(). This routine +** invokes the collation factory if the named collation cannot be found +** and generates an error message. +** +** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq() +*/ +SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ + sqlite3 *db = pParse->db; + u8 enc = ENC(db); + u8 initbusy = db->init.busy; + CollSeq *pColl; + + pColl = sqlite3FindCollSeq(db, enc, zName, initbusy); + if( !initbusy && (!pColl || !pColl->xCmp) ){ + pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName); + } + + return pColl; +} + /* ** Generate code that will increment the schema cookie. ** ** The schema cookie is used to determine when the schema for the @@ -124153,12 +101826,12 @@ */ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, - (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie)); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, + db->aDb[iDb].pSchema->schema_cookie+1); } /* ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used @@ -124174,18 +101847,18 @@ } return n + 2; } /* -** The first parameter is a pointer to an output buffer. The second +** The first parameter is a pointer to an output buffer. The second ** parameter is a pointer to an integer that contains the offset at ** which to write into the output buffer. This function copies the ** nul-terminated string pointed to by the third parameter, zSignedIdent, ** to the specified offset in the buffer and updates *pIdx to refer ** to the first byte after the last byte written before returning. -** -** If the string zSignedIdent consists entirely of alphanumeric +** +** If the string zSignedIdent consists entirely of alpha-numeric ** characters, does not begin with a digit and is not an SQL keyword, ** then it is copied to the output buffer exactly as it is. Otherwise, ** it is quoted using double-quotes. */ static void identPut(char *z, int *pIdx, char *zSignedIdent){ @@ -124221,14 +101894,14 @@ char *zStmt; char *zSep, *zSep2, *zEnd; Column *pCol; n = 0; for(pCol = p->aCol, i=0; inCol; i++, pCol++){ - n += identLength(pCol->zCnName) + 5; + n += identLength(pCol->zName) + 5; } n += identLength(p->zName); - if( n<50 ){ + if( n<50 ){ zSep = ""; zSep2 = ","; zEnd = ")"; }else{ zSep = "\n "; @@ -124249,33 +101922,30 @@ static const char * const azType[] = { /* SQLITE_AFF_BLOB */ "", /* SQLITE_AFF_TEXT */ " TEXT", /* SQLITE_AFF_NUMERIC */ " NUM", /* SQLITE_AFF_INTEGER */ " INT", - /* SQLITE_AFF_REAL */ " REAL", - /* SQLITE_AFF_FLEXNUM */ " NUM", + /* SQLITE_AFF_REAL */ " REAL" }; int len; const char *zType; sqlite3_snprintf(n-k, &zStmt[k], zSep); k += sqlite3Strlen30(&zStmt[k]); zSep = zSep2; - identPut(zStmt, &k, pCol->zCnName); + identPut(zStmt, &k, pCol->zName); assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 ); assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) ); testcase( pCol->affinity==SQLITE_AFF_BLOB ); testcase( pCol->affinity==SQLITE_AFF_TEXT ); testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); testcase( pCol->affinity==SQLITE_AFF_INTEGER ); testcase( pCol->affinity==SQLITE_AFF_REAL ); - testcase( pCol->affinity==SQLITE_AFF_FLEXNUM ); - + zType = azType[pCol->affinity - SQLITE_AFF_BLOB]; len = sqlite3Strlen30(zType); - assert( pCol->affinity==SQLITE_AFF_BLOB - || pCol->affinity==SQLITE_AFF_FLEXNUM + assert( pCol->affinity==SQLITE_AFF_BLOB || pCol->affinity==sqlite3AffinityType(zType, 0) ); memcpy(&zStmt[k], zType, len); k += len; assert( k<=n ); } @@ -124290,19 +101960,16 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){ char *zExtra; int nByte; if( pIdx->nColumn>=N ) return SQLITE_OK; assert( pIdx->isResized==0 ); - nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N; + nByte = (sizeof(char*) + sizeof(i16) + 1)*N; zExtra = sqlite3DbMallocZero(db, nByte); if( zExtra==0 ) return SQLITE_NOMEM_BKPT; memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn); pIdx->azColl = (const char**)zExtra; zExtra += sizeof(char*)*N; - memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1)); - pIdx->aiRowLogEst = (LogEst*)zExtra; - zExtra += sizeof(LogEst)*N; memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn); pIdx->aiColumn = (i16*)zExtra; zExtra += sizeof(i16)*N; memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn); pIdx->aSortOrder = (u8*)zExtra; @@ -124333,95 +102000,20 @@ int i; const Column *aCol = pIdx->pTable->aCol; for(i=0; inColumn; i++){ i16 x = pIdx->aiColumn[i]; assert( xpTable->nCol ); - wIndex += x<0 ? 1 : aCol[x].szEst; + wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst; } pIdx->szIdxRow = sqlite3LogEst(wIndex*4); } -/* Return true if column number x is any of the first nCol entries of aiCol[]. -** This is used to determine if the column number x appears in any of the -** first nCol entries of an index. +/* Return true if value x is found any of the first nCol entries of aiCol[] */ static int hasColumn(const i16 *aiCol, int nCol, int x){ - while( nCol-- > 0 ){ - if( x==*(aiCol++) ){ - return 1; - } - } - return 0; -} - -/* -** Return true if any of the first nKey entries of index pIdx exactly -** match the iCol-th entry of pPk. pPk is always a WITHOUT ROWID -** PRIMARY KEY index. pIdx is an index on the same table. pIdx may -** or may not be the same index as pPk. -** -** The first nKey entries of pIdx are guaranteed to be ordinary columns, -** not a rowid or expression. -** -** This routine differs from hasColumn() in that both the column and the -** collating sequence must match for this routine, but for hasColumn() only -** the column name must match. -*/ -static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){ - int i, j; - assert( nKey<=pIdx->nColumn ); - assert( iColnColumn,pPk->nKeyCol) ); - assert( pPk->idxType==SQLITE_IDXTYPE_PRIMARYKEY ); - assert( pPk->pTable->tabFlags & TF_WithoutRowid ); - assert( pPk->pTable==pIdx->pTable ); - testcase( pPk==pIdx ); - j = pPk->aiColumn[iCol]; - assert( j!=XN_ROWID && j!=XN_EXPR ); - for(i=0; iaiColumn[i]>=0 || j>=0 ); - if( pIdx->aiColumn[i]==j - && sqlite3StrICmp(pIdx->azColl[i], pPk->azColl[iCol])==0 - ){ - return 1; - } - } - return 0; -} - -/* Recompute the colNotIdxed field of the Index. -** -** colNotIdxed is a bitmask that has a 0 bit representing each indexed -** columns that are within the first 63 columns of the table and a 1 for -** all other bits (all columns that are not in the index). The -** high-order bit of colNotIdxed is always 1. All unindexed columns -** of the table have a 1. -** -** 2019-10-24: For the purpose of this computation, virtual columns are -** not considered to be covered by the index, even if they are in the -** index, because we do not trust the logic in whereIndexExprTrans() to be -** able to find all instances of a reference to the indexed table column -** and convert them into references to the index. Hence we always want -** the actual table at hand in order to recompute the virtual column, if -** necessary. -** -** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask -** to determine if the index is covering index. -*/ -static void recomputeColumnsNotIndexed(Index *pIdx){ - Bitmask m = 0; - int j; - Table *pTab = pIdx->pTable; - for(j=pIdx->nColumn-1; j>=0; j--){ - int x = pIdx->aiColumn[j]; - if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){ - testcase( x==BMS-1 ); - testcase( x==BMS-2 ); - if( xcolNotIdxed = ~m; - assert( (pIdx->colNotIdxed>>63)==1 ); /* See note-20221022-a */ + while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1; + return 0; } /* ** This routine runs at the end of parsing a CREATE TABLE statement that ** has a WITHOUT ROWID clause. The job of this routine is to convert both @@ -124428,20 +102020,21 @@ ** internal schema data structures and the generated VDBE code so that they ** are appropriate for a WITHOUT ROWID table instead of a rowid table. ** Changes include: ** ** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL. -** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY -** into BTREE_BLOBKEY. -** (3) Bypass the creation of the sqlite_schema table entry +** (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. +** (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_schema table entry of the table itself. +** identified by the sqlite_master table entry of the table itself. ** (4) Set the Index.tnum of the PRIMARY KEY Index object in the ** 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.nAllField and are not used for +** columns are part of KeyInfo.nXField 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. ** ** For virtual tables, only (1) is performed. @@ -124448,99 +102041,84 @@ */ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ Index *pIdx; Index *pPk; int nPk; - int nExtra; int i, j; sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; /* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables) */ if( !db->init.imposterTable ){ for(i=0; inCol; i++){ - if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 - && (pTab->aCol[i].notNull==OE_None) - ){ + if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){ pTab->aCol[i].notNull = OE_Abort; } } - pTab->tabFlags |= TF_HasNotNull; } - /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY - ** into BTREE_BLOBKEY. + /* The remaining transformations only apply to b-tree tables, not to + ** 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. */ - assert( !pParse->bReturning ); - if( pParse->u1.addrCrTab ){ + if( pParse->addrCrTab ){ assert( v ); - sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY); + sqlite3VdbeChangeOpcode(v, pParse->addrCrTab, OP_CreateIndex); } /* Locate the PRIMARY KEY index. Or, if this table was originally - ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. + ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. */ if( pTab->iPKey>=0 ){ ExprList *pList; Token ipkToken; - sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName); - pList = sqlite3ExprListAppend(pParse, 0, + sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName); + pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); - if( pList==0 ){ - pTab->tabFlags &= ~TF_WithoutRowid; - return; - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); - } - pList->a[0].fg.sortFlags = pParse->iPkSortOrder; + if( pList==0 ) return; + pList->a[0].sortOrder = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); - pTab->iPKey = -1; sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, SQLITE_IDXTYPE_PRIMARYKEY); - if( pParse->nErr ){ - pTab->tabFlags &= ~TF_WithoutRowid; - return; - } - assert( db->mallocFailed==0 ); + if( db->mallocFailed ) return; pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk->nKeyCol==1 ); + pTab->iPKey = -1; }else{ pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); + + /* 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 ** code assumes the PRIMARY KEY contains no repeated columns. */ for(i=j=1; inKeyCol; i++){ - if( isDupColumn(pPk, j, pPk, i) ){ + if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ pPk->nColumn--; }else{ - testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ); - pPk->azColl[j] = pPk->azColl[i]; - pPk->aSortOrder[j] = pPk->aSortOrder[i]; pPk->aiColumn[j++] = pPk->aiColumn[i]; } } pPk->nKeyCol = j; } assert( pPk!=0 ); pPk->isCovering = 1; if( !db->init.imposterTable ) pPk->uniqNotNull = 1; - nPk = pPk->nColumn = pPk->nKeyCol; - - /* Bypass the creation of the PRIMARY KEY btree and the sqlite_schema - ** 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, (int)pPk->tnum, OP_Goto); - } + nPk = pPk->nKeyCol; /* The root page of the PRIMARY KEY is the table root page */ pPk->tnum = pTab->tnum; /* Update the in-memory representation of all UNIQUE indices by converting @@ -124548,192 +102126,73 @@ */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int n; if( IsPrimaryKeyIndex(pIdx) ) continue; for(i=n=0; inKeyCol, pPk, i) ){ - testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); - n++; - } + if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++; } if( n==0 ){ /* This index is a superset of the primary key */ pIdx->nColumn = pIdx->nKeyCol; continue; } if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return; for(i=0, j=pIdx->nKeyCol; inKeyCol, pPk, i) ){ - testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); + if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){ pIdx->aiColumn[j] = pPk->aiColumn[i]; pIdx->azColl[j] = pPk->azColl[i]; - if( pPk->aSortOrder[i] ){ - /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */ - pIdx->bAscKeyBug = 1; - } j++; } } assert( pIdx->nColumn>=pIdx->nKeyCol+n ); assert( pIdx->nColumn>=j ); } /* Add all table columns to the PRIMARY KEY index */ - nExtra = 0; - for(i=0; inCol; i++){ - if( !hasColumn(pPk->aiColumn, nPk, i) - && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++; - } - if( resizeIndexObject(db, pPk, nPk+nExtra) ) return; - for(i=0, j=nPk; inCol; i++){ - if( !hasColumn(pPk->aiColumn, j, i) - && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 - ){ - assert( jnColumn ); - pPk->aiColumn[j] = i; - pPk->azColl[j] = sqlite3StrBINARY; - j++; - } - } - assert( pPk->nColumn==j ); - assert( pTab->nNVCol<=j ); - recomputeColumnsNotIndexed(pPk); -} - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Return true if pTab is a virtual table and zName is a shadow table name -** for that virtual table. -*/ -SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){ - int nName; /* Length of zName */ - Module *pMod; /* Module for the virtual table */ - - if( !IsVirtual(pTab) ) return 0; - nName = sqlite3Strlen30(pTab->zName); - if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0; - if( zName[nName]!='_' ) return 0; - pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]); - if( pMod==0 ) return 0; - if( pMod->pModule->iVersion<3 ) return 0; - if( pMod->pModule->xShadowName==0 ) return 0; - return pMod->pModule->xShadowName(zName+nName+1); -} -#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Table pTab is a virtual table. If it the virtual table implementation -** exists and has an xShadowName method, then loop over all other ordinary -** tables within the same schema looking for shadow tables of pTab, and mark -** any shadow tables seen using the TF_Shadow flag. -*/ -SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){ - int nName; /* Length of pTab->zName */ - Module *pMod; /* Module for the virtual table */ - HashElem *k; /* For looping through the symbol table */ - - assert( IsVirtual(pTab) ); - pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]); - if( pMod==0 ) return; - if( NEVER(pMod->pModule==0) ) return; - if( pMod->pModule->iVersion<3 ) return; - if( pMod->pModule->xShadowName==0 ) return; - assert( pTab->zName!=0 ); - nName = sqlite3Strlen30(pTab->zName); - for(k=sqliteHashFirst(&pTab->pSchema->tblHash); k; k=sqliteHashNext(k)){ - Table *pOther = sqliteHashData(k); - assert( pOther->zName!=0 ); - if( !IsOrdinaryTable(pOther) ) continue; - if( pOther->tabFlags & TF_Shadow ) continue; - if( sqlite3StrNICmp(pOther->zName, pTab->zName, nName)==0 - && pOther->zName[nName]=='_' - && pMod->pModule->xShadowName(pOther->zName+nName+1) - ){ - pOther->tabFlags |= TF_Shadow; - } - } -} -#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Return true if zName is a shadow table name in the current database -** connection. -** -** zName is temporarily modified while this routine is running, but is -** restored to its original value prior to this routine returning. -*/ -SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ - char *zTail; /* Pointer to the last "_" in zName */ - Table *pTab; /* Table that zName is a shadow of */ - zTail = strrchr(zName, '_'); - if( zTail==0 ) return 0; - *zTail = 0; - pTab = sqlite3FindTable(db, zName, 0); - *zTail = '_'; - if( pTab==0 ) return 0; - if( !IsVirtual(pTab) ) return 0; - return sqlite3IsShadowTableOf(db, pTab, zName); -} -#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ - - -#ifdef SQLITE_DEBUG -/* -** Mark all nodes of an expression as EP_Immutable, indicating that -** they should not be changed. Expressions attached to a table or -** index definition are tagged this way to help ensure that we do -** not pass them into code generator routines by mistake. -*/ -static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){ - (void)pWalker; - ExprSetVVAProperty(pExpr, EP_Immutable); - return WRC_Continue; -} -static void markExprListImmutable(ExprList *pList){ - if( pList ){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = markImmutableExprStep; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.xSelectCallback2 = 0; - sqlite3WalkExprList(&w, pList); - } -} -#else -#define markExprListImmutable(X) /* no-op */ -#endif /* SQLITE_DEBUG */ - + if( nPknCol ){ + if( resizeIndexObject(db, pPk, pTab->nCol) ) return; + for(i=0, j=nPk; inCol; i++){ + if( !hasColumn(pPk->aiColumn, j, i) ){ + assert( jnColumn ); + pPk->aiColumn[j] = i; + pPk->azColl[j] = sqlite3StrBINARY; + j++; + } + } + assert( pPk->nColumn==j ); + assert( pTab->nCol==j ); + }else{ + pPk->nColumn = pTab->nCol; + } +} /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure that other action routines have been building ** is added to the internal hash tables, assuming no errors have ** occurred. ** -** An entry for the table is made in the schema table on disk, unless +** An entry for the table is made in the master table on disk, unless ** this is a temporary table or db->init.busy==1. When db->init.busy==1 -** it means we are reading the sqlite_schema table because we just -** connected to the database or because the sqlite_schema table has +** it means we are reading the sqlite_master table because we just +** connected to the database or because the sqlite_master table has ** recently changed, so the entry for this table already exists in -** the sqlite_schema table. We do not want to create it again. +** the sqlite_master table. We do not want to create it again. ** ** If the pSelect argument is not NULL, it means that this routine -** was called to create a table generated from a +** was called to create a table generated from a ** "CREATE TABLE ... AS SELECT ..." statement. The column names of ** the new table will match the result set of the SELECT. */ SQLITE_PRIVATE void sqlite3EndTable( Parse *pParse, /* Parse context */ Token *pCons, /* The ',' token after the last column defn. */ Token *pEnd, /* The ')' before options in the CREATE TABLE */ - u32 tabOpts, /* Extra table options. Usually 0. */ + u8 tabOpts, /* Extra table options. Usually 0. */ Select *pSelect /* Select from a "CREATE ... AS SELECT" */ ){ Table *p; /* The new table */ sqlite3 *db = pParse->db; /* The database connection */ int iDb; /* Database in which the table lives */ @@ -124740,149 +102199,63 @@ Index *pIdx; /* An implied index of the table */ if( pEnd==0 && pSelect==0 ){ return; } + assert( !db->mallocFailed ); p = pParse->pNewTable; if( p==0 ) return; - if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){ - p->tabFlags |= TF_Shadow; - } + assert( !db->init.busy || !pSelect ); /* If the db->init.busy is 1 it means we are reading the SQL off the - ** "sqlite_schema" or "sqlite_temp_schema" table on the disk. + ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number ** for the table from the db->init.newTnum field. (The page number ** should have been put there by the sqliteOpenCb routine.) ** - ** If the root page number is 1, that means this is the sqlite_schema + ** If the root page number is 1, that means this is the sqlite_master ** table itself. So mark it read-only. */ if( db->init.busy ){ - if( pSelect || (!IsOrdinaryTable(p) && db->init.newTnum) ){ - sqlite3ErrorMsg(pParse, ""); - return; - } p->tnum = db->init.newTnum; if( p->tnum==1 ) p->tabFlags |= TF_Readonly; } - /* Special processing for tables that include the STRICT keyword: - ** - ** * Do not allow custom column datatypes. Every column must have - ** a datatype that is one of INT, INTEGER, REAL, TEXT, or BLOB. - ** - ** * If a PRIMARY KEY is defined, other than the INTEGER PRIMARY KEY, - ** then all columns of the PRIMARY KEY must have a NOT NULL - ** constraint. - */ - if( tabOpts & TF_Strict ){ - int ii; - p->tabFlags |= TF_Strict; - for(ii=0; iinCol; ii++){ - Column *pCol = &p->aCol[ii]; - if( pCol->eCType==COLTYPE_CUSTOM ){ - if( pCol->colFlags & COLFLAG_HASTYPE ){ - sqlite3ErrorMsg(pParse, - "unknown datatype for %s.%s: \"%s\"", - p->zName, pCol->zCnName, sqlite3ColumnType(pCol, "") - ); - }else{ - sqlite3ErrorMsg(pParse, "missing datatype for %s.%s", - p->zName, pCol->zCnName); - } - return; - }else if( pCol->eCType==COLTYPE_ANY ){ - pCol->affinity = SQLITE_AFF_BLOB; - } - if( (pCol->colFlags & COLFLAG_PRIMKEY)!=0 - && p->iPKey!=ii - && pCol->notNull == OE_None - ){ - pCol->notNull = OE_Abort; - p->tabFlags |= TF_HasNotNull; - } - } - } - - assert( (p->tabFlags & TF_HasPrimaryKey)==0 - || p->iPKey>=0 || sqlite3PrimaryKeyIndex(p)!=0 ); - assert( (p->tabFlags & TF_HasPrimaryKey)!=0 - || (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) ); - /* Special processing for WITHOUT ROWID Tables */ if( tabOpts & TF_WithoutRowid ){ if( (p->tabFlags & TF_Autoincrement) ){ sqlite3ErrorMsg(pParse, "AUTOINCREMENT not allowed on WITHOUT ROWID tables"); return; } if( (p->tabFlags & TF_HasPrimaryKey)==0 ){ sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); - return; + }else{ + p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; + convertToWithoutRowidTable(pParse, p); } - p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; - convertToWithoutRowidTable(pParse, p); } + iDb = sqlite3SchemaToIndex(db, p->pSchema); #ifndef SQLITE_OMIT_CHECK /* Resolve names in all CHECK constraint expressions. */ if( p->pCheck ){ sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck); - if( pParse->nErr ){ - /* If errors are seen, delete the CHECK constraints now, else they might - ** actually be used if PRAGMA writable_schema=ON is set. */ - sqlite3ExprListDelete(db, p->pCheck); - p->pCheck = 0; - }else{ - markExprListImmutable(p->pCheck); - } } #endif /* !defined(SQLITE_OMIT_CHECK) */ -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( p->tabFlags & TF_HasGenerated ){ - int ii, nNG = 0; - testcase( p->tabFlags & TF_HasVirtual ); - testcase( p->tabFlags & TF_HasStored ); - for(ii=0; iinCol; ii++){ - u32 colFlags = p->aCol[ii].colFlags; - if( (colFlags & COLFLAG_GENERATED)!=0 ){ - Expr *pX = sqlite3ColumnExpr(p, &p->aCol[ii]); - testcase( colFlags & COLFLAG_VIRTUAL ); - testcase( colFlags & COLFLAG_STORED ); - if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){ - /* If there are errors in resolving the expression, change the - ** expression to a NULL. This prevents code generators that operate - ** on the expression from inserting extra parts into the expression - ** tree that have been allocated from lookaside memory, which is - ** illegal in a schema and will lead to errors or heap corruption - ** when the database connection closes. */ - sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii], - sqlite3ExprAlloc(db, TK_NULL, 0, 0)); - } - }else{ - nNG++; - } - } - if( nNG==0 ){ - sqlite3ErrorMsg(pParse, "must have at least one non-generated column"); - return; - } - } -#endif /* Estimate the average row size for the table and for all implied indices */ estimateTableWidth(p); for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ estimateIndexWidth(pIdx); } /* If not initializing, then create a record for the new table - ** in the schema table of the database. + ** in the SQLITE_MASTER table of the database. ** ** If this is a TEMPORARY table, write the entry into the auxiliary ** file instead of into the main database file. */ if( !db->init.busy ){ @@ -124895,14 +102268,14 @@ v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return; sqlite3VdbeAddOp1(v, OP_Close, 0); - /* + /* ** Initialize zType for the new view or table. */ - if( IsOrdinaryTable(p) ){ + if( p->pSelect==0 ){ /* A regular table */ zType = "table"; zType2 = "TABLE"; #ifndef SQLITE_OMIT_VIEW }else{ @@ -124931,72 +102304,66 @@ int addrTop; /* Top of the co-routine */ int regRec; /* A record to be insert into the new table */ int regRowid; /* Rowid of the next row to insert */ int addrInsLoop; /* Top of the loop for inserting rows */ Table *pSelTab; /* A table that describes the SELECT results */ - int iCsr; /* Write cursor on the new table */ - - if( IN_SPECIAL_PARSE ){ - pParse->rc = SQLITE_ERROR; - pParse->nErr++; - return; - } - iCsr = pParse->nTab++; + regYield = ++pParse->nMem; regRec = ++pParse->nMem; regRowid = ++pParse->nMem; + assert(pParse->nTab==1); sqlite3MayAbort(pParse); - sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb); + sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); + 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, SQLITE_AFF_BLOB); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); - p->nCol = p->nNVCol = pSelTab->nCol; + p->nCol = pSelTab->nCol; p->aCol = pSelTab->aCol; 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); sqlite3TableAffinity(v, p, 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid); + sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid); sqlite3VdbeGoto(v, addrInsLoop); sqlite3VdbeJumpHere(v, addrInsLoop); - sqlite3VdbeAddOp1(v, OP_Close, iCsr); + sqlite3VdbeAddOp1(v, OP_Close, 1); } /* Compute the complete text of the CREATE statement */ if( pSelect ){ zStmt = createTableStmt(db, p); }else{ Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd; n = (int)(pEnd2->z - pParse->sNameToken.z); if( pEnd2->z[0]!=';' ) n += pEnd2->n; - zStmt = sqlite3MPrintf(db, + zStmt = sqlite3MPrintf(db, "CREATE %s %.*s", zType2, n, pParse->sNameToken.z ); } - /* A slot for the record has already been allocated in the - ** schema table. We just need to update that slot with all + /* A slot for the record has already been allocated in the + ** SQLITE_MASTER table. We just need to update that slot with all ** the information we've collected. */ sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE - " SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q" - " WHERE rowid=#%d", - db->aDb[iDb].zDbSName, + "UPDATE %Q.%s " + "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " + "WHERE rowid=#%d", + db->aDb[iDb].zDbSName, MASTER_NAME, zType, p->zName, p->zName, pParse->regRoot, zStmt, @@ -125007,11 +102374,11 @@ #ifndef SQLITE_OMIT_AUTOINCREMENT /* Check to see if we need to create an sqlite_sequence table for ** keeping track of autoincrement keys. */ - if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){ + if( (p->tabFlags & TF_Autoincrement)!=0 ){ Db *pDb = &db->aDb[iDb]; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", @@ -125021,58 +102388,42 @@ } #endif /* Reparse everything to update our internal data structures */ sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0); - - /* Test for cycles in generated columns and illegal expressions - ** in CHECK constraints and in DEFAULT clauses. */ - if( p->tabFlags & TF_HasGenerated ){ - sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0, - sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", - db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); - } - } + sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName)); + } + /* Add the table to the in-memory representation of the database. */ if( db->init.busy ){ Table *pOld; Schema *pSchema = p->pSchema; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( HasRowid(p) || p->iPKey<0 ); pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ sqlite3OomFault(db); return; } pParse->pNewTable = 0; - db->mDbFlags |= DBFLAG_SchemaChange; - - /* If this is the magic sqlite_sequence table used by autoincrement, - ** then record a pointer to this table in the main database structure - ** so that INSERT can find the table easily. */ - assert( !pParse->nested ); -#ifndef SQLITE_OMIT_AUTOINCREMENT - if( strcmp(p->zName, "sqlite_sequence")==0 ){ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - p->pSchema->pSeqTab = p; - } -#endif - } + db->flags |= SQLITE_InternChanges; #ifndef SQLITE_OMIT_ALTERTABLE - if( !pSelect && IsOrdinaryTable(p) ){ - assert( pCons && pEnd ); - if( pCons->z==0 ){ - pCons = pEnd; - } - p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z); - } -#endif + if( !p->pSelect ){ + const char *zName = (const char *)pParse->sNameToken.z; + int nName; + assert( !pSelect && pCons && pEnd ); + if( pCons->z==0 ){ + pCons = pEnd; + } + nName = (int)((const char *)pCons->z - zName); + p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName); + } +#endif + } } #ifndef SQLITE_OMIT_VIEW /* ** The parser calls this routine in order to create a new VIEW @@ -125101,23 +102452,10 @@ goto create_view_fail; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; - - /* Legacy versions of SQLite allowed the use of the magic "rowid" column - ** on a view, even though views do not have rowids. The following flag - ** setting fixes this problem. But the fix can be disabled by compiling - ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that - ** depend upon the old buggy behavior. The ability can also be toggled - ** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */ -#else - p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */ -#endif - sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; @@ -125124,26 +102462,19 @@ /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite3_exec() call returns. */ - pSelect->selFlags |= SF_View; - if( IN_RENAME_OBJECT ){ - p->u.view.pSelect = pSelect; - pSelect = 0; - }else{ - p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - } + p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); - p->eTabType = TABTYP_VIEW; if( db->mallocFailed ) goto create_view_fail; /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; - assert( sEnd.z[0]!=0 || sEnd.n==0 ); + assert( sEnd.z[0]!=0 ); if( sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = (int)(sEnd.z - pBegin->z); @@ -125151,59 +102482,50 @@ z = pBegin->z; while( sqlite3Isspace(z[n-1]) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; - /* Use sqlite3EndTable() to add the view to the schema table */ + /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ sqlite3EndTable(pParse, 0, &sEnd, 0, 0); create_view_fail: sqlite3SelectDelete(db, pSelect); - if( IN_RENAME_OBJECT ){ - sqlite3RenameExprlistUnmap(pParse, pCNames); - } sqlite3ExprListDelete(db, pCNames); return; } #endif /* SQLITE_OMIT_VIEW */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** The Table structure pTable is really a VIEW. Fill in the names of -** the columns of the view in the pTable structure. Return non-zero if -** there are errors. If an error is seen an error message is left -** in pParse->zErrMsg. +** the columns of the view in the pTable structure. Return the number +** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ -static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){ +SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ Table *pSelTab; /* A fake table from which we get the result set */ Select *pSel; /* Copy of the SELECT that implements the view */ 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 assert( pTable ); #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTable) ){ - db->nSchemaLock++; - rc = sqlite3VtabCallConnect(pParse, pTable); - db->nSchemaLock--; - return rc; + if( sqlite3VtabCallConnect(pParse, pTable) ){ + return SQLITE_ERROR; } + if( IsVirtual(pTable) ) return 0; #endif #ifndef SQLITE_OMIT_VIEW /* A positive nCol means the columns names for this view are - ** already known. This routine is not called unless either the - ** table is virtual or nCol is zero. + ** already known. */ - assert( pTable->nCol<=0 ); + if( pTable->nCol>0 ) return 0; /* A negative nCol is a special marker meaning that we are currently ** trying to compute the column names. If we enter this routine with ** a negative nCol, it means two or more views form a loop, like this: ** @@ -125211,11 +102533,11 @@ ** CREATE VIEW two AS SELECT * FROM one; ** ** Actually, the error above is now caught prior to reaching this point. ** But the following test is still important as it does come up ** in the following: - ** + ** ** CREATE TABLE main.ex1(a); ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1; ** SELECT * FROM temp.ex1; */ if( pTable->nCol<0 ){ @@ -125229,79 +102551,64 @@ ** "*" elements in the results set of the view and will assign cursors ** to the elements of the FROM clause. But we do not want these changes ** to be permanent. So the computation is done on a copy of the SELECT ** statement that defines the view. */ - assert( IsView(pTable) ); - pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0); + assert( pTable->pSelect ); + pSel = sqlite3SelectDup(db, pTable->pSelect, 0); if( pSel ){ - u8 eParseMode = pParse->eParseMode; - int nTab = pParse->nTab; - int nSelect = pParse->nSelect; - pParse->eParseMode = PARSE_MODE_NORMAL; + n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; - DisableLookaside; + db->lookaside.bDisable++; #ifndef SQLITE_OMIT_AUTHORIZATION xAuth = db->xAuth; db->xAuth = 0; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); db->xAuth = xAuth; #else - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); #endif - pParse->nTab = nTab; - pParse->nSelect = nSelect; - if( pSelTab==0 ){ - pTable->nCol = 0; - nErr++; - }else if( pTable->pCheck ){ + pParse->nTab = n; + if( pTable->pCheck ){ /* CREATE VIEW name(arglist) AS ... ** The names of the columns in the table are taken from ** arglist which is stored in pTable->pCheck. The pCheck field ** normally holds CHECK constraints on an ordinary table, but for ** a VIEW it holds the list of column names. */ - sqlite3ColumnsFromExprList(pParse, pTable->pCheck, + sqlite3ColumnsFromExprList(pParse, pTable->pCheck, &pTable->nCol, &pTable->aCol); - if( pParse->nErr==0 + if( db->mallocFailed==0 + && pParse->nErr==0 && pTable->nCol==pSel->pEList->nExpr ){ - assert( db->mallocFailed==0 ); - sqlite3SubqueryColumnTypes(pParse, pTable, pSel, SQLITE_AFF_NONE); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel); } - }else{ + }else if( pSelTab ){ /* CREATE VIEW name AS... without an argument list. Construct ** the column names from the SELECT statement that defines the view. */ assert( pTable->aCol==0 ); pTable->nCol = pSelTab->nCol; pTable->aCol = pSelTab->aCol; - pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT); pSelTab->nCol = 0; pSelTab->aCol = 0; assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); + }else{ + pTable->nCol = 0; + nErr++; } - pTable->nNVCol = pTable->nCol; sqlite3DeleteTable(db, pSelTab); sqlite3SelectDelete(db, pSel); - EnableLookaside; - pParse->eParseMode = eParseMode; + db->lookaside.bDisable--; } else { nErr++; } pTable->pSchema->schemaFlags |= DB_UnresetViews; - if( db->mallocFailed ){ - sqlite3DeleteColumnNames(db, pTable); - } #endif /* SQLITE_OMIT_VIEW */ - return nErr + pParse->nErr; -} -SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ - assert( pTable!=0 ); - if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0; - return viewGetColumnNames(pParse, pTable); + return nErr; } #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ #ifndef SQLITE_OMIT_VIEW /* @@ -125311,12 +102618,14 @@ HashElem *i; assert( sqlite3SchemaMutexHeld(db, idx, 0) ); if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); - if( IsView(pTab) ){ + if( pTab->pSelect ){ sqlite3DeleteColumnNames(db, pTab); + pTab->aCol = 0; + pTab->nCol = 0; } } DbClearProperty(db, idx, DB_UnresetViews); } #else @@ -125331,19 +102640,19 @@ ** ** Ticket #1728: The symbol table might still contain information ** on tables and/or indices that are the process of being deleted. ** If you are unlucky, one of those deleted indices or tables might ** have the same rootpage number as the real table or index that is -** being moved. So we cannot stop searching after the first match +** being moved. So we cannot stop searching after the first match ** because the first match might be for one of the deleted indices ** or tables and not the table/index that is actually being moved. ** We must continue looping until all tables and indices with ** rootpage==iFrom have been converted to have a rootpage of iTo ** in order to be certain that we got the right one. */ #ifndef SQLITE_OMIT_AUTOVACUUM -SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3 *db, int iDb, Pgno iFrom, Pgno iTo){ +SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){ HashElem *pElem; Hash *pHash; Db *pDb; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); @@ -125365,73 +102674,80 @@ } #endif /* ** Write code to erase the table with root-page iTable from database iDb. -** Also write code to modify the sqlite_schema table and internal schema +** Also write code to modify the sqlite_master table and internal schema ** if a root-page of another table is moved by the btree-layer whilst ** erasing iTable (this can happen with an auto-vacuum database). -*/ +*/ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ Vdbe *v = sqlite3GetVdbe(pParse); int r1 = sqlite3GetTempReg(pParse); - if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema"); + assert( iTable>1 ); sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); sqlite3MayAbort(pParse); #ifndef SQLITE_OMIT_AUTOVACUUM /* OP_Destroy stores an in integer r1. If this integer ** is non-zero, then it is the root page number of a table moved to - ** location iTable. The following code modifies the sqlite_schema table to + ** location iTable. The following code modifies the sqlite_master table to ** reflect this. ** ** The "#NNN" in the SQL is a special constant that means whatever value ** is in register NNN. See grammar rules associated with the TK_REGISTER ** token for additional information. */ - sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE - " SET rootpage=%d WHERE #%d AND rootpage=#%d", - pParse->db->aDb[iDb].zDbSName, iTable, r1, r1); + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", + pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1); #endif sqlite3ReleaseTempReg(pParse, r1); } /* ** Write VDBE code to erase table pTab and all associated indices on disk. -** Code to update the sqlite_schema tables and internal schema definitions +** Code to update the sqlite_master tables and internal schema definitions ** in case a root-page belonging to another table is moved by the btree layer ** 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 + ** table and index root-pages in order, starting with the numerically ** largest root-page number. This guarantees that none of the root-pages ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the ** following were coded: ** ** OP_Destroy 4 0 ** ... ** OP_Destroy 5 0 ** ** and root page 5 happened to be the largest root-page number in the - ** database, then root page 5 would be moved to page 4 by the + ** database, then root page 5 would be moved to page 4 by the ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit ** a free-list page. */ - Pgno iTab = pTab->tnum; - Pgno iDestroyed = 0; + int iTab = pTab->tnum; + int iDestroyed = 0; while( 1 ){ Index *pIdx; - Pgno iLargest = 0; + int iLargest = 0; if( iDestroyed==0 || iTabpIndex; pIdx; pIdx=pIdx->pNext){ - Pgno iIdx = pIdx->tnum; + int iIdx = pIdx->tnum; assert( pIdx->pSchema==pTab->pSchema ); if( (iDestroyed==0 || (iIdxiLargest ){ iLargest = iIdx; } } @@ -125442,10 +102758,11 @@ assert( iDb>=0 && iDbdb->nDb ); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } +#endif } /* ** Remove entries from the sqlite_statN tables (for N in (1,2,3)) ** after a DROP INDEX or DROP TABLE command. @@ -125488,16 +102805,16 @@ sqlite3VdbeAddOp0(v, OP_VBegin); } #endif /* Drop all triggers associated with the table being dropped. Code - ** is generated to remove entries from sqlite_schema and/or - ** sqlite_temp_schema if required. + ** is generated to remove entries from sqlite_master and/or + ** sqlite_temp_master if required. */ pTrigger = sqlite3TriggerList(pParse, pTab); while( pTrigger ){ - assert( pTrigger->pSchema==pTab->pSchema || + assert( pTrigger->pSchema==pTab->pSchema || pTrigger->pSchema==db->aDb[1].pSchema ); sqlite3DropTriggerPtr(pParse, pTrigger); pTrigger = pTrigger->pNext; } @@ -125513,72 +102830,35 @@ pDb->zDbSName, pTab->zName ); } #endif - /* Drop all entries in the schema table that refer to the - ** table. The program name loops through the schema table and deletes + /* Drop all SQLITE_MASTER table and index entries that refer to the + ** table. The program name loops through the master table and deletes ** every row that refers to a table of the same name as the one being ** dropped. Triggers are handled separately because a trigger can be ** created in the temp database that refers to a table in another ** database. */ - sqlite3NestedParse(pParse, - "DELETE FROM %Q." LEGACY_SCHEMA_TABLE - " WHERE tbl_name=%Q and type!='trigger'", - pDb->zDbSName, pTab->zName); + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", + pDb->zDbSName, MASTER_NAME, pTab->zName); if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } /* Remove the table entry from SQLite's internal schema and modify ** the schema cookie. */ if( IsVirtual(pTab) ){ sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0); - sqlite3MayAbort(pParse); } sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); sqlite3ChangeCookie(pParse, iDb); sqliteViewResetAll(db, iDb); } -/* -** Return TRUE if shadow tables should be read-only in the current -** context. -*/ -SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (db->flags & SQLITE_Defensive)!=0 - && db->pVtabCtx==0 - && db->nVdbeExec==0 - && !sqlite3VtabInSync(db) - ){ - return 1; - } -#endif - return 0; -} - -/* -** Return true if it is not allowed to drop the given table -*/ -static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){ - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ - if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0; - if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0; - return 1; - } - if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){ - return 1; - } - if( pTab->tabFlags & TF_Eponymous ){ - return 1; - } - return 0; -} - /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ @@ -125590,23 +102870,18 @@ if( db->mallocFailed ){ goto exit_drop_table; } assert( pParse->nErr==0 ); assert( pName->nSrc==1 ); - assert( pName->a[0].fg.fixedSchema==0 ); - assert( pName->a[0].fg.isSubquery==0 ); if( sqlite3ReadSchema(pParse) ) goto exit_drop_table; if( noErr ) db->suppressErr++; assert( isView==0 || isView==LOCATE_VIEW ); pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; if( pTab==0 ){ - if( noErr ){ - sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase); - sqlite3ForceNotReadOnly(pParse); - } + if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); goto exit_drop_table; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 && iDbnDb ); @@ -125649,39 +102924,38 @@ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto exit_drop_table; } } #endif - if( tableMayNotBeDropped(db, pTab) ){ + if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 + && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); goto exit_drop_table; } #ifndef SQLITE_OMIT_VIEW /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used ** on a table. */ - if( isView && !IsView(pTab) ){ + if( isView && pTab->pSelect==0 ){ sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); goto exit_drop_table; } - if( !isView && IsView(pTab) ){ + if( !isView && pTab->pSelect ){ sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); goto exit_drop_table; } #endif - /* Generate code to remove the table from the schema table + /* Generate code to remove the table from the master table ** on disk. */ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3BeginWriteOperation(pParse, 1, iDb); - if( !isView ){ - sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); - sqlite3FkDropTable(pParse, pName, pTab); - } + sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); + sqlite3FkDropTable(pParse, pName, pTab); sqlite3CodeDropTable(pParse, pTab, iDb, isView); } exit_drop_table: sqlite3SrcListDelete(db, pName); @@ -125713,11 +102987,11 @@ sqlite3 *db = pParse->db; #ifndef SQLITE_OMIT_FOREIGN_KEY FKey *pFKey = 0; FKey *pNextTo; Table *p = pParse->pNewTable; - i64 nByte; + int nByte; int i; int nCol; char *z; assert( pTo!=0 ); @@ -125726,11 +103000,11 @@ int iCol = p->nCol-1; if( NEVER(iCol<0) ) goto fk_end; if( pToCol && pToCol->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "foreign key on %s" " should reference only one column of table %T", - p->aCol[iCol].zCnName, pTo); + p->aCol[iCol].zName, pTo); goto fk_end; } nCol = 1; }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ sqlite3ErrorMsg(pParse, @@ -125741,25 +103015,21 @@ nCol = pFromCol->nExpr; } nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1; if( pToCol ){ for(i=0; inExpr; i++){ - nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1; + nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1; } } pFKey = sqlite3DbMallocZero(db, nByte ); if( pFKey==0 ){ goto fk_end; } pFKey->pFrom = p; - assert( IsOrdinaryTable(p) ); - pFKey->pNextFrom = p->u.tab.pFKey; + pFKey->pNextFrom = p->pFKey; z = (char*)&pFKey->aCol[nCol]; pFKey->zTo = z; - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)z, pTo); - } memcpy(z, pTo->z, pTo->n); z[pTo->n] = 0; sqlite3Dequote(z); z += pTo->n+1; pFKey->nCol = nCol; @@ -125767,44 +103037,38 @@ pFKey->aCol[0].iFrom = p->nCol-1; }else{ for(i=0; inCol; j++){ - if( sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){ + if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ pFKey->aCol[i].iFrom = j; break; } } if( j>=p->nCol ){ - sqlite3ErrorMsg(pParse, - "unknown column \"%s\" in foreign key definition", - pFromCol->a[i].zEName); + sqlite3ErrorMsg(pParse, + "unknown column \"%s\" in foreign key definition", + pFromCol->a[i].zName); goto fk_end; } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName); - } } } if( pToCol ){ for(i=0; ia[i].zEName); + int n = sqlite3Strlen30(pToCol->a[i].zName); pFKey->aCol[i].zCol = z; - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName); - } - memcpy(z, pToCol->a[i].zEName, n); + memcpy(z, pToCol->a[i].zName, n); z[n] = 0; z += n+1; } } pFKey->isDeferred = 0; pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */ pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */ assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); - pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, + pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, pFKey->zTo, (void *)pFKey ); if( pNextTo==pFKey ){ sqlite3OomFault(db); goto fk_end; @@ -125815,12 +103079,11 @@ pNextTo->pPrevTo = pFKey; } /* Link the foreign key to the table as the last step. */ - assert( IsOrdinaryTable(p) ); - p->u.tab.pFKey = pFKey; + p->pFKey = pFKey; pFKey = 0; fk_end: sqlite3DbFree(db, pFKey); #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ @@ -125837,13 +103100,11 @@ */ SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ #ifndef SQLITE_OMIT_FOREIGN_KEY Table *pTab; FKey *pFKey; - if( (pTab = pParse->pNewTable)==0 ) return; - if( NEVER(!IsOrdinaryTable(pTab)) ) return; - if( (pFKey = pTab->u.tab.pFKey)==0 ) return; + if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */ pFKey->isDeferred = (u8)isDeferred; #endif } @@ -125863,11 +103124,11 @@ int iTab = pParse->nTab++; /* Btree cursor used for pTab */ int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ int iSorter; /* Cursor opened by OpenSorter (if in use) */ int addr1; /* Address of top of loop */ int addr2; /* Address to jump to for next iteration */ - Pgno tnum; /* Root page of index */ + int tnum; /* Root page of index */ int iPartIdxLabel; /* Jump to this label to skip a row */ Vdbe *v; /* Generate code into this virtual machine */ KeyInfo *pKey; /* KeyInfo for index */ int regRecord; /* Register holding assembled index record */ sqlite3 *db = pParse->db; /* The database connection */ @@ -125884,16 +103145,16 @@ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); v = sqlite3GetVdbe(pParse); if( v==0 ) return; if( memRootPage>=0 ){ - tnum = (Pgno)memRootPage; + tnum = memRootPage; }else{ tnum = pIndex->tnum; } pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); - assert( pKey!=0 || pParse->nErr ); + assert( pKey!=0 || db->mallocFailed || pParse->nErr ); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*) sqlite3KeyInfoRef(pKey), P4_KEYINFO); @@ -125901,53 +103162,34 @@ /* Open the table. Loop through all rows of the table, inserting index ** records into the sorter. */ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); regRecord = sqlite3GetTempReg(pParse); - sqlite3MultiWrite(pParse); sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); - sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, (int)tnum, iDb, + sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); if( IsUniqueIndex(pIndex) ){ - int j2 = sqlite3VdbeGoto(v, 1); + int j2 = sqlite3VdbeCurrentAddr(v) + 3; + sqlite3VdbeGoto(v, j2); addr2 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeVerifyAbortable(v, OE_Abort); sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); - sqlite3VdbeJumpHere(v, j2); }else{ - /* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not - ** abort. The exception is if one of the indexed expressions contains a - ** user function that throws an exception when it is evaluated. But the - ** overhead of adding a statement journal to a CREATE INDEX statement is - ** very small (since most of the pages written do not contain content that - ** needs to be restored if the statement aborts), so we call - ** sqlite3MayAbort() for all CREATE INDEX statements. */ - sqlite3MayAbort(pParse); addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - if( !pIndex->bAscKeyBug ){ - /* This OP_SeekEnd opcode makes index insert for a REINDEX go much - ** faster by avoiding unnecessary seeks. But the optimization does - ** not work for UNIQUE constraint indexes on WITHOUT ROWID tables - ** with DESC primary keys, since those indexes have there keys in - ** a different order from the main table. - ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf - */ - sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); - } + sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); @@ -125991,41 +103233,20 @@ } return p; } /* -** If expression list pList contains an expression that was parsed with -** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in -** pParse and return non-zero. Otherwise, return zero. -*/ -SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){ - if( pList ){ - int i; - for(i=0; inExpr; i++){ - if( pList->a[i].fg.bNulls ){ - u8 sf = pList->a[i].fg.sortFlags; - sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", - (sf==0 || sf==3) ? "FIRST" : "LAST" - ); - return 1; - } - } - } - return 0; -} - -/* -** Create a new index for an SQL table. pName1.pName2 is the name of the index -** and pTblList is the name of the table that is to be indexed. Both will +** Create a new index for an SQL table. pName1.pName2 is the name of the index +** and pTblList is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable ** as the table to be indexed. pParse->pNewTable is a table that is ** currently being constructed by a CREATE TABLE statement. ** ** pList is a list of columns to be indexed. pList will be NULL if this ** is a primary key or unique-constraint on the most recent column added -** to the table currently under construction. +** to the table currently under construction. */ SQLITE_PRIVATE void sqlite3CreateIndex( Parse *pParse, /* All information about this parse */ Token *pName1, /* First part of index name. May be NULL */ Token *pName2, /* Second part of index name. May be NULL */ @@ -126053,31 +103274,26 @@ int nExtra = 0; /* Space allocated for zExtra[] */ int nExtraCol; /* Number of extra columns needed */ char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - assert( db->pParse==pParse ); - if( pParse->nErr ){ + if( db->mallocFailed || pParse->nErr>0 ){ goto exit_create_index; } - assert( db->mallocFailed==0 ); if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } - if( sqlite3HasExplicitNulls(pParse, pList) ){ - goto exit_create_index; - } /* ** Find the table that is to be indexed. Return early if not found. */ if( pTblName!=0 ){ - /* Use the two-part index name to determine the database + /* Use the two-part index name to determine the database ** to search for the table. 'Fix' the table name to this db ** before looking up the table. */ assert( pName1 && pName2 ); iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); @@ -126085,11 +103301,11 @@ assert( pName && pName->z ); #ifndef SQLITE_OMIT_TEMPDB /* If the index name was unqualified, check if the table ** is a temp table. If so, set the database to 1. Do not do this - ** if initializing a database schema. + ** if initialising a database schema. */ if( !db->init.busy ){ pTab = sqlite3SrcListLookup(pParse, pTblName); if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; @@ -126105,11 +103321,11 @@ } pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); assert( db->mallocFailed==0 || pTab==0 ); if( pTab==0 ) goto exit_create_index; if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "cannot create a TEMP index on non-TEMP table \"%s\"", pTab->zName); goto exit_create_index; } if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab); @@ -126121,19 +103337,22 @@ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 + assert( pParse->nErr==0 ); + if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && db->init.busy==0 - && pTblName!=0 - ){ +#if SQLITE_USER_AUTHENTICATION + && sqlite3UserAuthTable(pTab->zName)==0 +#endif + && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } #ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) ){ + if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -126143,14 +103362,14 @@ } #endif /* ** Find the name of the index. Make sure there is not already another - ** index or table with the same name. + ** index or table with the same name. ** ** Exception: If we are reading the names of permanent indices from the - ** sqlite_schema table (because some other process changed the schema) and + ** sqlite_master table (because some other process changed the schema) and ** one of the index names collides with the name of a temporary table or ** index, then we will continue to process this index. ** ** If pName==0 it means that we are ** dealing with a primary key or UNIQUE constraint. We have to invent our @@ -126158,30 +103377,27 @@ */ if( pName ){ zName = sqlite3NameFromToken(db, pName); if( zName==0 ) goto exit_create_index; assert( pName->z!=0 ); - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){ - goto exit_create_index; - } - if( !IN_RENAME_OBJECT ){ - if( !db->init.busy ){ - if( sqlite3FindTable(db, zName, pDb->zDbSName)!=0 ){ - sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); - goto exit_create_index; - } - } - if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ - if( !ifNotExist ){ - sqlite3ErrorMsg(pParse, "index %s already exists", zName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3ForceNotReadOnly(pParse); - } - goto exit_create_index; - } + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_create_index; + } + if( !db->init.busy ){ + if( sqlite3FindTable(db, zName, 0)!=0 ){ + sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); + goto exit_create_index; + } + } + if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + }else{ + assert( !db->init.busy ); + sqlite3CodeVerifySchema(pParse, iDb); + } + goto exit_create_index; } }else{ int n; Index *pLoop; for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} @@ -126193,17 +103409,17 @@ /* Automatic index names generated from within sqlite3_declare_vtab() ** must have names that are distinct from normal automatic index names. ** The following statement converts "sqlite3_autoindex..." into ** "sqlite3_butoindex..." in order to make the names distinct. ** The "vtab_err.test" test demonstrates the need of this statement. */ - if( IN_SPECIAL_PARSE ) zName[7]++; + if( IN_DECLARE_VTAB ) zName[7]++; } /* Check for authorization to create an index. */ #ifndef SQLITE_OMIT_AUTHORIZATION - if( !IN_RENAME_OBJECT ){ + { const char *zDb = pDb->zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } i = SQLITE_CREATE_INDEX; @@ -126218,41 +103434,36 @@ ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ Token prevCol; - Column *pCol = &pTab->aCol[pTab->nCol-1]; - pCol->colFlags |= COLFLAG_UNIQUE; - sqlite3TokenInit(&prevCol, pCol->zCnName); + sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; assert( pList->nExpr==1 ); - sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED); + sqlite3ExprListSetSortOrder(pList, sortOrder); }else{ sqlite3ExprListCheckLength(pParse, pList, "index"); - if( pParse->nErr ) goto exit_create_index; } /* Figure out how many bytes of space are required to store explicitly ** specified collation sequence names. */ for(i=0; inExpr; i++){ Expr *pExpr = pList->a[i].pExpr; assert( pExpr!=0 ); if( pExpr->op==TK_COLLATE ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken)); } } - /* - ** Allocate the index structure. + /* + ** Allocate the index structure. */ nName = sqlite3Strlen30(zName); nExtraCol = pPk ? pPk->nKeyCol : 1; - assert( pList->nExpr + nExtraCol <= 32767 /* Fits in i16 */ ); pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol, nName + nExtra + 1, &zExtra); if( db->mallocFailed ){ goto exit_create_index; } @@ -126289,16 +103500,11 @@ ** ** TODO: Issue a warning if two or more columns of the index are identical. ** TODO: Issue a warning if the table primary key is used as part of the ** index key. */ - pListItem = pList->a; - if( IN_RENAME_OBJECT ){ - pIndex->aColExpr = pList; - pList = 0; - } - for(i=0; inKeyCol; i++, pListItem++){ + for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ Expr *pCExpr; /* The i-th index expression */ int requestedSortOrder; /* ASC or DESC on the i-th expression */ const char *zColl; /* Collation sequence name */ sqlite3StringToId(pListItem->pExpr); @@ -126310,53 +103516,49 @@ sqlite3ErrorMsg(pParse, "expressions prohibited in PRIMARY KEY and " "UNIQUE constraints"); goto exit_create_index; } if( pIndex->aColExpr==0 ){ - pIndex->aColExpr = pList; - pList = 0; + ExprList *pCopy = sqlite3ExprListDup(db, pList, 0); + pIndex->aColExpr = pCopy; + if( !db->mallocFailed ){ + assert( pCopy!=0 ); + pListItem = &pCopy->a[i]; + } } j = XN_EXPR; pIndex->aiColumn[i] = XN_EXPR; pIndex->uniqNotNull = 0; - pIndex->bHasExpr = 1; }else{ j = pCExpr->iColumn; assert( j<=0x7fff ); if( j<0 ){ j = pTab->iPKey; - }else{ - if( pTab->aCol[j].notNull==0 ){ - pIndex->uniqNotNull = 0; - } - if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){ - pIndex->bHasVCol = 1; - pIndex->bHasExpr = 1; - } + }else if( pTab->aCol[j].notNull==0 ){ + pIndex->uniqNotNull = 0; } pIndex->aiColumn[i] = (i16)j; } zColl = 0; if( pListItem->pExpr->op==TK_COLLATE ){ int nColl; - assert( !ExprHasProperty(pListItem->pExpr, EP_IntValue) ); zColl = pListItem->pExpr->u.zToken; nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); memcpy(zExtra, zColl, nColl); zColl = zExtra; zExtra += nColl; nExtra -= nColl; }else if( j>=0 ){ - zColl = sqlite3ColumnColl(&pTab->aCol[j]); + zColl = pTab->aCol[j].zColl; } if( !zColl ) zColl = sqlite3StrBINARY; if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ goto exit_create_index; } pIndex->azColl[i] = zColl; - requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask; + requestedSortOrder = pListItem->sortOrder & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; } /* Append the table key to the end of the index. For WITHOUT ROWID ** tables (when pPk!=0) this will be the declared PRIMARY KEY. For @@ -126364,14 +103566,13 @@ */ if( pPk ){ for(j=0; jnKeyCol; j++){ int x = pPk->aiColumn[j]; assert( x>=0 ); - if( isDupColumn(pIndex, pIndex->nKeyCol, pPk, j) ){ - pIndex->nColumn--; + if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){ + pIndex->nColumn--; }else{ - testcase( hasColumn(pIndex->aiColumn,pIndex->nKeyCol,x) ); pIndex->aiColumn[i] = x; pIndex->azColl[i] = pPk->azColl[j]; pIndex->aSortOrder[i] = pPk->aSortOrder[j]; i++; } @@ -126384,18 +103585,17 @@ sqlite3DefaultRowEst(pIndex); if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); /* If this index contains every column of its table, then mark ** it as a covering index */ - assert( HasRowid(pTab) - || pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 ); - recomputeColumnsNotIndexed(pIndex); + assert( HasRowid(pTab) + || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 ); if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ pIndex->isCovering = 1; for(j=0; jnCol; j++){ if( j==pTab->iPKey ) continue; - if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue; + if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue; pIndex->isCovering = 0; break; } } @@ -126440,179 +103640,148 @@ } if( k==pIdx->nKeyCol ){ if( pIdx->onError!=pIndex->onError ){ /* This constraint creates the same index as a previous ** constraint specified somewhere in the CREATE TABLE statement. - ** However the ON CONFLICT clauses are different. If both this + ** However the ON CONFLICT clauses are different. If both this ** constraint and the previous equivalent constraint have explicit ** ON CONFLICT clauses this is an error. Otherwise, use the ** explicitly specified behavior for the index. */ if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "conflicting ON CONFLICT clauses specified", 0); } if( pIdx->onError==OE_Default ){ pIdx->onError = pIndex->onError; } } if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType; - if( IN_RENAME_OBJECT ){ - pIndex->pNext = pParse->pNewIndex; - pParse->pNewIndex = pIndex; - pIndex = 0; - } - goto exit_create_index; - } - } - } - - if( !IN_RENAME_OBJECT ){ - - /* Link the new Index structure to its table and to the other - ** in-memory database structures. - */ - assert( pParse->nErr==0 ); - if( db->init.busy ){ - Index *p; - assert( !IN_SPECIAL_PARSE ); - assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); - if( pTblName!=0 ){ - pIndex->tnum = db->init.newTnum; - if( sqlite3IndexHasDuplicateRootPage(pIndex) ){ - sqlite3ErrorMsg(pParse, "invalid rootpage"); - pParse->rc = SQLITE_CORRUPT_BKPT; - goto exit_create_index; - } - } - p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, pIndex); - if( p ){ - assert( p==pIndex ); /* Malloc must have failed */ - sqlite3OomFault(db); - goto exit_create_index; - } - db->mDbFlags |= DBFLAG_SchemaChange; - } - - /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the - ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then - ** emit code to allocate the index rootpage on disk and make an entry for - ** the index in the sqlite_schema table and populate the index with - ** content. But, do not do this if we are simply reading the sqlite_schema - ** table to parse the schema, or if this index is the PRIMARY KEY index - ** of a WITHOUT ROWID table. - ** - ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY - ** or UNIQUE index in a CREATE TABLE statement. Since the table - ** has just been created, it contains no data and the index initialization - ** step can be skipped. - */ - else if( HasRowid(pTab) || pTblName!=0 ){ - Vdbe *v; - char *zStmt; - int iMem = ++pParse->nMem; - - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto exit_create_index; - - sqlite3BeginWriteOperation(pParse, 1, iDb); - - /* Create the rootpage for the index using CreateIndex. But before - ** doing so, code a Noop instruction and store its address in - ** Index.tnum. This is required in case this index is actually a - ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In - ** that case the convertToWithoutRowidTable() routine will replace - ** the Noop with a Goto to jump over the VDBE code generated below. */ - pIndex->tnum = (Pgno)sqlite3VdbeAddOp0(v, OP_Noop); - sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY); - - /* Gather the complete text of the CREATE INDEX statement into - ** the zStmt variable - */ - assert( pName!=0 || pStart==0 ); - if( pStart ){ - int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; - if( pName->z[n-1]==';' ) n--; - /* A named index with an explicit CREATE INDEX statement */ - zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", - onError==OE_None ? "" : " UNIQUE", n, pName->z); - }else{ - /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ - /* zStmt = sqlite3MPrintf(""); */ - zStmt = 0; - } - - /* Add an entry in sqlite_schema for this index - */ - sqlite3NestedParse(pParse, - "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zDbSName, - pIndex->zName, - pTab->zName, - iMem, - zStmt - ); - sqlite3DbFree(db, zStmt); - - /* Fill the index with data and reparse the schema. Code an OP_Expire - ** to invalidate all pre-compiled statements. - */ - if( pTblName ){ - sqlite3RefillIndex(pParse, pIndex, iMem); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0); - sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); - } - - sqlite3VdbeJumpHere(v, (int)pIndex->tnum); - } - } - if( db->init.busy || pTblName==0 ){ - pIndex->pNext = pTab->pIndex; - pTab->pIndex = pIndex; - pIndex = 0; - } - else if( IN_RENAME_OBJECT ){ - assert( pParse->pNewIndex==0 ); - pParse->pNewIndex = pIndex; + goto exit_create_index; + } + } + } + + /* Link the new Index structure to its table and to the other + ** in-memory database structures. + */ + assert( pParse->nErr==0 ); + if( db->init.busy ){ + Index *p; + assert( !IN_DECLARE_VTAB ); + assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); + p = sqlite3HashInsert(&pIndex->pSchema->idxHash, + pIndex->zName, pIndex); + if( p ){ + assert( p==pIndex ); /* Malloc must have failed */ + sqlite3OomFault(db); + goto exit_create_index; + } + db->flags |= SQLITE_InternChanges; + if( pTblName!=0 ){ + pIndex->tnum = db->init.newTnum; + } + } + + /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the + ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then + ** emit code to allocate the index rootpage on disk and make an entry for + ** the index in the sqlite_master table and populate the index with + ** content. But, do not do this if we are simply reading the sqlite_master + ** table to parse the schema, or if this index is the PRIMARY KEY index + ** of a WITHOUT ROWID table. + ** + ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY + ** or UNIQUE index in a CREATE TABLE statement. Since the table + ** has just been created, it contains no data and the index initialization + ** step can be skipped. + */ + else if( HasRowid(pTab) || pTblName!=0 ){ + Vdbe *v; + char *zStmt; + int iMem = ++pParse->nMem; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto exit_create_index; + + sqlite3BeginWriteOperation(pParse, 1, iDb); + + /* Create the rootpage for the index using CreateIndex. But before + ** doing so, code a Noop instruction and store its address in + ** Index.tnum. This is required in case this index is actually a + ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In + ** 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); + + /* Gather the complete text of the CREATE INDEX statement into + ** the zStmt variable + */ + if( pStart ){ + int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; + if( pName->z[n-1]==';' ) n--; + /* A named index with an explicit CREATE INDEX statement */ + zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", + onError==OE_None ? "" : " UNIQUE", n, pName->z); + }else{ + /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ + /* zStmt = sqlite3MPrintf(""); */ + zStmt = 0; + } + + /* Add an entry in sqlite_master for this index + */ + sqlite3NestedParse(pParse, + "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", + db->aDb[iDb].zDbSName, MASTER_NAME, + pIndex->zName, + pTab->zName, + iMem, + zStmt + ); + sqlite3DbFree(db, zStmt); + + /* Fill the index with data and reparse the schema. Code an OP_Expire + ** to invalidate all pre-compiled statements. + */ + if( pTblName ){ + sqlite3RefillIndex(pParse, pIndex, iMem); + sqlite3ChangeCookie(pParse, iDb); + sqlite3VdbeAddParseSchemaOp(v, iDb, + sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); + sqlite3VdbeAddOp0(v, OP_Expire); + } + + sqlite3VdbeJumpHere(v, pIndex->tnum); + } + + /* When adding an index to the list of indices for a table, make + ** sure all indices labeled OE_Replace come after all those labeled + ** OE_Ignore. This is necessary for the correct constraint check + ** processing (in sqlite3GenerateConstraintChecks()) as part of + ** UPDATE and INSERT statements. + */ + if( db->init.busy || pTblName==0 ){ + if( onError!=OE_Replace || pTab->pIndex==0 + || pTab->pIndex->onError==OE_Replace){ + pIndex->pNext = pTab->pIndex; + pTab->pIndex = pIndex; + }else{ + Index *pOther = pTab->pIndex; + while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ + pOther = pOther->pNext; + } + pIndex->pNext = pOther->pNext; + pOther->pNext = pIndex; + } pIndex = 0; } /* Clean up before exiting */ exit_create_index: - if( pIndex ) sqlite3FreeIndex(db, pIndex); - if( pTab ){ - /* Ensure all REPLACE indexes on pTab are at the end of the pIndex list. - ** The list was already ordered when this routine was entered, so at this - ** point at most a single index (the newly added index) will be out of - ** order. So we have to reorder at most one index. */ - Index **ppFrom; - Index *pThis; - for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){ - Index *pNext; - if( pThis->onError!=OE_Replace ) continue; - while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){ - *ppFrom = pNext; - pThis->pNext = pNext->pNext; - pNext->pNext = pThis; - ppFrom = &pNext->pNext; - } - break; - } -#ifdef SQLITE_DEBUG - /* Verify that all REPLACE indexes really are now at the end - ** of the index list. In other words, no other index type ever - ** comes after a REPLACE index on the list. */ - for(pThis = pTab->pIndex; pThis; pThis=pThis->pNext){ - assert( pThis->onError!=OE_Replace - || pThis->pNext==0 - || pThis->pNext->onError==OE_Replace ); - } -#endif - } + if( pIndex ) freeIndex(db, pIndex); sqlite3ExprDelete(db, pPIWhere); sqlite3ExprListDelete(db, pList); sqlite3SrcListDelete(db, pTblName); sqlite3DbFree(db, zName); } @@ -126634,37 +103803,25 @@ ** Apart from that, we have little to go on besides intuition as to ** how aiRowEst[] should be initialized. The numbers generated here ** are based on typical values found in actual indices. */ SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ - /* 10, 9, 8, 7, 6 */ - static const LogEst aVal[] = { 33, 32, 30, 28, 26 }; + /* 10, 9, 8, 7, 6 */ + LogEst aVal[] = { 33, 32, 30, 28, 26 }; LogEst *a = pIdx->aiRowLogEst; - LogEst x; 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 + /* 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. - ** - ** 2020-05-27: If some of the stat data is coming from the sqlite_stat1 - ** table but other parts we are having to guess at, then do not let the - ** estimated number of rows in the table be less than 1000 (LogEst 99). - ** Failure to do this can cause the indexes for which we do not have - ** stat1 data to be ignored by the query planner. - */ - x = pIdx->pTable->nRowLogEst; - assert( 99==sqlite3LogEst(1000) ); - if( x<99 ){ - pIdx->pTable->nRowLogEst = x = 99; - } - if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==sqlite3LogEst(2) ); } - a[0] = x; + ** for a partial index. But do not let the estimate drop below 10. */ + a[0] = pIdx->pTable->nRowLogEst; + if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) ); + if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) ); /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is ** 6 and each subsequent value (if any) is 5. */ memcpy(&a[1], aVal, nCopy*sizeof(LogEst)); for(i=nCopy+1; i<=pIdx->nKeyCol; i++){ @@ -126683,27 +103840,24 @@ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; int iDb; + assert( pParse->nErr==0 ); /* Never called with prior errors */ if( db->mallocFailed ){ goto exit_drop_index; } - assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */ assert( pName->nSrc==1 ); - assert( pName->a[0].fg.fixedSchema==0 ); - assert( pName->a[0].fg.isSubquery==0 ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_drop_index; } - pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].u4.zDatabase); + pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ if( !ifExists ){ - sqlite3ErrorMsg(pParse, "no such index: %S", pName->a); + sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); }else{ - sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase); - sqlite3ForceNotReadOnly(pParse); + sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); } pParse->checkSchema = 1; goto exit_drop_index; } if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ @@ -126719,24 +103873,24 @@ const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } - if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX; + if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } } #endif - /* Generate code to remove the index and from the schema table */ + /* Generate code to remove the index and from the master table */ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3NestedParse(pParse, - "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='index'", - db->aDb[iDb].zDbSName, pIndex->zName + "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", + db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName ); sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); sqlite3ChangeCookie(pParse, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); @@ -126769,22 +103923,23 @@ int szEntry, /* Size of each object in the array */ int *pnEntry, /* Number of objects currently in use */ int *pIdx /* Write the index of a new slot here */ ){ char *z; - sqlite3_int64 n = *pIdx = *pnEntry; + int n = *pnEntry; if( (n & (n-1))==0 ){ - sqlite3_int64 sz = (n==0) ? 1 : 2*n; + int sz = (n==0) ? 1 : 2*n; void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry); if( pNew==0 ){ *pIdx = -1; return pArray; } pArray = pNew; } z = (char*)pArray; memset(&z[n * szEntry], 0, szEntry); + *pIdx = n; ++*pnEntry; return pArray; } /* @@ -126791,72 +103946,57 @@ ** Append a new element to the given IdList. Create a new IdList if ** need be. ** ** A new IdList is returned, or NULL if malloc() fails. */ -SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ - sqlite3 *db = pParse->db; +SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ int i; if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(IdList) ); if( pList==0 ) return 0; - }else{ - IdList *pNew; - pNew = sqlite3DbRealloc(db, pList, - sizeof(IdList) + pList->nId*sizeof(pList->a)); - if( pNew==0 ){ - sqlite3IdListDelete(db, pList); - return 0; - } - pList = pNew; - } - i = pList->nId++; - pList->a[i].zName = sqlite3NameFromToken(db, pToken); - if( IN_RENAME_OBJECT && pList->a[i].zName ){ - sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); - } + } + pList->a = sqlite3ArrayAllocate( + db, + pList->a, + sizeof(pList->a[0]), + &pList->nId, + &i + ); + if( i<0 ){ + sqlite3IdListDelete(db, pList); + return 0; + } + pList->a[i].zName = sqlite3NameFromToken(db, pToken); return pList; } /* ** Delete an IdList. */ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ int i; - assert( db!=0 ); if( pList==0 ) return; for(i=0; inId; i++){ sqlite3DbFree(db, pList->a[i].zName); } - sqlite3DbNNFreeNN(db, pList); + sqlite3DbFree(db, pList->a); + sqlite3DbFreeNN(db, pList); } /* ** Return the index in pList of the identifier named zId. Return -1 ** if not found. */ SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){ int i; - assert( pList!=0 ); + if( pList==0 ) return -1; for(i=0; inId; i++){ if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; } return -1; } -/* -** Maximum size of a SrcList object. -** The SrcList object is used to represent the FROM clause of a -** SELECT statement, and the query planner cannot deal with more -** than 64 tables in a join. So any value larger than 64 here -** is sufficient for most uses. Smaller values, like say 10, are -** appropriate for small and memory-limited applications. -*/ -#ifndef SQLITE_MAX_SRCLIST -# define SQLITE_MAX_SRCLIST 200 -#endif - /* ** Expand the space allocated for the given SrcList object by ** creating nExtra new slots beginning at iStart. iStart is zero based. ** New slots are zeroed. ** @@ -126869,16 +104009,15 @@ ** If the iStart argument had been 1 instead of 2, then the result ** would have been: A, nil, nil, nil, B. To prepend the new slots, ** the iStart value would be 0. The result then would ** be: nil, nil, nil, A, B. ** -** If a memory allocation fails or the SrcList becomes too large, leave -** the original SrcList unchanged, return NULL, and leave an error message -** in pParse. +** If a memory allocation fails the SrcList is unchanged. The +** db->mallocFailed flag will be set to true. */ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( - Parse *pParse, /* Parsing context into which errors are reported */ + sqlite3 *db, /* Database connection to notify of OOM errors */ SrcList *pSrc, /* The SrcList to be enlarged */ int nExtra, /* Number of new slots to add to pSrc->a[] */ int iStart /* Index in pSrc->a[] of first new slot */ ){ int i; @@ -126890,27 +104029,21 @@ assert( iStart<=pSrc->nSrc ); /* Allocate additional space if needed */ if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ SrcList *pNew; - sqlite3_int64 nAlloc = 2*(sqlite3_int64)pSrc->nSrc+nExtra; - sqlite3 *db = pParse->db; - - if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){ - sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d", - SQLITE_MAX_SRCLIST); - return 0; - } - if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST; + int nAlloc = pSrc->nSrc*2+nExtra; + int nGot; pNew = sqlite3DbRealloc(db, pSrc, sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) ); if( pNew==0 ){ assert( db->mallocFailed ); - return 0; + return pSrc; } pSrc = pNew; - pSrc->nAlloc = nAlloc; + nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1; + pSrc->nAlloc = nGot; } /* Move existing slots that come after the newly inserted slots ** out of the way */ for(i=pSrc->nSrc-1; i>=iStart; i--){ @@ -126931,21 +104064,20 @@ /* ** Append a new table name to the given SrcList. Create a new SrcList if ** need be. A new entry is created in the SrcList even if pTable is NULL. ** -** A SrcList is returned, or NULL if there is an OOM error or if the -** SrcList grows to large. The returned +** A SrcList is returned, or NULL if there is an OOM error. The returned ** SrcList might be the same as the SrcList that was input or it might be ** a new one. If an OOM error does occurs, then the prior value of pList ** that is input to this routine is automatically freed. ** ** If pDatabase is not null, it means that the table has an optional ** database name prefix. Like this: "database.table". The pDatabase ** points to the table name and the pTable points to the database name. ** The SrcList.a[].zName field is filled with the table name which might -** come from pTable (if pDatabase is NULL) or from pDatabase. +** come from pTable (if pDatabase is NULL) or from pDatabase. ** SrcList.a[].zDatabase is filled with the database name from pTable, ** or with NULL if no database is specified. ** ** In other words, if call like this: ** @@ -126963,181 +104095,84 @@ ** ** Both pTable and pDatabase are assumed to be quoted. They are dequoted ** before being added to the SrcList. */ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( - Parse *pParse, /* Parsing context, in which errors are reported */ + sqlite3 *db, /* Connection to notify of malloc failures */ SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */ Token *pTable, /* Table to append */ Token *pDatabase /* Database of the table */ ){ - SrcItem *pItem; - sqlite3 *db; + struct SrcList_item *pItem; assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ - assert( pParse!=0 ); - assert( pParse->db!=0 ); - db = pParse->db; + assert( db!=0 ); if( pList==0 ){ - pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) ); + pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; pList->nSrc = 1; memset(&pList->a[0], 0, sizeof(pList->a[0])); pList->a[0].iCursor = -1; }else{ - SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc); - if( pNew==0 ){ - sqlite3SrcListDelete(db, pList); - return 0; - }else{ - pList = pNew; - } + pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); + } + if( db->mallocFailed ){ + sqlite3SrcListDelete(db, pList); + return 0; } pItem = &pList->a[pList->nSrc-1]; if( pDatabase && pDatabase->z==0 ){ pDatabase = 0; } - assert( pItem->fg.fixedSchema==0 ); - assert( pItem->fg.isSubquery==0 ); if( pDatabase ){ pItem->zName = sqlite3NameFromToken(db, pDatabase); - pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable); + pItem->zDatabase = sqlite3NameFromToken(db, pTable); }else{ pItem->zName = sqlite3NameFromToken(db, pTable); - pItem->u4.zDatabase = 0; + pItem->zDatabase = 0; } return pList; } /* ** Assign VdbeCursor index numbers to all tables in a SrcList */ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; - SrcItem *pItem; - assert( pList || pParse->db->mallocFailed ); - if( ALWAYS(pList) ){ + struct SrcList_item *pItem; + assert(pList || pParse->db->mallocFailed ); + if( pList ){ for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pItem->iCursor>=0 ) continue; + if( pItem->iCursor>=0 ) break; pItem->iCursor = pParse->nTab++; - if( pItem->fg.isSubquery ){ - assert( pItem->u4.pSubq!=0 ); - assert( pItem->u4.pSubq->pSelect!=0 ); - assert( pItem->u4.pSubq->pSelect->pSrc!=0 ); - sqlite3SrcListAssignCursors(pParse, pItem->u4.pSubq->pSelect->pSrc); - } - } - } -} - -/* -** Delete a Subquery object and its substructure. -*/ -SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3 *db, Subquery *pSubq){ - assert( pSubq!=0 && pSubq->pSelect!=0 ); - sqlite3SelectDelete(db, pSubq->pSelect); - sqlite3DbFree(db, pSubq); -} - -/* -** Remove a Subquery from a SrcItem. Return the associated Select object. -** The returned Select becomes the responsibility of the caller. -*/ -SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3 *db, SrcItem *pItem){ - Select *pSel; - assert( pItem!=0 ); - assert( pItem->fg.isSubquery ); - pSel = pItem->u4.pSubq->pSelect; - sqlite3DbFree(db, pItem->u4.pSubq); - pItem->u4.pSubq = 0; - pItem->fg.isSubquery = 0; - return pSel; + if( pItem->pSelect ){ + sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + } + } + } } /* ** Delete an entire SrcList including all its substructure. */ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ int i; - SrcItem *pItem; - assert( db!=0 ); + struct SrcList_item *pItem; if( pList==0 ) return; for(pItem=pList->a, i=0; inSrc; i++, pItem++){ - - /* Check invariants on SrcItem */ - assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc ); - assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy ); - assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery ); - assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 && - pItem->u4.pSubq->pSelect!=0) ); - - if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName); - if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias); - if( pItem->fg.isSubquery ){ - sqlite3SubqueryDelete(db, pItem->u4.pSubq); - }else if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){ - sqlite3DbNNFreeNN(db, pItem->u4.zDatabase); - } + sqlite3DbFree(db, pItem->zDatabase); + sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zAlias); if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy); if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg); - sqlite3DeleteTable(db, pItem->pSTab); - if( pItem->fg.isUsing ){ - sqlite3IdListDelete(db, pItem->u3.pUsing); - }else if( pItem->u3.pOn ){ - sqlite3ExprDelete(db, pItem->u3.pOn); - } - } - sqlite3DbNNFreeNN(db, pList); -} - -/* -** Attach a Subquery object to pItem->uv.pSubq. Set the -** pSelect value but leave all the other values initialized -** to zero. -** -** A copy of the Select object is made if dupSelect is true, and the -** SrcItem takes responsibility for deleting the copy. If dupSelect is -** false, ownership of the Select passes to the SrcItem. Either way, -** the SrcItem will take responsibility for deleting the Select. -** -** When dupSelect is zero, that means the Select might get deleted right -** away if there is an OOM error. Beware. -** -** Return non-zero on success. Return zero on an OOM error. -*/ -SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery( - Parse *pParse, /* Parsing context */ - SrcItem *pItem, /* Item to which the subquery is to be attached */ - Select *pSelect, /* The subquery SELECT. Must be non-NULL */ - int dupSelect /* If true, attach a copy of pSelect, not pSelect itself.*/ -){ - Subquery *p; - assert( pSelect!=0 ); - assert( pItem->fg.isSubquery==0 ); - if( pItem->fg.fixedSchema ){ - pItem->u4.pSchema = 0; - pItem->fg.fixedSchema = 0; - }else if( pItem->u4.zDatabase!=0 ){ - sqlite3DbFree(pParse->db, pItem->u4.zDatabase); - pItem->u4.zDatabase = 0; - } - if( dupSelect ){ - pSelect = sqlite3SelectDup(pParse->db, pSelect, 0); - if( pSelect==0 ) return 0; - } - p = pItem->u4.pSubq = sqlite3DbMallocRawNN(pParse->db, sizeof(Subquery)); - if( p==0 ){ - sqlite3SelectDelete(pParse->db, pSelect); - return 0; - } - pItem->fg.isSubquery = 1; - p->pSelect = pSelect; - assert( offsetof(Subquery, pSelect)==0 ); - memset(((char*)p)+sizeof(p->pSelect), 0, sizeof(*p)-sizeof(p->pSelect)); - return 1; -} - + sqlite3DeleteTable(db, pItem->pTab); + sqlite3SelectDelete(db, pItem->pSelect); + sqlite3ExprDelete(db, pItem->pOn); + sqlite3IdListDelete(db, pItem->pUsing); + } + sqlite3DbFreeNN(db, pList); +} /* ** This routine is called by the parser to add a new term to the ** end of a growing FROM clause. The "p" parameter is the part of ** the FROM clause that has already been constructed. "p" is NULL @@ -127158,116 +104193,72 @@ SrcList *p, /* The left part of the FROM clause already seen */ Token *pTable, /* Name of the table to add to the FROM clause */ Token *pDatabase, /* Name of the database containing pTable */ Token *pAlias, /* The right-hand side of the AS subexpression */ Select *pSubquery, /* A subquery used in place of a table name */ - OnOrUsing *pOnUsing /* Either the ON clause or the USING clause */ -){ - SrcItem *pItem; - sqlite3 *db = pParse->db; - if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){ - sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", - (pOnUsing->pOn ? "ON" : "USING") - ); - goto append_from_error; - } - p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase); - if( p==0 ){ - goto append_from_error; - } - assert( p->nSrc>0 ); - pItem = &p->a[p->nSrc-1]; - assert( (pTable==0)==(pDatabase==0) ); - assert( pItem->zName==0 || pDatabase!=0 ); - if( IN_RENAME_OBJECT && pItem->zName ){ - Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable; - sqlite3RenameTokenMap(pParse, pItem->zName, pToken); - } + Expr *pOn, /* The ON clause of a join */ + IdList *pUsing /* The USING clause of a join */ +){ + struct SrcList_item *pItem; + sqlite3 *db = pParse->db; + if( !p && (pOn || pUsing) ){ + sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", + (pOn ? "ON" : "USING") + ); + goto append_from_error; + } + p = sqlite3SrcListAppend(db, p, pTable, pDatabase); + if( p==0 || NEVER(p->nSrc==0) ){ + goto append_from_error; + } + pItem = &p->a[p->nSrc-1]; assert( pAlias!=0 ); if( pAlias->n ){ pItem->zAlias = sqlite3NameFromToken(db, pAlias); } - assert( pSubquery==0 || pDatabase==0 ); - if( pSubquery ){ - if( sqlite3SrcItemAttachSubquery(pParse, pItem, pSubquery, 0) ){ - if( pSubquery->selFlags & SF_NestedFrom ){ - pItem->fg.isNestedFrom = 1; - } - } - } - assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 ); - assert( pItem->fg.isUsing==0 ); - if( pOnUsing==0 ){ - pItem->u3.pOn = 0; - }else if( pOnUsing->pUsing ){ - pItem->fg.isUsing = 1; - pItem->u3.pUsing = pOnUsing->pUsing; - }else{ - pItem->u3.pOn = pOnUsing->pOn; - } + pItem->pSelect = pSubquery; + pItem->pOn = pOn; + pItem->pUsing = pUsing; return p; -append_from_error: + append_from_error: assert( p==0 ); - sqlite3ClearOnOrUsing(db, pOnUsing); + sqlite3ExprDelete(db, pOn); + sqlite3IdListDelete(db, pUsing); sqlite3SelectDelete(db, pSubquery); return 0; } /* -** Add an INDEXED BY or NOT INDEXED clause to the most recently added +** Add an INDEXED BY or NOT INDEXED clause to the most recently added ** element of the source-list passed as the second argument. */ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ assert( pIndexedBy!=0 ); - if( p && pIndexedBy->n>0 ){ - SrcItem *pItem; - assert( p->nSrc>0 ); - pItem = &p->a[p->nSrc-1]; + if( p && ALWAYS(p->nSrc>0) ){ + struct SrcList_item *pItem = &p->a[p->nSrc-1]; assert( pItem->fg.notIndexed==0 ); assert( pItem->fg.isIndexedBy==0 ); assert( pItem->fg.isTabFunc==0 ); if( pIndexedBy->n==1 && !pIndexedBy->z ){ - /* A "NOT INDEXED" clause was supplied. See parse.y + /* A "NOT INDEXED" clause was supplied. See parse.y ** construct "indexed_opt" for details. */ pItem->fg.notIndexed = 1; }else{ pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); - pItem->fg.isIndexedBy = 1; - assert( pItem->fg.isCte==0 ); /* No collision on union u2 */ - } - } -} - -/* -** Append the contents of SrcList p2 to SrcList p1 and return the resulting -** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2 -** are deleted by this function. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){ - assert( p1 && p1->nSrc==1 ); - if( p2 ){ - SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1); - if( pNew==0 ){ - sqlite3SrcListDelete(pParse->db, p2); - }else{ - p1 = pNew; - memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem)); - sqlite3DbFree(pParse->db, p2); - p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype); - } - } - return p1; + pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0); + } + } } /* ** Add the list of function arguments to the SrcList entry for a ** table-valued-function. */ SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){ if( p ){ - SrcItem *pItem = &p->a[p->nSrc-1]; + struct SrcList_item *pItem = &p->a[p->nSrc-1]; assert( pItem->fg.notIndexed==0 ); assert( pItem->fg.isIndexedBy==0 ); assert( pItem->fg.isTabFunc==0 ); pItem->u1.pFuncArg = pList; pItem->fg.isTabFunc = 1; @@ -127288,38 +104279,18 @@ ** A natural cross join B ** ** The operator is "natural cross join". The A and B operands are stored ** in p->a[0] and p->a[1], respectively. The parser initially stores the ** operator with A. This routine shifts that operator over to B. -** -** Additional changes: -** -** * All tables to the left of the right-most RIGHT JOIN are tagged with -** JT_LTORJ (mnemonic: Left Table Of Right Join) so that the -** code generator can easily tell that the table is part of -** the left operand of at least one RIGHT JOIN. */ -SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse *pParse, SrcList *p){ - (void)pParse; - if( p && p->nSrc>1 ){ - int i = p->nSrc-1; - u8 allFlags = 0; - do{ - allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype; - }while( (--i)>0 ); +SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){ + if( p ){ + int i; + for(i=p->nSrc-1; i>0; i--){ + p->a[i].fg.jointype = p->a[i-1].fg.jointype; + } p->a[0].fg.jointype = 0; - - /* All terms to the left of a RIGHT JOIN should be tagged with the - ** JT_LTORJ flags */ - if( allFlags & JT_RIGHT ){ - for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){} - i--; - assert( i>=0 ); - do{ - p->a[i].fg.jointype |= JT_LTORJ; - }while( (--i)>=0 ); - } } } /* ** Generate VDBE code for a BEGIN statement. @@ -127337,20 +104308,11 @@ } v = sqlite3GetVdbe(pParse); if( !v ) return; if( type!=TK_DEFERRED ){ for(i=0; inDb; i++){ - int eTxnType; - Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeIsReadonly(pBt) ){ - eTxnType = 0; /* Read txn */ - }else if( type==TK_EXCLUSIVE ){ - eTxnType = 2; /* Exclusive txn */ - }else{ - eTxnType = 1; /* Write txn */ - } - sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType); + sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); sqlite3VdbeUsesBtree(v, i); } } sqlite3VdbeAddOp0(v, OP_AutoCommit); } @@ -127366,11 +104328,11 @@ assert( pParse!=0 ); assert( pParse->db!=0 ); assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK ); isRollback = eType==TK_ROLLBACK; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){ return; } v = sqlite3GetVdbe(pParse); if( v ){ @@ -127378,11 +104340,11 @@ } } /* ** This function is called by the parser when it parses a command to create, -** release or rollback an SQL savepoint. +** release or rollback an SQL savepoint. */ SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){ char *zName = sqlite3NameFromToken(pParse->db, pName); if( zName ){ Vdbe *v = sqlite3GetVdbe(pParse); @@ -127405,11 +104367,11 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ sqlite3 *db = pParse->db; if( db->aDb[1].pBt==0 && !pParse->explain ){ int rc; Btree *pBt; - static const int flags = + static const int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_DB; @@ -127421,11 +104383,11 @@ pParse->rc = rc; return 1; } db->aDb[1].pBt = pBt; assert( db->aDb[1].pSchema ); - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){ + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ sqlite3OomFault(db); return 1; } } return 0; @@ -127435,29 +104397,27 @@ ** Record the fact that the schema cookie will need to be verified ** for database iDb. The code to actually verify the schema cookie ** will occur at the end of the top-level VDBE and will be generated ** later, by sqlite3FinishCoding(). */ -static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){ - assert( iDb>=0 && iDbdb->nDb ); - assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 ); - assert( iDbdb, iDb, 0) ); +SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); + + assert( iDb>=0 && iDbdb->nDb ); + assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDbdb, iDb, 0) ); if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ DbMaskSet(pToplevel->cookieMask, iDb); if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pToplevel); } } } -SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ - sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb); -} - /* -** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each +** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each ** attached database. Otherwise, invoke it for the database named zDb only. */ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){ sqlite3 *db = pParse->db; int i; @@ -127482,11 +104442,11 @@ ** can be checked before any changes are made to the database, it is never ** necessary to undo a write and the checkpoint should not be set. */ SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb); + sqlite3CodeVerifySchema(pParse, iDb); DbMaskSet(pToplevel->writeMask, iDb); pToplevel->isMultiWrite |= setStatement; } /* @@ -127499,22 +104459,22 @@ SQLITE_PRIVATE void sqlite3MultiWrite(Parse *pParse){ Parse *pToplevel = sqlite3ParseToplevel(pParse); pToplevel->isMultiWrite = 1; } -/* +/* ** The code generator calls this routine if is discovers that it is -** possible to abort a statement prior to completion. In order to +** possible to abort a statement prior to completion. In order to ** perform this abort without corrupting the database, we need to make ** sure that the statement is protected by a statement transaction. ** ** Technically, we only need to set the mayAbort flag if the ** isMultiWrite flag was previously set. There is a time dependency ** such that the abort must occur after the multiwrite. This makes ** some statements involving the REPLACE conflict resolution algorithm ** go a little faster. But taking advantage of this time dependency -** makes it more difficult to prove that the code is correct (in +** makes it more difficult to prove that the code is correct (in ** particular, it prevents us from writing an effective ** implementation of sqlite3AssertMayAbort()) and so we have chosen ** to take the safe route and skip the optimization. */ SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){ @@ -127533,14 +104493,12 @@ int onError, /* Constraint type */ char *p4, /* Error message */ i8 p4type, /* P4_STATIC or P4_TRANSIENT */ u8 p5Errmsg /* P5_ErrMsg type */ ){ - Vdbe *v; - assert( pParse->pVdbe!=0 ); - v = sqlite3GetVdbe(pParse); - assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested ); + Vdbe *v = sqlite3GetVdbe(pParse); + assert( (errCode&0xff)==SQLITE_CONSTRAINT ); if( onError==OE_Abort ){ sqlite3MayAbort(pParse); } sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type); sqlite3VdbeChangeP5(v, p5Errmsg); @@ -127557,28 +104515,27 @@ char *zErr; int j; StrAccum errMsg; Table *pTab = pIdx->pTable; - sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, - pParse->db->aLimit[SQLITE_LIMIT_LENGTH]); + sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); if( pIdx->aColExpr ){ - sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); + sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); }else{ for(j=0; jnKeyCol; j++){ char *zCol; assert( pIdx->aiColumn[j]>=0 ); - zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName; - if( j ) sqlite3_str_append(&errMsg, ", ", 2); - sqlite3_str_appendall(&errMsg, pTab->zName); - sqlite3_str_append(&errMsg, ".", 1); - sqlite3_str_appendall(&errMsg, zCol); + zCol = pTab->aCol[pIdx->aiColumn[j]].zName; + if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); + sqlite3StrAccumAppendAll(&errMsg, pTab->zName); + sqlite3StrAccumAppend(&errMsg, ".", 1); + sqlite3StrAccumAppendAll(&errMsg, zCol); } } zErr = sqlite3StrAccumFinish(&errMsg); - sqlite3HaltConstraint(pParse, - IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY + sqlite3HaltConstraint(pParse, + IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY : SQLITE_CONSTRAINT_UNIQUE, onError, zErr, P4_DYNAMIC, P5_ConstraintUnique); } @@ -127586,17 +104543,17 @@ ** Code an OP_Halt due to non-unique rowid. */ SQLITE_PRIVATE void sqlite3RowidConstraint( Parse *pParse, /* Parsing context */ int onError, /* Conflict resolution algorithm */ - Table *pTab /* The table with the non-unique rowid */ + Table *pTab /* The table with the non-unique rowid */ ){ char *zMsg; int rc; if( pTab->iPKey>=0 ){ zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName, - pTab->aCol[pTab->iPKey].zCnName); + pTab->aCol[pTab->iPKey].zName); rc = SQLITE_CONSTRAINT_PRIMARYKEY; }else{ zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName); rc = SQLITE_CONSTRAINT_ROWID; } @@ -127627,19 +104584,17 @@ ** Recompute all indices of pTab that use the collating sequence pColl. ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ - if( !IsVirtual(pTab) ){ - Index *pIndex; /* An index associated with pTab */ - - for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ - if( zColl==0 || collationMatch(zColl, pIndex) ){ - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3RefillIndex(pParse, pIndex, -1); - } + Index *pIndex; /* An index associated with pTab */ + + for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ + if( zColl==0 || collationMatch(zColl, pIndex) ){ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); } } } #endif @@ -127715,21 +104670,20 @@ } iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; - zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; + zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, pTab, 0); sqlite3DbFree(db, z); return; } pIndex = sqlite3FindIndex(db, z, zDb); sqlite3DbFree(db, z); if( pIndex ){ - iDb = sqlite3SchemaToIndex(db, pIndex->pTable->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); return; } sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); @@ -127757,104 +104711,39 @@ assert( sqlite3KeyInfoIsWriteable(pKey) ); for(i=0; iazColl[i]; pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 : sqlite3LocateCollSeq(pParse, zColl); - pKey->aSortFlags[i] = pIdx->aSortOrder[i]; - assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) ); + 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; } } return pKey; } #ifndef SQLITE_OMIT_CTE -/* -** Create a new CTE object -*/ -SQLITE_PRIVATE Cte *sqlite3CteNew( - Parse *pParse, /* Parsing context */ - Token *pName, /* Name of the common-table */ - ExprList *pArglist, /* Optional column name list for the table */ - Select *pQuery, /* Query used to initialize the table */ - u8 eM10d /* The MATERIALIZED flag */ -){ - Cte *pNew; - sqlite3 *db = pParse->db; - - pNew = sqlite3DbMallocZero(db, sizeof(*pNew)); - assert( pNew!=0 || db->mallocFailed ); - - if( db->mallocFailed ){ - sqlite3ExprListDelete(db, pArglist); - sqlite3SelectDelete(db, pQuery); - }else{ - pNew->pSelect = pQuery; - pNew->pCols = pArglist; - pNew->zName = sqlite3NameFromToken(pParse->db, pName); - pNew->eM10d = eM10d; - } - return pNew; -} - -/* -** Clear information from a Cte object, but do not deallocate storage -** for the object itself. -*/ -static void cteClear(sqlite3 *db, Cte *pCte){ - assert( pCte!=0 ); - sqlite3ExprListDelete(db, pCte->pCols); - sqlite3SelectDelete(db, pCte->pSelect); - sqlite3DbFree(db, pCte->zName); -} - -/* -** Free the contents of the CTE object passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ - assert( pCte!=0 ); - cteClear(db, pCte); - sqlite3DbFree(db, pCte); -} - -/* -** This routine is invoked once per CTE by the parser while parsing a -** WITH clause. The CTE described by the third argument is added to -** the WITH clause of the second argument. If the second argument is -** NULL, then a new WITH argument is created. +/* +** This routine is invoked once per CTE by the parser while parsing a +** WITH clause. */ SQLITE_PRIVATE With *sqlite3WithAdd( Parse *pParse, /* Parsing context */ With *pWith, /* Existing WITH clause, or NULL */ - Cte *pCte /* CTE to add to the WITH clause */ + Token *pName, /* Name of the common-table */ + ExprList *pArglist, /* Optional column name list for the table */ + Select *pQuery /* Query used to initialize the table */ ){ sqlite3 *db = pParse->db; With *pNew; char *zName; - if( pCte==0 ){ - return pWith; - } - /* Check that the CTE name is unique within this WITH clause. If ** not, store an error in the Parse structure. */ - zName = pCte->zName; + zName = sqlite3NameFromToken(pParse->db, pName); if( zName && pWith ){ int i; for(i=0; inCte; i++){ if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName); @@ -127861,23 +104750,28 @@ } } } if( pWith ){ - sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); + int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); pNew = sqlite3DbRealloc(db, pWith, nByte); }else{ pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); } assert( (pNew!=0 && zName!=0) || db->mallocFailed ); if( db->mallocFailed ){ - sqlite3CteDelete(db, pCte); + sqlite3ExprListDelete(db, pArglist); + sqlite3SelectDelete(db, pQuery); + sqlite3DbFree(db, zName); pNew = pWith; }else{ - pNew->a[pNew->nCte++] = *pCte; - sqlite3DbFree(db, pCte); + pNew->a[pNew->nCte].pSelect = pQuery; + pNew->a[pNew->nCte].pCols = pArglist; + pNew->a[pNew->nCte].zName = zName; + pNew->a[pNew->nCte].zCteErr = 0; + pNew->nCte++; } return pNew; } @@ -127886,24 +104780,24 @@ */ SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){ if( pWith ){ int i; for(i=0; inCte; i++){ - cteClear(db, &pWith->a[i]); + struct Cte *pCte = &pWith->a[i]; + sqlite3ExprListDelete(db, pCte->pCols); + sqlite3SelectDelete(db, pCte->pSelect); + sqlite3DbFree(db, pCte->zName); } sqlite3DbFree(db, pWith); } } -SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){ - sqlite3WithDelete(db, (With*)pWith); -} #endif /* !defined(SQLITE_OMIT_CTE) */ /************** End of build.c ***********************************************/ /************** Begin file callback.c ****************************************/ /* -** 2005 May 23 +** 2005 May 23 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. @@ -127964,19 +104858,63 @@ return SQLITE_OK; } } return SQLITE_ERROR; } + +/* +** This function is responsible for invoking the collation factory callback +** or substituting a collation sequence of a different encoding when the +** requested collation sequence is not available in the desired encoding. +** +** If it is not NULL, then pColl must point to the database native encoding +** collation sequence with name zName, length nName. +** +** The return value is either the collation sequence to be used in database +** db for collation type name zName, length nName, or NULL, if no collation +** sequence can be found. If no collation is found, leave an error message. +** +** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() +*/ +SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( + Parse *pParse, /* Parsing context */ + u8 enc, /* The desired encoding for the collating sequence */ + CollSeq *pColl, /* Collating sequence with native encoding, or NULL */ + const char *zName /* Collating sequence name */ +){ + CollSeq *p; + sqlite3 *db = pParse->db; + + p = pColl; + if( !p ){ + p = sqlite3FindCollSeq(db, enc, zName, 0); + } + if( !p || !p->xCmp ){ + /* No collation sequence of this type for this encoding is registered. + ** Call the collation factory to see if it can supply us with one. + */ + callCollNeeded(db, enc, zName); + p = sqlite3FindCollSeq(db, enc, zName, 0); + } + if( p && !p->xCmp && synthCollSeq(db, p) ){ + p = 0; + } + assert( !p || p->xCmp ); + if( p==0 ){ + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); + } + return p; +} /* ** This routine is called on a collation sequence before it is used to ** check that it is defined. An undefined collation sequence exists when ** a database is loaded that contains references to collation sequences ** that have not been defined by sqlite3_create_collation() etc. ** ** If required, this routine calls the 'collation needed' callback to -** request a definition of the collating sequence. If this doesn't work, +** request a definition of the collating sequence. If this doesn't work, ** an equivalent collating sequence that uses a text encoding different ** from the main database is substituted, if one is available. */ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ if( pColl && pColl->xCmp==0 ){ @@ -128026,11 +104964,11 @@ pColl[2].zName = (char*)&pColl[3]; pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl); - /* If a malloc() failure occurred in sqlite3HashInsert(), it will + /* If a malloc() failure occurred in sqlite3HashInsert(), it will ** return the pColl pointer to be deleted (because it wasn't added ** to the hash table). */ assert( pDel==0 || pDel==pColl ); if( pDel!=0 ){ @@ -128057,117 +104995,24 @@ ** cannot be found. ** ** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() */ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq( - sqlite3 *db, /* Database connection to search */ - u8 enc, /* Desired text encoding */ - const char *zName, /* Name of the collating sequence. Might be NULL */ - int create /* True to create CollSeq if doesn't already exist */ + sqlite3 *db, + u8 enc, + const char *zName, + int create ){ CollSeq *pColl; - assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); if( zName ){ pColl = findCollSeqEntry(db, zName, create); - if( pColl ) pColl += enc-1; }else{ pColl = db->pDfltColl; } - return pColl; -} - -/* -** Change the text encoding for a database connection. This means that -** the pDfltColl must change as well. -*/ -SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){ - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - db->enc = enc; - /* EVIDENCE-OF: R-08308-17224 The default collating function for all - ** strings is BINARY. - */ - db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0); - sqlite3ExpirePreparedStatements(db, 1); -} - -/* -** This function is responsible for invoking the collation factory callback -** or substituting a collation sequence of a different encoding when the -** requested collation sequence is not available in the desired encoding. -** -** If it is not NULL, then pColl must point to the database native encoding -** collation sequence with name zName, length nName. -** -** The return value is either the collation sequence to be used in database -** db for collation type name zName, length nName, or NULL, if no collation -** sequence can be found. If no collation is found, leave an error message. -** -** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( - Parse *pParse, /* Parsing context */ - u8 enc, /* The desired encoding for the collating sequence */ - CollSeq *pColl, /* Collating sequence with native encoding, or NULL */ - const char *zName /* Collating sequence name */ -){ - CollSeq *p; - sqlite3 *db = pParse->db; - - p = pColl; - if( !p ){ - p = sqlite3FindCollSeq(db, enc, zName, 0); - } - if( !p || !p->xCmp ){ - /* No collation sequence of this type for this encoding is registered. - ** Call the collation factory to see if it can supply us with one. - */ - callCollNeeded(db, enc, zName); - p = sqlite3FindCollSeq(db, enc, zName, 0); - } - if( p && !p->xCmp && synthCollSeq(db, p) ){ - p = 0; - } - assert( !p || p->xCmp ); - if( p==0 ){ - sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); - pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ; - } - return p; -} - -/* -** This function returns the collation sequence for database native text -** encoding identified by the string zName. -** -** If the requested collation sequence is not available, or not available -** in the database native encoding, the collation factory is invoked to -** request it. If the collation factory does not supply such a sequence, -** and the sequence is available in another text encoding, then that is -** returned instead. -** -** If no versions of the requested collations sequence are available, or -** another error occurs, NULL is returned and an error message written into -** pParse. -** -** This routine is a wrapper around sqlite3FindCollSeq(). This routine -** invokes the collation factory if the named collation cannot be found -** and generates an error message. -** -** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ - sqlite3 *db = pParse->db; - u8 enc = ENC(db); - u8 initbusy = db->init.busy; - CollSeq *pColl; - - pColl = sqlite3FindCollSeq(db, enc, zName, initbusy); - if( !initbusy && (!pColl || !pColl->xCmp) ){ - pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName); - } - + assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); + if( pColl ) pColl += enc-1; return pColl; } /* During the search for the best function definition, this procedure ** is called to test how well the function passed as the first argument @@ -128177,11 +105022,11 @@ ** ** If nArg is -1 that means to only return a match (non-zero) if p->nArg ** is also -1. In other words, we are searching for a function that ** takes a variable number of arguments. ** -** If nArg is -2 that means that we are searching for any function +** If nArg is -2 that means that we are searching for any function ** regardless of the number of arguments it uses, so return a positive ** match score for any ** ** The returned value is always between 0 and 6, as follows: ** @@ -128202,23 +105047,16 @@ FuncDef *p, /* The function we are evaluating for match quality */ int nArg, /* Desired number of arguments. (-1)==any */ u8 enc /* Desired text encoding */ ){ int match; - assert( p->nArg>=(-4) && p->nArg!=(-2) ); - assert( nArg>=(-2) ); + + /* nArg of -2 is a special case */ + if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH; /* Wrong number of arguments means "no match" */ - if( p->nArg!=nArg ){ - if( nArg==(-2) ) return p->xSFunc==0 ? 0 : FUNC_PERFECT_MATCH; - if( p->nArg>=0 ) return 0; - /* Special p->nArg values available to built-in functions only: - ** -3 1 or more arguments required - ** -4 2 or more arguments required - */ - if( p->nArg<(-2) && nArg<(-2-p->nArg) ) return 0; - } + if( p->nArg!=nArg && p->nArg>=0 ) return 0; /* Give a better score to a function with a specific number of arguments ** than to function that accepts any number of arguments. */ if( p->nArg==nArg ){ match = 4; @@ -128238,17 +105076,16 @@ /* ** Search a FuncDefHash for a function with the given name. Return ** a pointer to the matching FuncDef if found, or 0 if there is no match. */ -SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch( +static FuncDef *functionSearch( int h, /* Hash of the name */ const char *zFunc /* Name of function */ ){ FuncDef *p; for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ - assert( p->funcFlags & SQLITE_FUNC_BUILTIN ); if( sqlite3StrICmp(p->zName, zFunc)==0 ){ return p; } } return 0; @@ -128264,13 +105101,13 @@ int i; for(i=0; i='a' && zName[0]<='z' ); + pOther = functionSearch(h, zName); if( pOther ){ assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] ); aDef[i].pNext = pOther->pNext; pOther->pNext = &aDef[i]; }else{ @@ -128278,12 +105115,12 @@ aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h]; sqlite3BuiltinFunctions.a[h] = &aDef[i]; } } } - - + + /* ** Locate a user function given a name, a number of arguments and a flag ** indicating whether the function prefers UTF-16 over UTF-8. Return a ** pointer to the FuncDef structure that defines that function, or return @@ -128331,24 +105168,24 @@ p = p->pNext; } /* If no match is found, search the built-in functions. ** - ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in + ** If the SQLITE_PreferBuiltin flag is set, then search the built-in ** functions even if a prior app-defined function was found. And give ** priority to built-in functions. ** ** Except, if createFlag is true, that means that we are trying to ** install a new function. Whatever FuncDef structure is returned it will ** have fields overwritten with new information appropriate for the ** new function. But the FuncDefs for built-in functions are read-only. ** So we must not search for built-ins when creating a new function. - */ - if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ + */ + if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ bestScore = 0; - h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName); - p = sqlite3FunctionSearch(h, zName); + h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; + p = functionSearch(h, zName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ pBest = p; bestScore = score; @@ -128359,19 +105196,17 @@ /* If the createFlag parameter is true and the search did not reveal an ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ - if( createFlag && bestScorezName = (const char*)&pBest[1]; pBest->nArg = (u16)nArg; pBest->funcFlags = enc; memcpy((char*)&pBest[1], zName, nName+1); - for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z]; pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); if( pOther==pBest ){ sqlite3DbFree(db, pBest); sqlite3OomFault(db); return 0; @@ -128386,11 +105221,11 @@ return 0; } /* ** Free all resources held by the schema structure. The void* argument points -** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the +** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the ** pointer itself, it just cleans up subsidiary resources (i.e. the contents ** of the schema hash tables). ** ** The Schema.cache_size variable is not cleared. */ @@ -128397,33 +105232,31 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ Hash temp1; Hash temp2; HashElem *pElem; Schema *pSchema = (Schema *)p; - sqlite3 xdb; - memset(&xdb, 0, sizeof(xdb)); temp1 = pSchema->tblHash; temp2 = pSchema->trigHash; sqlite3HashInit(&pSchema->trigHash); sqlite3HashClear(&pSchema->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem)); + sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem)); } sqlite3HashClear(&temp2); sqlite3HashInit(&pSchema->tblHash); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); - sqlite3DeleteTable(&xdb, pTab); + sqlite3DeleteTable(0, pTab); } sqlite3HashClear(&temp1); sqlite3HashClear(&pSchema->fkeyHash); pSchema->pSeqTab = 0; if( pSchema->schemaFlags & DB_SchemaLoaded ){ pSchema->iGeneration++; + pSchema->schemaFlags &= ~DB_SchemaLoaded; } - pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted); } /* ** Find and return the schema associated with a BTree. Create ** a new one if necessary. @@ -128468,116 +105301,63 @@ /* ** While a SrcList can in general represent multiple tables and subqueries ** (as in the FROM clause of a SELECT statement) in this case it contains ** the name of a single table, as one might find in an INSERT, DELETE, ** or UPDATE statement. Look up that table in the symbol table and -** return a pointer. Set an error message and return NULL if the table +** return a pointer. Set an error message and return NULL if the table ** name is not found or if any other error occurs. ** ** The following fields are initialized appropriate in pSrc: ** -** pSrc->a[0].spTab Pointer to the Table object -** pSrc->a[0].u2.pIBIndex Pointer to the INDEXED BY index, if there is one +** pSrc->a[0].pTab Pointer to the Table object +** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one ** */ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ - SrcItem *pItem = pSrc->a; + struct SrcList_item *pItem = pSrc->a; Table *pTab; - assert( pItem && pSrc->nSrc>=1 ); + assert( pItem && pSrc->nSrc==1 ); pTab = sqlite3LocateTableItem(pParse, 0, pItem); - if( pItem->pSTab ) sqlite3DeleteTable(pParse->db, pItem->pSTab); - pItem->pSTab = pTab; - pItem->fg.notCte = 1; + sqlite3DeleteTable(pParse->db, pItem->pTab); + pItem->pTab = pTab; if( pTab ){ pTab->nTabRef++; - if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){ - pTab = 0; - } + } + if( sqlite3IndexedByLookup(pParse, pItem) ){ + pTab = 0; } return pTab; } -/* Generate byte-code that will report the number of rows modified -** by a DELETE, INSERT, or UPDATE statement. -*/ -SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){ - sqlite3VdbeAddOp0(v, OP_FkCheck); - sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC); -} - -/* Return true if table pTab is read-only. -** -** A table is read-only if any of the following are true: -** -** 1) It is a virtual table and no implementation of the xUpdate method -** has been provided -** -** 2) A trigger is currently being coded and the table is a virtual table -** that is SQLITE_VTAB_DIRECTONLY or if PRAGMA trusted_schema=OFF and -** the table is not SQLITE_VTAB_INNOCUOUS. -** -** 3) It is a system table (i.e. sqlite_schema), this call is not -** part of a nested parse and writable_schema pragma has not -** been specified -** -** 4) The table is a shadow table, the database connection is in -** defensive mode, and the current sqlite3_prepare() -** is for a top-level SQL statement. -*/ -static int vtabIsReadOnly(Parse *pParse, Table *pTab){ - assert( IsVirtual(pTab) ); - if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){ - return 1; - } - - /* Within triggers: - ** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY - ** virtual tables - ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS - ** virtual tables if PRAGMA trusted_schema=ON. - */ - if( pParse->pToplevel!=0 - && pTab->u.vtab.p->eVtabRisk > - ((pParse->db->flags & SQLITE_TrustedSchema)!=0) - ){ - sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", - pTab->zName); - } - return 0; -} -static int tabIsReadOnly(Parse *pParse, Table *pTab){ - sqlite3 *db; - if( IsVirtual(pTab) ){ - return vtabIsReadOnly(pParse, pTab); - } - if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; - db = pParse->db; - if( (pTab->tabFlags & TF_Readonly)!=0 ){ - return sqlite3WritableSchema(db)==0 && pParse->nested==0; - } - assert( pTab->tabFlags & TF_Shadow ); - return sqlite3ReadOnlyShadowTables(db); -} - -/* -** Check to make sure the given table is writable. -** -** If pTab is not writable -> generate an error message and return 1. -** If pTab is writable but other errors have occurred -> return 1. -** If pTab is writable and no prior errors -> return 0; -*/ -SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, Trigger *pTrigger){ - if( tabIsReadOnly(pParse, pTab) ){ +/* +** Check to make sure the given table is writable. If it is not +** writable, generate an error message and return 1. If it is +** writable return 0; +*/ +SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ + /* A table is not writable under the following circumstances: + ** + ** 1) It is a virtual table and no implementation of the xUpdate method + ** has been provided, or + ** 2) It is a system table (i.e. sqlite_master), this call is not + ** part of a nested parse and writable_schema pragma has not + ** been specified. + ** + ** In either case leave an error message in pParse and return non-zero. + */ + if( ( IsVirtual(pTab) + && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) + || ( (pTab->tabFlags & TF_Readonly)!=0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && pParse->nested==0 ) + ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } + #ifndef SQLITE_OMIT_VIEW - if( IsView(pTab) - && (pTrigger==0 || (pTrigger->bReturning && pTrigger->pNext==0)) - ){ + if( !viewOk && pTab->pSelect ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); return 1; } #endif return 0; @@ -128592,31 +105372,28 @@ */ 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; Select *pSel; SrcList *pFrom; sqlite3 *db = pParse->db; int iDb = sqlite3SchemaToIndex(db, pView->pSchema); pWhere = sqlite3ExprDup(db, pWhere, 0); - pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0); + pFrom = sqlite3SrcListAppend(db, 0, 0, 0); if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); - assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 ); - pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); - assert( pFrom->a[0].fg.isUsing==0 ); - assert( pFrom->a[0].u3.pOn==0 ); + pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); + assert( pFrom->a[0].pOn==0 ); + assert( pFrom->a[0].pUsing==0 ); } - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, - SF_IncludeHidden, pLimit); + pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, + SF_IncludeHidden, 0, 0); sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pSel, &dest); sqlite3SelectDelete(db, pSel); } #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ @@ -128634,99 +105411,75 @@ Parse *pParse, /* The parser context */ SrcList *pSrc, /* the FROM clause -- which tables to scan */ 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. */ ){ - sqlite3 *db = pParse->db; - Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ + Expr *pWhereRowid = NULL; /* WHERE rowid .. */ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ - ExprList *pEList = NULL; /* Expression list containing only pSelectRowid*/ + 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); - sqlite3ExprDelete(pParse->db, pWhere); - sqlite3ExprListDelete(pParse->db, pOrderBy); - return 0; + goto limit_where_cleanup; } /* 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; } - /* Generate a select expression tree to enforce the limit/offset + /* Generate a select expression tree to enforce the limit/offset ** term for the DELETE or UPDATE statement. For example: ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 ** becomes: - ** DELETE FROM table_a WHERE rowid IN ( + ** DELETE FROM table_a WHERE rowid IN ( ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 ** ); */ - pTab = pSrc->a[0].pSTab; - 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); - assert( pPk!=0 ); - assert( pPk->nKeyCol>=1 ); - if( pPk->nKeyCol==1 ){ - const char *zName; - assert( pPk->aiColumn[0]>=0 && pPk->aiColumn[0]nCol ); - zName = pTab->aCol[pPk->aiColumn[0]].zCnName; - 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; - assert( pPk->aiColumn[i]>=0 && pPk->aiColumn[i]nCol ); - p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); - pEList = sqlite3ExprListAppend(pParse, pEList, p); - } - pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( pLhs ){ - pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0); - } - } - } + pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); + if( pSelectRowid == 0 ) goto limit_where_cleanup; + pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); + if( pEList == 0 ) goto limit_where_cleanup; /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree ** and the SELECT subtree. */ - pSrc->a[0].pSTab = 0; - pSelectSrc = sqlite3SrcListDup(db, pSrc, 0); - pSrc->a[0].pSTab = pTab; - if( pSrc->a[0].fg.isIndexedBy ){ - assert( pSrc->a[0].fg.isCte==0 ); - pSrc->a[0].u2.pIBIndex = 0; - pSrc->a[0].fg.isIndexedBy = 0; - sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy); - }else if( pSrc->a[0].fg.isCte ){ - pSrc->a[0].u2.pCteUse->nUse++; + pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); + if( pSelectSrc == 0 ) { + sqlite3ExprListDelete(pParse->db, pEList); + goto limit_where_cleanup; } /* generate the SELECT expression tree. */ - pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, - pOrderBy,0,pLimit - ); + pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, + pOrderBy,0,pLimit,pOffset); + if( pSelect == 0 ) return 0; - /* now generate the new WHERE rowid IN clause for the DELETE/UPDATE */ - pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0); + /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ + pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); + pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 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) */ /* @@ -128737,13 +105490,11 @@ ** pTabList pWhere */ 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 */ - ExprList *pOrderBy, /* ORDER BY clause. May be null */ - Expr *pLimit /* LIMIT clause. May be null */ + Expr *pWhere /* The WHERE clause. May be null */ ){ Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ @@ -128754,11 +105505,11 @@ int nIdx; /* Number of indices */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ - int memCnt = 0; /* Memory cell used for change counting */ + int memCnt = -1; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ Index *pPk; /* The PRIMARY KEY index on the table */ @@ -128771,23 +105522,21 @@ int addrBypass = 0; /* Address of jump over the delete logic */ int addrLoop = 0; /* Top of the delete loop */ int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ int bComplex; /* True if there are triggers or FKs or ** subqueries in the WHERE clause */ - + #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ #endif memset(&sContext, 0, sizeof(sContext)); db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nErr ){ + if( pParse->nErr || db->mallocFailed ){ goto delete_from_cleanup; } - assert( db->mallocFailed==0 ); 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 @@ -128799,51 +105548,33 @@ /* Figure out if we have any triggers and if the table being ** deleted from is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - isView = IsView(pTab); + 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 - -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__); - sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere, - pOrderBy, pLimit, pTrigger); - } -#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) ){ goto delete_from_cleanup; } - if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ + if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto delete_from_cleanup; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); - rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, + rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, db->aDb[iDb].zDbSName); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; } @@ -128868,23 +105599,19 @@ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, bComplex, iDb); + sqlite3BeginWriteOperation(pParse, 1, iDb); /* If we are trying to delete from a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ - sqlite3MaterializeView(pParse, pTab, - pWhere, pOrderBy, pLimit, iTabCur - ); + sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur); iDataCur = iIdxCur = iTabCur; - pOrderBy = 0; - pLimit = 0; } #endif /* Resolve the column names in the WHERE clause. */ @@ -128896,23 +105623,19 @@ } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ - if( (db->flags & SQLITE_CountRows)!=0 - && !pParse->nested - && !pParse->pTriggerTab - && !pParse->bReturning - ){ + if( db->flags & SQLITE_CountRows ){ memCnt = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); } #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION /* Special case: A DELETE without a WHERE clause deletes everything. ** It is easier just to erase the whole table. Prior to version 3.6.5, - ** this optimization caused the row change count (the value returned by + ** this optimization caused the row change count (the value returned by ** API function sqlite3_count_changes) to be set incorrectly. ** ** 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 @@ -128928,31 +105651,27 @@ #endif ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, + sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, pTab->zName, P4_STATIC); } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->pSchema==pTab->pSchema ); - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Clear, pIdx->tnum, iDb, memCnt ? memCnt : -1); - }else{ - sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); - } + sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { - u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; - if( sNC.ncFlags & NC_Subquery ) bComplex = 1; + u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE; + if( sNC.ncFlags & NC_VarSelect ) bComplex = 1; wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; - assert( nPk==1 ); + nPk = 1; iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); }else{ /* For a WITHOUT ROWID table, create an ephemeral table used to ** hold all primary keys for rows to be deleted. */ @@ -128963,48 +105682,44 @@ pParse->nMem += nPk; iEphCur = pParse->nTab++; addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk); sqlite3VdbeSetP4KeyInfo(pParse, pPk); } - + /* Construct a query to find the rowid or primary key for every row ** to be deleted, based on the WHERE clause. Set variable eOnePass ** to indicate the strategy used to implement this delete: ** ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values. ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); - assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF - || OptimizationDisabled(db, SQLITE_OnePass) ); - if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); - if( sqlite3WhereUsesDeferredSeek(pWInfo) ){ - sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur); - } - + assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); + /* Keep track of the number of rows to be deleted */ - if( memCnt ){ + if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } - + /* Extract the rowid or primary key for the current row */ if( pPk ){ for(i=0; iaiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i], iPk+i); } iKey = iPk; }else{ - iKey = ++pParse->nMem; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey); + iKey = pParse->nMem + 1; + iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); + if( iKey>pParse->nMem ) pParse->nMem = iKey; } - + if( eOnePass!=ONEPASS_OFF ){ /* For ONEPASS, no need to store the rowid/primary-key. There is only ** one, so just keep it in its register(s) and fall through to the ** delete code. */ nKey = nPk; /* OP_Found will use an unpacked key */ @@ -129016,11 +105731,10 @@ memset(aToOpen, 1, nIdx+1); aToOpen[nIdx+1] = 0; if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); - addrBypass = sqlite3VdbeMakeLabel(pParse); }else{ if( pPk ){ /* Add the PK key for this row to the temporary table */ iKey = ++pParse->nMem; nKey = 0; /* Zero tells OP_Found to use a composite key */ @@ -129030,16 +105744,23 @@ }else{ /* Add the rowid of the row to be deleted to the RowSet */ nKey = 1; /* OP_DeferredSeek always uses a single rowid */ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); } + } + + /* If this DELETE cannot use the ONEPASS strategy, this is the + ** end of the WHERE loop */ + if( eOnePass!=ONEPASS_OFF ){ + addrBypass = sqlite3VdbeMakeLabel(v); + }else{ sqlite3WhereEnd(pWInfo); } - - /* Unless this is a view, open cursors for the table we are + + /* Unless this is a view, open cursors for the table we are ** deleting from and all its indices. If this is a view, then the - ** only effect this statement has is to fire the INSTEAD OF + ** only effect this statement has is to fire the INSTEAD OF ** triggers. */ if( !isView ){ int iAddrOnce = 0; if( eOnePass==ONEPASS_MULTI ){ @@ -129048,62 +105769,53 @@ testcase( IsVirtual(pTab) ); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, iTabCur, aToOpen, &iDataCur, &iIdxCur); assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); - if( eOnePass==ONEPASS_MULTI ){ - sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce); - } + if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); } - + /* Set up a loop over the rowids/primary-keys that were found in the ** where-clause loop above. */ if( eOnePass!=ONEPASS_OFF ){ assert( nKey==nPk ); /* OP_Found will use an unpacked key */ if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ - assert( pPk!=0 || IsView(pTab) ); + assert( pPk!=0 || pTab->pSelect!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); - if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey); - }else{ - sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); - } + 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); VdbeCoverage(v); assert( nKey==1 ); - } - + } + /* Delete the row */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); sqlite3VtabMakeWritable(pParse, pTab); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); + sqlite3VdbeChangeP5(v, OE_Abort); assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); - if( eOnePass==ONEPASS_SINGLE ){ - sqlite3VdbeAddOp1(v, OP_Close, iTabCur); - if( sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; - } - } - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, OE_Abort); + if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ + pParse->isMultiWrite = 0; + } }else #endif { int count = (pParse->nested==0); /* True to count changes */ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]); } - + /* End of the loop over all rowids/primary-keys. */ if( eOnePass!=ONEPASS_OFF ){ sqlite3VdbeResolveLabel(v, addrBypass); sqlite3WhereEnd(pWInfo); }else if( pPk ){ @@ -129110,11 +105822,11 @@ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); }else{ sqlite3VdbeGoto(v, addrLoop); sqlite3VdbeJumpHere(v, addrLoop); - } + } } /* End non-truncate path */ /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. @@ -129121,27 +105833,25 @@ */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } - /* Return the number of rows that were deleted. If this routine is + /* Return the number of rows that were deleted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( memCnt ){ - sqlite3CodeChangeCount(v, memCnt, "rows deleted"); + if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); } delete_from_cleanup: sqlite3AuthContextPop(&sContext); sqlite3SrcListDelete(db, pTabList); sqlite3ExprDelete(db, pWhere); -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) - sqlite3ExprListDelete(db, pOrderBy); - sqlite3ExprDelete(db, pLimit); -#endif - if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen); + sqlite3DbFree(db, aToOpen); return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** they may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ @@ -129178,11 +105888,11 @@ ** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF ** then this function must seek iDataCur to the entry identified by iPk ** and nPk before reading from it. ** ** 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 +** of a ONEPASS delete that affects multiple rows. In this case, if ** 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. ** @@ -129214,21 +105924,21 @@ /* Vdbe is guaranteed to have been allocated by this stage. */ assert( v ); VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)", iDataCur, iIdxCur, iPk, (int)nPk)); - /* Seek cursor iCur to the row to delete. If this row no longer exists + /* Seek cursor iCur to the row to delete. If this row no longer exists ** (this can happen if a trigger program has already deleted it), do ** not attempt to delete it or fire any DELETE triggers. */ - iLabel = sqlite3VdbeMakeLabel(pParse); + iLabel = sqlite3VdbeMakeLabel(v); opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; if( eMode==ONEPASS_OFF ){ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); VdbeCoverageIf(v, opSeek==OP_NotExists); VdbeCoverageIf(v, opSeek==OP_NotFound); } - + /* If there are any triggers to fire, allocate a range of registers to ** use for the old.* references in the triggers. */ if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){ u32 mask; /* Mask of OLD.* columns in use */ int iCol; /* Iterator used while populating OLD.* */ @@ -129241,29 +105951,28 @@ ); mask |= sqlite3FkOldmask(pParse, pTab); iOld = pParse->nMem+1; pParse->nMem += (1 + pTab->nCol); - /* Populate the OLD.* pseudo-table register array. These values will be + /* Populate the OLD.* pseudo-table register array. These values will be ** used by any BEFORE and AFTER triggers that exist. */ sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld); for(iCol=0; iColnCol; iCol++){ testcase( mask!=0xffffffff && iCol==31 ); testcase( mask!=0xffffffff && iCol==32 ); if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){ - int kk = sqlite3TableColumnToStorage(pTab, iCol); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+kk+1); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1); } } /* Invoke BEFORE DELETE trigger programs. */ addrStart = sqlite3VdbeCurrentAddr(v); - sqlite3CodeRowTrigger(pParse, pTrigger, + sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel ); - /* If any BEFORE triggers were coded, then seek the cursor to the + /* 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 already deleted the row that the cursor was ** pointing to. ** ** Also disable the iIdxNoSeek optimization since the BEFORE trigger @@ -129276,30 +105985,30 @@ testcase( iIdxNoSeek>=0 ); iIdxNoSeek = -1; } /* Do FK processing. This call checks that any FK constraints that - ** refer to this table (i.e. constraints attached to other tables) + ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); } /* Delete the index and table entries. Skip this step if pTab is really ** a view (in which case the only effect of the DELETE statement is to - ** fire the INSTEAD OF triggers). + ** fire the INSTEAD OF triggers). ** ** If variable 'count' is non-zero, then this OP_Delete instruction should ** invoke the update-hook. The pre-update-hook, on the other hand should ** be invoked unless table pTab is a system table. The difference is that - ** the update-hook is not invoked for rows removed by REPLACE, but the + ** the update-hook is not invoked for rows removed by REPLACE, but the ** pre-update-hook is. - */ - if( !IsView(pTab) ){ + */ + if( pTab->pSelect==0 ){ u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); - if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){ + if( pParse->nested==0 ){ sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); } if( eMode!=ONEPASS_OFF ){ sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } @@ -129310,22 +106019,20 @@ sqlite3VdbeChangeP5(v, p5); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key - ** to the row just deleted. */ + ** to the row just deleted. */ sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); /* Invoke AFTER DELETE trigger programs. */ - if( pTrigger ){ - sqlite3CodeRowTrigger(pParse, pTrigger, - TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel - ); - } + sqlite3CodeRowTrigger(pParse, pTrigger, + TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel + ); /* Jump here if the row had already been deleted before any BEFORE - ** trigger programs were invoked. Or if a trigger program throws a + ** trigger programs were invoked. Or if a trigger program throws a ** RAISE(IGNORE) exception. */ sqlite3VdbeResolveLabel(v, iLabel); VdbeModuleComment((v, "END: GenRowDel()")); } @@ -129373,11 +106080,10 @@ VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel, pPrior, r1); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); - sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */ sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); pPrior = pIdx; } } @@ -129406,11 +106112,11 @@ ** a pointer to a different index for which an index key has just been ** computed into register regPrior. If the current pIdx index is generating ** its key into the same sequence of registers and if pPrior and pIdx share ** a column in common, then the register corresponding to that column already ** holds the correct value and the loading of that register is skipped. -** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK +** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK ** on a table with multiple indices, and especially with the ROWID or ** PRIMARY KEY columns of the index. */ SQLITE_PRIVATE int sqlite3GenerateIndexKey( Parse *pParse, /* Parsing context */ @@ -129427,17 +106133,15 @@ int regBase; int nCol; if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ - *piPartIdxLabel = sqlite3VdbeMakeLabel(pParse); - pParse->iSelfTab = iDataCur + 1; - sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, + *piPartIdxLabel = sqlite3VdbeMakeLabel(v); + pParse->iSelfTab = iDataCur; + sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, SQLITE_JUMPIFNULL); - pParse->iSelfTab = 0; - pPrior = 0; /* Ticket a9efb42811fa41ee 2019-11-02; - ** pPartIdxWhere may have corrupted regPrior registers */ }else{ *piPartIdxLabel = 0; } } nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn; @@ -129450,22 +106154,24 @@ ){ /* This column was already computed by the previous index */ continue; } sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); - if( pIdx->aiColumn[j]>=0 ){ - /* If the column affinity is REAL but the number is an integer, then it - ** might be stored in the table as an integer (using a compact - ** representation) then converted to REAL by an OP_RealAffinity opcode. - ** But we are getting ready to store this value back into an index, where - ** it should be converted by to INTEGER again. So omit the - ** OP_RealAffinity opcode if it is present */ - sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); - } + /* If the column affinity is REAL but the number is an integer, then it + ** might be stored in the table as an integer (using a compact + ** representation) then converted to REAL by an OP_RealAffinity opcode. + ** But we are getting ready to store this value back into an index, where + ** it should be converted by to INTEGER again. So omit the OP_RealAffinity + ** opcode if it is present */ + sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); } 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; } @@ -129475,10 +106181,11 @@ ** resolve that label. */ SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ if( iLabel ){ sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); + sqlite3ExprCachePop(pParse); } } /************** End of delete.c **********************************************/ /************** Begin file func.c ********************************************/ @@ -129498,13 +106205,10 @@ ** time functions, are implemented separately.) */ /* #include "sqliteInt.h" */ /* #include */ /* #include */ -#ifndef SQLITE_OMIT_FLOATING_POINT -/* #include */ -#endif /* #include "vdbeInt.h" */ /* ** Return the collating function associated with a function. */ @@ -129520,12 +106224,10 @@ /* ** Indicate that the accumulator load should be skipped on this ** iteration of the aggregate loop. */ static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ - assert( context->isError<=0 ); - context->isError = -1; context->skipFlag = 1; } /* ** Implementation of the non-aggregate min() and max() functions @@ -129579,31 +106281,21 @@ ** V. The returned value is one of SQLITE_INTEGER, SQLITE_FLOAT, ** SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL. */ sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC); } -/* subtype(X) -** -** Return the subtype of X -*/ -static void subtypeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - sqlite3_result_int(context, sqlite3_value_subtype(argv[0])); -} /* ** Implementation of the length() function */ static void lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ + int len; + assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_BLOB: case SQLITE_INTEGER: @@ -129611,57 +106303,17 @@ sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); break; } case SQLITE_TEXT: { const unsigned char *z = sqlite3_value_text(argv[0]); - const unsigned char *z0; - unsigned char c; if( z==0 ) return; - z0 = z; - while( (c = *z)!=0 ){ - z++; - if( c>=0xc0 ){ - while( (*z & 0xc0)==0x80 ){ z++; z0++; } - } - } - sqlite3_result_int(context, (int)(z-z0)); - break; - } - default: { - sqlite3_result_null(context); - break; - } - } -} - -/* -** Implementation of the octet_length() function -*/ -static void bytelengthFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_BLOB: { - sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); - break; - } - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - i64 m = sqlite3_context_db_handle(context)->enc<=SQLITE_UTF8 ? 1 : 2; - sqlite3_result_int64(context, sqlite3_value_bytes(argv[0])*m); - break; - } - case SQLITE_TEXT: { - if( sqlite3_value_encoding(argv[0])<=SQLITE_UTF8 ){ - sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); - }else{ - sqlite3_result_int(context, sqlite3_value_bytes16(argv[0])); - } + len = 0; + while( *z ){ + len++; + SQLITE_SKIP_UTF8(z); + } + sqlite3_result_int(context, len); break; } default: { sqlite3_result_null(context); break; @@ -129671,11 +106323,11 @@ /* ** Implementation of the abs() function. ** ** IMP: R-23979-26855 The abs(X) function returns the absolute value of -** the numeric argument X. +** the numeric argument X. */ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ @@ -129688,11 +106340,11 @@ ** equivalent positive 64-bit two complement value. */ sqlite3_result_error(context, "integer overflow", -1); return; } iVal = -iVal; - } + } sqlite3_result_int64(context, iVal); break; } case SQLITE_NULL: { /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ @@ -129734,13 +106386,10 @@ int nHaystack; int nNeedle; int typeHaystack, typeNeedle; int N = 1; int isText; - unsigned char firstChar; - sqlite3_value *pC1 = 0; - sqlite3_value *pC2 = 0; UNUSED_PARAMETER(argc); typeHaystack = sqlite3_value_type(argv[0]); typeNeedle = sqlite3_value_type(argv[1]); if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; @@ -129749,50 +106398,30 @@ if( nNeedle>0 ){ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ zHaystack = sqlite3_value_blob(argv[0]); zNeedle = sqlite3_value_blob(argv[1]); isText = 0; - }else if( typeHaystack!=SQLITE_BLOB && typeNeedle!=SQLITE_BLOB ){ + }else{ zHaystack = sqlite3_value_text(argv[0]); zNeedle = sqlite3_value_text(argv[1]); isText = 1; - }else{ - pC1 = sqlite3_value_dup(argv[0]); - zHaystack = sqlite3_value_text(pC1); - if( zHaystack==0 ) goto endInstrOOM; - nHaystack = sqlite3_value_bytes(pC1); - pC2 = sqlite3_value_dup(argv[1]); - zNeedle = sqlite3_value_text(pC2); - if( zNeedle==0 ) goto endInstrOOM; - nNeedle = sqlite3_value_bytes(pC2); - isText = 1; - } - if( zNeedle==0 || (nHaystack && zHaystack==0) ) goto endInstrOOM; - firstChar = zNeedle[0]; - while( nNeedle<=nHaystack - && (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0) - ){ + } + 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; } sqlite3_result_int(context, N); -endInstr: - sqlite3_value_free(pC1); - sqlite3_value_free(pC2); - return; -endInstrOOM: - sqlite3_result_error_nomem(context); - goto endInstr; } /* -** Implementation of the printf() (a.k.a. format()) SQL function. +** Implementation of the printf() function. */ static void printfFunc( sqlite3_context *context, int argc, sqlite3_value **argv @@ -129807,11 +106436,11 @@ x.nArg = argc-1; x.nUsed = 0; x.apArg = argv+1; sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); str.printfFlags = SQLITE_PRINTF_SQLFUNC; - sqlite3_str_appendf(&str, zFormat, &x); + sqlite3XPrintf(&str, zFormat, &x); n = str.nChar; sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, SQLITE_DYNAMIC); } } @@ -129836,19 +106465,20 @@ const unsigned char *z; const unsigned char *z2; int len; int p0type; i64 p1, p2; + int negP2 = 0; assert( argc==3 || argc==2 ); if( sqlite3_value_type(argv[1])==SQLITE_NULL || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL) ){ return; } p0type = sqlite3_value_type(argv[0]); - p1 = sqlite3_value_int64(argv[1]); + p1 = sqlite3_value_int(argv[1]); if( p0type==SQLITE_BLOB ){ len = sqlite3_value_bytes(argv[0]); z = sqlite3_value_blob(argv[0]); if( z==0 ) return; assert( len==sqlite3_value_bytes(argv[0]) ); @@ -129869,36 +106499,36 @@ ** from 2009-02-02 for compatibility of applications that exploited the ** old buggy behavior. */ if( p1==0 ) p1 = 1; /* */ #endif if( argc==3 ){ - p2 = sqlite3_value_int64(argv[2]); + p2 = sqlite3_value_int(argv[2]); + if( p2<0 ){ + p2 = -p2; + negP2 = 1; + } }else{ p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; } if( p1<0 ){ p1 += len; if( p1<0 ){ - if( p2<0 ){ - p2 = 0; - }else{ - p2 += p1; - } + p2 += p1; + if( p2<0 ) p2 = 0; p1 = 0; } }else if( p1>0 ){ p1--; }else if( p2>0 ){ p2--; } - if( p2<0 ){ - if( p2<-p1 ){ - p2 = p1; - }else{ - p2 = -p2; - } + if( negP2 ){ p1 -= p2; + if( p1<0 ){ + p2 += p1; + p1 = 0; + } } assert( p1>=0 && p2>=0 ); if( p0type!=SQLITE_BLOB ){ while( *z && p1 ){ SQLITE_SKIP_UTF8(z); @@ -129908,15 +106538,13 @@ SQLITE_SKIP_UTF8(z2); } sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT, SQLITE_UTF8); }else{ - if( p1>=len ){ - p1 = p2 = 0; - }else if( p2>len-p1 ){ + if( p1+p2>len ){ p2 = len-p1; - assert( p2>0 ); + if( p2<0 ) p2 = 0; } sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT); } } @@ -129923,32 +106551,32 @@ /* ** Implementation of the round() function */ #ifndef SQLITE_OMIT_FLOATING_POINT static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - i64 n = 0; + int n = 0; double r; char *zBuf; assert( argc==1 || argc==2 ); if( argc==2 ){ if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; - n = sqlite3_value_int64(argv[1]); + n = sqlite3_value_int(argv[1]); if( n>30 ) n = 30; if( n<0 ) n = 0; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; r = sqlite3_value_double(argv[0]); /* If Y==0 and X will fit in a 64-bit int, ** handle the rounding directly, ** otherwise use printf. */ - if( r<-4503599627370496.0 || r>+4503599627370496.0 ){ - /* The value has no fractional part so there is nothing to round */ - }else if( n==0 ){ - r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); + if( n==0 && r>=0 && rmatchOne; /* "?" or "_" */ u32 matchAll = pInfo->matchAll; /* "*" or "%" */ u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ const u8 *zEscaped = 0; /* One past the last escaped input char */ - + while( (c = Utf8Read(zPattern))!=0 ){ if( c==matchAll ){ /* Match "*" */ /* Skip over multiple "*" characters in the pattern. If there ** are also "?" characters, skip those as well, but consume a ** single character of the input string for each "?" skipped */ - while( (c=Utf8Read(zPattern)) == matchAll - || (c == matchOne && matchOne!=0) ){ + while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ return SQLITE_NOWILDCARDMATCH; } } if( c==0 ){ @@ -130259,25 +106886,21 @@ ** ** For a case-insensitive search, set variable cx to be the same as ** c but in the other case and search the input string for either ** c or cx. */ - if( c<0x80 ){ - char zStop[3]; + if( c<=0x80 ){ + u32 cx; int bMatch; if( noCase ){ - zStop[0] = sqlite3Toupper(c); - zStop[1] = sqlite3Tolower(c); - zStop[2] = 0; + cx = sqlite3Toupper(c); + c = sqlite3Tolower(c); }else{ - zStop[0] = c; - zStop[1] = 0; + cx = c; } - while(1){ - zString += strcspn((const char*)zString, zStop); - if( zString[0]==0 ) break; - zString++; + while( (c2 = *(zString++))!=0 ){ + if( c2!=c && c2!=cx ) continue; bMatch = patternCompare(zPattern,zString,pInfo,matchOther); if( bMatch!=SQLITE_NOMATCH ) return bMatch; } }else{ int bMatch; @@ -130342,31 +106965,19 @@ /* ** 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){ - if( zString==0 ){ - return zGlobPattern!=0; - }else if( zGlobPattern==0 ){ - return 1; - }else { - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); - } + return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); } /* ** 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){ - if( zStr==0 ){ - return zPattern!=0; - }else if( zPattern==0 ){ - return 1; - }else{ - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); - } + return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); } /* ** Count the number of times that the LIKE operator (or GLOB which is ** just a variation of LIKE) gets called. This is used for testing @@ -130377,11 +106988,11 @@ #endif /* ** Implementation of the like() SQL function. This function implements -** the built-in LIKE operator. The first argument to the function is the +** the build-in LIKE operator. The first argument to the function is the ** pattern and the second argument is the string. So, the SQL statements: ** ** A LIKE B ** ** is implemented as like(B,A). @@ -130388,20 +106999,19 @@ ** ** This same function (with a different compareInfo structure) computes ** the GLOB operator. */ static void likeFunc( - sqlite3_context *context, - int argc, + sqlite3_context *context, + int argc, sqlite3_value **argv ){ const unsigned char *zA, *zB; u32 escape; int nPat; sqlite3 *db = sqlite3_context_db_handle(context); struct compareInfo *pInfo = sqlite3_user_data(context); - struct compareInfo backupInfo; #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS if( sqlite3_value_type(argv[0])==SQLITE_BLOB || sqlite3_value_type(argv[1])==SQLITE_BLOB ){ @@ -130410,10 +107020,12 @@ #endif sqlite3_result_int(context, 0); return; } #endif + zB = sqlite3_value_text(argv[0]); + zA = sqlite3_value_text(argv[1]); /* Limit the length of the LIKE or GLOB pattern to avoid problems ** of deep recursion and N*N behavior in patternCompare(). */ nPat = sqlite3_value_bytes(argv[0]); @@ -130421,39 +107033,32 @@ testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 ); if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); return; } + assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */ + if( argc==3 ){ /* The escape character string must consist of a single UTF-8 character. ** Otherwise, return an error. */ const unsigned char *zEsc = sqlite3_value_text(argv[2]); if( zEsc==0 ) return; if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ - sqlite3_result_error(context, + sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3Utf8Read(&zEsc); - if( escape==pInfo->matchAll || escape==pInfo->matchOne ){ - memcpy(&backupInfo, pInfo, sizeof(backupInfo)); - pInfo = &backupInfo; - if( escape==pInfo->matchAll ) pInfo->matchAll = 0; - if( escape==pInfo->matchOne ) pInfo->matchOne = 0; - } }else{ escape = pInfo->matchSet; } - zB = sqlite3_value_text(argv[0]); - zA = sqlite3_value_text(argv[1]); if( zA && zB ){ #ifdef SQLITE_TEST sqlite3_like_count++; #endif - sqlite3_result_int(context, - patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); } } /* ** Implementation of the NULLIF(x,y) function. The result is the first @@ -130541,12 +107146,12 @@ } } #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ /* -** Implementation of the sqlite_compileoption_get() function. -** The result is a string that identifies the compiler options +** Implementation of the sqlite_compileoption_get() function. +** The result is a string that identifies the compiler options ** used to build SQLite. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS static void compileoptiongetFunc( sqlite3_context *context, @@ -130566,104 +107171,95 @@ /* Array for converting from half-bytes (nybbles) into ASCII hex ** digits. */ static const char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /* -** Append to pStr text that is the SQL literal representation of the -** value contained in pValue. +** Implementation of the QUOTE() function. This function takes a single +** argument. If the argument is numeric, the return value is the same as +** the argument. If the argument is NULL, the return value is the string +** "NULL". Otherwise, the argument is enclosed in single quotes with +** single-quote escapes. */ -SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ - /* As currently implemented, the string must be initially empty. - ** we might relax this requirement in the future, but that will - ** require enhancements to the implementation. */ - assert( pStr!=0 && pStr->nChar==0 ); - - switch( sqlite3_value_type(pValue) ){ +static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + assert( argc==1 ); + UNUSED_PARAMETER(argc); + switch( sqlite3_value_type(argv[0]) ){ case SQLITE_FLOAT: { double r1, r2; - const char *zVal; - r1 = sqlite3_value_double(pValue); - sqlite3_str_appendf(pStr, "%!0.15g", r1); - zVal = sqlite3_str_value(pStr); - if( zVal ){ - sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); - if( r1!=r2 ){ - sqlite3_str_reset(pStr); - sqlite3_str_appendf(pStr, "%!0.20e", r1); - } - } + char zBuf[50]; + r1 = sqlite3_value_double(argv[0]); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); + sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8); + if( r1!=r2 ){ + sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1); + } + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); break; } case SQLITE_INTEGER: { - sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue)); + sqlite3_result_value(context, argv[0]); break; } case SQLITE_BLOB: { - char const *zBlob = sqlite3_value_blob(pValue); - i64 nBlob = sqlite3_value_bytes(pValue); - assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */ - sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4); - if( pStr->accError==0 ){ - char *zText = pStr->zText; + char *zText = 0; + char const *zBlob = sqlite3_value_blob(argv[0]); + int nBlob = sqlite3_value_bytes(argv[0]); + assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); + if( zText ){ int i; for(i=0; i>4)&0x0F]; zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; } zText[(nBlob*2)+2] = '\''; zText[(nBlob*2)+3] = '\0'; zText[0] = 'X'; zText[1] = '\''; - pStr->nChar = nBlob*2 + 3; + sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); + sqlite3_free(zText); } break; } case SQLITE_TEXT: { - const unsigned char *zArg = sqlite3_value_text(pValue); - sqlite3_str_appendf(pStr, "%Q", zArg); + int i,j; + u64 n; + const unsigned char *zArg = sqlite3_value_text(argv[0]); + char *z; + + if( zArg==0 ) return; + for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } + z = contextMalloc(context, ((i64)i)+((i64)n)+3); + if( z ){ + z[0] = '\''; + for(i=0, j=1; zArg[i]; i++){ + z[j++] = zArg[i]; + if( zArg[i]=='\'' ){ + z[j++] = '\''; + } + } + z[j++] = '\''; + z[j] = 0; + sqlite3_result_text(context, z, j, sqlite3_free); + } break; } default: { - assert( sqlite3_value_type(pValue)==SQLITE_NULL ); - sqlite3_str_append(pStr, "NULL", 4); + assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); + sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); break; } } } -/* -** Implementation of the QUOTE() function. -** -** The quote(X) function returns the text of an SQL literal which is the -** value of its argument suitable for inclusion into an SQL statement. -** Strings are surrounded by single-quotes with escapes on interior quotes -** as needed. BLOBs are encoded as hexadecimal literals. Strings with -** embedded NUL characters cannot be represented as string literals in SQL -** and hence the returned string literal is truncated prior to the first NUL. -*/ -static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - sqlite3_str str; - sqlite3 *db = sqlite3_context_db_handle(context); - assert( argc==1 ); - UNUSED_PARAMETER(argc); - sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); - sqlite3QuoteValue(&str,argv[0]); - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, - SQLITE_DYNAMIC); - if( str.accError!=SQLITE_OK ){ - sqlite3_result_null(context); - sqlite3_result_error_code(context, str.accError); - } -} - /* ** The unicode() function. Return the integer unicode code-point value -** for the first character of the input string. +** for the first character of the input string. */ static void unicodeFunc( sqlite3_context *context, int argc, sqlite3_value **argv @@ -130710,11 +107306,10 @@ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); *zOut++ = 0x80 + (u8)(c & 0x3F); } \ } - *zOut = 0; sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); } /* ** The hex() function. Interpret the argument as a blob. Return @@ -130739,104 +107334,13 @@ unsigned char c = *pBlob; *(z++) = hexdigits[(c>>4)&0xf]; *(z++) = hexdigits[c&0xf]; } *z = 0; - sqlite3_result_text64(context, zHex, (u64)(z-zHex), - sqlite3_free, SQLITE_UTF8); - } -} - -/* -** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr -** contains character ch, or 0 if it does not. -*/ -static int strContainsChar(const u8 *zStr, int nStr, u32 ch){ - const u8 *zEnd = &zStr[nStr]; - const u8 *z = zStr; - while( zmallocFailed ); return; } if( zPattern[0]==0 ){ assert( sqlite3_value_type(argv[1])!=SQLITE_NULL ); - sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT); + sqlite3_result_value(context, argv[0]); return; } nPattern = sqlite3_value_bytes(argv[1]); assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */ zRep = sqlite3_value_text(argv[2]); @@ -130907,45 +107409,38 @@ assert( nOutnPattern ){ - nOut += nRep - nPattern; - testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); - if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - sqlite3_free(zOut); - return; - } - cntExpand++; - if( (cntExpand&(cntExpand-1))==0 ){ - /* Grow the size of the output buffer only on substitutions - ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */ - u8 *zOld; - zOld = zOut; - zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1)); - if( zOut==0 ){ - sqlite3_result_error_nomem(context); - sqlite3_free(zOld); - return; - } - } + u8 *zOld; + sqlite3 *db = sqlite3_context_db_handle(context); + nOut += nRep - nPattern; + testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); + testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); + if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + sqlite3_free(zOut); + return; + } + zOld = zOut; + zOut = sqlite3_realloc64(zOut, (int)nOut); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + sqlite3_free(zOld); + return; } memcpy(&zOut[j], zRep, nRep); j += nRep; i += nPattern-1; } } - assert( j+nStr-i+1<=nOut ); + assert( j+nStr-i+1==nOut ); memcpy(&zOut[j], &zStr[i], nStr-i); j += nStr - i; assert( j<=nOut ); zOut[j] = 0; sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); @@ -130960,29 +107455,29 @@ int argc, sqlite3_value **argv ){ const unsigned char *zIn; /* Input string */ const unsigned char *zCharSet; /* Set of characters to trim */ - unsigned int nIn; /* Number of bytes in input */ + int nIn; /* Number of bytes in input */ int flags; /* 1: trimleft 2: trimright 3: trim */ int i; /* Loop counter */ - unsigned int *aLen = 0; /* Length of each character in zCharSet */ + unsigned char *aLen = 0; /* Length of each character in zCharSet */ unsigned char **azChar = 0; /* Individual characters in zCharSet */ int nChar; /* Number of characters in zCharSet */ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ return; } zIn = sqlite3_value_text(argv[0]); if( zIn==0 ) return; - nIn = (unsigned)sqlite3_value_bytes(argv[0]); + nIn = sqlite3_value_bytes(argv[0]); assert( zIn==sqlite3_value_text(argv[0]) ); if( argc==1 ){ - static const unsigned lenOne[] = { 1 }; + static const unsigned char lenOne[] = { 1 }; static unsigned char * const azOne[] = { (u8*)" " }; nChar = 1; - aLen = (unsigned*)lenOne; + aLen = (u8*)lenOne; azChar = (unsigned char **)azOne; zCharSet = 0; }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ return; }else{ @@ -130989,28 +107484,27 @@ const unsigned char *z; for(z=zCharSet, nChar=0; *z; nChar++){ SQLITE_SKIP_UTF8(z); } if( nChar>0 ){ - azChar = contextMalloc(context, - ((i64)nChar)*(sizeof(char*)+sizeof(unsigned))); + azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1)); if( azChar==0 ){ return; } - aLen = (unsigned*)&azChar[nChar]; + aLen = (unsigned char*)&azChar[nChar]; for(z=zCharSet, nChar=0; *z; nChar++){ azChar[nChar] = (unsigned char *)z; SQLITE_SKIP_UTF8(z); - aLen[nChar] = (unsigned)(z - azChar[nChar]); + aLen[nChar] = (u8)(z - azChar[nChar]); } } } if( nChar>0 ){ flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); if( flags & 1 ){ while( nIn>0 ){ - unsigned int len = 0; + int len = 0; for(i=0; i=nChar ) break; @@ -131018,11 +107512,11 @@ nIn -= len; } } if( flags & 2 ){ while( nIn>0 ){ - unsigned int len = 0; + int len = 0; for(i=0; i=nChar ) break; @@ -131034,91 +107528,16 @@ } } sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); } -/* The core implementation of the CONCAT(...) and CONCAT_WS(SEP,...) -** functions. -** -** Return a string value that is the concatenation of all non-null -** entries in argv[]. Use zSep as the separator. -*/ -static void concatFuncCore( - sqlite3_context *context, - int argc, - sqlite3_value **argv, - int nSep, - const char *zSep -){ - i64 j, k, n = 0; - int i; - char *z; - for(i=0; i0 ){ - const char *v = (const char*)sqlite3_value_text(argv[i]); - if( v!=0 ){ - if( j>0 && nSep>0 ){ - memcpy(&z[j], zSep, nSep); - j += nSep; - } - memcpy(&z[j], v, k); - j += k; - } - } - } - z[j] = 0; - assert( j<=n ); - sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8); -} - -/* -** The CONCAT(...) function. Generate a string result that is the -** concatentation of all non-null arguments. -*/ -static void concatFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - concatFuncCore(context, argc, argv, 0, ""); -} - -/* -** The CONCAT_WS(separator, ...) function. -** -** Generate a string that is the concatenation of 2nd through the Nth -** argument. Use the first argument (which must be non-NULL) as the -** separator. -*/ -static void concatwsFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int nSep = sqlite3_value_bytes(argv[0]); - const char *zSep = (const char*)sqlite3_value_text(argv[0]); - if( zSep==0 ) return; - concatFuncCore(context, argc-1, argv+1, nSep, zSep); -} - #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION /* ** The "unknown" function is automatically substituted in place of ** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN -** when the SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option is used. +** when the SQLITE_ENABLE_UNKNOWN_FUNCTION compile-time option is used. ** When the "sqlite3" command-line shell is built using this functionality, ** that allows an EXPLAIN or EXPLAIN QUERY PLAN for complex queries ** involving application-defined functions to be examined in a generic ** sqlite3 shell. */ @@ -131126,13 +107545,10 @@ sqlite3_context *context, int argc, sqlite3_value **argv ){ /* no-op */ - (void)context; - (void)argc; - (void)argv; } #endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/ /* IMP: R-25361-16150 This function is omitted from SQLite by default. It @@ -131142,11 +107558,11 @@ #ifdef SQLITE_SOUNDEX /* ** Compute the soundex encoding of a word. ** ** IMP: R-59782-00072 The soundex(X) function returns a string that is the -** soundex encoding of the string X. +** soundex encoding of the string X. */ static void soundexFunc( sqlite3_context *context, int argc, sqlite3_value **argv @@ -131230,72 +107646,17 @@ ** An instance of the following structure holds the context of a ** sum() or avg() aggregate computation. */ typedef struct SumCtx SumCtx; struct SumCtx { - double rSum; /* Running sum as as a double */ - double rErr; /* Error term for Kahan-Babushka-Neumaier summation */ - i64 iSum; /* Running sum as a signed integer */ + double rSum; /* Floating point sum */ + i64 iSum; /* Integer sum */ i64 cnt; /* Number of elements summed */ - u8 approx; /* True if any non-integer value was input to the sum */ - u8 ovrfl; /* Integer overflow seen */ + u8 overflow; /* True if integer overflow seen */ + u8 approx; /* True if non-integer value was input to the sum */ }; -/* -** Do one step of the Kahan-Babushka-Neumaier summation. -** -** https://en.wikipedia.org/wiki/Kahan_summation_algorithm -** -** Variables are marked "volatile" to defeat c89 x86 floating point -** optimizations can mess up this algorithm. -*/ -static void kahanBabuskaNeumaierStep( - volatile SumCtx *pSum, - volatile double r -){ - volatile double s = pSum->rSum; - volatile double t = s + r; - if( fabs(s) > fabs(r) ){ - pSum->rErr += (s - t) + r; - }else{ - pSum->rErr += (r - t) + s; - } - pSum->rSum = t; -} - -/* -** Add a (possibly large) integer to the running sum. -*/ -static void kahanBabuskaNeumaierStepInt64(volatile SumCtx *pSum, i64 iVal){ - if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){ - i64 iBig, iSm; - iSm = iVal % 16384; - iBig = iVal - iSm; - kahanBabuskaNeumaierStep(pSum, iBig); - kahanBabuskaNeumaierStep(pSum, iSm); - }else{ - kahanBabuskaNeumaierStep(pSum, (double)iVal); - } -} - -/* -** Initialize the Kahan-Babaska-Neumaier sum from a 64-bit integer -*/ -static void kahanBabuskaNeumaierInit( - volatile SumCtx *p, - i64 iVal -){ - if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){ - i64 iSm = iVal % 16384; - p->rSum = (double)(iVal - iSm); - p->rErr = (double)iSm; - }else{ - p->rSum = (double)iVal; - p->rErr = 0.0; - } -} - /* ** Routines used to compute the sum, average, and total. ** ** The SUM() function follows the (broken) SQL standard which means ** that it returns NULL if it sums over no inputs. TOTAL returns @@ -131311,123 +107672,56 @@ UNUSED_PARAMETER(argc); p = sqlite3_aggregate_context(context, sizeof(*p)); type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ p->cnt++; - if( p->approx==0 ){ - if( type!=SQLITE_INTEGER ){ - kahanBabuskaNeumaierInit(p, p->iSum); - p->approx = 1; - kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); - }else{ - i64 x = p->iSum; - if( sqlite3AddInt64(&x, sqlite3_value_int64(argv[0]))==0 ){ - p->iSum = x; - }else{ - p->ovrfl = 1; - kahanBabuskaNeumaierInit(p, p->iSum); - p->approx = 1; - kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); - } - } - }else{ - if( type==SQLITE_INTEGER ){ - kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); - }else{ - p->ovrfl = 0; - kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); - } - } - } -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ - SumCtx *p; - int type; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - type = sqlite3_value_numeric_type(argv[0]); - /* p is always non-NULL because sumStep() will have been called first - ** to initialize it */ - if( ALWAYS(p) && type!=SQLITE_NULL ){ - assert( p->cnt>0 ); - p->cnt--; - if( !p->approx ){ - p->iSum -= sqlite3_value_int64(argv[0]); - }else if( type==SQLITE_INTEGER ){ - i64 iVal = sqlite3_value_int64(argv[0]); - if( iVal!=SMALLEST_INT64 ){ - kahanBabuskaNeumaierStepInt64(p, -iVal); - }else{ - kahanBabuskaNeumaierStepInt64(p, LARGEST_INT64); - kahanBabuskaNeumaierStepInt64(p, 1); - } - }else{ - kahanBabuskaNeumaierStep(p, -sqlite3_value_double(argv[0])); - } - } -} -#else -# define sumInverse 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ + if( type==SQLITE_INTEGER ){ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ + p->overflow = 1; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); + p->approx = 1; + } + } +} static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - if( p->approx ){ - if( p->ovrfl ){ - sqlite3_result_error(context,"integer overflow",-1); - }else if( !sqlite3IsOverflow(p->rErr) ){ - sqlite3_result_double(context, p->rSum+p->rErr); - }else{ - sqlite3_result_double(context, p->rSum); - } + if( p->overflow ){ + sqlite3_result_error(context,"integer overflow",-1); + }else if( p->approx ){ + sqlite3_result_double(context, p->rSum); }else{ sqlite3_result_int64(context, p->iSum); } } } static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - double r; - if( p->approx ){ - r = p->rSum; - if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; - }else{ - r = (double)(p->iSum); - } - sqlite3_result_double(context, r/(double)p->cnt); + sqlite3_result_double(context, p->rSum/(double)p->cnt); } } static void totalFinalize(sqlite3_context *context){ SumCtx *p; - double r = 0.0; p = sqlite3_aggregate_context(context, 0); - if( p ){ - if( p->approx ){ - r = p->rSum; - if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr; - }else{ - r = (double)(p->iSum); - } - } - sqlite3_result_double(context, r); + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + sqlite3_result_double(context, p ? p->rSum : (double)0); } /* ** The following structure keeps track of state information for the ** count() aggregate function. */ typedef struct CountCtx CountCtx; struct CountCtx { i64 n; -#ifdef SQLITE_DEBUG - int bInverse; /* True if xInverse() ever called */ -#endif }; /* ** Routines to implement the count() aggregate function. */ @@ -131438,54 +107732,39 @@ p->n++; } #ifndef SQLITE_OMIT_DEPRECATED /* The sqlite3_aggregate_count() function is deprecated. But just to make - ** sure it still operates correctly, verify that its count agrees with our + ** sure it still operates correctly, verify that its count agrees with our ** internal count when using count(*) and when the total count can be ** expressed as a 32-bit integer. */ - assert( argc==1 || p==0 || p->n>0x7fffffff || p->bInverse + assert( argc==1 || p==0 || p->n>0x7fffffff || p->n==sqlite3_aggregate_count(context) ); #endif -} +} static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, 0); sqlite3_result_int64(context, p ? p->n : 0); } -#ifndef SQLITE_OMIT_WINDOWFUNC -static void countInverse(sqlite3_context *ctx, int argc, sqlite3_value **argv){ - CountCtx *p; - p = sqlite3_aggregate_context(ctx, sizeof(*p)); - /* p is always non-NULL since countStep() will have been called first */ - if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && ALWAYS(p) ){ - p->n--; -#ifdef SQLITE_DEBUG - p->bInverse = 1; -#endif - } -} -#else -# define countInverse 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ /* ** Routines to implement min() and max() aggregate functions. */ static void minmaxStep( - sqlite3_context *context, - int NotUsed, + sqlite3_context *context, + int NotUsed, sqlite3_value **argv ){ Mem *pArg = (Mem *)argv[0]; Mem *pBest; UNUSED_PARAMETER(NotUsed); pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( !pBest ) return; - if( sqlite3_value_type(pArg)==SQLITE_NULL ){ + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); }else if( pBest->flags ){ int max; int cmp; CollSeq *pColl = sqlite3GetFuncCollSeq(context); @@ -131507,207 +107786,70 @@ }else{ pBest->db = sqlite3_context_db_handle(context); sqlite3VdbeMemCopy(pBest, pArg); } } -static void minMaxValueFinalize(sqlite3_context *context, int bValue){ +static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); if( pRes ){ if( pRes->flags ){ sqlite3_result_value(context, pRes); } - if( bValue==0 ) sqlite3VdbeMemRelease(pRes); - } -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void minMaxValue(sqlite3_context *context){ - minMaxValueFinalize(context, 1); -} -#else -# define minMaxValue 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ -static void minMaxFinalize(sqlite3_context *context){ - minMaxValueFinalize(context, 0); + sqlite3VdbeMemRelease(pRes); + } } /* ** group_concat(EXPR, ?SEPARATOR?) -** string_agg(EXPR, SEPARATOR) -** -** Content is accumulated in GroupConcatCtx.str with the SEPARATOR -** coming before the EXPR value, except for the first entry which -** omits the SEPARATOR. -** -** It is tragic that the SEPARATOR goes before the EXPR string. The -** groupConcatInverse() implementation would have been easier if the -** SEPARATOR were appended after EXPR. And the order is undocumented, -** so we could change it, in theory. But the old behavior has been -** around for so long that we dare not, for fear of breaking something. -*/ -typedef struct { - StrAccum str; /* The accumulated concatenation */ -#ifndef SQLITE_OMIT_WINDOWFUNC - int nAccum; /* Number of strings presently concatenated */ - int nFirstSepLength; /* Used to detect separator length change */ - /* If pnSepLengths!=0, refs an array of inter-string separator lengths, - ** stored as actually incorporated into presently accumulated result. - ** (Hence, its slots in use number nAccum-1 between method calls.) - ** If pnSepLengths==0, nFirstSepLength is the length used throughout. - */ - int *pnSepLengths; -#endif -} GroupConcatCtx; - +*/ static void groupConcatStep( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zVal; - GroupConcatCtx *pGCC; + StrAccum *pAccum; const char *zSep; int nVal, nSep; assert( argc==1 || argc==2 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC)); - if( pGCC ){ + pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); + + if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); - int firstTerm = pGCC->str.mxAlloc==0; - pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; - if( argc==1 ){ - if( !firstTerm ){ - sqlite3_str_appendchar(&pGCC->str, 1, ','); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - else{ - pGCC->nFirstSepLength = 1; - } -#endif - }else if( !firstTerm ){ - zSep = (char*)sqlite3_value_text(argv[1]); - nSep = sqlite3_value_bytes(argv[1]); - if( zSep ){ - sqlite3_str_append(&pGCC->str, zSep, nSep); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - else{ - nSep = 0; - } - if( nSep != pGCC->nFirstSepLength || pGCC->pnSepLengths != 0 ){ - int *pnsl = pGCC->pnSepLengths; - if( pnsl == 0 ){ - /* First separator length variation seen, start tracking them. */ - pnsl = (int*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int)); - if( pnsl!=0 ){ - int i = 0, nA = pGCC->nAccum-1; - while( inFirstSepLength; - } - }else{ - pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int)); - } - if( pnsl!=0 ){ - if( ALWAYS(pGCC->nAccum>0) ){ - pnsl[pGCC->nAccum-1] = nSep; - } - pGCC->pnSepLengths = pnsl; - }else{ - sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM); - } - } -#endif - } -#ifndef SQLITE_OMIT_WINDOWFUNC - else{ - pGCC->nFirstSepLength = sqlite3_value_bytes(argv[1]); - } - pGCC->nAccum += 1; -#endif + int firstTerm = pAccum->mxAlloc==0; + pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; + if( !firstTerm ){ + if( argc==2 ){ + zSep = (char*)sqlite3_value_text(argv[1]); + nSep = sqlite3_value_bytes(argv[1]); + }else{ + zSep = ","; + nSep = 1; + } + if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); + } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); - if( zVal ) sqlite3_str_append(&pGCC->str, zVal, nVal); - } -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -static void groupConcatInverse( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GroupConcatCtx *pGCC; - assert( argc==1 || argc==2 ); - (void)argc; /* Suppress unused parameter warning */ - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC)); - /* pGCC is always non-NULL since groupConcatStep() will have always - ** run first to initialize it */ - if( ALWAYS(pGCC) ){ - int nVS; /* Number of characters to remove */ - /* Must call sqlite3_value_text() to convert the argument into text prior - ** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */ - (void)sqlite3_value_text(argv[0]); - nVS = sqlite3_value_bytes(argv[0]); - pGCC->nAccum -= 1; - if( pGCC->pnSepLengths!=0 ){ - assert(pGCC->nAccum >= 0); - if( pGCC->nAccum>0 ){ - nVS += *pGCC->pnSepLengths; - memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1, - (pGCC->nAccum-1)*sizeof(int)); - } - }else{ - /* If removing single accumulated string, harmlessly over-do. */ - nVS += pGCC->nFirstSepLength; - } - if( nVS>=(int)pGCC->str.nChar ){ - pGCC->str.nChar = 0; - }else{ - pGCC->str.nChar -= nVS; - memmove(pGCC->str.zText, &pGCC->str.zText[nVS], pGCC->str.nChar); - } - if( pGCC->str.nChar==0 ){ - pGCC->str.mxAlloc = 0; - sqlite3_free(pGCC->pnSepLengths); - pGCC->pnSepLengths = 0; - } - } -} -#else -# define groupConcatInverse 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ + if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); + } +} static void groupConcatFinalize(sqlite3_context *context){ - GroupConcatCtx *pGCC - = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); - if( pGCC ){ - sqlite3ResultStrAccum(context, &pGCC->str); -#ifndef SQLITE_OMIT_WINDOWFUNC - sqlite3_free(pGCC->pnSepLengths); -#endif - } -} -#ifndef SQLITE_OMIT_WINDOWFUNC -static void groupConcatValue(sqlite3_context *context){ - GroupConcatCtx *pGCC - = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); - if( pGCC ){ - StrAccum *pAccum = &pGCC->str; - if( pAccum->accError==SQLITE_TOOBIG ){ + StrAccum *pAccum; + pAccum = sqlite3_aggregate_context(context, 0); + if( pAccum ){ + if( pAccum->accError==STRACCUM_TOOBIG ){ sqlite3_result_error_toobig(context); - }else if( pAccum->accError==SQLITE_NOMEM ){ + }else if( pAccum->accError==STRACCUM_NOMEM ){ sqlite3_result_error_nomem(context); - }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){ - sqlite3_result_text(context, "", 1, SQLITE_STATIC); - }else{ - const char *zText = sqlite3_str_value(pAccum); - sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, + sqlite3_free); } } } -#else -# define groupConcatValue 0 -#endif /* SQLITE_OMIT_WINDOWFUNC */ /* ** This routine does per-connection function registration. Most ** of the built-in functions above are part of the global function set. ** This routine only deals with those that are not global. @@ -131719,67 +107861,63 @@ sqlite3OomFault(db); } } /* -** Re-register the built-in LIKE functions. The caseSensitive +** Set the LIKEOPT flag on the 2-argument function with the given name. +*/ +static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ + FuncDef *pDef; + pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0); + if( ALWAYS(pDef) ){ + pDef->funcFlags |= flagVal; + } +} + +/* +** Register the built-in LIKE and GLOB functions. The caseSensitive ** parameter determines whether or not the LIKE operator is case -** sensitive. +** sensitive. GLOB is always case sensitive. */ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ - FuncDef *pDef; struct compareInfo *pInfo; - int flags; - int nArg; if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; - flags = SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE; }else{ pInfo = (struct compareInfo*)&likeInfoNorm; - flags = SQLITE_FUNC_LIKE; - } - for(nArg=2; nArg<=3; nArg++){ - sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc, - 0, 0, 0, 0, 0); - pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0); - pDef->funcFlags |= flags; - pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE; - } + } + sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); + sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); + sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, + (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0); + setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); + setLikeOptFlag(db, "like", + caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); } /* ** 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 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. +** 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. ** ** *pIsNocase is set to true if uppercase and lowercase are equivalent for ** the function (default for LIKE). If the function makes the distinction ** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to ** false. */ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; - int nExpr; - assert( pExpr!=0 ); - assert( pExpr->op==TK_FUNCTION ); - assert( ExprUseXList(pExpr) ); - if( !pExpr->x.pList ){ + if( pExpr->op!=TK_FUNCTION + || !pExpr->x.pList + || pExpr->x.pList->nExpr!=2 + ){ return 0; } - nExpr = pExpr->x.pList->nExpr; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); -#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION - if( pDef==0 ) return 0; -#endif + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ return 0; } /* The memcpy() statement assumes that the wildcard characters are @@ -131788,349 +107926,14 @@ */ memcpy(aWc, pDef->pUserData, 3); assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); - - if( nExpr<3 ){ - aWc[3] = 0; - }else{ - Expr *pEscape = pExpr->x.pList->a[2].pExpr; - char *zEscape; - if( pEscape->op!=TK_STRING ) return 0; - assert( !ExprHasProperty(pEscape, EP_IntValue) ); - zEscape = pEscape->u.zToken; - if( zEscape[0]==0 || zEscape[1]!=0 ) return 0; - if( zEscape[0]==aWc[0] ) return 0; - if( zEscape[0]==aWc[1] ) return 0; - aWc[3] = zEscape[0]; - } - *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0; return 1; } -/* Mathematical Constants */ -#ifndef M_PI -# define M_PI 3.141592653589793238462643383279502884 -#endif -#ifndef M_LN10 -# define M_LN10 2.302585092994045684017991454684364208 -#endif -#ifndef M_LN2 -# define M_LN2 0.693147180559945309417232121458176568 -#endif - - -/* Extra math functions that require linking with -lm -*/ -#ifdef SQLITE_ENABLE_MATH_FUNCTIONS -/* -** Implementation SQL functions: -** -** ceil(X) -** ceiling(X) -** floor(X) -** -** The sqlite3_user_data() pointer is a pointer to the libm implementation -** of the underlying C function. -*/ -static void ceilingFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - assert( argc==1 ); - switch( sqlite3_value_numeric_type(argv[0]) ){ - case SQLITE_INTEGER: { - sqlite3_result_int64(context, sqlite3_value_int64(argv[0])); - break; - } - case SQLITE_FLOAT: { - double (*x)(double) = (double(*)(double))sqlite3_user_data(context); - sqlite3_result_double(context, x(sqlite3_value_double(argv[0]))); - break; - } - default: { - break; - } - } -} - -/* -** On some systems, ceil() and floor() are intrinsic function. You are -** unable to take a pointer to these functions. Hence, we here wrap them -** in our own actual functions. -*/ -static double xCeil(double x){ return ceil(x); } -static double xFloor(double x){ return floor(x); } - -/* -** Some systems do not have log2() and log10() in their standard math -** libraries. -*/ -#if defined(HAVE_LOG10) && HAVE_LOG10==0 -# define log10(X) (0.4342944819032517867*log(X)) -#endif -#if defined(HAVE_LOG2) && HAVE_LOG2==0 -# define log2(X) (1.442695040888963456*log(X)) -#endif - - -/* -** Implementation of SQL functions: -** -** ln(X) - natural logarithm -** log(X) - log X base 10 -** log10(X) - log X base 10 -** log(B,X) - log X base B -*/ -static void logFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - double x, b, ans; - assert( argc==1 || argc==2 ); - switch( sqlite3_value_numeric_type(argv[0]) ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - x = sqlite3_value_double(argv[0]); - if( x<=0.0 ) return; - break; - default: - return; - } - if( argc==2 ){ - switch( sqlite3_value_numeric_type(argv[0]) ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - b = log(x); - if( b<=0.0 ) return; - x = sqlite3_value_double(argv[1]); - if( x<=0.0 ) return; - break; - default: - return; - } - ans = log(x)/b; - }else{ - switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){ - case 1: - ans = log10(x); - break; - case 2: - ans = log2(x); - break; - default: - ans = log(x); - break; - } - } - sqlite3_result_double(context, ans); -} - -/* -** Functions to converts degrees to radians and radians to degrees. -*/ -static double degToRad(double x){ return x*(M_PI/180.0); } -static double radToDeg(double x){ return x*(180.0/M_PI); } - -/* -** Implementation of 1-argument SQL math functions: -** -** exp(X) - Compute e to the X-th power -*/ -static void math1Func( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int type0; - double v0, ans; - double (*x)(double); - assert( argc==1 ); - type0 = sqlite3_value_numeric_type(argv[0]); - if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return; - v0 = sqlite3_value_double(argv[0]); - x = (double(*)(double))sqlite3_user_data(context); - ans = x(v0); - sqlite3_result_double(context, ans); -} - -/* -** Implementation of 2-argument SQL math functions: -** -** power(X,Y) - Compute X to the Y-th power -*/ -static void math2Func( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int type0, type1; - double v0, v1, ans; - double (*x)(double,double); - assert( argc==2 ); - type0 = sqlite3_value_numeric_type(argv[0]); - if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return; - type1 = sqlite3_value_numeric_type(argv[1]); - if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return; - v0 = sqlite3_value_double(argv[0]); - v1 = sqlite3_value_double(argv[1]); - x = (double(*)(double,double))sqlite3_user_data(context); - ans = x(v0, v1); - sqlite3_result_double(context, ans); -} - -/* -** Implementation of 0-argument pi() function. -*/ -static void piFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - assert( argc==0 ); - (void)argv; - sqlite3_result_double(context, M_PI); -} - -#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */ - -/* -** Implementation of sign(X) function. -*/ -static void signFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int type0; - double x; - UNUSED_PARAMETER(argc); - assert( argc==1 ); - type0 = sqlite3_value_numeric_type(argv[0]); - if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return; - x = sqlite3_value_double(argv[0]); - sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0); -} - -#ifdef SQLITE_DEBUG -/* -** Implementation of fpdecode(x,y,z) function. -** -** x is a real number that is to be decoded. y is the precision. -** z is the maximum real precision. Return a string that shows the -** results of the sqlite3FpDecode() function. -** -** Used for testing and debugging only, specifically testing and debugging -** of the sqlite3FpDecode() function. This SQL function does not appear -** in production builds. This function is not an API and is subject to -** modification or removal in future versions of SQLite. -*/ -static void fpdecodeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - FpDecode s; - double x; - int y, z; - char zBuf[100]; - UNUSED_PARAMETER(argc); - assert( argc==3 ); - x = sqlite3_value_double(argv[0]); - y = sqlite3_value_int(argv[1]); - z = sqlite3_value_int(argv[2]); - if( z<=0 ) z = 1; - sqlite3FpDecode(&s, x, y, z); - if( s.isSpecial==2 ){ - sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN"); - }else{ - sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP); - } - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -** Implementation of parseuri(uri,flags) function. -** -** Required Arguments: -** "uri" The URI to parse. -** "flags" Bitmask of flags, as if to sqlite3_open_v2(). -** -** Additional arguments beyond the first two make calls to -** sqlite3_uri_key() for integers and sqlite3_uri_parameter for -** anything else. -** -** The result is a string showing the results of calling sqlite3ParseUri(). -** -** Used for testing and debugging only, specifically testing and debugging -** of the sqlite3ParseUri() function. This SQL function does not appear -** in production builds. This function is not an API and is subject to -** modification or removal in future versions of SQLite. -*/ -static void parseuriFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - sqlite3_str *pResult; - const char *zVfs; - const char *zUri; - unsigned int flgs; - int rc; - sqlite3_vfs *pVfs = 0; - char *zFile = 0; - char *zErr = 0; - - if( argc<2 ) return; - pVfs = sqlite3_vfs_find(0); - assert( pVfs ); - zVfs = pVfs->zName; - zUri = (const char*)sqlite3_value_text(argv[0]); - if( zUri==0 ) return; - flgs = (unsigned int)sqlite3_value_int(argv[1]); - rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr); - pResult = sqlite3_str_new(0); - if( pResult ){ - int i; - sqlite3_str_appendf(pResult, "rc=%d", rc); - sqlite3_str_appendf(pResult, ", flags=0x%x", flgs); - sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0); - sqlite3_str_appendf(pResult, ", err=%Q", zErr); - sqlite3_str_appendf(pResult, ", file=%Q", zFile); - if( zFile ){ - const char *z = zFile; - z += sqlite3Strlen30(z)+1; - while( z[0] ){ - sqlite3_str_appendf(pResult, ", %Q", z); - z += sqlite3Strlen30(z)+1; - } - for(i=2; iu.pHash){ int n = sqlite3Strlen30(p->zName); int h = p->zName[0] + n; - assert( p->funcFlags & SQLITE_FUNC_BUILTIN ); printf(" %s(%d)", p->zName, h); } printf("\n"); } } @@ -132346,29 +108089,29 @@ ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. ** If an immediate foreign key constraint is violated, ** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current -** statement transaction rolled back. If a -** deferred foreign key constraint is violated, no action is taken -** immediately. However if the application attempts to commit the +** statement transaction rolled back. If a +** deferred foreign key constraint is violated, no action is taken +** immediately. However if the application attempts to commit the ** transaction before fixing the constraint violation, the attempt fails. ** ** Deferred constraints are implemented using a simple counter associated -** with the database handle. The counter is set to zero each time a -** database transaction is opened. Each time a statement is executed +** with the database handle. The counter is set to zero each time a +** database transaction is opened. Each time a statement is executed ** that causes a foreign key violation, the counter is incremented. Each ** time a statement is executed that removes an existing violation from ** the database, the counter is decremented. When the transaction is ** committed, the commit fails if the current value of the counter is ** greater than zero. This scheme has two big drawbacks: ** -** * When a commit fails due to a deferred foreign key constraint, +** * When a commit fails due to a deferred foreign key constraint, ** there is no way to tell which foreign constraint is not satisfied, ** or which row it is not satisfied for. ** -** * If the database contains foreign key violations when the +** * If the database contains foreign key violations when the ** transaction is opened, this may cause the mechanism to malfunction. ** ** Despite these problems, this approach is adopted as it seems simpler ** than the alternatives. ** @@ -132376,42 +108119,42 @@ ** ** I.1) For each FK for which the table is the child table, search ** the parent table for a match. If none is found increment the ** constraint counter. ** -** I.2) For each FK for which the table is the parent table, +** I.2) For each FK for which the table is the parent table, ** search the child table for rows that correspond to the new ** row in the parent table. Decrement the counter for each row ** found (as the constraint is now satisfied). ** ** DELETE operations: ** -** D.1) For each FK for which the table is the child table, -** search the parent table for a row that corresponds to the -** deleted row in the child table. If such a row is not found, +** D.1) For each FK for which the table is the child table, +** search the parent table for a row that corresponds to the +** deleted row in the child table. If such a row is not found, ** decrement the counter. ** -** D.2) For each FK for which the table is the parent table, search -** the child table for rows that correspond to the deleted row +** D.2) For each FK for which the table is the parent table, search +** the child table for rows that correspond to the deleted row ** in the parent table. For each found increment the counter. ** ** UPDATE operations: ** ** An UPDATE command requires that all 4 steps above are taken, but only -** for FK constraints for which the affected columns are actually +** for FK constraints for which the affected columns are actually ** modified (values must be compared at runtime). ** ** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2. ** This simplifies the implementation a bit. ** ** For the purposes of immediate FK constraints, the OR REPLACE conflict ** resolution is considered to delete rows before the new row is inserted. ** If a delete caused by OR REPLACE violates an FK constraint, an exception -** is thrown, even if the FK constraint would be satisfied after the new +** is thrown, even if the FK constraint would be satisfied after the new ** row is inserted. ** -** Immediate constraints are usually handled similarly. The only difference +** Immediate constraints are usually handled similarly. The only difference ** is that the counter used is stored as part of each individual statement ** object (struct Vdbe). If, after the statement has run, its immediate ** constraint counter is greater than zero, ** it returns SQLITE_CONSTRAINT_FOREIGNKEY ** and the statement transaction is rolled back. An exception is an INSERT @@ -132418,11 +108161,11 @@ ** statement that inserts a single row only (no triggers). In this case, ** instead of using a counter, an exception is thrown immediately if the ** INSERT violates a foreign key constraint. This is necessary as such ** an INSERT does not open a statement transaction. ** -** TODO: How should dropping a table be handled? How should renaming a +** TODO: How should dropping a table be handled? How should renaming a ** table be handled? ** ** ** Query API Notes ** --------------- @@ -132429,11 +108172,11 @@ ** ** Before coding an UPDATE or DELETE row operation, the code-generator ** for those two operations needs to know whether or not the operation ** requires any FK processing and, if so, which columns of the original ** row are required by the FK processing VDBE code (i.e. if FKs were -** implemented using triggers, which of the old.* columns would be +** implemented using triggers, which of the old.* columns would be ** accessed). No information is required by the code-generator before ** coding an INSERT operation. The functions used by the UPDATE/DELETE ** generation code to query for this information are: ** ** sqlite3FkRequired() - Test to see if FK processing is required. @@ -132466,17 +108209,17 @@ */ /* ** A foreign key constraint requires that the key columns in the parent ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. -** Given that pParent is the parent table for foreign key constraint pFKey, -** search the schema for a unique index on the parent key columns. +** Given that pParent is the parent table for foreign key constraint pFKey, +** search the schema for a unique index on the parent key columns. ** -** If successful, zero is returned. If the parent key is an INTEGER PRIMARY -** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx -** is set to point to the unique index. -** +** If successful, zero is returned. If the parent key is an INTEGER PRIMARY +** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx +** is set to point to the unique index. +** ** If the parent key consists of a single column (the foreign key constraint ** is not a composite foreign key), output variable *paiCol is set to NULL. ** Otherwise, it is set to point to an allocated array of size N, where ** N is the number of columns in the parent key. The first element of the ** array is the index of the child table column that is mapped by the FK @@ -132495,12 +108238,12 @@ ** 3) No parent key columns were provided explicitly as part of the ** foreign key definition, and the parent table does not have a ** PRIMARY KEY, or ** ** 4) No parent key columns were provided explicitly as part of the -** foreign key definition, and the PRIMARY KEY of the parent table -** consists of a different number of columns to the child key in +** foreign key definition, and the PRIMARY KEY of the parent table +** consists of a different number of columns to the child key in ** the child table. ** ** then non-zero is returned, and a "foreign key mismatch" error loaded ** into pParse. If an OOM error occurs, non-zero is returned and the ** pParse->db->mallocFailed flag is set. @@ -132520,48 +108263,46 @@ /* The caller is responsible for zeroing output parameters. */ assert( ppIdx && *ppIdx==0 ); assert( !paiCol || *paiCol==0 ); assert( pParse ); - /* If this is a non-composite (single column) foreign key, check if it - ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx - ** and *paiCol set to zero and return early. + /* If this is a non-composite (single column) foreign key, check if it + ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx + ** and *paiCol set to zero and return early. ** ** Otherwise, for a composite foreign key (more than one column), allocate ** space for the aiCol array (returned via output parameter *paiCol). ** Non-composite foreign keys do not require the aiCol array. */ if( nCol==1 ){ /* The FK maps to the IPK if any of the following are true: ** - ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly + ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly ** mapped to the primary key of table pParent, or ** 2) The FK is explicitly mapped to a column declared as INTEGER ** PRIMARY KEY. */ if( pParent->iPKey>=0 ){ if( !zKey ) return 0; - if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){ - return 0; - } + if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; } }else if( paiCol ){ assert( nCol>1 ); aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); if( !aiCol ) return 1; *paiCol = aiCol; } for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){ + 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. */ if( zKey==0 ){ - /* If zKey is NULL, then this foreign key is implicitly mapped to - ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be + /* If zKey is NULL, then this foreign key is implicitly mapped to + ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be ** identified by the test. */ if( IsPrimaryKeyIndex(pIdx) ){ if( aiCol ){ int i; for(i=0; iaCol[i].iFrom; @@ -132582,15 +108323,15 @@ if( iCol<0 ) break; /* No foreign keys against expression indexes */ /* If the index uses a collation sequence that is different from ** the default collation sequence for the column, this index is ** unusable. Bail out early in this case. */ - zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]); + zDfltColl = pParent->aCol[iCol].zColl; if( !zDfltColl ) zDfltColl = sqlite3StrBINARY; if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; - zIdxCol = pParent->aCol[iCol].zCnName; + zIdxCol = pParent->aCol[iCol].zName; for(j=0; jaCol[j].zCol, zIdxCol)==0 ){ if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; break; } @@ -132615,19 +108356,19 @@ *ppIdx = pIdx; return 0; } /* -** This function is called when a row is inserted into or deleted from the -** child table of foreign key constraint pFKey. If an SQL UPDATE is executed +** This function is called when a row is inserted into or deleted from the +** child table of foreign key constraint pFKey. If an SQL UPDATE is executed ** on the child table of pFKey, this function is invoked twice for each row ** affected - once to "delete" the old row, and then again to "insert" the ** new row. ** ** Each time it is called, this function generates VDBE code to locate the -** row in the parent table that corresponds to the row being inserted into -** or deleted from the child table. If the parent row can be found, no +** row in the parent table that corresponds to the row being inserted into +** or deleted from the child table. If the parent row can be found, no ** special action is taken. Otherwise, if the parent row can *not* be ** found in the parent table: ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- @@ -132637,11 +108378,11 @@ ** ** INSERT deferred Increment the "deferred constraint counter". ** ** DELETE deferred Decrement the "deferred constraint counter". ** -** These operations are identified in the comment at the top of this file +** These operations are identified in the comment at the top of this file ** (fkey.c) as "I.1" and "D.1". */ static void fkLookupParent( Parse *pParse, /* Parse context */ int iDb, /* Index of database housing pTab */ @@ -132654,96 +108395,85 @@ int isIgnore /* If true, pretend pTab contains all NULL values */ ){ int i; /* Iterator variable */ Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */ int iCur = pParse->nTab - 1; /* Cursor number to use */ - int iOk = sqlite3VdbeMakeLabel(pParse); /* jump here if parent key found */ - - sqlite3VdbeVerifyAbortable(v, - (!pFKey->isDeferred - && !(pParse->db->flags & SQLITE_DeferFKs) - && !pParse->pToplevel - && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore); + int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ /* If nIncr is less than zero, then check at runtime if there are any ** outstanding constraints to resolve. If there are not, there is no need ** to check if deleting this row resolves any outstanding violations. ** - ** Check if any of the key columns in the child table row are NULL. If - ** any are, then the constraint is considered satisfied. No need to + ** Check if any of the key columns in the child table row are NULL. If + ** any are, then the constraint is considered satisfied. No need to ** search for a matching row in the parent table. */ if( nIncr<0 ){ sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); VdbeCoverage(v); } for(i=0; inCol; i++){ - int iReg = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i]) + regData + 1; + int iReg = aiCol[i] + regData + 1; sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v); } if( isIgnore==0 ){ if( pIdx==0 ){ /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY ** column of the parent table (table pTab). */ int iMustBeInt; /* Address of MustBeInt instruction */ int regTemp = sqlite3GetTempReg(pParse); - - /* Invoke MustBeInt to coerce the child key value to an integer (i.e. + + /* Invoke MustBeInt to coerce the child key value to an integer (i.e. ** apply the affinity of the parent key). If this fails, then there ** is no matching parent key. Before using MustBeInt, make a copy of ** the value. Otherwise, the value inserted into the child key column ** will have INTEGER affinity applied to it, which may not be correct. */ - sqlite3VdbeAddOp2(v, OP_SCopy, - sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[0])+1+regData, regTemp); + sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); VdbeCoverage(v); - + /* If the parent table is the same as the child table, and we are about ** to increment the constraint-counter (i.e. this is an INSERT operation), ** then check if the row being inserted matches itself. If so, do not ** increment the constraint-counter. */ if( pTab==pFKey->pFrom && nIncr==1 ){ sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); } - + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); sqlite3VdbeGoto(v, iOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); sqlite3VdbeJumpHere(v, iMustBeInt); sqlite3ReleaseTempReg(pParse, regTemp); }else{ int nCol = pFKey->nCol; int regTemp = sqlite3GetTempRange(pParse, nCol); - + int regRec = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); for(i=0; ipFrom, aiCol[i])+1+regData, - regTemp+i); + sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i); } - + /* If the parent table is the same as the child table, and we are about ** to increment the constraint-counter (i.e. this is an INSERT operation), ** then check if the row being inserted matches itself. If so, do not - ** increment the constraint-counter. + ** increment the constraint-counter. ** - ** If any of the parent-key values are NULL, then the row cannot match + ** If any of the parent-key values are NULL, then the row cannot match ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any ** of the parent-key values are NULL (at this point it is known that ** none of the child key values are). */ if( pTab==pFKey->pFrom && nIncr==1 ){ int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; for(i=0; ipFrom,aiCol[i]) - +1+regData; - int iParent = 1+regData; - iParent += sqlite3TableColumnToStorage(pIdx->pTable, - pIdx->aiColumn[i]); + int iChild = aiCol[i]+1+regData; + int iParent = pIdx->aiColumn[i]+1+regData; assert( pIdx->aiColumn[i]>=0 ); assert( aiCol[i]!=pTab->iPKey ); if( pIdx->aiColumn[i]==pTab->iPKey ){ /* The parent key is a composite key that includes the IPK column */ iParent = regData; @@ -132751,22 +108481,23 @@ sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } sqlite3VdbeGoto(v, iOk); } - - sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0, + + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, sqlite3IndexAffinityStr(pParse->db,pIdx), nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol); - VdbeCoverage(v); + sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); + + sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempRange(pParse, regTemp, nCol); } } if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) - && !pParse->pToplevel - && !pParse->isMultiWrite + && !pParse->pToplevel + && !pParse->isMultiWrite ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being ** generated for will not open a statement transaction. */ @@ -132806,18 +108537,18 @@ pExpr = sqlite3Expr(db, TK_REGISTER, 0); if( pExpr ){ if( iCol>=0 && iCol!=pTab->iPKey ){ pCol = &pTab->aCol[iCol]; - pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1; - pExpr->affExpr = pCol->affinity; - zColl = sqlite3ColumnColl(pCol); + pExpr->iTable = regBase + iCol + 1; + pExpr->affinity = pCol->affinity; + zColl = pCol->zColl; if( zColl==0 ) zColl = db->pDfltColl->zName; pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl); }else{ pExpr->iTable = regBase; - pExpr->affExpr = SQLITE_AFF_INTEGER; + pExpr->affinity = SQLITE_AFF_INTEGER; } } return pExpr; } @@ -132831,21 +108562,20 @@ int iCursor, /* The open cursor on the table */ i16 iCol /* The column that is wanted */ ){ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); if( pExpr ){ - assert( ExprUseYTab(pExpr) ); - pExpr->y.pTab = pTab; + pExpr->pTab = pTab; pExpr->iTable = iCursor; pExpr->iColumn = iCol; } return pExpr; } /* ** This function is called to generate code executed when a row is deleted -** from the parent table of foreign key constraint pFKey and, if pFKey is +** from the parent table of foreign key constraint pFKey and, if pFKey is ** deferred, when a row is inserted into the same table. When generating ** code for an SQL UPDATE operation, this function may be called twice - ** once to "delete" the old row and once to "insert" the new row. ** ** Parameter nIncr is passed -1 when inserting a row (as this may decrease @@ -132857,18 +108587,22 @@ ** For each child row found, one of the following actions is taken: ** ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- ** DELETE immediate Increment the "immediate constraint counter". +** Or, if the ON (UPDATE|DELETE) action is RESTRICT, +** throw a "FOREIGN KEY constraint failed" exception. ** ** INSERT immediate Decrement the "immediate constraint counter". ** ** DELETE deferred Increment the "deferred constraint counter". +** Or, if the ON (UPDATE|DELETE) action is RESTRICT, +** throw a "FOREIGN KEY constraint failed" exception. ** ** INSERT deferred Decrement the "deferred constraint counter". ** -** These operations are identified in the comment at the top of this file +** These operations are identified in the comment at the top of this file ** (fkey.c) as "I.2" and "D.2". */ static void fkScanChildren( Parse *pParse, /* Parse context */ SrcList *pSrc, /* The child table to be scanned */ @@ -132907,21 +108641,21 @@ */ for(i=0; inCol; i++){ Expr *pLeft; /* Value from parent table row */ Expr *pRight; /* Column ref to child table */ Expr *pEq; /* Expression (pLeft = pRight) */ - i16 iCol; /* Index of column in child table */ + i16 iCol; /* Index of column in child table */ const char *zCol; /* Name of column in child table */ iCol = pIdx ? pIdx->aiColumn[i] : -1; pLeft = exprTableRegister(pParse, pTab, regData, iCol); iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iCol>=0 ); - zCol = pFKey->pFrom->aCol[iCol].zCnName; + zCol = pFKey->pFrom->aCol[iCol].zName; pRight = sqlite3Expr(db, TK_ID, zCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); - pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); + pWhere = sqlite3ExprAnd(db, pWhere, pEq); } /* If the child table is the same as the parent table, then add terms ** to the WHERE clause that prevent this entry from being scanned. ** The added WHERE clause terms are like this: @@ -132928,15 +108662,12 @@ ** ** $current_rowid!=rowid ** NOT( $current_a==a AND $current_b==b AND ... ) ** ** The first form is used for rowid tables. The second form is used - ** for WITHOUT ROWID tables. In the second form, the *parent* key is - ** (a,b,...). Either the parent or primary key could be used to - ** uniquely identify the current row, but the parent key is more convenient - ** as the required values have already been loaded into registers - ** by the caller. + ** for WITHOUT ROWID tables. In the second form, the primary key is + ** (a,b,...) */ if( pTab==pFKey->pFrom && nIncr>0 ){ Expr *pNe; /* Expression (pLeft != pRight) */ Expr *pLeft; /* Value from parent table row */ Expr *pRight; /* Column ref to child table */ @@ -132944,22 +108675,23 @@ pLeft = exprTableRegister(pParse, pTab, regData, -1); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight); }else{ Expr *pEq, *pAll = 0; + Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pIdx!=0 ); - for(i=0; inKeyCol; i++){ + for(i=0; inKeyCol; i++){ i16 iCol = pIdx->aiColumn[i]; assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); - pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName); - pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight); - pAll = sqlite3ExprAnd(pParse, pAll, pEq); + pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); + pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); + pAll = sqlite3ExprAnd(db, pAll, pEq); } pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); } - pWhere = sqlite3ExprAnd(pParse, pWhere, pNe); + pWhere = sqlite3ExprAnd(db, pWhere, pNe); } /* Resolve the references in the WHERE clause. */ memset(&sNameContext, 0, sizeof(NameContext)); sNameContext.pSrcList = pSrc; @@ -132968,21 +108700,21 @@ /* 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. */ if( pParse->nErr==0 ){ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 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. */ sqlite3ExprDelete(db, pWhere); if( iFkIfZero ){ - sqlite3VdbeJumpHereOrPopInst(v, iFkIfZero); + sqlite3VdbeJumpHere(v, iFkIfZero); } } /* ** This function returns a linked list of FKey objects (connected by @@ -133001,11 +108733,11 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName); } /* -** The second argument is a Trigger structure allocated by the +** The second argument is a Trigger structure allocated by the ** fkActionTrigger() routine. This function deletes the Trigger structure ** and all of its sub-components. ** ** The Trigger structure or any of its sub-components may be allocated from ** the lookaside buffer belonging to database handle dbMem. @@ -133019,29 +108751,10 @@ sqlite3ExprDelete(dbMem, p->pWhen); sqlite3DbFree(dbMem, p); } } -/* -** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys -** in a particular database. This needs to happen when the schema -** changes. -*/ -SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){ - HashElem *k; - Hash *pHash = &db->aDb[iDb].pSchema->tblHash; - for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){ - Table *pTab = sqliteHashData(k); - FKey *pFKey; - if( !IsOrdinaryTable(pTab) ) continue; - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ - fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0; - fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0; - } - } -} - /* ** This function is called to generate code that runs when table pTab is ** being dropped from the database. The SrcList passed as the second argument ** to this function contains a single entry guaranteed to resolve to ** table pTab. @@ -133048,55 +108761,53 @@ ** ** Normally, no code is required. However, if either ** ** (a) The table is the parent table of a FK constraint, or ** (b) The table is the child table of a deferred FK constraint and it is -** determined at runtime that there are outstanding deferred FK +** determined at runtime that there are outstanding deferred FK ** constraint violations in the database, ** ** then the equivalent of "DELETE FROM " is executed before dropping ** the table from the database. Triggers are disabled while running this ** DELETE, but foreign key actions are not. */ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ sqlite3 *db = pParse->db; - if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){ + if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ int iSkip = 0; Vdbe *v = sqlite3GetVdbe(pParse); assert( v ); /* VDBE has already been allocated */ - assert( IsOrdinaryTable(pTab) ); if( sqlite3FkReferences(pTab)==0 ){ /* Search for a deferred foreign key constraint for which this table - ** is the child table. If one cannot be found, return without + ** is the child table. If one cannot be found, return without ** generating any VDBE code. If one can be found, then jump over ** the entire DELETE if there are no outstanding deferred constraints ** when this statement is run. */ FKey *p; - for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ + for(p=pTab->pFKey; p; p=p->pNextFrom){ if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; } if( !p ) return; - iSkip = sqlite3VdbeMakeLabel(pParse); + iSkip = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); } pParse->disableTriggers = 1; - sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0); + sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); pParse->disableTriggers = 0; - /* If the DELETE has generated immediate foreign key constraint + /* If the DELETE has generated immediate foreign key constraint ** violations, halt the VDBE and return an error at this point, before ** any modifications to the schema are made. This is because statement - ** transactions are not able to rollback schema changes. + ** transactions are not able to rollback schema changes. ** ** If the SQLITE_DeferFKs flag is set, then this is not required, as ** the statement transaction will not be rolled back even if FK ** constraints are violated. */ if( (db->flags & SQLITE_DeferFKs)==0 ){ - sqlite3VdbeVerifyAbortable(v, OE_Abort); sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, OE_Abort, 0, P4_STATIC, P5_ConstraintFK); } @@ -133109,11 +108820,11 @@ /* ** The second argument points to an FKey object representing a foreign key ** for which pTab is the child table. An UPDATE statement against pTab -** is currently being processed. For each column of the table that is +** is currently being processed. For each column of the table that is ** actually updated, the corresponding element in the aChange[] array ** is zero or greater (if a column is unmodified the corresponding element ** is set to -1). If the rowid column is modified by the UPDATE statement ** the bChngRowid argument is non-zero. ** @@ -133136,23 +108847,23 @@ } /* ** The second argument points to an FKey object representing a foreign key ** for which pTab is the parent table. An UPDATE statement against pTab -** is currently being processed. For each column of the table that is +** is currently being processed. For each column of the table that is ** actually updated, the corresponding element in the aChange[] array ** is zero or greater (if a column is unmodified the corresponding element ** is set to -1). If the rowid column is modified by the UPDATE statement ** the bChngRowid argument is non-zero. ** ** This function returns true if any of the columns that are part of the ** parent key for FK constraint *p are modified. */ static int fkParentIsModified( - Table *pTab, - FKey *p, - int *aChange, + Table *pTab, + FKey *p, + int *aChange, int bChngRowid ){ int i; for(i=0; inCol; i++){ char *zKey = p->aCol[i].zCol; @@ -133159,11 +108870,11 @@ int iKey; for(iKey=0; iKeynCol; iKey++){ if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){ Column *pCol = &pTab->aCol[iKey]; if( zKey ){ - if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1; + if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1; }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ return 1; } } } @@ -133181,20 +108892,19 @@ if( pTop->pTriggerPrg ){ Trigger *p = pTop->pTriggerPrg->pTrigger; if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) ){ - assert( (pTop->db->flags & SQLITE_FkNoAction)==0 ); return 1; } } return 0; } /* ** This function is called when inserting, deleting or updating a row of -** table pTab to generate VDBE code to perform foreign key constraint +** table pTab to generate VDBE code to perform foreign key constraint ** processing for the operation. ** ** For a DELETE operation, parameter regOld is passed the index of the ** first register in an array of (pTab->nCol+1) registers containing the ** rowid of the row being deleted, followed by each of the column values @@ -133206,15 +108916,15 @@ ** row data. ** ** For an UPDATE operation, this function is called twice. Once before ** the original record is deleted from the table using the calling convention ** described for DELETE. Then again after the original record is deleted -** but before the new record is inserted using the INSERT convention. +** but before the new record is inserted using the INSERT convention. */ SQLITE_PRIVATE void sqlite3FkCheck( Parse *pParse, /* Parse context */ - Table *pTab, /* Row is being deleted from this table */ + Table *pTab, /* Row is being deleted from this table */ int regOld, /* Previous row data is stored here */ int regNew, /* New row data is stored here */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ @@ -133227,36 +108937,35 @@ /* Exactly one of regOld and regNew should be non-zero. */ assert( (regOld==0)!=(regNew==0) ); /* If foreign-keys are disabled, this function is a no-op. */ if( (db->flags&SQLITE_ForeignKeys)==0 ) return; - if( !IsOrdinaryTable(pTab) ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ + for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ Table *pTo; /* Parent table of foreign key pFKey */ Index *pIdx = 0; /* Index on key columns in pTo */ int *aiFree = 0; int *aiCol; int iCol; int i; int bIgnore = 0; - if( aChange + if( aChange && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 - && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 + && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ continue; } - /* Find the parent table of this foreign key. Also find a unique index - ** on the parent key columns in the parent table. If either of these - ** schema items cannot be located, set an error in pParse and return + /* Find the parent table of this foreign key. Also find a unique index + ** on the parent key columns in the parent table. If either of these + ** schema items cannot be located, set an error in pParse and return ** early. */ if( pParse->disableTriggers ){ pTo = sqlite3FindTable(db, pFKey->zTo, zDb); }else{ pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); @@ -133273,13 +108982,11 @@ ** FK counter for each row of the current table with non-NULL keys. */ Vdbe *v = sqlite3GetVdbe(pParse); int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; for(i=0; inCol; i++){ - int iFromCol, iReg; - iFromCol = pFKey->aCol[i].iFrom; - iReg = sqlite3TableColumnToStorage(pFKey->pFrom,iFromCol) + regOld+1; + int iReg = pFKey->aCol[i].iFrom + regOld + 1; sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); } continue; @@ -133296,40 +109003,40 @@ if( aiCol[i]==pTab->iPKey ){ aiCol[i] = -1; } assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION - /* Request permission to read the parent key columns. If the + /* Request permission to read the parent key columns. If the ** authorization callback returns SQLITE_IGNORE, behave as if any ** values read from the parent table are NULL. */ if( db->xAuth ){ int rcauth; - char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName; + char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); bIgnore = (rcauth==SQLITE_IGNORE); } #endif } - /* Take a shared-cache advisory read-lock on the parent table. Allocate - ** a cursor to use to search the unique index on the parent key columns + /* Take a shared-cache advisory read-lock on the parent table. Allocate + ** a cursor to use to search the unique index on the parent key columns ** in the parent table. */ sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); pParse->nTab++; if( regOld!=0 ){ /* A row is being removed from the child table. Search for the parent. - ** If the parent does not exist, removing the child row resolves an + ** If the parent does not exist, removing the child row resolves an ** outstanding foreign key constraint violation. */ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); } if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ /* A row is being added to the child table. If a parent row cannot - ** be found, adding the child row has violated the FK constraint. + ** be found, adding the child row has violated the FK constraint. ** ** If this operation is being performed as part of a trigger program - ** that is actually a "SET NULL" action belonging to this very + ** that is actually a "SET NULL" action belonging to this very ** foreign key, then omit this scan altogether. As all child key ** values are guaranteed to be NULL, it is not possible for adding ** this row to cause an FK violation. */ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); } @@ -133346,12 +109053,12 @@ if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ continue; } - if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) - && !pParse->pToplevel && !pParse->isMultiWrite + if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) + && !pParse->pToplevel && !pParse->isMultiWrite ){ assert( regOld==0 && regNew!=0 ); /* Inserting a single row into a parent table cannot cause (or fix) ** an immediate foreign key violation. So do nothing in this case. */ continue; @@ -133363,25 +109070,23 @@ } assert( aiCol || pFKey->nCol==1 ); /* Create a SrcList structure containing the child table. We need the ** child table as a SrcList for sqlite3WhereBegin() */ - pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); + pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ - SrcItem *pItem = pSrc->a; - pItem->pSTab = pFKey->pFrom; + struct SrcList_item *pItem = pSrc->a; + pItem->pTab = pFKey->pFrom; pItem->zName = pFKey->pFrom->zName; - pItem->pSTab->nTabRef++; + pItem->pTab->nTabRef++; pItem->iCursor = pParse->nTab++; - + if( regNew!=0 ){ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); } if( regOld!=0 ){ int eAction = pFKey->aAction[aChange!=0]; - if( (db->flags & SQLITE_FkNoAction) ) eAction = OE_None; - fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); /* If this is a deferred FK constraint, or a CASCADE or SET NULL ** action applies, then any foreign key violations caused by ** removing the parent key will be rectified by the action trigger. ** So do not set the "may-abort" flag in this case. @@ -133391,14 +109096,14 @@ ** (when this function is called as part of processing the UPDATE ** within the action trigger). ** ** Note 2: At first glance it may seem like SQLite could simply omit ** all OP_FkCounter related scans when either CASCADE or SET NULL - ** applies. The trouble starts if the CASCADE or SET NULL action - ** trigger causes other triggers or action rules attached to the + ** applies. The trouble starts if the CASCADE or SET NULL action + ** trigger causes other triggers or action rules attached to the ** child table to fire. In these cases the fk constraint counters - ** might be set incorrectly if any OP_FkCounter related scans are + ** might be set incorrectly if any OP_FkCounter related scans are ** omitted. */ if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ sqlite3MayAbort(pParse); } } @@ -133410,22 +109115,22 @@ } #define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) /* -** This function is called before generating code to update or delete a +** This function is called before generating code to update or delete a ** row contained in table pTab. */ SQLITE_PRIVATE u32 sqlite3FkOldmask( Parse *pParse, /* Parse context */ Table *pTab /* Table being modified */ ){ u32 mask = 0; - if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){ + if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *p; int i; - for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ + for(p=pTab->pFKey; p; p=p->pNextFrom){ for(i=0; inCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); } for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ Index *pIdx = 0; sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); @@ -133440,28 +109145,26 @@ return mask; } /* -** This function is called before generating code to update or delete a +** This function is called before generating code to update or delete a ** row contained in table pTab. If the operation is a DELETE, then ** parameter aChange is passed a NULL value. For an UPDATE, aChange points ** to an array of size N, where N is the number of columns in table pTab. -** If the i'th column is not modified by the UPDATE, then the corresponding +** If the i'th column is not modified by the UPDATE, then the corresponding ** entry in the aChange[] array is set to -1. If the column is modified, ** the value is 0 or greater. Parameter chngRowid is set to true if the ** UPDATE statement modifies the rowid fields of the table. ** ** If any foreign key processing will be required, this function returns -** non-zero. If there is no foreign key related processing, this function +** 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 -** and any FK processing at all is required (even of a different FK), or -** +** * 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. */ @@ -133469,61 +109172,56 @@ Parse *pParse, /* Parse context */ Table *pTab, /* Table being modified */ int *aChange, /* Non-NULL for UPDATE operations */ int chngRowid /* True for UPDATE that affects rowid */ ){ - int eRet = 1; /* Value to return if bHaveFK is true */ - int bHaveFK = 0; /* If FK processing is required */ - if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){ + 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 + /* 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. */ - bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.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. */ FKey *p; /* Check if any child key columns are being modified. */ - for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ + for(p=pTab->pFKey; p; p=p->pNextFrom){ + if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2; if( fkChildIsModified(pTab, p, aChange, chngRowid) ){ - if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2; - bHaveFK = 1; + 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) ){ - if( (pParse->db->flags & SQLITE_FkNoAction)==0 - && p->aAction[1]!=OE_None - ){ - return 2; - } - bHaveFK = 1; + if( p->aAction[1]!=OE_None ) return 2; + eRet = 1; } } } } - return bHaveFK ? eRet : 0; + return eRet; } /* -** This function is called when an UPDATE or DELETE operation is being +** This function is called when an UPDATE or DELETE operation is being ** compiled on table pTab, which is the parent table of foreign-key pFKey. ** If the current operation is an UPDATE, then the pChanges parameter is ** passed a pointer to the list of columns being modified. If it is a ** DELETE, pChanges is passed a NULL pointer. ** ** It returns a pointer to a Trigger structure containing a trigger ** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. -** If the action is "NO ACTION" then a NULL pointer is returned (these actions -** require no special handling by the triggers sub-system, code for them is -** created by fkScanChildren()). +** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is +** returned (these actions require no special handling by the triggers +** sub-system, code for them is created by fkScanChildren()). ** -** For example, if pFKey is the foreign key and pTab is table "p" in +** For example, if pFKey is the foreign key and pTab is table "p" in ** the following schema: ** ** CREATE TABLE p(pk PRIMARY KEY); ** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); ** @@ -133532,11 +109230,11 @@ ** CREATE TRIGGER ... DELETE ON p BEGIN ** DELETE FROM c WHERE ck = old.pk; ** END; ** ** The returned pointer is cached as part of the foreign key object. It -** is eventually freed along with the rest of the foreign key object by +** is eventually freed along with the rest of the foreign key object by ** sqlite3FkDelete(). */ static Trigger *fkActionTrigger( Parse *pParse, /* Parse context */ Table *pTab, /* Table being updated or deleted from */ @@ -133547,11 +109245,10 @@ int action; /* One of OE_None, OE_Cascade etc. */ Trigger *pTrigger; /* Trigger definition to return */ int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ action = pFKey->aAction[iAction]; - if( (db->flags & SQLITE_FkNoAction) ) action = OE_None; if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ return 0; } pTrigger = pFKey->apTrigger[iAction]; @@ -133581,58 +109278,50 @@ iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); sqlite3TokenInit(&tToCol, - pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName); - sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName); + pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName); + sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName); /* Create the expression "OLD.zToCol = zFromCol". It is important ** that the "OLD.zToCol" term is on the LHS of the = operator, so ** that the affinity and collation sequence associated with the ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, - sqlite3PExpr(pParse, TK_DOT, + sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tOld, 0), sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) ); - pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); + pWhere = sqlite3ExprAnd(db, pWhere, pEq); /* For ON UPDATE, construct the next term of the WHEN clause. ** The final WHEN clause will be like this: ** ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) */ if( pChanges ){ pEq = sqlite3PExpr(pParse, TK_IS, - sqlite3PExpr(pParse, TK_DOT, + sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tOld, 0), sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), - sqlite3PExpr(pParse, TK_DOT, + sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tNew, 0), sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)) ); - pWhen = sqlite3ExprAnd(pParse, pWhen, pEq); + pWhen = sqlite3ExprAnd(db, pWhen, pEq); } - + if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ Expr *pNew; if( action==OE_Cascade ){ - pNew = sqlite3PExpr(pParse, TK_DOT, + pNew = sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tNew, 0), sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)); }else if( action==OE_SetDflt ){ - Column *pCol = pFKey->pFrom->aCol + iFromCol; - Expr *pDflt; - if( pCol->colFlags & COLFLAG_GENERATED ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - pDflt = 0; - }else{ - pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol); - } + Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; if( pDflt ){ pNew = sqlite3ExprDup(db, pDflt, 0); }else{ pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); } @@ -133647,48 +109336,41 @@ zFrom = pFKey->pFrom->zName; nFrom = sqlite3Strlen30(zFrom); if( action==OE_Restrict ){ - int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - SrcList *pSrc; - Expr *pRaise; + Token tFrom; + Expr *pRaise; - pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"), - pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0); + tFrom.z = zFrom; + tFrom.n = nFrom; + pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); if( pRaise ){ - pRaise->affExpr = OE_Abort; - } - pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - if( pSrc ){ - assert( pSrc->nSrc==1 ); - pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom); - assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 ); - pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); - } - pSelect = sqlite3SelectNew(pParse, + pRaise->affinity = OE_Abort; + } + pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), - pSrc, + sqlite3SrcListAppend(db, 0, &tFrom, 0), pWhere, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 ); pWhere = 0; } /* Disable lookaside memory allocation */ - DisableLookaside; + db->lookaside.bDisable++; - pTrigger = (Trigger *)sqlite3DbMallocZero(db, + pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ sizeof(TriggerStep) + /* Single step in trigger program */ nFrom + 1 /* Space for pStep->zTarget */ ); if( pTrigger ){ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; pStep->zTarget = (char *)&pStep[1]; memcpy((char *)pStep->zTarget, zFrom, nFrom); - + pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); if( pWhen ){ pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0); @@ -133695,11 +109377,11 @@ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); } } /* Re-enable the lookaside buffer, if it was disabled earlier. */ - EnableLookaside; + db->lookaside.bDisable--; sqlite3ExprDelete(db, pWhere); sqlite3ExprDelete(db, pWhen); sqlite3ExprListDelete(db, pList); sqlite3SelectDelete(db, pSelect); @@ -133706,22 +109388,20 @@ if( db->mallocFailed==1 ){ fkTriggerDelete(db, pTrigger); return 0; } assert( pStep!=0 ); - assert( pTrigger!=0 ); switch( action ){ case OE_Restrict: - pStep->op = TK_SELECT; - break; - case OE_Cascade: - if( !pChanges ){ - pStep->op = TK_DELETE; - break; - } - /* no break */ deliberate_fall_through + pStep->op = TK_SELECT; + break; + case OE_Cascade: + if( !pChanges ){ + pStep->op = TK_DELETE; + break; + } default: pStep->op = TK_UPDATE; } pStep->pTrig = pTrigger; pTrigger->pSchema = pTab->pSchema; @@ -133743,13 +109423,13 @@ ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ int regOld, /* Address of array containing old row */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ - /* If foreign-key support is enabled, iterate through all FKs that - ** refer to table pTab. If there is an action associated with the FK - ** for this operation (either update or delete), invoke the associated + /* If foreign-key support is enabled, iterate through all FKs that + ** refer to table pTab. If there is an action associated with the FK + ** for this operation (either update or delete), invoke the associated ** trigger sub-program. */ if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *pFKey; /* Iterator variable */ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){ @@ -133771,22 +109451,22 @@ */ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ - assert( IsOrdinaryTable(pTab) ); - assert( db!=0 ); - for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){ - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); + assert( db==0 || IsVirtual(pTab) + || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); + for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ /* Remove the FK from the fkeyHash hash table. */ - if( db->pnBytesFreed==0 ){ + if( !db || db->pnBytesFreed==0 ){ if( pFKey->pPrevTo ){ pFKey->pPrevTo->pNextTo = pFKey->pNextTo; }else{ - const char *z = (pFKey->pNextTo ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, pFKey->pNextTo); + void *p = (void *)pFKey->pNextTo; + const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); + sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; } } @@ -133825,11 +109505,11 @@ ** to handle INSERT statements in SQLite. */ /* #include "sqliteInt.h" */ /* -** Generate code that will +** Generate code that will ** ** (1) acquire a lock for table pTab then ** (2) open pTab as cursor iCur. ** ** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index @@ -133842,33 +109522,30 @@ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; assert( !IsVirtual(pTab) ); - assert( pParse->pVdbe!=0 ); - v = pParse->pVdbe; + v = sqlite3GetVdbe(pParse); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); - if( !pParse->db->noSharedCache ){ - sqlite3TableLock(pParse, iDb, pTab->tnum, - (opcode==OP_OpenWrite)?1:0, pTab->zName); - } + sqlite3TableLock(pParse, iDb, pTab->tnum, + (opcode==OP_OpenWrite)?1:0, pTab->zName); if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol); + sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol); VdbeComment((v, "%s", pTab->zName)); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); - assert( pPk->tnum==pTab->tnum || CORRUPT_DB ); + assert( pPk->tnum==pTab->tnum ); sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pPk); VdbeComment((v, "%s", pTab->zName)); } } /* ** Return a pointer to the column affinity string associated with index -** pIdx. A column affinity string has one character for each column in +** pIdx. A column affinity string has one character for each column in ** the table, according to the affinity of the column: ** ** Character Column affinity ** ------------------------------ ** 'A' BLOB @@ -133882,163 +109559,102 @@ ** ** Memory for the buffer containing the column index affinity string ** is managed along with the rest of the Index structure. It will be ** released when sqlite3DeleteIndex() is called. */ -static SQLITE_NOINLINE const char *computeIndexAffStr(sqlite3 *db, Index *pIdx){ - /* The first time a column affinity string for a particular index is - ** required, it is allocated and populated here. It is then stored as - ** a member of the Index structure for subsequent use. - ** - ** The column affinity string will eventually be deleted by - ** sqliteDeleteIndex() when the Index structure itself is cleaned - ** up. - */ - int n; - Table *pTab = pIdx->pTable; - pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); - if( !pIdx->zColAff ){ - sqlite3OomFault(db); - return 0; - } - for(n=0; nnColumn; n++){ - i16 x = pIdx->aiColumn[n]; - char aff; - if( x>=0 ){ - aff = pTab->aCol[x].affinity; - }else if( x==XN_ROWID ){ - aff = SQLITE_AFF_INTEGER; - }else{ - assert( x==XN_EXPR ); - assert( pIdx->bHasExpr ); - assert( pIdx->aColExpr!=0 ); - aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); - } - if( affSQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC; - pIdx->zColAff[n] = aff; - } - pIdx->zColAff[n] = 0; - return pIdx->zColAff; -} -SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ - if( !pIdx->zColAff ) return computeIndexAffStr(db, pIdx); - return pIdx->zColAff; -} - - -/* -** Compute an affinity string for a table. Space is obtained -** from sqlite3DbMalloc(). The caller is responsible for freeing -** the space when done. -*/ -SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){ - char *zColAff; - zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1); - if( zColAff ){ - int i, j; - for(i=j=0; inCol; i++){ - if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ - zColAff[j++] = pTab->aCol[i].affinity; - } - } - do{ - zColAff[j--] = 0; - }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB ); - } - return zColAff; -} - -/* -** Make changes to the evolving bytecode to do affinity transformations -** of values that are about to be gathered into a row for table pTab. -** -** For ordinary (legacy, non-strict) tables: -** ----------------------------------------- -** -** Compute the affinity string for table pTab, if it has not already been -** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. -** -** If the affinity string is empty (because it was all SQLITE_AFF_BLOB entries -** which were then optimized out) then this routine becomes a no-op. -** -** Otherwise if iReg>0 then code an OP_Affinity opcode that will set the -** affinities for register iReg and following. Or if iReg==0, +SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ + if( !pIdx->zColAff ){ + /* The first time a column affinity string for a particular index is + ** required, it is allocated and populated here. It is then stored as + ** a member of the Index structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqliteDeleteIndex() when the Index structure itself is cleaned + ** up. + */ + int n; + Table *pTab = pIdx->pTable; + pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); + if( !pIdx->zColAff ){ + sqlite3OomFault(db); + return 0; + } + for(n=0; nnColumn; n++){ + i16 x = pIdx->aiColumn[n]; + if( x>=0 ){ + pIdx->zColAff[n] = pTab->aCol[x].affinity; + }else if( x==XN_ROWID ){ + pIdx->zColAff[n] = SQLITE_AFF_INTEGER; + }else{ + char aff; + assert( x==XN_EXPR ); + assert( pIdx->aColExpr!=0 ); + aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); + if( aff==0 ) aff = SQLITE_AFF_BLOB; + pIdx->zColAff[n] = aff; + } + } + pIdx->zColAff[n] = 0; + } + + return pIdx->zColAff; +} + +/* +** Compute the affinity string for table pTab, if it has not already been +** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. +** +** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and +** if iReg>0 then code an OP_Affinity opcode that will set the affinities +** for register iReg and following. Or if affinities exists and iReg==0, ** then just set the P4 operand of the previous opcode (which should be ** an OP_MakeRecord) to the affinity string. ** ** A column affinity string has one character per column: ** -** Character Column affinity -** --------- --------------- -** 'A' BLOB -** 'B' TEXT -** 'C' NUMERIC -** 'D' INTEGER -** 'E' REAL -** -** For STRICT tables: -** ------------------ -** -** Generate an appropriate OP_TypeCheck opcode that will verify the -** datatypes against the column definitions in pTab. If iReg==0, that -** means an OP_MakeRecord opcode has already been generated and should be -** the last opcode generated. The new OP_TypeCheck needs to be inserted -** before the OP_MakeRecord. The new OP_TypeCheck should use the same -** register set as the OP_MakeRecord. If iReg>0 then register iReg is -** the first of a series of registers that will form the new record. -** Apply the type checking to that array of registers. +** Character Column affinity +** ------------------------------ +** 'A' BLOB +** 'B' TEXT +** 'C' NUMERIC +** 'D' INTEGER +** 'E' REAL */ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ int i; - char *zColAff; - if( pTab->tabFlags & TF_Strict ){ - if( iReg==0 ){ - /* Move the previous opcode (which should be OP_MakeRecord) forward - ** by one slot and insert a new OP_TypeCheck where the current - ** OP_MakeRecord is found */ - VdbeOp *pPrev; - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - pPrev = sqlite3VdbeGetLastOp(v); - assert( pPrev!=0 ); - assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); - pPrev->opcode = OP_TypeCheck; - sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3); - }else{ - /* Insert an isolated OP_Typecheck */ - sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol); - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); - } - return; - } - zColAff = pTab->zColAff; + char *zColAff = pTab->zColAff; if( zColAff==0 ){ - zColAff = sqlite3TableAffinityStr(0, pTab); + sqlite3 *db = sqlite3VdbeDb(v); + zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); if( !zColAff ){ - sqlite3OomFault(sqlite3VdbeDb(v)); + sqlite3OomFault(db); return; } + + for(i=0; inCol; i++){ + zColAff[i] = pTab->aCol[i].affinity; + } + do{ + zColAff[i--] = 0; + }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); pTab->zColAff = zColAff; } - assert( zColAff!=0 ); - i = sqlite3Strlen30NN(zColAff); + i = sqlite3Strlen30(zColAff); if( i ){ if( iReg ){ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); }else{ - assert( sqlite3VdbeGetLastOp(v)->opcode==OP_MakeRecord - || sqlite3VdbeDb(v)->mallocFailed ); sqlite3VdbeChangeP4(v, -1, zColAff, i); } } } /* ** Return non-zero if the table pTab in database iDb or any of its indices -** have been opened at any point in the VDBE program. This is used to see if -** a statement of the form "INSERT INTO SELECT ..." can -** run without using a temporary table for the results of the SELECT. +** have been opened at any point in the VDBE program. This is used to see if +** a statement of the form "INSERT INTO SELECT ..." can +** run without using a temporary table for the results of the SELECT. */ static int readsTable(Parse *p, int iDb, Table *pTab){ Vdbe *v = sqlite3GetVdbe(p); int i; int iEnd = sqlite3VdbeCurrentAddr(v); @@ -134049,11 +109665,11 @@ for(i=1; iopcode==OP_OpenRead && pOp->p3==iDb ){ Index *pIndex; - Pgno tnum = pOp->p2; + int tnum = pOp->p2; if( tnum==pTab->tnum ){ return 1; } for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ if( tnum==pIndex->tnum ){ @@ -134069,129 +109685,10 @@ } #endif } return 0; } - -/* This walker callback will compute the union of colFlags flags for all -** referenced columns in a CHECK constraint or generated column expression. -*/ -static int exprColumnFlagUnion(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 ){ - assert( pExpr->iColumn < pWalker->u.pTab->nCol ); - pWalker->eCode |= pWalker->u.pTab->aCol[pExpr->iColumn].colFlags; - } - return WRC_Continue; -} - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS -/* -** All regular columns for table pTab have been puts into registers -** starting with iRegStore. The registers that correspond to STORED -** or VIRTUAL columns have not yet been initialized. This routine goes -** back and computes the values for those columns based on the previously -** computed normal columns. -*/ -SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns( - Parse *pParse, /* Parsing context */ - int iRegStore, /* Register holding the first column */ - Table *pTab /* The table */ -){ - int i; - Walker w; - Column *pRedo; - int eProgress; - VdbeOp *pOp; - - assert( pTab->tabFlags & TF_HasGenerated ); - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - - /* Before computing generated columns, first go through and make sure - ** that appropriate affinity has been applied to the regular columns - */ - sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore); - if( (pTab->tabFlags & TF_HasStored)!=0 ){ - pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); - if( pOp->opcode==OP_Affinity ){ - /* Change the OP_Affinity argument to '@' (NONE) for all stored - ** columns. '@' is the no-op affinity and those columns have not - ** yet been computed. */ - int ii, jj; - char *zP4 = pOp->p4.z; - assert( zP4!=0 ); - assert( pOp->p4type==P4_DYNAMIC ); - for(ii=jj=0; zP4[jj]; ii++){ - if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){ - continue; - } - if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){ - zP4[jj] = SQLITE_AFF_NONE; - } - jj++; - } - }else if( pOp->opcode==OP_TypeCheck ){ - /* If an OP_TypeCheck was generated because the table is STRICT, - ** then set the P3 operand to indicate that generated columns should - ** not be checked */ - pOp->p3 = 1; - } - } - - /* Because there can be multiple generated columns that refer to one another, - ** this is a two-pass algorithm. On the first pass, mark all generated - ** columns as "not available". - */ - for(i=0; inCol; i++){ - if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){ - testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ); - testcase( pTab->aCol[i].colFlags & COLFLAG_STORED ); - pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL; - } - } - - w.u.pTab = pTab; - w.xExprCallback = exprColumnFlagUnion; - w.xSelectCallback = 0; - w.xSelectCallback2 = 0; - - /* On the second pass, compute the value of each NOT-AVAILABLE column. - ** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will - ** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as - ** they are needed. - */ - pParse->iSelfTab = -iRegStore; - do{ - eProgress = 0; - pRedo = 0; - for(i=0; inCol; i++){ - Column *pCol = pTab->aCol + i; - if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){ - int x; - pCol->colFlags |= COLFLAG_BUSY; - w.eCode = 0; - sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol)); - pCol->colFlags &= ~COLFLAG_BUSY; - if( w.eCode & COLFLAG_NOTAVAIL ){ - pRedo = pCol; - continue; - } - eProgress = 1; - assert( pCol->colFlags & COLFLAG_GENERATED ); - x = sqlite3TableColumnToStorage(pTab, i) + iRegStore; - sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x); - pCol->colFlags &= ~COLFLAG_NOTAVAIL; - } - } - }while( pRedo && eProgress ); - if( pRedo ){ - sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName); - } - pParse->iSelfTab = 0; -} -#endif /* SQLITE_OMIT_GENERATED_COLUMNS */ - #ifndef SQLITE_OMIT_AUTOINCREMENT /* ** Locate or create an AutoincInfo structure associated with table pTab ** which is in database iDb. Return the register number for the register @@ -134203,16 +109700,15 @@ ** same table is autoincremented multiple times due to inserts within ** triggers. A new AutoincInfo structure is created if this is the ** first use of table pTab. On 2nd and subsequent uses, the original ** AutoincInfo structure is used. ** -** Four consecutive registers are allocated: +** Three memory locations are allocated: ** -** (1) The name of the pTab table. -** (2) The maximum ROWID of pTab. -** (3) The rowid in sqlite_sequence of pTab -** (4) The original value of the max ROWID in pTab, or NULL if none +** (1) Register to hold the name of the pTab table. +** (2) Register to hold the maximum ROWID of pTab. +** (3) Register to hold the rowid in sqlite_sequence of pTab ** ** The 2nd register is the one that is returned. That is all the ** insert routine needs to know about. */ static int autoIncBegin( @@ -134219,54 +109715,37 @@ Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ - assert( pParse->db->aDb[iDb].pSchema!=0 ); if( (pTab->tabFlags & TF_Autoincrement)!=0 - && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 + && (pParse->db->flags & SQLITE_Vacuum)==0 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; - Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; - - /* Verify that the sqlite_sequence table exists and is an ordinary - ** rowid table with exactly two columns. - ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ - if( pSeqTab==0 - || !HasRowid(pSeqTab) - || NEVER(IsVirtual(pSeqTab)) - || pSeqTab->nCol!=2 - ){ - pParse->nErr++; - pParse->rc = SQLITE_CORRUPT_SEQUENCE; - return 0; - } pInfo = pToplevel->pAinc; while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } if( pInfo==0 ){ pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); - sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo); - testcase( pParse->earlyCleanup ); - if( pParse->db->mallocFailed ) return 0; + if( pInfo==0 ) return 0; pInfo->pNext = pToplevel->pAinc; pToplevel->pAinc = pInfo; pInfo->pTab = pTab; pInfo->iDb = iDb; pToplevel->nMem++; /* Register to hold name of table */ pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ - pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */ + pToplevel->nMem++; /* Rowid in sqlite_sequence */ } memId = pInfo->regCtr; } return memId; } /* ** This routine generates code that will initialize all of the -** register used by the autoincrement tracker. +** register used by the autoincrement tracker. */ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ AutoincInfo *p; /* Information about an AUTOINCREMENT */ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* Database only autoinc table */ @@ -134281,21 +109760,19 @@ assert( v ); /* We failed long ago if this is not so */ for(p = pParse->pAinc; p; p = p->pNext){ static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList autoInc[] = { /* 0 */ {OP_Null, 0, 0, 0}, - /* 1 */ {OP_Rewind, 0, 10, 0}, + /* 1 */ {OP_Rewind, 0, 9, 0}, /* 2 */ {OP_Column, 0, 0, 0}, - /* 3 */ {OP_Ne, 0, 9, 0}, + /* 3 */ {OP_Ne, 0, 7, 0}, /* 4 */ {OP_Rowid, 0, 0, 0}, /* 5 */ {OP_Column, 0, 1, 0}, - /* 6 */ {OP_AddImm, 0, 0, 0}, - /* 7 */ {OP_Copy, 0, 0, 0}, - /* 8 */ {OP_Goto, 0, 11, 0}, - /* 9 */ {OP_Next, 0, 2, 0}, - /* 10 */ {OP_Integer, 0, 0, 0}, - /* 11 */ {OP_Close, 0, 0, 0} + /* 6 */ {OP_Goto, 0, 9, 0}, + /* 7 */ {OP_Next, 0, 2, 0}, + /* 8 */ {OP_Integer, 0, 0, 0}, + /* 9 */ {OP_Close, 0, 0, 0} }; VdbeOp *aOp; pDb = &db->aDb[p->iDb]; memId = p->regCtr; assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); @@ -134302,22 +109779,18 @@ sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); if( aOp==0 ) break; aOp[0].p2 = memId; - aOp[0].p3 = memId+2; + aOp[0].p3 = memId+1; aOp[2].p3 = memId; aOp[3].p1 = memId-1; aOp[3].p3 = memId; aOp[3].p5 = SQLITE_JUMPIFNULL; aOp[4].p2 = memId+1; aOp[5].p3 = memId; - aOp[6].p1 = memId; - aOp[7].p2 = memId+2; - aOp[7].p1 = memId; - aOp[10].p2 = memId; - if( pParse->nTab==0 ) pParse->nTab = 1; + aOp[8].p2 = memId; } } /* ** Update the maximum rowid for an autoincrement calculation. @@ -134360,12 +109833,10 @@ int iRec; int memId = p->regCtr; iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); - sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId); - VdbeCoverage(v); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); if( aOp==0 ) break; aOp[0].p1 = memId+1; aOp[1].p2 = memId+1; @@ -134387,214 +109858,10 @@ */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ -/* -** If argument pVal is a Select object returned by an sqlite3MultiValues() -** that was able to use the co-routine optimization, finish coding the -** co-routine. -*/ -SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ - if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){ - SrcItem *pItem = &pVal->pSrc->a[0]; - assert( (pItem->fg.isSubquery && pItem->u4.pSubq!=0) || pParse->nErr ); - if( pItem->fg.isSubquery ){ - sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->u4.pSubq->regReturn); - sqlite3VdbeJumpHere(pParse->pVdbe, pItem->u4.pSubq->addrFillSub - 1); - } - } -} - -/* -** Return true if all expressions in the expression-list passed as the -** only argument are constant. -*/ -static int exprListIsConstant(Parse *pParse, ExprList *pRow){ - int ii; - for(ii=0; iinExpr; ii++){ - if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0; - } - return 1; -} - -/* -** Return true if all expressions in the expression-list passed as the -** only argument are both constant and have no affinity. -*/ -static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){ - int ii; - if( exprListIsConstant(pParse,pRow)==0 ) return 0; - for(ii=0; iinExpr; ii++){ - Expr *pExpr = pRow->a[ii].pExpr; - assert( pExpr->op!=TK_RAISE ); - assert( pExpr->affExpr==0 ); - if( 0!=sqlite3ExprAffinity(pExpr) ) return 0; - } - return 1; - -} - -/* -** This function is called by the parser for the second and subsequent -** rows of a multi-row VALUES clause. Argument pLeft is the part of -** the VALUES clause already parsed, argument pRow is the vector of values -** for the new row. The Select object returned represents the complete -** VALUES clause, including the new row. -** -** There are two ways in which this may be achieved - by incremental -** coding of a co-routine (the "co-routine" method) or by returning a -** Select object equivalent to the following (the "UNION ALL" method): -** -** "pLeft UNION ALL SELECT pRow" -** -** If the VALUES clause contains a lot of rows, this compound Select -** object may consume a lot of memory. -** -** When the co-routine method is used, each row that will be returned -** by the VALUES clause is coded into part of a co-routine as it is -** passed to this function. The returned Select object is equivalent to: -** -** SELECT * FROM ( -** Select object to read co-routine -** ) -** -** The co-routine method is used in most cases. Exceptions are: -** -** a) If the current statement has a WITH clause. This is to avoid -** statements like: -** -** WITH cte AS ( VALUES('x'), ('y') ... ) -** SELECT * FROM cte AS a, cte AS b; -** -** This will not work, as the co-routine uses a hard-coded register -** for its OP_Yield instructions, and so it is not possible for two -** cursors to iterate through it concurrently. -** -** b) The schema is currently being parsed (i.e. the VALUES clause is part -** of a schema item like a VIEW or TRIGGER). In this case there is no VM -** being generated when parsing is taking place, and so generating -** a co-routine is not possible. -** -** c) There are non-constant expressions in the VALUES clause (e.g. -** the VALUES clause is part of a correlated sub-query). -** -** d) One or more of the values in the first row of the VALUES clause -** has an affinity (i.e. is a CAST expression). This causes problems -** because the complex rules SQLite uses (see function -** sqlite3SubqueryColumnTypes() in select.c) to determine the effective -** affinity of such a column for all rows require access to all values in -** the column simultaneously. -*/ -SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - - if( pParse->bHasWith /* condition (a) above */ - || pParse->db->init.busy /* condition (b) above */ - || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */ - || (pLeft->pSrc->nSrc==0 && - exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */ - || IN_SPECIAL_PARSE - ){ - /* The co-routine method cannot be used. Fall back to UNION ALL. */ - Select *pSelect = 0; - int f = SF_Values | SF_MultiValue; - if( pLeft->pSrc->nSrc ){ - sqlite3MultiValuesEnd(pParse, pLeft); - f = SF_Values; - }else if( pLeft->pPrior ){ - /* In this case set the SF_MultiValue flag only if it was set on pLeft */ - f = (f & pLeft->selFlags); - } - pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0); - pLeft->selFlags &= ~SF_MultiValue; - if( pSelect ){ - pSelect->op = TK_ALL; - pSelect->pPrior = pLeft; - pLeft = pSelect; - } - }else{ - SrcItem *p = 0; /* SrcItem that reads from co-routine */ - - if( pLeft->pSrc->nSrc==0 ){ - /* Co-routine has not yet been started and the special Select object - ** that accesses the co-routine has not yet been created. This block - ** does both those things. */ - Vdbe *v = sqlite3GetVdbe(pParse); - Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); - - /* Ensure the database schema has been read. This is to ensure we have - ** the correct text encoding. */ - if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){ - sqlite3ReadSchema(pParse); - } - - if( pRet ){ - SelectDest dest; - Subquery *pSubq; - pRet->pSrc->nSrc = 1; - pRet->pPrior = pLeft->pPrior; - pRet->op = pLeft->op; - if( pRet->pPrior ) pRet->selFlags |= SF_Values; - pLeft->pPrior = 0; - pLeft->op = TK_SELECT; - assert( pLeft->pNext==0 ); - assert( pRet->pNext==0 ); - p = &pRet->pSrc->a[0]; - p->fg.viaCoroutine = 1; - p->iCursor = -1; - assert( !p->fg.isIndexedBy && !p->fg.isTabFunc ); - p->u1.nRow = 2; - if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){ - pSubq = p->u4.pSubq; - pSubq->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; - pSubq->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, - pSubq->regReturn, 0, pSubq->addrFillSub); - sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn); - - /* Allocate registers for the output of the co-routine. Do so so - ** that there are two unused registers immediately before those - ** used by the co-routine. This allows the code in sqlite3Insert() - ** to use these registers directly, instead of copying the output - ** of the co-routine to a separate array for processing. */ - dest.iSdst = pParse->nMem + 3; - dest.nSdst = pLeft->pEList->nExpr; - pParse->nMem += 2 + dest.nSdst; - - pLeft->selFlags |= SF_MultiValue; - sqlite3Select(pParse, pLeft, &dest); - pSubq->regResult = dest.iSdst; - assert( pParse->nErr || dest.iSdst>0 ); - } - pLeft = pRet; - } - }else{ - p = &pLeft->pSrc->a[0]; - assert( !p->fg.isTabFunc && !p->fg.isIndexedBy ); - p->u1.nRow++; - } - - if( pParse->nErr==0 ){ - Subquery *pSubq; - assert( p!=0 ); - assert( p->fg.isSubquery ); - pSubq = p->u4.pSubq; - assert( pSubq!=0 ); - assert( pSubq->pSelect!=0 ); - assert( pSubq->pSelect->pEList!=0 ); - if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){ - sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect); - }else{ - sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0); - sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn); - } - } - sqlite3ExprListDelete(pParse->db, pRow); - } - - return pLeft; -} /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ Table *pDest, /* The table we are inserting into */ @@ -134702,16 +109969,16 @@ */ SQLITE_PRIVATE void sqlite3Insert( Parse *pParse, /* Parser context */ SrcList *pTabList, /* Name of table into which we are inserting */ Select *pSelect, /* A SELECT statement to use as the data source */ - IdList *pColumn, /* Column names corresponding to IDLIST, or NULL. */ - int onError, /* How to handle constraint errors */ - Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */ + IdList *pColumn, /* Column names corresponding to IDLIST. */ + int onError /* How to handle constraint errors */ ){ 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; /* 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 */ int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ @@ -134727,34 +109994,30 @@ u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ u8 bIdListInOrder; /* True if IDLIST is in table order */ ExprList *pList = 0; /* List of VALUES() to be inserted */ - int iRegStore; /* Register in which to store next column */ /* Register allocations */ int regFromSelect = 0;/* Base register for data coming from SELECT */ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ int regRowCount = 0; /* Memory cell used for the row counter */ int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ int *aRegIdx = 0; /* One register allocated to each index */ - int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ int tmask; /* Mask of trigger times */ #endif db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nErr ){ + if( pParse->nErr || db->mallocFailed ){ goto insert_cleanup; } - assert( db->mallocFailed==0 ); 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 ** and discard the other (unused) parts of the pSelect object @@ -134767,10 +110030,12 @@ } /* 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; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -134784,11 +110049,11 @@ /* Figure out if we have any triggers and if the table being ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); - isView = IsView(pTab); + isView = pTab->pSelect!=0; #else # define pTrigger 0 # define tmask 0 # define isView 0 #endif @@ -134796,28 +110061,20 @@ # undef isView # define isView 0 #endif assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__); - sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList, - onError, pUpsert, pTrigger); - } -#endif - /* If pTab is really a view, make sure it has been initialized. ** ViewGetColumnNames() is a no-op if pTab is not a view. */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } /* Cannot insert into a read-only table. */ - if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ + if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ goto insert_cleanup; } /* Allocate a VDBE */ @@ -134834,15 +110091,11 @@ ** Then special optimizations can be applied that make the transfer ** very fast and which reduce fragmentation of indices. ** ** This is the 2nd template. */ - if( pColumn==0 - && pSelect!=0 - && pTrigger==0 - && xferOptimization(pParse, pTab, pSelect, onError, iDb) - ){ + if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !pTrigger ); assert( pList==0 ); goto insert_end; } #endif /* SQLITE_OMIT_XFER_OPT */ @@ -134850,12 +110103,12 @@ /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell regAutoinc. */ regAutoinc = autoIncBegin(pParse, iDb, pTab); - /* Allocate a block registers to hold the rowid and the values - ** for all columns of the new row. + /* Allocate registers for holding the rowid of the new row, + ** the content of the new row, and the assembled row record. */ regRowid = regIns = pParse->nMem+1; pParse->nMem += pTab->nCol + 1; if( IsVirtual(pTab) ){ regRowid++; @@ -134862,61 +110115,43 @@ pParse->nMem++; } regData = regRowid+1; /* If the INSERT statement included an IDLIST term, then make sure - ** all elements of the IDLIST really are columns of the table and + ** all elements of the IDLIST really are columns of the table and ** remember the column indices. ** ** If the table has an INTEGER PRIMARY KEY column and that column ** is named in the IDLIST, then record in the ipkColumn variable ** the index into IDLIST of the primary key column. ipkColumn is ** the index of the primary key as it appears in IDLIST, not as ** is appears in the original table. (The index of the INTEGER - ** PRIMARY KEY in the original table is pTab->iPKey.) After this - ** loop, if ipkColumn==(-1), that means that integer primary key - ** is unspecified, and hence the table is either WITHOUT ROWID or - ** it will automatically generated an integer primary key. - ** - ** bIdListInOrder is true if the columns in IDLIST are in storage - ** order. This enables an optimization that avoids shuffling the - ** columns into storage order. False negatives are harmless, - ** but false positives will cause database corruption. + ** PRIMARY KEY in the original table is pTab->iPKey.) */ - bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; + bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0; if( pColumn ){ - aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int)); - if( aTabColMap==0 ) goto insert_cleanup; for(i=0; inId; i++){ - const char *zCName = pColumn->a[i].zName; - u8 hName = sqlite3StrIHash(zCName); + pColumn->a[i].idx = -1; + } + for(i=0; inId; i++){ for(j=0; jnCol; j++){ - if( pTab->aCol[j].hName!=hName ) continue; - if( sqlite3StrICmp(zCName, pTab->aCol[j].zCnName)==0 ){ - if( aTabColMap[j]==0 ) aTabColMap[j] = i+1; + if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ + pColumn->a[i].idx = j; if( i!=j ) bIdListInOrder = 0; if( j==pTab->iPKey ){ ipkColumn = i; assert( !withoutRowid ); } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){ - sqlite3ErrorMsg(pParse, - "cannot INSERT into generated column \"%s\"", - pTab->aCol[j].zCnName); - goto insert_cleanup; - } -#endif break; } } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ ipkColumn = i; bIdListInOrder = 0; }else{ sqlite3ErrorMsg(pParse, "table %S has no column named %s", - pTabList->a, pColumn->a[i].zName); + pTabList, 0, pColumn->a[i].zName); pParse->checkSchema = 1; goto insert_cleanup; } } } @@ -134928,57 +110163,35 @@ ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* Data is coming from a SELECT or from a multi-row VALUES clause. ** Generate a co-routine to run the SELECT. */ + int regYield; /* Register holding co-routine entry-point */ + int addrTop; /* Top of the co-routine */ int rc; /* Result code */ - if( pSelect->pSrc->nSrc==1 - && pSelect->pSrc->a[0].fg.viaCoroutine - && pSelect->pPrior==0 - ){ - SrcItem *pItem = &pSelect->pSrc->a[0]; - Subquery *pSubq; - assert( pItem->fg.isSubquery ); - pSubq = pItem->u4.pSubq; - dest.iSDParm = pSubq->regReturn; - regFromSelect = pSubq->regResult; - assert( pSubq->pSelect!=0 ); - assert( pSubq->pSelect->pEList!=0 ); - nColumn = pSubq->pSelect->pEList->nExpr; - ExplainQueryPlan((pParse, 0, "SCAN %S", pItem)); - if( bIdListInOrder && nColumn==pTab->nCol ){ - regData = regFromSelect; - regRowid = regData - 1; - regIns = regRowid - (IsVirtual(pTab) ? 1 : 0); - } - }else{ - int addrTop; /* Top of the co-routine */ - int regYield = ++pParse->nMem; - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); - dest.iSdst = bIdListInOrder ? regData : 0; - dest.nSdst = pTab->nCol; - rc = sqlite3Select(pParse, pSelect, &dest); - regFromSelect = dest.iSdst; - assert( db->pParse==pParse ); - if( rc || pParse->nErr ) goto insert_cleanup; - assert( db->mallocFailed==0 ); - sqlite3VdbeEndCoroutine(v, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ - assert( pSelect->pEList ); - nColumn = pSelect->pEList->nExpr; - } + regYield = ++pParse->nMem; + addrTop = sqlite3VdbeCurrentAddr(v) + 1; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); + sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + dest.iSdst = bIdListInOrder ? regData : 0; + dest.nSdst = pTab->nCol; + rc = sqlite3Select(pParse, pSelect, &dest); + regFromSelect = dest.iSdst; + if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; + sqlite3VdbeEndCoroutine(v, regYield); + sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ + assert( pSelect->pEList ); + nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to ** FALSE if each output row of the SELECT can be written directly into ** the destination table (template 3). ** ** A temp table must be used if the table being updated is also one - ** of the tables being read by the SELECT statement. Also use a + ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ if( pTrigger || readsTable(pParse, iDb, pTab) ){ useTempTable = 1; } @@ -135010,11 +110223,11 @@ sqlite3VdbeJumpHere(v, addrL); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regTempRowid); } }else{ - /* This is the case if the data for the INSERT is coming from a + /* This is the case if the data for the INSERT is coming from a ** single-row VALUES clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; @@ -135029,111 +110242,56 @@ nColumn = 0; } } /* If there is no IDLIST term but the table has an integer primary - ** key, the set the ipkColumn variable to the integer primary key + ** key, the set the ipkColumn variable to the integer primary key ** column index in the original table definition. */ if( pColumn==0 && nColumn>0 ){ ipkColumn = pTab->iPKey; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - for(i=ipkColumn-1; i>=0; i--){ - if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){ - testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ); - testcase( pTab->aCol[i].colFlags & COLFLAG_STORED ); - ipkColumn--; - } - } - } -#endif - - /* Make sure the number of columns in the source data matches the number - ** of columns to be inserted into the table. - */ - assert( TF_HasHidden==COLFLAG_HIDDEN ); - assert( TF_HasGenerated==COLFLAG_GENERATED ); - assert( COLFLAG_NOINSERT==(COLFLAG_GENERATED|COLFLAG_HIDDEN) ); - if( (pTab->tabFlags & (TF_HasGenerated|TF_HasHidden))!=0 ){ - for(i=0; inCol; i++){ - if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++; - } - } - if( nColumn!=(pTab->nCol-nHidden) ){ - sqlite3ErrorMsg(pParse, - "table %S has %d columns but %d values were supplied", - pTabList->a, pTab->nCol-nHidden, nColumn); - goto insert_cleanup; - } + } + + /* Make sure the number of columns in the source data matches the number + ** of columns to be inserted into the table. + */ + for(i=0; inCol; i++){ + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); + } + if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ + sqlite3ErrorMsg(pParse, + "table %S has %d columns but %d values were supplied", + pTabList, 0, pTab->nCol-nHidden, nColumn); + goto insert_cleanup; } if( pColumn!=0 && nColumn!=pColumn->nId ){ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } - + /* Initialize the count of rows to be inserted */ - if( (db->flags & SQLITE_CountRows)!=0 - && !pParse->nested - && !pParse->pTriggerTab - && !pParse->bReturning - ){ + if( db->flags & SQLITE_CountRows ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); - aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+2)); + aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } for(i=0, pIdx=pTab->pIndex; ipNext, i++){ assert( pIdx ); aRegIdx[i] = ++pParse->nMem; pParse->nMem += pIdx->nColumn; } - aRegIdx[i] = ++pParse->nMem; /* Register to store the table record */ - } -#ifndef SQLITE_OMIT_UPSERT - if( pUpsert ){ - Upsert *pNx; - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"", - pTab->zName); - goto insert_cleanup; - } - if( IsView(pTab) ){ - sqlite3ErrorMsg(pParse, "cannot UPSERT a view"); - goto insert_cleanup; - } - if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){ - goto insert_cleanup; - } - pTabList->a[0].iCursor = iDataCur; - pNx = pUpsert; - do{ - pNx->pUpsertSrc = pTabList; - pNx->regData = regData; - pNx->iDataCur = iDataCur; - pNx->iIdxCur = iIdxCur; - if( pNx->pUpsertTarget ){ - if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){ - goto insert_cleanup; - } - } - pNx = pNx->pNextUpsert; - }while( pNx!=0 ); - } -#endif - + } /* This is the top of the main insertion loop */ if( useTempTable ){ /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 4): @@ -135153,110 +110311,17 @@ ** C: yield X, at EOF goto D ** insert the select result into
                from R..R+n ** goto C ** D: ... */ - sqlite3VdbeReleaseRegisters(pParse, regData, pTab->nCol, 0, 0); addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); - if( ipkColumn>=0 ){ - /* tag-20191021-001: If the INTEGER PRIMARY KEY is being generated by the - ** SELECT, go ahead and copy the value into the rowid slot now, so that - ** the value does not get overwritten by a NULL at tag-20191021-002. */ - sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid); - } - } - - /* Compute data for ordinary columns of the new entry. Values - ** are written in storage order into registers starting with regData. - ** Only ordinary columns are computed in this loop. The rowid - ** (if there is one) is computed later and generated columns are - ** computed after the rowid since they might depend on the value - ** of the rowid. - */ - nHidden = 0; - iRegStore = regData; assert( regData==regRowid+1 ); - for(i=0; inCol; i++, iRegStore++){ - int k; - u32 colFlags; - assert( i>=nHidden ); - if( i==pTab->iPKey ){ - /* tag-20191021-002: References to the INTEGER PRIMARY KEY are filled - ** using the rowid. So put a NULL in the IPK slot of the record to avoid - ** using excess space. The file format definition requires this extra - ** NULL - we cannot optimize further by skipping the column completely */ - sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); - continue; - } - if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){ - nHidden++; - if( (colFlags & COLFLAG_VIRTUAL)!=0 ){ - /* Virtual columns do not participate in OP_MakeRecord. So back up - ** iRegStore by one slot to compensate for the iRegStore++ in the - ** outer for() loop */ - iRegStore--; - continue; - }else if( (colFlags & COLFLAG_STORED)!=0 ){ - /* Stored columns are computed later. But if there are BEFORE - ** triggers, the slots used for stored columns will be OP_Copy-ed - ** to a second block of registers, so the register needs to be - ** initialized to NULL to avoid an uninitialized register read */ - if( tmask & TRIGGER_BEFORE ){ - sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); - } - continue; - }else if( pColumn==0 ){ - /* Hidden columns that are not explicitly named in the INSERT - ** get there default value */ - sqlite3ExprCodeFactorable(pParse, - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - iRegStore); - continue; - } - } - if( pColumn ){ - j = aTabColMap[i]; - assert( j>=0 && j<=pColumn->nId ); - if( j==0 ){ - /* A column not named in the insert column list gets its - ** default value */ - sqlite3ExprCodeFactorable(pParse, - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - iRegStore); - continue; - } - k = j - 1; - }else if( nColumn==0 ){ - /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */ - sqlite3ExprCodeFactorable(pParse, - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - iRegStore); - continue; - }else{ - k = i - nHidden; - } - - if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore); - }else if( pSelect ){ - if( regFromSelect!=regData ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore); - } - }else{ - Expr *pX = pList->a[k].pExpr; - int y = sqlite3ExprCodeTarget(pParse, pX, iRegStore); - if( y!=iRegStore ){ - sqlite3VdbeAddOp2(v, - ExprHasProperty(pX, EP_Subquery) ? OP_Copy : OP_SCopy, y, iRegStore); - } - } - } - + } /* Run the BEFORE and INSTEAD OF triggers, if there are any */ - endOfLoop = sqlite3VdbeMakeLabel(pParse); + endOfLoop = sqlite3VdbeMakeLabel(v); if( tmask & TRIGGER_BEFORE ){ int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1); /* build the NEW.* reference row. Note that if there is an INTEGER ** PRIMARY KEY into which a NULL is being inserted, that NULL will be @@ -135279,25 +110344,34 @@ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); } - /* Copy the new data already generated. */ - assert( pTab->nNVCol>0 || pParse->nErr>0 ); - sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1); - -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Compute the new value for generated columns after all other - ** columns have already been computed. This must be done after - ** computing the ROWID in case one of the generated columns - ** refers to the ROWID. */ - if( pTab->tabFlags & TF_HasGenerated ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - sqlite3ComputeGeneratedColumns(pParse, regCols+1, pTab); - } -#endif + /* Cannot have triggers on a virtual table. If it were possible, + ** this block would have to account for hidden column. + */ + assert( !IsVirtual(pTab) ); + + /* Create the new column data + */ + for(i=j=0; inCol; i++){ + if( pColumn ){ + for(j=0; jnId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) + || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); + }else{ + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); + } + if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++; + } /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, ** do not attempt any conversions before assembling the record. ** If this is a real table, attempt conversions as required by the ** table column affinities. @@ -135305,34 +110379,39 @@ if( !isView ){ sqlite3TableAffinity(v, pTab, regCols+1); } /* Fire BEFORE or INSTEAD OF triggers */ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, + sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, pTab, regCols-pTab->nCol-1, onError, endOfLoop); sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1); } + /* Compute the content of the next row to insert into a range of + ** registers beginning at regIns. + */ if( !isView ){ if( IsVirtual(pTab) ){ /* The row that the VUpdate opcode will delete: none */ sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); } if( ipkColumn>=0 ){ - /* Compute the new rowid */ if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid); }else if( pSelect ){ - /* Rowid already initialized at tag-20191021-001 */ + sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid); }else{ - Expr *pIpk = pList->a[ipkColumn].pExpr; - if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){ - sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); + VdbeOp *pOp; + sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); + pOp = sqlite3VdbeGetOp(v, -1); + if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ appendFlag = 1; - }else{ - sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); + pOp->opcode = OP_NewRowid; + pOp->p1 = iDataCur; + pOp->p2 = regRowid; + pOp->p3 = regAutoinc; } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid ** to generate a unique primary key value. */ @@ -135354,19 +110433,49 @@ sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); appendFlag = 1; } autoIncStep(pParse, regAutoinc, regRowid); -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Compute the new value for generated columns after all other - ** columns have already been computed. This must be done after - ** computing the ROWID in case one of the generated columns - ** is derived from the INTEGER PRIMARY KEY. */ - if( pTab->tabFlags & TF_HasGenerated ){ - sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab); - } -#endif + /* Compute data for all columns of the new entry, beginning + ** with the first column. + */ + nHidden = 0; + for(i=0; inCol; i++){ + int iRegStore = regRowid+1+i; + if( i==pTab->iPKey ){ + /* The value of the INTEGER PRIMARY KEY column is always a NULL. + ** Whenever this column is read, the rowid will be substituted + ** in its place. Hence, fill this column with a NULL to avoid + ** taking up data space with information that will never be used. + ** As there may be shallow copies of this value, make it a soft-NULL */ + sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); + continue; + } + if( pColumn==0 ){ + if( IsHiddenColumn(&pTab->aCol[i]) ){ + j = -1; + nHidden++; + }else{ + j = i - nHidden; + } + }else{ + for(j=0; jnId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ + sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); + }else if( pSelect ){ + if( regFromSelect!=regData ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + } + }else{ + sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); + } + } /* Generate code to check constraints and generate index keys and ** do the insertion. */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -135377,50 +110486,43 @@ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); }else #endif { - int isReplace = 0;/* Set to true if constraints may cause a replace */ + 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, pUpsert + regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ); - if( db->flags & SQLITE_ForeignKeys ){ - sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 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 + ** 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 || !sqlite3VdbeHasSubProgram(v)); + bUseSeek = (isReplace==0 || (pTrigger==0 && + ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0) + )); sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, regIns, aRegIdx, 0, appendFlag, bUseSeek ); } -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - }else if( pParse->bReturning ){ - /* If there is a RETURNING clause, populate the rowid register with - ** constant value -1, in case one or more of the returned expressions - ** refer to the "rowid" of the view. */ - sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid); -#endif } /* Update the count of rows that are inserted */ - if( regRowCount ){ + if( (db->flags & SQLITE_CountRows)!=0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, + sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, pTab, regData-2-pTab->nCol, onError, endOfLoop); } /* The bottom of the main insertion loop, if the data source ** is a SELECT statement. @@ -135430,52 +110532,39 @@ sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ sqlite3VdbeGoto(v, addrCont); -#ifdef SQLITE_DEBUG - /* If we are jumping back to an OP_Yield that is preceded by an - ** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the - ** OP_ReleaseReg will be included in the loop. */ - if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){ - assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield ); - sqlite3VdbeChangeP5(v, 1); - } -#endif sqlite3VdbeJumpHere(v, addrInsTop); } -#ifndef SQLITE_OMIT_XFER_OPT insert_end: -#endif /* SQLITE_OMIT_XFER_OPT */ /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } /* - ** Return the number of rows inserted. If this routine is + ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( regRowCount ){ - sqlite3CodeChangeCount(v, regRowCount, "rows inserted"); + if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); } insert_cleanup: sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pList); - sqlite3UpsertDelete(db, pUpsert); sqlite3SelectDelete(db, pSelect); - if( pColumn ){ - sqlite3IdListDelete(db, pColumn); - sqlite3DbFree(db, aTabColMap); - } - if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx); + sqlite3IdListDelete(db, pColumn); + sqlite3DbFree(db, aRegIdx); } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** they may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ @@ -135488,20 +110577,19 @@ #ifdef tmask #undef tmask #endif /* -** Meanings of bits in of pWalker->eCode for -** sqlite3ExprReferencesUpdatedColumn() +** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() */ #define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ #define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ -/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). -* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this -** expression node references any of the -** columns that are being modified by an UPDATE statement. +/* This is the Walker callback from checkConstraintUnchanged(). Set +** bit 0x01 of pWalker->eCode if +** pWalker->eCode to 0 if this expression node references any of the +** columns that are being modifed by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_COLUMN ){ assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 ); if( pExpr->iColumn>=0 ){ @@ -135518,25 +110606,16 @@ /* ** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The ** only columns that are modified by the UPDATE are those for which ** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. ** -** Return true if CHECK constraint pExpr uses any of the +** Return true if CHECK constraint pExpr does not use any of the ** changing columns (or the rowid if it is changing). In other words, -** return true if this CHECK constraint must be validated for +** return true if this CHECK constraint can be skipped when validating ** the new row in the UPDATE statement. -** -** 2018-09-15: pExpr might also be an expression for an index-on-expressions. -** The operation of this routine is the same - return true if an only if -** the expression uses one or more of columns identified by the second and -** third arguments. */ -SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn( - Expr *pExpr, /* The expression to be checked */ - int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ - int chngRowid /* True if UPDATE changes the rowid */ -){ +static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ Walker w; memset(&w, 0, sizeof(w)); w.eCode = 0; w.xExprCallback = checkConstraintExprNode; w.u.aiCol = aiChng; @@ -135547,75 +110626,11 @@ } testcase( w.eCode==0 ); testcase( w.eCode==CKCNSTRNT_COLUMN ); testcase( w.eCode==CKCNSTRNT_ROWID ); testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); - return w.eCode!=0; -} - -/* -** The sqlite3GenerateConstraintChecks() routine usually wants to visit -** the indexes of a table in the order provided in the Table->pIndex list. -** However, sometimes (rarely - when there is an upsert) it wants to visit -** the indexes in a different order. The following data structures accomplish -** this. -** -** The IndexIterator object is used to walk through all of the indexes -** of a table in either Index.pNext order, or in some other order established -** by an array of IndexListTerm objects. -*/ -typedef struct IndexListTerm IndexListTerm; -typedef struct IndexIterator IndexIterator; -struct IndexIterator { - int eType; /* 0 for Index.pNext list. 1 for an array of IndexListTerm */ - int i; /* Index of the current item from the list */ - union { - struct { /* Use this object for eType==0: A Index.pNext list */ - Index *pIdx; /* The current Index */ - } lx; - struct { /* Use this object for eType==1; Array of IndexListTerm */ - int nIdx; /* Size of the array */ - IndexListTerm *aIdx; /* Array of IndexListTerms */ - } ax; - } u; -}; - -/* When IndexIterator.eType==1, then each index is an array of instances -** of the following object -*/ -struct IndexListTerm { - Index *p; /* The index */ - int ix; /* Which entry in the original Table.pIndex list is this index*/ -}; - -/* Return the first index on the list */ -static Index *indexIteratorFirst(IndexIterator *pIter, int *pIx){ - assert( pIter->i==0 ); - if( pIter->eType ){ - *pIx = pIter->u.ax.aIdx[0].ix; - return pIter->u.ax.aIdx[0].p; - }else{ - *pIx = 0; - return pIter->u.lx.pIdx; - } -} - -/* Return the next index from the list. Return NULL when out of indexes */ -static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){ - if( pIter->eType ){ - int i = ++pIter->i; - if( i>=pIter->u.ax.nIdx ){ - *pIx = i; - return 0; - } - *pIx = pIter->u.ax.aIdx[i].ix; - return pIter->u.ax.aIdx[i].p; - }else{ - ++(*pIx); - pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext; - return pIter->u.lx.pIdx; - } + return !w.eCode; } /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE ** on table pTab. @@ -135649,18 +110664,10 @@ ** registers identified by aRegIdx[]. No index entry is created for ** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is ** the same as the order of indices on the linked list of indices ** at pTab->pIndex. ** -** (2019-05-07) The generated code also creates a new record for the -** main table, if pTab is a rowid table, and stores that record in the -** register identified by aRegIdx[nIdx] - in other words in the first -** entry of aRegIdx[] past the last index. It is important that the -** record be generated during constraint checks to avoid affinity changes -** to the register content that occur after constraint checks but before -** the new record is inserted. -** ** The caller must have already opened writeable cursors on the main ** table and all applicable indices (that is to say, all indices for which ** aRegIdx[] is not zero). iDataCur is the cursor for the main table when ** inserting or updating a rowid table, or the cursor for the PRIMARY KEY ** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor @@ -135717,48 +110724,37 @@ int regOldData, /* Previous content. 0 for INSERTs */ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ u8 overrideError, /* Override onError to this if not OE_Default */ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ - int *aiChng, /* column i is unchanged if aiChng[i]<0 */ - Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ + int *aiChng /* column i is unchanged if aiChng[i]<0 */ ){ - Vdbe *v; /* VDBE under construction */ + Vdbe *v; /* VDBE under constrution */ Index *pIdx; /* Pointer to one of the indices */ - Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */ + Index *pPk = 0; /* The PRIMARY KEY index */ sqlite3 *db; /* Database connection */ int i; /* loop counter */ int ix; /* Index loop counter */ int nCol; /* Number of columns */ int onError; /* Conflict resolution strategy */ + int addr1; /* Address of jump instruction */ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ - Upsert *pUpsertClause = 0; /* The specific ON CONFLICT clause for pIdx */ - u8 isUpdate; /* True if this is an UPDATE operation */ + int ipkTop = 0; /* Top of the rowid change constraint check */ + 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 upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */ - int upsertIpkDelay = 0; /* Address of Goto to bypass initial IPK check */ - int ipkTop = 0; /* Top of the IPK uniqueness check */ - int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */ - /* Variables associated with retesting uniqueness constraints after - ** replace triggers fire have run */ - int regTrigCnt; /* Register used to count replace trigger invocations */ - int addrRecheck = 0; /* Jump here to recheck all uniqueness constraints */ - int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */ - Trigger *pTrigger; /* List of DELETE triggers on the table pTab */ - int nReplaceTrig = 0; /* Number of replace triggers coded */ - IndexIterator sIdxIter; /* Index iterator */ isUpdate = regOldData!=0; db = pParse->db; - v = pParse->pVdbe; + v = sqlite3GetVdbe(pParse); assert( v!=0 ); - assert( !IsView(pTab) ); /* This table is not a VIEW */ + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ nCol = pTab->nCol; - + /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for - ** normal rowid tables. nPkField is the number of key fields in the + ** normal rowid tables. nPkField is the number of key fields in the ** pPk index or 1 for a rowid table. In other words, nPkField is the ** number of fields in the true primary key of the table. */ if( HasRowid(pTab) ){ pPk = 0; nPkField = 1; @@ -135771,360 +110767,140 @@ VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)", iDataCur, iIdxCur, regNewData, regOldData, pkChng)); /* Test all NOT NULL constraints. */ - if( pTab->tabFlags & TF_HasNotNull ){ - int b2ndPass = 0; /* True if currently running 2nd pass */ - int nSeenReplace = 0; /* Number of ON CONFLICT REPLACE operations */ - int nGenerated = 0; /* Number of generated columns with NOT NULL */ - while(1){ /* Make 2 passes over columns. Exit loop via "break" */ - for(i=0; iaCol[i]; /* The column to check for NOT NULL */ - int isGenerated; /* non-zero if column is generated */ - onError = pCol->notNull; - if( onError==OE_None ) continue; /* No NOT NULL on this column */ - if( i==pTab->iPKey ){ - continue; /* ROWID is never NULL */ - } - isGenerated = pCol->colFlags & COLFLAG_GENERATED; - if( isGenerated && !b2ndPass ){ - nGenerated++; - continue; /* Generated columns processed on 2nd pass */ - } - if( aiChng && aiChng[i]<0 && !isGenerated ){ - /* Do not check NOT NULL on columns that do not change */ - continue; - } - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( onError==OE_Replace ){ - if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */ - || pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */ - ){ - testcase( pCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pCol->colFlags & COLFLAG_STORED ); - testcase( pCol->colFlags & COLFLAG_GENERATED ); - onError = OE_Abort; - }else{ - assert( !isGenerated ); - } - }else if( b2ndPass && !isGenerated ){ - continue; - } - assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace ); - testcase( i!=sqlite3TableColumnToStorage(pTab, i) ); - iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1; - switch( onError ){ - case OE_Replace: { - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg); - VdbeCoverage(v); - assert( (pCol->colFlags & COLFLAG_GENERATED)==0 ); - nSeenReplace++; - sqlite3ExprCodeCopy(pParse, - sqlite3ColumnExpr(pTab, pCol), iReg); - sqlite3VdbeJumpHere(v, addr1); - break; - } - case OE_Abort: - sqlite3MayAbort(pParse); - /* no break */ deliberate_fall_through - case OE_Rollback: - case OE_Fail: { - char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, - pCol->zCnName); - testcase( zMsg==0 && db->mallocFailed==0 ); - sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, - onError, iReg); - sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); - sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); - VdbeCoverage(v); - break; - } - default: { - assert( onError==OE_Ignore ); - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest); - VdbeCoverage(v); - break; - } - } /* end switch(onError) */ - } /* end loop i over columns */ - if( nGenerated==0 && nSeenReplace==0 ){ - /* If there are no generated columns with NOT NULL constraints - ** and no NOT NULL ON CONFLICT REPLACE constraints, then a single - ** pass is sufficient */ - break; - } - if( b2ndPass ) break; /* Never need more than 2 passes */ - b2ndPass = 1; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( nSeenReplace>0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){ - /* If any NOT NULL ON CONFLICT REPLACE constraints fired on the - ** first pass, recomputed values for all generated columns, as - ** those values might depend on columns affected by the REPLACE. - */ - sqlite3ComputeGeneratedColumns(pParse, regNewData+1, pTab); - } -#endif - } /* end of 2-pass loop */ - } /* end if( has-not-null-constraints ) */ + for(i=0; iiPKey ){ + continue; /* ROWID is never NULL */ + } + if( aiChng && aiChng[i]<0 ){ + /* Don't bother checking for NOT NULL on columns that do not change */ + continue; + } + onError = pTab->aCol[i].notNull; + if( onError==OE_None ) continue; /* This column is allowed to be NULL */ + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ + onError = OE_Abort; + } + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Abort: + sqlite3MayAbort(pParse); + /* Fall through */ + case OE_Rollback: + case OE_Fail: { + char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, + pTab->aCol[i].zName); + sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, + regNewData+1+i); + sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); + sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); + VdbeCoverage(v); + break; + } + case OE_Ignore: { + sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); + VdbeCoverage(v); + break; + } + default: { + assert( onError==OE_Replace ); + addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); + VdbeCoverage(v); + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); + sqlite3VdbeJumpHere(v, addr1); + break; + } + } + } /* Test all CHECK constraints */ #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; - pParse->iSelfTab = -(regNewData+1); + pParse->ckBase = regNewData+1; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; inExpr; i++){ int allOk; - Expr *pCopy; Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng - && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) - ){ - /* The check constraints do not reference any of the columns being - ** updated so there is no point it verifying the check constraint */ - continue; - } - if( bAffinityDone==0 ){ - sqlite3TableAffinity(v, pTab, regNewData+1); - bAffinityDone = 1; - } - allOk = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeVerifyAbortable(v, onError); - pCopy = sqlite3ExprDup(db, pExpr, 0); - if( !db->mallocFailed ){ - sqlite3ExprIfTrue(pParse, pCopy, allOk, SQLITE_JUMPIFNULL); - } - sqlite3ExprDelete(db, pCopy); + if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; + allOk = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeGoto(v, ignoreDest); }else{ - char *zName = pCheck->a[i].zEName; - assert( zName!=0 || pParse->db->mallocFailed ); - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */ + char *zName = pCheck->a[i].zName; + if( zName==0 ) zName = pTab->zName; + if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, onError, zName, P4_TRANSIENT, P5_ConstraintCheck); } sqlite3VdbeResolveLabel(v, allOk); } - pParse->iSelfTab = 0; } #endif /* !defined(SQLITE_OMIT_CHECK) */ - /* UNIQUE and PRIMARY KEY constraints should be handled in the following - ** order: - ** - ** (1) OE_Update - ** (2) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore - ** (3) OE_Replace - ** - ** OE_Fail and OE_Ignore must happen before any changes are made. - ** OE_Update guarantees that only a single row will change, so it - ** must happen before OE_Replace. Technically, OE_Abort and OE_Rollback - ** could happen in any order, but they are grouped up front for - ** convenience. - ** - ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43 - ** The order of constraints used to have OE_Update as (2) and OE_Abort - ** and so forth as (1). But apparently PostgreSQL checks the OE_Update - ** constraint before any others, so it had to be moved. - ** - ** Constraint checking code is generated in this order: - ** (A) The rowid constraint - ** (B) Unique index constraints that do not have OE_Replace as their - ** default conflict resolution strategy - ** (C) Unique index that do use OE_Replace by default. - ** - ** The ordering of (2) and (3) is accomplished by making sure the linked - ** list of indexes attached to a table puts all OE_Replace indexes last - ** in the list. See sqlite3CreateIndex() for where that happens. - */ - sIdxIter.eType = 0; - sIdxIter.i = 0; - sIdxIter.u.ax.aIdx = 0; /* Silence harmless compiler warning */ - sIdxIter.u.lx.pIdx = pTab->pIndex; - if( pUpsert ){ - if( pUpsert->pUpsertTarget==0 ){ - /* There is just on ON CONFLICT clause and it has no constraint-target */ - assert( pUpsert->pNextUpsert==0 ); - if( pUpsert->isDoUpdate==0 ){ - /* A single ON CONFLICT DO NOTHING clause, without a constraint-target. - ** Make all unique constraint resolution be OE_Ignore */ - overrideError = OE_Ignore; - pUpsert = 0; - }else{ - /* A single ON CONFLICT DO UPDATE. Make all resolutions OE_Update */ - overrideError = OE_Update; - } - }else if( pTab->pIndex!=0 ){ - /* Otherwise, we'll need to run the IndexListTerm array version of the - ** iterator to ensure that all of the ON CONFLICT conditions are - ** checked first and in order. */ - int nIdx, jj; - u64 nByte; - Upsert *pTerm; - u8 *bUsed; - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ - assert( aRegIdx[nIdx]>0 ); - } - sIdxIter.eType = 1; - sIdxIter.u.ax.nIdx = nIdx; - nByte = (sizeof(IndexListTerm)+1)*nIdx + nIdx; - sIdxIter.u.ax.aIdx = sqlite3DbMallocZero(db, nByte); - if( sIdxIter.u.ax.aIdx==0 ) return; /* OOM */ - bUsed = (u8*)&sIdxIter.u.ax.aIdx[nIdx]; - pUpsert->pToFree = sIdxIter.u.ax.aIdx; - for(i=0, pTerm=pUpsert; pTerm; pTerm=pTerm->pNextUpsert){ - if( pTerm->pUpsertTarget==0 ) break; - if( pTerm->pUpsertIdx==0 ) continue; /* Skip ON CONFLICT for the IPK */ - jj = 0; - pIdx = pTab->pIndex; - while( ALWAYS(pIdx!=0) && pIdx!=pTerm->pUpsertIdx ){ - pIdx = pIdx->pNext; - jj++; - } - if( bUsed[jj] ) continue; /* Duplicate ON CONFLICT clause ignored */ - bUsed[jj] = 1; - sIdxIter.u.ax.aIdx[i].p = pIdx; - sIdxIter.u.ax.aIdx[i].ix = jj; - i++; - } - for(jj=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, jj++){ - if( bUsed[jj] ) continue; - sIdxIter.u.ax.aIdx[i].p = pIdx; - sIdxIter.u.ax.aIdx[i].ix = jj; - i++; - } - assert( i==nIdx ); - } - } - - /* Determine if it is possible that triggers (either explicitly coded - ** triggers or FK resolution actions) might run as a result of deletes - ** that happen when OE_Replace conflict resolution occurs. (Call these - ** "replace triggers".) If any replace triggers run, we will need to - ** recheck all of the uniqueness constraints after they have all run. - ** But on the recheck, the resolution is OE_Abort instead of OE_Replace. - ** - ** If replace triggers are a possibility, then - ** - ** (1) Allocate register regTrigCnt and initialize it to zero. - ** That register will count the number of replace triggers that - ** fire. Constraint recheck only occurs if the number is positive. - ** (2) Initialize pTrigger to the list of all DELETE triggers on pTab. - ** (3) Initialize addrRecheck and lblRecheckOk - ** - ** The uniqueness rechecking code will create a series of tests to run - ** in a second pass. The addrRecheck and lblRecheckOk variables are - ** used to link together these tests which are separated from each other - ** in the generate bytecode. - */ - if( (db->flags & (SQLITE_RecTriggers|SQLITE_ForeignKeys))==0 ){ - /* There are not DELETE triggers nor FK constraints. No constraint - ** rechecks are needed. */ - pTrigger = 0; - regTrigCnt = 0; - }else{ - if( db->flags&SQLITE_RecTriggers ){ - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - regTrigCnt = pTrigger!=0 || sqlite3FkRequired(pParse, pTab, 0, 0); - }else{ - pTrigger = 0; - regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0); - } - if( regTrigCnt ){ - /* Replace triggers might exist. Allocate the counter and - ** initialize it to zero. */ - regTrigCnt = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regTrigCnt); - VdbeComment((v, "trigger count")); - lblRecheckOk = sqlite3VdbeMakeLabel(pParse); - addrRecheck = lblRecheckOk; - } - } - /* If rowid is changing, make sure the new rowid does not previously ** exist in the table. */ if( pkChng && pPk==0 ){ - int addrRowidOk = sqlite3VdbeMakeLabel(pParse); + int addrRowidOk = sqlite3VdbeMakeLabel(v); /* Figure out what action to take in case of a rowid collision */ onError = pTab->keyConf; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } - /* figure out whether or not upsert applies in this case */ - if( pUpsert ){ - pUpsertClause = sqlite3UpsertOfIndex(pUpsert,0); - if( pUpsertClause!=0 ){ - if( pUpsertClause->isDoUpdate==0 ){ - onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ - }else{ - onError = OE_Update; /* DO UPDATE */ - } - } - if( pUpsertClause!=pUpsert ){ - /* The first ON CONFLICT clause has a conflict target other than - ** the IPK. We have to jump ahead to that first ON CONFLICT clause - ** and then come back here and deal with the IPK afterwards */ - upsertIpkDelay = sqlite3VdbeAddOp0(v, OP_Goto); - } - } - - /* If the response to a rowid conflict is REPLACE but the response - ** to some other UNIQUE constraint is FAIL or IGNORE, then we need - ** to defer the running of the rowid conflict checking until after - ** the UNIQUE constraints have run. - */ - if( onError==OE_Replace /* IPK rule is REPLACE */ - && onError!=overrideError /* Rules for other constraints are different */ - && pTab->pIndex /* There exist other constraints */ - && !upsertIpkDelay /* IPK check already deferred by UPSERT */ - ){ - ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; - VdbeComment((v, "defer IPK REPLACE until last")); - } - if( isUpdate ){ /* 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); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } + + /* If the response to a rowid conflict is REPLACE but the response + ** to some other UNIQUE constraint is FAIL or IGNORE, then we need + ** to defer the running of the rowid conflict checking until after + ** the UNIQUE constraints have run. + */ + if( onError==OE_Replace && overrideError!=OE_Replace ){ + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){ + ipkTop = sqlite3VdbeAddOp0(v, OP_Goto); + break; + } + } + } /* Check to see if the new rowid already exists in the table. Skip ** the following conflict logic if it does not. */ - VdbeNoopComment((v, "uniqueness check for ROWID")); - sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); VdbeCoverage(v); + /* Generate code that deals with a rowid collision */ switch( onError ){ default: { onError = OE_Abort; - /* no break */ deliberate_fall_through + /* Fall thru into the next case */ } case OE_Rollback: case OE_Abort: case OE_Fail: { - testcase( onError==OE_Rollback ); - testcase( onError==OE_Abort ); - testcase( onError==OE_Fail ); sqlite3RowidConstraint(pParse, onError, pTab); break; } case OE_Replace: { /* If there are DELETE triggers on this table and the @@ -136131,14 +110907,14 @@ ** recursive-triggers flag is set, call GenerateRowDelete() to ** remove the conflicting row from the table. This will fire ** the triggers and remove both the table and index b-tree entries. ** ** Otherwise, if there are no triggers or the recursive-triggers - ** flag is not set, but the table has one or more indexes, call - ** GenerateRowIndexDelete(). This removes the index b-tree entries - ** only. The table b-tree entry will be replaced by the new entry - ** when it is inserted. + ** flag is not set, but the table has one or more indexes, call + ** GenerateRowIndexDelete(). This removes the index b-tree entries + ** only. The table b-tree entry will be replaced by the new entry + ** when it is inserted. ** ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, ** also invoke MultiWrite() to indicate that this VDBE may require ** statement rollback (if the statement is aborted after the delete ** takes place). Earlier versions called sqlite3MultiWrite() regardless, @@ -136147,52 +110923,47 @@ ** REPLACE INTO t(rowid) VALUES($newrowid) ** ** to run without a statement journal if there are no indexes on the ** table. */ - if( regTrigCnt ){ + Trigger *pTrigger = 0; + if( db->flags&SQLITE_RecTriggers ){ + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); + } + if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regNewData, 1, 0, OE_Replace, 1, -1); - sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */ - nReplaceTrig++; }else{ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK - assert( HasRowid(pTab) ); - /* This OP_Delete opcode fires the pre-update-hook only. It does - ** not modify the b-tree. It is more efficient to let the coming - ** 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); - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + if( HasRowid(pTab) ){ + /* This OP_Delete opcode fires the pre-update-hook only. It does + ** not modify the b-tree. It is more efficient to let the coming + ** 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); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ if( pTab->pIndex ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); } } seenReplace = 1; break; } -#ifndef SQLITE_OMIT_UPSERT - case OE_Update: { - sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur); - /* no break */ deliberate_fall_through - } -#endif case OE_Ignore: { - testcase( onError==OE_Ignore ); + /*assert( seenReplace==0 );*/ sqlite3VdbeGoto(v, ignoreDest); break; } } sqlite3VdbeResolveLabel(v, addrRowidOk); - if( pUpsert && pUpsertClause!=pUpsert ){ - upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto); - }else if( ipkTop ){ + if( ipkTop ){ ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, ipkTop-1); + sqlite3VdbeJumpHere(v, ipkTop); } } /* Test all UNIQUE constraints by creating entries for each UNIQUE ** index and making sure that duplicate entries do not already exist. @@ -136199,43 +110970,31 @@ ** Compute the revised record entries for indices as we go. ** ** This loop also handles the case of the PRIMARY KEY index for a ** WITHOUT ROWID table. */ - for(pIdx = indexIteratorFirst(&sIdxIter, &ix); - pIdx; - pIdx = indexIteratorNext(&sIdxIter, &ix) - ){ - int regIdx; /* Range of registers holding content for pIdx */ + for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){ + int regIdx; /* Range of registers hold conent for pIdx */ int regR; /* Range of registers holding conflicting PK */ int iThisCur; /* Cursor for this UNIQUE index */ int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ - int addrConflictCk; /* First opcode in the conflict check logic */ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ - if( pUpsert ){ - pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx); - if( upsertIpkDelay && pUpsertClause==pUpsert ){ - sqlite3VdbeJumpHere(v, upsertIpkDelay); - } - } - addrUniqueOk = sqlite3VdbeMakeLabel(pParse); if( bAffinityDone==0 ){ sqlite3TableAffinity(v, pTab, regNewData+1); bAffinityDone = 1; } - VdbeNoopComment((v, "prep index %s", pIdx->zName)); iThisCur = iIdxCur+ix; - + addrUniqueOk = sqlite3VdbeMakeLabel(v); /* Skip partial indices for which the WHERE clause is not true */ if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); - pParse->iSelfTab = -(regNewData+1); + pParse->ckBase = regNewData+1; sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk, SQLITE_JUMPIFNULL); - pParse->iSelfTab = 0; + pParse->ckBase = 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 */ @@ -136242,35 +111001,31 @@ regIdx = aRegIdx[ix]+1; for(i=0; inColumn; i++){ int iField = pIdx->aiColumn[i]; int x; if( iField==XN_EXPR ){ - pParse->iSelfTab = -(regNewData+1); + pParse->ckBase = regNewData+1; sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); - pParse->iSelfTab = 0; + pParse->ckBase = 0; VdbeComment((v, "%s column %d", pIdx->zName, i)); - }else if( iField==XN_ROWID || iField==pTab->iPKey ){ - x = regNewData; - sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i); - VdbeComment((v, "rowid")); }else{ - testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField ); - x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1; - sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i); - VdbeComment((v, "%s", pTab->aCol[iField].zCnName)); + if( iField==XN_ROWID || iField==pTab->iPKey ){ + x = regNewData; + }else{ + x = iField + regNewData + 1; + } + sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i); + VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); } } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); #ifdef SQLITE_ENABLE_NULL_TRIM - if( pIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ - sqlite3SetMakeRecordP5(v, pIdx->pTable); - } + if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable); #endif - sqlite3VdbeReleaseRegisters(pParse, regIdx, pIdx->nColumn, 0, 0); - /* In an UPDATE operation, if this index is the PRIMARY KEY index + /* In an UPDATE operation, if this index is the PRIMARY KEY index ** of a WITHOUT ROWID table and there has been no change the ** primary key, then no collision is possible. The collision detection ** logic below can all be skipped. */ if( isUpdate && pPk==pIdx && pkChng==0 ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); @@ -136277,62 +111032,45 @@ continue; } /* Find out what action to take in case there is a uniqueness conflict */ onError = pIdx->onError; - if( onError==OE_None ){ + if( onError==OE_None ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; /* pIdx is not a UNIQUE index */ } if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } - /* Figure out if the upsert clause applies to this index */ - if( pUpsertClause ){ - if( pUpsertClause->isDoUpdate==0 ){ - onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ - }else{ - onError = OE_Update; /* DO UPDATE */ - } - } - /* 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. - ** - ** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row - ** must be explicitly deleted in order to ensure any pre-update hook - ** is invoked. */ - assert( IsOrdinaryTable(pTab) ); -#ifndef SQLITE_ENABLE_PREUPDATE_HOOK + */ 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->u.tab.pFKey && 0==sqlite3FkReferences(pTab))) + (0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } -#endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */ /* Check to see if the new index entry will be unique */ - sqlite3VdbeVerifyAbortable(v, onError); - addrConflictCk = - sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, - regIdx, pIdx->nKeyCol); VdbeCoverage(v); + sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, + regIdx, pIdx->nKeyCol); VdbeCoverage(v); /* Generate code to handle collisions */ - regR = pIdx==pPk ? regIdx : sqlite3GetTempRange(pParse, nPkField); + regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); if( isUpdate || onError==OE_Replace ){ if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); /* Conflict only if the rowid of the existing index entry ** is different from old-rowid */ @@ -136346,38 +111084,37 @@ /* Extract the PRIMARY KEY from the end of the index entry and ** store it in registers regR..regR+nPk-1 */ if( pIdx!=pPk ){ for(i=0; inKeyCol; i++){ assert( pPk->aiColumn[i]>=0 ); - x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); + x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); VdbeComment((v, "%s.%s", pTab->zName, - pTab->aCol[pPk->aiColumn[i]].zCnName)); + pTab->aCol[pPk->aiColumn[i]].zName)); } } if( isUpdate ){ - /* If currently processing the PRIMARY KEY of a WITHOUT ROWID + /* If currently processing the PRIMARY KEY of a WITHOUT ROWID ** table, only conflict if the new PRIMARY KEY values are actually - ** different from the old. See TH3 withoutrowid04.test. + ** different from the old. ** ** For a UNIQUE index, only conflict if the PRIMARY KEY values ** of the matched index row are different from the original PRIMARY ** KEY values of this row before the update. */ int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; int op = OP_Ne; int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); - + for(i=0; inKeyCol; i++){ char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); x = pPk->aiColumn[i]; assert( x>=0 ); if( i==(pPk->nKeyCol-1) ){ addrJump = addrUniqueOk; op = OP_Eq; } - x = sqlite3TableColumnToStorage(pTab, x); - sqlite3VdbeAddOp4(v, op, + sqlite3VdbeAddOp4(v, op, regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ ); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverageIf(v, op==OP_Eq); VdbeCoverageIf(v, op==OP_Ne); @@ -136386,155 +111123,44 @@ } } /* Generate code that executes if the new index entry is not unique */ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update ); + || onError==OE_Ignore || onError==OE_Replace ); switch( onError ){ case OE_Rollback: case OE_Abort: case OE_Fail: { - testcase( onError==OE_Rollback ); - testcase( onError==OE_Abort ); - testcase( onError==OE_Fail ); sqlite3UniqueConstraint(pParse, onError, pIdx); break; } -#ifndef SQLITE_OMIT_UPSERT - case OE_Update: { - sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix); - /* no break */ deliberate_fall_through - } -#endif case OE_Ignore: { - testcase( onError==OE_Ignore ); sqlite3VdbeGoto(v, ignoreDest); break; } default: { - int nConflictCk; /* Number of opcodes in conflict check logic */ - + Trigger *pTrigger = 0; assert( onError==OE_Replace ); - nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk; - assert( nConflictCk>0 || db->mallocFailed ); - testcase( nConflictCk<=0 ); - testcase( nConflictCk>1 ); - if( regTrigCnt ){ - sqlite3MultiWrite(pParse); - nReplaceTrig++; - } - if( pTrigger && isUpdate ){ - sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur); + sqlite3MultiWrite(pParse); + if( db->flags&SQLITE_RecTriggers ){ + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); - if( pTrigger && isUpdate ){ - sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur); - } - if( regTrigCnt ){ - int addrBypass; /* Jump destination to bypass recheck logic */ - - sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */ - addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */ - VdbeComment((v, "bypass recheck")); - - /* Here we insert code that will be invoked after all constraint - ** checks have run, if and only if one or more replace triggers - ** fired. */ - sqlite3VdbeResolveLabel(v, lblRecheckOk); - lblRecheckOk = sqlite3VdbeMakeLabel(pParse); - if( pIdx->pPartIdxWhere ){ - /* Bypass the recheck if this partial index is not defined - ** for the current row */ - sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk); - VdbeCoverage(v); - } - /* Copy the constraint check code from above, except change - ** the constraint-ok jump destination to be the address of - ** the next retest block */ - while( nConflictCk>0 ){ - VdbeOp x; /* Conflict check opcode to copy */ - /* The sqlite3VdbeAddOp4() call might reallocate the opcode array. - ** Hence, make a complete copy of the opcode, rather than using - ** a pointer to the opcode. */ - x = *sqlite3VdbeGetOp(v, addrConflictCk); - if( x.opcode!=OP_IdxRowid ){ - int p2; /* New P2 value for copied conflict check opcode */ - const char *zP4; - if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){ - p2 = lblRecheckOk; - }else{ - p2 = x.p2; - } - zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z; - sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type); - sqlite3VdbeChangeP5(v, x.p5); - VdbeCoverageIf(v, p2!=x.p2); - } - nConflictCk--; - addrConflictCk++; - } - /* If the retest fails, issue an abort */ - sqlite3UniqueConstraint(pParse, OE_Abort, pIdx); - - sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */ - } seenReplace = 1; break; } } sqlite3VdbeResolveLabel(v, addrUniqueOk); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); - if( pUpsertClause - && upsertIpkReturn - && sqlite3UpsertNextIsIPK(pUpsertClause) - ){ - sqlite3VdbeGoto(v, upsertIpkDelay+1); - sqlite3VdbeJumpHere(v, upsertIpkReturn); - upsertIpkReturn = 0; - } - } - - /* If the IPK constraint is a REPLACE, run it last */ + } if( ipkTop ){ - sqlite3VdbeGoto(v, ipkTop); - VdbeComment((v, "Do IPK REPLACE")); - assert( ipkBottom>0 ); + sqlite3VdbeGoto(v, ipkTop+1); sqlite3VdbeJumpHere(v, ipkBottom); } - - /* Recheck all uniqueness constraints after replace triggers have run */ - testcase( regTrigCnt!=0 && nReplaceTrig==0 ); - assert( regTrigCnt!=0 || nReplaceTrig==0 ); - if( nReplaceTrig ){ - sqlite3VdbeAddOp2(v, OP_IfNot, regTrigCnt, lblRecheckOk);VdbeCoverage(v); - if( !pPk ){ - if( isUpdate ){ - sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRecheck, regOldData); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRecheck, regNewData); - VdbeCoverage(v); - sqlite3RowidConstraint(pParse, OE_Abort, pTab); - }else{ - sqlite3VdbeGoto(v, addrRecheck); - } - sqlite3VdbeResolveLabel(v, lblRecheckOk); - } - - /* Generate the table record */ - if( HasRowid(pTab) ){ - int regRec = aRegIdx[ix]; - sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec); - sqlite3SetMakeRecordP5(v, pTab); - if( !bAffinityDone ){ - sqlite3TableAffinity(v, pTab, 0); - } - } - + *pbMayReplace = seenReplace; VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); } #ifdef SQLITE_ENABLE_NULL_TRIM @@ -136550,43 +111176,17 @@ /* 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].iDflt!=0 ) break; + if( pTab->aCol[i].pDflt!=0 ) break; if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; } sqlite3VdbeChangeP5(v, i+1); } #endif -/* -** Table pTab is a WITHOUT ROWID table that is being written to. The cursor -** number is iCur, and register regData contains the new record for the -** PK index. This function adds code to invoke the pre-update hook, -** if one is registered. -*/ -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK -static void codeWithoutRowidPreupdate( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being updated */ - int iCur, /* Cursor number for table */ - int regData /* Data containing new record */ -){ - Vdbe *v = pParse->pVdbe; - int r = sqlite3GetTempReg(pParse); - assert( !HasRowid(pTab) ); - assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB ); - sqlite3VdbeAddOp2(v, OP_Integer, 0, r); - sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE); - sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP); - sqlite3ReleaseTempReg(pParse, r); -} -#else -# define codeWithoutRowidPreupdate(a,b,c,d) -#endif - /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqlite3GenerateConstraintChecks. ** A consecutive range of registers starting at regNewData contains the ** rowid and the content to be inserted. @@ -136606,44 +111206,58 @@ int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ ){ Vdbe *v; /* Prepared statements under construction */ Index *pIdx; /* An index being inserted or updated */ u8 pik_flags; /* flag values passed to the btree insert */ + int regData; /* Content registers (after the rowid) */ + int regRec; /* Register holding assembled record for the table */ 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 = pParse->pVdbe; + v = sqlite3GetVdbe(pParse); assert( v!=0 ); - assert( !IsView(pTab) ); /* This table is not a VIEW */ + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - /* All REPLACE indexes are at the end of the list */ - assert( pIdx->onError!=OE_Replace - || pIdx->pNext==0 - || pIdx->pNext->onError==OE_Replace ); if( aRegIdx[i]==0 ) continue; + bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); } 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 ){ - codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]); + 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); + 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 |= (update_flags?update_flags:OPFLAG_LASTROWID); @@ -136652,11 +111266,11 @@ pik_flags |= OPFLAG_APPEND; } if( useSeekResult ){ pik_flags |= OPFLAG_USESEEKRESULT; } - sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, aRegIdx[i], regNewData); + sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); if( !pParse->nested ){ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } sqlite3VdbeChangeP5(v, pik_flags); } @@ -136698,36 +111312,33 @@ Index *pIdx; Vdbe *v; assert( op==OP_OpenRead || op==OP_OpenWrite ); assert( op==OP_OpenWrite || p5==0 ); - assert( piDataCur!=0 ); - assert( piIdxCur!=0 ); if( IsVirtual(pTab) ){ /* This routine is a no-op for virtual tables. Leave the output - ** variables *piDataCur and *piIdxCur set to illegal cursor numbers - ** for improved error detection. */ - *piDataCur = *piIdxCur = -999; + ** variables *piDataCur and *piIdxCur uninitialized so that valgrind + ** can detect if they are used by mistake in the caller. */ return 0; } iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - v = pParse->pVdbe; + v = sqlite3GetVdbe(pParse); assert( v!=0 ); if( iBase<0 ) iBase = pParse->nTab; iDataCur = iBase++; - *piDataCur = iDataCur; + if( piDataCur ) *piDataCur = iDataCur; if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); - }else if( pParse->db->noSharedCache==0 ){ + }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); } - *piIdxCur = iBase; + if( piIdxCur ) *piIdxCur = iBase; for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ int iIdxCur = iBase++; assert( pIdx->pSchema==pTab->pSchema ); if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - *piDataCur = iIdxCur; + if( piDataCur ) *piDataCur = iIdxCur; p5 = 0; } if( aToOpen==0 || aToOpen[i+1] ){ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); @@ -136765,11 +111376,11 @@ */ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ int i; assert( pDest && pSrc ); assert( pDest->pTable!=pSrc->pTable ); - if( pDest->nKeyCol!=pSrc->nKeyCol || pDest->nColumn!=pSrc->nColumn ){ + if( pDest->nKeyCol!=pSrc->nKeyCol ){ return 0; /* Different number of columns */ } if( pDest->onError!=pSrc->onError ){ return 0; /* Different conflict resolution strategies */ } @@ -136802,11 +111413,11 @@ /* ** Attempt the transfer optimization on INSERTs of the form ** ** INSERT INTO tab1 SELECT * FROM tab2; ** -** The xfer optimization transfers raw records from tab2 over to tab1. +** The xfer optimization transfers raw records from tab2 over to tab1. ** Columns are not decoded and reassembled, which greatly improves ** performance. Raw index records are transferred in the same way. ** ** The xfer optimization is only attempted if tab1 and tab2 are compatible. ** There are lots of rules for determining compatibility - see comments @@ -136833,11 +111444,11 @@ ){ sqlite3 *db = pParse->db; ExprList *pEList; /* The result set of the SELECT */ Table *pSrc; /* The table in the FROM clause of SELECT */ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ - SrcItem *pItem; /* An element of pSelect->pSrc */ + struct SrcList_item *pItem; /* An element of pSelect->pSrc */ int i; /* Loop counter */ int iDbSrc; /* The database of pSrc */ int iSrc, iDest; /* Cursors from source and destination */ int addr1, addr2; /* Loop addresses */ int emptyDestTest = 0; /* Address of test for empty pDest */ @@ -136845,17 +111456,22 @@ Vdbe *v; /* The VDBE we are building */ int regAutoinc; /* Memory register used by AUTOINC */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ int regData, regRowid; /* Registers holding data and rowid */ - assert( pSelect!=0 ); + if( pSelect==0 ){ + return 0; /* Must be of the form INSERT INTO ... SELECT ... */ + } if( pParse->pWith || pSelect->pWith ){ /* Do not attempt to process this query if there are an WITH clauses ** attached to it. Proceeding may generate a false "no such table: xxx" ** error if pSelect reads from a CTE named "xxx". */ return 0; } + if( sqlite3TriggerList(pParse, pDest) ){ + return 0; /* tab1 must not have triggers */ + } #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pDest) ){ return 0; /* tab1 must not be a virtual table */ } #endif @@ -136865,11 +111481,11 @@ } assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ if( pSelect->pSrc->nSrc!=1 ){ return 0; /* FROM clause must have exactly one term */ } - if( pSelect->pSrc->a[0].fg.isSubquery ){ + if( pSelect->pSrc->a[0].pSelect ){ return 0; /* FROM clause cannot contain a subquery */ } if( pSelect->pWhere ){ return 0; /* SELECT may not have a WHERE clause */ } @@ -136882,10 +111498,11 @@ return 0; /* SELECT may not have a GROUP BY clause */ } 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 */ } if( pSelect->selFlags & SF_Distinct ){ return 0; /* SELECT may not be DISTINCT */ @@ -136907,95 +111524,56 @@ pItem = pSelect->pSrc->a; pSrc = sqlite3LocateTableItem(pParse, 0, pItem); if( pSrc==0 ){ return 0; /* FROM clause does not contain a real table */ } - if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){ - testcase( pSrc!=pDest ); /* Possible due to bad sqlite_schema.rootpage */ + if( pSrc==pDest ){ return 0; /* tab1 and tab2 may not be the same table */ } if( HasRowid(pDest)!=HasRowid(pSrc) ){ return 0; /* source and destination must both be WITHOUT ROWID or not */ } - if( !IsOrdinaryTable(pSrc) ){ - return 0; /* tab2 may not be a view or virtual table */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pSrc) ){ + return 0; /* tab2 must not be a virtual table */ + } +#endif + if( pSrc->pSelect ){ + return 0; /* tab2 may not be a view */ } if( pDest->nCol!=pSrc->nCol ){ return 0; /* Number of columns must be the same in tab1 and tab2 */ } if( pDest->iPKey!=pSrc->iPKey ){ return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ } - if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){ - return 0; /* Cannot feed from a non-strict into a strict table */ - } for(i=0; inCol; i++){ Column *pDestCol = &pDest->aCol[i]; Column *pSrcCol = &pSrc->aCol[i]; #ifdef SQLITE_ENABLE_HIDDEN_COLUMNS - if( (db->mDbFlags & DBFLAG_Vacuum)==0 - && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN + if( (db->flags & SQLITE_Vacuum)==0 + && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN ){ return 0; /* Neither table may have __hidden__ columns */ } -#endif -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Even if tables t1 and t2 have identical schemas, if they contain - ** generated columns, then this statement is semantically incorrect: - ** - ** INSERT INTO t2 SELECT * FROM t1; - ** - ** The reason is that generated column values are returned by the - ** the SELECT statement on the right but the INSERT statement on the - ** left wants them to be omitted. - ** - ** Nevertheless, this is a useful notational shorthand to tell SQLite - ** to do a bulk transfer all of the content from t1 over to t2. - ** - ** We could, in theory, disable this (except for internal use by the - ** VACUUM command where it is actually needed). But why do that? It - ** seems harmless enough, and provides a useful service. - */ - if( (pDestCol->colFlags & COLFLAG_GENERATED) != - (pSrcCol->colFlags & COLFLAG_GENERATED) ){ - return 0; /* Both columns have the same generated-column type */ - } - /* But the transfer is only allowed if both the source and destination - ** tables have the exact same expressions for generated columns. - ** This requirement could be relaxed for VIRTUAL columns, I suppose. - */ - if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){ - if( sqlite3ExprCompare(0, - sqlite3ColumnExpr(pSrc, pSrcCol), - sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){ - testcase( pDestCol->colFlags & COLFLAG_VIRTUAL ); - testcase( pDestCol->colFlags & COLFLAG_STORED ); - return 0; /* Different generator expressions */ - } - } #endif if( pDestCol->affinity!=pSrcCol->affinity ){ return 0; /* Affinity must be the same on all columns */ } - if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol), - sqlite3ColumnColl(pSrcCol))!=0 ){ + if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){ return 0; /* Collating sequence must be the same on all columns */ } if( pDestCol->notNull && !pSrcCol->notNull ){ return 0; /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ - if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){ - Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol); - Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol); - assert( pDestExpr==0 || pDestExpr->op==TK_SPAN ); - assert( pDestExpr==0 || !ExprHasProperty(pDestExpr, EP_IntValue) ); - assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN ); - assert( pSrcExpr==0 || !ExprHasProperty(pSrcExpr, EP_IntValue) ); - if( (pDestExpr==0)!=(pSrcExpr==0) - || (pDestExpr!=0 && strcmp(pDestExpr->u.zToken, - pSrcExpr->u.zToken)!=0) + if( i>0 ){ + assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN ); + assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN ); + if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0) + || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken, + pSrcCol->pDflt->u.zToken)!=0) ){ return 0; /* Default values must be the same for all columns */ } } } @@ -137007,36 +111585,25 @@ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } if( pSrcIdx==0 ){ return 0; /* pDestIdx has no corresponding index in pSrc */ } - if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema - && sqlite3FaultSim(411)==SQLITE_OK ){ - /* The sqlite3FaultSim() call allows this corruption test to be - ** bypassed during testing, in order to exercise other corruption tests - ** further downstream. */ - return 0; /* Corrupt schema - two indexes on the same btree */ - } } #ifndef SQLITE_OMIT_CHECK - if( pDest->pCheck - && (db->mDbFlags & DBFLAG_Vacuum)==0 - && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) - ){ + if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ } #endif #ifndef SQLITE_OMIT_FOREIGN_KEY - /* Disallow the transfer optimization if the destination table contains + /* Disallow the transfer optimization if the destination table constains ** any foreign key constraints. This is more restrictive than necessary. - ** But the main beneficiary of the transfer optimization is the VACUUM + ** But the main beneficiary of the transfer optimization is the VACUUM ** command, and the VACUUM command disables foreign key constraints. So ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ - assert( IsOrdinaryTable(pDest) ); - if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){ + if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ return 0; } #endif if( (db->flags & SQLITE_CountRows)!=0 ){ return 0; /* xfer opt does not play well with PRAGMA count_changes */ @@ -137054,32 +111621,31 @@ sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; regAutoinc = autoIncBegin(pParse, iDbDest, pDest); regData = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, regData); regRowid = sqlite3GetTempReg(pParse); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 && ( + if( (db->flags & SQLITE_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 - ** DBFLAG_Vacuum flag is set, this block generates code to make - ** that determination. If DBFLAG_Vacuum is set, then the destination + ** SQLITE_Vacuum flag is set, this block generates code to make + ** that determination. If SQLITE_Vacuum is set, then the destination ** table is always empty. ** ** Conditions under which the destination must be empty: ** ** (1) There is no INTEGER PRIMARY KEY but there are indices. ** (If the destination is not initially empty, the rowid fields ** of index entries might need to change.) ** - ** (2) The destination has a unique index. (The xfer optimization + ** (2) The destination has a unique index. (The xfer optimization ** is unable to test uniqueness.) ** ** (3) onError is something other than OE_Abort and OE_Rollback. */ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); @@ -137090,46 +111656,32 @@ u8 insFlags; sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ - sqlite3VdbeVerifyAbortable(v, onError); - addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); - VdbeCoverage(v); - sqlite3RowidConstraint(pParse, onError, pDest); - sqlite3VdbeJumpHere(v, addr2); - } + addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + VdbeCoverage(v); + sqlite3RowidConstraint(pParse, onError, pDest); + sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); - }else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){ + }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); } - - if( db->mDbFlags & DBFLAG_Vacuum ){ - sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); - insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT; + sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); + if( db->flags & SQLITE_Vacuum ){ + sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| + OPFLAG_APPEND|OPFLAG_USESEEKRESULT; }else{ - insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT; - } -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ - sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - insFlags &= ~OPFLAG_PREFORMAT; - }else -#endif - { - sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid); - } - sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){ - sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE); - } - sqlite3VdbeChangeP5(v, insFlags); - + insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND; + } + sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, + (char*)pDest, P4_TABLE); + sqlite3VdbeChangeP5(v, insFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); @@ -137147,45 +111699,37 @@ sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest); sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); - if( db->mDbFlags & DBFLAG_Vacuum ){ + sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); + if( db->flags & SQLITE_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 + ** 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_SeekEnd is added before the - ** OP_IdxInsert to seek to the point within the b-tree where each key + ** of every OP_IdxInsert opcode, an OP_Last is added before the + ** OP_IdxInsert to seek to the point within the b-tree where each key ** should be inserted. This is faster. ** ** If any of the indexed columns use a collation sequence other than - ** BINARY, this optimization is disabled. This is because the user + ** BINARY, this optimization is disabled. This is because the user ** might change the definition of a collation sequence and then run ** a VACUUM command. In that case keys may not be written in strictly ** sorted order. */ for(i=0; inColumn; i++){ const char *zColl = pSrcIdx->azColl[i]; if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break; } if( i==pSrcIdx->nColumn ){ - idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT; - sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); - sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc); - } - }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ - idxInsFlags |= OPFLAG_NCHANGE; - } - if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){ - sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - if( (db->mDbFlags & DBFLAG_Vacuum)==0 - && !HasRowid(pDest) - && IsPrimaryKeyIndex(pDestIdx) - ){ - codeWithoutRowidPreupdate(pParse, pDest, iDest, regData); - } + idxInsFlags = OPFLAG_USESEEKRESULT; + sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + } + } + if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ + idxInsFlags |= OPFLAG_NCHANGE; } sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); @@ -137255,11 +111799,11 @@ if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); sqlite3Error(db, SQLITE_OK); while( rc==SQLITE_OK && zSql[0] ){ - int nCol = 0; + int nCol; char **azVals = 0; pStmt = 0; rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); assert( rc==SQLITE_OK || pStmt==0 ); @@ -137269,22 +111813,23 @@ if( !pStmt ){ /* this happens for a comment or white-space */ zSql = zLeftover; continue; } + callbackIsInit = 0; + nCol = sqlite3_column_count(pStmt); while( 1 ){ int i; rc = sqlite3_step(pStmt); /* Invoke the callback function if required */ - if( xCallback && (SQLITE_ROW==rc || + if( xCallback && (SQLITE_ROW==rc || (SQLITE_DONE==rc && !callbackIsInit && db->flags&SQLITE_NullCallback)) ){ if( !callbackIsInit ){ - nCol = sqlite3_column_count(pStmt); azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*)); if( azCols==0 ){ goto exec_out; } for(i=0; iresult_text16le #define sqlite3_result_value sqlite3_api->result_value #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->xsnprintf +#define sqlite3_snprintf sqlite3_api->snprintf #define sqlite3_step sqlite3_api->step #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup #define sqlite3_total_changes sqlite3_api->total_changes #define sqlite3_trace sqlite3_api->trace @@ -137889,11 +112360,11 @@ #define sqlite3_value_text16 sqlite3_api->value_text16 #define sqlite3_value_text16be sqlite3_api->value_text16be #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->xvsnprintf +#define sqlite3_vsnprintf sqlite3_api->vsnprintf #define sqlite3_overload_function sqlite3_api->overload_function #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 #define sqlite3_clear_bindings sqlite3_api->clear_bindings #define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob @@ -137965,11 +112436,11 @@ #define sqlite3_stmt_readonly sqlite3_api->stmt_readonly #define sqlite3_stricmp sqlite3_api->stricmp #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->xvsnprintf +#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 /* Version 3.8.7 and later */ #define sqlite3_auto_extension sqlite3_api->auto_extension #define sqlite3_bind_blob64 sqlite3_api->bind_blob64 #define sqlite3_bind_text64 sqlite3_api->bind_text64 @@ -138005,88 +112476,21 @@ #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 sqlite3_api->value_nochange -#define sqlite3_vtab_collation sqlite3_api->vtab_collation -/* Version 3.24.0 and later */ -#define sqlite3_keyword_count sqlite3_api->keyword_count -#define sqlite3_keyword_name sqlite3_api->keyword_name -#define sqlite3_keyword_check sqlite3_api->keyword_check -#define sqlite3_str_new sqlite3_api->str_new -#define sqlite3_str_finish sqlite3_api->str_finish -#define sqlite3_str_appendf sqlite3_api->str_appendf -#define sqlite3_str_vappendf sqlite3_api->str_vappendf -#define sqlite3_str_append sqlite3_api->str_append -#define sqlite3_str_appendall sqlite3_api->str_appendall -#define sqlite3_str_appendchar sqlite3_api->str_appendchar -#define sqlite3_str_reset sqlite3_api->str_reset -#define sqlite3_str_errcode sqlite3_api->str_errcode -#define sqlite3_str_length sqlite3_api->str_length -#define sqlite3_str_value sqlite3_api->str_value -/* Version 3.25.0 and later */ -#define sqlite3_create_window_function sqlite3_api->create_window_function -/* Version 3.26.0 and later */ -#define sqlite3_normalized_sql sqlite3_api->normalized_sql -/* Version 3.28.0 and later */ -#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain -#define sqlite3_value_frombind sqlite3_api->value_frombind -/* Version 3.30.0 and later */ -#define sqlite3_drop_modules sqlite3_api->drop_modules -/* Version 3.31.0 and later */ -#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64 -#define sqlite3_uri_key sqlite3_api->uri_key -#define sqlite3_filename_database sqlite3_api->filename_database -#define sqlite3_filename_journal sqlite3_api->filename_journal -#define sqlite3_filename_wal sqlite3_api->filename_wal -/* Version 3.32.0 and later */ -#define sqlite3_create_filename sqlite3_api->create_filename -#define sqlite3_free_filename sqlite3_api->free_filename -#define sqlite3_database_file_object sqlite3_api->database_file_object -/* Version 3.34.0 and later */ -#define sqlite3_txn_state sqlite3_api->txn_state -/* Version 3.36.1 and later */ -#define sqlite3_changes64 sqlite3_api->changes64 -#define sqlite3_total_changes64 sqlite3_api->total_changes64 -/* Version 3.37.0 and later */ -#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages -/* Version 3.38.0 and later */ -#define sqlite3_error_offset sqlite3_api->error_offset -#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value -#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct -#define sqlite3_vtab_in sqlite3_api->vtab_in -#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first -#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next -/* Version 3.39.0 and later */ -#ifndef SQLITE_OMIT_DESERIALIZE -#define sqlite3_deserialize sqlite3_api->deserialize -#define sqlite3_serialize sqlite3_api->serialize -#endif -#define sqlite3_db_name sqlite3_api->db_name -/* Version 3.40.0 and later */ -#define sqlite3_value_encoding sqlite3_api->value_encoding -/* Version 3.41.0 and later */ -#define sqlite3_is_interrupted sqlite3_api->is_interrupted -/* Version 3.43.0 and later */ -#define sqlite3_stmt_explain sqlite3_api->stmt_explain -/* Version 3.44.0 and later */ -#define sqlite3_get_clientdata sqlite3_api->get_clientdata -#define sqlite3_set_clientdata sqlite3_api->set_clientdata #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) - /* This case when the file really is being compiled as a loadable + /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; # define SQLITE_EXTENSION_INIT3 \ extern const sqlite3_api_routines *sqlite3_api; #else - /* This case when the file is being statically linked into the + /* This case when the file is being statically linked into the ** application */ # define SQLITE_EXTENSION_INIT1 /*no-op*/ # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ # define SQLITE_EXTENSION_INIT3 /*no-op*/ #endif @@ -138160,11 +112564,10 @@ # define sqlite3_create_module 0 # define sqlite3_create_module_v2 0 # define sqlite3_declare_vtab 0 # define sqlite3_vtab_config 0 # define sqlite3_vtab_on_conflict 0 -# define sqlite3_vtab_collation 0 #endif #ifdef SQLITE_OMIT_SHARED_CACHE # define sqlite3_enable_shared_cache 0 #endif @@ -138374,12 +112777,12 @@ sqlite3_create_collation_v2, sqlite3_file_control, sqlite3_memory_highwater, sqlite3_memory_used, #ifdef SQLITE_MUTEX_OMIT - 0, - 0, + 0, + 0, 0, 0, 0, #else sqlite3_mutex_alloc, @@ -138507,116 +112910,22 @@ /* 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, - /* Version 3.24.0 and later */ - sqlite3_keyword_count, - sqlite3_keyword_name, - sqlite3_keyword_check, - sqlite3_str_new, - sqlite3_str_finish, - sqlite3_str_appendf, - sqlite3_str_vappendf, - sqlite3_str_append, - sqlite3_str_appendall, - sqlite3_str_appendchar, - sqlite3_str_reset, - sqlite3_str_errcode, - sqlite3_str_length, - sqlite3_str_value, - /* Version 3.25.0 and later */ - sqlite3_create_window_function, - /* Version 3.26.0 and later */ -#ifdef SQLITE_ENABLE_NORMALIZE - sqlite3_normalized_sql, -#else - 0, -#endif - /* Version 3.28.0 and later */ - sqlite3_stmt_isexplain, - sqlite3_value_frombind, - /* Version 3.30.0 and later */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_drop_modules, -#else - 0, -#endif - /* Version 3.31.0 and later */ - sqlite3_hard_heap_limit64, - sqlite3_uri_key, - sqlite3_filename_database, - sqlite3_filename_journal, - sqlite3_filename_wal, - /* Version 3.32.0 and later */ - sqlite3_create_filename, - sqlite3_free_filename, - sqlite3_database_file_object, - /* Version 3.34.0 and later */ - sqlite3_txn_state, - /* Version 3.36.1 and later */ - sqlite3_changes64, - sqlite3_total_changes64, - /* Version 3.37.0 and later */ - sqlite3_autovacuum_pages, - /* Version 3.38.0 and later */ - sqlite3_error_offset, -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_vtab_rhs_value, - sqlite3_vtab_distinct, - sqlite3_vtab_in, - sqlite3_vtab_in_first, - sqlite3_vtab_in_next, -#else - 0, - 0, - 0, - 0, - 0, -#endif - /* Version 3.39.0 and later */ -#ifndef SQLITE_OMIT_DESERIALIZE - sqlite3_deserialize, - sqlite3_serialize, -#else - 0, - 0, -#endif - sqlite3_db_name, - /* Version 3.40.0 and later */ - sqlite3_value_encoding, - /* Version 3.41.0 and later */ - sqlite3_is_interrupted, - /* Version 3.43.0 and later */ - sqlite3_stmt_explain, - /* Version 3.44.0 and later */ - sqlite3_get_clientdata, - sqlite3_set_clientdata + sqlite3_value_pointer }; -/* True if x is the directory separator character -*/ -#if SQLITE_OS_WIN -# define DirSep(X) ((X)=='/'||(X)=='\\') -#else -# define DirSep(X) ((X)=='/') -#endif - /* ** Attempt to load an SQLite extension library contained in the file ** zFile. The entry point is zProc. zProc may be 0 in which case a ** default entry point name (sqlite3_extension_init) is used. Use ** of the default name is recommended. ** ** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. ** -** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with +** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with ** error message text. The calling function should free this memory ** by calling sqlite3DbFree(db, ). */ static int sqlite3LoadExtension( sqlite3 *db, /* Load the extension into this database connection */ @@ -138629,18 +112938,18 @@ sqlite3_loadext_entry xInit; char *zErrmsg = 0; const char *zEntry; char *zAltEntry = 0; void **aHandle; - u64 nMsg = strlen(zFile); + u64 nMsg = 300 + sqlite3Strlen30(zFile); int ii; int rc; /* Shared library endings to try if zFile cannot be loaded as written */ static const char *azEndings[] = { #if SQLITE_OS_WIN - "dll" + "dll" #elif defined(__APPLE__) "dylib" #else "so" #endif @@ -138663,44 +112972,38 @@ return SQLITE_ERROR; } zEntry = zProc ? zProc : "sqlite3_extension_init"; - /* tag-20210611-1. Some dlopen() implementations will segfault if given - ** an oversize filename. Most filesystems have a pathname limit of 4K, - ** so limit the extension filename length to about twice that. - ** https://sqlite.org/forum/forumpost/08a0d6d9bf - ** - ** Later (2023-03-25): Save an extra 6 bytes for the filename suffix. - ** See https://sqlite.org/forum/forumpost/24083b579d. - */ - if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found; - - /* Do not allow sqlite3_load_extension() to link to a copy of the - ** running application, by passing in an empty filename. */ - if( nMsg==0 ) goto extension_not_found; - handle = sqlite3OsDlOpen(pVfs, zFile); #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; ii sqlite3_example_init ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init */ @@ -138711,11 +113014,11 @@ if( zAltEntry==0 ){ sqlite3OsDlClose(pVfs, handle); return SQLITE_NOMEM_BKPT; } memcpy(zAltEntry, "sqlite3_", 8); - for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} + for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){} iFile++; if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ if( sqlite3Isalpha(c) ){ zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; @@ -138725,15 +113028,14 @@ zEntry = zAltEntry; xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); } if( xInit==0 ){ if( pzErrMsg ){ - nMsg += strlen(zEntry) + 300; + nMsg += sqlite3Strlen30(zEntry); *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ - assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */ - sqlite3_snprintf((int)nMsg, zErrmsg, + sqlite3_snprintf(nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zEntry, zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); } } sqlite3OsDlClose(pVfs, handle); @@ -138763,23 +113065,10 @@ sqlite3DbFree(db, db->aExtension); db->aExtension = aHandle; db->aExtension[db->nExtension++] = handle; return SQLITE_OK; - -extension_not_found: - if( pzErrMsg ){ - nMsg += 300; - *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); - if( zErrmsg ){ - assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */ - sqlite3_snprintf((int)nMsg, zErrmsg, - "unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile); - sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); - } - } - return SQLITE_ERROR; } SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ @@ -138809,18 +113098,15 @@ /* ** Enable or disable extension loading. Extension loading is disabled by ** default so as not to open security holes in older applications. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); if( onoff ){ db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; }else{ - db->flags &= ~(u64)(SQLITE_LoadExtension|SQLITE_LoadExtFunc); + db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc); } sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -138828,16 +113114,16 @@ /* ** The following object holds the list of automatically loaded ** extensions. ** -** This list is shared across threads. The SQLITE_MUTEX_STATIC_MAIN +** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER ** mutex must be held while accessing this list. */ typedef struct sqlite3AutoExtList sqlite3AutoExtList; static SQLITE_WSD struct sqlite3AutoExtList { - u32 nExt; /* Number of entries in aExt[] */ + u32 nExt; /* Number of entries in aExt[] */ void (**aExt)(void); /* Pointers to the extension init functions */ } sqlite3Autoext = { 0, 0 }; /* The "wsdAutoext" macro will resolve to the autoextension ** state vector. If writable static data is unsupported on the target, @@ -138861,23 +113147,20 @@ */ SQLITE_API int sqlite3_auto_extension( void (*xInit)(void) ){ int rc = SQLITE_OK; -#ifdef SQLITE_ENABLE_API_ARMOR - if( xInit==0 ) return SQLITE_MISUSE_BKPT; -#endif #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); if( rc ){ return rc; }else #endif { u32 i; #if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif wsdAutoextInit; sqlite3_mutex_enter(mutex); for(i=0; i=0; i--){ if( wsdAutoext.aExt[i]==xInit ){ wsdAutoext.nExt--; wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; @@ -138941,11 +113221,11 @@ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize()==SQLITE_OK ) #endif { #if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif wsdAutoextInit; sqlite3_mutex_enter(mutex); sqlite3_free(wsdAutoext.aExt); wsdAutoext.aExt = 0; @@ -138971,11 +113251,11 @@ return; } for(i=0; go; i++){ char *zErrmsg; #if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif #ifdef SQLITE_OMIT_LOAD_EXTENSION const sqlite3_api_routines *pThunk = 0; #else const sqlite3_api_routines *pThunk = &sqlite3Apis; @@ -139026,11 +113306,11 @@ /*************************************************************************** ** The "pragma.h" include file is an automatically generated file that ** that includes the PragType_XXXX macro definitions and the aPragmaName[] ** object. This ensures that the aPragmaName[] table is arranged in ** lexicographical order to facility a binary search of the pragma name. -** Do not edit pragma.h directly. Edit and rerun the script in at +** Do not edit pragma.h directly. Edit and rerun the script in at ** ../tool/mkpragmatab.tcl. */ /************** Include pragma.h in the middle of pragma.c *******************/ /************** Begin file pragma.h ******************************************/ /* DO NOT EDIT! ** This file is automatically generated by the script at @@ -139037,56 +113317,57 @@ ** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit ** that script and rerun it. */ /* The various pragma types */ -#define PragTyp_ACTIVATE_EXTENSIONS 0 -#define PragTyp_ANALYSIS_LIMIT 1 -#define PragTyp_HEADER_VALUE 2 -#define PragTyp_AUTO_VACUUM 3 -#define PragTyp_FLAG 4 -#define PragTyp_BUSY_TIMEOUT 5 -#define PragTyp_CACHE_SIZE 6 -#define PragTyp_CACHE_SPILL 7 -#define PragTyp_CASE_SENSITIVE_LIKE 8 -#define PragTyp_COLLATION_LIST 9 -#define PragTyp_COMPILE_OPTIONS 10 -#define PragTyp_DATA_STORE_DIRECTORY 11 -#define PragTyp_DATABASE_LIST 12 -#define PragTyp_DEFAULT_CACHE_SIZE 13 -#define PragTyp_ENCODING 14 -#define PragTyp_FOREIGN_KEY_CHECK 15 -#define PragTyp_FOREIGN_KEY_LIST 16 -#define PragTyp_FUNCTION_LIST 17 -#define PragTyp_HARD_HEAP_LIMIT 18 -#define PragTyp_INCREMENTAL_VACUUM 19 -#define PragTyp_INDEX_INFO 20 -#define PragTyp_INDEX_LIST 21 -#define PragTyp_INTEGRITY_CHECK 22 -#define PragTyp_JOURNAL_MODE 23 -#define PragTyp_JOURNAL_SIZE_LIMIT 24 -#define PragTyp_LOCK_PROXY_FILE 25 -#define PragTyp_LOCKING_MODE 26 -#define PragTyp_PAGE_COUNT 27 -#define PragTyp_MMAP_SIZE 28 -#define PragTyp_MODULE_LIST 29 -#define PragTyp_OPTIMIZE 30 -#define PragTyp_PAGE_SIZE 31 -#define PragTyp_PRAGMA_LIST 32 -#define PragTyp_SECURE_DELETE 33 -#define PragTyp_SHRINK_MEMORY 34 -#define PragTyp_SOFT_HEAP_LIMIT 35 -#define PragTyp_SYNCHRONOUS 36 -#define PragTyp_TABLE_INFO 37 -#define PragTyp_TABLE_LIST 38 -#define PragTyp_TEMP_STORE 39 -#define PragTyp_TEMP_STORE_DIRECTORY 40 -#define PragTyp_THREADS 41 -#define PragTyp_WAL_AUTOCHECKPOINT 42 -#define PragTyp_WAL_CHECKPOINT 43 +#define PragTyp_HEADER_VALUE 0 +#define PragTyp_AUTO_VACUUM 1 +#define PragTyp_FLAG 2 +#define PragTyp_BUSY_TIMEOUT 3 +#define PragTyp_CACHE_SIZE 4 +#define PragTyp_CACHE_SPILL 5 +#define PragTyp_CASE_SENSITIVE_LIKE 6 +#define PragTyp_COLLATION_LIST 7 +#define PragTyp_COMPILE_OPTIONS 8 +#define PragTyp_DATA_STORE_DIRECTORY 9 +#define PragTyp_DATABASE_LIST 10 +#define PragTyp_DEFAULT_CACHE_SIZE 11 +#define PragTyp_ENCODING 12 +#define PragTyp_FOREIGN_KEY_CHECK 13 +#define PragTyp_FOREIGN_KEY_LIST 14 +#define PragTyp_FUNCTION_LIST 15 +#define PragTyp_INCREMENTAL_VACUUM 16 +#define PragTyp_INDEX_INFO 17 +#define PragTyp_INDEX_LIST 18 +#define PragTyp_INTEGRITY_CHECK 19 +#define PragTyp_JOURNAL_MODE 20 +#define PragTyp_JOURNAL_SIZE_LIMIT 21 +#define PragTyp_LOCK_PROXY_FILE 22 +#define PragTyp_LOCKING_MODE 23 +#define PragTyp_PAGE_COUNT 24 +#define PragTyp_MMAP_SIZE 25 +#define PragTyp_MODULE_LIST 26 +#define PragTyp_OPTIMIZE 27 +#define PragTyp_PAGE_SIZE 28 +#define PragTyp_PRAGMA_LIST 29 +#define PragTyp_SECURE_DELETE 30 +#define PragTyp_SHRINK_MEMORY 31 +#define PragTyp_SOFT_HEAP_LIMIT 32 +#define PragTyp_SYNCHRONOUS 33 +#define PragTyp_TABLE_INFO 34 +#define PragTyp_TEMP_STORE 35 +#define PragTyp_TEMP_STORE_DIRECTORY 36 +#define PragTyp_THREADS 37 +#define PragTyp_WAL_AUTOCHECKPOINT 38 +#define PragTyp_WAL_CHECKPOINT 39 +#define PragTyp_ACTIVATE_EXTENSIONS 40 +#define PragTyp_HEXKEY 41 +#define PragTyp_KEY 42 +#define PragTyp_REKEY 43 #define PragTyp_LOCK_STATUS 44 -#define PragTyp_STATS 45 +#define PragTyp_PARSER_TRACE 45 +#define PragTyp_STATS 46 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ #define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ @@ -139099,95 +113380,81 @@ /* Names of columns for pragmas that return multi-column result ** or that return single-column results where the name of the ** result column is different from the name of the pragma */ static const char *const pragCName[] = { - /* 0 */ "id", /* Used by: foreign_key_list */ - /* 1 */ "seq", - /* 2 */ "table", - /* 3 */ "from", - /* 4 */ "to", - /* 5 */ "on_update", - /* 6 */ "on_delete", - /* 7 */ "match", - /* 8 */ "cid", /* Used by: table_xinfo */ - /* 9 */ "name", - /* 10 */ "type", - /* 11 */ "notnull", - /* 12 */ "dflt_value", - /* 13 */ "pk", - /* 14 */ "hidden", - /* table_info reuses 8 */ - /* 15 */ "schema", /* Used by: table_list */ - /* 16 */ "name", - /* 17 */ "type", - /* 18 */ "ncol", - /* 19 */ "wr", - /* 20 */ "strict", - /* 21 */ "seqno", /* Used by: index_xinfo */ - /* 22 */ "cid", - /* 23 */ "name", - /* 24 */ "desc", - /* 25 */ "coll", - /* 26 */ "key", - /* 27 */ "name", /* Used by: function_list */ - /* 28 */ "builtin", - /* 29 */ "type", - /* 30 */ "enc", - /* 31 */ "narg", - /* 32 */ "flags", - /* 33 */ "tbl", /* Used by: stats */ - /* 34 */ "idx", - /* 35 */ "wdth", - /* 36 */ "hght", - /* 37 */ "flgs", - /* 38 */ "seq", /* Used by: index_list */ - /* 39 */ "name", - /* 40 */ "unique", - /* 41 */ "origin", - /* 42 */ "partial", - /* 43 */ "table", /* Used by: foreign_key_check */ - /* 44 */ "rowid", - /* 45 */ "parent", - /* 46 */ "fkid", - /* index_info reuses 21 */ - /* 47 */ "seq", /* Used by: database_list */ - /* 48 */ "name", - /* 49 */ "file", - /* 50 */ "busy", /* Used by: wal_checkpoint */ - /* 51 */ "log", - /* 52 */ "checkpointed", - /* collation_list reuses 38 */ - /* 53 */ "database", /* Used by: lock_status */ - /* 54 */ "status", - /* 55 */ "cache_size", /* Used by: default_cache_size */ - /* module_list pragma_list reuses 9 */ - /* 56 */ "timeout", /* Used by: busy_timeout */ + /* 0 */ "cache_size", /* Used by: default_cache_size */ + /* 1 */ "cid", /* Used by: table_info */ + /* 2 */ "name", + /* 3 */ "type", + /* 4 */ "notnull", + /* 5 */ "dflt_value", + /* 6 */ "pk", + /* 7 */ "tbl", /* Used by: stats */ + /* 8 */ "idx", + /* 9 */ "wdth", + /* 10 */ "hght", + /* 11 */ "flgs", + /* 12 */ "seqno", /* Used by: index_info */ + /* 13 */ "cid", + /* 14 */ "name", + /* 15 */ "seqno", /* Used by: index_xinfo */ + /* 16 */ "cid", + /* 17 */ "name", + /* 18 */ "desc", + /* 19 */ "coll", + /* 20 */ "key", + /* 21 */ "seq", /* Used by: index_list */ + /* 22 */ "name", + /* 23 */ "unique", + /* 24 */ "origin", + /* 25 */ "partial", + /* 26 */ "seq", /* Used by: database_list */ + /* 27 */ "name", + /* 28 */ "file", + /* 29 */ "name", /* Used by: function_list */ + /* 30 */ "builtin", + /* 31 */ "name", /* Used by: module_list pragma_list */ + /* 32 */ "seq", /* Used by: collation_list */ + /* 33 */ "name", + /* 34 */ "id", /* Used by: foreign_key_list */ + /* 35 */ "seq", + /* 36 */ "table", + /* 37 */ "from", + /* 38 */ "to", + /* 39 */ "on_update", + /* 40 */ "on_delete", + /* 41 */ "match", + /* 42 */ "table", /* Used by: foreign_key_check */ + /* 43 */ "rowid", + /* 44 */ "parent", + /* 45 */ "fkid", + /* 46 */ "busy", /* Used by: wal_checkpoint */ + /* 47 */ "log", + /* 48 */ "checkpointed", + /* 49 */ "timeout", /* Used by: busy_timeout */ + /* 50 */ "database", /* Used by: lock_status */ + /* 51 */ "status", }; /* Definitions of all built-in pragmas */ typedef struct PragmaName { const char *const zName; /* Name of pragma */ u8 ePragTyp; /* PragTyp_XXX value */ u8 mPragFlg; /* Zero or more PragFlg_XXX values */ u8 iPragCName; /* Start of column names in pragCName[] */ u8 nPragCName; /* Num of col names. 0 means use pragma name */ - u64 iArg; /* Extra argument */ + u32 iArg; /* Extra argument */ } PragmaName; static const PragmaName aPragmaName[] = { -#if defined(SQLITE_ENABLE_CEROD) +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) {/* zName: */ "activate_extensions", /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif - {/* zName: */ "analysis_limit", - /* ePragTyp: */ PragTyp_ANALYSIS_LIMIT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "application_id", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, /* ColNames: */ 0, 0, @@ -139210,11 +113477,11 @@ #endif #endif {/* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 56, 1, + /* ColNames: */ 49, 1, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "cache_size", /* ePragTyp: */ PragTyp_CACHE_SIZE, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, @@ -139226,17 +113493,15 @@ /* ePragTyp: */ PragTyp_CACHE_SPILL, /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif -#if !defined(SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA) {/* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, /* ePragFlg: */ PragFlg_NoColumns, /* ColNames: */ 0, 0, /* iArg: */ 0 }, -#endif {/* zName: */ "cell_size_check", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_CellSizeCk }, @@ -139249,11 +113514,11 @@ #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) {/* zName: */ "collation_list", /* ePragTyp: */ PragTyp_COLLATION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 38, 2, + /* ColNames: */ 32, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) {/* zName: */ "compile_options", /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, @@ -139283,19 +113548,19 @@ /* iArg: */ BTREE_DATA_VERSION }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) {/* zName: */ "database_list", /* ePragTyp: */ PragTyp_DATABASE_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 47, 3, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, + /* ColNames: */ 26, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) {/* zName: */ "default_cache_size", /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 55, 1, + /* ColNames: */ 0, 1, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "defer_foreign_keys", @@ -139320,19 +113585,19 @@ /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "foreign_key_check", /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 43, 4, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, + /* ColNames: */ 42, 4, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) {/* zName: */ "foreign_key_list", /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 0, 8, + /* ColNames: */ 34, 8, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "foreign_keys", @@ -139360,23 +113625,30 @@ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_FullFSync }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) +#if defined(SQLITE_INTROSPECTION_PRAGMAS) {/* zName: */ "function_list", /* ePragTyp: */ PragTyp_FUNCTION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 27, 6, + /* ColNames: */ 29, 2, + /* iArg: */ 0 }, +#endif +#endif +#if defined(SQLITE_HAS_CODEC) + {/* zName: */ "hexkey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, /* iArg: */ 0 }, -#endif -#endif - {/* zName: */ "hard_heap_limit", - /* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT, - /* ePragFlg: */ PragFlg_Result0, + {/* zName: */ "hexrekey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, /* ColNames: */ 0, 0, /* iArg: */ 0 }, +#endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_CHECK) {/* zName: */ "ignore_check_constraints", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -139393,27 +113665,27 @@ #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) {/* zName: */ "index_info", /* ePragTyp: */ PragTyp_INDEX_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 21, 3, + /* ColNames: */ 12, 3, /* iArg: */ 0 }, {/* zName: */ "index_list", /* ePragTyp: */ PragTyp_INDEX_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 38, 5, + /* ColNames: */ 21, 5, /* iArg: */ 0 }, {/* zName: */ "index_xinfo", /* ePragTyp: */ PragTyp_INDEX_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 21, 6, + /* ColNames: */ 15, 6, /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "integrity_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "journal_mode", @@ -139424,17 +113696,24 @@ {/* zName: */ "journal_size_limit", /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, /* ColNames: */ 0, 0, /* iArg: */ 0 }, +#endif +#if defined(SQLITE_HAS_CODEC) + {/* zName: */ "key", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "legacy_alter_table", + {/* zName: */ "legacy_file_format", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_LegacyAlter }, + /* iArg: */ SQLITE_LegacyFileFmt }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE {/* zName: */ "lock_proxy_file", /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, /* ePragFlg: */ PragFlg_NoColumns1, @@ -139443,11 +113722,11 @@ #endif #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) {/* zName: */ "lock_status", /* ePragTyp: */ PragTyp_LOCK_STATUS, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 53, 2, + /* ColNames: */ 50, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "locking_mode", /* ePragTyp: */ PragTyp_LOCKING_MODE, @@ -139465,15 +113744,15 @@ /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) #if !defined(SQLITE_OMIT_VIRTUALTABLE) -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) +#if defined(SQLITE_INTROSPECTION_PRAGMAS) {/* zName: */ "module_list", /* ePragTyp: */ PragTyp_MODULE_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 9, 1, + /* ColNames: */ 31, 1, /* iArg: */ 0 }, #endif #endif #endif {/* zName: */ "optimize", @@ -139491,24 +113770,22 @@ /* ePragTyp: */ PragTyp_PAGE_SIZE, /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE) {/* zName: */ "parser_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, + /* ePragTyp: */ PragTyp_PARSER_TRACE, + /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ParserTrace }, + /* iArg: */ 0 }, #endif -#endif -#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) +#if defined(SQLITE_INTROSPECTION_PRAGMAS) {/* zName: */ "pragma_list", /* ePragTyp: */ PragTyp_PRAGMA_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 9, 1, + /* ColNames: */ 31, 1, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "query_only", /* ePragTyp: */ PragTyp_FLAG, @@ -139517,11 +113794,11 @@ /* iArg: */ SQLITE_QueryOnly }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "read_uncommitted", @@ -139532,10 +113809,19 @@ {/* zName: */ "recursive_triggers", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_RecTriggers }, +#endif +#if defined(SQLITE_HAS_CODEC) + {/* zName: */ "rekey", + /* ePragTyp: */ PragTyp_REKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "reverse_unordered_selects", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_ReverseOrder }, @@ -139582,11 +113868,11 @@ #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG) {/* zName: */ "stats", /* ePragTyp: */ PragTyp_STATS, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 33, 5, + /* ColNames: */ 7, 5, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "synchronous", /* ePragTyp: */ PragTyp_SYNCHRONOUS, @@ -139596,22 +113882,12 @@ #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) {/* zName: */ "table_info", /* ePragTyp: */ PragTyp_TABLE_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 8, 6, - /* iArg: */ 0 }, - {/* zName: */ "table_list", - /* ePragTyp: */ PragTyp_TABLE_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1, - /* ColNames: */ 15, 6, - /* iArg: */ 0 }, - {/* zName: */ "table_xinfo", - /* ePragTyp: */ PragTyp_TABLE_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 8, 7, - /* iArg: */ 1 }, + /* ColNames: */ 1, 6, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "temp_store", /* ePragTyp: */ PragTyp_TEMP_STORE, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -139626,17 +113902,10 @@ {/* zName: */ "threads", /* ePragTyp: */ PragTyp_THREADS, /* ePragFlg: */ PragFlg_Result0, /* ColNames: */ 0, 0, /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "trusted_schema", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_TrustedSchema }, -#endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "user_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, /* ColNames: */ 0, 0, @@ -139678,57 +113947,29 @@ /* ColNames: */ 0, 0, /* iArg: */ 0 }, {/* zName: */ "wal_checkpoint", /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 50, 3, + /* ColNames: */ 46, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "writable_schema", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, + /* iArg: */ SQLITE_WriteSchema }, #endif }; -/* Number of pragmas: 68 on by default, 78 total. */ +/* Number of pragmas: 60 on by default, 77 total. */ /************** End of pragma.h **********************************************/ /************** Continuing where we left off in pragma.c *********************/ -/* -** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands -** will be run with an analysis_limit set to the lessor of the value of -** the following macro or to the actual analysis_limit if it is non-zero, -** in order to prevent PRAGMA optimize from running for too long. -** -** The value of 2000 is chosen emperically so that the worst-case run-time -** for PRAGMA optimize does not exceed 100 milliseconds against a variety -** of test databases on a RaspberryPI-4 compiled using -Os and without -** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of -** this paragraph, "worst-case" means that ANALYZE ends up being -** run on every table in the database. The worst case typically only -** happens if PRAGMA optimize is run on a database file for which ANALYZE -** has not been previously run and the 0x10000 flag is included so that -** all tables are analyzed. The usual case for PRAGMA optimize is that -** no ANALYZE commands will be run at all, or if any ANALYZE happens it -** will be against a single table, so that expected timing for PRAGMA -** optimize on a PI-4 is more like 1 millisecond or less with the 0x10000 -** flag or less than 100 microseconds without the 0x10000 flag. -** -** An analysis limit of 2000 is almost always sufficient for the query -** planner to fully characterize an index. The additional accuracy from -** a larger analysis is not usually helpful. -*/ -#ifndef SQLITE_DEFAULT_OPTIMIZE_LIMIT -# define SQLITE_DEFAULT_OPTIMIZE_LIMIT 2000 -#endif - /* ** Interpret the given string as a safety level. Return 0 for OFF, -** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or +** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or ** unrecognized string argument. The FULL and EXTRA option is disallowed ** if the omitFull parameter it 1. ** ** Note that the values returned are one less that the values that ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done @@ -139783,11 +114024,11 @@ #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Interpret the given string as an auto-vacuum mode value. ** -** The following strings, "none", "full" and "incremental" are +** The following strings, "none", "full" and "incremental" are ** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively. */ static int getAutoVacuum(const char *z){ int i; if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE; @@ -139823,13 +114064,11 @@ ** from default, or when 'file' and the temp_store_directory has changed */ static int invalidateTempStorage(Parse *pParse){ sqlite3 *db = pParse->db; if( db->aDb[1].pBt!=0 ){ - if( !db->autoCommit - || sqlite3BtreeTxnState(db->aDb[1].pBt)!=SQLITE_TXN_NONE - ){ + if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){ sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " "from within a transaction"); return SQLITE_ERROR; } sqlite3BtreeClose(db->aDb[1].pBt); @@ -139937,11 +114176,11 @@ switch( action ){ case OE_SetNull: zName = "SET NULL"; break; case OE_SetDflt: zName = "SET DEFAULT"; break; case OE_Cascade: zName = "CASCADE"; break; case OE_Restrict: zName = "RESTRICT"; break; - default: zName = "NO ACTION"; + default: zName = "NO ACTION"; assert( action==OE_None ); break; } return zName; } #endif @@ -139988,79 +114227,29 @@ lwr = mid + 1; } } return lwr>upr ? 0 : &aPragmaName[mid]; } - -/* -** Create zero or more entries in the output for the SQL functions -** defined by FuncDef p. -*/ -static void pragmaFunclistLine( - Vdbe *v, /* The prepared statement being created */ - FuncDef *p, /* A particular function definition */ - int isBuiltin, /* True if this is a built-in function */ - int showInternFuncs /* True if showing internal functions */ -){ - u32 mask = - SQLITE_DETERMINISTIC | - SQLITE_DIRECTONLY | - SQLITE_SUBTYPE | - SQLITE_INNOCUOUS | - SQLITE_FUNC_INTERNAL - ; - if( showInternFuncs ) mask = 0xffffffff; - for(; p; p=p->pNext){ - const char *zType; - static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" }; - - assert( SQLITE_FUNC_ENCMASK==0x3 ); - assert( strcmp(azEnc[SQLITE_UTF8],"utf8")==0 ); - assert( strcmp(azEnc[SQLITE_UTF16LE],"utf16le")==0 ); - assert( strcmp(azEnc[SQLITE_UTF16BE],"utf16be")==0 ); - - if( p->xSFunc==0 ) continue; - if( (p->funcFlags & SQLITE_FUNC_INTERNAL)!=0 - && showInternFuncs==0 - ){ - continue; - } - if( p->xValue!=0 ){ - zType = "w"; - }else if( p->xFinalize!=0 ){ - zType = "a"; - }else{ - zType = "s"; - } - sqlite3VdbeMultiLoad(v, 1, "sissii", - p->zName, isBuiltin, - zType, azEnc[p->funcFlags&SQLITE_FUNC_ENCMASK], - p->nArg, - (p->funcFlags & mask) ^ SQLITE_INNOCUOUS - ); - } -} - /* ** 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. +** Generate code to output a single-column result row with the result +** held in register regResult. Decrement the result count and halt if +** the maximum number of result rows have been issued. */ -static int integrityCheckResultRow(Vdbe *v){ +static int integrityCheckResultRow(Vdbe *v, int regResult){ int addr; - sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1); addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); VdbeCoverage(v); - sqlite3VdbeAddOp0(v, OP_Halt); + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); return addr; } /* -** Process a pragma statement. +** Process a pragma statement. ** ** Pragmas are of this form: ** ** PRAGMA [schema.]id [= value] ** @@ -140071,11 +114260,11 @@ ** If the left side is "database.id" then pId1 is the database name ** and pId2 is the id. If the left side is just "id" then pId1 is the ** id and pId2 is any empty string. */ SQLITE_PRIVATE void sqlite3Pragma( - Parse *pParse, + Parse *pParse, Token *pId1, /* First part of [schema.]id field */ Token *pId2, /* Second part of [schema.]id field, or NULL */ Token *pValue, /* Token for , or NULL */ int minusFlag /* True if a '-' sign preceded */ ){ @@ -140099,12 +114288,12 @@ ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; pDb = &db->aDb[iDb]; - /* If the temp database has been explicitly named as part of the - ** pragma, make sure it is open. + /* If the temp database has been explicitly named as part of the + ** pragma, make sure it is open. */ if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ return; } @@ -140160,31 +114349,27 @@ goto pragma_out; } /* Locate the pragma in the lookup table */ pPragma = pragmaLocate(zLeft); - if( pPragma==0 ){ - /* IMP: R-43042-22504 No error messages are generated if an - ** unknown pragma is issued. */ - goto pragma_out; - } + if( pPragma==0 ) goto pragma_out; /* Make sure the database schema is loaded if the pragma requires that */ 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 + 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 ){ - + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* ** PRAGMA [schema.]default_cache_size ** PRAGMA [schema.]default_cache_size=N ** @@ -140254,11 +114439,11 @@ }else{ /* Malloc may fail when setting the page-size, as there is an internal ** buffer that the pager module resizes using sqlite3_realloc(). */ db->nextPagesize = sqlite3Atoi(zRight); - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,0,0) ){ + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ sqlite3OomFault(db); } } break; } @@ -140296,11 +114481,11 @@ /* ** PRAGMA [schema.]max_page_count ** PRAGMA [schema.]max_page_count=N ** ** The first form reports the current setting for the - ** maximum number of pages in the database file. The + ** maximum number of pages in the database file. The ** second form attempts to change this setting. Both ** forms return the current setting. ** ** The absolute value of N is used. This is undocumented and might ** change. The only purpose is to provide an easy way to test @@ -140310,23 +114495,17 @@ ** ** Return the number of pages in the specified database. */ case PragTyp_PAGE_COUNT: { int iReg; - i64 x = 0; sqlite3CodeVerifySchema(pParse, iDb); iReg = ++pParse->nMem; if( sqlite3Tolower(zLeft[0])=='p' ){ sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); }else{ - if( zRight && sqlite3DecOrHexToI64(zRight,&x)==0 ){ - if( x<0 ) x = 0; - else if( x>0xfffffffe ) x = 0xfffffffe; - }else{ - x = 0; - } - sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, (int)x); + sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, + sqlite3AbsInt32(sqlite3Atoi(zRight))); } sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); break; } @@ -140398,15 +114577,10 @@ if( !zMode ){ /* If the "=MODE" part does not match any known journal mode, ** then do a query */ eMode = PAGER_JOURNALMODE_QUERY; } - if( eMode==PAGER_JOURNALMODE_OFF && (db->flags & SQLITE_Defensive)!=0 ){ - /* Do not allow journal-mode "OFF" in defensive since the database - ** can become corrupted using ordinary SQL when the journal is off */ - eMode = PAGER_JOURNALMODE_QUERY; - } } if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){ /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */ iDb = 0; pId2->n = 1; @@ -140463,11 +114637,11 @@ ** creates the database file. It is important that it is created ** as an auto-vacuum capable db. */ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ - /* When setting the auto_vacuum mode to either "full" or + /* When setting the auto_vacuum mode to either "full" or ** "incremental", write the value of meta[6] in the database ** file. Before writing to meta[6], check that meta[3] indicates ** that this really is an auto-vacuum capable database. */ static const int iLn = VDBE_OFFSET_LINENO(2); @@ -140500,11 +114674,11 @@ ** ** Do N steps of incremental vacuuming on a database. */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_INCREMENTAL_VACUUM: { - int iLimit = 0, addr; + int iLimit, addr; if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ iLimit = 0x7fffffff; } sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); @@ -140546,11 +114720,11 @@ ** PRAGMA cache_spill=BOOLEAN ** PRAGMA [schema.]cache_spill=N ** ** The first form reports the current local setting for the ** page cache spill size. The second form turns cache spill on - ** or off. When turning cache spill on, the size is set to the + ** or off. When turnning cache spill on, the size is set to the ** current cache_size. The third form sets a spill size that ** may be different form the cache size. ** If N is positive then that is the ** number of pages in the cache. If N is negative, then the ** number of pages is adjusted so that the cache uses -N kibibytes @@ -140565,21 +114739,21 @@ */ case PragTyp_CACHE_SPILL: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ returnSingleInt(v, - (db->flags & SQLITE_CacheSpill)==0 ? 0 : + (db->flags & SQLITE_CacheSpill)==0 ? 0 : sqlite3BtreeSetSpillSize(pDb->pBt,0)); }else{ int size = 1; if( sqlite3GetInt32(zRight, &size) ){ sqlite3BtreeSetSpillSize(pDb->pBt, size); } if( sqlite3GetBoolean(zRight, size!=0) ){ db->flags |= SQLITE_CacheSpill; }else{ - db->flags &= ~(u64)SQLITE_CacheSpill; + db->flags &= ~SQLITE_CacheSpill; } setAllPagerFlags(db); } break; } @@ -140657,21 +114831,19 @@ ** Setting to a null string reverts to the default temporary directory search. ** If temporary directory is changed, then invalidateTempStorage. ** */ case PragTyp_TEMP_STORE_DIRECTORY: { - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_temp_directory); }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ int res; rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } if( SQLITE_TEMP_STORE==0 || (SQLITE_TEMP_STORE==1 && db->temp_store<=1) @@ -140685,11 +114857,10 @@ }else{ sqlite3_temp_directory = 0; } #endif /* SQLITE_OMIT_WSD */ } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } #if SQLITE_OS_WIN /* @@ -140704,21 +114875,19 @@ ** process. Database file specified with an absolute path are not impacted ** by this setting, regardless of its value. ** */ case PragTyp_DATA_STORE_DIRECTORY: { - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_data_directory); }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ int res; rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } sqlite3_free(sqlite3_data_directory); if( zRight[0] ){ @@ -140726,11 +114895,10 @@ }else{ sqlite3_data_directory = 0; } #endif /* SQLITE_OMIT_WSD */ } - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } #endif #if SQLITE_ENABLE_LOCKING_STYLE @@ -140745,33 +114913,33 @@ case PragTyp_LOCK_PROXY_FILE: { if( !zRight ){ Pager *pPager = sqlite3BtreePager(pDb->pBt); char *proxy_file_path = NULL; sqlite3_file *pFile = sqlite3PagerFile(pPager); - sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, + sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, &proxy_file_path); returnSingleText(v, proxy_file_path); }else{ Pager *pPager = sqlite3BtreePager(pDb->pBt); sqlite3_file *pFile = sqlite3PagerFile(pPager); int res; if( zRight[0] ){ - res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, + res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, zRight); } else { - res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, + res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, NULL); } if( res!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "failed to set lock proxy file"); goto pragma_out; } } break; } -#endif /* SQLITE_ENABLE_LOCKING_STYLE */ - +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + /* ** PRAGMA [schema.]synchronous ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA ** ** Return or set the local value of the synchronous flag. Changing @@ -140782,11 +114950,11 @@ case PragTyp_SYNCHRONOUS: { if( !zRight ){ returnSingleInt(v, pDb->safety_level-1); }else{ if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else if( iDb!=1 ){ int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; if( iLevel==0 ) iLevel = 1; pDb->safety_level = iLevel; @@ -140802,37 +114970,31 @@ case PragTyp_FLAG: { if( zRight==0 ){ setPragmaResultColumnNames(v, pPragma); returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); }else{ - u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */ + int mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ mask &= ~(SQLITE_ForeignKeys); } +#if SQLITE_USER_AUTHENTICATION + if( db->auth.authLevel==UAUTH_User ){ + /* Do not allow non-admin users to modify the schema arbitrarily */ + mask &= ~(SQLITE_WriteSchema); + } +#endif if( sqlite3GetBoolean(zRight, 0) ){ - if( (mask & SQLITE_WriteSchema)==0 - || (db->flags & SQLITE_Defensive)==0 - ){ - db->flags |= mask; - } + db->flags |= mask; }else{ db->flags &= ~mask; if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; - if( (mask & SQLITE_WriteSchema)!=0 - && sqlite3_stricmp(zRight, "reset")==0 - ){ - /* IMP: R-60817-01178 If the argument is "RESET" then schema - ** writing is disabled (as with "PRAGMA writable_schema=OFF") and, - ** in addition, the schema is reloaded. */ - sqlite3ResetAllSchemasOfConnection(db); - } } - /* Many of the flag-pragmas modify the code generated by the SQL + /* Many of the flag-pragmas modify the code generated by the SQL ** compiler (eg. count_changes). So add an opcode to expire all ** compiled SQL statements after modifying a pragma value. */ sqlite3VdbeAddOp0(v, OP_Expire); setAllPagerFlags(db); @@ -140851,138 +115013,42 @@ ** cid: Column id (numbered from left to right, starting at 0) ** name: Column name ** 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; - sqlite3CodeVerifyNamedSchema(pParse, zDb); pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); - pParse->nMem = 7; + pParse->nMem = 6; + sqlite3CodeVerifySchema(pParse, iDb); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ - int isHidden = 0; - const Expr *pColExpr; - if( pCol->colFlags & COLFLAG_NOINSERT ){ - if( pPragma->iArg==0 ){ - nHidden++; - continue; - } - if( pCol->colFlags & COLFLAG_VIRTUAL ){ - isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */ - }else if( pCol->colFlags & COLFLAG_STORED ){ - isHidden = 3; /* GENERATED ALWAYS AS ... STORED */ - }else{ assert( pCol->colFlags & COLFLAG_HIDDEN ); - isHidden = 1; /* HIDDEN */ - } + if( IsHiddenColumn(pCol) ){ + nHidden++; + continue; } if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } - pColExpr = sqlite3ColumnExpr(pTab,pCol); - assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 ); - assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue) - || isHidden>=2 ); - sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", + assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); + sqlite3VdbeMultiLoad(v, 1, "issisi", i-nHidden, - pCol->zCnName, + pCol->zName, sqlite3ColumnType(pCol,""), pCol->notNull ? 1 : 0, - (isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken, - k, - isHidden); - } - } - } - break; - - /* - ** PRAGMA table_list - ** - ** Return a single row for each table, virtual table, or view in the - ** entire schema. - ** - ** schema: Name of attached database hold this table - ** name: Name of the table itself - ** type: "table", "view", "virtual", "shadow" - ** ncol: Number of columns - ** wr: True for a WITHOUT ROWID table - ** strict: True for a STRICT table - */ - case PragTyp_TABLE_LIST: { - int ii; - pParse->nMem = 6; - sqlite3CodeVerifyNamedSchema(pParse, zDb); - for(ii=0; iinDb; ii++){ - HashElem *k; - Hash *pHash; - int initNCol; - if( zDb && sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue; - - /* Ensure that the Table.nCol field is initialized for all views - ** and virtual tables. Each time we initialize a Table.nCol value - ** for a table, that can potentially disrupt the hash table, so restart - ** the initialization scan. - */ - pHash = &db->aDb[ii].pSchema->tblHash; - initNCol = sqliteHashCount(pHash); - while( initNCol-- ){ - for(k=sqliteHashFirst(pHash); 1; k=sqliteHashNext(k) ){ - Table *pTab; - if( k==0 ){ initNCol = 0; break; } - pTab = sqliteHashData(k); - if( pTab->nCol==0 ){ - char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName); - if( zSql ){ - sqlite3_stmt *pDummy = 0; - (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG, - &pDummy, 0); - (void)sqlite3_finalize(pDummy); - sqlite3DbFree(db, zSql); - } - if( db->mallocFailed ){ - sqlite3ErrorMsg(db->pParse, "out of memory"); - db->pParse->rc = SQLITE_NOMEM_BKPT; - } - pHash = &db->aDb[ii].pSchema->tblHash; - break; - } - } - } - - for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){ - Table *pTab = sqliteHashData(k); - const char *zType; - if( zRight && sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue; - if( IsView(pTab) ){ - zType = "view"; - }else if( IsVirtual(pTab) ){ - zType = "virtual"; - }else if( pTab->tabFlags & TF_Shadow ){ - zType = "shadow"; - }else{ - zType = "table"; - } - sqlite3VdbeMultiLoad(v, 1, "sssiii", - db->aDb[ii].zDbSName, - sqlite3PreferredTableName(pTab->zName), - zType, - pTab->nCol, - (pTab->tabFlags & TF_WithoutRowid)!=0, - (pTab->tabFlags & TF_Strict)!=0 - ); + pCol->pDflt ? pCol->pDflt->u.zToken : 0, + k); } } } break; @@ -140993,11 +115059,11 @@ pParse->nMem = 5; sqlite3CodeVerifySchema(pParse, iDb); for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); sqlite3VdbeMultiLoad(v, 1, "ssiii", - sqlite3PreferredTableName(pTab->zName), + pTab->zName, 0, pTab->szTabRow, pTab->nRowLogEst, pTab->tabFlags); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ @@ -141015,21 +115081,11 @@ case PragTyp_INDEX_INFO: if( zRight ){ Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); - if( pIdx==0 ){ - /* If there is no index named zRight, check to see if there is a - ** WITHOUT ROWID table named zRight, and if there is, show the - ** structure of the PRIMARY KEY index for that table. */ - pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); - if( pTab && !HasRowid(pTab) ){ - pIdx = sqlite3PrimaryKeyIndex(pTab); - } - } if( pIdx ){ - int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); int i; int mx; if( pPragma->iArg ){ /* PRAGMA index_xinfo (newer version with more rows and columns) */ mx = pIdx->nColumn; @@ -141038,16 +115094,16 @@ /* PRAGMA index_info (legacy version) */ mx = pIdx->nKeyCol; pParse->nMem = 3; } pTab = pIdx->pTable; - sqlite3CodeVerifySchema(pParse, iIdxDb); + sqlite3CodeVerifySchema(pParse, iDb); assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; iaiColumn[i]; sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum, - cnum<0 ? 0 : pTab->aCol[cnum].zCnName); + cnum<0 ? 0 : pTab->aCol[cnum].zName); if( pPragma->iArg ){ sqlite3VdbeMultiLoad(v, 4, "isiX", pIdx->aSortOrder[i], pIdx->azColl[i], inKeyCol); @@ -141062,13 +115118,12 @@ Index *pIdx; Table *pTab; int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ - int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); pParse->nMem = 5; - sqlite3CodeVerifySchema(pParse, iTabDb); + sqlite3CodeVerifySchema(pParse, iDb); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeMultiLoad(v, 1, "isisi", i, pIdx->zName, @@ -141103,27 +115158,26 @@ sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); } } break; -#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS +#ifdef SQLITE_INTROSPECTION_PRAGMAS case PragTyp_FUNCTION_LIST: { int i; HashElem *j; FuncDef *p; - int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0; - pParse->nMem = 6; + pParse->nMem = 2; for(i=0; iu.pHash ){ - assert( p->funcFlags & SQLITE_FUNC_BUILTIN ); - pragmaFunclistLine(v, p, 1, showInternFunc); + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } } for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){ p = (FuncDef*)sqliteHashData(j); - assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 ); - pragmaFunclistLine(v, p, 0, showInternFunc); + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } } break; #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -141131,19 +115185,21 @@ 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); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } } break; #endif /* SQLITE_OMIT_VIRTUALTABLE */ case PragTyp_PRAGMA_LIST: { int i; for(i=0; iu.tab.pFKey; + if( pTab ){ + pFK = pTab->pFKey; if( pFK ){ - int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); - int i = 0; + int i = 0; pParse->nMem = 8; - sqlite3CodeVerifySchema(pParse, iTabDb); + sqlite3CodeVerifySchema(pParse, iDb); while(pFK){ int j; for(j=0; jnCol; j++){ sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j, pFK->zTo, - pTab->aCol[pFK->aCol[j].iFrom].zCnName, + pTab->aCol[pFK->aCol[j].iFrom].zName, pFK->aCol[j].zCol, actionName(pFK->aAction[1]), /* ON UPDATE */ actionName(pFK->aAction[0]), /* ON DELETE */ "NONE"); } @@ -141193,37 +115248,36 @@ int i; /* Loop counter: Foreign key number for pTab */ int j; /* Loop counter: Field of the foreign key */ HashElem *k; /* Loop counter: Next table in schema */ int x; /* result variable */ int regResult; /* 3 registers to hold a result row */ + int regKey; /* Register to hold key for checking the FK */ int regRow; /* Registers to hold a row from pTab */ 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 */ regResult = pParse->nMem+1; pParse->nMem += 4; + regKey = ++pParse->nMem; regRow = ++pParse->nMem; + sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); k = 0; }else{ pTab = (Table*)sqliteHashData(k); k = sqliteHashNext(k); } - if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zDb = db->aDb[iDb].zDbSName; - sqlite3CodeVerifySchema(pParse, iDb); + if( pTab==0 || pTab->pFKey==0 ) continue; sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - sqlite3TouchRegister(pParse, pTab->nCol+regRow); + if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regResult, pTab->zName); - assert( IsOrdinaryTable(pTab) ); - for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; pIdx = 0; sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); @@ -141241,44 +115295,42 @@ } assert( pParse->nErr>0 || pFK==0 ); if( pFK ) break; if( pParse->nTabnTab = i; addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); - assert( IsOrdinaryTable(pTab) ); - for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); pIdx = 0; aiCols = 0; if( pParent ){ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); - assert( x==0 || db->mallocFailed ); + assert( x==0 ); } - addrOk = sqlite3VdbeMakeLabel(pParse); + addrOk = sqlite3VdbeMakeLabel(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 + ** 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. */ - sqlite3TouchRegister(pParse, regRow + pFK->nCol); 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_Affinity, regRow, pFK->nCol, 0, + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, 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); - assert( pFK->nCol==1 || db->mallocFailed ); + assert( pFK->nCol==1 ); } /* Generate code to report an FK violation to the caller. */ if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); @@ -141296,21 +115348,32 @@ } break; #endif /* !defined(SQLITE_OMIT_TRIGGER) */ #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ -#ifndef SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA +#ifndef NDEBUG + case PragTyp_PARSER_TRACE: { + if( zRight ){ + if( sqlite3GetBoolean(zRight, 0) ){ + sqlite3ParserTrace(stdout, "parser: "); + }else{ + sqlite3ParserTrace(0, 0); + } + } + } + break; +#endif + /* Reinstall the LIKE and GLOB functions. The variant of LIKE ** used will be case sensitive or not depending on the RHS. */ case PragTyp_CASE_SENSITIVE_LIKE: { if( zRight ){ sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); } } break; -#endif /* SQLITE_OMIT_CASE_SENSITIVE_LIKE_PRAGMA */ #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 #endif @@ -141320,30 +115383,17 @@ ** PRAGMA quick_check ** PRAGMA quick_check(N) ** ** Verify the integrity of the database. ** - ** The "quick_check" is reduced version of + ** The "quick_check" is reduced version of ** integrity_check designed to detect most database corruption ** without the overhead of cross-checking indexes. Quick_check - ** is linear time whereas integrity_check is O(NlogN). - ** - ** The maximum number of errors is 100 by default. A different default - ** can be specified using a numeric parameter N. - ** - ** Or, the parameter N can be the name of a table. In that case, only - ** the one table named is verified. The freelist is only verified if - ** the named table is "sqlite_schema" (or one of its aliases). - ** - ** All schemas are checked by default. To check just a single - ** schema, use the form: - ** - ** PRAGMA schema.integrity_check; + ** is linear time wherease integrity_check is O(NlogN). */ case PragTyp_INTEGRITY_CHECK: { int i, j, addr, mxErr; - Table *pObjTab = 0; /* Check only this one table, if not NULL */ int isQuick = (sqlite3Tolower(zLeft[0])=='q'); /* If the PRAGMA command was of the form "PRAGMA .integrity_check", ** then iDb is set to the index of the database identified by . @@ -141362,495 +115412,222 @@ pParse->nMem = 6; /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; if( zRight ){ - if( sqlite3GetInt32(pValue->z, &mxErr) ){ - if( mxErr<=0 ){ - mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; - } - }else{ - pObjTab = sqlite3LocateTable(pParse, 0, zRight, - iDb>=0 ? db->aDb[iDb].zDbSName : 0); + sqlite3GetInt32(zRight, &mxErr); + if( mxErr<=0 ){ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; } } 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; /* 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[] */ + HashElem *x; + Hash *pTbls; + int *aRoot; + int cnt = 0; + int mxIdx = 0; + int nIdx; if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; sqlite3CodeVerifySchema(pParse, i); - pParse->okConstFactor = 0; /* tag-20230327-1 */ /* Do an integrity check of the B-Tree ** ** Begin by finding the root pages numbers ** for all tables and indices in the database. */ 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); /* Current table */ - Index *pIdx; /* An index on pTab */ - int nIdx; /* Number of indexes on pTab */ - if( pObjTab && pObjTab!=pTab ) continue; + Table *pTab = sqliteHashData(x); + Index *pIdx; if( HasRowid(pTab) ) cnt++; for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } + if( nIdx>mxIdx ) mxIdx = nIdx; } - if( cnt==0 ) continue; - if( pObjTab ) cnt++; aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1)); if( aRoot==0 ) break; - cnt = 0; - if( pObjTab ) aRoot[++cnt] = 0; - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; - if( pObjTab && pObjTab!=pTab ) continue; - 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[0] = cnt; + aRoot[cnt] = 0; /* Make sure sufficient number of registers have been allocated */ - sqlite3TouchRegister(pParse, 8+cnt); - sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt); - sqlite3ClearTempRegCache(pParse); + pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); /* Do the b-tree integrity checks */ - sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY); - sqlite3VdbeChangeP5(v, (u16)i); + sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); + sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), P4_DYNAMIC); - sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, addr); - - /* Check that the indexes all have the right number of rows */ - cnt = pObjTab ? 1 : 0; - sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - int iTab = 0; - Table *pTab = sqliteHashData(x); - Index *pIdx; - if( pObjTab && pObjTab!=pTab ) continue; - if( HasRowid(pTab) ){ - iTab = cnt++; - }else{ - iTab = cnt; - for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){ - if( IsPrimaryKeyIndex(pIdx) ) break; - iTab++; - } - } - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->pPartIdxWhere==0 ){ - addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+cnt, 0, 8+iTab); - VdbeCoverageNeverNull(v); - sqlite3VdbeLoadString(v, 4, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, addr); - } - cnt++; - } - } + sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); + sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); + integrityCheckResultRow(v, 2); + sqlite3VdbeJumpHere(v, addr); /* Make sure all the indices are constructed correctly. */ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx, *pPk; - Index *pPrior = 0; /* Previous index */ + Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; int r1 = -1; - int bStrict; /* True for a STRICT table */ - int r2; /* Previous key for WITHOUT ROWID tables */ - int mxCol; /* Maximum non-virtual column number */ - - if( pObjTab && pObjTab!=pTab ) continue; - if( !IsOrdinaryTable(pTab) ) continue; - if( isQuick || HasRowid(pTab) ){ - pPk = 0; - r2 = 0; - }else{ - pPk = sqlite3PrimaryKeyIndex(pTab); - r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol); - sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1); - } + + if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ + if( pTab->pCheck==0 + && (pTab->tabFlags & TF_HasNotNull)==0 + && (pTab->pIndex==0 || isQuick) + ){ + continue; /* No additional checks needed for this table */ + } + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); + 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 */ } assert( pParse->nMem>=8+j ); assert( sqlite3NoTempsInRange(pParse,1,7+j) ); sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); - - /* Fetch the right-most column from the table. This will cause - ** the entire record header to be parsed and sanity checked. It - ** will also prepopulate the cursor column cache that is used - ** by the OP_IsType code, so it is a required step. - */ - assert( !IsVirtual(pTab) ); - if( HasRowid(pTab) ){ - mxCol = -1; - for(j=0; jnCol; j++){ - if( (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)==0 ) mxCol++; - } - if( mxCol==pTab->iPKey ) mxCol--; - }else{ - /* COLFLAG_VIRTUAL columns are not included in the WITHOUT ROWID - ** PK index column-count, so there is no need to account for them - ** in this case. */ - mxCol = sqlite3PrimaryKeyIndex(pTab)->nColumn-1; - } - if( mxCol>=0 ){ - sqlite3VdbeAddOp3(v, OP_Column, iDataCur, mxCol, 3); - sqlite3VdbeTypeofColumn(v, 3); - } - - if( !isQuick ){ - if( pPk ){ - /* Verify WITHOUT ROWID keys are in ascending order */ - int a1; - char *zErr; - a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol); - VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v); - zErr = sqlite3MPrintf(db, - "row not in PRIMARY KEY order for %s", - pTab->zName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, a1); - sqlite3VdbeJumpHere(v, a1+1); - for(j=0; jnKeyCol; j++){ - sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j); - } - } - } - /* Verify datatypes for all columns: - ** - ** (1) NOT NULL columns may not contain a NULL - ** (2) Datatype must be exact for non-ANY columns in STRICT tables - ** (3) Datatype for TEXT columns in non-STRICT tables must be - ** NULL, TEXT, or BLOB. - ** (4) Datatype for numeric columns in non-STRICT tables must not - ** be a TEXT value that can be losslessly converted to numeric. - */ - bStrict = (pTab->tabFlags & TF_Strict)!=0; - for(j=0; jnCol; j++){ - char *zErr; - Column *pCol = pTab->aCol + j; /* The column to be checked */ - int labelError; /* Jump here to report an error */ - int labelOk; /* Jump here if all looks ok */ - int p1, p3, p4; /* Operands to the OP_IsType opcode */ - int doTypeCheck; /* Check datatypes (besides NOT NULL) */ - - if( j==pTab->iPKey ) continue; - if( bStrict ){ - doTypeCheck = pCol->eCType>COLTYPE_ANY; - }else{ - doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB; - } - if( pCol->notNull==0 && !doTypeCheck ) continue; - - /* Compute the operands that will be needed for OP_IsType */ - p4 = SQLITE_NULL; - if( pCol->colFlags & COLFLAG_VIRTUAL ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); - p1 = -1; - p3 = 3; - }else{ - if( pCol->iDflt ){ - sqlite3_value *pDfltValue = 0; - sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db), - pCol->affinity, &pDfltValue); - if( pDfltValue ){ - p4 = sqlite3_value_type(pDfltValue); - sqlite3ValueFree(pDfltValue); - } - } - p1 = iDataCur; - if( !HasRowid(pTab) ){ - testcase( j!=sqlite3TableColumnToStorage(pTab, j) ); - p3 = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), j); - }else{ - p3 = sqlite3TableColumnToStorage(pTab,j); - testcase( p3!=j); - } - } - - labelError = sqlite3VdbeMakeLabel(pParse); - labelOk = sqlite3VdbeMakeLabel(pParse); - if( pCol->notNull ){ - /* (1) NOT NULL columns may not contain a NULL */ - int jmp3; - int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - VdbeCoverage(v); - if( p1<0 ){ - sqlite3VdbeChangeP5(v, 0x0f); /* INT, REAL, TEXT, or BLOB */ - jmp3 = jmp2; - }else{ - sqlite3VdbeChangeP5(v, 0x0d); /* INT, TEXT, or BLOB */ - /* OP_IsType does not detect NaN values in the database file - ** which should be treated as a NULL. So if the header type - ** is REAL, we have to load the actual data using OP_Column - ** to reliably determine if the value is a NULL. */ - sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3); - sqlite3ColumnDefault(v, pTab, j, 3); - jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk); - VdbeCoverage(v); - } - zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, - pCol->zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - if( doTypeCheck ){ - sqlite3VdbeGoto(v, labelError); - sqlite3VdbeJumpHere(v, jmp2); - sqlite3VdbeJumpHere(v, jmp3); - }else{ - /* VDBE byte code will fall thru */ - } - } - if( bStrict && doTypeCheck ){ - /* (2) Datatype must be exact for non-ANY columns in STRICT tables*/ - static unsigned char aStdTypeMask[] = { - 0x1f, /* ANY */ - 0x18, /* BLOB */ - 0x11, /* INT */ - 0x11, /* INTEGER */ - 0x13, /* REAL */ - 0x14 /* TEXT */ - }; - sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) ); - sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]); - VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "non-%s value in %s.%s", - sqlite3StdType[pCol->eCType-1], - pTab->zName, pTab->aCol[j].zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - }else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){ - /* (3) Datatype for TEXT columns in non-STRICT tables must be - ** NULL, TEXT, or BLOB. */ - sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */ - VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s", - pTab->zName, pTab->aCol[j].zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - }else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){ - /* (4) Datatype for numeric columns in non-STRICT tables must not - ** be a TEXT value that can be converted to numeric. */ - sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); - sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */ - VdbeCoverage(v); - if( p1>=0 ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); - } - sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC); - sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4); - sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */ - VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "TEXT value in %s.%s", - pTab->zName, pTab->aCol[j].zCnName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - } - sqlite3VdbeResolveLabel(v, labelError); - integrityCheckResultRow(v); - sqlite3VdbeResolveLabel(v, labelOk); + /* Verify that all NOT NULL columns really are NOT NULL */ + for(j=0; jnCol; j++){ + char *zErr; + 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); + zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, + pTab->aCol[j].zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); + integrityCheckResultRow(v, 3); + sqlite3VdbeJumpHere(v, jmp2); } /* 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(pParse); - int addrCkOk = sqlite3VdbeMakeLabel(pParse); + int addrCkFault = sqlite3VdbeMakeLabel(v); + int addrCkOk = sqlite3VdbeMakeLabel(v); char *zErr; int k; - pParse->iSelfTab = iDataCur + 1; + pParse->iSelfTab = iDataCur; + sqlite3ExprCachePush(pParse); for(k=pCheck->nExpr-1; k>0; k--){ sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); } - sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, + 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); + integrityCheckResultRow(v, 3); sqlite3VdbeResolveLabel(v, addrCkOk); + sqlite3ExprCachePop(pParse); } sqlite3ExprListDelete(db, pCheck); } - if( !isQuick ){ /* Omit the remaining tests for quick_check */ - /* Validate index entries for the current row */ - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - int jmp2, jmp3, jmp4, jmp5, label6; - int kk; - int ckUniq = sqlite3VdbeMakeLabel(pParse); - 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); - - /* The OP_IdxRowid opcode is an optimized version of OP_Column - ** that extracts the rowid off the end of the index record. - ** But it only works correctly if index record does not have - ** any extra bytes at the end. Verify that this is the case. */ - if( HasRowid(pTab) ){ - int jmp7; - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur+j, 3); - jmp7 = sqlite3VdbeAddOp3(v, OP_Eq, 3, 0, r1+pIdx->nColumn-1); - VdbeCoverageNeverNull(v); - sqlite3VdbeLoadString(v, 3, - "rowid not at end-of-record for row "); - sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " of index "); - sqlite3VdbeGoto(v, jmp5-1); - sqlite3VdbeJumpHere(v, jmp7); - } - - /* Any indexed columns with non-BINARY collations must still hold - ** the exact same text value as the table. */ - label6 = 0; - for(kk=0; kknKeyCol; kk++){ - if( pIdx->azColl[kk]==sqlite3StrBINARY ) continue; - if( label6==0 ) label6 = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur+j, kk, 3); - sqlite3VdbeAddOp3(v, OP_Ne, 3, label6, r1+kk); VdbeCoverage(v); - } - if( label6 ){ - int jmp6 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeResolveLabel(v, label6); - sqlite3VdbeLoadString(v, 3, "row "); - sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " values differ from index "); - sqlite3VdbeGoto(v, jmp5-1); - sqlite3VdbeJumpHere(v, jmp6); - } - - /* 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(pParse); - int jmp6; - 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); - } + /* Validate index entries for the current row */ + for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; 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, 3); + 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); } sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); - if( pPk ){ - assert( !isQuick ); - sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol); - } - } - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Second pass to invoke the xIntegrity method on all virtual - ** tables. - */ - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - sqlite3_vtab *pVTab; - int a1; - if( pObjTab && pObjTab!=pTab ) continue; - if( IsOrdinaryTable(pTab) ) continue; - if( !IsVirtual(pTab) ) continue; - if( pTab->nCol<=0 ){ - const char *zMod = pTab->u.vtab.azArg[0]; - if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; - } - sqlite3ViewGetColumnNames(pParse, pTab); - if( pTab->u.vtab.p==0 ) continue; - pVTab = pTab->u.vtab.p->pVtab; - if( NEVER(pVTab==0) ) continue; - if( NEVER(pVTab->pModule==0) ) continue; - if( pVTab->pModule->iVersion<4 ) continue; - if( pVTab->pModule->xIntegrity==0 ) continue; - sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick); - pTab->nTabRef++; - sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF); - a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); - integrityCheckResultRow(v); - sqlite3VdbeJumpHere(v, a1); - continue; - } -#endif +#ifndef SQLITE_OMIT_BTREECOUNT + 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, 3, pIdx->zName); + sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); + integrityCheckResultRow(v, 7); + sqlite3VdbeJumpHere(v, addr); + } + } +#endif /* SQLITE_OMIT_BTREECOUNT */ + } } { static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ { 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 = 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; #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ @@ -141865,11 +115642,11 @@ ** The second form of this pragma is a no-op if the main database file ** has not already been initialized. In this case it sets the default ** encoding that will be used for the main database file if a new file ** is created. If an existing main database file is opened, then the ** default text encoding for the existing database is used. - ** + ** ** In all cases new databases created using the ATTACH command are ** created to use the same default text encoding as the main database. If ** the main database has not been initialized and/or created when ATTACH ** is executed, this is done before the ATTACH operation. ** @@ -141903,16 +115680,18 @@ /* Only change the value of sqlite.enc if the database handle is not ** initialized. If the main database exists, the new sqlite.enc value ** will be overwritten when the schema is next loaded. If it does not ** already exists, it will be created to use the new encoding value. */ - if( (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){ + if( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - u8 enc = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; - SCHEMA_ENC(db) = enc; - sqlite3SetTextEncoding(db, enc); + SCHEMA_ENC(db) = ENC(db) = + pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; break; } } if( !pEnc->zName ){ sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); @@ -141971,16 +115750,10 @@ if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; aOp[0].p1 = iDb; aOp[1].p1 = iDb; aOp[1].p2 = iCookie; aOp[1].p3 = sqlite3Atoi(zRight); - aOp[1].p5 = 1; - if( iCookie==BTREE_SCHEMA_VERSION && (db->flags & SQLITE_Defensive)!=0 ){ - /* Do not allow the use of PRAGMA schema_version=VALUE in defensive - ** mode. Change the OP_SetCookie opcode into a no-op. */ - aOp[1].opcode = OP_Noop; - } }else{ /* Read the specified cookie value */ static const VdbeOpList readCookie[] = { { OP_Transaction, 0, 0, 0}, /* 0 */ { OP_ReadCookie, 0, 1, 0}, /* 1 */ @@ -142024,11 +115797,11 @@ ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate ** ** Checkpoint the database. */ case PragTyp_WAL_CHECKPOINT: { - int iBt = (pId2->z?iDb:SQLITE_MAX_DB); + int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); int eMode = SQLITE_CHECKPOINT_PASSIVE; if( zRight ){ if( sqlite3StrICmp(zRight, "full")==0 ){ eMode = SQLITE_CHECKPOINT_FULL; }else if( sqlite3StrICmp(zRight, "restart")==0 ){ @@ -142053,12 +115826,12 @@ */ case PragTyp_WAL_AUTOCHECKPOINT: { if( zRight ){ sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, - db->xWalCallback==sqlite3WalDefaultHook ? + returnSingleInt(v, + db->xWalCallback==sqlite3WalDefaultHook ? SQLITE_PTR_TO_INT(db->pWalArg) : 0); } break; #endif @@ -142087,190 +115860,104 @@ ** 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: ** - ** 0x00001 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. - ** - ** 0x00002 Run ANALYZE on tables that might benefit. On by default. - ** See below for additional information. - ** - ** 0x00010 Run all ANALYZE operations using an analysis_limit that - ** is the lessor of the current analysis_limit and the - ** SQLITE_DEFAULT_OPTIMIZE_LIMIT compile-time option. - ** The default value of SQLITE_DEFAULT_OPTIMIZE_LIMIT is - ** currently (2024-02-19) set to 2000, which is such that - ** the worst case run-time for PRAGMA optimize on a 100MB - ** database will usually be less than 100 milliseconds on - ** a RaspberryPI-4 class machine. On by default. - ** - ** 0x10000 Look at tables to see if they need to be reanalyzed - ** due to growth or shrinkage even if they have not been - ** queried during the current connection. Off by default. - ** - ** The default MASK is and always shall be 0x0fffe. In the current - ** implementation, the default mask only covers the 0x00002 optimization, - ** though additional optimizations that are covered by 0x0fffe might be - ** added in the future. Optimizations that are off by default and must - ** be explicitly requested have masks of 0x10000 or greater. + ** 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 0x00002 is set. - ** - ** (2) The table is an ordinary table, not a virtual table or view. - ** - ** (3) The table name does not begin with "sqlite_". - ** - ** (4) One or more of the following is true: - ** (4a) The 0x10000 MASK bit is set. - ** (4b) One or more indexes on the table lacks an entry - ** in the sqlite_stat1 table. - ** (4c) 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. - ** - ** (5) One or more of the following is true: - ** (5a) One or more indexes on the table lacks an entry - ** in the sqlite_stat1 table. (Same as 4a) - ** (5b) The number of rows in the table has increased or decreased by - ** 10-fold. In other words, the current size of the table is - ** 10 times larger than the size in sqlite_stat1 or else the - ** current size is less than 1/10th the size in sqlite_stat1. + ** (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. Future versions of SQLite might accept a string - ** literal argument to this pragma that contains a mnemonic description - ** of the options rather than a bitmap. + ** 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 needed */ + 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 */ - int nLimit; /* Analysis limit to use */ - int nCheck = 0; /* Number of tables to be optimized */ - int nBtree = 0; /* Number of btrees to scan */ - int nIndex; /* Number of indexes on the current table */ if( zRight ){ opMask = (u32)sqlite3Atoi(zRight); if( (opMask & 0x02)==0 ) break; }else{ opMask = 0xfffe; } - if( (opMask & 0x10)==0 ){ - nLimit = 0; - }else if( db->nAnalysisLimit>0 - && db->nAnalysisLimitnTab++; 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); - /* This only works for ordinary tables */ - if( !IsOrdinaryTable(pTab) ) continue; - - /* Do not scan system tables */ - if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue; - - /* Find the size of the table as last recorded in sqlite_stat1. - ** If any index is unanalyzed, then the threshold is -1 to - ** indicate a new, unanalyzed index - */ - szThreshold = pTab->nRowLogEst; - nIndex = 0; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - nIndex++; + /* 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 = -1; /* Always analyze if any index lacks statistics */ - } - } - - /* If table pTab has not been used in a way that would benefit from - ** having analysis statistics during the current session, then skip it, - ** unless the 0x10000 MASK bit is set. */ - if( (pTab->tabFlags & TF_MaybeReanalyze)!=0 ){ - /* Check for size change if stat1 has been used for a query */ - }else if( opMask & 0x10000 ){ - /* Check for size change if 0x10000 is set */ - }else if( pTab->pIndex!=0 && szThreshold<0 ){ - /* Do analysis if unanalyzed indexes exists */ - }else{ - /* Otherwise, we can skip this table */ - continue; - } - - nCheck++; - if( nCheck==2 ){ - /* If ANALYZE might be invoked two or more times, hold a write - ** transaction for efficiency */ - sqlite3BeginWriteOperation(pParse, 0, iDb); - } - nBtree += nIndex+1; - - /* Reanalyze if the table is 10 times larger or smaller than - ** the last analysis. Unconditional reanalysis if there are - ** unanalyzed indexes. */ - sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - if( szThreshold>=0 ){ - const LogEst iRange = 33; /* 10x size change */ - sqlite3VdbeAddOp4Int(v, OP_IfSizeBetween, iTabCur, - sqlite3VdbeCurrentAddr(v)+2+(opMask&1), - szThreshold>=iRange ? szThreshold-iRange : -1, - szThreshold+iRange); - VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Rewind, iTabCur, - sqlite3VdbeCurrentAddr(v)+2+(opMask&1)); + 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, nLimit ? 0x02 : 00, nLimit, 0, - zSubSql, P4_DYNAMIC); + sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC); } } } sqlite3VdbeAddOp0(v, OP_Expire); - - /* In a schema with a large number of tables and indexes, scale back - ** the analysis_limit to avoid excess run-time in the worst case. - */ - if( !db->mallocFailed && nLimit>0 && nBtree>100 ){ - int iAddr, iEnd; - VdbeOp *aOp; - nLimit = 100*nLimit/nBtree; - if( nLimit<100 ) nLimit = 100; - aOp = sqlite3VdbeGetOp(v, 0); - iEnd = sqlite3VdbeCurrentAddr(v); - for(iAddr=0; iAddr0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N); - } - returnSingleInt(v, sqlite3_hard_heap_limit64(-1)); - break; - } - /* ** PRAGMA threads ** PRAGMA threads = N ** ** Configure the maximum number of worker threads. Return the new @@ -142348,29 +116014,10 @@ } returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); break; } - /* - ** PRAGMA analysis_limit - ** PRAGMA analysis_limit = N - ** - ** Configure the maximum number of rows that ANALYZE will examine - ** in each index that it looks at. Return the new limit. - */ - case PragTyp_ANALYSIS_LIMIT: { - sqlite3_int64 N; - if( zRight - && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */ - && N>=0 - ){ - db->nAnalysisLimit = (int)(N&0x7fffffff); - } - returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */ - break; - } - #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Report the current state of file logs for all databases */ case PragTyp_LOCK_STATUS: { @@ -142385,35 +116032,69 @@ int j; if( db->aDb[i].zDbSName==0 ) continue; pBt = db->aDb[i].pBt; if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ zState = "closed"; - }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, + }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ zState = azLockName[j]; } sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); } break; } #endif -#if defined(SQLITE_ENABLE_CEROD) +#ifdef SQLITE_HAS_CODEC + case PragTyp_KEY: { + if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); + break; + } + case PragTyp_REKEY: { + if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); + break; + } + case PragTyp_HEXKEY: { + if( zRight ){ + u8 iByte; + int i; + char zKey[40]; + for(i=0, iByte=0; imPragFlg & PragFlg_NoColumns1) && zRight ){ sqlite3VdbeVerifyNoResultRow(v); } @@ -142440,11 +116121,11 @@ 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, @@ -142461,29 +116142,30 @@ char zBuf[200]; UNUSED_PARAMETER(argc); UNUSED_PARAMETER(argv); sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3_str_appendall(&acc, "CREATE TABLE x"); + sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){ - sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]); + sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); cSep = ','; } if( i==0 ){ - sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName); + sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); + cSep = ','; i++; } j = 0; if( pPragma->mPragFlg & PragFlg_Result1 ){ - sqlite3_str_appendall(&acc, ",arg HIDDEN"); + sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); j++; } if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ - sqlite3_str_appendall(&acc, ",schema HIDDEN"); + sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); j++; } - sqlite3_str_append(&acc, ")", 1); + 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)); @@ -142502,11 +116184,11 @@ *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); @@ -142530,13 +116212,13 @@ if( pTab->nHidden==0 ){ return SQLITE_OK; } pConstraint = pIdxInfo->aConstraint; seen[0] = 0; seen[1] = 0; for(i=0; inConstraint; i++, pConstraint++){ - if( pConstraint->iColumn < pTab->iHidden ) continue; + if( pConstraint->usable==0 ) continue; if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT; + if( pConstraint->iColumn < pTab->iHidden ) continue; j = pConstraint->iColumn - pTab->iHidden; assert( j < 2 ); seen[j] = i+1; } if( seen[0]==0 ){ @@ -142545,17 +116227,16 @@ 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; - if( seen[1] ){ - j = seen[1]-1; - pIdxInfo->aConstraintUsage[j].argvIndex = 2; - pIdxInfo->aConstraintUsage[j].omit = 1; - } + 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){ @@ -142571,11 +116252,10 @@ /* Clear all content from pragma virtual table cursor. */ static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ int i; sqlite3_finalize(pCsr->pPragma); pCsr->pPragma = 0; - pCsr->iRowid = 0; for(i=0; iazArg); i++){ sqlite3_free(pCsr->azArg[i]); pCsr->azArg[i] = 0; } } @@ -142602,15 +116282,15 @@ pragmaVtabCursorClear(pCsr); } return rc; } -/* +/* ** Pragma virtual table module xFilter method. */ static int pragmaVtabFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); @@ -142622,28 +116302,24 @@ 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; - } + pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i])); + if( pCsr->azArg[j]==0 ){ + return SQLITE_NOMEM; } } sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); - sqlite3_str_appendall(&acc, "PRAGMA "); + sqlite3StrAccumAppendAll(&acc, "PRAGMA "); if( pCsr->azArg[1] ){ - sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]); + sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); } - sqlite3_str_appendall(&acc, pTab->pName->zName); + sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); if( pCsr->azArg[0] ){ - sqlite3_str_appendf(&acc, "=%Q", 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); @@ -142661,15 +116337,15 @@ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; return (pCsr->pPragma==0); } /* The xColumn method simply returns the corresponding column from -** the PRAGMA. +** the PRAGMA. */ static int pragmaVtabColumn( - sqlite3_vtab_cursor *pVtabCursor, - sqlite3_context *ctx, + sqlite3_vtab_cursor *pVtabCursor, + sqlite3_context *ctx, int i ){ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); if( iiHidden ){ @@ -142678,11 +116354,11 @@ 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; @@ -142711,13 +116387,11 @@ 0, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ + 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 @@ -142760,171 +116434,108 @@ ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ - char **azObj, /* Type and name of object being parsed */ + const char *zObj, /* Object being parsed at the point of error */ const char *zExtra /* Error information */ ){ sqlite3 *db = pData->db; - if( db->mallocFailed ){ - pData->rc = SQLITE_NOMEM_BKPT; - }else if( pData->pzErrMsg[0]!=0 ){ - /* A error message has already been generated. Do not overwrite it */ - }else if( pData->mInitFlags & (INITFLAG_AlterMask) ){ - static const char *azAlterType[] = { - "rename", - "drop column", - "add column" - }; - *pData->pzErrMsg = sqlite3MPrintf(db, - "error in %s %s after %s: %s", azObj[0], azObj[1], - azAlterType[(pData->mInitFlags&INITFLAG_AlterMask)-1], - zExtra - ); - pData->rc = SQLITE_ERROR; - }else if( db->flags & SQLITE_WriteSchema ){ - pData->rc = SQLITE_CORRUPT_BKPT; - }else{ + if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){ char *z; - const char *zObj = azObj[1] ? azObj[1] : "?"; + if( zObj==0 ) zObj = "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); - if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); + if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); + sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; - pData->rc = SQLITE_CORRUPT_BKPT; - } -} - -/* -** Check to see if any sibling index (another index on the same table) -** of pIndex has the same root page number, and if it does, return true. -** This would indicate a corrupt schema. -*/ -SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index *pIndex){ - Index *p; - for(p=pIndex->pTable->pIndex; p; p=p->pNext){ - if( p->tnum==pIndex->tnum && p!=pIndex ) return 1; - } - return 0; -} - -/* forward declaration */ -static int sqlite3Prepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - 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 */ -); - + } + pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; +} /* ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. ** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** ** Each callback contains the following information: ** -** argv[0] = type of object: "table", "index", "trigger", or "view". -** argv[1] = name of thing being created -** argv[2] = associated table if an index or trigger -** argv[3] = root page number for table or index. 0 for trigger or view. -** argv[4] = SQL text for the CREATE statement. +** argv[0] = name of thing being created +** argv[1] = root page number for table or index. 0 for trigger or view. +** argv[2] = SQL text for the CREATE statement. ** */ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ InitData *pData = (InitData*)pInit; sqlite3 *db = pData->db; int iDb = pData->iDb; - assert( argc==5 ); + assert( argc==3 ); UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); - db->mDbFlags |= DBFLAG_EncodingFixed; - if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - pData->nInitRow++; + DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ - corruptSchema(pData, argv, 0); + corruptSchema(pData, argv[0], 0); return 1; } assert( iDb>=0 && iDbnDb ); - if( argv[3]==0 ){ - corruptSchema(pData, argv, 0); - }else if( argv[4] - && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]] - && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){ + if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ + if( argv[1]==0 ){ + corruptSchema(pData, argv[0], 0); + }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data ** structures that describe the table, index, or view. - ** - ** No other valid SQL statement, other than the variable CREATE statements, - ** can begin with the letters "C" and "R". Thus, it is not possible run - ** any other kind of statement while parsing the schema, even a corrupt - ** schema. */ int rc; u8 saved_iDb = db->init.iDb; sqlite3_stmt *pStmt; TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ assert( db->init.busy ); db->init.iDb = iDb; - if( sqlite3GetUInt32(argv[3], &db->init.newTnum)==0 - || (db->init.newTnum>pData->mxPage && pData->mxPage>0) - ){ - if( sqlite3Config.bExtraSchemaChecks ){ - corruptSchema(pData, argv, "invalid rootpage"); - } - } + db->init.newTnum = sqlite3Atoi(argv[1]); db->init.orphanTrigger = 0; - db->init.azInit = (const char**)argv; - pStmt = 0; - TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0); + TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = saved_iDb; - /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */ + assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); }else{ - if( rc > pData->rc ) pData->rc = rc; + pData->rc = rc; if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ - corruptSchema(pData, argv, sqlite3_errmsg(db)); + corruptSchema(pData, argv[0], sqlite3_errmsg(db)); } } } - db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */ sqlite3_finalize(pStmt); - }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){ - corruptSchema(pData, argv, 0); + }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){ + corruptSchema(pData, argv[0], 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName); + pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName); if( pIndex==0 ){ - corruptSchema(pData, argv, "orphan index"); - }else - if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0 - || pIndex->tnum<2 - || pIndex->tnum>pData->mxPage - || sqlite3IndexHasDuplicateRootPage(pIndex) - ){ - if( sqlite3Config.bExtraSchemaChecks ){ - corruptSchema(pData, argv, "invalid rootpage"); - } + /* This can occur if there exists an index on a TEMP table which + ** has the same name as another index on a permanent index. Since + ** the permanent table is hidden by the TEMP table, we can also + ** safely ignore the index on the permanent table. + */ + /* Do Nothing */; + }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){ + corruptSchema(pData, argv[0], "invalid rootpage"); } } return 0; } @@ -142934,74 +116545,64 @@ ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ -SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ +static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; int i; #ifndef SQLITE_OMIT_DEPRECATED int size; #endif Db *pDb; - char const *azArg[6]; + char const *azArg[4]; int meta[5]; InitData initData; - const char *zSchemaTabName; + const char *zMasterName; int openedTransaction = 0; - int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed); - assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pSchema ); 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_schema or - ** sqlite_temp_schema) by invoking the parser directly. The appropriate + /* 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 ** use the abbreviation "x" here. The parser will also automatically tag ** the schema table as read-only. */ - azArg[0] = "table"; - azArg[1] = zSchemaTabName = SCHEMA_TABLE(iDb); - azArg[2] = azArg[1]; - azArg[3] = "1"; - azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text," - "rootpage int,sql text)"; - azArg[5] = 0; + 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)"; + azArg[3] = 0; initData.db = db; initData.iDb = iDb; initData.rc = SQLITE_OK; initData.pzErrMsg = pzErrMsg; - initData.mInitFlags = mFlags; - initData.nInitRow = 0; - initData.mxPage = 0; - sqlite3InitCallback(&initData, 5, (char **)azArg, 0); - db->mDbFlags &= mask; + sqlite3InitCallback(&initData, 3, (char **)azArg, 0); if( initData.rc ){ rc = initData.rc; goto error_out; } /* Create a cursor to hold the database open */ pDb = &db->aDb[iDb]; if( pDb->pBt==0 ){ - assert( iDb==1 ); - DbSetProperty(db, 1, DB_SchemaLoaded); - rc = SQLITE_OK; - goto error_out; + if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ + DbSetProperty(db, 1, DB_SchemaLoaded); + } + return SQLITE_OK; } /* If there is not already a read-only (or read-write) transaction opened - ** on the b-tree database, open one now. If a transaction is opened, it + ** on the b-tree database, open one now. If a transaction is opened, it ** will be closed before this function returns. */ sqlite3BtreeEnter(pDb->pBt); - if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){ - rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0); + if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ + rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); if( rc!=SQLITE_OK ){ sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); goto initone_error_out; } openedTransaction = 1; @@ -143025,40 +116626,39 @@ ** the possible values of meta[4]. */ for(i=0; ipBt, i+1, (u32 *)&meta[i]); } - if( (db->flags & SQLITE_ResetDatabase)!=0 ){ - memset(meta, 0, sizeof(meta)); - } pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. */ if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ - if( iDb==0 && (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){ - u8 encoding; + if( iDb==0 ){ #ifndef SQLITE_OMIT_UTF16 + u8 encoding; /* If opening the main database, set ENC(db). */ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; if( encoding==0 ) encoding = SQLITE_UTF8; + ENC(db) = encoding; #else - encoding = SQLITE_UTF8; + ENC(db) = SQLITE_UTF8; #endif - sqlite3SetTextEncoding(db, encoding); }else{ /* If opening an attached database, the encoding much match ENC(db) */ - if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){ + if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){ sqlite3SetString(pzErrMsg, db, "attached databases must use the same" " text encoding as main database"); rc = SQLITE_ERROR; goto initone_error_out; } } + }else{ + DbSetProperty(db, iDb, DB_Empty); } pDb->pSchema->enc = ENC(db); if( pDb->pSchema->cache_size==0 ){ #ifndef SQLITE_OMIT_DEPRECATED @@ -143091,22 +116691,21 @@ ** clear the legacy_file_format pragma flag so that a VACUUM will ** not downgrade the database and thus invalidate any descending ** indices that the user might have created. */ if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){ - db->flags &= ~(u64)SQLITE_LegacyFileFmt; + db->flags &= ~SQLITE_LegacyFileFmt; } /* Read the schema information out of the schema tables */ assert( db->init.busy ); - initData.mxPage = sqlite3BtreeLastPage(pDb->pBt); { char *zSql; - zSql = sqlite3MPrintf(db, - "SELECT*FROM\"%w\".%s ORDER BY rowid", - db->aDb[iDb].zDbSName, zSchemaTabName); + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid", + db->aDb[iDb].zDbSName, zMasterName); #ifndef SQLITE_OMIT_AUTHORIZATION { sqlite3_xauth xAuth; xAuth = db->xAuth; db->xAuth = 0; @@ -143122,26 +116721,22 @@ if( rc==SQLITE_OK ){ sqlite3AnalysisLoad(db, iDb); } #endif } - assert( pDb == &(db->aDb[iDb]) ); if( db->mallocFailed ){ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); - pDb = &db->aDb[iDb]; - }else - if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){ - /* Hack: If the SQLITE_NoSchemaError flag is set, then consider - ** the schema loaded, even if errors (other than OOM) occurred. In - ** this situation the current sqlite3_prepare() operation will fail, - ** but the following one will attempt to compile the supplied statement - ** against whatever subset of the schema was loaded before the error - ** occurred. - ** - ** The primary purpose of this is to allow access to the sqlite_schema - ** table even when its contents have been corrupted. + } + 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 + ** of the schema was loaded before the error occurred. The primary + ** purpose of this is to allow access to the sqlite_master table + ** even when its contents have been corrupted. */ DbSetProperty(db, iDb, DB_SchemaLoaded); rc = SQLITE_OK; } @@ -143154,17 +116749,13 @@ sqlite3BtreeCommit(pDb->pBt); } sqlite3BtreeLeave(pDb->pBt); error_out: - if( rc ){ - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - } - sqlite3ResetOneSchema(db, iDb); + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); } - db->init.busy = 0; return rc; } /* ** Initialize all database files - the main database file, the file @@ -143171,38 +116762,51 @@ ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** ** After a database is initialized, the DB_SchemaLoaded bit is set -** bit is set in the flags field of the Db structure. +** bit is set in the flags field of the Db structure. If the database +** file was of zero-length, then the DB_Empty flag is also set. */ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; - int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange); - + int commit_internal = !(db->flags&SQLITE_InternChanges); + 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); - assert( db->nDb>0 ); - /* Do the main schema first */ - if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, 0, pzErrMsg, 0); - if( rc ) return rc; - } - /* All other schemas after the main schema. The "temp" schema must be last */ - for(i=db->nDb-1; i>0; i--){ - assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) ); - if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, i, pzErrMsg, 0); - if( rc ) return rc; - } - } - if( commit_internal ){ + 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); + } + } + + /* 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); + } + } +#endif + + db->init.busy = 0; + if( rc==SQLITE_OK && commit_internal ){ sqlite3CommitInternalChanges(db); } - return SQLITE_OK; + + return rc; } /* ** This routine is a no-op if the database schema is already initialized. ** Otherwise, the schema is loaded. An error code is returned. @@ -143211,16 +116815,14 @@ int rc = SQLITE_OK; sqlite3 *db = pParse->db; assert( sqlite3_mutex_held(db->mutex) ); if( !db->init.busy ){ rc = sqlite3Init(db, &pParse->zErrMsg); - if( rc!=SQLITE_OK ){ - pParse->rc = rc; - pParse->nErr++; - }else if( db->noSharedCache ){ - db->mDbFlags |= DBFLAG_SchemaKnownOk; - } + } + if( rc!=SQLITE_OK ){ + pParse->rc = rc; + pParse->nErr++; } return rc; } @@ -143241,30 +116843,29 @@ int openedTransaction = 0; /* True if a transaction is opened */ Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */ if( pBt==0 ) continue; /* If there is not already a read-only (or read-write) transaction opened - ** on the b-tree database, open one now. If a transaction is opened, it + ** on the b-tree database, open one now. If a transaction is opened, it ** will be closed immediately after reading the meta-value. */ - if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){ - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( !sqlite3BtreeIsInReadTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ sqlite3OomFault(db); - pParse->rc = SQLITE_NOMEM; } if( rc!=SQLITE_OK ) return; openedTransaction = 1; } - /* Read the schema cookie from the database. If it does not match the + /* Read the schema cookie from the database. If it does not match the ** value stored as part of the in-memory schema representation, ** set Parse.rc to SQLITE_SCHEMA. */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - if( DbHasProperty(db, iDb, DB_SchemaLoaded) ) pParse->rc = SQLITE_SCHEMA; sqlite3ResetOneSchema(db, iDb); + pParse->rc = SQLITE_SCHEMA; } /* Close the transaction, if one was opened. */ if( openedTransaction ){ sqlite3BtreeCommit(pBt); @@ -143278,27 +116879,25 @@ ** ** If the same database is attached more than once, the first ** attached database is returned. */ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ - int i = -32768; + int i = -1000000; - /* If pSchema is NULL, then return -32768. This happens when code in + /* If pSchema is NULL, then return -1000000. This happens when code in ** expr.c is trying to resolve a reference to a transient table (i.e. one - ** created by a sub-select). In this case the return value of this + ** created by a sub-select). In this case the return value of this ** function should never be used. ** - ** We return -32768 instead of the more usual -1 simply because using - ** -32768 as the incorrect index into db->aDb[] is much + ** We return -1000000 instead of the more usual -1 simply because using + ** -1000000 as the incorrect index into db->aDb[] is much ** more likely to cause a segfault than -1 (of course there are assert() - ** statements too, but it never hurts to play the odds) and - ** -32768 will still fit into a 16-bit signed integer. + ** statements too, but it never hurts to play the odds). */ assert( sqlite3_mutex_held(db->mutex) ); if( pSchema ){ - for(i=0; 1; i++){ - assert( inDb ); + for(i=0; ALWAYS(inDb); i++){ if( db->aDb[i].pSchema==pSchema ){ break; } } assert( i>=0 && inDb ); @@ -143307,116 +116906,22 @@ } /* ** Free all memory allocations in the pParse object */ -SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ - sqlite3 *db = pParse->db; - assert( db!=0 ); - assert( db->pParse==pParse ); - assert( pParse->nested==0 ); -#ifndef SQLITE_OMIT_SHARED_CACHE - if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock); -#endif - while( pParse->pCleanup ){ - ParseCleanup *pCleanup = pParse->pCleanup; - pParse->pCleanup = pCleanup->pNext; - pCleanup->xCleanup(db, pCleanup->pPtr); - sqlite3DbNNFreeNN(db, pCleanup); - } - if( pParse->aLabel ) sqlite3DbNNFreeNN(db, pParse->aLabel); - if( pParse->pConstExpr ){ +SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ + if( pParse ){ + sqlite3 *db = pParse->db; + sqlite3DbFree(db, pParse->aLabel); sqlite3ExprListDelete(db, pParse->pConstExpr); - } - assert( db->lookaside.bDisable >= pParse->disableLookaside ); - db->lookaside.bDisable -= pParse->disableLookaside; - db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; - assert( pParse->db->pParse==pParse ); - db->pParse = pParse->pOuterParse; -} - -/* -** Add a new cleanup operation to a Parser. The cleanup should happen when -** the parser object is destroyed. But, beware: the cleanup might happen -** immediately. -** -** Use this mechanism for uncommon cleanups. There is a higher setup -** cost for this mechanism (an extra malloc), so it should not be used -** for common cleanups that happen on most calls. But for less -** common cleanups, we save a single NULL-pointer comparison in -** sqlite3ParseObjectReset(), which reduces the total CPU cycle count. -** -** If a memory allocation error occurs, then the cleanup happens immediately. -** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the -** pParse->earlyCleanup flag is set in that case. Calling code show verify -** that test cases exist for which this happens, to guard against possible -** use-after-free errors following an OOM. The preferred way to do this is -** to immediately follow the call to this routine with: -** -** testcase( pParse->earlyCleanup ); -** -** This routine returns a copy of its pPtr input (the third parameter) -** except if an early cleanup occurs, in which case it returns NULL. So -** another way to check for early cleanup is to check the return value. -** Or, stop using the pPtr parameter with this call and use only its -** return value thereafter. Something like this: -** -** pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj); -*/ -SQLITE_PRIVATE void *sqlite3ParserAddCleanup( - Parse *pParse, /* Destroy when this Parser finishes */ - void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */ - void *pPtr /* Pointer to object to be cleaned up */ -){ - ParseCleanup *pCleanup; - if( sqlite3FaultSim(300) ){ - pCleanup = 0; - sqlite3OomFault(pParse->db); - }else{ - pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup)); - } - if( pCleanup ){ - pCleanup->pNext = pParse->pCleanup; - pParse->pCleanup = pCleanup; - pCleanup->pPtr = pPtr; - pCleanup->xCleanup = xCleanup; - }else{ - xCleanup(pParse->db, pPtr); - pPtr = 0; -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) - pParse->earlyCleanup = 1; -#endif - } - return pPtr; -} - -/* -** Turn bulk memory into a valid Parse object and link that Parse object -** into database connection db. -** -** Call sqlite3ParseObjectReset() to undo this operation. -** -** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which -** is generated by Lemon. -*/ -SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){ - memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ); - memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); - assert( db->pParse!=pParse ); - pParse->pOuterParse = db->pParse; - db->pParse = pParse; - pParse->db = db; - if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory"); -} - -/* -** Maximum number of times that we will try again to prepare a statement -** that returns SQLITE_ERROR_RETRY. -*/ -#ifndef SQLITE_MAX_PREPARE_RETRY -# define SQLITE_MAX_PREPARE_RETRY 25 -#endif + if( db ){ + assert( db->lookaside.bDisable >= pParse->disableLookaside ); + db->lookaside.bDisable -= pParse->disableLookaside; + } + pParse->disableLookaside = 0; + } +} /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare( @@ -143426,42 +116931,29 @@ 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 */ ){ + char *zErrMsg = 0; /* Error message */ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ Parse sParse; /* Parsing context */ - /* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */ - memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ); + memset(&sParse, 0, PARSE_HDR_SZ); memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); - sParse.pOuterParse = db->pParse; - db->pParse = &sParse; - sParse.db = db; - if( pReprepare ){ - sParse.pReprepare = pReprepare; - sParse.explain = sqlite3_stmt_isexplain((sqlite3_stmt*)pReprepare); - }else{ - assert( sParse.pReprepare==0 ); - } + sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); - if( db->mallocFailed ){ - sqlite3ErrorMsg(&sParse, "out of memory"); - db->errCode = rc = SQLITE_NOMEM; - goto end_prepare; - } + /* 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++; - DisableLookaside; + db->lookaside.bDisable++; } - sParse.prepFlags = prepFlags & 0xff; /* 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 ** turn means that the other connection has made uncommitted changes @@ -143474,38 +116966,35 @@ ** the schema change. Disaster would follow. ** ** This thread is currently holding mutexes on all Btrees (because ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it ** is not possible for another thread to start a new schema change - ** while this routine is running. Hence, we do not need to hold - ** locks on the schema, we just need to make sure nobody else is + ** while this routine is running. Hence, we do not need to hold + ** locks on the schema, we just need to make sure nobody else is ** holding them. ** ** Note that setting READ_UNCOMMITTED overrides most lock detection, ** but it does *not* override schema lock detection, so this all still ** works even if READ_UNCOMMITTED is set. */ - if( !db->noSharedCache ){ - for(i=0; inDb; i++) { - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - assert( sqlite3BtreeHoldsMutex(pBt) ); - rc = sqlite3BtreeSchemaLocked(pBt); - if( rc ){ - const char *zDb = db->aDb[i].zDbSName; - sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); - testcase( db->flags & SQLITE_ReadUncommit ); - goto end_prepare; - } + for(i=0; inDb; i++) { + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + assert( sqlite3BtreeHoldsMutex(pBt) ); + rc = sqlite3BtreeSchemaLocked(pBt); + if( rc ){ + const char *zDb = db->aDb[i].zDbSName; + sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); + testcase( db->flags & SQLITE_ReadUncommit ); + goto end_prepare; } } } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( db->pDisconnect ) sqlite3VtabUnlockList(db); -#endif + sqlite3VtabUnlockList(db); + sParse.db = db; if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; testcase( nBytes==mxLen ); testcase( nBytes==mxLen+1 ); @@ -143514,54 +117003,72 @@ rc = sqlite3ApiExit(db, SQLITE_TOOBIG); goto end_prepare; } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(&sParse, zSqlCopy); + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; sqlite3DbFree(db, zSqlCopy); }else{ sParse.zTail = &zSql[nBytes]; } }else{ - sqlite3RunParser(&sParse, zSql); + sqlite3RunParser(&sParse, zSql, &zErrMsg); } assert( 0==sParse.nQueryLoop ); + if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; + if( sParse.checkSchema ){ + schemaIsValid(&sParse); + } + if( db->mallocFailed ){ + sParse.rc = SQLITE_NOMEM_BKPT; + } if( pzTail ){ *pzTail = sParse.zTail; } + rc = sParse.rc; + +#ifndef SQLITE_OMIT_EXPLAIN + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ + static const char * const azColName[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", + "selectid", "order", "from", "detail" + }; + int iFirst, mx; + if( sParse.explain==2 ){ + sqlite3VdbeSetNumCols(sParse.pVdbe, 4); + iFirst = 8; + mx = 12; + }else{ + sqlite3VdbeSetNumCols(sParse.pVdbe, 8); + iFirst = 0; + mx = 8; + } + for(i=iFirst; iinit.busy==0 ){ sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags); } - if( db->mallocFailed ){ - sParse.rc = SQLITE_NOMEM_BKPT; - sParse.checkSchema = 0; - } - if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){ - if( sParse.checkSchema && db->init.busy==0 ){ - schemaIsValid(&sParse); - } - if( sParse.pVdbe ){ - sqlite3VdbeFinalize(sParse.pVdbe); - } - assert( 0==(*ppStmt) ); - rc = sParse.rc; - if( sParse.zErrMsg ){ - sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg); - sqlite3DbFree(db, sParse.zErrMsg); - }else{ - sqlite3Error(db, rc); - } - }else{ - assert( sParse.zErrMsg==0 ); + if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ + sqlite3VdbeFinalize(sParse.pVdbe); + assert(!(*ppStmt)); + }else{ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; - rc = SQLITE_OK; - sqlite3ErrorClear(db); } + if( zErrMsg ){ + sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); + sqlite3DbFree(db, zErrMsg); + }else{ + sqlite3Error(db, rc); + } /* Delete any TriggerPrg structures allocated while parsing this statement. */ while( sParse.pTriggerPrg ){ TriggerPrg *pT = sParse.pTriggerPrg; sParse.pTriggerPrg = pT->pNext; @@ -143568,11 +117075,13 @@ sqlite3DbFree(db, pT); } end_prepare: - sqlite3ParseObjectReset(&sParse); + 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. */ @@ -143581,11 +117090,10 @@ 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; #endif *ppStmt = 0; @@ -143592,35 +117100,27 @@ if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); - 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); + if( rc==SQLITE_SCHEMA ){ + sqlite3_finalize(*ppStmt); rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); - assert( rc==SQLITE_OK || *ppStmt==0 ); - if( rc==SQLITE_OK || db->mallocFailed ) break; - }while( (rc==SQLITE_ERROR_RETRY && (cnt++)errMask)==rc ); - db->busyHandler.nBusy = 0; sqlite3_mutex_leave(db->mutex); - assert( rc==SQLITE_OK || (*ppStmt)==0 ); + assert( rc==SQLITE_OK || *ppStmt==0 ); return rc; } - /* ** Rerun the compilation of a statement after a schema change. ** ** If the statement is successfully recompiled, return SQLITE_OK. Otherwise, ** if the statement cannot be recompiled because another connection has -** locked the sqlite3_schema table, return SQLITE_LOCKED. If any other error +** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error ** occurs, return SQLITE_SCHEMA. */ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ int rc; sqlite3_stmt *pNew; @@ -143717,11 +117217,11 @@ #ifndef SQLITE_OMIT_UTF16 /* ** Compile the UTF-16 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare16( - sqlite3 *db, /* Database handle. */ + sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ 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 */ @@ -143739,28 +117239,16 @@ #endif *ppStmt = 0; if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ return SQLITE_MISUSE_BKPT; } - - /* Make sure nBytes is non-negative and correct. It should be the - ** number of bytes until the end of the input buffer or until the first - ** U+0000 character. If the input nBytes is odd, convert it into - ** an even number. If the input nBytes is negative, then the input - ** must be terminated by at least one U+0000 character */ if( nBytes>=0 ){ int sz; const char *z = (const char*)zSql; for(sz=0; szmutex); zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); if( zSql8 ){ rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8); } @@ -143770,13 +117258,13 @@ ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8)); - *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed); + *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); } - sqlite3DbFree(db, zSql8); + sqlite3DbFree(db, zSql8); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -143787,11 +117275,11 @@ ** sqlite3_step(). In the new version, the original SQL text is retained ** and the statement is automatically recompiled if an schema change ** occurs. */ SQLITE_API int sqlite3_prepare16( - sqlite3 *db, /* Database handle. */ + sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */ ){ @@ -143799,11 +117287,11 @@ rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail); assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } SQLITE_API int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle. */ + sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */ ){ @@ -143811,11 +117299,11 @@ 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. */ + 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 */ @@ -143845,41 +117333,42 @@ ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. */ /* #include "sqliteInt.h" */ + +/* +** Trace output macros +*/ +#if SELECTTRACE_ENABLED +/***/ int sqlite3SelectTrace = 0; +# define SELECTTRACE(K,P,S,X) \ + if(sqlite3SelectTrace&(K)) \ + sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ + (S)->zSelName,(S)),\ + sqlite3DebugPrintf X +#else +# define SELECTTRACE(K,P,S,X) +#endif + /* ** An instance of the following object is used to record information about ** how to process the DISTINCT keyword, to simplify passing that information ** into the selectInnerLoop() routine. */ typedef struct DistinctCtx DistinctCtx; struct DistinctCtx { - u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */ + u8 isTnct; /* True if the DISTINCT keyword is present */ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */ int tabTnct; /* Ephemeral table used for DISTINCT processing */ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ }; /* ** An instance of the following object is used to record information about ** the ORDER BY (or GROUP BY) clause of query is being coded. -** -** The aDefer[] array is used by the sorter-references optimization. For -** example, assuming there is no index that can be used for the ORDER BY, -** for the query: -** -** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10; -** -** it may be more efficient to add just the "a" values to the sorter, and -** retrieve the associated "bigblob" values directly from table t1 as the -** 10 smallest "a" values are extracted from the sorter. -** -** When the sorter-reference optimization is used, there is one entry in the -** aDefer[] array for each database table that may be read as values are -** extracted from the sorter. */ typedef struct SortCtx SortCtx; struct SortCtx { ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */ int nOBSat; /* Number of ORDER BY terms satisfied by indices */ @@ -143886,57 +117375,32 @@ int iECursor; /* Cursor number for the sorter */ int regReturn; /* Register holding block-output return address */ int labelBkOut; /* Start label for the block-output subroutine */ int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ int labelDone; /* Jump here when done, ex: LIMIT reached */ - int labelOBLopt; /* Jump here when sorter is full */ u8 sortFlags; /* Zero or more SORTFLAG_* bits */ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - u8 nDefer; /* Number of valid entries in aDefer[] */ - struct DeferredCsr { - Table *pTab; /* Table definition */ - int iCsr; /* Cursor number for table */ - int nKey; /* Number of PK columns for table pTab (>=1) */ - } aDefer[4]; -#endif - struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrPush; /* First instruction to push data into sorter */ - int addrPushEnd; /* Last instruction that pushes data into sorter */ -#endif + u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ /* ** Delete all the content of a Select structure. Deallocate the structure -** itself depending on the value of bFree -** -** If bFree==1, call sqlite3DbFree() on the p object. -** If bFree==0, Leave the first Select object unfreed +** itself only if bFree is true. */ static void clearSelect(sqlite3 *db, Select *p, int bFree){ - assert( db!=0 ); while( p ){ Select *pPrior = p->pPrior; sqlite3ExprListDelete(db, p->pEList); sqlite3SrcListDelete(db, p->pSrc); sqlite3ExprDelete(db, p->pWhere); sqlite3ExprListDelete(db, p->pGroupBy); sqlite3ExprDelete(db, p->pHaving); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); - if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ - sqlite3WindowListDelete(db, p->pWinDefn); - } - while( p->pWin ){ - assert( p->pWin->ppThis==&p->pWin ); - sqlite3WindowUnlinkFromSelect(p->pWin); - } -#endif - if( bFree ) sqlite3DbNNFreeNN(db, p); + sqlite3ExprDelete(db, p->pOffset); + if( p->pWith ) sqlite3WithDelete(db, p->pWith); + if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; } } @@ -143944,11 +117408,10 @@ ** Initialize a SelectDest structure. */ SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; pDest->iSDParm = iParm; - pDest->iSDParm2 = 0; pDest->zAffSdst = 0; pDest->iSdst = 0; pDest->nSdst = 0; } @@ -143964,29 +117427,31 @@ Expr *pWhere, /* the WHERE clause */ ExprList *pGroupBy, /* the GROUP BY clause */ 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 *pLimit, /* LIMIT value. NULL means not used */ + Expr *pOffset /* OFFSET value. NULL means no offset */ ){ - Select *pNew, *pAllocated; + Select *pNew; Select standin; - pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) ); + pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) ); if( pNew==0 ){ assert( pParse->db->mallocFailed ); pNew = &standin; } if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, - sqlite3Expr(pParse->db,TK_ASTERISK,0)); + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0)); } pNew->pEList = pEList; pNew->op = TK_SELECT; pNew->selFlags = selFlags; pNew->iLimit = 0; pNew->iOffset = 0; - pNew->selId = ++pParse->nSelect; +#if SELECTTRACE_ENABLED + pNew->zSelName[0] = 0; +#endif pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = 0; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc)); pNew->pSrc = pSrc; @@ -143995,33 +117460,40 @@ pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->pPrior = 0; pNew->pNext = 0; pNew->pLimit = pLimit; + pNew->pOffset = pOffset; pNew->pWith = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - pNew->pWin = 0; - pNew->pWinDefn = 0; -#endif + assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 ); if( pParse->db->mallocFailed ) { clearSelect(pParse->db, pNew, pNew!=&standin); - pAllocated = 0; + pNew = 0; }else{ assert( pNew->pSrc!=0 || pParse->nErr>0 ); } - return pAllocated; + assert( pNew!=&standin ); + return pNew; } + +#if SELECTTRACE_ENABLED +/* +** Set the name of a Select object +*/ +SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ + if( p && zName ){ + sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName); + } +} +#endif /* ** Delete the given Select structure and all of its substructures. */ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ - if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1); -} -SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3 *db, void *p){ - if( ALWAYS(p) ) clearSelect(db, (Select*)p, 1); + if( p ) clearSelect(db, p, 1); } /* ** Return a pointer to the right-most SELECT statement in a compound. */ @@ -144044,56 +117516,10 @@ ** ** A full outer join is the combination of JT_LEFT and JT_RIGHT. ** ** If an illegal or unsupported join type is seen, then still return ** a join type, but put an error in the pParse structure. -** -** These are the valid join types: -** -** -** pA pB pC Return Value -** ------- ----- ----- ------------ -** CROSS - - JT_CROSS -** INNER - - JT_INNER -** LEFT - - JT_LEFT|JT_OUTER -** LEFT OUTER - JT_LEFT|JT_OUTER -** RIGHT - - JT_RIGHT|JT_OUTER -** RIGHT OUTER - JT_RIGHT|JT_OUTER -** FULL - - JT_LEFT|JT_RIGHT|JT_OUTER -** FULL OUTER - JT_LEFT|JT_RIGHT|JT_OUTER -** NATURAL INNER - JT_NATURAL|JT_INNER -** NATURAL LEFT - JT_NATURAL|JT_LEFT|JT_OUTER -** NATURAL LEFT OUTER JT_NATURAL|JT_LEFT|JT_OUTER -** NATURAL RIGHT - JT_NATURAL|JT_RIGHT|JT_OUTER -** NATURAL RIGHT OUTER JT_NATURAL|JT_RIGHT|JT_OUTER -** NATURAL FULL - JT_NATURAL|JT_LEFT|JT_RIGHT -** NATURAL FULL OUTER JT_NATRUAL|JT_LEFT|JT_RIGHT -** -** To preserve historical compatibly, SQLite also accepts a variety -** of other non-standard and in many cases nonsensical join types. -** This routine makes as much sense at it can from the nonsense join -** type and returns a result. Examples of accepted nonsense join types -** include but are not limited to: -** -** INNER CROSS JOIN -> same as JOIN -** NATURAL CROSS JOIN -> same as NATURAL JOIN -** OUTER LEFT JOIN -> same as LEFT JOIN -** LEFT NATURAL JOIN -> same as NATURAL LEFT JOIN -** LEFT RIGHT JOIN -> same as FULL JOIN -** RIGHT OUTER FULL JOIN -> same as FULL JOIN -** CROSS CROSS CROSS JOIN -> same as JOIN -** -** The only restrictions on the join type name are: -** -** * "INNER" cannot appear together with "OUTER", "LEFT", "RIGHT", -** or "FULL". -** -** * "CROSS" cannot appear together with "OUTER", "LEFT", "RIGHT, -** or "FULL". -** -** * If "OUTER" is present then there must also be one of -** "LEFT", "RIGHT", or "FULL" */ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; Token *apAll[3]; Token *p; @@ -144102,26 +117528,26 @@ static const struct { u8 i; /* Beginning of keyword text in zKeyText[] */ u8 nChar; /* Length of the keyword in characters */ u8 code; /* Join type mask */ } aKeyword[] = { - /* (0) natural */ { 0, 7, JT_NATURAL }, - /* (1) left */ { 6, 4, JT_LEFT|JT_OUTER }, - /* (2) outer */ { 10, 5, JT_OUTER }, - /* (3) right */ { 14, 5, JT_RIGHT|JT_OUTER }, - /* (4) full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, - /* (5) inner */ { 23, 5, JT_INNER }, - /* (6) cross */ { 28, 5, JT_INNER|JT_CROSS }, + /* natural */ { 0, 7, JT_NATURAL }, + /* left */ { 6, 4, JT_LEFT|JT_OUTER }, + /* outer */ { 10, 5, JT_OUTER }, + /* right */ { 14, 5, JT_RIGHT|JT_OUTER }, + /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + /* inner */ { 23, 5, JT_INNER }, + /* cross */ { 28, 5, JT_INNER|JT_CROSS }, }; int i, j; apAll[0] = pA; apAll[1] = pB; apAll[2] = pC; for(i=0; i<3 && apAll[i]; i++){ p = apAll[i]; for(j=0; jn==aKeyword[j].nChar + if( p->n==aKeyword[j].nChar && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){ jointype |= aKeyword[j].code; break; } } @@ -144131,89 +117557,63 @@ break; } } if( (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 || - (jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER + (jointype & JT_ERROR)!=0 ){ - const char *zSp1 = " "; - const char *zSp2 = " "; - if( pB==0 ){ zSp1++; } - if( pC==0 ){ zSp2++; } - sqlite3ErrorMsg(pParse, "unknown join type: " - "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC); + const char *zSp = " "; + assert( pB!=0 ); + if( pC==0 ){ zSp++; } + sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " + "%T %T%s%T", pA, pB, zSp, pC); + jointype = JT_INNER; + }else if( (jointype & JT_OUTER)!=0 + && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){ + sqlite3ErrorMsg(pParse, + "RIGHT and FULL OUTER JOINs are not currently supported"); jointype = JT_INNER; } return jointype; } /* ** Return the index of a column in a table. Return -1 if the column ** is not contained in the table. */ -SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ +static int columnIndex(Table *pTab, const char *zCol){ int i; - u8 h = sqlite3StrIHash(zCol); - Column *pCol; - for(pCol=pTab->aCol, i=0; inCol; pCol++, i++){ - if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i; + for(i=0; inCol; i++){ + if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i; } return -1; } /* -** Mark a subquery result column as having been used. -*/ -SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){ - assert( pItem!=0 ); - assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) ); - if( pItem->fg.isNestedFrom ){ - ExprList *pResults; - assert( pItem->fg.isSubquery ); - assert( pItem->u4.pSubq!=0 ); - assert( pItem->u4.pSubq->pSelect!=0 ); - pResults = pItem->u4.pSubq->pSelect->pEList; - assert( pResults!=0 ); - assert( iCol>=0 && iColnExpr ); - pResults->a[iCol].fg.bUsed = 1; - } -} - -/* -** Search the tables iStart..iEnd (inclusive) in pSrc, looking for a -** table that has a column named zCol. The search is left-to-right. -** The first match found is returned. +** Search the first N tables in pSrc, from left to right, looking for a +** table that has a column named zCol. ** ** When found, set *piTab and *piCol to the table index and column index ** of the matching column and return TRUE. ** ** If not found, return FALSE. */ static int tableAndColumnIndex( SrcList *pSrc, /* Array of tables to search */ - int iStart, /* First member of pSrc->a[] to check */ - int iEnd, /* Last member of pSrc->a[] to check */ + int N, /* Number of tables in pSrc->a[] to search */ const char *zCol, /* Name of the column we are looking for */ int *piTab, /* Write index of pSrc->a[] here */ - int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */ - int bIgnoreHidden /* Ignore hidden columns */ + int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */ ){ int i; /* For looping over tables in pSrc */ int iCol; /* Index of column matching zCol */ - assert( iEndnSrc ); - assert( iStart>=0 ); assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ - - for(i=iStart; i<=iEnd; i++){ - iCol = sqlite3ColumnIndex(pSrc->a[i].pSTab, zCol); - if( iCol>=0 - && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pSTab->aCol[iCol])==0) - ){ + for(i=0; ia[i].pTab, zCol); + if( iCol>=0 ){ if( piTab ){ - sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol); *piTab = i; *piCol = iCol; } return 1; } @@ -144220,23 +117620,67 @@ } return 0; } /* -** Set the EP_OuterON property on all terms of the given expression. -** And set the Expr.w.iJoin to iTable for every term in the +** This function is used to add terms implied by JOIN syntax to the +** WHERE clause expression of a SELECT statement. The new term, which +** is ANDed with the existing WHERE clause, is of the form: +** +** (tab1.col1 = tab2.col2) +** +** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the +** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is +** column iColRight of tab2. +*/ +static void addWhereTerm( + Parse *pParse, /* Parsing context */ + SrcList *pSrc, /* List of tables in FROM clause */ + int iLeft, /* Index of first table to join in pSrc */ + int iColLeft, /* Index of column in first table */ + int iRight, /* Index of second table in pSrc */ + int iColRight, /* Index of column in second table */ + int isOuterJoin, /* True if this is an OUTER join */ + Expr **ppWhere /* IN/OUT: The WHERE clause to add to */ +){ + sqlite3 *db = pParse->db; + Expr *pE1; + Expr *pE2; + Expr *pEq; + + assert( iLeftnSrc>iRight ); + assert( pSrc->a[iLeft].pTab ); + assert( pSrc->a[iRight].pTab ); + + pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft); + pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight); + + pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); + if( pEq && isOuterJoin ){ + ExprSetProperty(pEq, EP_FromJoin); + assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); + ExprSetVVAProperty(pEq, EP_NoReduce); + pEq->iRightJoinTable = (i16)pE2->iTable; + } + *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq); +} + +/* +** Set the EP_FromJoin property on all terms of the given expression. +** And set the Expr.iRightJoinTable to iTable for every term in the ** expression. ** -** The EP_OuterON property is used on terms of an expression to tell -** the OUTER JOIN processing logic that this term is part of the +** The EP_FromJoin property is used on terms of an expression to tell +** the LEFT OUTER JOIN processing logic that this term is part of the ** join restriction specified in the ON or USING clause and not a part ** of the more general WHERE clause. These terms are moved over to the ** WHERE clause during join processing but we need to remember that they ** originated in the ON or USING clause. ** -** The Expr.w.iJoin tells the WHERE clause processing that the -** expression depends on table w.iJoin even if that table is not +** The Expr.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table iRightJoinTable even if that table is not ** explicitly mentioned in the expression. That information is needed ** for cases like this: ** ** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 ** @@ -144245,286 +117689,136 @@ ** NULL t2 row will be inserted whenever t1.x!=5. If we do not ** defer the handling of t1.x=5, it will be processed immediately ** after the t1 loop and rows with t1.x!=5 will never appear in ** the output, which is incorrect. */ -SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){ - assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON ); +static void setJoinExpr(Expr *p, int iTable){ while( p ){ - ExprSetProperty(p, joinFlag); + ExprSetProperty(p, EP_FromJoin); assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); - p->w.iJoin = iTable; - if( p->op==TK_FUNCTION ){ - assert( ExprUseXList(p) ); - if( p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag); - } - } - } - sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag); - p = p->pRight; - } -} - -/* Undo the work of sqlite3SetJoinExpr(). This is used when a LEFT JOIN -** is simplified into an ordinary JOIN, and when an ON expression is -** "pushed down" into the WHERE clause of a subquery. -** -** Convert every term that is marked with EP_OuterON and w.iJoin==iTable into -** an ordinary term that omits the EP_OuterON mark. Or if iTable<0, then -** just clear every EP_OuterON and EP_InnerON mark from the expression tree. -** -** If nullable is true, that means that Expr p might evaluate to NULL even -** if it is a reference to a NOT NULL column. This can happen, for example, -** if the table that p references is on the left side of a RIGHT JOIN. -** If nullable is true, then take care to not remove the EP_CanBeNull bit. -** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c -*/ -static void unsetJoinExpr(Expr *p, int iTable, int nullable){ - while( p ){ - if( iTable<0 || (ExprHasProperty(p, EP_OuterON) && p->w.iJoin==iTable) ){ - ExprClearProperty(p, EP_OuterON|EP_InnerON); - if( iTable>=0 ) ExprSetProperty(p, EP_InnerON); - } - if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){ - ExprClearProperty(p, EP_CanBeNull); - } - if( p->op==TK_FUNCTION ){ - assert( ExprUseXList(p) ); - assert( p->pLeft==0 ); - if( p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable); - } - } - } - unsetJoinExpr(p->pLeft, iTable, nullable); - p = p->pRight; - } + p->iRightJoinTable = (i16)iTable; + if( p->op==TK_FUNCTION && p->x.pList ){ + int i; + for(i=0; ix.pList->nExpr; i++){ + setJoinExpr(p->x.pList->a[i].pExpr, iTable); + } + } + setJoinExpr(p->pLeft, iTable); + p = p->pRight; + } } /* ** This routine processes the join information for a SELECT statement. -** -** * A NATURAL join is converted into a USING join. After that, we -** do not need to be concerned with NATURAL joins and we only have -** think about USING joins. -** -** * ON and USING clauses result in extra terms being added to the -** WHERE clause to enforce the specified constraints. The extra -** WHERE clause terms will be tagged with EP_OuterON or -** EP_InnerON so that we know that they originated in ON/USING. +** ON and USING clauses are converted into extra terms of the WHERE clause. +** NATURAL joins also create extra WHERE clause terms. ** ** The terms of a FROM clause are contained in the Select.pSrc structure. ** The left most table is the first entry in Select.pSrc. The right-most ** table is the last entry. The join operator is held in the entry to -** the right. Thus entry 1 contains the join operator for the join between +** the left. Thus entry 0 contains the join operator for the join between ** entries 0 and 1. Any ON or USING clauses associated with the join are -** also attached to the right entry. +** also attached to the left entry. ** ** This routine returns the number of errors encountered. */ -static int sqlite3ProcessJoin(Parse *pParse, Select *p){ +static int sqliteProcessJoin(Parse *pParse, Select *p){ SrcList *pSrc; /* All tables in the FROM clause */ int i, j; /* Loop counters */ - SrcItem *pLeft; /* Left table being joined */ - SrcItem *pRight; /* Right table being joined */ + struct SrcList_item *pLeft; /* Left table being joined */ + struct SrcList_item *pRight; /* Right table being joined */ pSrc = p->pSrc; pLeft = &pSrc->a[0]; pRight = &pLeft[1]; for(i=0; inSrc-1; i++, pRight++, pLeft++){ - Table *pRightTab = pRight->pSTab; - u32 joinType; - - if( NEVER(pLeft->pSTab==0 || pRightTab==0) ) continue; - joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON; - - /* If this is a NATURAL join, synthesize an appropriate USING clause - ** to specify which columns should be joined. + Table *pLeftTab = pLeft->pTab; + Table *pRightTab = pRight->pTab; + int isOuter; + + if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; + isOuter = (pRight->fg.jointype & JT_OUTER)!=0; + + /* When the NATURAL keyword is present, add WHERE clause terms for + ** every column that the two tables have in common. */ if( pRight->fg.jointype & JT_NATURAL ){ - IdList *pUsing = 0; - if( pRight->fg.isUsing || pRight->u3.pOn ){ + if( pRight->pOn || pRight->pUsing ){ sqlite3ErrorMsg(pParse, "a NATURAL join may not have " "an ON or USING clause", 0); return 1; } for(j=0; jnCol; j++){ char *zName; /* Name of column in the right table */ - - if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue; - zName = pRightTab->aCol[j].zCnName; - if( tableAndColumnIndex(pSrc, 0, i, zName, 0, 0, 1) ){ - pUsing = sqlite3IdListAppend(pParse, pUsing, 0); - if( pUsing ){ - assert( pUsing->nId>0 ); - assert( pUsing->a[pUsing->nId-1].zName==0 ); - pUsing->a[pUsing->nId-1].zName = sqlite3DbStrDup(pParse->db, zName); - } - } - } - if( pUsing ){ - pRight->fg.isUsing = 1; - pRight->fg.isSynthUsing = 1; - pRight->u3.pUsing = pUsing; - } - if( pParse->nErr ) return 1; + int iLeft; /* Matching left table */ + int iLeftCol; /* Matching column in the left table */ + + zName = pRightTab->aCol[j].zName; + if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){ + addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j, + isOuter, &p->pWhere); + } + } + } + + /* Disallow both ON and USING clauses in the same join + */ + if( pRight->pOn && pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "cannot have both ON and USING " + "clauses in the same join"); + return 1; + } + + /* Add the ON clause to the end of the WHERE clause, connected by + ** an AND operator. + */ + if( pRight->pOn ){ + if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor); + p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn); + pRight->pOn = 0; } /* Create extra terms on the WHERE clause for each column named - ** in the USING clause. Example: If the two tables to be joined are + ** in the USING clause. Example: If the two tables to be joined are ** A and B and the USING clause names X, Y, and Z, then add this ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z ** Report an error if any column mentioned in the USING clause is ** not contained in both tables to be joined. */ - if( pRight->fg.isUsing ){ - IdList *pList = pRight->u3.pUsing; - sqlite3 *db = pParse->db; - assert( pList!=0 ); + if( pRight->pUsing ){ + IdList *pList = pRight->pUsing; for(j=0; jnId; j++){ char *zName; /* Name of the term in the USING clause */ int iLeft; /* Table on the left with matching column name */ int iLeftCol; /* Column number of matching column on the left */ int iRightCol; /* Column number of matching column on the right */ - Expr *pE1; /* Reference to the column on the LEFT of the join */ - Expr *pE2; /* Reference to the column on the RIGHT of the join */ - Expr *pEq; /* Equality constraint. pE1 == pE2 */ zName = pList->a[j].zName; - iRightCol = sqlite3ColumnIndex(pRightTab, zName); + iRightCol = columnIndex(pRightTab, zName); if( iRightCol<0 - || tableAndColumnIndex(pSrc, 0, i, zName, &iLeft, &iLeftCol, - pRight->fg.isSynthUsing)==0 + || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } - pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); - sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); - if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ - /* This branch runs if the query contains one or more RIGHT or FULL - ** JOINs. If only a single table on the left side of this join - ** contains the zName column, then this branch is a no-op. - ** But if there are two or more tables on the left side - ** of the join, construct a coalesce() function that gathers all - ** such tables. Raise an error if more than one of those references - ** to zName is not also within a prior USING clause. - ** - ** We really ought to raise an error if there are two or more - ** non-USING references to zName on the left of an INNER or LEFT - ** JOIN. But older versions of SQLite do not do that, so we avoid - ** adding a new error so as to not break legacy applications. - */ - ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */ - static const Token tkCoalesce = { "coalesce", 8 }; - while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol, - pRight->fg.isSynthUsing)!=0 ){ - if( pSrc->a[iLeft].fg.isUsing==0 - || sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0 - ){ - sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()", - zName); - break; - } - pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); - pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); - sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); - } - if( pFuncArgs ){ - pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); - pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0); - } - } - pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol); - sqlite3SrcItemColumnUsed(pRight, iRightCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); - assert( pE2!=0 || pEq==0 ); - if( pEq ){ - ExprSetProperty(pEq, joinType); - assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); - ExprSetVVAProperty(pEq, EP_NoReduce); - pEq->w.iJoin = pE2->iTable; - } - p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pEq); - } - } - - /* Add the ON clause to the end of the WHERE clause, connected by - ** an AND operator. - */ - else if( pRight->u3.pOn ){ - sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType); - p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); - pRight->u3.pOn = 0; - pRight->fg.isOn = 1; + addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol, + isOuter, &p->pWhere); + } } } return 0; } -/* -** An instance of this object holds information (beyond pParse and pSelect) -** needed to load the next result row that is to be added to the sorter. -*/ -typedef struct RowLoadInfo RowLoadInfo; -struct RowLoadInfo { - int regResult; /* Store results in array of registers here */ - u8 ecelFlags; /* Flag argument to ExprCodeExprList() */ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - ExprList *pExtra; /* Extra columns needed by sorter refs */ - int regExtraResult; /* Where to load the extra columns */ -#endif -}; - -/* -** This routine does the work of loading query data into an array of -** registers so that it can be added to the sorter. -*/ -static void innerLoopLoadRow( - Parse *pParse, /* Statement under construction */ - Select *pSelect, /* The query being coded */ - RowLoadInfo *pInfo /* Info needed to complete the row load */ -){ - sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult, - 0, pInfo->ecelFlags); -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( pInfo->pExtra ){ - sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0); - sqlite3ExprListDelete(pParse->db, pInfo->pExtra); - } -#endif -} - -/* -** Code the OP_MakeRecord instruction that generates the entry to be -** added into the sorter. -** -** Return the register in which the result is stored. -*/ -static int makeSorterRecord( - Parse *pParse, - SortCtx *pSort, - Select *pSelect, - int regBase, - int nBase -){ - int nOBSat = pSort->nOBSat; - Vdbe *v = pParse->pVdbe; - int regOut = ++pParse->nMem; - if( pSort->pDeferredRowLoad ){ - innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut); - return regOut; -} +/* Forward reference */ +static KeyInfo *keyInfoFromExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* Form the KeyInfo object from this ExprList */ + int iStart, /* Begin with this column of pList */ + int nExtra /* Add this many extra columns to the end */ +); /* ** Generate code that will push the record in registers regData ** through regData+nData-1 onto the sorter. */ @@ -144532,95 +117826,74 @@ Parse *pParse, /* Parser context */ SortCtx *pSort, /* Information about the ORDER BY clause */ Select *pSelect, /* The whole SELECT statement */ int regData, /* First register holding data to be sorted */ int regOrigData, /* First register holding data before packing */ - int nData, /* Number of elements in the regData data array */ + int nData, /* Number of elements in the data array */ int nPrefixReg /* No. of reg prior to regData available for use */ ){ Vdbe *v = pParse->pVdbe; /* Stmt under construction */ int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0); int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ int regBase; /* Regs for sorter record */ - int regRecord = 0; /* Assembled sorter record */ + int regRecord = ++pParse->nMem; /* Assembled sorter record */ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ int iLimit; /* LIMIT counter */ - int iSkip = 0; /* End of the sorter insert loop */ assert( bSeq==0 || bSeq==1 ); - - /* Three cases: - ** (1) The data to be sorted has already been packed into a Record - ** by a prior OP_MakeRecord. In this case nData==1 and regData - ** will be completely unrelated to regOrigData. - ** (2) All output columns are included in the sort record. In that - ** case regData==regOrigData. - ** (3) Some output columns are omitted from the sort record due to - ** the SQLITE_ENABLE_SORTER_REFERENCES optimization, or due to the - ** SQLITE_ECEL_OMITREF optimization, or due to the - ** SortCtx.pDeferredRowLoad optimization. In any of these cases - ** regOrigData is 0 to prevent this routine from trying to copy - ** values that might not yet exist. - */ assert( nData==1 || regData==regOrigData || regOrigData==0 ); - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pSort->addrPush = sqlite3VdbeCurrentAddr(v); -#endif - if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); - regBase = regData - nPrefixReg; + regBase = regData - nExpr - bSeq; }else{ regBase = pParse->nMem + 1; pParse->nMem += nBase; } assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; - pSort->labelDone = sqlite3VdbeMakeLabel(pParse); + pSort->labelDone = sqlite3VdbeMakeLabel(v); sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0)); if( bSeq ){ sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); } if( nPrefixReg==0 && nData>0 ){ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ int addrFirst; /* Address of the OP_IfNot opcode */ int addrJmp; /* Address of the OP_Jump opcode */ VdbeOp *pOp; /* Opcode that opens the sorter */ int nKey; /* Number of sorting key columns, including OP_Sequence */ KeyInfo *pKI; /* Original KeyInfo on the sorter table */ - regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); regPrevKey = pParse->nMem+1; pParse->nMem += pSort->nOBSat; nKey = nExpr - pSort->nOBSat + bSeq; if( bSeq ){ - addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); + addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); }else{ addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor); } VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat); pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); if( pParse->db->mallocFailed ) return; pOp->p2 = nKey + nData; pKI = pOp->p4.pKeyInfo; - memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */ + memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); - testcase( pKI->nAllField > pKI->nKeyField+2 ); - pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, - pKI->nAllField-pKI->nKeyField-1); - pOp = 0; /* Ensure pOp not used after sqlite3VdbeAddOp3() */ + testcase( pKI->nXField>2 ); + pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, + pKI->nXField-1); addrJmp = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); - pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse); + pSort->labelBkOut = sqlite3VdbeMakeLabel(v); pSort->regReturn = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor); if( iLimit ){ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone); @@ -144628,52 +117901,45 @@ } sqlite3VdbeJumpHere(v, addrFirst); sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); sqlite3VdbeJumpHere(v, addrJmp); } - if( iLimit ){ - /* At this point the values for the new sorter entry are stored - ** in an array of registers. They need to be composed into a record - ** and inserted into the sorter if either (a) there are currently - ** less than LIMIT+OFFSET items or (b) the new record is smaller than - ** the largest record currently in the sorter. If (b) is true and there - ** are already LIMIT+OFFSET items in the sorter, delete the largest - ** entry before inserting the new one. This way there are never more - ** than LIMIT+OFFSET items in the sorter. - ** - ** If the new record does not need to be inserted into the sorter, - ** jump to the next iteration of the loop. If the pSort->labelOBLopt - ** value is not zero, then it is a label of where to jump. Otherwise, - ** just bypass the row insert logic. See the header comment on the - ** sqlite3WhereOrderByLimitOptLabel() function for additional info. - */ - int iCsr = pSort->iECursor; - sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); - iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE, - iCsr, 0, regBase+nOBSat, nExpr-nOBSat); - VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_Delete, iCsr); - } - if( regRecord==0 ){ - regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); - } if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; }else{ op = OP_IdxInsert; } sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, regBase+nOBSat, nBase-nOBSat); - if( iSkip ){ - sqlite3VdbeChangeP2(v, iSkip, - pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v)); + if( iLimit ){ + int addr; + int r1 = 0; + /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit + ** 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 = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); + sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); + if( pSort->bOrderedInnerLoop ){ + r1 = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); + VdbeComment((v, "seq")); + } + sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); + if( pSort->bOrderedInnerLoop ){ + /* If the inner loop is driven by an index such that values from + ** the same iteration of the inner loop are in sorted order, then + ** immediately jump to the next iteration of an inner loop if the + ** entry from the current iteration does not fit into the top + ** LIMIT+OFFSET entries of the sorter. */ + int iBrk = sqlite3VdbeCurrentAddr(v) + 2; + sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + VdbeCoverage(v); + } + sqlite3VdbeJumpHere(v, addr); } -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pSort->addrPushEnd = sqlite3VdbeCurrentAddr(v)-1; -#endif } /* ** Add code to implement the OFFSET */ @@ -144687,262 +117953,51 @@ VdbeComment((v, "OFFSET")); } } /* -** Add code that will check to make sure the array of registers starting at -** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and -** distinct aggregates ("SELECT count(DISTINCT ) ..."). Three strategies -** are available. Which is used depends on the value of parameter eTnctType, -** as follows: -** -** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP: -** Build an ephemeral table that contains all entries seen before and -** skip entries which have been seen before. -** -** Parameter iTab is the cursor number of an ephemeral table that must -** be opened before the VM code generated by this routine is executed. -** The ephemeral cursor table is queried for a record identical to the -** record formed by the current array of registers. If one is found, -** jump to VM address addrRepeat. Otherwise, insert a new record into -** the ephemeral cursor and proceed. -** -** The returned value in this case is a copy of parameter iTab. -** -** WHERE_DISTINCT_ORDERED: -** In this case rows are being delivered sorted order. The ephemeral -** table is not required. Instead, the current set of values -** is compared against previous row. If they match, the new row -** is not distinct and control jumps to VM address addrRepeat. Otherwise, -** the VM program proceeds with processing the new row. -** -** The returned value in this case is the register number of the first -** in an array of registers used to store the previous result row so that -** it can be compared to the next. The caller must ensure that this -** register is initialized to NULL. (The fixDistinctOpenEph() routine -** will take care of this initialization.) -** -** WHERE_DISTINCT_UNIQUE: -** In this case it has already been determined that the rows are distinct. -** No special action is required. The return value is zero. -** -** Parameter pEList is the list of expressions used to generated the -** contents of each row. It is used by this routine to determine (a) -** how many elements there are in the array of registers and (b) the -** collation sequences that should be used for the comparisons if -** eTnctType is WHERE_DISTINCT_ORDERED. -*/ -static int codeDistinct( - Parse *pParse, /* Parsing and code generating context */ - int eTnctType, /* WHERE_DISTINCT_* value */ +** Add code that will check to make sure the N registers starting at iMem +** form a distinct entry. iTab is a sorting index that holds previously +** seen combinations of the N values. A new entry is made in iTab +** if the current N values are new. +** +** A jump to addrRepeat is made and the N+1 values are popped from the +** stack if the top N elements are not distinct. +*/ +static void codeDistinct( + Parse *pParse, /* Parsing and code generating context */ int iTab, /* A sorting index used to test for distinctness */ int addrRepeat, /* Jump to here if not distinct */ - ExprList *pEList, /* Expression for each element */ - int regElem /* First element */ -){ - int iRet = 0; - int nResultCol = pEList->nExpr; - Vdbe *v = pParse->pVdbe; - - switch( eTnctType ){ - case WHERE_DISTINCT_ORDERED: { - int i; - int iJump; /* Jump destination */ - int regPrev; /* Previous row content */ - - /* Allocate space for the previous row */ - iRet = regPrev = pParse->nMem+1; - pParse->nMem += nResultCol; - - iJump = sqlite3VdbeCurrentAddr(v) + nResultCol; - for(i=0; ia[i].pExpr); - if( idb->mallocFailed ); - sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1); - break; - } - - case WHERE_DISTINCT_UNIQUE: { - /* nothing to do */ - break; - } - - default: { - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3ReleaseTempReg(pParse, r1); - iRet = iTab; - break; - } - } - - return iRet; -} - -/* -** This routine runs after codeDistinct(). It makes necessary -** adjustments to the OP_OpenEphemeral opcode that the codeDistinct() -** routine made use of. This processing must be done separately since -** sometimes codeDistinct is called before the OP_OpenEphemeral is actually -** laid down. -** -** WHERE_DISTINCT_NOOP: -** WHERE_DISTINCT_UNORDERED: -** -** No adjustments necessary. This function is a no-op. -** -** WHERE_DISTINCT_UNIQUE: -** -** The ephemeral table is not needed. So change the -** OP_OpenEphemeral opcode into an OP_Noop. -** -** WHERE_DISTINCT_ORDERED: -** -** The ephemeral table is not needed. But we do need register -** iVal to be initialized to NULL. So change the OP_OpenEphemeral -** into an OP_Null on the iVal register. -*/ -static void fixDistinctOpenEph( - Parse *pParse, /* Parsing and code generating context */ - int eTnctType, /* WHERE_DISTINCT_* value */ - int iVal, /* Value returned by codeDistinct() */ - int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */ -){ - if( pParse->nErr==0 - && (eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED) - ){ - Vdbe *v = pParse->pVdbe; - sqlite3VdbeChangeToNoop(v, iOpenEphAddr); - if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){ - sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1); - } - if( eTnctType==WHERE_DISTINCT_ORDERED ){ - /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared - ** bit on the first register of the previous value. This will cause the - ** OP_Ne added in codeDistinct() to always fail on the first iteration of - ** the loop even if the first row is all NULLs. */ - VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr); - pOp->opcode = OP_Null; - pOp->p1 = 1; - pOp->p2 = iVal; - } - } -} - -#ifdef SQLITE_ENABLE_SORTER_REFERENCES -/* -** This function is called as part of inner-loop generation for a SELECT -** statement with an ORDER BY that is not optimized by an index. It -** determines the expressions, if any, that the sorter-reference -** optimization should be used for. The sorter-reference optimization -** is used for SELECT queries like: -** -** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10 -** -** If the optimization is used for expression "bigblob", then instead of -** storing values read from that column in the sorter records, the PK of -** the row from table t1 is stored instead. Then, as records are extracted from -** the sorter to return to the user, the required value of bigblob is -** retrieved directly from table t1. If the values are very large, this -** can be more efficient than storing them directly in the sorter records. -** -** The ExprList_item.fg.bSorterRef flag is set for each expression in pEList -** for which the sorter-reference optimization should be enabled. -** Additionally, the pSort->aDefer[] array is populated with entries -** for all cursors required to evaluate all selected expressions. Finally. -** output variable (*ppExtra) is set to an expression list containing -** expressions for all extra PK values that should be stored in the -** sorter records. -*/ -static void selectExprDefer( - Parse *pParse, /* Leave any error here */ - SortCtx *pSort, /* Sorter context */ - ExprList *pEList, /* Expressions destined for sorter */ - ExprList **ppExtra /* Expressions to append to sorter record */ -){ - int i; - int nDefer = 0; - ExprList *pExtra = 0; - for(i=0; inExpr; i++){ - struct ExprList_item *pItem = &pEList->a[i]; - if( pItem->u.x.iOrderByCol==0 ){ - Expr *pExpr = pItem->pExpr; - Table *pTab; - if( pExpr->op==TK_COLUMN - && pExpr->iColumn>=0 - && ALWAYS( ExprUseYTab(pExpr) ) - && (pTab = pExpr->y.pTab)!=0 - && IsOrdinaryTable(pTab) - && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)!=0 - ){ - int j; - for(j=0; jaDefer[j].iCsr==pExpr->iTable ) break; - } - if( j==nDefer ){ - if( nDefer==ArraySize(pSort->aDefer) ){ - continue; - }else{ - int nKey = 1; - int k; - Index *pPk = 0; - if( !HasRowid(pTab) ){ - pPk = sqlite3PrimaryKeyIndex(pTab); - nKey = pPk->nKeyCol; - } - for(k=0; kiTable = pExpr->iTable; - assert( ExprUseYTab(pNew) ); - pNew->y.pTab = pExpr->y.pTab; - pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; - pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); - } - } - pSort->aDefer[nDefer].pTab = pExpr->y.pTab; - pSort->aDefer[nDefer].iCsr = pExpr->iTable; - pSort->aDefer[nDefer].nKey = nKey; - nDefer++; - } - } - pItem->fg.bSorterRef = 1; - } - } - } - pSort->nDefer = (u8)nDefer; - *ppExtra = pExtra; -} -#endif + int N, /* Number of elements */ + int iMem /* First element */ +){ + Vdbe *v; + int r1; + + v = pParse->pVdbe; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + sqlite3ReleaseTempReg(pParse, r1); +} /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** -** If srcTab is negative, then the p->pEList expressions +** If srcTab is negative, then the 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 p->pEList is used only +** zero or more, then data is pulled from srcTab and 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 */ - int srcTab, /* Pull data from this table if non-negative */ + ExprList *pEList, /* List of values being extracted */ + int srcTab, /* Pull data from this table */ 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 */ int iContinue, /* Jump here to continue with next row */ int iBreak /* Jump here to break out of the inner loop */ @@ -144952,11 +118007,10 @@ 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 */ - RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */ /* 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 @@ -144963,21 +118017,21 @@ ** 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( p->pEList!=0 ); + assert( pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; if( pSort && pSort->pOrderBy==0 ) pSort = 0; if( pSort==0 && !hasDistinct ){ assert( iContinue!=0 ); codeOffset(v, p->iOffset, iContinue); } /* Pull the requested columns. */ - nResultCol = p->pEList->nExpr; + nResultCol = pEList->nExpr; if( pDest->iSdst==0 ){ if( pSort ){ nPrefixReg = pSort->pOrderBy->nExpr; if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++; @@ -144996,109 +118050,100 @@ pDest->nSdst = nResultCol; regOrig = regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; ipEList->a[i].zEName)); + VdbeComment((v, "%s", pEList->a[i].zName)); } }else if( eDest!=SRT_Exists ){ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - ExprList *pExtra = 0; -#endif /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */ - ExprList *pEList; + u8 ecelFlags; if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ ecelFlags = 0; } 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 + /* For each expression in 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, + ** This allows the 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; - } - } -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - selectExprDefer(pParse, pSort, p->pEList, &pExtra); - if( pExtra && pParse->db->mallocFailed==0 ){ - /* If there are any extra PK columns to add to the sorter records, - ** allocate extra memory cells and adjust the OpenEphemeral - ** instruction to account for the larger records. This is only - ** required if there are one or more WITHOUT ROWID tables with - ** composite primary keys in the SortCtx.aDefer[] array. */ - VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); - pOp->p2 += (pExtra->nExpr - pSort->nDefer); - pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer); - pParse->nMem += pExtra->nExpr; - } -#endif - - /* Adjust nResultCol to account for columns that are omitted - ** from the sorter by the optimizations in this branch */ - pEList = p->pEList; - for(i=0; inExpr; i++){ - if( pEList->a[i].u.x.iOrderByCol>0 -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - || pEList->a[i].fg.bSorterRef -#endif - ){ - nResultCol--; - regOrig = 0; - } - } - - testcase( regOrig ); - testcase( eDest==SRT_Set ); - testcase( eDest==SRT_Mem ); - testcase( eDest==SRT_Coroutine ); - testcase( eDest==SRT_Output ); - assert( eDest==SRT_Set || eDest==SRT_Mem - || eDest==SRT_Coroutine || eDest==SRT_Output - || eDest==SRT_Upfrom ); - } - sRowLoadInfo.regResult = regResult; - sRowLoadInfo.ecelFlags = ecelFlags; -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - sRowLoadInfo.pExtra = pExtra; - sRowLoadInfo.regExtraResult = regResult + nResultCol; - if( pExtra ) nResultCol += pExtra->nExpr; -#endif - if( p->iLimit - && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 - && nPrefixReg>0 - ){ - assert( pSort!=0 ); - assert( hasDistinct==0 ); - pSort->pDeferredRowLoad = &sRowLoadInfo; - regOrig = 0; - }else{ - innerLoopLoadRow(pParse, p, &sRowLoadInfo); - } + 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,pEList,regResult,0,ecelFlags); } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ - int eType = pDistinct->eTnctType; - int iTab = pDistinct->tabTnct; - assert( nResultCol==p->pEList->nExpr ); - iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult); - fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct); + switch( pDistinct->eTnctType ){ + case WHERE_DISTINCT_ORDERED: { + VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ + int iJump; /* Jump destination */ + int regPrev; /* Previous row content */ + + /* Allocate space for the previous row */ + regPrev = pParse->nMem+1; + pParse->nMem += nResultCol; + + /* Change the OP_OpenEphemeral coded earlier to an OP_Null + ** sets the MEM_Cleared bit on the first register of the + ** previous value. This will cause the OP_Ne below to always + ** fail on the first iteration of the loop even if the first + ** row is all NULLs. + */ + sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); + pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct); + pOp->opcode = OP_Null; + pOp->p1 = 1; + pOp->p2 = regPrev; + + iJump = sqlite3VdbeCurrentAddr(v) + nResultCol; + for(i=0; ia[i].pExpr); + if( idb->mallocFailed ); + sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1); + break; + } + + case WHERE_DISTINCT_UNIQUE: { + sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); + break; + } + + default: { + assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED ); + codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, + regResult); + break; + } + } if( pSort==0 ){ codeOffset(v, p->iOffset, iContinue); } } @@ -145136,20 +118181,10 @@ testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); testcase( eDest==SRT_Fifo ); testcase( eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); -#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) - /* A destination of SRT_Table and a non-zero iSDParm2 parameter means - ** that this is an "UPDATE ... FROM" on a virtual table or view. In this - ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. - ** This does not affect operation in any way - it just allows MakeRecord - ** to process OPFLAG_NOCHANGE values without an assert() failing. */ - if( eDest==SRT_Table && pDest->iSDParm2 ){ - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); - } -#endif #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open ** on an ephemeral index. If the current row is already present ** in the index, do not write it to the output. If not, add the @@ -145161,44 +118196,19 @@ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol); assert( pSort==0 ); } #endif if( pSort ){ - assert( regResult==regOrig ); - pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg); + pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); }else{ int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); } sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1); - break; - } - - case SRT_Upfrom: { - if( pSort ){ - pushOntoSorter( - pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); - }else{ - int i2 = pDest->iSDParm2; - int r1 = sqlite3GetTempReg(pParse); - - /* If the UPDATE FROM join is an aggregate that matches no rows, it - ** might still be trying to return one row, because that is what - ** aggregates do. Don't record that empty row in the output table. */ - sqlite3VdbeAddOp2(v, OP_IsNull, regResult, iBreak); VdbeCoverage(v); - - sqlite3VdbeAddOp3(v, OP_MakeRecord, - regResult+(i2<0), nResultCol-(i2<0), r1); - if( i2<0 ){ - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult); - }else{ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2); - } - } break; } #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, @@ -145211,27 +118221,21 @@ ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ pushOntoSorter( pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); - pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */ }else{ int r1 = sqlite3GetTempReg(pParse); assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, + sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, r1, pDest->zAffSdst, nResultCol); + sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); - if( pDest->iSDParm2 ){ - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0, - regResult, nResultCol); - ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER")); - } sqlite3ReleaseTempReg(pParse, r1); } break; } - /* If any row exist in the result set, record that fact and abort. */ case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); @@ -145238,11 +118242,11 @@ /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell or array of + ** store the results in the appropriate memory cell or array of ** memory cells and break out of the scan loop. */ case SRT_Mem: { if( pSort ){ assert( nResultCol<=pDest->nSdst ); @@ -145266,10 +118270,11 @@ nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); + sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); } break; } #ifndef SQLITE_OMIT_CTE @@ -145293,11 +118298,11 @@ r3 = r2+nKey+1; if( eDest==SRT_DistQueue ){ /* If the destination is DistQueue, then cursor (iParm+1) is open ** on a second ephemeral index that holds all values every previously ** added to the queue. */ - addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, + addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, regResult, nResultCol); VdbeCoverage(v); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); if( eDest==SRT_DistQueue ){ @@ -145349,32 +118354,31 @@ */ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*); KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); if( p ){ - p->aSortFlags = (u8*)&p->aColl[N+X]; - p->nKeyField = (u16)N; - p->nAllField = (u16)(N+X); + p->aSortOrder = (u8*)&p->aColl[N+X]; + p->nField = (u16)N; + p->nXField = (u16)X; p->enc = ENC(db); p->db = db; p->nRef = 1; memset(&p[1], 0, nExtra); }else{ - return (KeyInfo*)sqlite3OomFault(db); + sqlite3OomFault(db); } return p; } /* ** Deallocate a KeyInfo object */ SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){ if( p ){ - assert( p->db!=0 ); assert( p->nRef>0 ); p->nRef--; - if( p->nRef==0 ) sqlite3DbNNFreeNN(p->db, p); + if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p); } } /* ** Make a new pointer to a KeyInfo object @@ -145409,11 +118413,11 @@ ** ** Space to hold the KeyInfo structure is obtained from malloc. The calling ** function is responsible for seeing that this structure is eventually ** freed. */ -SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList( +static KeyInfo *keyInfoFromExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* Form the KeyInfo object from this ExprList */ int iStart, /* Begin with this column of pList */ int nExtra /* Add this many extra columns to the end */ ){ @@ -145426,21 +118430,24 @@ nExpr = pList->nExpr; pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); if( pInfo ){ assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=iStart, pItem=pList->a+iStart; iaColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); - pInfo->aSortFlags[i-iStart] = pItem->fg.sortFlags; + CollSeq *pColl; + pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); + if( !pColl ) pColl = db->pDfltColl; + pInfo->aColl[i-iStart] = pColl; + pInfo->aSortOrder[i-iStart] = pItem->sortOrder; } } return pInfo; } /* ** Name of the connection operator, used for error messages. */ -SQLITE_PRIVATE const char *sqlite3SelectOpName(int id){ +static const char *selectOpName(int id){ char *z; switch( id ){ case TK_ALL: z = "UNION ALL"; break; case TK_INTERSECT: z = "INTERSECT"; break; case TK_EXCEPT: z = "EXCEPT"; break; @@ -145459,11 +118466,15 @@ ** ** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which ** is determined by the zUsage argument. */ static void explainTempTable(Parse *pParse, const char *zUsage){ - ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage)); + if( pParse->explain==2 ){ + Vdbe *v = pParse->pVdbe; + char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); + sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); + } } /* ** Assign expression b to lvalue a. A second, no-op, version of this macro ** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code @@ -145477,10 +118488,46 @@ /* No-op versions of the explainXXX() functions and macros. */ # define explainTempTable(y,z) # define explainSetInteger(y,z) #endif +#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) +/* +** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function +** is a no-op. Otherwise, it adds a single row of output to the EQP result, +** where the caption is of one of the two forms: +** +** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" +** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" +** +** where iSub1 and iSub2 are the integers passed as the corresponding +** function parameters, and op is the text representation of the parameter +** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, +** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is +** false, or the second form if it is true. +*/ +static void explainComposite( + Parse *pParse, /* Parse context */ + int op, /* One of TK_UNION, TK_EXCEPT etc. */ + int iSub1, /* Subquery id 1 */ + int iSub2, /* Subquery id 2 */ + int bUseTmp /* True if a temp table was used */ +){ + assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); + if( pParse->explain==2 ){ + Vdbe *v = pParse->pVdbe; + char *zMsg = sqlite3MPrintf( + pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, + bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) + ); + sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); + } +} +#else +/* No-op versions of the explainXXX() functions and macros. */ +# define explainComposite(v,w,x,y,z) +#endif /* ** If the inner loop was generated using a non-null pOrderBy argument, ** then the results were placed in a sorter. After the loop is terminated ** we need to run the sorter and output the results. The following @@ -145493,159 +118540,76 @@ int nColumn, /* Number of columns of data */ SelectDest *pDest /* Write the sorted results here */ ){ Vdbe *v = pParse->pVdbe; /* The prepared statement */ int addrBreak = pSort->labelDone; /* Jump here to exit loop */ - int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */ - int addr; /* Top of output loop. Jump for Next. */ + int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ + int addr; int addrOnce = 0; int iTab; ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int iCol; - int nKey; /* Number of key columns in sorter record */ + 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. */ - int nRefKey = 0; struct ExprList_item *aOutEx = p->pEList->a; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; /* Address of OP_Explain instruction */ -#endif - - nKey = pOrderBy->nExpr - pSort->nOBSat; - if( pSort->nOBSat==0 || nKey==1 ){ - ExplainQueryPlan2(addrExplain, (pParse, 0, - "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":"" - )); - }else{ - ExplainQueryPlan2(addrExplain, (pParse, 0, - "USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey - )); - } - sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd); - sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush); - assert( addrBreak<0 ); if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeGoto(v, addrBreak); sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } - -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - /* Open any cursors needed for sorter-reference expressions */ - for(i=0; inDefer; i++){ - Table *pTab = pSort->aDefer[i].pTab; - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); - nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); - } -#endif - iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ - if( eDest==SRT_Mem && p->iOffset ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst); - } regRowid = 0; regRow = pDest->iSdst; + nSortData = nColumn; }else{ regRowid = sqlite3GetTempReg(pParse); - if( eDest==SRT_EphemTab || eDest==SRT_Table ){ - regRow = sqlite3GetTempReg(pParse); - nColumn = 0; - }else{ - regRow = sqlite3GetTempRange(pParse, nColumn); - } + regRow = sqlite3GetTempRange(pParse, nColumn); + nSortData = nColumn; } + nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; iSortTab = pParse->nTab++; if( pSort->labelBkOut ){ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } - sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, - nKey+1+nColumn+nRefKey); + sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); - assert( p->iLimit==0 && p->iOffset==0 ); + codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; }else{ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; - if( p->iOffset>0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); - } - } - for(i=0, iCol=nKey+bSeq-1; inDefer ){ - int iKey = iCol+1; - int regKey = sqlite3GetTempRange(pParse, nRefKey); - - for(i=0; inDefer; i++){ - int iCsr = pSort->aDefer[i].iCsr; - Table *pTab = pSort->aDefer[i].pTab; - int nKey = pSort->aDefer[i].nKey; - - sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey); - sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr, - sqlite3VdbeCurrentAddr(v)+1, regKey); - }else{ - int k; - int iJmp; - assert( sqlite3PrimaryKeyIndex(pTab)->nKeyCol==nKey ); - for(k=0; k=0; i--){ -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( aOutEx[i].fg.bSorterRef ){ - sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i); - }else -#endif - { - int iRead; - if( aOutEx[i].u.x.iOrderByCol ){ - iRead = aOutEx[i].u.x.iOrderByCol-1; - }else{ - iRead = iCol--; - } - sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); - VdbeComment((v, "%s", aOutEx[i].zEName)); - } - } - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); + } + for(i=0, iCol=nKey+bSeq; izAffSdst) ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, pDest->zAffSdst, nColumn); + sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); break; } case SRT_Mem: { /* The LIMIT clause will terminate the loop for us */ break; } #endif - case SRT_Upfrom: { - int i2 = pDest->iSDParm2; - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord,regRow+(i2<0),nColumn-(i2<0),r1); - if( i2<0 ){ - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regRow); - }else{ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regRow, i2); - } - break; - } default: { - assert( eDest==SRT_Output || eDest==SRT_Coroutine ); + assert( eDest==SRT_Output || eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); testcase( eDest==SRT_Coroutine ); if( eDest==SRT_Output ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); + sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); }else{ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); } break; } @@ -145699,151 +118654,154 @@ if( pSort->sortFlags & SORTFLAG_UseSorter ){ sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v); } - sqlite3VdbeScanStatusRange(v, addrExplain, sqlite3VdbeCurrentAddr(v)-1, -1); if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn); sqlite3VdbeResolveLabel(v, addrBreak); } /* ** Return a pointer to a string containing the 'declaration type' of the ** expression pExpr. The string may be treated as static by the caller. +** +** Also try to estimate the size of the returned value and return that +** result in *pEstWidth. ** ** The declaration type is the exact datatype definition extracted from the ** original CREATE TABLE statement if the expression is a column. The ** declaration type for a ROWID field is INTEGER. Exactly when an expression ** is considered a column can be complex in the presence of subqueries. The -** result-set expression in all of the following SELECT statements is +** result-set expression in all of the following SELECT statements is ** considered a column by this function. ** ** SELECT col FROM tbl; ** SELECT (SELECT col FROM tbl; ** SELECT (SELECT col FROM tbl); ** SELECT abc FROM (SELECT col AS abc FROM tbl); -** +** ** The declaration type for any expression other than a column is NULL. ** ** This routine has either 3 or 6 parameters depending on whether or not ** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used. */ #ifdef SQLITE_ENABLE_COLUMN_METADATA -# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E) +# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) #else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ -# define columnType(A,B,C,D,E) columnTypeImpl(A,B) +# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) #endif static const char *columnTypeImpl( - NameContext *pNC, -#ifndef SQLITE_ENABLE_COLUMN_METADATA - Expr *pExpr -#else + NameContext *pNC, 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; char const *zOrigCol = 0; #endif assert( pExpr!=0 ); assert( pNC->pSrcList!=0 ); 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 ** database table or a subquery. */ 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++); if( jnSrc ){ - pTab = pTabList->a[j].pSTab; - if( pTabList->a[j].fg.isSubquery ){ - pS = pTabList->a[j].u4.pSubq->pSelect; - }else{ - pS = 0; - } + pTab = pTabList->a[j].pTab; + pS = pTabList->a[j].pSelect; }else{ pNC = pNC->pNext; } } if( pTab==0 ){ /* At one time, code such as "SELECT new.x" within a trigger would ** cause this condition to run. Since then, we have restructured how - ** trigger code is generated and so this condition is no longer + ** trigger code is generated and so this condition is no longer ** possible. However, it can still be true for statements like ** the following: ** ** CREATE TABLE t1(col INTEGER); ** SELECT (SELECT t1.col) FROM FROM t1; ** - ** when columnType() is called on the expression "t1.col" in the + ** when columnType() is called on the expression "t1.col" in the ** sub-select. In this case, set the column type to NULL, even ** though it should really be "INTEGER". ** ** This is not a problem, as the column type of "t1.col" is never - ** used. When columnType() is called on the expression + ** used. When columnType() is called on the expression ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT ** branch below. */ break; } - assert( pTab && ExprUseYTab(pExpr) && pExpr->y.pTab==pTab ); + assert( pTab && pExpr->pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ - if( iColpEList->nExpr - && (!ViewCanHaveRowid || iCol>=0) - ){ + if( iCol>=0 && ALWAYS(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 + ** 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); + zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); } - }else{ - /* A real table or a CTE table */ + }else if( pTab->pSchema ){ + /* A real table */ assert( !pS ); -#ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==XN_ROWID || (iCol>=0 && iColnCol) ); + assert( iCol==-1 || (iCol>=0 && iColnCol) ); +#ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ - zOrigCol = pTab->aCol[iCol].zCnName; + zOrigCol = pTab->aCol[iCol].zName; zType = sqlite3ColumnType(&pTab->aCol[iCol],0); + estWidth = pTab->aCol[iCol].szEst; } zOrigTab = pTab->zName; - if( pNC->pParse && pTab->pSchema ){ + if( pNC->pParse ){ 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 } break; } @@ -145852,32 +118810,31 @@ /* The expression is a sub-select. Return the declaration type and ** origin info for the single column in the result set of the SELECT ** statement. */ NameContext sNC; - Select *pS; - Expr *p; - assert( ExprUseXSelect(pExpr) ); - pS = pExpr->x.pSelect; - p = pS->pEList->a[0].pExpr; + Select *pS = pExpr->x.pSelect; + Expr *p = pS->pEList->a[0].pExpr; + assert( ExprHasProperty(pExpr, EP_xIsSelect) ); sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth); break; } #endif } -#ifdef SQLITE_ENABLE_COLUMN_METADATA +#ifdef SQLITE_ENABLE_COLUMN_METADATA if( pzOrigDb ){ assert( pzOrigTab && pzOrigCol ); *pzOrigDb = zOrigDb; *pzOrigTab = zOrigTab; *pzOrigCol = zOrigCol; } #endif + if( pEstWidth ) *pEstWidth = estWidth; return zType; } /* ** Generate code that will tell the VDBE the declaration types of columns @@ -145900,26 +118857,38 @@ const char *zType; #ifdef SQLITE_ENABLE_COLUMN_METADATA const char *zOrigDb = 0; const char *zOrigTab = 0; const char *zOrigCol = 0; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0); - /* The vdbe must make its own copy of the column-type and other + /* The vdbe must make its own copy of the column-type and other ** column specific strings, in case the schema is reset before this ** virtual machine is deleted. */ sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); #else - zType = columnType(&sNC, p, 0, 0, 0); + zType = columnType(&sNC, p, 0, 0, 0, 0); #endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } + +/* +** Return the Table objecct in the SrcList that has cursor iCursor. +** Or return NULL if no such Table object exists in the SrcList. +*/ +static Table *tableWithCursor(SrcList *pList, int iCursor){ + int j; + for(j=0; jnSrc; j++){ + if( pList->a[j].iCursor==iCursor ) return pList->a[j].pTab; + } + return 0; +} /* ** Compute the column names for a SELECT statement. ** @@ -145940,37 +118909,38 @@ ** 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. +** 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. */ -SQLITE_PRIVATE void sqlite3GenerateColumnNames( +static void generateColumnNames( Parse *pParse, /* Parser context */ - Select *pSelect /* Generate column names for this SELECT statement */ + SrcList *pTabList, /* The FROM clause of the SELECT */ + ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; int i; Table *pTab; - SrcList *pTabList; - ExprList *pEList; sqlite3 *db = pParse->db; - 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 */ - - if( pParse->colNamesSet ) return; - /* Column names are determined by the left-most term of a compound select */ - while( pSelect->pPrior ) pSelect = pSelect->pPrior; - TREETRACE(0x80,pParse,pSelect,("generating column names\n")); - pTabList = pSelect->pSrc; - pEList = pSelect->pEList; + 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 */ + if( pParse->explain ){ + return; + } +#endif + + if( pParse->colNamesSet || db->mallocFailed ) return; assert( v!=0 ); assert( pTabList!=0 ); pParse->colNamesSet = 1; fullName = (db->flags & SQLITE_FullColNames)!=0; srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName; @@ -145977,38 +118947,36 @@ sqlite3VdbeSetNumCols(v, pEList->nExpr); for(i=0; inExpr; i++){ 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 - || (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */ - if( pEList->a[i].zEName && pEList->a[i].fg.eEName==ENAME_NAME ){ + if( pEList->a[i].zName ){ /* An AS clause always takes first priority */ - char *zName = pEList->a[i].zEName; + char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); - }else if( srcName && p->op==TK_COLUMN ){ + }else if( srcName + && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) + && (pTab = tableWithCursor(pTabList, p->iTable))!=0 + ){ char *zCol; int iCol = p->iColumn; - pTab = p->y.pTab; - assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); if( iCol<0 ){ zCol = "rowid"; }else{ - zCol = pTab->aCol[iCol].zCnName; + zCol = pTab->aCol[iCol].zName; } if( fullName ){ char *zName = 0; zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); } }else{ - const char *z = pEList->a[i].zEName; + const char *z = pEList->a[i].zSpan; z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z); sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC); } } generateColumnTypes(pParse, pTabList, pEList); @@ -146032,11 +119000,11 @@ ** 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: sqlite3GenerateColumnNames() +** See Also: generateColumnNames() */ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( Parse *pParse, /* Parsing context */ ExprList *pEList, /* Expr list from which to derive column names */ i16 *pnCol, /* Write the number of columns here */ @@ -146048,229 +119016,171 @@ Column *aCol, *pCol; /* For looping over result columns */ int nCol; /* Number of columns in the result set */ char *zName; /* Column name */ int nName; /* Size of name in zName[] */ Hash ht; /* Hash table of column names */ - Table *pTab; sqlite3HashInit(&ht); if( pEList ){ nCol = pEList->nExpr; aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); testcase( aCol==0 ); - if( NEVER(nCol>32767) ) nCol = 32767; }else{ nCol = 0; aCol = 0; } assert( nCol==(i16)nCol ); *pnCol = nCol; *paCol = aCol; - for(i=0, pCol=aCol; inErr; i++, pCol++){ - struct ExprList_item *pX = &pEList->a[i]; - struct ExprList_item *pCollide; + for(i=0, pCol=aCol; imallocFailed; i++, pCol++){ /* Get an appropriate name for the column */ - if( (zName = pX->zEName)!=0 && pX->fg.eEName==ENAME_NAME ){ + if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS " phrase, use as the name */ }else{ - Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pX->pExpr); - while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){ + Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr); + while( pColExpr->op==TK_DOT ){ pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } - if( pColExpr->op==TK_COLUMN - && ALWAYS( ExprUseYTab(pColExpr) ) - && ALWAYS( pColExpr->y.pTab!=0 ) - ){ + if( pColExpr->op==TK_COLUMN && pColExpr->pTab!=0 ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; - pTab = pColExpr->y.pTab; + Table *pTab = pColExpr->pTab; if( iCol<0 ) iCol = pTab->iPKey; - zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid"; + zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; }else if( pColExpr->op==TK_ID ){ assert( !ExprHasProperty(pColExpr, EP_IntValue) ); zName = pColExpr->u.zToken; }else{ /* Use the original text of the column expression as its name */ - assert( zName==pX->zEName ); /* pointer comparison intended */ + zName = pEList->a[i].zSpan; } } - if( zName && !sqlite3IsTrueOrFalse(zName) ){ + if( zName ){ zName = sqlite3DbStrDup(db, zName); }else{ zName = sqlite3MPrintf(db,"column%d",i+1); } /* Make sure the column name is unique. If the name is not unique, ** append an integer to the name so that it becomes unique. */ cnt = 0; - while( zName && (pCollide = sqlite3HashFind(&ht, zName))!=0 ){ - if( pCollide->fg.bUsingTerm ){ - pCol->colFlags |= COLFLAG_NOEXPAND; - } + while( zName && sqlite3HashFind(&ht, zName)!=0 ){ nName = sqlite3Strlen30(zName); if( nName>0 ){ for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} if( zName[j]==':' ) nName = j; } zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); - sqlite3ProgressCheck(pParse); - if( cnt>3 ){ - sqlite3_randomness(sizeof(cnt), &cnt); - } - } - pCol->zCnName = zName; - pCol->hName = sqlite3StrIHash(zName); - if( pX->fg.bNoExpand ){ - pCol->colFlags |= COLFLAG_NOEXPAND; - } + if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); + } + pCol->zName = zName; sqlite3ColumnPropertiesFromName(0, pCol); - if( zName && sqlite3HashInsert(&ht, zName, pX)==pX ){ + if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ sqlite3OomFault(db); } } sqlite3HashClear(&ht); - if( pParse->nErr ){ + if( db->mallocFailed ){ for(j=0; jrc; + return SQLITE_NOMEM_BKPT; } return SQLITE_OK; } /* -** pTab is a transient Table object that represents a subquery of some -** kind (maybe a parenthesized subquery in the FROM clause of a larger -** query, or a VIEW, or a CTE). This routine computes type information -** for that Table object based on the Select object that implements the -** subquery. For the purposes of this routine, "type information" means: +** Add type and collation information to a column list based on +** a SELECT statement. +** +** The column list presumably came from selectColumnNamesFromExprList(). +** The column list has only names, not types or collations. This +** routine goes through and adds the types and collations. ** -** * The datatype name, as it might appear in a CREATE TABLE statement -** * Which collating sequence to use for the column -** * The affinity of the column +** This routine requires that all identifiers in the SELECT +** statement be resolved. */ -SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( - Parse *pParse, /* Parsing contexts */ - Table *pTab, /* Add column type information to this table */ - Select *pSelect, /* SELECT used to determine types and collations */ - char aff /* Default affinity. */ +SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation( + Parse *pParse, /* Parsing contexts */ + Table *pTab, /* Add column type information to this table */ + Select *pSelect /* SELECT used to determine types and collations */ ){ sqlite3 *db = pParse->db; + NameContext sNC; Column *pCol; CollSeq *pColl; - int i,j; + int i; Expr *p; struct ExprList_item *a; - NameContext sNC; + u64 szAll = 0; assert( pSelect!=0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 ); - assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); - assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); - if( db->mallocFailed || IN_RENAME_OBJECT ) return; - while( pSelect->pPrior ) pSelect = pSelect->pPrior; - a = pSelect->pEList->a; + assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); + if( db->mallocFailed ) return; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; + a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ const char *zType; - i64 n; - int m = 0; - Select *pS2 = pSelect; - pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); + int n, m; p = a[i].pExpr; - /* pCol->szEst = ... // Column size est for SELECT tables never used */ + zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); + szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); - while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){ - m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); - pS2 = pS2->pNext; - pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr); - } - if( pCol->affinity<=SQLITE_AFF_NONE ){ - pCol->affinity = aff; - } - if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){ - for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){ - m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); - } - if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ - pCol->affinity = SQLITE_AFF_BLOB; - }else - if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){ - pCol->affinity = SQLITE_AFF_BLOB; - } - if( pCol->affinity>=SQLITE_AFF_NUMERIC && p->op==TK_CAST ){ - pCol->affinity = SQLITE_AFF_FLEXNUM; - } - } - zType = columnType(&sNC, p, 0, 0, 0); - if( zType==0 || pCol->affinity!=sqlite3AffinityType(zType, 0) ){ - if( pCol->affinity==SQLITE_AFF_NUMERIC - || pCol->affinity==SQLITE_AFF_FLEXNUM - ){ - zType = "NUM"; - }else{ - zType = 0; - for(j=1; jaffinity ){ - zType = sqlite3StdType[j]; - break; - } - } - } - } - if( zType ){ - const i64 k = sqlite3Strlen30(zType); - n = sqlite3Strlen30(pCol->zCnName); - pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2); - pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); - if( pCol->zCnName ){ - memcpy(&pCol->zCnName[n+1], zType, k+1); + if( zType && (m = sqlite3Strlen30(zType))>0 ){ + n = sqlite3Strlen30(pCol->zName); + pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2); + if( pCol->zName ){ + memcpy(&pCol->zName[n+1], zType, m+1); pCol->colFlags |= COLFLAG_HASTYPE; } } + if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; pColl = sqlite3ExprCollSeq(pParse, p); - if( pColl ){ - assert( pTab->pIndex==0 ); - sqlite3ColumnSetColl(db, pCol, pColl->zName); + if( pColl && pCol->zColl==0 ){ + pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } - pTab->szTabRow = 1; /* Any non-zero value works */ + pTab->szTabRow = sqlite3LogEst(szAll*4); } /* ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ -SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){ +SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ Table *pTab; sqlite3 *db = pParse->db; - u64 savedFlags; + int savedFlags; savedFlags = db->flags; - db->flags &= ~(u64)SQLITE_FullColNames; + db->flags &= ~SQLITE_FullColNames; db->flags |= SQLITE_ShortColNames; sqlite3SelectPrep(pParse, pSelect, 0); - db->flags = savedFlags; if( pParse->nErr ) return 0; while( pSelect->pPrior ) pSelect = pSelect->pPrior; + db->flags = savedFlags; pTab = sqlite3DbMallocZero(db, sizeof(Table) ); if( pTab==0 ){ return 0; } + /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside + ** is disabled */ + assert( db->lookaside.bDisable ); pTab->nTabRef = 1; pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - sqlite3SubqueryColumnTypes(pParse, pTab, pSelect, aff); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); return 0; } @@ -146279,86 +119189,87 @@ /* ** Get a VDBE for the given parser context. Create a new one if necessary. ** If an error occurs, return NULL and leave a message in pParse. */ -SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ - if( pParse->pVdbe ){ - return pParse->pVdbe; - } +static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse); + if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1); if( pParse->pToplevel==0 && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) ){ pParse->okConstFactor = 1; } - return sqlite3VdbeCreate(pParse); + return v; +} +SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe; + return v ? v : allocVdbe(pParse); } /* ** Compute the iLimit and iOffset fields of the SELECT based on the -** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions +** pLimit and pOffset expressions. pLimit and pOffset hold the expressions ** that appear in the original SQL statement after the LIMIT and OFFSET -** keywords. Or NULL if those keywords are omitted. iLimit and iOffset -** are the integer memory register numbers for counters used to compute -** the limit and offset. If there is no limit and/or offset, then +** keywords. Or NULL if those keywords are omitted. iLimit and iOffset +** are the integer memory register numbers for counters used to compute +** the limit and offset. If there is no limit and/or offset, then ** iLimit and iOffset are negative. ** ** This routine changes the values of iLimit and iOffset only if -** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit -** and iOffset should have been preset to appropriate default values (zero) +** a limit or offset is defined by pLimit and pOffset. iLimit and +** iOffset should have been preset to appropriate default values (zero) ** prior to calling this routine. ** ** The iOffset register (if it exists) is initialized to the value ** of the OFFSET. The iLimit register is initialized to LIMIT. Register ** iOffset+1 is initialized to LIMIT+OFFSET. ** -** Only if pLimit->pLeft!=0 do the limit registers get +** Only if pLimit!=0 or pOffset!=0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple ** SELECT statements. */ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ Vdbe *v = 0; int iLimit = 0; int iOffset; int n; - Expr *pLimit = p->pLimit; - if( p->iLimit ) return; - /* + /* ** "LIMIT -1" always shows all rows. There is some ** controversy about what the correct behavior should be. ** The current implementation interprets "LIMIT 0" to mean ** no rows. */ - if( pLimit ){ - assert( pLimit->op==TK_LIMIT ); - assert( pLimit->pLeft!=0 ); + sqlite3ExprCacheClear(pParse); + assert( p->pOffset==0 || p->pLimit!=0 ); + if( p->pLimit ){ p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); assert( v!=0 ); - if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){ + if( sqlite3ExprIsInteger(p->pLimit, &n) ){ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment((v, "LIMIT counter")); if( n==0 ){ sqlite3VdbeGoto(v, iBreak); }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){ p->nSelectRow = sqlite3LogEst((u64)n); p->selFlags |= SF_FixedLimit; } }else{ - sqlite3ExprCode(pParse, pLimit->pLeft, iLimit); + sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); } - if( pLimit->pRight ){ + if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; pParse->nMem++; /* Allocate an extra register for limit+offset */ - sqlite3ExprCode(pParse, pLimit->pRight, iOffset); + sqlite3ExprCode(pParse, p->pOffset, iOffset); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); VdbeComment((v, "OFFSET counter")); sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); VdbeComment((v, "LIMIT+OFFSET")); } @@ -146400,11 +119311,11 @@ ** function is responsible for ensuring that this structure is eventually ** freed. */ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ ExprList *pOrderBy = p->pOrderBy; - int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0; + int nOrderBy = p->pOrderBy->nExpr; sqlite3 *db = pParse->db; KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); if( pRet ){ int i; for(i=0; ia[i].pExpr = sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); } assert( sqlite3KeyInfoIsWriteable(pRet) ); pRet->aColl[i] = pColl; - pRet->aSortFlags[i] = pOrderBy->a[i].fg.sortFlags; + pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder; } } return pRet; } @@ -146452,11 +119363,11 @@ ** ** If the compound query operator is UNION then no duplicate rows are ever ** inserted into the Queue table. The iDistinct table keeps a copy of all rows ** that have ever been inserted into Queue and causes duplicates to be ** discarded. If the operator is UNION ALL, then duplicates are allowed. -** +** ** If the query has an ORDER BY, then entries in the Queue table are kept in ** ORDER BY order and the first entry is extracted for each cycle. Without ** an ORDER BY, the Queue table is just a FIFO. ** ** If a LIMIT clause is provided, then the iteration stops after LIMIT rows @@ -146472,44 +119383,37 @@ SelectDest *pDest /* What to do with query results */ ){ SrcList *pSrc = p->pSrc; /* The FROM clause of the recursive query */ int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */ Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ - Select *pSetup; /* The setup query */ - Select *pFirstRec; /* Left-most recursive term */ + Select *pSetup = p->pPrior; /* The setup query */ int addrTop; /* Top of the loop */ int addrCont, addrBreak; /* CONTINUE and BREAK addresses */ int iCurrent = 0; /* The Current table */ int regCurrent; /* Register holding Current table */ int iQueue; /* The Queue table */ int iDistinct = 0; /* To ensure unique results if UNION */ int eDest = SRT_Fifo; /* How to write to Queue */ - SelectDest destQueue; /* SelectDest targeting the Queue table */ + SelectDest destQueue; /* SelectDest targetting the Queue table */ int i; /* Loop counter */ int rc; /* Result code */ ExprList *pOrderBy; /* The ORDER BY clause */ - Expr *pLimit; /* Saved LIMIT and OFFSET */ + Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */ int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ){ - sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries"); - return; - } -#endif - /* Obtain authorization to do a recursive query */ if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; /* Process the LIMIT and OFFSET clauses, if they exist */ - addrBreak = sqlite3VdbeMakeLabel(pParse); + addrBreak = sqlite3VdbeMakeLabel(v); p->nSelectRow = 320; /* 4 billion rows */ computeLimitRegisters(pParse, p, addrBreak); pLimit = p->pLimit; + pOffset = p->pOffset; regLimit = p->iLimit; regOffset = p->iOffset; - p->pLimit = 0; + p->pLimit = p->pOffset = 0; p->iLimit = p->iOffset = 0; pOrderBy = p->pOrderBy; /* Locate the cursor number of the Current table */ for(i=0; ALWAYS(inSrc); i++){ @@ -146549,30 +119453,12 @@ } /* Detach the ORDER BY clause from the compound SELECT */ p->pOrderBy = 0; - /* Figure out how many elements of the compound SELECT are part of the - ** recursive query. Make sure no recursive elements use aggregate - ** functions. Mark the recursive elements as UNION ALL even if they - ** are really UNION because the distinctness will be enforced by the - ** iDistinct table. pFirstRec is left pointing to the left-most - ** recursive term of the CTE. - */ - for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){ - if( pFirstRec->selFlags & SF_Aggregate ){ - sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); - goto end_of_recursive_query; - } - pFirstRec->op = TK_ALL; - if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break; - } - /* Store the results of the setup-query in Queue. */ - pSetup = pFirstRec->pPrior; pSetup->pNext = 0; - ExplainQueryPlan((pParse, 1, "SETUP")); rc = sqlite3Select(pParse, pSetup, &destQueue); pSetup->pNext = p; if( rc ) goto end_of_recursive_query; /* Find the next row in the Queue and output that row */ @@ -146586,13 +119472,13 @@ sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent); } sqlite3VdbeAddOp1(v, OP_Delete, iQueue); /* Output the single row in Current */ - addrCont = sqlite3VdbeMakeLabel(pParse); + addrCont = sqlite3VdbeMakeLabel(v); codeOffset(v, regOffset, addrCont); - selectInnerLoop(pParse, p, iCurrent, + selectInnerLoop(pParse, p, p->pEList, iCurrent, 0, 0, pDest, addrCont, addrBreak); if( regLimit ){ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); VdbeCoverage(v); } @@ -146599,24 +119485,28 @@ sqlite3VdbeResolveLabel(v, addrCont); /* Execute the recursive SELECT taking the single row in Current as ** the value for the recursive-table. Store the results in the Queue. */ - pFirstRec->pPrior = 0; - ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); - sqlite3Select(pParse, p, &destQueue); - assert( pFirstRec->pPrior==0 ); - pFirstRec->pPrior = pSetup; + if( p->selFlags & SF_Aggregate ){ + sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); + }else{ + p->pPrior = 0; + sqlite3Select(pParse, p, &destQueue); + assert( p->pPrior==0 ); + p->pPrior = pSetup; + } /* Keep running the loop until the Queue is empty */ sqlite3VdbeGoto(v, addrTop); sqlite3VdbeResolveLabel(v, addrBreak); end_of_recursive_query: sqlite3ExprListDelete(pParse->db, p->pOrderBy); p->pOrderBy = pOrderBy; p->pLimit = pLimit; + p->pOffset = pOffset; return; } #endif /* SQLITE_OMIT_CTE */ /* Forward references */ @@ -146631,69 +119521,54 @@ ** VALUES clause. By handling this as a special case, we avoid deep ** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT ** on a VALUES clause. ** ** Because the Select object originates from a VALUES clause: -** (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1 +** (1) It has no LIMIT or OFFSET ** (2) All terms are UNION ALL ** (3) There is no ORDER BY clause -** -** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES -** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))"). -** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case. -** Since the limit is exactly 1, we only need to evaluate the left-most VALUES. */ static int multiSelectValues( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ ){ + Select *pPrior; int nRow = 1; int rc = 0; - int bShowAll = p->pLimit==0; assert( p->selFlags & SF_MultiValue ); do{ assert( p->selFlags & SF_Values ); assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); + assert( p->pLimit==0 ); + assert( p->pOffset==0 ); assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin ) return -1; -#endif if( p->pPrior==0 ) break; assert( p->pPrior->pNext==p ); p = p->pPrior; - nRow += bShowAll; + nRow++; }while(1); - ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow, - nRow==1 ? "" : "S")); while( p ){ - selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1); - if( !bShowAll ) break; + pPrior = p->pPrior; + p->pPrior = 0; + rc = sqlite3Select(pParse, p, pDest); + p->pPrior = pPrior; + if( rc ) break; p->nSelectRow = nRow; p = p->pNext; } return rc; } -/* -** Return true if the SELECT statement which is known to be the recursive -** part of a recursive CTE still has its anchor terms attached. If the -** anchor terms have already been removed, then return false. -*/ -static int hasAnchor(Select *p){ - while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; } - return p!=0; -} - /* ** This routine is called to process a compound query form from ** two or more separate queries using UNION, UNION ALL, EXCEPT, or ** INTERSECT ** ** "p" points to the right-most of the two queries. the query on the ** left is p->pPrior. The left query could also be a compound query -** in which case this routine will be called recursively. +** in which case this routine will be called recursively. ** ** The results of the total query are to be written into a destination ** of type eDest with parameter iParm. ** ** Example 1: Consider a three-way compound SQL statement. @@ -146724,22 +119599,35 @@ Select *pPrior; /* Another SELECT immediately to our left */ Vdbe *v; /* Generate code to this VDBE */ SelectDest dest; /* Alternative data destination */ Select *pDelete = 0; /* Chain of simple selects to delete */ sqlite3 *db; /* Database connection */ +#ifndef SQLITE_OMIT_EXPLAIN + int iSub1 = 0; /* EQP id of left-hand query */ + int iSub2 = 0; /* EQP id of right-hand query */ +#endif /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. */ assert( p && p->pPrior ); /* Calling function guarantees this much */ assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION ); - assert( p->selFlags & SF_Compound ); db = pParse->db; pPrior = p->pPrior; dest = *pDest; - assert( pPrior->pOrderBy==0 ); - assert( pPrior->pLimit==0 ); + if( pPrior->pOrderBy ){ + sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + if( pPrior->pLimit ){ + sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } v = sqlite3GetVdbe(pParse); assert( v!=0 ); /* The VDBE already created by calling function */ /* Create the destination temporary table if necessary @@ -146752,263 +119640,260 @@ /* Special handling for a compound-select that originates as a VALUES clause. */ if( p->selFlags & SF_MultiValue ){ rc = multiSelectValues(pParse, p, &dest); - if( rc>=0 ) goto multi_select_end; - rc = SQLITE_OK; + goto multi_select_end; } /* Make sure all SELECTs in the statement have the same number of elements ** in their result sets. */ assert( p->pEList && pPrior->pEList ); assert( p->pEList->nExpr==pPrior->pEList->nExpr ); #ifndef SQLITE_OMIT_CTE - if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){ + if( p->selFlags & SF_Recursive ){ generateWithRecursiveQuery(pParse, p, &dest); }else #endif /* Compound SELECTs that have an ORDER BY clause are handled separately. */ if( p->pOrderBy ){ return multiSelectOrderBy(pParse, p, pDest); - }else{ - -#ifndef SQLITE_OMIT_EXPLAIN - if( pPrior->pPrior==0 ){ - ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); - ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); - } -#endif - - /* Generate code for the left and right SELECT statements. - */ - switch( p->op ){ - case TK_ALL: { - int addr = 0; - int nLimit = 0; /* Initialize to suppress harmless compiler warning */ - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = p->pLimit; - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); - rc = sqlite3Select(pParse, pPrior, &dest); - pPrior->pLimit = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); - VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_OffsetLimit, - p->iLimit, p->iOffset+1, p->iOffset); - } - } - ExplainQueryPlan((pParse, 1, "UNION ALL")); - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - if( p->pLimit - && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) - ){ - p->nSelectRow = sqlite3LogEst((u64)nLimit); - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - } - break; - } - case TK_EXCEPT: - case TK_UNION: { - int unionTab; /* Cursor number of the temp table holding result */ - u8 op = 0; /* One of the SRT_ operations to apply to self */ - int priorOp; /* The SRT_ operation to apply to prior selects */ - Expr *pLimit; /* Saved values of p->nLimit */ - int addr; - SelectDest uniondest; - - testcase( p->op==TK_EXCEPT ); - testcase( p->op==TK_UNION ); - priorOp = SRT_Union; - if( dest.eDest==priorOp ){ - /* We can reuse a temporary table generated by a SELECT to our - ** right. - */ - assert( p->pLimit==0 ); /* Not allowed on leftward elements */ - unionTab = dest.iSDParm; - }else{ - /* We will need to create our own temporary table to hold the - ** intermediate results. - */ - unionTab = pParse->nTab++; - assert( p->pOrderBy==0 ); - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - findRightmost(p)->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - } - - - /* Code the SELECT statements to our left - */ - assert( !pPrior->pOrderBy ); - sqlite3SelectDestInit(&uniondest, priorOp, unionTab); - TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); - rc = sqlite3Select(pParse, pPrior, &uniondest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT statement - */ - if( p->op==TK_EXCEPT ){ - op = SRT_Except; - }else{ - assert( p->op==TK_UNION ); - op = SRT_Union; - } - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - uniondest.eDest = op; - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", - sqlite3SelectOpName(p->op))); - TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); - rc = sqlite3Select(pParse, p, &uniondest); - testcase( rc!=SQLITE_OK ); - assert( p->pOrderBy==0 ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->pOrderBy = 0; - if( p->op==TK_UNION ){ - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->iLimit = 0; - p->iOffset = 0; - - /* Convert the data in the temporary table into whatever form - ** it is that we currently need. - */ - assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); - assert( p->pEList || db->mallocFailed ); - if( dest.eDest!=priorOp && db->mallocFailed==0 ){ - int iCont, iBreak, iStart; - iBreak = sqlite3VdbeMakeLabel(pParse); - iCont = sqlite3VdbeMakeLabel(pParse); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); - iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, unionTab, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); - } - break; - } - default: assert( p->op==TK_INTERSECT ); { - int tab1, tab2; - int iCont, iBreak, iStart; - Expr *pLimit; - int addr; - SelectDest intersectdest; - int r1; - - /* INTERSECT is different from the others since it requires - ** two temporary tables. Hence it has its own case. Begin - ** by allocating the tables we will need. - */ - tab1 = pParse->nTab++; - tab2 = pParse->nTab++; - assert( p->pOrderBy==0 ); - - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - findRightmost(p)->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - - /* Code the SELECTs to our left into temporary table "tab1". - */ - sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); - TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n")); - rc = sqlite3Select(pParse, pPrior, &intersectdest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT into temporary table "tab2" - */ - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); - assert( p->addrOpenEphm[1] == -1 ); - p->addrOpenEphm[1] = addr; - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - intersectdest.iSDParm = tab2; - ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", - sqlite3SelectOpName(p->op))); - TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n")); - rc = sqlite3Select(pParse, p, &intersectdest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - if( p->nSelectRow>pPrior->nSelectRow ){ - p->nSelectRow = pPrior->nSelectRow; - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - - /* Generate code to take the intersection of the two temporary - ** tables. - */ - if( rc ) break; - assert( p->pEList ); - iBreak = sqlite3VdbeMakeLabel(pParse); - iCont = sqlite3VdbeMakeLabel(pParse); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); - r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); - VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, tab1, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); - sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); - break; - } - } - - #ifndef SQLITE_OMIT_EXPLAIN - if( p->pNext==0 ){ - ExplainQueryPlanPop(pParse); - } - #endif - } - if( pParse->nErr ) goto multi_select_end; - - /* Compute collating sequences used by + }else + + /* Generate code for the left and right SELECT statements. + */ + switch( p->op ){ + case TK_ALL: { + int addr = 0; + int nLimit; + assert( !pPrior->pLimit ); + pPrior->iLimit = p->iLimit; + pPrior->iOffset = p->iOffset; + pPrior->pLimit = p->pLimit; + pPrior->pOffset = p->pOffset; + explainSetInteger(iSub1, pParse->iNextSelectId); + rc = sqlite3Select(pParse, pPrior, &dest); + p->pLimit = 0; + p->pOffset = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit ){ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); + VdbeComment((v, "Jump ahead if LIMIT reached")); + if( p->iOffset ){ + sqlite3VdbeAddOp3(v, OP_OffsetLimit, + p->iLimit, p->iOffset+1, p->iOffset); + } + } + explainSetInteger(iSub2, pParse->iNextSelectId); + rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + if( pPrior->pLimit + && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) + ){ + p->nSelectRow = sqlite3LogEst((u64)nLimit); + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temporary table holding result */ + u8 op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ + int addr; + SelectDest uniondest; + + testcase( p->op==TK_EXCEPT ); + testcase( p->op==TK_UNION ); + priorOp = SRT_Union; + if( dest.eDest==priorOp ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + assert( p->pLimit==0 ); /* Not allowed on leftward elements */ + assert( p->pOffset==0 ); /* Not allowed on leftward elements */ + unionTab = dest.iSDParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + assert( p->pOrderBy==0 ); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + } + + /* Code the SELECT statements to our left + */ + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + explainSetInteger(iSub1, pParse->iNextSelectId); + rc = sqlite3Select(pParse, pPrior, &uniondest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement + */ + if( p->op==TK_EXCEPT ){ + op = SRT_Except; + }else{ + assert( p->op==TK_UNION ); + op = SRT_Union; + } + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + uniondest.eDest = op; + explainSetInteger(iSub2, pParse->iNextSelectId); + rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); + /* Query flattening in sqlite3Select() might refill p->pOrderBy. + ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ + sqlite3ExprListDelete(db, p->pOrderBy); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->pOrderBy = 0; + if( p->op==TK_UNION ){ + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + p->iLimit = 0; + p->iOffset = 0; + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); + if( dest.eDest!=priorOp ){ + int iCont, iBreak, iStart; + assert( p->pEList ); + if( dest.eDest==SRT_Output ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, p->pEList, unionTab, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + default: assert( p->op==TK_INTERSECT ); { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit, *pOffset; + int addr; + SelectDest intersectdest; + int r1; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; + assert( p->pOrderBy==0 ); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + explainSetInteger(iSub1, pParse->iNextSelectId); + rc = sqlite3Select(pParse, pPrior, &intersectdest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + intersectdest.iSDParm = tab2; + explainSetInteger(iSub2, pParse->iNextSelectId); + rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + + /* Generate code to take the intersection of the two temporary + ** tables. + */ + assert( p->pEList ); + if( dest.eDest==SRT_Output ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, p->pEList, tab1, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; + } + } + + explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); + + /* Compute collating sequences used by ** temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. ** ** This section is run by the right-most SELECT statement only. ** SELECT statements to the left always skip this part. The right-most @@ -147021,11 +119906,10 @@ Select *pLoop; /* For looping through SELECT statements */ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ int nCol; /* Number of columns in result set */ assert( p->pNext==0 ); - assert( p->pEList!=0 ); nCol = p->pEList->nExpr; pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); if( !pKeyInfo ){ rc = SQLITE_NOMEM_BKPT; goto multi_select_end; @@ -147056,13 +119940,11 @@ } multi_select_end: pDest->iSdst = dest.iSdst; pDest->nSdst = dest.nSdst; - if( pDelete ){ - sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete); - } + sqlite3SelectDelete(db, pDelete); return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ /* @@ -147072,18 +119954,17 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ if( p->selFlags & SF_Values ){ sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); }else{ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", - sqlite3SelectOpName(p->op)); + " do not have the same number of result columns", selectOpName(p->op)); } } /* ** Code an output subroutine for a coroutine implementation of a -** SELECT statement. +** SELECT statment. ** ** The data to be output is contained in pIn->iSdst. There are ** pIn->nSdst columns to be output. pDest is where the output should ** be sent. ** @@ -147112,13 +119993,13 @@ Vdbe *v = pParse->pVdbe; int iContinue; int addr; addr = sqlite3VdbeCurrentAddr(v); - iContinue = sqlite3VdbeMakeLabel(pParse); + iContinue = sqlite3VdbeMakeLabel(v); - /* Suppress duplicates for UNION, EXCEPT, and INTERSECT + /* Suppress duplicates for UNION, EXCEPT, and INTERSECT */ if( regPrev ){ int addr1, addr2; addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, @@ -147156,31 +120037,26 @@ */ case SRT_Set: { int r1; testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, + sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1, pDest->zAffSdst, pIn->nSdst); + sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, pIn->iSdst, pIn->nSdst); - if( pDest->iSDParm2>0 ){ - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0, - pIn->iSdst, pIn->nSdst); - ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER")); - } sqlite3ReleaseTempReg(pParse, r1); break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out - ** of the scan loop. Note that the select might return multiple columns - ** if it is the RHS of a row-value IN operator. + ** of the scan loop. */ case SRT_Mem: { - testcase( pIn->nSdst>1 ); - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst); + assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); + sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ @@ -147199,17 +120075,18 @@ /* If none of the above, then the result destination must be ** SRT_Output. This routine is never called with any other ** destination other than the ones handled above or SRT_Output. ** - ** For SRT_Output, results are stored in a sequence of registers. + ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to ** return the next row of result. */ default: { assert( pDest->eDest==SRT_Output ); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); + sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); break; } } /* Jump to the end of the loop if the LIMIT is reached. @@ -147256,11 +120133,11 @@ ** ** EofA: Called when data is exhausted from selectA. ** ** EofB: Called when data is exhausted from selectB. ** -** The implementation of the latter five subroutines depend on which +** The implementation of the latter five subroutines depend on which ** is used: ** ** ** UNION ALL UNION EXCEPT INTERSECT ** ------------- ----------------- -------------- ----------------- @@ -147306,11 +120183,11 @@ ** Jump AltB, AeqB, AgtB ** End: ... ** ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not ** actually called using Gosub and they do not Return. EofA and EofB loop -** until all data is exhausted then jump to the "end" label. AltB, AeqB, +** until all data is exhausted then jump to the "end" labe. AltB, AeqB, ** and AgtB jump to either L2 or to one of EofA or EofB. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ @@ -147317,12 +120194,10 @@ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ ){ int i, j; /* Loop counters */ Select *pPrior; /* Another SELECT immediately to our left */ - Select *pSplit; /* Left-most SELECT in the right-hand group */ - int nSelect; /* Number of SELECT statements in the compound */ Vdbe *v; /* Generate code to this VDBE */ SelectDest destA; /* Destination for coroutine A */ SelectDest destB; /* Destination for coroutine B */ int regAddrA; /* Address register for select-A coroutine */ int regAddrB; /* Address register for select-B coroutine */ @@ -147343,32 +120218,37 @@ int regPrev; /* A range of registers to hold previous output */ int savedLimit; /* Saved value of p->iLimit */ int savedOffset; /* Saved value of p->iOffset */ int labelCmpr; /* Label for the start of the merge algorithm */ int labelEnd; /* Label for the end of the overall SELECT stmt */ - int addr1; /* Jump instructions that get retargeted */ + int addr1; /* Jump instructions that get retargetted */ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ KeyInfo *pKeyMerge; /* Comparison information for merging rows */ sqlite3 *db; /* Database connection */ ExprList *pOrderBy; /* The ORDER BY clause */ int nOrderBy; /* Number of terms in the ORDER BY clause */ - u32 *aPermute; /* Mapping from ORDER BY terms to result set columns */ + int *aPermute; /* Mapping from ORDER BY terms to result set columns */ +#ifndef SQLITE_OMIT_EXPLAIN + int iSub1; /* EQP id of left-hand query */ + int iSub2; /* EQP id of right-hand query */ +#endif assert( p->pOrderBy!=0 ); assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ db = pParse->db; v = pParse->pVdbe; assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */ - labelEnd = sqlite3VdbeMakeLabel(pParse); - labelCmpr = sqlite3VdbeMakeLabel(pParse); + labelEnd = sqlite3VdbeMakeLabel(v); + labelCmpr = sqlite3VdbeMakeLabel(v); /* Patch up the ORDER BY clause */ - op = p->op; - assert( p->pPrior->pOrderBy==0 ); + op = p->op; + pPrior = p->pPrior; + assert( pPrior->pOrderBy==0 ); pOrderBy = p->pOrderBy; assert( pOrderBy ); nOrderBy = pOrderBy->nExpr; /* For operators other than UNION ALL we have to make sure that @@ -147377,11 +120257,10 @@ */ if( op!=TK_ALL ){ for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){ struct ExprList_item *pItem; for(j=0, pItem=pOrderBy->a; ju.x.iOrderByCol>0 ); if( pItem->u.x.iOrderByCol==i ) break; } if( j==nOrderBy ){ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); @@ -147399,25 +120278,29 @@ ** row of results comes from selectA or selectB. Also add explicit ** collations to the ORDER BY clause terms so that when the subqueries ** to the right and the left are evaluated, they use the correct ** collation. */ - aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1)); + aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1)); if( aPermute ){ struct ExprList_item *pItem; aPermute[0] = nOrderBy; for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ - assert( pItem!=0 ); assert( pItem->u.x.iOrderByCol>0 ); assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; } pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); }else{ pKeyMerge = 0; } + /* Reattach the ORDER BY clause to the query. + */ + p->pOrderBy = pOrderBy; + pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); + /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). */ if( op==TK_ALL ){ @@ -147431,41 +120314,23 @@ pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1); if( pKeyDup ){ assert( sqlite3KeyInfoIsWriteable(pKeyDup) ); for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i); - pKeyDup->aSortFlags[i] = 0; + pKeyDup->aSortOrder[i] = 0; } } } - + /* Separate the left and the right query from one another */ - nSelect = 1; - if( (op==TK_ALL || op==TK_UNION) - && OptimizationEnabled(db, SQLITE_BalancedMerge) - ){ - for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){ - nSelect++; - assert( pSplit->pPrior->pNext==pSplit ); - } - } - if( nSelect<=3 ){ - pSplit = p; - }else{ - pSplit = p; - for(i=2; ipPrior; } - } - pPrior = pSplit->pPrior; - assert( pPrior!=0 ); - pSplit->pPrior = 0; + p->pPrior = 0; pPrior->pNext = 0; - assert( p->pOrderBy == pOrderBy ); - assert( pOrderBy!=0 || db->mallocFailed ); - pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); - sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); + if( pPrior->pPrior==0 ){ + sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); + } /* Compute the limit registers */ computeLimitRegisters(pParse, p, labelEnd); if( p->iLimit && op==TK_ALL ){ regLimitA = ++pParse->nMem; @@ -147476,43 +120341,43 @@ }else{ regLimitA = regLimitB = 0; } sqlite3ExprDelete(db, p->pLimit); p->pLimit = 0; + sqlite3ExprDelete(db, p->pOffset); + p->pOffset = 0; regAddrA = ++pParse->nMem; regAddrB = ++pParse->nMem; regOutA = ++pParse->nMem; regOutB = ++pParse->nMem; sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); - ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlite3SelectOpName(p->op))); - /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. */ addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; - ExplainQueryPlan((pParse, 1, "LEFT")); + explainSetInteger(iSub1, pParse->iNextSelectId); sqlite3Select(pParse, pPrior, &destA); sqlite3VdbeEndCoroutine(v, regAddrA); sqlite3VdbeJumpHere(v, addr1); - /* Generate a coroutine to evaluate the SELECT statement on + /* Generate a coroutine to evaluate the SELECT statement on ** the right - the "B" select */ addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); VdbeComment((v, "right SELECT")); savedLimit = p->iLimit; savedOffset = p->iOffset; p->iLimit = regLimitB; - p->iOffset = 0; - ExplainQueryPlan((pParse, 1, "RIGHT")); + p->iOffset = 0; + explainSetInteger(iSub2, pParse->iNextSelectId); sqlite3Select(pParse, p, &destB); p->iLimit = savedLimit; p->iOffset = savedOffset; sqlite3VdbeEndCoroutine(v, regAddrB); @@ -147521,11 +120386,11 @@ */ VdbeNoopComment((v, "Output routine for A")); addrOutA = generateOutputSubroutine(pParse, p, &destA, pDest, regOutA, regPrev, pKeyDup, labelEnd); - + /* Generate a subroutine that outputs the current row of the B ** select as the next output row of the compound select. */ if( op==TK_ALL || op==TK_UNION ){ VdbeNoopComment((v, "Output routine for B")); @@ -147538,11 +120403,11 @@ /* Generate a subroutine to run when the results from select A ** are exhausted and only data in select B remains. */ if( op==TK_EXCEPT || op==TK_INTERSECT ){ addrEofA_noB = addrEofA = labelEnd; - }else{ + }else{ VdbeNoopComment((v, "eof-A subroutine")); addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); VdbeCoverage(v); sqlite3VdbeGoto(v, addrEofA); @@ -147553,11 +120418,11 @@ ** are exhausted and only data in select A remains. */ if( op==TK_INTERSECT ){ addrEofB = addrEofA; if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; - }else{ + }else{ VdbeNoopComment((v, "eof-B subroutine")); addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); sqlite3VdbeGoto(v, addrEofB); } @@ -147610,23 +120475,29 @@ /* Jump to the this point in order to terminate the query. */ sqlite3VdbeResolveLabel(v, labelEnd); - /* Make arrangements to free the 2nd and subsequent arms of the compound - ** after the parse has finished */ - if( pSplit->pPrior ){ - sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior); - } - pSplit->pPrior = pPrior; - pPrior->pNext = pSplit; - sqlite3ExprListDelete(db, pPrior->pOrderBy); - pPrior->pOrderBy = 0; + /* Set the number of output columns + */ + if( pDest->eDest==SRT_Output ){ + Select *pFirst = pPrior; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); + } + + /* Reassembly the compound query so that it will be freed correctly + ** by the calling function */ + if( p->pPrior ){ + sqlite3SelectDelete(db, p->pPrior); + } + p->pPrior = pPrior; + pPrior->pNext = p; /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ - ExplainQueryPlanPop(pParse); + explainComposite(pParse, p->op, iSub1, iSub2, 0); return pParse->nErr!=0; } #endif #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) @@ -147634,142 +120505,71 @@ /* An instance of the SubstContext object describes an substitution edit ** to be performed on a parse tree. ** ** All references to columns in table iTable are to be replaced by corresponding ** expressions in pEList. -** -** ## About "isOuterJoin": -** -** The isOuterJoin column indicates that the replacement will occur into a -** position in the parent that NULL-able due to an OUTER JOIN. Either the -** target slot in the parent is the right operand of a LEFT JOIN, or one of -** the left operands of a RIGHT JOIN. In either case, we need to potentially -** bypass the substituted expression with OP_IfNullRow. -** -** Suppose the original expression is an integer constant. Even though the table -** has the nullRow flag set, because the expression is an integer constant, -** it will not be NULLed out. So instead, we insert an OP_IfNullRow opcode -** that checks to see if the nullRow flag is set on the table. If the nullRow -** flag is set, then the value in the register is set to NULL and the original -** expression is bypassed. If the nullRow flag is not set, then the original -** expression runs to populate the register. -** -** Example where this is needed: -** -** CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT); -** CREATE TABLE t2(x INT UNIQUE); -** -** SELECT a,b,m,x FROM t1 LEFT JOIN (SELECT 59 AS m,x FROM t2) ON b=x; -** -** When the subquery on the right side of the LEFT JOIN is flattened, we -** have to add OP_IfNullRow in front of the OP_Integer that implements the -** "m" value of the subquery so that a NULL will be loaded instead of 59 -** when processing a non-matched row of the left. */ typedef struct SubstContext { Parse *pParse; /* The parsing context */ int iTable; /* Replace references to this table */ int iNewTable; /* New table number */ - int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ + int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ ExprList *pEList; /* Replacement expressions */ - ExprList *pCList; /* Collation sequences for replacement expr */ } SubstContext; /* Forward Declarations */ static void substExprList(SubstContext*, ExprList*); static void substSelect(SubstContext*, Select*, int); /* ** Scan through the expression pExpr. Replace every reference to ** a column in table number iTable with a copy of the iColumn-th -** entry in pEList. (But leave references to the ROWID column +** entry in pEList. (But leave references to the ROWID column ** unchanged.) ** ** This routine is part of the flattening procedure. A subquery ** whose result set is defined by pEList appears as entry in the ** FROM clause of a SELECT such that the VDBE cursor assigned to that -** FORM clause entry is iTable. This routine makes the necessary +** FORM clause entry is iTable. This routine makes the necessary ** changes to pExpr so that it refers directly to the source table ** of the subquery rather the result set of the subquery. */ static Expr *substExpr( SubstContext *pSubst, /* Description of the substitution */ Expr *pExpr /* Expr in which substitution occurs */ ){ if( pExpr==0 ) return 0; - if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) - && pExpr->w.iJoin==pSubst->iTable - ){ - testcase( ExprHasProperty(pExpr, EP_InnerON) ); - pExpr->w.iJoin = pSubst->iNewTable; - } - if( pExpr->op==TK_COLUMN - && pExpr->iTable==pSubst->iTable - && !ExprHasProperty(pExpr, EP_FixedCol) - ){ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){ + pExpr->iRightJoinTable = pSubst->iNewTable; + } + if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; - }else -#endif - { + }else{ Expr *pNew; - int iColumn; - Expr *pCopy; + Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr; Expr ifNullRow; - iColumn = pExpr->iColumn; - assert( iColumn>=0 ); - assert( pSubst->pEList!=0 && iColumnpEList->nExpr ); - assert( pExpr->pRight==0 ); - pCopy = pSubst->pEList->a[iColumn].pExpr; + assert( pSubst->pEList!=0 && pExpr->iColumnpEList->nExpr ); + assert( pExpr->pLeft==0 && pExpr->pRight==0 ); if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ sqlite3 *db = pSubst->pParse->db; - if( pSubst->isOuterJoin - && (pCopy->op!=TK_COLUMN || pCopy->iTable!=pSubst->iNewTable) - ){ + if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){ memset(&ifNullRow, 0, sizeof(ifNullRow)); ifNullRow.op = TK_IF_NULL_ROW; ifNullRow.pLeft = pCopy; ifNullRow.iTable = pSubst->iNewTable; - ifNullRow.iColumn = -99; - ifNullRow.flags = EP_IfNullRow; pCopy = &ifNullRow; } - testcase( ExprHasProperty(pCopy, EP_Subquery) ); pNew = sqlite3ExprDup(db, pCopy, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pNew); - return pExpr; - } - if( pSubst->isOuterJoin ){ + if( pNew && pSubst->isLeftJoin ){ ExprSetProperty(pNew, EP_CanBeNull); } - if( pNew->op==TK_TRUEFALSE ){ - pNew->u.iValue = sqlite3ExprTruthValue(pNew); - pNew->op = TK_INTEGER; - ExprSetProperty(pNew, EP_IntValue); - } - - /* Ensure that the expression now has an implicit collation sequence, - ** just as it did when it was a column of a view or sub-query. */ - { - CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew); - CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, - pSubst->pCList->a[iColumn].pExpr - ); - if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){ - pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew, - (pColl ? pColl->zName : "BINARY") - ); - } - } - ExprClearProperty(pNew, EP_Collate); - if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){ - sqlite3SetJoinExpr(pNew, pExpr->w.iJoin, - pExpr->flags & (EP_OuterON|EP_InnerON)); + if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){ + pNew->iRightJoinTable = pExpr->iRightJoinTable; + ExprSetProperty(pNew, EP_FromJoin); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; } } @@ -147777,23 +120577,15 @@ if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){ pExpr->iTable = pSubst->iNewTable; } pExpr->pLeft = substExpr(pSubst, pExpr->pLeft); pExpr->pRight = substExpr(pSubst, pExpr->pRight); - if( ExprUseXSelect(pExpr) ){ + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ substSelect(pSubst, pExpr->x.pSelect, 1); }else{ substExprList(pSubst, pExpr->x.pList); } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - Window *pWin = pExpr->y.pWin; - pWin->pFilter = substExpr(pSubst, pWin->pFilter); - substExprList(pSubst, pWin->pPartition); - substExprList(pSubst, pWin->pOrderBy); - } -#endif } return pExpr; } static void substExprList( SubstContext *pSubst, /* Description of the substitution */ @@ -147809,11 +120601,11 @@ SubstContext *pSubst, /* Description of the substitution */ Select *p, /* SELECT statement in which to make substitutions */ int doPrior /* Do substitutes on p->pPrior too */ ){ SrcList *pSrc; - SrcItem *pItem; + struct SrcList_item *pItem; int i; if( !p ) return; do{ substExprList(pSubst, p->pEList); substExprList(pSubst, p->pGroupBy); @@ -147821,192 +120613,19 @@ p->pHaving = substExpr(pSubst, p->pHaving); p->pWhere = substExpr(pSubst, p->pWhere); pSrc = p->pSrc; assert( pSrc!=0 ); for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( pItem->fg.isSubquery ){ - substSelect(pSubst, pItem->u4.pSubq->pSelect, 1); - } + substSelect(pSubst, pItem->pSelect, 1); if( pItem->fg.isTabFunc ){ substExprList(pSubst, pItem->u1.pFuncArg); } } }while( doPrior && (p = p->pPrior)!=0 ); } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -/* -** pSelect is a SELECT statement and pSrcItem is one item in the FROM -** clause of that SELECT. -** -** This routine scans the entire SELECT statement and recomputes the -** pSrcItem->colUsed mask. -*/ -static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){ - SrcItem *pItem; - if( pExpr->op!=TK_COLUMN ) return WRC_Continue; - pItem = pWalker->u.pSrcItem; - if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue; - if( pExpr->iColumn<0 ) return WRC_Continue; - pItem->colUsed |= sqlite3ExprColUsed(pExpr); - return WRC_Continue; -} -static void recomputeColumnsUsed( - Select *pSelect, /* The complete SELECT statement */ - SrcItem *pSrcItem /* Which FROM clause item to recompute */ -){ - Walker w; - if( NEVER(pSrcItem->pSTab==0) ) return; - memset(&w, 0, sizeof(w)); - w.xExprCallback = recomputeColumnsUsedExpr; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.u.pSrcItem = pSrcItem; - pSrcItem->colUsed = 0; - sqlite3WalkSelect(&w, pSelect); -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -/* -** Assign new cursor numbers to each of the items in pSrc. For each -** new cursor number assigned, set an entry in the aCsrMap[] array -** to map the old cursor number to the new: -** -** aCsrMap[iOld+1] = iNew; -** -** The array is guaranteed by the caller to be large enough for all -** existing cursor numbers in pSrc. aCsrMap[0] is the array size. -** -** If pSrc contains any sub-selects, call this routine recursively -** on the FROM clause of each such sub-select, with iExcept set to -1. -*/ -static void srclistRenumberCursors( - Parse *pParse, /* Parse context */ - int *aCsrMap, /* Array to store cursor mappings in */ - SrcList *pSrc, /* FROM clause to renumber */ - int iExcept /* FROM clause item to skip */ -){ - int i; - SrcItem *pItem; - for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){ - if( i!=iExcept ){ - Select *p; - assert( pItem->iCursor < aCsrMap[0] ); - if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){ - aCsrMap[pItem->iCursor+1] = pParse->nTab++; - } - pItem->iCursor = aCsrMap[pItem->iCursor+1]; - if( pItem->fg.isSubquery ){ - for(p=pItem->u4.pSubq->pSelect; p; p=p->pPrior){ - srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1); - } - } - } - } -} - -/* -** *piCursor is a cursor number. Change it if it needs to be mapped. -*/ -static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){ - int *aCsrMap = pWalker->u.aiCol; - int iCsr = *piCursor; - if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){ - *piCursor = aCsrMap[iCsr+1]; - } -} - -/* -** Expression walker callback used by renumberCursors() to update -** Expr objects to match newly assigned cursor numbers. -*/ -static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){ - int op = pExpr->op; - if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){ - renumberCursorDoMapping(pWalker, &pExpr->iTable); - } - if( ExprHasProperty(pExpr, EP_OuterON) ){ - renumberCursorDoMapping(pWalker, &pExpr->w.iJoin); - } - return WRC_Continue; -} - -/* -** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc) -** of the SELECT statement passed as the second argument, and to each -** cursor in the FROM clause of any FROM clause sub-selects, recursively. -** Except, do not assign a new cursor number to the iExcept'th element in -** the FROM clause of (*p). Update all expressions and other references -** to refer to the new cursor numbers. -** -** Argument aCsrMap is an array that may be used for temporary working -** space. Two guarantees are made by the caller: -** -** * the array is larger than the largest cursor number used within the -** select statement passed as an argument, and -** -** * the array entries for all cursor numbers that do *not* appear in -** FROM clauses of the select statement as described above are -** initialized to zero. -*/ -static void renumberCursors( - Parse *pParse, /* Parse context */ - Select *p, /* Select to renumber cursors within */ - int iExcept, /* FROM clause item to skip */ - int *aCsrMap /* Working space */ -){ - Walker w; - srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept); - memset(&w, 0, sizeof(w)); - w.u.aiCol = aCsrMap; - w.xExprCallback = renumberCursorsCb; - w.xSelectCallback = sqlite3SelectWalkNoop; - sqlite3WalkSelect(&w, p); -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -/* -** If pSel is not part of a compound SELECT, return a pointer to its -** expression list. Otherwise, return a pointer to the expression list -** of the leftmost SELECT in the compound. -*/ -static ExprList *findLeftmostExprlist(Select *pSel){ - while( pSel->pPrior ){ - pSel = pSel->pPrior; - } - return pSel->pEList; -} - -/* -** Return true if any of the result-set columns in the compound query -** have incompatible affinities on one or more arms of the compound. -*/ -static int compoundHasDifferentAffinities(Select *p){ - int ii; - ExprList *pList; - assert( p!=0 ); - assert( p->pEList!=0 ); - assert( p->pPrior!=0 ); - pList = p->pEList; - for(ii=0; iinExpr; ii++){ - char aff; - Select *pSub1; - assert( pList->a[ii].pExpr!=0 ); - aff = sqlite3ExprAffinity(pList->a[ii].pExpr); - for(pSub1=p->pPrior; pSub1; pSub1=pSub1->pPrior){ - assert( pSub1->pEList!=0 ); - assert( pSub1->pEList->nExpr>ii ); - assert( pSub1->pEList->a[ii].pExpr!=0 ); - if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){ - return 1; - } - } - } - return 0; -} - #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* ** This routine attempts to flatten subqueries as a performance optimization. ** This routine returns 1 if it makes changes and 0 if no flattening occurs. ** @@ -148026,91 +120645,75 @@ ** a single flat select, like this: ** ** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 ** ** The code generated for this simplification gives the same result -** but only has to scan the data once. And because indices might +** but only has to scan the data once. And because indices might ** exist on the table t1, a complete scan of the data might be ** avoided. ** -** Flattening is subject to the following constraints: -** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** The subquery and the outer query cannot both be aggregates. -** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** (2) If the subquery is an aggregate then -** (2a) the outer query must not be a join and -** (2b) the outer query must not use subqueries -** other than the one FROM-clause subquery that is a candidate -** for flattening. (This is due to ticket [2f7170d73bf9abf80] -** from 2015-02-09.) -** -** (3) If the subquery is the right operand of a LEFT JOIN then -** (3a) the subquery may not be a join and -** (3b) the FROM clause of the subquery may not contain a virtual -** table and -** (**) Was: "The outer query may not have a GROUP BY." This case -** is now managed correctly -** (3d) the outer query may not be DISTINCT. -** See also (26) for restrictions on RIGHT JOIN. -** -** (4) The subquery can not be DISTINCT. +** Flattening is only attempted if all of the following are true: +** +** (1) The subquery and the outer query do not both use aggregates. +** +** (2) The subquery is not an aggregate or (2a) the outer query is not a join +** and (2b) the outer query does not use subqueries other than the one +** FROM-clause subquery that is a candidate for flattening. (2b is +** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) +** +** (3) The subquery is not the right operand of a LEFT JOIN +** or the subquery is not itself a join and the outer query is not +** an aggregate. +** +** (4) The subquery is not DISTINCT. ** ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT -** sub-queries that were excluded from this optimization. Restriction +** sub-queries that were excluded from this optimization. Restriction ** (4) has since been expanded to exclude all DISTINCT subqueries. ** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** If the subquery is aggregate, the outer query may not be DISTINCT. +** (6) The subquery does not use aggregates or the outer query is not +** DISTINCT. ** -** (7) The subquery must have a FROM clause. TODO: For subqueries without +** (7) The subquery has a FROM clause. TODO: For subqueries without ** A FROM clause, consider adding a FROM clause with the special ** table sqlite_once that consists of a single row containing a ** single NULL. ** -** (8) If the subquery uses LIMIT then the outer query may not be a join. +** (8) The subquery does not use LIMIT or the outer query is not a join. ** -** (9) If the subquery uses LIMIT then the outer query may not be aggregate. +** (9) The subquery does not use LIMIT or the outer query does not use +** aggregates. ** ** (**) Restriction (10) was removed from the code on 2005-02-05 but we -** accidentally carried the comment forward until 2014-09-15. Original -** constraint: "If the subquery is aggregate then the outer query -** may not use LIMIT." +** accidently carried the comment forward until 2014-09-15. Original +** text: "The subquery does not use aggregates or the outer query +** does not use LIMIT." ** -** (11) The subquery and the outer query may not both have ORDER BY clauses. +** (11) The subquery and the outer query do not both have ORDER BY clauses. ** ** (**) Not implemented. Subsumed into restriction (3). Was previously ** a separate restriction deriving from ticket #350. ** -** (13) The subquery and outer query may not both use LIMIT. +** (13) The subquery and outer query do not both use LIMIT. ** -** (14) The subquery may not use OFFSET. +** (14) The subquery does not use OFFSET. ** -** (15) If the outer query is part of a compound select, then the -** subquery may not use LIMIT. +** (15) The outer query is not part of a compound select or the +** subquery does not have a LIMIT clause. ** (See ticket #2339 and ticket [02a8e81d44]). ** -** (16) If the outer query is aggregate, then the subquery may not -** use ORDER BY. (Ticket #2942) This used to not matter -** until we introduced the group_concat() function. +** (16) The outer query is not an aggregate or the subquery does +** not contain ORDER BY. (Ticket #2942) This used to not matter +** until we introduced the group_concat() function. ** -** (17) If the subquery is a compound select, then -** (17a) all compound operators must be a UNION ALL, and -** (17b) no terms within the subquery compound may be aggregate -** or DISTINCT, and -** (17c) every term within the subquery compound must have a FROM clause -** (17d) the outer query may not be -** (17d1) aggregate, or -** (17d2) DISTINCT -** (17e) the subquery may not contain window functions, and -** (17f) the subquery must not be the RHS of a LEFT JOIN. -** (17g) either the subquery is the first element of the outer -** query or there are no RIGHT or FULL JOINs in any arm -** of the subquery. (This is a duplicate of condition (27b).) -** (17h) The corresponding result set expressions in all arms of the -** compound must have the same affinity. +** (17) The sub-query is not a compound select, or it is a UNION ALL +** compound clause made up entirely of non-aggregate queries, and +** the parent query: +** +** * is not itself part of a compound select, +** * is not an aggregate or DISTINCT query, and +** * is not a join ** ** The parent and sub-query may contain WHERE clauses. Subject to ** rules (11), (13) and (14), they may also contain ORDER BY, ** LIMIT and OFFSET clauses. The subquery cannot use any compound ** operator other than UNION ALL because all the other compound @@ -148122,58 +120725,41 @@ ** SELECT statement, but all the code here does is make sure that no ** such (illegal) sub-query is flattened. The caller will detect the ** syntax error and return a detailed message. ** ** (18) If the sub-query is a compound select, then all terms of the -** ORDER BY clause of the parent must be copies of a term returned -** by the parent query. +** ORDER by clause of the parent must be simple references to +** columns of the sub-query. ** -** (19) If the subquery uses LIMIT then the outer query may not +** (19) The subquery does not use LIMIT or the outer query does not ** have a WHERE clause. ** ** (20) If the sub-query is a compound select, then it must not use ** an ORDER BY clause. Ticket #3773. We could relax this constraint ** somewhat by saying that the terms of the ORDER BY clause must ** appear as unmodified result columns in the outer query. But we ** have other optimizations in mind to deal with that case. ** -** (21) If the subquery uses LIMIT then the outer query may not be +** (21) The subquery does not use LIMIT or the outer query is not ** DISTINCT. (See ticket [752e1646fc]). ** -** (22) The subquery may not be a recursive CTE. +** (22) The subquery is not a recursive CTE. ** -** (23) If the outer query is a recursive CTE, then the sub-query may not be -** a compound query. This restriction is because transforming the +** (23) The parent is not a recursive CTE, or the sub-query is not a +** compound query. This restriction is because transforming the ** parent to a compound query confuses the code that handles ** recursive queries in multiSelect(). ** -** (**) We no longer attempt to flatten aggregate subqueries. Was: -** The subquery may not be an aggregate that uses the built-in min() or +** (24) The subquery is not an aggregate that uses the built-in min() or ** or max() functions. (Without this restriction, a query like: ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) ** -** (25) If either the subquery or the parent query contains a window -** function in the select list or ORDER BY clause, flattening -** is not attempted. -** -** (26) The subquery may not be the right operand of a RIGHT JOIN. -** See also (3) for restrictions on LEFT JOIN. -** -** (27) The subquery may not contain a FULL or RIGHT JOIN unless it -** is the first element of the parent query. Two subcases: -** (27a) the subquery is not a compound query. -** (27b) the subquery is a compound query and the RIGHT JOIN occurs -** in any arm of the compound query. (See also (17g).) -** -** (28) The subquery is not a MATERIALIZED CTE. (This is handled -** in the caller before ever reaching this routine.) -** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query -** uses aggregates. +** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. ** ** If flattening is not attempted, this routine is a no-op and returns 0. ** If flattening is attempted this routine returns 1. ** ** All of the expression analysis must occur on both the outer query and @@ -148181,199 +120767,174 @@ */ static int flattenSubquery( Parse *pParse, /* Parsing context */ Select *p, /* The parent or outer SELECT statement */ int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ - int isAgg /* True if outer SELECT uses aggregate functions */ + int isAgg, /* True if outer SELECT uses aggregate functions */ + int subqueryIsAgg /* True if the subquery uses aggregate functions */ ){ const char *zSavedAuthContext = pParse->zAuthContext; Select *pParent; /* Current UNION ALL term of the other query */ Select *pSub; /* The inner query or "subquery" */ Select *pSub1; /* Pointer to the rightmost select in sub-query */ SrcList *pSrc; /* The FROM clause of the outer query */ SrcList *pSubSrc; /* The FROM clause of the subquery */ + ExprList *pList; /* The result set of the outer query */ int iParent; /* VDBE cursor number of the pSub result set temp table */ int iNewParent = -1;/* Replacement table for iParent */ - int isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ + int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ int i; /* Loop counter */ Expr *pWhere; /* The WHERE clause */ - SrcItem *pSubitem; /* The subquery */ + struct SrcList_item *pSubitem; /* The subquery */ sqlite3 *db = pParse->db; - Walker w; /* Walker to persist agginfo data */ - int *aCsrMap = 0; /* Check to see if flattening is permitted. Return 0 if not. */ assert( p!=0 ); - assert( p->pPrior==0 ); + assert( p->pPrior==0 ); /* Unable to flatten compound queries */ if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; pSrc = p->pSrc; assert( pSrc && iFrom>=0 && iFromnSrc ); pSubitem = &pSrc->a[iFrom]; iParent = pSubitem->iCursor; - assert( pSubitem->fg.isSubquery ); - pSub = pSubitem->u4.pSubq->pSelect; + pSub = pSubitem->pSelect; assert( pSub!=0 ); - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */ -#endif + if( subqueryIsAgg ){ + if( isAgg ) return 0; /* Restriction (1) */ + if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ + if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) + || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 + || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 + ){ + return 0; /* Restriction (2b) */ + } + } pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET ** because they could be computed at compile-time. But when LIMIT and OFFSET ** became arbitrary expressions, we were forced to add restrictions (13) ** and (14). */ if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ - if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */ + if( pSub->pOffset ) return 0; /* Restriction (14) */ if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){ return 0; /* Restriction (15) */ } if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ - if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */ + if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */ if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ return 0; /* Restrictions (8)(9) */ + } + if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){ + return 0; /* Restriction (6) */ } if( p->pOrderBy && pSub->pOrderBy ){ return 0; /* Restriction (11) */ } if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */ if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */ if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ return 0; /* Restriction (21) */ } - if( pSub->selFlags & (SF_Recursive) ){ - return 0; /* Restrictions (22) */ + testcase( pSub->selFlags & SF_Recursive ); + testcase( pSub->selFlags & SF_MinMaxAgg ); + if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){ + return 0; /* Restrictions (22) and (24) */ + } + if( (p->selFlags & SF_Recursive) && pSub->pPrior ){ + return 0; /* Restriction (23) */ } /* ** If the subquery is the right operand of a LEFT JOIN, then the - ** subquery may not be a join itself (3a). Example of why this is not - ** allowed: + ** subquery may not be a join itself. Example of why this is not allowed: ** ** t1 LEFT OUTER JOIN (t2 JOIN t3) ** ** If we flatten the above, we would get ** ** (t1 LEFT OUTER JOIN t2) JOIN t3 ** ** which is not at all the same thing. + ** + ** If the subquery is the right operand of a LEFT JOIN, then the outer + ** query cannot be an aggregate. This is an artifact of the way aggregates + ** are processed - there is no mechanism to determine if the LEFT JOIN + ** table should be all-NULL. ** ** See also tickets #306, #350, and #3300. */ - if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ - if( pSubSrc->nSrc>1 /* (3a) */ - || IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */ - || (p->selFlags & SF_Distinct)!=0 /* (3d) */ - || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */ - ){ - return 0; - } - isOuterJoin = 1; - } - - assert( pSubSrc->nSrc>0 ); /* True by restriction (7) */ - if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ - return 0; /* Restriction (27a) */ - } - - /* Condition (28) is blocked by the caller */ - assert( !pSubitem->fg.isCte || pSubitem->u2.pCteUse->eM10d!=M10d_Yes ); - - /* Restriction (17): If the sub-query is a compound SELECT, then it must + if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ + isLeftJoin = 1; + if( pSubSrc->nSrc>1 || isAgg ){ + return 0; /* Restriction (3) */ + } + } +#ifdef SQLITE_EXTRA_IFNULLROW + else if( iFrom>0 && !isAgg ){ + /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for + ** every reference to any result column from subquery in a join, even though + ** they are not necessary. This will stress-test the OP_IfNullRow opcode. */ + isLeftJoin = -1; + } +#endif + + /* Restriction 17: If the sub-query is a compound SELECT, then it must ** use only the UNION ALL operator. And none of the simple select queries ** that make up the compound SELECT are allowed to be aggregate or distinct ** queries. */ if( pSub->pPrior ){ - int ii; if( pSub->pOrderBy ){ - return 0; /* Restriction (20) */ + return 0; /* Restriction 20 */ } - if( isAgg || (p->selFlags & SF_Distinct)!=0 || isOuterJoin>0 ){ - return 0; /* (17d1), (17d2), or (17f) */ + if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ + return 0; } for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); assert( pSub->pSrc!=0 ); - assert( (pSub->selFlags & SF_Recursive)==0 ); assert( pSub->pEList->nExpr==pSub1->pEList->nExpr ); - if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */ - || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */ - || pSub1->pSrc->nSrc<1 /* (17c) */ -#ifndef SQLITE_OMIT_WINDOWFUNC - || pSub1->pWin /* (17e) */ -#endif + if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 + || (pSub1->pPrior && pSub1->op!=TK_ALL) + || pSub1->pSrc->nSrc<1 ){ return 0; } - if( iFrom>0 && (pSub1->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ - /* Without this restriction, the JT_LTORJ flag would end up being - ** omitted on left-hand tables of the right join that is being - ** flattened. */ - return 0; /* Restrictions (17g), (27b) */ - } testcase( pSub1->pSrc->nSrc>1 ); } - /* Restriction (18). */ + /* Restriction 18. */ if( p->pOrderBy ){ + int ii; for(ii=0; iipOrderBy->nExpr; ii++){ if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0; } } - - /* Restriction (23) */ - if( (p->selFlags & SF_Recursive) ) return 0; - - /* Restriction (17h) */ - if( compoundHasDifferentAffinities(pSub) ) return 0; - - if( pSrc->nSrc>1 ){ - if( pParse->nSelect>500 ) return 0; - if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0; - aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int)); - if( aCsrMap ) aCsrMap[0] = pParse->nTab; - } } /***** If we reach this point, flattening is permitted. *****/ - TREETRACE(0x4,pParse,p,("flatten %u.%p from term %d\n", - pSub->selId, pSub, iFrom)); + SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", + pSub->zSelName, pSub, iFrom)); /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); testcase( i==SQLITE_DENY ); pParse->zAuthContext = zSavedAuthContext; - /* Delete the transient structures associated with the subquery */ - - if( ALWAYS(pSubitem->fg.isSubquery) ){ - pSub1 = sqlite3SubqueryDetach(db, pSubitem); - }else{ - pSub1 = 0; - } - assert( pSubitem->fg.isSubquery==0 ); - assert( pSubitem->fg.fixedSchema==0 ); - sqlite3DbFree(db, pSubitem->zName); - sqlite3DbFree(db, pSubitem->zAlias); - pSubitem->zName = 0; - pSubitem->zAlias = 0; - assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 ); - /* If the sub-query is a compound SELECT statement, then (by restrictions - ** 17 and 18 above) it must be a UNION ALL and the parent query must + ** 17 and 18 above) it must be a UNION ALL and the parent query must ** be of the form: ** - ** SELECT FROM () + ** SELECT FROM () ** ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block - ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or + ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or ** OFFSET clauses and joins them to the left-hand-side of the original ** using UNION ALL operators. In this case N is the number of simple ** select statements in the compound sub-query. ** ** Example: @@ -148399,63 +120960,71 @@ */ for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ Select *pNew; ExprList *pOrderBy = p->pOrderBy; Expr *pLimit = p->pLimit; + Expr *pOffset = p->pOffset; Select *pPrior = p->pPrior; - Table *pItemTab = pSubitem->pSTab; - pSubitem->pSTab = 0; p->pOrderBy = 0; + p->pSrc = 0; p->pPrior = 0; p->pLimit = 0; + p->pOffset = 0; pNew = sqlite3SelectDup(db, p, 0); + sqlite3SelectSetName(pNew, pSub->zSelName); + p->pOffset = pOffset; p->pLimit = pLimit; p->pOrderBy = pOrderBy; + p->pSrc = pSrc; p->op = TK_ALL; - pSubitem->pSTab = pItemTab; if( pNew==0 ){ p->pPrior = pPrior; }else{ - pNew->selId = ++pParse->nSelect; - if( aCsrMap && ALWAYS(db->mallocFailed==0) ){ - renumberCursors(pParse, pNew, iFrom, aCsrMap); - } pNew->pPrior = pPrior; if( pPrior ) pPrior->pNext = pNew; pNew->pNext = p; p->pPrior = pNew; - TREETRACE(0x4,pParse,p,("compound-subquery flattener" - " creates %u as peer\n",pNew->selId)); - } - assert( pSubitem->fg.isSubquery==0 ); - } - sqlite3DbFree(db, aCsrMap); - if( db->mallocFailed ){ - assert( pSubitem->fg.fixedSchema==0 ); - assert( pSubitem->fg.isSubquery==0 ); - assert( pSubitem->u4.zDatabase==0 ); - sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0); - return 1; - } + SELECTTRACE(2,pParse,p, + ("compound-subquery flattener creates %s.%p as peer\n", + pNew->zSelName, pNew)); + } + if( db->mallocFailed ) return 1; + } + + /* Begin flattening the iFrom-th entry of the FROM clause + ** in the outer query. + */ + pSub = pSub1 = pSubitem->pSelect; + + /* Delete the transient table structure associated with the + ** subquery + */ + sqlite3DbFree(db, pSubitem->zDatabase); + sqlite3DbFree(db, pSubitem->zName); + sqlite3DbFree(db, pSubitem->zAlias); + pSubitem->zDatabase = 0; + pSubitem->zName = 0; + pSubitem->zAlias = 0; + pSubitem->pSelect = 0; /* Defer deleting the Table object associated with the ** subquery until code generation is ** complete, since there may still exist Expr.pTab entries that ** refer to the subquery even after flattening. Ticket #3346. ** ** pSubitem->pTab is always non-NULL by test restrictions and tests above. */ - if( ALWAYS(pSubitem->pSTab!=0) ){ - Table *pTabToDel = pSubitem->pSTab; + if( ALWAYS(pSubitem->pTab!=0) ){ + Table *pTabToDel = pSubitem->pTab; if( pTabToDel->nTabRef==1 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel); - testcase( pToplevel->earlyCleanup ); + pTabToDel->pNextZombie = pToplevel->pZombieTab; + pToplevel->pZombieTab = pTabToDel; }else{ pTabToDel->nTabRef--; } - pSubitem->pSTab = 0; + pSubitem->pTab = 0; } /* The following loop runs once for each term in a compound-subquery ** flattening (as described above). If we are doing a different kind ** of flattening - a flattening other than a compound-subquery flattening - @@ -148467,22 +121036,27 @@ ** iParent. The iParent cursor will never be used. Subsequent code ** will scan expressions looking for iParent references and replace ** those references with expressions that resolve to the subquery FROM ** elements we are now copying in. */ - pSub = pSub1; for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ int nSubSrc; u8 jointype = 0; - u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ; - assert( pSub!=0 ); pSubSrc = pSub->pSrc; /* FROM clause of subquery */ nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ pSrc = pParent->pSrc; /* FROM clause of the outer query */ - if( pParent==p ){ - jointype = pSubitem->fg.jointype; /* First time through the loop */ + if( pSrc ){ + assert( pParent==p ); /* First time through the loop */ + jointype = pSubitem->fg.jointype; + }else{ + assert( pParent!=p ); /* 2nd and subsequent times through the loop */ + pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); + if( pSrc==0 ){ + assert( db->mallocFailed ); + break; + } } /* The subquery uses a single slot of the FROM clause of the outer ** query. If the subquery has more than one element in its FROM clause, ** then expand the outer query to make space for it to hold all elements @@ -148497,51 +121071,54 @@ ** block of code will expand the outer query FROM clause to 4 slots. ** The middle slot is expanded to two slots in order to make space ** for the two elements in the FROM clause of the subquery. */ if( nSubSrc>1 ){ - pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1); - if( pSrc==0 ) break; - pParent->pSrc = pSrc; + pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); + if( db->mallocFailed ){ + break; + } } /* Transfer the FROM clause terms from the subquery into the ** outer query. */ - iNewParent = pSubSrc->a[0].iCursor; for(i=0; ia[i+iFrom]; - assert( pItem->fg.isTabFunc==0 ); - assert( pItem->fg.isSubquery - || pItem->fg.fixedSchema - || pItem->u4.zDatabase==0 ); - if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing); - *pItem = pSubSrc->a[i]; - pItem->fg.jointype |= ltorj; + sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing); + assert( pSrc->a[i+iFrom].fg.isTabFunc==0 ); + pSrc->a[i+iFrom] = pSubSrc->a[i]; + iNewParent = pSubSrc->a[i].iCursor; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } - pSrc->a[iFrom].fg.jointype &= JT_LTORJ; - pSrc->a[iFrom].fg.jointype |= jointype | ltorj; - - /* Now begin substituting subquery result set expressions for + pSrc->a[iFrom].fg.jointype = jointype; + + /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. - ** + ** ** Example: ** ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; ** \ \_____________ subquery __________/ / ** \_____________________ outer query ______________________________/ ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ - if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){ + pList = pParent->pEList; + for(i=0; inExpr; i++){ + if( pList->a[i].zName==0 ){ + char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); + sqlite3Dequote(zName); + pList->a[i].zName = zName; + } + } + if( pSub->pOrderBy ){ /* At this point, any non-zero iOrderByCol values indicate that the ** ORDER BY column expression is identical to the iOrderByCol'th ** expression returned by SELECT statement pSub. Since these values ** do not necessarily correspond to columns in SELECT statement pParent, - ** zero them before transferring the ORDER BY clause. + ** zero them before transfering the ORDER BY clause. ** ** Not doing this may cause an error if a subsequent call to this ** function attempts to flatten a compound sub-query into pParent ** (the only way this can happen is if the compound sub-query is ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ @@ -148548,42 +121125,45 @@ ExprList *pOrderBy = pSub->pOrderBy; for(i=0; inExpr; i++){ pOrderBy->a[i].u.x.iOrderByCol = 0; } assert( pParent->pOrderBy==0 ); + assert( pSub->pPrior==0 ); pParent->pOrderBy = pOrderBy; pSub->pOrderBy = 0; } - pWhere = pSub->pWhere; - pSub->pWhere = 0; - if( isOuterJoin>0 ){ - assert( pSubSrc->nSrc==1 ); - sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON); - } - if( pWhere ){ - if( pParent->pWhere ){ - pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere); - }else{ - pParent->pWhere = pWhere; - } + pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); + if( isLeftJoin>0 ){ + setJoinExpr(pWhere, iNewParent); + } + if( subqueryIsAgg ){ + assert( pParent->pHaving==0 ); + pParent->pHaving = pParent->pWhere; + pParent->pWhere = pWhere; + pParent->pHaving = sqlite3ExprAnd(db, + sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving + ); + assert( pParent->pGroupBy==0 ); + pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); + }else{ + pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); } if( db->mallocFailed==0 ){ SubstContext x; x.pParse = pParse; x.iTable = iParent; x.iNewTable = iNewParent; - x.isOuterJoin = isOuterJoin; + x.isLeftJoin = isLeftJoin; x.pEList = pSub->pEList; - x.pCList = findLeftmostExprlist(pSub); substSelect(&x, pParent, 0); } - - /* The flattened query is a compound if either the inner or the - ** outer query is a compound. */ - pParent->selFlags |= pSub->selFlags & SF_Compound; - assert( (pSub->selFlags & SF_Distinct)==0 ); /* restriction (17b) */ - + + /* The flattened query is distinct if either the inner or the + ** outer query is distinct. + */ + pParent->selFlags |= pSub->selFlags & SF_Distinct; + /* ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; ** ** One is tempted to try to add a and b to combine the limits. But this ** does not work if either limit is negative. @@ -148590,333 +121170,29 @@ */ if( pSub->pLimit ){ pParent->pLimit = pSub->pLimit; pSub->pLimit = 0; } - - /* Recompute the SrcItem.colUsed masks for the flattened - ** tables. */ - for(i=0; ia[i+iFrom]); - } } - /* Finally, delete what is left of the subquery and return success. + /* Finially, delete what is left of the subquery and return + ** success. */ - sqlite3AggInfoPersistWalkerInit(&w, pParse); - sqlite3WalkSelect(&w,pSub1); sqlite3SelectDelete(db, pSub1); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x4 ){ - TREETRACE(0x4,pParse,p,("After flattening:\n")); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p,("After flattening:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ -/* -** A structure to keep track of all of the column values that are fixed to -** a known value due to WHERE clause constraints of the form COLUMN=VALUE. -*/ -typedef struct WhereConst WhereConst; -struct WhereConst { - Parse *pParse; /* Parsing context */ - u8 *pOomFault; /* Pointer to pParse->db->mallocFailed */ - int nConst; /* Number for COLUMN=CONSTANT terms */ - int nChng; /* Number of times a constant is propagated */ - int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */ - u32 mExcludeOn; /* Which ON expressions to exclude from considertion. - ** Either EP_OuterON or EP_InnerON|EP_OuterON */ - Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */ -}; - -/* -** Add a new entry to the pConst object. Except, do not add duplicate -** pColumn entries. Also, do not add if doing so would not be appropriate. -** -** The caller guarantees the pColumn is a column and pValue is a constant. -** This routine has to do some additional checks before completing the -** insert. -*/ -static void constInsert( - WhereConst *pConst, /* The WhereConst into which we are inserting */ - Expr *pColumn, /* The COLUMN part of the constraint */ - Expr *pValue, /* The VALUE part of the constraint */ - Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */ -){ - int i; - assert( pColumn->op==TK_COLUMN ); - assert( sqlite3ExprIsConstant(pConst->pParse, pValue) ); - - if( ExprHasProperty(pColumn, EP_FixedCol) ) return; - if( sqlite3ExprAffinity(pValue)!=0 ) return; - if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){ - return; - } - - /* 2018-10-25 ticket [cf5ed20f] - ** Make sure the same pColumn is not inserted more than once */ - for(i=0; inConst; i++){ - const Expr *pE2 = pConst->apExpr[i*2]; - assert( pE2->op==TK_COLUMN ); - if( pE2->iTable==pColumn->iTable - && pE2->iColumn==pColumn->iColumn - ){ - return; /* Already present. Return without doing anything. */ - } - } - if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){ - pConst->bHasAffBlob = 1; - } - - pConst->nConst++; - pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr, - pConst->nConst*2*sizeof(Expr*)); - if( pConst->apExpr==0 ){ - pConst->nConst = 0; - }else{ - pConst->apExpr[pConst->nConst*2-2] = pColumn; - pConst->apExpr[pConst->nConst*2-1] = pValue; - } -} - -/* -** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE -** is a constant expression and where the term must be true because it -** is part of the AND-connected terms of the expression. For each term -** found, add it to the pConst structure. -*/ -static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ - Expr *pRight, *pLeft; - if( NEVER(pExpr==0) ) return; - if( ExprHasProperty(pExpr, pConst->mExcludeOn) ){ - testcase( ExprHasProperty(pExpr, EP_OuterON) ); - testcase( ExprHasProperty(pExpr, EP_InnerON) ); - return; - } - if( pExpr->op==TK_AND ){ - findConstInWhere(pConst, pExpr->pRight); - findConstInWhere(pConst, pExpr->pLeft); - return; - } - if( pExpr->op!=TK_EQ ) return; - pRight = pExpr->pRight; - pLeft = pExpr->pLeft; - assert( pRight!=0 ); - assert( pLeft!=0 ); - if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){ - constInsert(pConst,pRight,pLeft,pExpr); - } - if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){ - constInsert(pConst,pLeft,pRight,pExpr); - } -} - -/* -** This is a helper function for Walker callback propagateConstantExprRewrite(). -** -** Argument pExpr is a candidate expression to be replaced by a value. If -** pExpr is equivalent to one of the columns named in pWalker->u.pConst, -** then overwrite it with the corresponding value. Except, do not do so -** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr -** is SQLITE_AFF_BLOB. -*/ -static int propagateConstantExprRewriteOne( - WhereConst *pConst, - Expr *pExpr, - int bIgnoreAffBlob -){ - int i; - if( pConst->pOomFault[0] ) return WRC_Prune; - if( pExpr->op!=TK_COLUMN ) return WRC_Continue; - if( ExprHasProperty(pExpr, EP_FixedCol|pConst->mExcludeOn) ){ - testcase( ExprHasProperty(pExpr, EP_FixedCol) ); - testcase( ExprHasProperty(pExpr, EP_OuterON) ); - testcase( ExprHasProperty(pExpr, EP_InnerON) ); - return WRC_Continue; - } - for(i=0; inConst; i++){ - Expr *pColumn = pConst->apExpr[i*2]; - if( pColumn==pExpr ) continue; - if( pColumn->iTable!=pExpr->iTable ) continue; - if( pColumn->iColumn!=pExpr->iColumn ) continue; - if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){ - break; - } - /* A match is found. Add the EP_FixedCol property */ - pConst->nChng++; - ExprClearProperty(pExpr, EP_Leaf); - ExprSetProperty(pExpr, EP_FixedCol); - assert( pExpr->pLeft==0 ); - pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0); - if( pConst->pParse->db->mallocFailed ) return WRC_Prune; - break; - } - return WRC_Prune; -} - -/* -** This is a Walker expression callback. pExpr is a node from the WHERE -** clause of a SELECT statement. This function examines pExpr to see if -** any substitutions based on the contents of pWalker->u.pConst should -** be made to pExpr or its immediate children. -** -** A substitution is made if: -** -** + pExpr is a column with an affinity other than BLOB that matches -** one of the columns in pWalker->u.pConst, or -** -** + pExpr is a binary comparison operator (=, <=, >=, <, >) that -** uses an affinity other than TEXT and one of its immediate -** children is a column that matches one of the columns in -** pWalker->u.pConst. -*/ -static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){ - WhereConst *pConst = pWalker->u.pConst; - assert( TK_GT==TK_EQ+1 ); - assert( TK_LE==TK_EQ+2 ); - assert( TK_LT==TK_EQ+3 ); - assert( TK_GE==TK_EQ+4 ); - if( pConst->bHasAffBlob ){ - if( (pExpr->op>=TK_EQ && pExpr->op<=TK_GE) - || pExpr->op==TK_IS - ){ - propagateConstantExprRewriteOne(pConst, pExpr->pLeft, 0); - if( pConst->pOomFault[0] ) return WRC_Prune; - if( sqlite3ExprAffinity(pExpr->pLeft)!=SQLITE_AFF_TEXT ){ - propagateConstantExprRewriteOne(pConst, pExpr->pRight, 0); - } - } - } - return propagateConstantExprRewriteOne(pConst, pExpr, pConst->bHasAffBlob); -} - -/* -** The WHERE-clause constant propagation optimization. -** -** If the WHERE clause contains terms of the form COLUMN=CONSTANT or -** CONSTANT=COLUMN that are top-level AND-connected terms that are not -** part of a ON clause from a LEFT JOIN, then throughout the query -** replace all other occurrences of COLUMN with CONSTANT. -** -** For example, the query: -** -** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b -** -** Is transformed into -** -** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=39 AND t3.c=39 -** -** Return true if any transformations where made and false if not. -** -** Implementation note: Constant propagation is tricky due to affinity -** and collating sequence interactions. Consider this example: -** -** CREATE TABLE t1(a INT,b TEXT); -** INSERT INTO t1 VALUES(123,'0123'); -** SELECT * FROM t1 WHERE a=123 AND b=a; -** SELECT * FROM t1 WHERE a=123 AND b=123; -** -** The two SELECT statements above should return different answers. b=a -** is always true because the comparison uses numeric affinity, but b=123 -** is false because it uses text affinity and '0123' is not the same as '123'. -** To work around this, the expression tree is not actually changed from -** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol -** and the "123" value is hung off of the pLeft pointer. Code generator -** routines know to generate the constant "123" instead of looking up the -** column value. Also, to avoid collation problems, this optimization is -** only attempted if the "a=123" term uses the default BINARY collation. -** -** 2021-05-25 forum post 6a06202608: Another troublesome case is... -** -** CREATE TABLE t1(x); -** INSERT INTO t1 VALUES(10.0); -** SELECT 1 FROM t1 WHERE x=10 AND x LIKE 10; -** -** The query should return no rows, because the t1.x value is '10.0' not '10' -** and '10.0' is not LIKE '10'. But if we are not careful, the first WHERE -** term "x=10" will cause the second WHERE term to become "10 LIKE 10", -** resulting in a false positive. To avoid this, constant propagation for -** columns with BLOB affinity is only allowed if the constant is used with -** operators ==, <=, <, >=, >, or IS in a way that will cause the correct -** type conversions to occur. See logic associated with the bHasAffBlob flag -** for details. -*/ -static int propagateConstants( - Parse *pParse, /* The parsing context */ - Select *p /* The query in which to propagate constants */ -){ - WhereConst x; - Walker w; - int nChng = 0; - x.pParse = pParse; - x.pOomFault = &pParse->db->mallocFailed; - do{ - x.nConst = 0; - x.nChng = 0; - x.apExpr = 0; - x.bHasAffBlob = 0; - if( ALWAYS(p->pSrc!=0) - && p->pSrc->nSrc>0 - && (p->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 - ){ - /* Do not propagate constants on any ON clause if there is a - ** RIGHT JOIN anywhere in the query */ - x.mExcludeOn = EP_InnerON | EP_OuterON; - }else{ - /* Do not propagate constants through the ON clause of a LEFT JOIN */ - x.mExcludeOn = EP_OuterON; - } - findConstInWhere(&x, p->pWhere); - if( x.nConst ){ - memset(&w, 0, sizeof(w)); - w.pParse = pParse; - w.xExprCallback = propagateConstantExprRewrite; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.xSelectCallback2 = 0; - w.walkerDepth = 0; - w.u.pConst = &x; - sqlite3WalkExpr(&w, p->pWhere); - sqlite3DbFree(x.pParse->db, x.apExpr); - nChng += x.nChng; - } - }while( x.nChng ); - return nChng; -} - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -# if !defined(SQLITE_OMIT_WINDOWFUNC) -/* -** This function is called to determine whether or not it is safe to -** push WHERE clause expression pExpr down to FROM clause sub-query -** pSubq, which contains at least one window function. Return 1 -** if it is safe and the expression should be pushed down, or 0 -** otherwise. -** -** It is only safe to push the expression down if it consists only -** of constants and copies of expressions that appear in the PARTITION -** BY clause of all window function used by the sub-query. It is safe -** to filter out entire partitions, but not rows within partitions, as -** this may change the results of the window functions. -** -** At the time this function is called it is guaranteed that -** -** * the sub-query uses only one distinct window frame, and -** * that the window frame has a PARTITION BY clause. -*/ -static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ - assert( pSubq->pWin->pPartition ); - assert( (pSubq->selFlags & SF_MultiPart)==0 ); - assert( pSubq->pPrior==0 ); - return sqlite3ExprIsConstantOrGroupBy(pParse, pExpr, pSubq->pWin->pPartition); -} -# endif /* SQLITE_OMIT_WINDOWFUNC */ -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ + #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* ** Make copies of relevant WHERE clause terms of the outer query into ** the WHERE clause of subquery. Example: @@ -148929,462 +121205,178 @@ ** WHERE x=5 AND y=10; ** ** The hope is that the terms added to the inner query will make it more ** efficient. ** -** NAME AMBIGUITY -** -** This optimization is called the "WHERE-clause push-down optimization" -** or sometimes the "predicate push-down optimization". -** -** Do not confuse this optimization with another unrelated optimization -** with a similar name: The "MySQL push-down optimization" causes WHERE -** clause terms that can be evaluated using only the index and without -** reference to the table are run first, so that if they are false, -** unnecessary table seeks are avoided. -** -** RULES -** ** Do not attempt this optimization if: ** -** (1) (** This restriction was removed on 2017-09-29. We used to -** disallow this optimization for aggregate subqueries, but now -** it is allowed by putting the extra terms on the HAVING clause. -** The added HAVING clause is pointless if the subquery lacks -** a GROUP BY clause. But such a HAVING clause is also harmless -** so there does not appear to be any reason to add extra logic -** to suppress it. **) +** (1) The inner query is an aggregate. (In that case, we'd really want +** to copy the outer WHERE-clause terms onto the HAVING clause of the +** inner query. But they probably won't help there so do not bother.) ** ** (2) The inner query is the recursive part of a common table expression. ** ** (3) The inner query has a LIMIT clause (since the changes to the WHERE -** clause would change the meaning of the LIMIT). +** close would change the meaning of the LIMIT). ** -** (4) The inner query is the right operand of a LEFT JOIN and the -** expression to be pushed down does not come from the ON clause -** on that LEFT JOIN. +** (4) The inner query is the right operand of a LEFT JOIN. (The caller +** enforces this restriction since this routine does not have enough +** information to know.) ** ** (5) The WHERE clause expression originates in the ON or USING clause -** of a LEFT JOIN where iCursor is not the right-hand table of that -** left join. An example: -** -** SELECT * -** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa -** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2) -** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2); -** -** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9). -** But if the (b2=2) term were to be pushed down into the bb subquery, -** then the (1,1,NULL) row would be suppressed. -** -** (6) Window functions make things tricky as changes to the WHERE clause -** of the inner query could change the window over which window -** functions are calculated. Therefore, do not attempt the optimization -** if: -** -** (6a) The inner query uses multiple incompatible window partitions. -** -** (6b) The inner query is a compound and uses window-functions. -** -** (6c) The WHERE clause does not consist entirely of constants and -** copies of expressions found in the PARTITION BY clause of -** all window-functions used by the sub-query. It is safe to -** filter out entire partitions, as this does not change the -** window over which any window-function is calculated. -** -** (7) The inner query is a Common Table Expression (CTE) that should -** be materialized. (This restriction is implemented in the calling -** routine.) -** -** (8) If the subquery is a compound that uses UNION, INTERSECT, -** or EXCEPT, then all of the result set columns for all arms of -** the compound must use the BINARY collating sequence. -** -** (9) All three of the following are true: -** -** (9a) The WHERE clause expression originates in the ON or USING clause -** of a join (either an INNER or an OUTER join), and -** -** (9b) The subquery is to the right of the ON/USING clause -** -** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING -** clause and the subquery. -** -** Without this restriction, the WHERE-clause push-down optimization -** might move the ON/USING filter expression from the left side of a -** RIGHT JOIN over to the right side, which leads to incorrect answers. -** See also restriction (6) in sqlite3ExprIsSingleTableConstraint(). -** -** (10) The inner query is not the right-hand table of a RIGHT JOIN. -** -** (11) The subquery is not a VALUES clause -** -** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This -** case only comes up if SQLite is compiled using -** SQLITE_ALLOW_ROWID_IN_VIEW. +** of a LEFT JOIN. ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ - SrcList *pSrcList, /* The complete from clause of the outer query */ - int iSrc /* Which FROM clause term to try to push into */ + int iCursor /* Cursor number of the subquery */ ){ Expr *pNew; - SrcItem *pSrc; /* The subquery FROM term into which WHERE is pushed */ int nChng = 0; - pSrc = &pSrcList->a[iSrc]; + Select *pX; /* For looping over compound SELECTs in pSubq */ if( pWhere==0 ) return 0; - if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ){ - return 0; /* restrictions (2) and (11) */ - } - if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ){ - return 0; /* restrictions (10) */ - } - - if( pSubq->pPrior ){ - Select *pSel; - int notUnionAll = 0; - for(pSel=pSubq; pSel; pSel=pSel->pPrior){ - u8 op = pSel->op; - assert( op==TK_ALL || op==TK_SELECT - || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT ); - if( op!=TK_ALL && op!=TK_SELECT ){ - notUnionAll = 1; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pSel->pWin ) return 0; /* restriction (6b) */ -#endif - } - if( notUnionAll ){ - /* If any of the compound arms are connected using UNION, INTERSECT, - ** or EXCEPT, then we must ensure that none of the columns use a - ** non-BINARY collating sequence. */ - for(pSel=pSubq; pSel; pSel=pSel->pPrior){ - int ii; - const ExprList *pList = pSel->pEList; - assert( pList!=0 ); - for(ii=0; iinExpr; ii++){ - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[ii].pExpr); - if( !sqlite3IsBinary(pColl) ){ - return 0; /* Restriction (8) */ - } - } - } - } - }else{ -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0; -#endif - } - -#ifdef SQLITE_DEBUG - /* Only the first term of a compound can have a WITH clause. But make - ** sure no other terms are marked SF_Recursive in case something changes - ** in the future. - */ - { - Select *pX; - for(pX=pSubq; pX; pX=pX->pPrior){ - assert( (pX->selFlags & (SF_Recursive))==0 ); - } - } -#endif - + for(pX=pSubq; pX; pX=pX->pPrior){ + if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ + testcase( pX->selFlags & SF_Aggregate ); + testcase( pX->selFlags & SF_Recursive ); + testcase( pX!=pSubq ); + return 0; /* restrictions (1) and (2) */ + } + } if( pSubq->pLimit!=0 ){ return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrcList, iSrc); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); pWhere = pWhere->pLeft; } - -#if 0 /* These checks now done by sqlite3ExprIsSingleTableConstraint() */ - if( ExprHasProperty(pWhere, EP_OuterON|EP_InnerON) /* (9a) */ - && (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (9c) */ - ){ - int jj; - for(jj=0; jjw.iJoin==pSrcList->a[jj].iCursor ){ - /* If we reach this point, both (9a) and (9b) are satisfied. - ** The following loop checks (9c): - */ - for(jj++; jja[jj].fg.jointype & JT_RIGHT)!=0 ){ - return 0; /* restriction (9) */ - } - } - } - } - } - if( isLeftJoin - && (ExprHasProperty(pWhere,EP_OuterON)==0 - || pWhere->w.iJoin!=iCursor) - ){ - return 0; /* restriction (4) */ - } - if( ExprHasProperty(pWhere,EP_OuterON) - && pWhere->w.iJoin!=iCursor - ){ - return 0; /* restriction (5) */ - } -#endif - -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){ - Expr *pLeft = pWhere->pLeft; - if( ALWAYS(pLeft) - && pLeft->op==TK_COLUMN - && pLeft->iColumn < 0 - ){ - return 0; /* Restriction (12) */ - } - } -#endif - - if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){ + if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ + if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ nChng++; - pSubq->selFlags |= SF_PushDown; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); - unsetJoinExpr(pNew, -1, 1); x.pParse = pParse; - x.iTable = pSrc->iCursor; - x.iNewTable = pSrc->iCursor; - x.isOuterJoin = 0; + x.iTable = iCursor; + x.iNewTable = iCursor; + x.isLeftJoin = 0; x.pEList = pSubq->pEList; - x.pCList = findLeftmostExprlist(pSubq); pNew = substExpr(&x, pNew); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){ - /* Restriction 6c has prevented push-down in this case */ - sqlite3ExprDelete(pParse->db, pNew); - nChng--; - break; - } -#endif - if( pSubq->selFlags & SF_Aggregate ){ - pSubq->pHaving = sqlite3ExprAnd(pParse, pSubq->pHaving, pNew); - }else{ - pSubq->pWhere = sqlite3ExprAnd(pParse, pSubq->pWhere, pNew); - } + pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); pSubq = pSubq->pPrior; } } return nChng; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* -** Check to see if a subquery contains result-set columns that are -** never used. If it does, change the value of those result-set columns -** to NULL so that they do not cause unnecessary work to compute. -** -** Return the number of column that were changed to NULL. -*/ -static int disableUnusedSubqueryResultColumns(SrcItem *pItem){ - int nCol; - Select *pSub; /* The subquery to be simplified */ - Select *pX; /* For looping over compound elements of pSub */ - Table *pTab; /* The table that describes the subquery */ - int j; /* Column number */ - int nChng = 0; /* Number of columns converted to NULL */ - Bitmask colUsed; /* Columns that may not be NULLed out */ - - assert( pItem!=0 ); - if( pItem->fg.isCorrelated || pItem->fg.isCte ){ - return 0; - } - assert( pItem->pSTab!=0 ); - pTab = pItem->pSTab; - assert( pItem->fg.isSubquery ); - pSub = pItem->u4.pSubq->pSelect; - assert( pSub->pEList->nExpr==pTab->nCol ); - for(pX=pSub; pX; pX=pX->pPrior){ - if( (pX->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){ - testcase( pX->selFlags & SF_Distinct ); - testcase( pX->selFlags & SF_Aggregate ); - return 0; - } - if( pX->pPrior && pX->op!=TK_ALL ){ - /* This optimization does not work for compound subqueries that - ** use UNION, INTERSECT, or EXCEPT. Only UNION ALL is allowed. */ - return 0; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pX->pWin ){ - /* This optimization does not work for subqueries that use window - ** functions. */ - return 0; - } -#endif - } - colUsed = pItem->colUsed; - if( pSub->pOrderBy ){ - ExprList *pList = pSub->pOrderBy; - for(j=0; jnExpr; j++){ - u16 iCol = pList->a[j].u.x.iOrderByCol; - if( iCol>0 ){ - iCol--; - colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); - } - } - } - nCol = pTab->nCol; - for(j=0; jpPrior) { - Expr *pY = pX->pEList->a[j].pExpr; - if( pY->op==TK_NULL ) continue; - pY->op = TK_NULL; - ExprClearProperty(pY, EP_Skip|EP_Unlikely); - pX->selFlags |= SF_PushDown; - nChng++; - } - } - return nChng; -} - - -/* -** The pFunc is the only aggregate function in the query. Check to see -** if the query is a candidate for the min/max optimization. -** -** If the query is a candidate for the min/max optimization, then set -** *ppMinMax to be an ORDER BY clause to be used for the optimization -** and return either WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX depending on -** whether pFunc is a min() or max() function. -** -** If the query is not a candidate for the min/max optimization, return -** WHERE_ORDERBY_NORMAL (which must be zero). -** -** This routine must be called after aggregate functions have been -** located but before their arguments have been subjected to aggregate -** analysis. -*/ -static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ - int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ - ExprList *pEList; /* Arguments to agg function */ - const char *zFunc; /* Name of aggregate function pFunc */ - ExprList *pOrderBy; - u8 sortFlags = 0; - - assert( *ppMinMax==0 ); - assert( pFunc->op==TK_AGG_FUNCTION ); - assert( !IsWindowFunc(pFunc) ); - assert( ExprUseXList(pFunc) ); - pEList = pFunc->x.pList; - if( pEList==0 - || pEList->nExpr!=1 - || ExprHasProperty(pFunc, EP_WinFunc) - || OptimizationDisabled(db, SQLITE_MinMaxOpt) - ){ - return eRet; - } - assert( !ExprHasProperty(pFunc, EP_IntValue) ); - zFunc = pFunc->u.zToken; - if( sqlite3StrICmp(zFunc, "min")==0 ){ - eRet = WHERE_ORDERBY_MIN; - if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){ - sortFlags = KEYINFO_ORDER_BIGNULL; - } - }else if( sqlite3StrICmp(zFunc, "max")==0 ){ - eRet = WHERE_ORDERBY_MAX; - sortFlags = KEYINFO_ORDER_DESC; - }else{ - return eRet; - } - *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); - assert( pOrderBy!=0 || db->mallocFailed ); - if( pOrderBy ) pOrderBy->a[0].fg.sortFlags = sortFlags; +** Based on the contents of the AggInfo structure indicated by the first +** argument, this function checks if the following are true: +** +** * the query contains just a single aggregate function, +** * the aggregate function is either min() or max(), and +** * the argument to the aggregate function is a column value. +** +** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX +** is returned as appropriate. Also, *ppMinMax is set to point to the +** list of arguments passed to the aggregate before returning. +** +** Or, if the conditions above are not met, *ppMinMax is set to 0 and +** WHERE_ORDERBY_NORMAL is returned. +*/ +static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ + int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ + + *ppMinMax = 0; + if( pAggInfo->nFunc==1 ){ + Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ + ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ + + assert( pExpr->op==TK_AGG_FUNCTION ); + if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ + const char *zFunc = pExpr->u.zToken; + if( sqlite3StrICmp(zFunc, "min")==0 ){ + eRet = WHERE_ORDERBY_MIN; + *ppMinMax = pEList; + }else if( sqlite3StrICmp(zFunc, "max")==0 ){ + eRet = WHERE_ORDERBY_MAX; + *ppMinMax = pEList; + } + } + } + + assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); return eRet; } /* ** The select statement passed as the first argument is an aggregate query. -** The second argument is the associated aggregate-info object. This +** The second argument is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** ** SELECT count(*) FROM ** ** where table is a database table, not a sub-select or view. If the query ** does match this pattern, then a pointer to the Table object representing -** is returned. Otherwise, NULL is returned. -** -** This routine checks to see if it is safe to use the count optimization. -** A correct answer is still obtained (though perhaps more slowly) if -** this routine returns NULL when it could have returned a table pointer. -** But returning the pointer when NULL should have been returned can -** result in incorrect answers and/or crashes. So, when in doubt, return NULL. +** is returned. Otherwise, 0 is returned. */ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ Table *pTab; Expr *pExpr; assert( !p->pGroupBy ); - if( p->pWhere - || p->pEList->nExpr!=1 - || p->pSrc->nSrc!=1 - || p->pSrc->a[0].fg.isSubquery - || pAggInfo->nFunc!=1 - || p->pHaving + if( p->pWhere || p->pEList->nExpr!=1 + || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect ){ return 0; } - pTab = p->pSrc->a[0].pSTab; - assert( pTab!=0 ); - assert( !IsView(pTab) ); - if( !IsOrdinaryTable(pTab) ) return 0; + pTab = p->pSrc->a[0].pTab; pExpr = p->pEList->a[0].pExpr; - assert( pExpr!=0 ); + assert( pTab && !pTab->pSelect && pExpr ); + + if( IsVirtual(pTab) ) return 0; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; - if( pExpr->pAggInfo!=pAggInfo ) return 0; + if( NEVER(pAggInfo->nFunc==0) ) return 0; if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0; - assert( pAggInfo->aFunc[0].pFExpr==pExpr ); - testcase( ExprHasProperty(pExpr, EP_Distinct) ); - testcase( ExprHasProperty(pExpr, EP_WinFunc) ); - if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0; + if( pExpr->flags&EP_Distinct ) return 0; return pTab; } /* ** If the source-list item passed as an argument was augmented with an ** INDEXED BY clause, then try to locate the specified index. If there -** was such a clause and the named index cannot be found, return -** SQLITE_ERROR and leave an error in pParse. Otherwise, populate +** was such a clause and the named index cannot be found, return +** SQLITE_ERROR and leave an error in pParse. Otherwise, populate ** pFrom->pIndex and return SQLITE_OK. */ -SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){ - Table *pTab = pFrom->pSTab; - char *zIndexedBy = pFrom->u1.zIndexedBy; - Index *pIdx; - assert( pTab!=0 ); - assert( pFrom->fg.isIndexedBy!=0 ); - - for(pIdx=pTab->pIndex; - pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); - pIdx=pIdx->pNext - ); - if( !pIdx ){ - sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); - pParse->checkSchema = 1; - return SQLITE_ERROR; - } - assert( pFrom->fg.isCte==0 ); - pFrom->u2.pIBIndex = pIdx; +SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){ + if( pFrom->pTab && pFrom->fg.isIndexedBy ){ + Table *pTab = pFrom->pTab; + char *zIndexedBy = pFrom->u1.zIndexedBy; + Index *pIdx; + for(pIdx=pTab->pIndex; + pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); + pIdx=pIdx->pNext + ); + if( !pIdx ){ + sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); + pParse->checkSchema = 1; + return SQLITE_ERROR; + } + pFrom->pIBIndex = pIdx; + } return SQLITE_OK; } - /* -** Detect compound SELECT statements that use an ORDER BY clause with +** Detect compound SELECT statements that use an ORDER BY clause with ** an alternative collating sequence. ** ** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ... ** ** These are rewritten as a subquery: @@ -149415,18 +121407,10 @@ if( p->pPrior==0 ) return WRC_Continue; if( p->pOrderBy==0 ) return WRC_Continue; for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){} if( pX==0 ) return WRC_Continue; a = p->pOrderBy->a; -#ifndef SQLITE_OMIT_WINDOWFUNC - /* If iOrderByCol is already non-zero, then it has already been matched - ** to a result column of the SELECT statement. This occurs when the - ** SELECT is rewritten for window-functions processing and then passed - ** to sqlite3SelectPrep() and similar a second time. The rewriting done - ** by this function is not required in this case. */ - if( a[0].u.x.iOrderByCol ) return WRC_Continue; -#endif for(i=p->pOrderBy->nExpr-1; i>=0; i--){ if( a[i].pExpr->flags & EP_Collate ) break; } if( i<0 ) return WRC_Continue; @@ -149435,16 +121419,12 @@ pParse = pWalker->pParse; db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); if( pNew==0 ) return WRC_Abort; memset(&dummy, 0, sizeof(dummy)); - pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0); - assert( pNewSrc!=0 || pParse->nErr ); - if( pParse->nErr ){ - sqlite3SrcListDelete(db, pNewSrc); - return WRC_Abort; - } + pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0); + if( pNewSrc==0 ) return WRC_Abort; *pNew = *p; p->pSrc = pNewSrc; p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); p->op = TK_SELECT; p->pWhere = 0; @@ -149452,260 +121432,182 @@ pNew->pHaving = 0; pNew->pOrderBy = 0; p->pPrior = 0; p->pNext = 0; p->pWith = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - p->pWinDefn = 0; -#endif p->selFlags &= ~SF_Compound; assert( (p->selFlags & SF_Converted)==0 ); p->selFlags |= SF_Converted; assert( pNew->pPrior!=0 ); pNew->pPrior->pNext = pNew; pNew->pLimit = 0; + pNew->pOffset = 0; return WRC_Continue; } /* ** Check to see if the FROM clause term pFrom has table-valued function ** arguments. If it does, leave an error message in pParse and return ** non-zero, since pFrom is not allowed to be a table-valued function. */ -static int cannotBeFunction(Parse *pParse, SrcItem *pFrom){ +static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){ if( pFrom->fg.isTabFunc ){ sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName); return 1; } return 0; } #ifndef SQLITE_OMIT_CTE /* -** Argument pWith (which may be NULL) points to a linked list of nested -** WITH contexts, from inner to outermost. If the table identified by -** FROM clause element pItem is really a common-table-expression (CTE) +** Argument pWith (which may be NULL) points to a linked list of nested +** WITH contexts, from inner to outermost. If the table identified by +** FROM clause element pItem is really a common-table-expression (CTE) ** then return a pointer to the CTE definition for that table. Otherwise ** return NULL. ** ** If a non-NULL value is returned, set *ppContext to point to the With ** object that the returned CTE belongs to. */ static struct Cte *searchWith( With *pWith, /* Current innermost WITH clause */ - SrcItem *pItem, /* FROM clause element to resolve */ + struct SrcList_item *pItem, /* FROM clause element to resolve */ With **ppContext /* OUT: WITH clause return value belongs to */ ){ - const char *zName = pItem->zName; - With *p; - assert( pItem->fg.fixedSchema || pItem->u4.zDatabase==0 ); - assert( zName!=0 ); - for(p=pWith; p; p=p->pOuter){ - int i; - for(i=0; inCte; i++){ - if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ - *ppContext = p; - return &p->a[i]; + const char *zName; + if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){ + With *p; + for(p=pWith; p; p=p->pOuter){ + int i; + for(i=0; inCte; i++){ + if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ + *ppContext = p; + return &p->a[i]; + } } } - if( p->bView ) break; } return 0; } /* The code generator maintains a stack of active WITH clauses ** with the inner-most WITH clause being at the top of the stack. ** ** This routine pushes the WITH clause passed as the second argument ** onto the top of the stack. If argument bFree is true, then this -** WITH clause will never be popped from the stack but should instead -** be freed along with the Parse object. In other cases, when -** bFree==0, the With object will be freed along with the SELECT +** WITH clause will never be popped from the stack. In this case it +** should be freed along with the Parse object. In other cases, when +** bFree==0, the With object will be freed along with the SELECT ** statement with which it is associated. -** -** This routine returns a copy of pWith. Or, if bFree is true and -** the pWith object is destroyed immediately due to an OOM condition, -** then this routine return NULL. -** -** If bFree is true, do not continue to use the pWith pointer after -** calling this routine, Instead, use only the return value. */ -SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ +SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ + assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) ); if( pWith ){ - if( bFree ){ - pWith = (With*)sqlite3ParserAddCleanup(pParse, sqlite3WithDeleteGeneric, - pWith); - if( pWith==0 ) return 0; - } - if( pParse->nErr==0 ){ - assert( pParse->pWith!=pWith ); - pWith->pOuter = pParse->pWith; - pParse->pWith = pWith; - } - } - return pWith; + assert( pParse->pWith!=pWith ); + pWith->pOuter = pParse->pWith; + pParse->pWith = pWith; + if( bFree ) pParse->pWithToFree = pWith; + } } /* -** This function checks if argument pFrom refers to a CTE declared by -** a WITH clause on the stack currently maintained by the parser (on the -** pParse->pWith linked list). And if currently processing a CTE -** CTE expression, through routine checks to see if the reference is -** a recursive reference to the CTE. -** -** If pFrom matches a CTE according to either of these two above, pFrom->pTab -** and other fields are populated accordingly. -** -** Return 0 if no match is found. -** Return 1 if a match is found. -** Return 2 if an error condition is detected. -*/ -static int resolveFromTermToCte( - Parse *pParse, /* The parsing context */ - Walker *pWalker, /* Current tree walker */ - SrcItem *pFrom /* The FROM clause term to check */ -){ - Cte *pCte; /* Matched CTE (or NULL if no match) */ - With *pWith; /* The matching WITH */ - - assert( pFrom->pSTab==0 ); - if( pParse->pWith==0 ){ - /* There are no WITH clauses in the stack. No match is possible */ - return 0; - } - if( pParse->nErr ){ - /* Prior errors might have left pParse->pWith in a goofy state, so - ** go no further. */ - return 0; - } - assert( pFrom->fg.hadSchema==0 || pFrom->fg.notCte!=0 ); - if( pFrom->fg.fixedSchema==0 && pFrom->u4.zDatabase!=0 ){ - /* The FROM term contains a schema qualifier (ex: main.t1) and so - ** it cannot possibly be a CTE reference. */ - return 0; - } - if( pFrom->fg.notCte ){ - /* The FROM term is specifically excluded from matching a CTE. - ** (1) It is part of a trigger that used to have zDatabase but had - ** zDatabase removed by sqlite3FixTriggerStep(). - ** (2) This is the first term in the FROM clause of an UPDATE. - */ - return 0; - } +** This function checks if argument pFrom refers to a CTE declared by +** a WITH clause on the stack currently maintained by the parser. And, +** if currently processing a CTE expression, if it is a recursive +** reference to the current CTE. +** +** If pFrom falls into either of the two categories above, pFrom->pTab +** and other fields are populated accordingly. The caller should check +** (pFrom->pTab!=0) to determine whether or not a successful match +** was found. +** +** Whether or not a match is found, SQLITE_OK is returned if no error +** occurs. If an error does occur, an error message is stored in the +** parser and some error code other than SQLITE_OK returned. +*/ +static int withExpand( + Walker *pWalker, + struct SrcList_item *pFrom +){ + Parse *pParse = pWalker->pParse; + sqlite3 *db = pParse->db; + struct Cte *pCte; /* Matched CTE (or NULL if no match) */ + With *pWith; /* WITH clause that pCte belongs to */ + + assert( pFrom->pTab==0 ); + pCte = searchWith(pParse->pWith, pFrom, &pWith); if( pCte ){ - sqlite3 *db = pParse->db; Table *pTab; ExprList *pEList; Select *pSel; Select *pLeft; /* Left-most SELECT statement */ - Select *pRecTerm; /* Left-most recursive term */ int bMayRecursive; /* True if compound joined by UNION [ALL] */ With *pSavedWith; /* Initial value of pParse->pWith */ - int iRecTab = -1; /* Cursor for recursive table */ - CteUse *pCteUse; /* If pCte->zCteErr is non-NULL at this point, then this is an illegal ** recursive reference to CTE pCte. Leave an error in pParse and return ** early. If pCte->zCteErr is NULL, then this is not a recursive reference. ** In this case, proceed. */ if( pCte->zCteErr ){ sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName); - return 2; - } - if( cannotBeFunction(pParse, pFrom) ) return 2; - - assert( pFrom->pSTab==0 ); - pTab = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTab==0 ) return 2; - pCteUse = pCte->pUse; - if( pCteUse==0 ){ - pCte->pUse = pCteUse = sqlite3DbMallocZero(db, sizeof(pCteUse[0])); - if( pCteUse==0 - || sqlite3ParserAddCleanup(pParse,sqlite3DbFree,pCteUse)==0 - ){ - sqlite3DbFree(db, pTab); - return 2; - } - pCteUse->eM10d = pCte->eM10d; - } - pFrom->pSTab = pTab; + return SQLITE_ERROR; + } + if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR; + + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTab==0 ) return WRC_Abort; pTab->nTabRef = 1; pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; - sqlite3SrcItemAttachSubquery(pParse, pFrom, pCte->pSelect, 1); - if( db->mallocFailed ) return 2; - assert( pFrom->fg.isSubquery && pFrom->u4.pSubq ); - pSel = pFrom->u4.pSubq->pSelect; - assert( pSel!=0 ); - pSel->selFlags |= SF_CopyCte; - if( pFrom->fg.isIndexedBy ){ - sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy); - return 2; - } - assert( !pFrom->fg.isIndexedBy ); - pFrom->fg.isCte = 1; - pFrom->u2.pCteUse = pCteUse; - pCteUse->nUse++; + pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); + if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; + assert( pFrom->pSelect ); /* Check if this is a recursive CTE. */ - pRecTerm = pSel; + pSel = pFrom->pSelect; bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION ); - while( bMayRecursive && pRecTerm->op==pSel->op ){ + if( bMayRecursive ){ int i; - SrcList *pSrc = pRecTerm->pSrc; - assert( pRecTerm->pPrior!=0 ); + SrcList *pSrc = pFrom->pSelect->pSrc; for(i=0; inSrc; i++){ - SrcItem *pItem = &pSrc->a[i]; - if( pItem->zName!=0 - && !pItem->fg.hadSchema - && ALWAYS( !pItem->fg.isSubquery ) - && (pItem->fg.fixedSchema || pItem->u4.zDatabase==0) + struct SrcList_item *pItem = &pSrc->a[i]; + if( pItem->zDatabase==0 + && pItem->zName!=0 && 0==sqlite3StrICmp(pItem->zName, pCte->zName) - ){ - pItem->pSTab = pTab; + ){ + pItem->pTab = pTab; + pItem->fg.isRecursive = 1; pTab->nTabRef++; - pItem->fg.isRecursive = 1; - if( pRecTerm->selFlags & SF_Recursive ){ - sqlite3ErrorMsg(pParse, - "multiple references to recursive table: %s", pCte->zName - ); - return 2; - } - pRecTerm->selFlags |= SF_Recursive; - if( iRecTab<0 ) iRecTab = pParse->nTab++; - pItem->iCursor = iRecTab; - } - } - if( (pRecTerm->selFlags & SF_Recursive)==0 ) break; - pRecTerm = pRecTerm->pPrior; - } + pSel->selFlags |= SF_Recursive; + } + } + } + + /* Only one recursive reference is permitted. */ + if( pTab->nTabRef>2 ){ + sqlite3ErrorMsg( + pParse, "multiple references to recursive table: %s", pCte->zName + ); + return SQLITE_ERROR; + } + assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); pCte->zCteErr = "circular reference: %s"; pSavedWith = pParse->pWith; pParse->pWith = pWith; - if( pSel->selFlags & SF_Recursive ){ - int rc; - assert( pRecTerm!=0 ); - assert( (pRecTerm->selFlags & SF_Recursive)==0 ); - assert( pRecTerm->pNext!=0 ); - assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 ); - assert( pRecTerm->pWith==0 ); - pRecTerm->pWith = pSel->pWith; - rc = sqlite3WalkSelect(pWalker, pRecTerm); - pRecTerm->pWith = 0; - if( rc ){ - pParse->pWith = pSavedWith; - return 2; - } + if( bMayRecursive ){ + Select *pPrior = pSel->pPrior; + assert( pPrior->pWith==0 ); + pPrior->pWith = pSel->pWith; + sqlite3WalkSelect(pWalker, pPrior); + pPrior->pWith = 0; }else{ - if( sqlite3WalkSelect(pWalker, pSel) ){ - pParse->pWith = pSavedWith; - return 2; - } + sqlite3WalkSelect(pWalker, pSel); } pParse->pWith = pWith; for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); pEList = pLeft->pEList; @@ -149713,11 +121615,11 @@ if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", pCte->zName, pEList->nExpr, pCte->pCols->nExpr ); pParse->pWith = pSavedWith; - return 2; + return SQLITE_ERROR; } pEList = pCte->pCols; } sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); @@ -149729,109 +121631,47 @@ } sqlite3WalkSelect(pWalker, pSel); } pCte->zCteErr = 0; pParse->pWith = pSavedWith; - return 1; /* Success */ } - return 0; /* No match */ + + return SQLITE_OK; } #endif #ifndef SQLITE_OMIT_CTE /* -** If the SELECT passed as the second argument has an associated WITH +** If the SELECT passed as the second argument has an associated WITH ** clause, pop it from the stack stored as part of the Parse object. ** ** This function is used as the xSelectCallback2() callback by ** sqlite3SelectExpand() when walking a SELECT tree to resolve table -** names and other FROM clause elements. +** names and other FROM clause elements. */ -SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){ +static void selectPopWith(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; - if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){ + if( pParse->pWith && p->pPrior==0 ){ With *pWith = findRightmost(p)->pWith; if( pWith!=0 ){ - assert( pParse->pWith==pWith || pParse->nErr ); + assert( pParse->pWith==pWith ); pParse->pWith = pWith->pOuter; } } } -#endif - -/* -** The SrcItem structure passed as the second argument represents a -** sub-query in the FROM clause of a SELECT statement. This function -** allocates and populates the SrcItem.pTab object. If successful, -** SQLITE_OK is returned. Otherwise, if an OOM error is encountered, -** SQLITE_NOMEM. -*/ -SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){ - Select *pSel; - Table *pTab; - - assert( pFrom->fg.isSubquery ); - assert( pFrom->u4.pSubq!=0 ); - pSel = pFrom->u4.pSubq->pSelect; - assert( pSel ); - pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table)); - if( pTab==0 ) return SQLITE_NOMEM; - pTab->nTabRef = 1; - if( pFrom->zAlias ){ - pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); - }else{ - pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom); - } - while( pSel->pPrior ){ pSel = pSel->pPrior; } - sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); - pTab->iPKey = -1; - pTab->eTabType = TABTYP_VIEW; - pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW - /* The usual case - do not allow ROWID on a subquery */ - pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; -#else - /* Legacy compatibility mode */ - pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid; -#endif - return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; -} - - -/* -** Check the N SrcItem objects to the right of pBase. (N might be zero!) -** If any of those SrcItem objects have a USING clause containing zName -** then return true. -** -** If N is zero, or none of the N SrcItem objects to the right of pBase -** contains a USING clause, or if none of the USING clauses contain zName, -** then return false. -*/ -static int inAnyUsingClause( - const char *zName, /* Name we are looking for */ - SrcItem *pBase, /* The base SrcItem. Looking at pBase[1] and following */ - int N /* How many SrcItems to check */ -){ - while( N>0 ){ - N--; - pBase++; - if( pBase->fg.isUsing==0 ) continue; - if( NEVER(pBase->u3.pUsing==0) ) continue; - if( sqlite3IdListIndex(pBase->u3.pUsing, zName)>=0 ) return 1; - } - return 0; -} - +#else +#define selectPopWith 0 +#endif /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. ** -** (2) Fill in the pTabList->a[].pTab fields in the SrcList that +** (2) Fill in the pTabList->a[].pTab fields in the SrcList that ** defines FROM clause. When views appear in the FROM clause, ** fill pTabList->a[].pSelect with a copy of the SELECT statement ** that implements the view. A copy is made of the view's SELECT ** statement so that we can freely modify or delete that statement ** without worrying about messing up the persistent representation @@ -149846,43 +121686,30 @@ ** and TABLE.* to be every column in TABLE. ** */ static int selectExpander(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; - int i, j, k, rc; + int i, j, k; SrcList *pTabList; ExprList *pEList; - SrcItem *pFrom; + struct SrcList_item *pFrom; sqlite3 *db = pParse->db; Expr *pE, *pRight, *pExpr; u16 selFlags = p->selFlags; - u32 elistFlags = 0; p->selFlags |= SF_Expanded; if( db->mallocFailed ){ return WRC_Abort; } - assert( p->pSrc!=0 ); - if( (selFlags & SF_Expanded)!=0 ){ + if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } - if( pWalker->eCode ){ - /* Renumber selId because it has been copied from a view */ - p->selId = ++pParse->nSelect; - } pTabList = p->pSrc; pEList = p->pEList; - if( pParse->pWith && (p->selFlags & SF_View) ){ - if( p->pWith==0 ){ - p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With)); - if( p->pWith==0 ){ - return WRC_Abort; - } - } - p->pWith->bView = 1; - } - sqlite3WithPush(pParse, p->pWith, 0); + if( p->pWith ){ + sqlite3WithPush(pParse, p->pWith, 0); + } /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, pTabList); @@ -149891,93 +121718,73 @@ ** an entry of the FROM clause is a subquery instead of a table or view, ** then create a transient table structure to describe the subquery. */ for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab; - assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 ); - if( pFrom->pSTab ) continue; - assert( pFrom->fg.isRecursive==0 ); + assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 ); + if( pFrom->fg.isRecursive ) continue; + assert( pFrom->pTab==0 ); +#ifndef SQLITE_OMIT_CTE + if( withExpand(pWalker, pFrom) ) return WRC_Abort; + if( pFrom->pTab ) {} else +#endif if( pFrom->zName==0 ){ #ifndef SQLITE_OMIT_SUBQUERY - Select *pSel; - assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 ); - pSel = pFrom->u4.pSubq->pSelect; + Select *pSel = pFrom->pSelect; /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); - assert( pFrom->pSTab==0 ); + assert( pFrom->pTab==0 ); if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; - if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort; -#endif -#ifndef SQLITE_OMIT_CTE - }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){ - if( rc>1 ) return WRC_Abort; - pTab = pFrom->pSTab; - assert( pTab!=0 ); + pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTab==0 ) return WRC_Abort; + pTab->nTabRef = 1; + pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); + while( pSel->pPrior ){ pSel = pSel->pPrior; } + sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); + pTab->iPKey = -1; + pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); + pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ - assert( pFrom->pSTab==0 ); - pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; if( pTab->nTabRef>=0xffff ){ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", pTab->zName); - pFrom->pSTab = 0; + pFrom->pTab = 0; return WRC_Abort; } pTab->nTabRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) - if( !IsOrdinaryTable(pTab) ){ +#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) + if( IsVirtual(pTab) || pTab->pSelect ){ i16 nCol; - u8 eCodeOrig = pWalker->eCode; if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; - assert( pFrom->fg.isSubquery==0 ); - if( IsView(pTab) ){ - if( (db->flags & SQLITE_EnableView)==0 - && pTab->pSchema!=db->aDb[1].pSchema - ){ - sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", - pTab->zName); - } - sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( ALWAYS(IsVirtual(pTab)) - && pFrom->fg.fromDDL - && ALWAYS(pTab->u.vtab.p!=0) - && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) - ){ - sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", - pTab->zName); - } - assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 ); -#endif + assert( pFrom->pSelect==0 ); + pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); + sqlite3SelectSetName(pFrom->pSelect, pTab->zName); nCol = pTab->nCol; pTab->nCol = -1; - pWalker->eCode = 1; /* Turn on Select.selId renumbering */ - if( pFrom->fg.isSubquery ){ - sqlite3WalkSelect(pWalker, pFrom->u4.pSubq->pSelect); - } - pWalker->eCode = eCodeOrig; + sqlite3WalkSelect(pWalker, pFrom->pSelect); pTab->nCol = nCol; } #endif } /* Locate the index named by the INDEXED BY clause, if any. */ - if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){ + if( sqlite3IndexedByLookup(pParse, pFrom) ){ return WRC_Abort; } } /* Process NATURAL keywords, and ON and USING clauses of joins. */ - assert( db->mallocFailed==0 || pParse->nErr!=0 ); - if( pParse->nErr || sqlite3ProcessJoin(pParse, p) ){ + if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){ return WRC_Abort; } /* For every "*" that occurs in the column list, insert the names of ** all columns in all tables. And for every TABLE.* insert the names @@ -149994,11 +121801,10 @@ pE = pEList->a[k].pExpr; if( pE->op==TK_ASTERISK ) break; assert( pE->op!=TK_DOT || pE->pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; - elistFlags |= pE->flags; } if( knExpr ){ /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression @@ -150010,201 +121816,125 @@ int longNames = (flags & SQLITE_FullColNames)!=0 && (flags & SQLITE_ShortColNames)==0; for(k=0; knExpr; k++){ pE = a[k].pExpr; - elistFlags |= pE->flags; pRight = pE->pRight; assert( pE->op!=TK_DOT || pRight!=0 ); if( pE->op!=TK_ASTERISK && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK) ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if( pNew ){ - pNew->a[pNew->nExpr-1].zEName = a[k].zEName; - pNew->a[pNew->nExpr-1].fg.eEName = a[k].fg.eEName; - a[k].zEName = 0; + pNew->a[pNew->nExpr-1].zName = a[k].zName; + pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; + a[k].zName = 0; + a[k].zSpan = 0; } a[k].pExpr = 0; }else{ /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName = 0; /* text of name of TABLE */ - int iErrOfst; if( pE->op==TK_DOT ){ - assert( (selFlags & SF_NestedFrom)==0 ); assert( pE->pLeft!=0 ); assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); zTName = pE->pLeft->u.zToken; - assert( ExprUseWOfst(pE->pLeft) ); - iErrOfst = pE->pRight->w.iOfst; - }else{ - assert( ExprUseWOfst(pE) ); - iErrOfst = pE->w.iOfst; } for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - int nAdd; /* Number of cols including rowid */ - Table *pTab = pFrom->pSTab; /* Table for this data source */ - ExprList *pNestedFrom; /* Result-set of a nested FROM clause */ - char *zTabName; /* AS name for this data source */ - const char *zSchemaName = 0; /* Schema name for this data source */ - int iDb; /* Schema index for this data src */ - IdList *pUsing; /* USING clause for pFrom[1] */ - - if( (zTabName = pFrom->zAlias)==0 ){ + Table *pTab = pFrom->pTab; + Select *pSub = pFrom->pSelect; + char *zTabName = pFrom->zAlias; + const char *zSchemaName = 0; + int iDb; + if( zTabName==0 ){ zTabName = pTab->zName; } if( db->mallocFailed ) break; - assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom) ); - if( pFrom->fg.isNestedFrom ){ - assert( pFrom->fg.isSubquery && pFrom->u4.pSubq ); - assert( pFrom->u4.pSubq->pSelect!=0 ); - pNestedFrom = pFrom->u4.pSubq->pSelect->pEList; - assert( pNestedFrom!=0 ); - assert( pNestedFrom->nExpr==pTab->nCol ); - assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid ); - }else{ + if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ + pSub = 0; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } - pNestedFrom = 0; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } - if( i+1nSrc - && pFrom[1].fg.isUsing - && (selFlags & SF_NestedFrom)!=0 - ){ - int ii; - pUsing = pFrom[1].u3.pUsing; - for(ii=0; iinId; ii++){ - const char *zUName = pUsing->a[ii].zName; - pRight = sqlite3Expr(db, TK_ID, zUName); - sqlite3ExprSetErrorOffset(pRight, iErrOfst); - pNew = sqlite3ExprListAppend(pParse, pNew, pRight); - if( pNew ){ - struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; - assert( pX->zEName==0 ); - pX->zEName = sqlite3MPrintf(db,"..%s", zUName); - pX->fg.eEName = ENAME_TAB; - pX->fg.bUsingTerm = 1; - } - } - }else{ - pUsing = 0; - } - - nAdd = pTab->nCol; - if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++; - for(j=0; jnCol ){ - zName = sqlite3RowidAlias(pTab); - if( zName==0 ) continue; - }else{ - zName = pTab->aCol[j].zCnName; - - /* If pTab is actually an SF_NestedFrom sub-select, do not - ** expand any ENAME_ROWID columns. */ - if( pNestedFrom && pNestedFrom->a[j].fg.eEName==ENAME_ROWID ){ - continue; - } - - if( zTName - && pNestedFrom - && sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0, 0)==0 - ){ - continue; - } - - /* If a column is marked as 'hidden', omit it from the expanded - ** result-set list unless the SELECT has the SF_IncludeHidden - ** bit set. - */ - if( (p->selFlags & SF_IncludeHidden)==0 - && IsHiddenColumn(&pTab->aCol[j]) - ){ - continue; - } - if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 - && zTName==0 - && (selFlags & (SF_NestedFrom))==0 - ){ - continue; - } - } - assert( zName ); - tableSeen = 1; - - if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){ - if( pFrom->fg.isUsing - && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0 - ){ + for(j=0; jnCol; j++){ + char *zName = pTab->aCol[j].zName; + char *zColname; /* The computed column name */ + char *zToFree; /* Malloced string that needs to be freed */ + Token sColname; /* Computed column name as a token */ + + assert( zName ); + if( zTName && pSub + && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 + ){ + continue; + } + + /* If a column is marked as 'hidden', omit it from the expanded + ** result-set list unless the SELECT has the SF_IncludeHidden + ** bit set. + */ + if( (p->selFlags & SF_IncludeHidden)==0 + && IsHiddenColumn(&pTab->aCol[j]) + ){ + continue; + } + tableSeen = 1; + + if( i>0 && zTName==0 ){ + if( (pFrom->fg.jointype & JT_NATURAL)!=0 + && tableAndColumnIndex(pTabList, i, zName, 0, 0) + ){ + /* In a NATURAL join, omit the join columns from the + ** table to the right of the join */ + continue; + } + if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){ /* In a join with a USING clause, omit columns in the ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(db, TK_ID, zName); - if( (pTabList->nSrc>1 - && ( (pFrom->fg.jointype & JT_LTORJ)==0 - || (selFlags & SF_NestedFrom)!=0 - || !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1) - ) - ) - || IN_RENAME_OBJECT - ){ + zColname = zName; + zToFree = 0; + if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - if( IN_RENAME_OBJECT && pE->pLeft ){ - sqlite3RenameTokenRemap(pParse, pLeft, pE->pLeft); - } if( zSchemaName ){ pLeft = sqlite3Expr(db, TK_ID, zSchemaName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr); } + if( longNames ){ + zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); + zToFree = zColname; + } }else{ pExpr = pRight; } - sqlite3ExprSetErrorOffset(pExpr, iErrOfst); - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); - if( pNew==0 ){ - break; /* OOM */ - } - pX = &pNew->a[pNew->nExpr-1]; - assert( pX->zEName==0 ); - if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ - if( pNestedFrom && (!ViewCanHaveRowid || jnExpr) ){ - assert( jnExpr ); - pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName); - testcase( pX->zEName==0 ); - }else{ - pX->zEName = sqlite3MPrintf(db, "%s.%s.%s", - zSchemaName, zTabName, zName); - testcase( pX->zEName==0 ); - } - pX->fg.eEName = (j==pTab->nCol ? ENAME_ROWID : ENAME_TAB); - if( (pFrom->fg.isUsing - && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0) - || (pUsing && sqlite3IdListIndex(pUsing, zName)>=0) - || (jnCol && (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)) - ){ - pX->fg.bNoExpand = 1; - } - }else if( longNames ){ - pX->zEName = sqlite3MPrintf(db, "%s.%s", zTabName, zName); - pX->fg.eEName = ENAME_NAME; - }else{ - pX->zEName = sqlite3DbStrDup(db, zName); - pX->fg.eEName = ENAME_NAME; - } + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); + sqlite3TokenInit(&sColname, zColname); + sqlite3ExprListSetName(pParse, pNew, &sColname, 0); + if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ + struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; + if( pSub ){ + pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); + testcase( pX->zSpan==0 ); + }else{ + pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", + zSchemaName, zTabName, zColname); + testcase( pX->zSpan==0 ); + } + pX->bSpanIsTab = 1; + } + sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ if( zTName ){ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); @@ -150215,27 +121945,41 @@ } } sqlite3ExprListDelete(db, pEList); p->pEList = pNew; } - if( p->pEList ){ - if( p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns in result set"); - return WRC_Abort; - } - if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){ - p->selFlags |= SF_ComplexResult; - } - } -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x8 ){ - TREETRACE(0x8,pParse,p,("After result-set wildcard expansion:\n")); - sqlite3TreeViewSelect(0, p, 0); +#if SQLITE_MAX_COLUMN + if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many columns in result set"); + return WRC_Abort; } #endif return WRC_Continue; } + +/* +** No-op routine for the parse-tree walker. +** +** When this routine is the Walker.xExprCallback then expression trees +** are walked without any actions being taken at each node. Presumably, +** when this routine is used for Walker.xExprCallback then +** Walker.xSelectCallback is set to do something useful for every +** subquery in the parser tree. +*/ +SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + return WRC_Continue; +} + +/* +** No-op routine for the parse-tree walker for SELECT statements. +** subquery in the parser tree. +*/ +SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + return WRC_Continue; +} #if SQLITE_DEBUG /* ** Always assert. This xSelectCallback2 implementation proves that the ** xSelectCallback2 is never invoked. @@ -150260,54 +122004,56 @@ */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; w.xExprCallback = sqlite3ExprWalkNoop; w.pParse = pParse; - if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){ + if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; w.xSelectCallback2 = 0; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; - w.xSelectCallback2 = sqlite3SelectPopWith; - w.eCode = 0; + w.xSelectCallback2 = selectPopWith; sqlite3WalkSelect(&w, pSelect); } #ifndef SQLITE_OMIT_SUBQUERY /* ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() ** interface. ** -** For each FROM-clause subquery, add Column.zType, Column.zColl, and -** Column.affinity information to the Table structure that represents -** the result set of that subquery. +** For each FROM-clause subquery, add Column.zType and Column.zColl +** information to the Table structure that represents the result set +** of that subquery. ** ** The Table structure that represents the result set was constructed -** by selectExpander() but the type and collation and affinity information -** was omitted at that point because identifiers had not yet been resolved. -** This routine is called after identifier resolution. +** by selectExpander() but the type and collation information was omitted +** at that point because identifiers had not yet been resolved. This +** routine is called after identifier resolution. */ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Parse *pParse; int i; SrcList *pTabList; - SrcItem *pFrom; + struct SrcList_item *pFrom; - if( p->selFlags & SF_HasTypeInfo ) return; + assert( p->selFlags & SF_Resolved ); + assert( (p->selFlags & SF_HasTypeInfo)==0 ); p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; - assert( (p->selFlags & SF_Resolved) ); pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pSTab; + Table *pTab = pFrom->pTab; assert( pTab!=0 ); - if( (pTab->tabFlags & TF_Ephemeral)!=0 && pFrom->fg.isSubquery ){ + if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ /* A sub-query in the FROM clause of a SELECT */ - Select *pSel = pFrom->u4.pSubq->pSelect; - sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE); + Select *pSel = pFrom->pSelect; + if( pSel ){ + while( pSel->pPrior ) pSel = pSel->pPrior; + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel); + } } } } #endif @@ -150346,201 +122092,22 @@ SQLITE_PRIVATE void sqlite3SelectPrep( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ - assert( p!=0 || pParse->db->mallocFailed ); - assert( pParse->db->pParse==pParse ); - if( pParse->db->mallocFailed ) return; + sqlite3 *db; + if( NEVER(p==0) ) return; + db = pParse->db; + if( db->mallocFailed ) return; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); - if( pParse->nErr ) return; + if( pParse->nErr || db->mallocFailed ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); - if( pParse->nErr ) return; + if( pParse->nErr || db->mallocFailed ) return; sqlite3SelectAddTypeInfo(pParse, p); } -#if TREETRACE_ENABLED -/* -** Display all information about an AggInfo object -*/ -static void printAggInfo(AggInfo *pAggInfo){ - int ii; - sqlite3DebugPrintf("AggInfo %d/%p:\n", - pAggInfo->selId, pAggInfo); - for(ii=0; iinColumn; ii++){ - struct AggInfo_col *pCol = &pAggInfo->aCol[ii]; - sqlite3DebugPrintf( - "agg-column[%d] pTab=%s iTable=%d iColumn=%d iMem=%d" - " iSorterColumn=%d %s\n", - ii, pCol->pTab ? pCol->pTab->zName : "NULL", - pCol->iTable, pCol->iColumn, pAggInfo->iFirstReg+ii, - pCol->iSorterColumn, - ii>=pAggInfo->nAccumulator ? "" : " Accumulator"); - sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0); - } - for(ii=0; iinFunc; ii++){ - sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n", - ii, pAggInfo->iFirstReg+pAggInfo->nColumn+ii); - sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0); - } -} -#endif /* TREETRACE_ENABLED */ - -/* -** Analyze the arguments to aggregate functions. Create new pAggInfo->aCol[] -** entries for columns that are arguments to aggregate functions but which -** are not otherwise used. -** -** The aCol[] entries in AggInfo prior to nAccumulator are columns that -** are referenced outside of aggregate functions. These might be columns -** that are part of the GROUP by clause, for example. Other database engines -** would throw an error if there is a column reference that is not in the -** GROUP BY clause and that is not part of an aggregate function argument. -** But SQLite allows this. -** -** The aCol[] entries beginning with the aCol[nAccumulator] and following -** are column references that are used exclusively as arguments to -** aggregate functions. This routine is responsible for computing -** (or recomputing) those aCol[] entries. -*/ -static void analyzeAggFuncArgs( - AggInfo *pAggInfo, - NameContext *pNC -){ - int i; - assert( pAggInfo!=0 ); - assert( pAggInfo->iFirstReg==0 ); - pNC->ncFlags |= NC_InAggFunc; - for(i=0; inFunc; i++){ - Expr *pExpr = pAggInfo->aFunc[i].pFExpr; - assert( pExpr->op==TK_FUNCTION || pExpr->op==TK_AGG_FUNCTION ); - assert( ExprUseXList(pExpr) ); - sqlite3ExprAnalyzeAggList(pNC, pExpr->x.pList); - if( pExpr->pLeft ){ - assert( pExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pExpr->pLeft) ); - sqlite3ExprAnalyzeAggList(pNC, pExpr->pLeft->x.pList); - } -#ifndef SQLITE_OMIT_WINDOWFUNC - assert( !IsWindowFunc(pExpr) ); - if( ExprHasProperty(pExpr, EP_WinFunc) ){ - sqlite3ExprAnalyzeAggregates(pNC, pExpr->y.pWin->pFilter); - } -#endif - } - pNC->ncFlags &= ~NC_InAggFunc; -} - -/* -** An index on expressions is being used in the inner loop of an -** aggregate query with a GROUP BY clause. This routine attempts -** to adjust the AggInfo object to take advantage of index and to -** perhaps use the index as a covering index. -** -*/ -static void optimizeAggregateUseOfIndexedExpr( - Parse *pParse, /* Parsing context */ - Select *pSelect, /* The SELECT statement being processed */ - AggInfo *pAggInfo, /* The aggregate info */ - NameContext *pNC /* Name context used to resolve agg-func args */ -){ - assert( pAggInfo->iFirstReg==0 ); - assert( pSelect!=0 ); - assert( pSelect->pGroupBy!=0 ); - pAggInfo->nColumn = pAggInfo->nAccumulator; - if( ALWAYS(pAggInfo->nSortingColumn>0) ){ - int mx = pSelect->pGroupBy->nExpr - 1; - int j, k; - for(j=0; jnColumn; j++){ - k = pAggInfo->aCol[j].iSorterColumn; - if( k>mx ) mx = k; - } - pAggInfo->nSortingColumn = mx+1; - } - analyzeAggFuncArgs(pAggInfo, pNC); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - IndexedExpr *pIEpr; - TREETRACE(0x20, pParse, pSelect, - ("AggInfo (possibly) adjusted for Indexed Exprs\n")); - sqlite3TreeViewSelect(0, pSelect, 0); - for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){ - printf("data-cursor=%d index={%d,%d}\n", - pIEpr->iDataCur, pIEpr->iIdxCur, pIEpr->iIdxCol); - sqlite3TreeViewExpr(0, pIEpr->pExpr, 0); - } - printAggInfo(pAggInfo); - } -#else - UNUSED_PARAMETER(pSelect); - UNUSED_PARAMETER(pParse); -#endif -} - -/* -** Walker callback for aggregateConvertIndexedExprRefToColumn(). -*/ -static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){ - AggInfo *pAggInfo; - struct AggInfo_col *pCol; - UNUSED_PARAMETER(pWalker); - if( pExpr->pAggInfo==0 ) return WRC_Continue; - if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue; - if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue; - if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue; - pAggInfo = pExpr->pAggInfo; - if( NEVER(pExpr->iAgg>=pAggInfo->nColumn) ) return WRC_Continue; - assert( pExpr->iAgg>=0 ); - pCol = &pAggInfo->aCol[pExpr->iAgg]; - pExpr->op = TK_AGG_COLUMN; - pExpr->iTable = pCol->iTable; - pExpr->iColumn = pCol->iColumn; - ExprClearProperty(pExpr, EP_Skip|EP_Collate|EP_Unlikely); - return WRC_Prune; -} - -/* -** Convert every pAggInfo->aFunc[].pExpr such that any node within -** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN -** opcode. -*/ -static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){ - int i; - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = aggregateIdxEprRefToColCallback; - for(i=0; inFunc; i++){ - sqlite3WalkExpr(&w, pAggInfo->aFunc[i].pFExpr); - } -} - - -/* -** Allocate a block of registers so that there is one register for each -** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo. The first -** register in this block is stored in pAggInfo->iFirstReg. -** -** This routine may only be called once for each AggInfo object. Prior -** to calling this routine: -** -** * The aCol[] and aFunc[] arrays may be modified -** * The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used -** -** After calling this routine: -** -** * The aCol[] and aFunc[] arrays are fixed -** * The AggInfoColumnReg() and AggInfoFuncReg() macros may be used -** -*/ -static void assignAggregateRegisters(Parse *pParse, AggInfo *pAggInfo){ - assert( pAggInfo!=0 ); - assert( pAggInfo->iFirstReg==0 ); - pAggInfo->iFirstReg = pParse->nMem + 1; - pParse->nMem += pAggInfo->nColumn + pAggInfo->nFunc; -} - /* ** Reset the aggregate accumulator. ** ** The aggregate accumulator is a set of memory cells that hold ** intermediate results while calculating an aggregate. This @@ -150550,62 +122117,38 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; int nReg = pAggInfo->nFunc + pAggInfo->nColumn; - assert( pAggInfo->iFirstReg>0 ); - assert( pParse->db->pParse==pParse ); - assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); if( nReg==0 ) return; - if( pParse->nErr ) return; - sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->iFirstReg, - pAggInfo->iFirstReg+nReg-1); +#ifdef SQLITE_DEBUG + /* Verify that all AggInfo registers are within the range specified by + ** AggInfo.mnReg..AggInfo.mxReg */ + assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 ); + for(i=0; inColumn; i++){ + assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg + && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg ); + } + for(i=0; inFunc; i++){ + assert( pAggInfo->aFunc[i].iMem>=pAggInfo->mnReg + && pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg ); + } +#endif + sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg); for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ if( pFunc->iDistinct>=0 ){ - Expr *pE = pFunc->pFExpr; - assert( ExprUseXList(pE) ); + Expr *pE = pFunc->pExpr; + assert( !ExprHasProperty(pE, EP_xIsSelect) ); if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " "argument"); pFunc->iDistinct = -1; }else{ - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0); - pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO); - ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)", - pFunc->pFunc->zName)); - } - } - if( pFunc->iOBTab>=0 ){ - ExprList *pOBList; - KeyInfo *pKeyInfo; - int nExtra = 0; - assert( pFunc->pFExpr->pLeft!=0 ); - assert( pFunc->pFExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pFunc->pFExpr->pLeft) ); - assert( pFunc->pFunc!=0 ); - pOBList = pFunc->pFExpr->pLeft->x.pList; - if( !pFunc->bOBUnique ){ - nExtra++; /* One extra column for the OP_Sequence */ - } - if( pFunc->bOBPayload ){ - /* extra columns for the function arguments */ - assert( ExprUseXList(pFunc->pFExpr) ); - nExtra += pFunc->pFExpr->x.pList->nExpr; - } - if( pFunc->bUseSubtype ){ - nExtra += pFunc->pFExpr->x.pList->nExpr; - } - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOBList, 0, nExtra); - if( !pFunc->bOBUnique && pParse->nErr==0 ){ - pKeyInfo->nKeyField++; - } - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - pFunc->iOBTab, pOBList->nExpr+nExtra, 0, - (char*)pKeyInfo, P4_KEYINFO); - ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(ORDER BY)", - pFunc->pFunc->zName)); + KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO); + } } } } /* @@ -150615,238 +122158,96 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pF; for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ - ExprList *pList; - assert( ExprUseXList(pF->pFExpr) ); - if( pParse->nErr ) return; - pList = pF->pFExpr->x.pList; - if( pF->iOBTab>=0 ){ - /* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs - ** were stored in emphermal table pF->iOBTab. Here, we extract those - ** inputs (in ORDER BY order) and make all calls to OP_AggStep - ** before doing the OP_AggFinal call. */ - int iTop; /* Start of loop for extracting columns */ - int nArg; /* Number of columns to extract */ - int nKey; /* Key columns to be skipped */ - int regAgg; /* Extract into this array */ - int j; /* Loop counter */ - - assert( pF->pFunc!=0 ); - nArg = pList->nExpr; - regAgg = sqlite3GetTempRange(pParse, nArg); - - if( pF->bOBPayload==0 ){ - nKey = 0; - }else{ - assert( pF->pFExpr->pLeft!=0 ); - assert( ExprUseXList(pF->pFExpr->pLeft) ); - assert( pF->pFExpr->pLeft->x.pList!=0 ); - nKey = pF->pFExpr->pLeft->x.pList->nExpr; - if( ALWAYS(!pF->bOBUnique) ) nKey++; - } - iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v); - for(j=nArg-1; j>=0; j--){ - sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j); - } - if( pF->bUseSubtype ){ - int regSubtype = sqlite3GetTempReg(pParse); - int iBaseCol = nKey + nArg + (pF->bOBPayload==0 && pF->bOBUnique==0); - for(j=nArg-1; j>=0; j--){ - sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, iBaseCol+j, regSubtype); - sqlite3VdbeAddOp2(v, OP_SetSubtype, regSubtype, regAgg+j); - } - sqlite3ReleaseTempReg(pParse, regSubtype); - } - sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u16)nArg); - sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, iTop); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); - } - sqlite3VdbeAddOp2(v, OP_AggFinal, AggInfoFuncReg(pAggInfo,i), - pList ? pList->nExpr : 0); + ExprList *pList = pF->pExpr->x.pList; + assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); + sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); } } /* -** Generate code that will update the accumulator memory cells for an -** aggregate based on the current cursor position. -** -** If regAcc is non-zero and there are no min() or max() aggregates -** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator -** registers if register regAcc contains 0. The caller will take care -** of setting and clearing regAcc. -** -** For an ORDER BY aggregate, the actual accumulator memory cell update -** is deferred until after all input rows have been received, so that they -** can be run in the requested order. In that case, instead of invoking -** OP_AggStep to update the accumulator, just add the arguments that would -** have been passed into OP_AggStep into the sorting ephemeral table -** (along with the appropriate sort key). +** Update the accumulator memory cells for an aggregate based on +** the current cursor position. */ -static void updateAccumulator( - Parse *pParse, - int regAcc, - AggInfo *pAggInfo, - int eDistinctType -){ +static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; int regHit = 0; int addrHitTest = 0; struct AggInfo_func *pF; struct AggInfo_col *pC; - assert( pAggInfo->iFirstReg>0 ); - if( pParse->nErr ) return; pAggInfo->directMode = 1; for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ int nArg; int addrNext = 0; int regAgg; - int regAggSz = 0; - int regDistinct = 0; - ExprList *pList; - assert( ExprUseXList(pF->pFExpr) ); - assert( !IsWindowFunc(pF->pFExpr) ); - assert( pF->pFunc!=0 ); - pList = pF->pFExpr->x.pList; - if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){ - Expr *pFilter = pF->pFExpr->y.pWin->pFilter; - if( pAggInfo->nAccumulator - && (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) - && regAcc - ){ - /* If regAcc==0, there there exists some min() or max() function - ** without a FILTER clause that will ensure the magnet registers - ** are populated. */ - if( regHit==0 ) regHit = ++pParse->nMem; - /* If this is the first row of the group (regAcc contains 0), clear the - ** "magnet" register regHit so that the accumulator registers - ** are populated if the FILTER clause jumps over the the - ** invocation of min() or max() altogether. Or, if this is not - ** the first row (regAcc contains 1), set the magnet register so that - ** the accumulators are not populated unless the min()/max() is invoked - ** and indicates that they should be. */ - sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit); - } - addrNext = sqlite3VdbeMakeLabel(pParse); - sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL); - } - if( pF->iOBTab>=0 ){ - /* Instead of invoking AggStep, we must push the arguments that would - ** have been passed to AggStep onto the sorting table. */ - int jj; /* Registered used so far in building the record */ - ExprList *pOBList; /* The ORDER BY clause */ - assert( pList!=0 ); - nArg = pList->nExpr; - assert( nArg>0 ); - assert( pF->pFExpr->pLeft!=0 ); - assert( pF->pFExpr->pLeft->op==TK_ORDER ); - assert( ExprUseXList(pF->pFExpr->pLeft) ); - pOBList = pF->pFExpr->pLeft->x.pList; - assert( pOBList!=0 ); - assert( pOBList->nExpr>0 ); - regAggSz = pOBList->nExpr; - if( !pF->bOBUnique ){ - regAggSz++; /* One register for OP_Sequence */ - } - if( pF->bOBPayload ){ - regAggSz += nArg; - } - if( pF->bUseSubtype ){ - regAggSz += nArg; - } - regAggSz++; /* One extra register to hold result of MakeRecord */ - regAgg = sqlite3GetTempRange(pParse, regAggSz); - regDistinct = regAgg; - sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP); - jj = pOBList->nExpr; - if( !pF->bOBUnique ){ - sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj); - jj++; - } - if( pF->bOBPayload ){ - regDistinct = regAgg+jj; - sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP); - jj += nArg; - } - if( pF->bUseSubtype ){ - int kk; - int regBase = pF->bOBPayload ? regDistinct : regAgg; - for(kk=0; kkpExpr->x.pList; + assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); + if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); - regDistinct = regAgg; sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); }else{ nArg = 0; regAgg = 0; } - if( pF->iDistinct>=0 && pList ){ - if( addrNext==0 ){ - addrNext = sqlite3VdbeMakeLabel(pParse); - } - pF->iDistinct = codeDistinct(pParse, eDistinctType, - pF->iDistinct, addrNext, pList, regDistinct); - } - if( pF->iOBTab>=0 ){ - /* Insert a new record into the ORDER BY table */ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regAgg, regAggSz-1, - regAgg+regAggSz-1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pF->iOBTab, regAgg+regAggSz-1, - regAgg, regAggSz-1); - sqlite3ReleaseTempRange(pParse, regAgg, regAggSz); - }else{ - /* Invoke the AggStep function */ - if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - CollSeq *pColl = 0; - struct ExprList_item *pItem; - int j; - assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ - for(j=0, pItem=pList->a; !pColl && jpExpr); - } - if( !pColl ){ - pColl = pParse->db->pDfltColl; - } - if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, - (char *)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u16)nArg); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); - } + if( pF->iDistinct>=0 ){ + addrNext = sqlite3VdbeMakeLabel(v); + testcase( nArg==0 ); /* Error condition */ + testcase( nArg>1 ); /* Also an error */ + codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); + } + if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + CollSeq *pColl = 0; + struct ExprList_item *pItem; + int j; + assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ + for(j=0, pItem=pList->a; !pColl && jpExpr); + } + if( !pColl ){ + pColl = pParse->db->pDfltColl; + } + if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); + } + sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nArg); + sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); + sqlite3ExprCacheClear(pParse); } - if( pParse->nErr ) return; } - if( regHit==0 && pAggInfo->nAccumulator ){ - regHit = regAcc; - } + + /* Before populating the accumulator registers, clear the column cache. + ** Otherwise, if any of the required column values are already present + ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value + ** to pC->iMem. But by the time the value is used, the original register + ** may have been used, invalidating the underlying buffer holding the + ** text or blob value. See ticket [883034dcb5]. + ** + ** Another solution would be to change the OP_SCopy used to copy cached + ** values to an OP_Copy. + */ if( regHit ){ addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); } + sqlite3ExprCacheClear(pParse); for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ - sqlite3ExprCode(pParse, pC->pCExpr, AggInfoColumnReg(pAggInfo,i)); - if( pParse->nErr ) return; + sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } - pAggInfo->directMode = 0; + sqlite3ExprCacheClear(pParse); if( addrHitTest ){ - sqlite3VdbeJumpHereOrPopInst(v, addrHitTest); + sqlite3VdbeJumpHere(v, addrHitTest); } } /* ** Add a single OP_Explain instruction to the VDBE to explain a simple @@ -150858,54 +122259,54 @@ Table *pTab, /* Table being queried */ Index *pIdx /* Index used to optimize scan, or NULL */ ){ if( pParse->explain==2 ){ int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); - sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s", + char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", pTab->zName, bCover ? " USING COVERING INDEX " : "", bCover ? pIdx->zName : "" ); + sqlite3VdbeAddOp4( + pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC + ); } } #else # define explainSimpleCount(a,b,c) #endif +/* +** Context object for havingToWhereExprCb(). +*/ +struct HavingToWhereCtx { + Expr **ppWhere; + ExprList *pGroupBy; +}; + /* ** sqlite3WalkExpr() callback used by havingToWhere(). ** -** If the node passed to the callback is a TK_AND node, return +** If the node passed to the callback is a TK_AND node, return ** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes. ** -** Otherwise, return WRC_Prune. In this case, also check if the +** Otherwise, return WRC_Prune. In this case, also check if the ** sub-expression matches the criteria for being moved to the WHERE ** clause. If so, add it to the WHERE clause and replace the sub-expression ** within the HAVING expression with a constant "1". */ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pExpr->op!=TK_AND ){ - Select *pS = pWalker->u.pSelect; - /* This routine is called before the HAVING clause of the current - ** SELECT is analyzed for aggregates. So if pExpr->pAggInfo is set - ** here, it indicates that the expression is a correlated reference to a - ** column from an outer aggregate query, or an aggregate function that - ** belongs to an outer query. Do not move the expression to the WHERE - ** clause in this obscure case, as doing so may corrupt the outer Select - ** statements AggInfo structure. */ - if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) - && ExprAlwaysFalse(pExpr)==0 - && pExpr->pAggInfo==0 - ){ + struct HavingToWhereCtx *p = pWalker->u.pHavingCtx; + if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){ sqlite3 *db = pWalker->pParse->db; - Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); + Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0); if( pNew ){ - Expr *pWhere = pS->pWhere; + Expr *pWhere = *(p->ppWhere); SWAP(Expr, *pNew, *pExpr); - pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew); - pS->pWhere = pNew; - pWalker->eCode = 1; + pNew = sqlite3ExprAnd(db, pWhere, pNew); + *(p->ppWhere) = pNew; } } return WRC_Prune; } return WRC_Continue; @@ -150924,80 +122325,58 @@ ** ** A term of the HAVING expression is eligible for transfer if it consists ** entirely of constants and expressions that are also GROUP BY terms that ** use the "BINARY" collation sequence. */ -static void havingToWhere(Parse *pParse, Select *p){ +static void havingToWhere( + Parse *pParse, + ExprList *pGroupBy, + Expr *pHaving, + Expr **ppWhere +){ + struct HavingToWhereCtx sCtx; Walker sWalker; + + sCtx.ppWhere = ppWhere; + sCtx.pGroupBy = pGroupBy; + memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.xExprCallback = havingToWhereExprCb; - sWalker.u.pSelect = p; - sqlite3WalkExpr(&sWalker, p->pHaving); -#if TREETRACE_ENABLED - if( sWalker.eCode && (sqlite3TreeTrace & 0x100)!=0 ){ - TREETRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif + sWalker.u.pHavingCtx = &sCtx; + sqlite3WalkExpr(&sWalker, pHaving); } /* -** Check to see if the pThis entry of pTabList is a self-join of another view. -** Search FROM-clause entries in the range of iFirst..iEnd, including iFirst -** but stopping before iEnd. -** -** If pThis is a self-join, then return the SrcItem for the first other -** instance of that view found. If pThis is not a self-join then return 0. +** Check to see if the pThis entry of pTabList is a self-join of a prior view. +** If it is, then return the SrcList_item for the prior view. If it is not, +** then return 0. */ -static SrcItem *isSelfJoinView( +static struct SrcList_item *isSelfJoinView( SrcList *pTabList, /* Search for self-joins in this FROM clause */ - SrcItem *pThis, /* Search for prior reference to this subquery */ - int iFirst, int iEnd /* Range of FROM-clause entries to search. */ + struct SrcList_item *pThis /* Search for prior reference to this subquery */ ){ - SrcItem *pItem; - Select *pSel; - assert( pThis->fg.isSubquery ); - pSel = pThis->u4.pSubq->pSelect; - assert( pSel!=0 ); - if( pSel->selFlags & SF_PushDown ) return 0; - while( iFirsta[iFirst++]; - if( !pItem->fg.isSubquery ) continue; + struct SrcList_item *pItem; + for(pItem = pTabList->a; pItempSelect==0 ) continue; if( pItem->fg.viaCoroutine ) continue; if( pItem->zName==0 ) continue; - assert( pItem->pSTab!=0 ); - assert( pThis->pSTab!=0 ); - if( pItem->pSTab->pSchema!=pThis->pSTab->pSchema ) continue; + if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue; if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue; - pS1 = pItem->u4.pSubq->pSelect; - if( pItem->pSTab->pSchema==0 && pSel->selId!=pS1->selId ){ - /* The query flattener left two different CTE tables with identical - ** names in the same FROM clause. */ - continue; - } - if( pS1->selFlags & SF_PushDown ){ + if( sqlite3ExprCompare(0, + pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) + ){ /* The view was modified by some other optimization such as ** pushDownWhereTerms() */ continue; } return pItem; } return 0; } -/* -** Deallocate a single AggInfo object -*/ -static void agginfoFree(sqlite3 *db, void *pArg){ - AggInfo *p = (AggInfo*)pArg; - sqlite3DbFree(db, p->aCol); - sqlite3DbFree(db, p->aFunc); - sqlite3DbFreeNN(db, p); -} - +#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION /* ** Attempt to transform a query of the form ** ** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) ** @@ -151006,57 +122385,44 @@ ** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2) ** ** The transformation only works if all of the following are true: ** ** * The subquery is a UNION ALL of two or more terms -** * The subquery does not have a LIMIT clause ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries -** * The outer query is a simple count(*) with no WHERE clause or other -** extraneous syntax. +** * The outer query is a simple count(*) ** ** Return TRUE if the optimization is undertaken. */ static int countOfViewOptimization(Parse *pParse, Select *p){ Select *pSub, *pPrior; Expr *pExpr; Expr *pCount; sqlite3 *db; - SrcItem *pFrom; - if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ + if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */ if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ - if( p->pWhere ) return 0; - if( p->pHaving ) return 0; - if( p->pGroupBy ) return 0; - if( p->pOrderBy ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ - assert( ExprUseUToken(pExpr) ); - if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */ - assert( ExprUseXList(pExpr) ); + if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */ if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ - if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */ - if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */ - pFrom = p->pSrc->a; - if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */ - pSub = pFrom->u4.pSubq->pSelect; - if( pSub->pPrior==0 ) return 0; /* Must be a compound */ - if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */ + if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */ + pSub = p->pSrc->a[0].pSelect; + if( pSub==0 ) return 0; /* The FROM is a subquery */ + if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */ do{ if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ if( pSub->pWhere ) return 0; /* No WHERE clause */ - if( pSub->pLimit ) return 0; /* No LIMIT clause */ if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */ - assert( pSub->pHaving==0 ); /* Due to the previous */ - pSub = pSub->pPrior; /* Repeat over compound */ + pSub = pSub->pPrior; /* Repeat over compound terms */ }while( pSub ); - /* If we reach this point then it is OK to perform the transformation */ + /* If we reach this point, that means it is OK to perform the transformation */ db = pParse->db; pCount = pExpr; pExpr = 0; - pSub = sqlite3SubqueryDetach(db, pFrom); + pSub = p->pSrc->a[0].pSelect; + p->pSrc->a[0].pSelect = 0; sqlite3SrcListDelete(db, p->pSrc); p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc)); while( pSub ){ Expr *pTerm; pPrior = pSub->pPrior; @@ -151063,11 +122429,11 @@ pSub->pPrior = 0; pSub->pNext = 0; pSub->selFlags |= SF_Aggregate; pSub->selFlags &= ~SF_Compound; pSub->nSelectRow = 0; - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList); + sqlite3ExprListDelete(db, pSub->pEList); pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0); sqlite3PExprAddSelect(pParse, pTerm, pSub); if( pExpr==0 ){ @@ -151078,106 +122444,22 @@ pSub = pPrior; } p->pEList->a[0].pExpr = pExpr; p->selFlags &= ~SF_Aggregate; -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x200 ){ - TREETRACE(0x200,pParse,p,("After count-of-view optimization:\n")); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif return 1; } - -/* -** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same -** as pSrcItem but has the same alias as p0, then return true. -** Otherwise return false. -*/ -static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ - int i; - for(i=0; inSrc; i++){ - SrcItem *p1 = &pSrc->a[i]; - if( p1==p0 ) continue; - if( p0->pSTab==p1->pSTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){ - return 1; - } - if( p1->fg.isSubquery - && (p1->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 - && sameSrcAlias(p0, p1->u4.pSubq->pSelect->pSrc) - ){ - return 1; - } - } - return 0; -} - -/* -** Return TRUE (non-zero) if the i-th entry in the pTabList SrcList can -** be implemented as a co-routine. The i-th entry is guaranteed to be -** a subquery. -** -** The subquery is implemented as a co-routine if all of the following are -** true: -** -** (1) The subquery will likely be implemented in the outer loop of -** the query. This will be the case if any one of the following -** conditions hold: -** (a) The subquery is the only term in the FROM clause -** (b) The subquery is the left-most term and a CROSS JOIN or similar -** requires it to be the outer loop -** (c) All of the following are true: -** (i) The subquery is the left-most subquery in the FROM clause -** (ii) There is nothing that would prevent the subquery from -** being used as the outer loop if the sqlite3WhereBegin() -** routine nominates it to that position. -** (iii) The query is not a UPDATE ... FROM -** (2) The subquery is not a CTE that should be materialized because -** (a) the AS MATERIALIZED keyword is used, or -** (b) the CTE is used multiple times and does not have the -** NOT MATERIALIZED keyword -** (3) The subquery is not part of a left operand for a RIGHT JOIN -** (4) The SQLITE_Coroutine optimization disable flag is not set -** (5) The subquery is not self-joined -*/ -static int fromClauseTermCanBeCoroutine( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* FROM clause */ - int i, /* Which term of the FROM clause holds the subquery */ - int selFlags /* Flags on the SELECT statement */ -){ - SrcItem *pItem = &pTabList->a[i]; - if( pItem->fg.isCte ){ - const CteUse *pCteUse = pItem->u2.pCteUse; - if( pCteUse->eM10d==M10d_Yes ) return 0; /* (2a) */ - if( pCteUse->nUse>=2 && pCteUse->eM10d!=M10d_No ) return 0; /* (2b) */ - } - if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ - if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ - if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){ - return 0; /* (5) */ - } - if( i==0 ){ - if( pTabList->nSrc==1 ) return 1; /* (1a) */ - if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1b) */ - if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ - return 1; - } - if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ - while( 1 /*exit-by-break*/ ){ - if( pItem->fg.jointype & (JT_OUTER|JT_CROSS) ) return 0; /* (1c-ii) */ - if( i==0 ) break; - i--; - pItem--; - if( pItem->fg.isSubquery ) return 0; /* (1c-i) */ - } - return 1; -} - -/* -** Generate byte-code for the SELECT statement given in the p argument. +#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */ + +/* +** Generate code for the SELECT statement given in the p argument. ** ** The results are returned according to the SelectDest structure. ** See comments in sqliteInt.h for further information. ** ** This routine returns the number of errors. If any errors are @@ -151184,44 +122466,10 @@ ** encountered, then an appropriate error message is left in ** pParse->zErrMsg. ** ** This routine does NOT free the Select structure passed in. The ** calling function needs to do that. -** -** This is a long function. The following is an outline of the processing -** steps, with tags referencing various milestones: -** -** * Resolve names and similar preparation tag-select-0100 -** * Scan of the FROM clause tag-select-0200 -** + OUTER JOIN strength reduction tag-select-0220 -** + Sub-query ORDER BY removal tag-select-0230 -** + Query flattening tag-select-0240 -** * Separate subroutine for compound-SELECT tag-select-0300 -** * WHERE-clause constant propagation tag-select-0330 -** * Count()-of-VIEW optimization tag-select-0350 -** * Scan of the FROM clause again tag-select-0400 -** + Authorize unreferenced tables tag-select-0410 -** + Predicate push-down optimization tag-select-0420 -** + Omit unused subquery columns optimization tag-select-0440 -** + Generate code to implement subqueries tag-select-0480 -** - Co-routines tag-select-0482 -** - Reuse previously computed CTE tag-select-0484 -** - REuse previously computed VIEW tag-select-0486 -** - Materialize a VIEW or CTE tag-select-0488 -** * DISTINCT ORDER BY -> GROUP BY optimization tag-select-0500 -** * Set up for ORDER BY tag-select-0600 -** * Create output table tag-select-0630 -** * Prepare registers for LIMIT tag-select-0650 -** * Setup for DISTINCT tag-select-0680 -** * Generate code for non-aggregate and non-GROUP BY tag-select-0700 -** * Generate code for aggregate and/or GROUP BY tag-select-0800 -** + GROUP BY queries tag-select-0810 -** + non-GROUP BY queries tag-select-0820 -** - Special case of count() w/o GROUP BY tag-select-0821 -** - General case of non-GROUP BY aggregates tag-select-0822 -** * Sort results, as needed tag-select-0900 -** * Internal self-checks tag-select-1000 */ SQLITE_PRIVATE int sqlite3Select( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ SelectDest *pDest /* What to do with the query results */ @@ -151233,191 +122481,75 @@ ExprList *pEList = 0; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ Expr *pHaving; /* The HAVING clause. May be NULL */ - AggInfo *pAggInfo = 0; /* Aggregate information */ - int rc = 1; /* Value to return from this function */ - DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ - SortCtx sSort; /* Info on how to code the ORDER BY clause */ - int iEnd; /* Address of the end of the query */ - sqlite3 *db; /* The database connection */ - ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ - u8 minMaxFlag; /* Flag for min/max queries */ - - db = pParse->db; - assert( pParse==db->pParse ); - v = sqlite3GetVdbe(pParse); - if( p==0 || pParse->nErr ){ - return 1; - } - assert( db->mallocFailed==0 ); - if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; -#if TREETRACE_ENABLED - TREETRACE(0x1,pParse,p, ("begin processing:\n", pParse->addrExplain)); - if( sqlite3TreeTrace & 0x10000 ){ - if( (sqlite3TreeTrace & 0x10001)==0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Select() at %s:%d", - __FILE__, __LINE__); - } - sqlite3ShowSelect(p); - } -#endif - - /* tag-select-0100 */ - assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo ); - assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo ); - assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue ); - assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue ); - if( IgnorableDistinct(pDest) ){ - assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || - pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard || - pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo ); - /* All of these destinations are also able to ignore the ORDER BY clause */ - if( p->pOrderBy ){ -#if TREETRACE_ENABLED - TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n")); - if( sqlite3TreeTrace & 0x800 ){ - sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY"); - } -#endif - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, - p->pOrderBy); - testcase( pParse->earlyCleanup ); - p->pOrderBy = 0; - } - p->selFlags &= ~SF_Distinct; - p->selFlags |= SF_NoopOrderBy; - } - sqlite3SelectPrep(pParse, p, 0); - if( pParse->nErr ){ - goto select_end; - } - assert( db->mallocFailed==0 ); - assert( p->pEList!=0 ); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10 ){ - TREETRACE(0x10,pParse,p, ("after name resolution:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - - /* If the SF_UFSrcCheck flag is set, then this function is being called - ** as part of populating the temp table for an UPDATE...FROM statement. - ** In this case, it is an error if the target object (pSrc->a[0]) name - ** or alias is duplicated within FROM clause (pSrc->a[1..n]). - ** - ** Postgres disallows this case too. The reason is that some other - ** systems handle this case differently, and not all the same way, - ** which is just confusing. To avoid this, we follow PG's lead and - ** disallow it altogether. */ - if( p->selFlags & SF_UFSrcCheck ){ - SrcItem *p0 = &p->pSrc->a[0]; - if( sameSrcAlias(p0, p->pSrc) ){ - sqlite3ErrorMsg(pParse, - "target object/alias may not appear in FROM clause: %s", - p0->zAlias ? p0->zAlias : p0->pSTab->zName - ); - goto select_end; - } - - /* Clear the SF_UFSrcCheck flag. The check has already been performed, - ** and leaving this flag set can cause errors if a compound sub-query - ** in p->pSrc is flattened into this query and this function called - ** again as part of compound SELECT processing. */ - p->selFlags &= ~SF_UFSrcCheck; - } - - if( pDest->eDest==SRT_Output ){ - sqlite3GenerateColumnNames(pParse, p); - } - -#ifndef SQLITE_OMIT_WINDOWFUNC - if( sqlite3WindowRewrite(pParse, p) ){ - assert( pParse->nErr ); - goto select_end; - } -#if TREETRACE_ENABLED - if( p->pWin && (sqlite3TreeTrace & 0x40)!=0 ){ - TREETRACE(0x40,pParse,p, ("after window rewrite:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif -#endif /* SQLITE_OMIT_WINDOWFUNC */ - pTabList = p->pSrc; - isAgg = (p->selFlags & SF_Aggregate)!=0; - memset(&sSort, 0, sizeof(sSort)); - sSort.pOrderBy = p->pOrderBy; - - /* Try to do various optimizations (flattening subqueries, and strength - ** reduction of join operators) in the FROM clause up into the main query - ** tag-select-0200 - */ -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - for(i=0; !p->pPrior && inSrc; i++){ - SrcItem *pItem = &pTabList->a[i]; - Select *pSub = pItem->fg.isSubquery ? pItem->u4.pSubq->pSelect : 0; - Table *pTab = pItem->pSTab; - - /* The expander should have already created transient Table objects - ** even for FROM clause elements such as subqueries that do not correspond - ** to a real table */ - assert( pTab!=0 ); - - /* Try to simplify joins: - ** - ** LEFT JOIN -> JOIN - ** RIGHT JOIN -> JOIN - ** FULL JOIN -> RIGHT JOIN - ** - ** If terms of the i-th table are used in the WHERE clause in such a - ** way that the i-th table cannot be the NULL row of a join, then - ** perform the appropriate simplification. This is called - ** "OUTER JOIN strength reduction" in the SQLite documentation. - ** tag-select-0220 - */ - if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 - && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor, - pItem->fg.jointype & JT_LTORJ) - && OptimizationEnabled(db, SQLITE_SimplifyJoin) - ){ - if( pItem->fg.jointype & JT_LEFT ){ - if( pItem->fg.jointype & JT_RIGHT ){ - TREETRACE(0x1000,pParse,p, - ("FULL-JOIN simplifies to RIGHT-JOIN on term %d\n",i)); - pItem->fg.jointype &= ~JT_LEFT; - }else{ - TREETRACE(0x1000,pParse,p, - ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); - pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); - unsetJoinExpr(p->pWhere, pItem->iCursor, 0); - } - } - if( pItem->fg.jointype & JT_LTORJ ){ - for(j=i+1; jnSrc; j++){ - SrcItem *pI2 = &pTabList->a[j]; - if( pI2->fg.jointype & JT_RIGHT ){ - if( pI2->fg.jointype & JT_LEFT ){ - TREETRACE(0x1000,pParse,p, - ("FULL-JOIN simplifies to LEFT-JOIN on term %d\n",j)); - pI2->fg.jointype &= ~JT_RIGHT; - }else{ - TREETRACE(0x1000,pParse,p, - ("RIGHT-JOIN simplifies to JOIN on term %d\n",j)); - pI2->fg.jointype &= ~(JT_RIGHT|JT_OUTER); - unsetJoinExpr(p->pWhere, pI2->iCursor, 1); - } - } - } - for(j=pTabList->nSrc-1; j>=0; j--){ - pTabList->a[j].fg.jointype &= ~JT_LTORJ; - if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; - } - } - } - - /* No further action if this term of the FROM clause is not a subquery */ + int rc = 1; /* Value to return from this function */ + DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ + SortCtx sSort; /* Info on how to code the ORDER BY clause */ + AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ + sqlite3 *db; /* The database connection */ + +#ifndef SQLITE_OMIT_EXPLAIN + int iRestoreSelectId = pParse->iSelectId; + pParse->iSelectId = pParse->iNextSelectId++; +#endif + + db = pParse->db; + if( p==0 || db->mallocFailed || pParse->nErr ){ + return 1; + } + if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + memset(&sAggInfo, 0, sizeof(sAggInfo)); +#if SELECTTRACE_ENABLED + pParse->nSelectIndent++; + SELECTTRACE(1,pParse,p, ("begin processing:\n")); + if( sqlite3SelectTrace & 0x100 ){ + sqlite3TreeViewSelect(0, p, 0); + } +#endif + + assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo ); + assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo ); + assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue ); + assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue ); + if( IgnorableOrderby(pDest) ){ + assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || + pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard || + pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo || + pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo); + /* If ORDER BY makes no difference in the output then neither does + ** DISTINCT so it can be removed too. */ + sqlite3ExprListDelete(db, p->pOrderBy); + p->pOrderBy = 0; + p->selFlags &= ~SF_Distinct; + } + sqlite3SelectPrep(pParse, p, 0); + memset(&sSort, 0, sizeof(sSort)); + sSort.pOrderBy = p->pOrderBy; + pTabList = p->pSrc; + if( pParse->nErr || db->mallocFailed ){ + goto select_end; + } + assert( p->pEList!=0 ); + isAgg = (p->selFlags & SF_Aggregate)!=0; +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + + /* Try to flatten subqueries in the FROM clause up into the main query + */ +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + for(i=0; !p->pPrior && inSrc; i++){ + struct SrcList_item *pItem = &pTabList->a[i]; + Select *pSub = pItem->pSelect; + int isAggSub; + Table *pTab = pItem->pTab; if( pSub==0 ) continue; /* Catch mismatch in the declared columns of a view and the number of ** columns in the SELECT on the RHS */ if( pTab->nCol!=pSub->pEList->nExpr ){ @@ -151424,212 +122556,97 @@ sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", pTab->nCol, pTab->zName, pSub->pEList->nExpr); goto select_end; } - /* Do not attempt the usual optimizations (flattening and ORDER BY - ** elimination) on a MATERIALIZED common table expression because - ** a MATERIALIZED common table expression is an optimization fence. - */ - if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){ - continue; - } - - /* Do not try to flatten an aggregate subquery. - ** - ** Flattening an aggregate subquery is only possible if the outer query - ** is not a join. But if the outer query is not a join, then the subquery - ** will be implemented as a co-routine and there is no advantage to - ** flattening in that case. - */ - if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; - assert( pSub->pGroupBy==0 ); - - /* tag-select-0230: - ** If a FROM-clause subquery has an ORDER BY clause that is not - ** really doing anything, then delete it now so that it does not - ** interfere with query flattening. See the discussion at - ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a - ** - ** Beware of these cases where the ORDER BY clause may not be safely - ** omitted: - ** - ** (1) There is also a LIMIT clause - ** (2) The subquery was added to help with window-function - ** processing - ** (3) The subquery is in the FROM clause of an UPDATE - ** (4) The outer query uses an aggregate function other than - ** the built-in count(), min(), or max(). - ** (5) The ORDER BY isn't going to accomplish anything because - ** one of: - ** (a) The outer query has a different ORDER BY clause - ** (b) The subquery is part of a join - ** See forum post 062d576715d277c8 - ** (6) The subquery is not a recursive CTE. ORDER BY has a different - ** meaning for recursive CTEs and this optimization does not - ** apply. - ** - ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled. - */ - if( pSub->pOrderBy!=0 - && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ - && pSub->pLimit==0 /* Condition (1) */ - && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0 /* (2) and (6) */ - && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */ - && OptimizationEnabled(db, SQLITE_OmitOrderBy) - ){ - TREETRACE(0x800,pParse,p, - ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1)); - sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, - pSub->pOrderBy); - pSub->pOrderBy = 0; - } - - /* If the outer query contains a "complex" result set (that is, - ** if the result set of the outer query uses functions or subqueries) - ** and if the subquery contains an ORDER BY clause and if - ** it will be implemented as a co-routine, then do not flatten. This - ** restriction allows SQL constructs like this: - ** - ** SELECT expensive_function(x) - ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10); - ** - ** The expensive_function() is only computed on the 10 rows that - ** are output, rather than every row of the table. - ** - ** The requirement that the outer query have a complex result set - ** means that flattening does occur on simpler SQL constraints without - ** the expensive_function() like: - ** - ** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10); - */ - if( pSub->pOrderBy!=0 - && i==0 - && (p->selFlags & SF_ComplexResult)!=0 - && (pTabList->nSrc==1 - || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) - ){ - continue; - } - - /* tag-select-0240 */ - if( flattenSubquery(pParse, p, i, isAgg) ){ - if( pParse->nErr ) goto select_end; + isAggSub = (pSub->selFlags & SF_Aggregate)!=0; + if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ /* This subquery can be absorbed into its parent. */ + if( isAggSub ){ + isAgg = 1; + p->selFlags |= SF_Aggregate; + } i = -1; } pTabList = p->pSrc; if( db->mallocFailed ) goto select_end; if( !IgnorableOrderby(pDest) ){ sSort.pOrderBy = p->pOrderBy; } } #endif + + /* Get a pointer the VDBE under construction, allocating a new VDBE if one + ** does not already exist */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto select_end; #ifndef SQLITE_OMIT_COMPOUND_SELECT /* Handle compound SELECT statements using the separate multiSelect() - ** procedure. tag-select-0300 + ** procedure. */ if( p->pPrior ){ rc = multiSelect(pParse, p, pDest); -#if TREETRACE_ENABLED - TREETRACE(0x400,pParse,p,("end compound-select processing\n")); - if( (sqlite3TreeTrace & 0x400)!=0 && ExplainQueryPlanParent(pParse)==0 ){ - sqlite3TreeViewSelect(0, p, 0); - } + explainSetInteger(pParse->iSelectId, iRestoreSelectId); +#if SELECTTRACE_ENABLED + SELECTTRACE(1,pParse,p,("end compound-select processing\n")); + pParse->nSelectIndent--; #endif - if( p->pNext==0 ) ExplainQueryPlanPop(pParse); return rc; } #endif - /* Do the WHERE-clause constant propagation optimization if this is - ** a join. No need to spend time on this operation for non-join queries - ** as the equivalent optimization will be handled by query planner in - ** sqlite3WhereBegin(). tag-select-0330 - */ - if( p->pWhere!=0 - && p->pWhere->op==TK_AND - && OptimizationEnabled(db, SQLITE_PropagateConst) - && propagateConstants(pParse, p) - ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x2000 ){ - TREETRACE(0x2000,pParse,p,("After constant propagation:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - }else{ - TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n")); - } - - /* tag-select-0350 */ - if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) - && countOfViewOptimization(pParse, p) - ){ - if( db->mallocFailed ) goto select_end; - pTabList = p->pSrc; - } - - /* Loop over all terms in the FROM clause and do two things for each term: - ** - ** (1) Authorize unreferenced tables - ** (2) Generate code for all sub-queries - ** - ** tag-select-0400 + /* For each term in the FROM clause, do two things: + ** (1) Authorized unreferenced tables + ** (2) Generate code for all sub-queries */ for(i=0; inSrc; i++){ - SrcItem *pItem = &pTabList->a[i]; - SrcItem *pPrior; + struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; - Subquery *pSubq; Select *pSub; -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - const char *zSavedAuthContext; -#endif - - /* Authorized unreferenced tables. tag-select-0410 - ** - ** Issue SQLITE_READ authorizations with a fake column name for any - ** tables that are referenced but from which no values are extracted. - ** Examples of where these kinds of null SQLITE_READ authorizations - ** would occur: + + /* Issue SQLITE_READ authorizations with a fake column name for any tables that + ** are referenced but from which no values are extracted. Examples of where these + ** kinds of null SQLITE_READ authorizations would occur: ** ** SELECT count(*) FROM t1; -- SQLITE_READ t1."" ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2."" ** ** The fake column name is an empty string. It is possible for a table to ** have a column named by the empty string, in which case there is no way to ** distinguish between an unreferenced table and an actual reference to the - ** "" column. The original design was for the fake column name to be a NULL, + ** "" column. The original design was for the fake column name to be a NULL, ** which would be unambiguous. But legacy authorization callbacks might - ** assume the column name is non-NULL and segfault. The use of an empty - ** string for the fake column name seems safer. + ** assume the column name is non-NULL and segfault. The use of an empty string + ** for the fake column name seems safer. */ - if( pItem->colUsed==0 && pItem->zName!=0 ){ - const char *zDb; - if( pItem->fg.fixedSchema ){ - int iDb = sqlite3SchemaToIndex(pParse->db, pItem->u4.pSchema); - zDb = db->aDb[iDb].zDbSName; - }else if( pItem->fg.isSubquery ){ - zDb = 0; - }else{ - zDb = pItem->u4.zDatabase; - } - sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", zDb); + if( pItem->colUsed==0 ){ + sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase); } #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Generate code for all sub-queries in the FROM clause */ - if( pItem->fg.isSubquery==0 ) continue; - pSubq = pItem->u4.pSubq; - assert( pSubq!=0 ); - pSub = pSubq->pSelect; + pSub = pItem->pSelect; + if( pSub==0 ) continue; - /* The code for a subquery should only be generated once. */ - if( pSubq->addrFillSub!=0 ) continue; + /* Sometimes the code for a subquery will be generated more than + ** once, if the subquery is part of the WHERE clause in a LEFT JOIN, + ** for example. In that case, do not regenerate the code to manifest + ** a view or the co-routine to implement a view. The first instance + ** is sufficient, though the subroutine to manifest the view does need + ** to be invoked again. */ + if( pItem->addrFillSub ){ + if( pItem->fg.viaCoroutine==0 ){ + /* The subroutine that manifests the view might be a one-time routine, + ** or it might need to be rerun on each iteration because it + ** encodes a correlated subquery. */ + testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once ); + sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); + } + continue; + } /* Increment Parse.nHeight by the height of the largest expression ** tree referred to by this, the parent select. The child select ** may contain expression trees of at most ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit @@ -151638,141 +122655,103 @@ */ pParse->nHeight += sqlite3SelectExprHeight(p); /* Make copies of constant WHERE-clause terms in the outer query down ** inside the subquery. This can help the subquery to run more efficiently. - ** This is the "predicate push-down optimization". tag-select-0420 - */ - if( OptimizationEnabled(db, SQLITE_PushDown) - && (pItem->fg.isCte==0 - || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2)) - && pushDownWhereTerms(pParse, pSub, p->pWhere, pTabList, i) - ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x4000 ){ - TREETRACE(0x4000,pParse,p, - ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 ); - }else{ - TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n")); - } - - /* Convert unused result columns of the subquery into simple NULL - ** expressions, to avoid unneeded searching and computation. - ** tag-select-0440 - */ - if( OptimizationEnabled(db, SQLITE_NullUnusedCols) - && disableUnusedSubqueryResultColumns(pItem) - ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x4000 ){ - TREETRACE(0x4000,pParse,p, - ("Change unused result columns to NULL for subquery %d:\n", - pSub->selId)); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - } - - zSavedAuthContext = pParse->zAuthContext; - pParse->zAuthContext = pItem->zName; - - /* Generate byte-code to implement the subquery tag-select-0480 - */ - if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){ - /* Implement a co-routine that will return a single row of the result - ** set on each invocation. tag-select-0482 - */ - int addrTop = sqlite3VdbeCurrentAddr(v)+1; - - pSubq->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, pSubq->regReturn, 0, addrTop); - VdbeComment((v, "%!S", pItem)); - pSubq->addrFillSub = addrTop; - sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn); - ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem)); - sqlite3Select(pParse, pSub, &dest); - pItem->pSTab->nRowLogEst = pSub->nSelectRow; - pItem->fg.viaCoroutine = 1; - pSubq->regResult = dest.iSdst; - sqlite3VdbeEndCoroutine(v, pSubq->regReturn); - VdbeComment((v, "end %!S", pItem)); - sqlite3VdbeJumpHere(v, addrTop-1); - sqlite3ClearTempRegCache(pParse); - }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){ - /* This is a CTE for which materialization code has already been - ** generated. Invoke the subroutine to compute the materialization, - ** then make the pItem->iCursor be a copy of the ephemeral table that - ** holds the result of the materialization. tag-select-0484 */ - CteUse *pCteUse = pItem->u2.pCteUse; - sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e); - if( pItem->iCursor!=pCteUse->iCur ){ - sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur); - VdbeComment((v, "%!S", pItem)); - } - pSub->nSelectRow = pCteUse->nRowEst; - }else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){ - /* This view has already been materialized by a prior entry in - ** this same FROM clause. Reuse it. tag-select-0486 */ - Subquery *pPriorSubq; - assert( pPrior->fg.isSubquery ); - pPriorSubq = pPrior->u4.pSubq; - assert( pPriorSubq!=0 ); - if( pPriorSubq->addrFillSub ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pPriorSubq->regReturn, - pPriorSubq->addrFillSub); - } - sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); - pSub->nSelectRow = pPriorSubq->pSelect->nSelectRow; - }else{ - /* Materialize the view. If the view is not correlated, generate a - ** subroutine to do the materialization so that subsequent uses of - ** the same view can reuse the materialization. tag-select-0488 */ - int topAddr; - int onceAddr = 0; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; -#endif - - pSubq->regReturn = ++pParse->nMem; - topAddr = sqlite3VdbeAddOp0(v, OP_Goto); - pSubq->addrFillSub = topAddr+1; - pItem->fg.isMaterialized = 1; - if( pItem->fg.isCorrelated==0 ){ - /* If the subquery is not correlated and if we are not inside of - ** a trigger, then we only need to compute the value of the subquery - ** once. */ - onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - VdbeComment((v, "materialize %!S", pItem)); - }else{ - VdbeNoopComment((v, "materialize %!S", pItem)); - } - sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - - ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem)); - sqlite3Select(pParse, pSub, &dest); - pItem->pSTab->nRowLogEst = pSub->nSelectRow; - if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); - sqlite3VdbeAddOp2(v, OP_Return, pSubq->regReturn, topAddr+1); - VdbeComment((v, "end %!S", pItem)); - sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); - sqlite3VdbeJumpHere(v, topAddr); - sqlite3ClearTempRegCache(pParse); - if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){ - CteUse *pCteUse = pItem->u2.pCteUse; - pCteUse->addrM9e = pSubq->addrFillSub; - pCteUse->regRtn = pSubq->regReturn; - pCteUse->iCur = pItem->iCursor; - pCteUse->nRowEst = pSub->nSelectRow; - } - } - if( db->mallocFailed ) goto select_end; - pParse->nHeight -= sqlite3SelectExprHeight(p); - pParse->zAuthContext = zSavedAuthContext; + */ + if( (pItem->fg.jointype & JT_OUTER)==0 + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) + ){ +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + } + + /* Generate code to implement the subquery + ** + ** The subquery is implemented as a co-routine if all of these are true: + ** (1) The subquery is guaranteed to be the outer loop (so that it + ** does not need to be computed more than once) + ** (2) The ALL keyword after SELECT is omitted. (Applications are + ** allowed to say "SELECT ALL" instead of just "SELECT" to disable + ** the use of co-routines.) + ** (3) Co-routines are not disabled using sqlite3_test_control() + ** with SQLITE_TESTCTRL_OPTIMIZATIONS. + ** + ** TODO: Are there other reasons beside (1) to use a co-routine + ** implementation? + */ + if( i==0 + && (pTabList->nSrc==1 + || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ + && (p->selFlags & SF_All)==0 /* (2) */ + && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */ + ){ + /* Implement a co-routine that will return a single row of the result + ** set on each invocation. + */ + int addrTop = sqlite3VdbeCurrentAddr(v)+1; + pItem->regReturn = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); + VdbeComment((v, "%s", pItem->pTab->zName)); + pItem->addrFillSub = addrTop; + sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); + explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); + sqlite3Select(pParse, pSub, &dest); + pItem->pTab->nRowLogEst = pSub->nSelectRow; + pItem->fg.viaCoroutine = 1; + pItem->regResult = dest.iSdst; + sqlite3VdbeEndCoroutine(v, pItem->regReturn); + sqlite3VdbeJumpHere(v, addrTop-1); + sqlite3ClearTempRegCache(pParse); + }else{ + /* Generate a subroutine that will fill an ephemeral table with + ** the content of this subquery. pItem->addrFillSub will point + ** to the address of the generated subroutine. pItem->regReturn + ** is a register allocated to hold the subroutine return address + */ + int topAddr; + int onceAddr = 0; + int retAddr; + struct SrcList_item *pPrior; + + assert( pItem->addrFillSub==0 ); + pItem->regReturn = ++pParse->nMem; + topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); + pItem->addrFillSub = topAddr+1; + if( pItem->fg.isCorrelated==0 ){ + /* If the subquery is not correlated and if we are not inside of + ** a trigger, then we only need to compute the value of the subquery + ** once. */ + onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); + }else{ + VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); + } + pPrior = isSelfJoinView(pTabList, pItem); + if( pPrior ){ + sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); + explainSetInteger(pItem->iSelectId, pPrior->iSelectId); + assert( pPrior->pSelect!=0 ); + pSub->nSelectRow = pPrior->pSelect->nSelectRow; + }else{ + sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); + explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); + sqlite3Select(pParse, pSub, &dest); + } + pItem->pTab->nRowLogEst = pSub->nSelectRow; + if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); + retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); + VdbeComment((v, "end %s", pItem->pTab->zName)); + sqlite3VdbeChangeP1(v, topAddr, retAddr); + sqlite3ClearTempRegCache(pParse); + } + if( db->mallocFailed ) goto select_end; + pParse->nHeight -= sqlite3SelectExprHeight(p); #endif } /* Various elements of the SELECT copied into local variables for ** convenience */ @@ -151780,58 +122759,55 @@ pWhere = p->pWhere; pGroupBy = p->pGroupBy; pHaving = p->pHaving; sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x8000 ){ - TREETRACE(0x8000,pParse,p,("After all FROM-clause analysis:\n")); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif - /* tag-select-0500 - ** - ** If the query is DISTINCT with an ORDER BY but is not an aggregate, and +#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION + if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) + && countOfViewOptimization(pParse, p) + ){ + if( db->mallocFailed ) goto select_end; + pEList = p->pEList; + pTabList = p->pSrc; + } +#endif + + /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and ** if the select-list is the same as the ORDER BY list, then this query ** can be rewritten as a GROUP BY. In other words, this: ** ** SELECT DISTINCT xyz FROM ... ORDER BY xyz ** ** is transformed to: ** ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz ** - ** The second form is preferred as a single index (or temp-table) may be - ** used for both the ORDER BY and DISTINCT processing. As originally - ** written the query must use a temp-table for at least one of the ORDER + ** The second form is preferred as a single index (or temp-table) may be + ** used for both the ORDER BY and DISTINCT processing. As originally + ** written the query must use a temp-table for at least one of the ORDER ** BY and DISTINCT, and an index or separate temp-table for the other. */ - if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct + if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 - && OptimizationEnabled(db, SQLITE_GroupByOrder) -#ifndef SQLITE_OMIT_WINDOWFUNC - && p->pWin==0 -#endif ){ p->selFlags &= ~SF_Distinct; pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); - if( pGroupBy ){ - for(i=0; inExpr; i++){ - pGroupBy->a[i].u.x.iOrderByCol = i+1; - } - } - p->selFlags |= SF_Aggregate; /* Notice that even thought SF_Distinct has been cleared from p->selFlags, ** the sDistinct.isTnct is still set. Hence, isTnct represents the ** original setting of the SF_Distinct flag, not the current setting */ assert( sDistinct.isTnct ); - sDistinct.isTnct = 2; -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20000 ){ - TREETRACE(0x20000,pParse,p,("Transform DISTINCT into GROUP BY:\n")); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif } @@ -151839,16 +122815,15 @@ ** do the sorting. But this sorting ephemeral index might end up ** being unused if the data can be extracted in pre-sorted order. ** If that is the case, then the OP_OpenEphemeral instruction will be ** changed to an OP_Noop once we figure out that the sorting index is ** not needed. The sSort.addrSortIndex variable is used to facilitate - ** that change. tag-select-0600 + ** that change. */ if( sSort.pOrderBy ){ KeyInfo *pKeyInfo; - pKeyInfo = sqlite3KeyInfoFromExprList( - pParse, sSort.pOrderBy, 0, pEList->nExpr); + pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); sSort.iECursor = pParse->nTab++; sSort.addrSortIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, (char*)pKeyInfo, P4_KEYINFO @@ -151856,130 +122831,84 @@ }else{ sSort.addrSortIndex = -1; } /* If the output is destined for a temporary table, open that table. - ** tag-select-0630 */ if( pDest->eDest==SRT_EphemTab ){ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr); - if( p->selFlags & SF_NestedFrom ){ - /* Delete or NULL-out result columns that will never be used */ - int ii; - for(ii=pEList->nExpr-1; ii>0 && pEList->a[ii].fg.bUsed==0; ii--){ - sqlite3ExprDelete(db, pEList->a[ii].pExpr); - sqlite3DbFree(db, pEList->a[ii].zEName); - pEList->nExpr--; - } - for(ii=0; iinExpr; ii++){ - if( pEList->a[ii].fg.bUsed==0 ) pEList->a[ii].pExpr->op = TK_NULL; - } - } - } - - /* Set the limiter. tag-select-0650 - */ - iEnd = sqlite3VdbeMakeLabel(pParse); + } + + /* Set the limiter. + */ + iEnd = sqlite3VdbeMakeLabel(v); if( (p->selFlags & SF_FixedLimit)==0 ){ p->nSelectRow = 320; /* 4 billion rows */ } - if( p->pLimit ) computeLimitRegisters(pParse, p, iEnd); + computeLimitRegisters(pParse, p, iEnd); if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); sSort.sortFlags |= SORTFLAG_UseSorter; } - /* Open an ephemeral index to use for the distinct set. tag-select-0680 + /* Open an ephemeral index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - sDistinct.tabTnct, 0, 0, - (char*)sqlite3KeyInfoFromExprList(pParse, p->pEList,0,0), - P4_KEYINFO); + sDistinct.tabTnct, 0, 0, + (char*)keyInfoFromExprList(pParse, p->pEList,0,0), + P4_KEYINFO); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; }else{ sDistinct.eTnctType = WHERE_DISTINCT_NOOP; } if( !isAgg && pGroupBy==0 ){ - /* No aggregate functions and no GROUP BY clause. tag-select-0700 */ - u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0) - | (p->selFlags & SF_FixedLimit); -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin = p->pWin; /* Main window object (or NULL) */ - if( pWin ){ - sqlite3WindowCodeInit(pParse, p); - } -#endif + /* No aggregate functions and no GROUP BY clause */ + u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0); assert( WHERE_USE_LIMIT==SF_FixedLimit ); - + wctrlFlags |= p->selFlags & SF_FixedLimit; /* Begin the database scan. */ - TREETRACE(0x2,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, - p->pEList, p, wctrlFlags, p->nSelectRow); + p->pEList, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); } if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){ sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo); } if( sSort.pOrderBy ){ sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); - sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo); + sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo); if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ sSort.pOrderBy = 0; } } - TREETRACE(0x2,pParse,p,("WhereBegin returns\n")); - /* If sorting index that was created by a prior OP_OpenEphemeral + /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); } - assert( p->pEList==pEList ); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin ){ - int addrGosub = sqlite3VdbeMakeLabel(pParse); - int iCont = sqlite3VdbeMakeLabel(pParse); - int iBreak = sqlite3VdbeMakeLabel(pParse); - int regGosub = ++pParse->nMem; - - sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub); - - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); - sqlite3VdbeResolveLabel(v, addrGosub); - VdbeNoopComment((v, "inner-loop subroutine")); - sSort.labelOBLopt = 0; - selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp1(v, OP_Return, regGosub); - VdbeComment((v, "end inner-loop subroutine")); - sqlite3VdbeResolveLabel(v, iBreak); - }else -#endif /* SQLITE_OMIT_WINDOWFUNC */ - { - /* Use the standard inner loop. */ - selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, - sqlite3WhereContinueLabel(pWInfo), - sqlite3WhereBreakLabel(pWInfo)); - - /* End the database scan loop. - */ - TREETRACE(0x2,pParse,p,("WhereEnd\n")); - sqlite3WhereEnd(pWInfo); - } - }else{ - /* This case is for when there exist aggregate functions or a GROUP BY - ** clause or both. tag-select-0800 */ + /* Use the standard inner loop. */ + selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest, + sqlite3WhereContinueLabel(pWInfo), + sqlite3WhereBreakLabel(pWInfo)); + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + }else{ + /* This case when there exist aggregate functions or a GROUP BY clause + ** or both */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ int iBMem; /* First Mem address for previous GROUP BY */ int iUseFlag; /* Mem address holding flag indicating that at least ** one row of the input to the aggregator has been @@ -152004,178 +122933,114 @@ for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){ pItem->u.x.iAlias = 0; } assert( 66==sqlite3LogEst(100) ); if( p->nSelectRow>66 ) p->nSelectRow = 66; - - /* If there is both a GROUP BY and an ORDER BY clause and they are - ** identical, then it may be possible to disable the ORDER BY clause - ** on the grounds that the GROUP BY will cause elements to come out - ** in the correct order. It also may not - the GROUP BY might use a - ** database index that causes rows to be grouped together as required - ** but not actually sorted. Either way, record the fact that the - ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp - ** variable. */ - if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){ - int ii; - /* The GROUP BY processing doesn't care whether rows are delivered in - ** ASC or DESC order - only that each group is returned contiguously. - ** So set the ASC/DESC flags in the GROUP BY to match those in the - ** ORDER BY to maximize the chances of rows being delivered in an - ** order that makes the ORDER BY redundant. */ - for(ii=0; iinExpr; ii++){ - u8 sortFlags; - sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; - pGroupBy->a[ii].fg.sortFlags = sortFlags; - } - if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ - orderByGrp = 1; - } - } }else{ assert( 0==sqlite3LogEst(1) ); p->nSelectRow = 0; } + /* If there is both a GROUP BY and an ORDER BY clause and they are + ** identical, then it may be possible to disable the ORDER BY clause + ** on the grounds that the GROUP BY will cause elements to come out + ** in the correct order. It also may not - the GROUP BY might use a + ** database index that causes rows to be grouped together as required + ** but not actually sorted. Either way, record the fact that the + ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp + ** variable. */ + if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ + orderByGrp = 1; + } + /* Create a label to jump to when we want to abort the query */ - addrEnd = sqlite3VdbeMakeLabel(pParse); + addrEnd = sqlite3VdbeMakeLabel(v); /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ - pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) ); - if( pAggInfo ){ - sqlite3ParserAddCleanup(pParse, agginfoFree, pAggInfo); - testcase( pParse->earlyCleanup ); - } - if( db->mallocFailed ){ - goto select_end; - } - pAggInfo->selId = p->selId; -#ifdef SQLITE_DEBUG - pAggInfo->pSelect = p; -#endif memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; - sNC.uNC.pAggInfo = pAggInfo; - VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) - pAggInfo->nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; - pAggInfo->pGroupBy = pGroupBy; + sNC.pAggInfo = &sAggInfo; + sAggInfo.mnReg = pParse->nMem+1; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; + sAggInfo.pGroupBy = pGroupBy; sqlite3ExprAnalyzeAggList(&sNC, pEList); sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy); if( pHaving ){ if( pGroupBy ){ assert( pWhere==p->pWhere ); - assert( pHaving==p->pHaving ); - assert( pGroupBy==p->pGroupBy ); - havingToWhere(pParse, p); + havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere); pWhere = p->pWhere; } sqlite3ExprAnalyzeAggregates(&sNC, pHaving); } - pAggInfo->nAccumulator = pAggInfo->nColumn; - if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){ - minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy); - }else{ - minMaxFlag = WHERE_ORDERBY_NORMAL; - } - analyzeAggFuncArgs(pAggInfo, &sNC); - if( db->mallocFailed ) goto select_end; -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - TREETRACE(0x20,pParse,p,("After aggregate analysis %p:\n", pAggInfo)); - sqlite3TreeViewSelect(0, p, 0); - if( minMaxFlag ){ - sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag); - sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY"); - } - printAggInfo(pAggInfo); - } -#endif - + sAggInfo.nAccumulator = sAggInfo.nColumn; + for(i=0; ix.pList); + sNC.ncFlags &= ~NC_InAggFunc; + } + sAggInfo.mxReg = pParse->nMem; + if( db->mallocFailed ) goto select_end; /* Processing for aggregates with GROUP BY is very different and - ** much more complex than aggregates without a GROUP BY. tag-select-0810 + ** much more complex than aggregates without a GROUP BY. */ if( pGroupBy ){ KeyInfo *pKeyInfo; /* Keying information for the group by clause */ - int addr1; /* A-vs-B comparison jump */ + int addr1; /* A-vs-B comparision jump */ int addrOutputRow; /* Start of subroutine that outputs a result row */ int regOutputRow; /* Return address register for output subroutine */ int addrSetAbort; /* Set the abort flag and return */ int addrTopOfLoop; /* Top of the input loop */ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ int addrReset; /* Subroutine for resetting the accumulator */ int regReset; /* Return address register for reset subroutine */ - ExprList *pDistinct = 0; - u16 distFlag = 0; - int eDist = WHERE_DISTINCT_NOOP; - - if( pAggInfo->nFunc==1 - && pAggInfo->aFunc[0].iDistinct>=0 - && ALWAYS(pAggInfo->aFunc[0].pFExpr!=0) - && ALWAYS(ExprUseXList(pAggInfo->aFunc[0].pFExpr)) - && pAggInfo->aFunc[0].pFExpr->x.pList!=0 - ){ - Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr; - pExpr = sqlite3ExprDup(db, pExpr, 0); - pDistinct = sqlite3ExprListDup(db, pGroupBy, 0); - pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr); - distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0; - } /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out ** that we do not need it after all, the OP_SorterOpen instruction - ** will be converted into a Noop. + ** will be converted into a Noop. */ - pAggInfo->sortingIdx = pParse->nTab++; - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pGroupBy, - 0, pAggInfo->nColumn); - addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, - pAggInfo->sortingIdx, pAggInfo->nSortingColumn, + sAggInfo.sortingIdx = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); + addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, + sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 0, (char*)pKeyInfo, P4_KEYINFO); /* Initialize memory locations used by GROUP BY aggregate processing */ iUseFlag = ++pParse->nMem; iAbortFlag = ++pParse->nMem; regOutputRow = ++pParse->nMem; - addrOutputRow = sqlite3VdbeMakeLabel(pParse); + addrOutputRow = sqlite3VdbeMakeLabel(v); regReset = ++pParse->nMem; - addrReset = sqlite3VdbeMakeLabel(pParse); + addrReset = sqlite3VdbeMakeLabel(v); iAMem = pParse->nMem + 1; pParse->nMem += pGroupBy->nExpr; iBMem = pParse->nMem + 1; pParse->nMem += pGroupBy->nExpr; sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); VdbeComment((v, "clear abort flag")); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); + VdbeComment((v, "indicate accumulator empty")); sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - TREETRACE(0x2,pParse,p,("WhereBegin\n")); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct, - p, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY) - | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0 + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, + WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 ); - if( pWInfo==0 ){ - sqlite3ExprListDelete(db, pDistinct); - goto select_end; - } - if( pParse->pIdxEpr ){ - optimizeAggregateUseOfIndexedExpr(pParse, p, pAggInfo, &sNC); - } - assignAggregateRegisters(pParse, pAggInfo); - eDist = sqlite3WhereIsDistinct(pWInfo); - TREETRACE(0x2,pParse,p,("WhereBegin returns\n")); + if( pWInfo==0 ) goto select_end; if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ @@ -152189,85 +123054,61 @@ int regBase; int regRecord; int nCol; int nGroupBy; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExp; /* Address of OP_Explain instruction */ -#endif - ExplainQueryPlan2(addrExp, (pParse, 0, "USE TEMP B-TREE FOR %s", + explainTempTable(pParse, (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? - "DISTINCT" : "GROUP BY" - )); + "DISTINCT" : "GROUP BY"); groupBySort = 1; nGroupBy = pGroupBy->nExpr; nCol = nGroupBy; j = nGroupBy; - for(i=0; inColumn; i++){ - if( pAggInfo->aCol[i].iSorterColumn>=j ){ + for(i=0; i=j ){ nCol++; j++; } } regBase = sqlite3GetTempRange(pParse, nCol); + sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); j = nGroupBy; - pAggInfo->directMode = 1; - for(i=0; inColumn; i++){ - struct AggInfo_col *pCol = &pAggInfo->aCol[i]; + for(i=0; iiSorterColumn>=j ){ - sqlite3ExprCode(pParse, pCol->pCExpr, j + regBase); + int r1 = j + regBase; + sqlite3ExprCodeGetColumnToReg(pParse, + pCol->pTab, pCol->iColumn, pCol->iTable, r1); j++; } } - pAggInfo->directMode = 0; regRecord = sqlite3GetTempReg(pParse); - sqlite3VdbeScanStatusCounters(v, addrExp, 0, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord); - sqlite3VdbeScanStatusRange(v, addrExp, sqlite3VdbeCurrentAddr(v)-2, -1); + sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); - TREETRACE(0x2,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); - pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++; + sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++; sortOut = sqlite3GetTempReg(pParse); - sqlite3VdbeScanStatusCounters(v, addrExp, sqlite3VdbeCurrentAddr(v), 0); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); - sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); + sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); - pAggInfo->useSortingIdx = 1; - sqlite3VdbeScanStatusRange(v, addrExp, -1, sortPTab); - sqlite3VdbeScanStatusRange(v, addrExp, -1, pAggInfo->sortingIdx); - } - - /* If there are entries in pAgggInfo->aFunc[] that contain subexpressions - ** that are indexed (and that were previously identified and tagged - ** in optimizeAggregateUseOfIndexedExpr()) then those subexpressions - ** must now be converted into a TK_AGG_COLUMN node so that the value - ** is correctly pulled from the index rather than being recomputed. */ - if( pParse->pIdxEpr ){ - aggregateConvertIndexedExprRefToColumn(pAggInfo); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - TREETRACE(0x20, pParse, p, - ("AggInfo function expressions converted to reference index\n")); - sqlite3TreeViewSelect(0, p, 0); - printAggInfo(pAggInfo); - } -#endif + sAggInfo.useSortingIdx = 1; + sqlite3ExprCacheClear(pParse); + } /* If the index or temporary table used by the GROUP BY sort ** will naturally deliver rows in the order required by the ORDER BY ** clause, cancel the ephemeral table open coded earlier. ** ** This is an optimization - the correct answer should result regardless. - ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to + ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to ** disable this optimization for testing purposes. */ - if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder) + if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder) && (groupBySort || sqlite3WhereIsSorted(pWInfo)) ){ sSort.pOrderBy = 0; sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); } @@ -152276,34 +123117,22 @@ ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); + sqlite3ExprCacheClear(pParse); if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx, + sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut, sortPTab); } for(j=0; jnExpr; j++){ - int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol; - if( groupBySort ){ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); }else{ - pAggInfo->directMode = 1; + sAggInfo.directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); } - - if( iOrderByCol ){ - Expr *pX = p->pEList->a[iOrderByCol-1].pExpr; - Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX); - if( ALWAYS(pBase!=0) - && pBase->op!=TK_AGG_COLUMN - && pBase->op!=TK_REGISTER - ){ - sqlite3ExprToRegister(pX, iAMem+j); - } - } } sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); addr1 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v); @@ -152315,37 +123144,35 @@ ** This code copies current group by terms in b0,b1,b2,... ** over to a0,a1,a2. It then calls the output subroutine ** and resets the aggregate accumulator registers in preparation ** for the next GROUP BY batch. */ + sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); VdbeComment((v, "output one row")); - sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v); VdbeComment((v, "check abort flag")); sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); VdbeComment((v, "reset accumulator")); /* Update the aggregate accumulators based on the content of ** the current row */ sqlite3VdbeJumpHere(v, addr1); - updateAccumulator(pParse, iUseFlag, pAggInfo, eDist); + updateAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); VdbeComment((v, "indicate data in accumulator")); /* End of the loop */ if( groupBySort ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop); + sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); VdbeCoverage(v); }else{ - TREETRACE(0x2,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); } - sqlite3ExprListDelete(db, pDistinct); /* Output the final row of result */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); VdbeComment((v, "output final row")); @@ -152369,38 +123196,31 @@ addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - finalizeAggFunctions(pParse, pAggInfo); + finalizeAggFunctions(pParse, &sAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, -1, &sSort, + selectInnerLoop(pParse, p, p->pEList, -1, &sSort, &sDistinct, pDest, addrOutputRow+1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); VdbeComment((v, "end groupby result generator")); /* Generate a subroutine that will reset the group-by accumulator */ sqlite3VdbeResolveLabel(v, addrReset); - resetAccumulator(pParse, pAggInfo); - sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); - VdbeComment((v, "indicate accumulator empty")); + resetAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp1(v, OP_Return, regReset); - - if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){ - struct AggInfo_func *pF = &pAggInfo->aFunc[0]; - fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr); - } + } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ else { - /* Aggregate functions without GROUP BY. tag-select-0820 */ + ExprList *pDel = 0; +#ifndef SQLITE_OMIT_BTREECOUNT Table *pTab; - if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){ - /* tag-select-0821 - ** - ** If isSimpleCount() returns a pointer to a Table structure, then + if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){ + /* If isSimpleCount() returns a pointer to a Table structure, then ** the SQL statement is of the form: ** ** SELECT count(*) FROM ** ** where the Table structure returned represents table . @@ -152414,11 +123234,11 @@ const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */ Index *pIdx; /* Iterator variable */ KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ Index *pBest = 0; /* Best index found so far */ - Pgno iRoot = pTab->tnum; /* Root page of scanned b-tree */ + int iRoot = pTab->tnum; /* Root page of scanned b-tree */ sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); /* Search for the index that has the lowest scan cost. @@ -152425,134 +123245,125 @@ ** ** (2011-04-15) Do not do a full scan of an unordered index. ** ** (2013-10-03) Do not count the entries in a partial index. ** - ** In practice the KeyInfo structure will not be used. It is only + ** In practice the KeyInfo structure will not be used. It is only ** passed to keep OP_OpenRead happy. */ if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab); - if( !p->pSrc->a[0].fg.notIndexed ){ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->bUnordered==0 - && pIdx->szIdxRowszTabRow - && pIdx->pPartIdxWhere==0 - && (!pBest || pIdx->szIdxRowszIdxRow) - ){ - pBest = pIdx; - } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->bUnordered==0 + && pIdx->szIdxRowszTabRow + && pIdx->pPartIdxWhere==0 + && (!pBest || pIdx->szIdxRowszIdxRow) + ){ + pBest = pIdx; } } if( pBest ){ iRoot = pBest->tnum; pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest); } /* Open a read-only cursor, execute the OP_Count, close the cursor. */ - sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, (int)iRoot, iDb, 1); + sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1); if( pKeyInfo ){ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO); } - assignAggregateRegisters(pParse, pAggInfo); - sqlite3VdbeAddOp2(v, OP_Count, iCsr, AggInfoFuncReg(pAggInfo,0)); + sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem); sqlite3VdbeAddOp1(v, OP_Close, iCsr); explainSimpleCount(pParse, pTab, pBest); - }else{ - /* The general case of an aggregate query without GROUP BY - ** tag-select-0822 */ - int regAcc = 0; /* "populate accumulators" flag */ - ExprList *pDistinct = 0; - u16 distFlag = 0; - int eDist; - - /* If there are accumulator registers but no min() or max() functions - ** without FILTER clauses, allocate register regAcc. Register regAcc - ** will contain 0 the first time the inner loop runs, and 1 thereafter. - ** The code generated by updateAccumulator() uses this to ensure - ** that the accumulator registers are (a) updated only once if - ** there are no min() or max functions or (b) always updated for the - ** first row visited by the aggregate, so that they are updated at - ** least once even if the FILTER clause means the min() or max() - ** function visits zero rows. */ - if( pAggInfo->nAccumulator ){ - for(i=0; inFunc; i++){ - if( ExprHasProperty(pAggInfo->aFunc[i].pFExpr, EP_WinFunc) ){ - continue; - } - if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){ - break; - } - } - if( i==pAggInfo->nFunc ){ - regAcc = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc); - } - }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){ - assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) ); - pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList; - distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0; - } - assignAggregateRegisters(pParse, pAggInfo); - + }else +#endif /* SQLITE_OMIT_BTREECOUNT */ + { + /* Check if the query is of one of the following forms: + ** + ** SELECT min(x) FROM ... + ** SELECT max(x) FROM ... + ** + ** If it is, then ask the code in where.c to attempt to sort results + ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. + ** If where.c is able to produce results sorted in this order, then + ** add vdbe code to break out of the processing loop after the + ** first iteration (since the first iteration of the loop is + ** guaranteed to operate on the row with the minimum or maximum + ** value of x, the only row required). + ** + ** A special flag must be passed to sqlite3WhereBegin() to slightly + ** modify behavior as follows: + ** + ** + If the query is a "SELECT min(x)", then the loop coded by + ** where.c should not iterate over any values with a NULL value + ** for x. + ** + ** + The optimizer code in where.c (the thing that decides which + ** index or indices to use) should place a different priority on + ** satisfying the 'ORDER BY' clause than it does in other cases. + ** Refer to code and comments in where.c for details. + */ + ExprList *pMinMax = 0; + u8 flag = WHERE_ORDERBY_NORMAL; + + assert( p->pGroupBy==0 ); + assert( flag==0 ); + if( p->pHaving==0 ){ + flag = minMaxQuery(&sAggInfo, &pMinMax); + } + assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); + + if( flag ){ + pMinMax = sqlite3ExprListDup(db, pMinMax, 0); + pDel = pMinMax; + assert( db->mallocFailed || pMinMax!=0 ); + if( !db->mallocFailed ){ + pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; + pMinMax->a[0].pExpr->op = TK_COLUMN; + } + } + /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ - assert( p->pGroupBy==0 ); - resetAccumulator(pParse, pAggInfo); - - /* If this query is a candidate for the min/max optimization, then - ** minMaxFlag will have been previously set to either - ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will - ** be an appropriate ORDER BY expression for the optimization. - */ - assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); - assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); - - TREETRACE(0x2,pParse,p,("WhereBegin\n")); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, - pDistinct, p, minMaxFlag|distFlag, 0); + resetAccumulator(pParse, &sAggInfo); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0); if( pWInfo==0 ){ + sqlite3ExprListDelete(db, pDel); goto select_end; } - TREETRACE(0x2,pParse,p,("WhereBegin returns\n")); - eDist = sqlite3WhereIsDistinct(pWInfo); - updateAccumulator(pParse, regAcc, pAggInfo, eDist); - if( eDist!=WHERE_DISTINCT_NOOP ){ - struct AggInfo_func *pF = pAggInfo->aFunc; - if( pF ){ - fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr); - } - } - - if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); - if( minMaxFlag ){ - sqlite3WhereMinMaxOptEarlyOut(v, pWInfo); - } - TREETRACE(0x2,pParse,p,("WhereEnd\n")); + updateAccumulator(pParse, &sAggInfo); + assert( pMinMax==0 || pMinMax->nExpr==1 ); + if( sqlite3WhereIsOrdered(pWInfo)>0 ){ + sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); + VdbeComment((v, "%s() by index", + (flag==WHERE_ORDERBY_MIN?"min":"max"))); + } sqlite3WhereEnd(pWInfo); - finalizeAggFunctions(pParse, pAggInfo); + finalizeAggFunctions(pParse, &sAggInfo); } sSort.pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, -1, 0, 0, + selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, pDest, addrEnd, addrEnd); + sqlite3ExprListDelete(db, pDel); } sqlite3VdbeResolveLabel(v, addrEnd); - + } /* endif aggregate query */ if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){ explainTempTable(pParse, "DISTINCT"); } /* If there is an ORDER BY clause, then we need to sort the results - ** and send them to the callback one by one. tag-select-0900 + ** and send them to the callback one by one. */ if( sSort.pOrderBy ){ - assert( p->pEList==pEList ); + explainTempTable(pParse, + sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); } /* Jump here to skip this query */ @@ -152564,44 +123375,24 @@ /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: - assert( db->mallocFailed==0 || db->mallocFailed==1 ); - assert( db->mallocFailed==0 || pParse->nErr!=0 ); - sqlite3ExprListDelete(db, pMinMaxOrderBy); -#ifdef SQLITE_DEBUG - /* Internal self-checks. tag-select-1000 */ - if( pAggInfo && !db->mallocFailed ){ -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x20 ){ - TREETRACE(0x20,pParse,p,("Finished with AggInfo\n")); - printAggInfo(pAggInfo); - } -#endif - for(i=0; inColumn; i++){ - Expr *pExpr = pAggInfo->aCol[i].pCExpr; - if( pExpr==0 ) continue; - assert( pExpr->pAggInfo==pAggInfo ); - assert( pExpr->iAgg==i ); - } - for(i=0; inFunc; i++){ - Expr *pExpr = pAggInfo->aFunc[i].pFExpr; - assert( pExpr!=0 ); - assert( pExpr->pAggInfo==pAggInfo ); - assert( pExpr->iAgg==i ); - } - } -#endif - -#if TREETRACE_ENABLED - TREETRACE(0x1,pParse,p,("end processing\n")); - if( (sqlite3TreeTrace & 0x40000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ - sqlite3TreeViewSelect(0, p, 0); - } -#endif - ExplainQueryPlanPop(pParse); + explainSetInteger(pParse->iSelectId, iRestoreSelectId); + + /* Identify column names if results of the SELECT are to be output. + */ + if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){ + generateColumnNames(pParse, pTabList, pEList); + } + + sqlite3DbFree(db, sAggInfo.aCol); + sqlite3DbFree(db, sAggInfo.aFunc); +#if SELECTTRACE_ENABLED + SELECTTRACE(1,pParse,p,("end processing\n")); + pParse->nSelectIndent--; +#endif return rc; } /************** End of select.c **********************************************/ /************** Begin file table.c *******************************************/ @@ -152661,11 +123452,11 @@ need = nCol; } if( p->nData + need > p->nAlloc ){ char **azNew; p->nAlloc = p->nAlloc*2 + need; - azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc ); + azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc ); if( azNew==0 ) goto malloc_failed; p->azResult = azNew; } /* If this is the first row, then generate an extra row containing @@ -152714,11 +123505,11 @@ ** Query the database. But instead of invoking a callback for each row, ** malloc() for space to hold the result and return the entire results ** at the conclusion of the call. ** ** The result that is written to ***pazResult is held in memory obtained -** from malloc(). But the caller cannot free this memory directly. +** from malloc(). But the caller cannot free this memory directly. ** Instead, the entire table should be passed to sqlite3_free_table() when ** the calling procedure is finished using it. */ SQLITE_API int sqlite3_get_table( sqlite3 *db, /* The database on which the SQL executes */ @@ -152770,11 +123561,11 @@ sqlite3_free_table(&res.azResult[1]); return rc; } if( res.nAlloc>res.nData ){ char **azNew; - azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData ); + azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData ); if( azNew==0 ){ sqlite3_free_table(&res.azResult[1]); db->errCode = SQLITE_NOMEM; return SQLITE_NOMEM_BKPT; } @@ -152831,20 +123622,17 @@ sqlite3ExprDelete(db, pTmp->pWhere); sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); - sqlite3UpsertDelete(db, pTmp->pUpsert); - sqlite3SrcListDelete(db, pTmp->pFrom); - sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); } } /* -** Given table pTab, return a list of all the triggers attached to +** Given table pTab, return a list of all the triggers attached to ** the table. The list is connected by Trigger.pNext pointers. ** ** All of the triggers on pTab that are in the same database as pTab ** are already attached to pTab->pTrigger. But there might be additional ** triggers on pTab in the TEMP schema. This routine prepends all @@ -152854,52 +123642,32 @@ ** To state it another way: This routine returns a list of all triggers ** that fire off of pTab. The list will include any TEMP triggers on ** pTab as well as the triggers lised in pTab->pTrigger. */ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ - Schema *pTmpSchema; /* Schema of the pTab table */ - Trigger *pList; /* List of triggers to return */ - HashElem *p; /* Loop variable for TEMP triggers */ - - assert( pParse->disableTriggers==0 ); - pTmpSchema = pParse->db->aDb[1].pSchema; - p = sqliteHashFirst(&pTmpSchema->trigHash); - pList = pTab->pTrigger; - while( p ){ - Trigger *pTrig = (Trigger *)sqliteHashData(p); - if( pTrig->pTabSchema==pTab->pSchema - && pTrig->table - && 0==sqlite3StrICmp(pTrig->table, pTab->zName) - && (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning) - ){ - pTrig->pNext = pList; - pList = pTrig; - }else if( pTrig->op==TK_RETURNING ){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - assert( pParse->db->pVtabCtx==0 ); -#endif - assert( pParse->bReturning ); - assert( &(pParse->u1.pReturning->retTrig) == pTrig ); - pTrig->table = pTab->zName; - pTrig->pTabSchema = pTab->pSchema; - pTrig->pNext = pList; - pList = pTrig; - } - p = sqliteHashNext(p); - } -#if 0 - if( pList ){ - Trigger *pX; - printf("Triggers for %s:", pTab->zName); - for(pX=pList; pX; pX=pX->pNext){ - printf(" %s", pX->zName); - } - printf("\n"); - fflush(stdout); - } -#endif - return pList; + Schema * const pTmpSchema = pParse->db->aDb[1].pSchema; + Trigger *pList = 0; /* List of triggers to return */ + + if( pParse->disableTriggers ){ + return 0; + } + + if( pTmpSchema!=pTab->pSchema ){ + HashElem *p; + assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) ); + for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){ + Trigger *pTrig = (Trigger *)sqliteHashData(p); + if( pTrig->pTabSchema==pTab->pSchema + && 0==sqlite3StrICmp(pTrig->table, pTab->zName) + ){ + pTrig->pNext = (pList ? pList : pTab->pTrigger); + pList = pTrig; + } + } + } + + return (pList ? pList : pTab->pTrigger); } /* ** This is called by the parser when it sees a CREATE TRIGGER statement ** up to the point of the BEGIN before the trigger actions. A Trigger @@ -152955,17 +123723,15 @@ ** ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... ** ^^^^^^^^ ** ** To maintain backwards compatibility, ignore the database - ** name on pTableName if we are reparsing out of the schema table + ** name on pTableName if we are reparsing out of SQLITE_MASTER. */ if( db->init.busy && iDb!=1 ){ - assert( pTableName->a[0].fg.fixedSchema==0 ); - assert( pTableName->a[0].fg.isSubquery==0 ); - sqlite3DbFree(db, pTableName->a[0].u4.zDatabase); - pTableName->a[0].u4.zDatabase = 0; + sqlite3DbFree(db, pTableName->a[0].zDatabase); + pTableName->a[0].zDatabase = 0; } /* If the trigger name was unqualified, and the table is a temp table, ** then set iDb to 1 to create the trigger in the temporary database. ** If sqlite3SrcListLookup() returns 0, indicating the table does not @@ -152985,43 +123751,43 @@ goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( !pTab ){ /* The table does not exist. */ - goto trigger_orphan_error; + if( db->init.iDb==1 ){ + /* Ticket #3810. + ** Normally, whenever a table is dropped, all associated triggers are + ** dropped too. But if a TEMP trigger is created on a non-TEMP table + ** and the table is dropped by a different database connection, the + ** trigger is not visible to the database connection that does the + ** drop so the trigger cannot be dropped. This results in an + ** "orphaned trigger" - a trigger whose associated table is missing. + */ + db->init.orphanTrigger = 1; + } + goto trigger_cleanup; } if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); - goto trigger_orphan_error; - } - if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){ - sqlite3ErrorMsg(pParse, "cannot create triggers on shadow tables"); - goto trigger_orphan_error; + goto trigger_cleanup; } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ zName = sqlite3NameFromToken(db, pName); - if( zName==0 ){ - assert( db->mallocFailed ); - goto trigger_cleanup; - } - if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){ + if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto trigger_cleanup; } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( !IN_RENAME_OBJECT ){ - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - VVA_ONLY( pParse->ifNotExists = 1; ) - } - goto trigger_cleanup; - } + if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); + }else{ + assert( !db->init.busy ); + sqlite3CodeVerifySchema(pParse, iDb); + } + goto trigger_cleanup; } /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); @@ -153029,23 +123795,23 @@ } /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. */ - if( IsView(pTab) && tr_tm!=TK_INSTEAD ){ - sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", - (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a); - goto trigger_orphan_error; + if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ + sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", + (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); + goto trigger_cleanup; } - if( !IsView(pTab) && tr_tm==TK_INSTEAD ){ + if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" - " trigger on table: %S", pTableName->a); - goto trigger_orphan_error; + " trigger on table: %S", pTableName, 0); + goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION - if( !IN_RENAME_OBJECT ){ + { int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[iTabDb].zDbSName; const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; @@ -153075,19 +123841,12 @@ pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); pTrigger->pSchema = db->aDb[iDb].pSchema; pTrigger->pTabSchema = pTab->pSchema; pTrigger->op = (u8)op; pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName); - pTrigger->pWhen = pWhen; - pWhen = 0; - }else{ - pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); - } - pTrigger->pColumns = pColumns; - pColumns = 0; + pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); + pTrigger->pColumns = sqlite3IdListDup(db, pColumns); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; trigger_cleanup: sqlite3DbFree(db, zName); @@ -153097,27 +123856,10 @@ if( !pParse->pNewTrigger ){ sqlite3DeleteTrigger(db, pTrigger); }else{ assert( pParse->pNewTrigger==pTrigger ); } - return; - -trigger_orphan_error: - if( db->init.iDb==1 ){ - /* Ticket #3810. - ** Normally, whenever a table is dropped, all associated triggers are - ** dropped too. But if a TEMP trigger is created on a non-TEMP table - ** and the table is dropped by a different database connection, the - ** trigger is not visible to the database connection that does the - ** drop so the trigger cannot be dropped. This results in an - ** "orphaned trigger" - a trigger whose associated table is missing. - ** - ** 2020-11-05 see also https://sqlite.org/forum/forumpost/157dc791df - */ - db->init.orphanTrigger = 1; - } - goto trigger_cleanup; } /* ** This routine is called after all of the trigger actions have been parsed ** in order to complete the process of building the trigger. @@ -153143,70 +123885,43 @@ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } sqlite3TokenInit(&nameToken, pTrig->zName); sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); - if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) - || sqlite3FixExpr(&sFix, pTrig->pWhen) + if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) + || sqlite3FixExpr(&sFix, pTrig->pWhen) ){ goto triggerfinish_cleanup; } -#ifndef SQLITE_OMIT_ALTERTABLE - if( IN_RENAME_OBJECT ){ - assert( !db->init.busy ); - pParse->pNewTrigger = pTrig; - pTrig = 0; - }else -#endif - /* if we are not initializing, - ** build the sqlite_schema entry + ** build the sqlite_master entry */ if( !db->init.busy ){ Vdbe *v; char *z; - /* If this is a new CREATE TABLE statement, and if shadow tables - ** are read-only, and the trigger makes a change to a shadow table, - ** then raise an error - do not allow the trigger to be created. */ - if( sqlite3ReadOnlyShadowTables(db) ){ - TriggerStep *pStep; - for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){ - if( pStep->zTarget!=0 - && sqlite3ShadowTableName(db, pStep->zTarget) - ){ - sqlite3ErrorMsg(pParse, - "trigger \"%s\" may not write to shadow table \"%s\"", - pTrig->zName, pStep->zTarget); - goto triggerfinish_cleanup; - } - } - } - - /* Make an entry in the sqlite_schema table */ + /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); testcase( z==0 ); sqlite3NestedParse(pParse, - "INSERT INTO %Q." LEGACY_SCHEMA_TABLE - " VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zDbSName, zName, + "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", + db->aDb[iDb].zDbSName, MASTER_NAME, zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0); + sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); } if( db->init.busy ){ Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( pLink!=0 ); pTrig = sqlite3HashInsert(pHash, zName, pTrig); if( pTrig ){ sqlite3OomFault(db); }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; @@ -153217,47 +123932,30 @@ } } triggerfinish_cleanup: sqlite3DeleteTrigger(db, pTrig); - assert( IN_RENAME_OBJECT || !pParse->pNewTrigger ); + assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(db, pStepList); } -/* -** Duplicate a range of text from an SQL statement, then convert all -** whitespace characters into ordinary space characters. -*/ -static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ - char *z = sqlite3DbSpanDup(db, zStart, zEnd); - int i; - if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' '; - return z; -} - /* ** Turn a SELECT statement (that the pSelect parameter points to) into ** a trigger step. Return a pointer to a TriggerStep structure. ** ** The parser calls this routine when it finds a SELECT statement in -** body of a TRIGGER. +** body of a TRIGGER. */ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep( - sqlite3 *db, /* Database connection */ - Select *pSelect, /* The SELECT statement */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ -){ +SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ) { sqlite3SelectDelete(db, pSelect); return 0; } pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; - pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); return pTriggerStep; } /* ** Allocate space to hold a new trigger step. The allocated space @@ -153264,31 +123962,23 @@ ** holds both the TriggerStep object and the TriggerStep.target.z string. ** ** If an OOM error occurs, NULL is returned and db->mallocFailed is set. */ static TriggerStep *triggerStepAllocate( - Parse *pParse, /* Parser context */ + sqlite3 *db, /* Database connection */ u8 op, /* Trigger opcode */ - Token *pName, /* The target name */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ + Token *pName /* The target name */ ){ - sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - if( pParse->nErr ) return 0; pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); if( pTriggerStep ){ char *z = (char*)&pTriggerStep[1]; memcpy(z, pName->z, pName->n); sqlite3Dequote(z); pTriggerStep->zTarget = z; pTriggerStep->op = op; - pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); - } } return pTriggerStep; } /* @@ -153297,43 +123987,27 @@ ** ** The parser calls this routine when it sees an INSERT inside the ** body of a trigger. */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( - Parse *pParse, /* Parser */ + sqlite3 *db, /* The database connection */ Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ Select *pSelect, /* A SELECT statement that supplies values */ - u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ - Upsert *pUpsert, /* ON CONFLICT clauses for upsert */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ + u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ){ - sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; assert(pSelect != 0 || db->mallocFailed); - pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); + pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); if( pTriggerStep ){ - if( IN_RENAME_OBJECT ){ - pTriggerStep->pSelect = pSelect; - pSelect = 0; - }else{ - pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - } + pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; - pTriggerStep->pUpsert = pUpsert; pTriggerStep->orconf = orconf; - if( pUpsert ){ - sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget); - } }else{ - testcase( pColumn ); sqlite3IdListDelete(db, pColumn); - testcase( pUpsert ); - sqlite3UpsertDelete(db, pUpsert); } sqlite3SelectDelete(db, pSelect); return pTriggerStep; } @@ -153342,88 +124016,65 @@ ** Construct a trigger step that implements an UPDATE statement and return ** a pointer to that trigger step. The parser calls this routine when it ** sees an UPDATE statement inside the body of a CREATE TRIGGER. */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( - Parse *pParse, /* Parser */ + sqlite3 *db, /* The database connection */ Token *pTableName, /* Name of the table to be updated */ - SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ - u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ + u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ){ - sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); + pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); if( pTriggerStep ){ - if( IN_RENAME_OBJECT ){ - pTriggerStep->pExprList = pEList; - pTriggerStep->pWhere = pWhere; - pTriggerStep->pFrom = pFrom; - pEList = 0; - pWhere = 0; - pFrom = 0; - }else{ - pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); - pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE); - } + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pTriggerStep->orconf = orconf; } sqlite3ExprListDelete(db, pEList); sqlite3ExprDelete(db, pWhere); - sqlite3SrcListDelete(db, pFrom); return pTriggerStep; } /* ** Construct a trigger step that implements a DELETE statement and return ** a pointer to that trigger step. The parser calls this routine when it ** sees a DELETE statement inside the body of a CREATE TRIGGER. */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( - Parse *pParse, /* Parser */ + sqlite3 *db, /* Database connection */ Token *pTableName, /* The table from which rows are deleted */ - Expr *pWhere, /* The WHERE clause */ - const char *zStart, /* Start of SQL text */ - const char *zEnd /* End of SQL text */ + Expr *pWhere /* The WHERE clause */ ){ - sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); + pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); if( pTriggerStep ){ - if( IN_RENAME_OBJECT ){ - pTriggerStep->pWhere = pWhere; - pWhere = 0; - }else{ - pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - } + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pTriggerStep->orconf = OE_Default; } sqlite3ExprDelete(db, pWhere); return pTriggerStep; } -/* +/* ** Recursively delete a Trigger structure */ SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ - if( pTrigger==0 || pTrigger->bReturning ) return; + if( pTrigger==0 ) return; sqlite3DeleteTriggerStep(db, pTrigger->step_list); sqlite3DbFree(db, pTrigger->zName); sqlite3DbFree(db, pTrigger->table); sqlite3ExprDelete(db, pTrigger->pWhen); sqlite3IdListDelete(db, pTrigger->pColumns); sqlite3DbFree(db, pTrigger); } /* -** This function is called to drop a trigger from the database schema. +** This function is called to drop a trigger from the database schema. ** ** This may be called directly from the parser and therefore identifies ** the trigger by name. The sqlite3DropTriggerPtr() routine does the ** same job as this routine except it takes a pointer to the trigger ** instead of the trigger name. @@ -153439,24 +124090,23 @@ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto drop_trigger_cleanup; } assert( pName->nSrc==1 ); - assert( pName->a[0].fg.fixedSchema==0 && pName->a[0].fg.isSubquery==0 ); - zDb = pName->a[0].u4.zDatabase; + zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue; + if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); if( pTrigger ) break; } if( !pTrigger ){ if( !noErr ){ - sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a); + sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); }else{ sqlite3CodeVerifyNamedSchema(pParse, zDb); } pParse->checkSchema = 1; goto drop_trigger_cleanup; @@ -153475,11 +124125,11 @@ return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); } /* -** Drop a trigger given a pointer to that trigger. +** Drop a trigger given a pointer to that trigger. */ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ Table *pTable; Vdbe *v; sqlite3 *db = pParse->db; @@ -153486,13 +124136,14 @@ int iDb; iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); assert( iDb>=0 && iDbnDb ); pTable = tableOfTrigger(pTrigger); - assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 ); + assert( pTable ); + assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION - if( pTable ){ + { int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || @@ -153502,14 +124153,15 @@ } #endif /* Generate code to destroy the database record of the trigger. */ + assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3NestedParse(pParse, - "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='trigger'", - db->aDb[iDb].zDbSName, pTrigger->zName + "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", + db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName ); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); } } @@ -153525,22 +124177,16 @@ pHash = &(db->aDb[iDb].pSchema->trigHash); pTrigger = sqlite3HashInsert(pHash, zName, 0); if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); - if( pTab ){ - Trigger **pp; - for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){ - if( *pp==pTrigger ){ - *pp = (*pp)->pNext; - break; - } - } - } + Trigger **pp; + for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); + *pp = (*pp)->pNext; } sqlite3DeleteTrigger(db, pTrigger); - db->mDbFlags |= DBFLAG_SchemaChange; + db->flags |= SQLITE_InternChanges; } } /* ** pEList is the SET clause of an UPDATE statement. Each entry @@ -153553,31 +124199,22 @@ */ static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){ int e; if( pIdList==0 || NEVER(pEList==0) ) return 1; for(e=0; enExpr; e++){ - if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1; - } - return 0; -} - -/* -** Return true if any TEMP triggers exist -*/ -static int tempTriggersExist(sqlite3 *db){ - if( NEVER(db->aDb[1].pSchema==0) ) return 0; - if( sqliteHashFirst(&db->aDb[1].pSchema->trigHash)==0 ) return 0; - return 1; + if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; + } + return 0; } /* ** Return a list of all triggers on table pTab if there exists at least -** one trigger that must be fired when an operation of type 'op' is +** one trigger that must be fired when an operation of type 'op' is ** performed on the table, and, if that operation is an UPDATE, if at ** least one of the columns in pChanges is being modified. */ -static SQLITE_NOINLINE Trigger *triggersReallyExist( +SQLITE_PRIVATE Trigger *sqlite3TriggersExist( Parse *pParse, /* Parse context */ Table *pTab, /* The table the contains the triggers */ int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ ExprList *pChanges, /* Columns that change in an UPDATE statement */ int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ @@ -153584,78 +124221,24 @@ ){ int mask = 0; Trigger *pList = 0; Trigger *p; - pList = sqlite3TriggerList(pParse, pTab); - assert( pList==0 || IsVirtual(pTab)==0 - || (pList->bReturning && pList->pNext==0) ); - if( pList!=0 ){ - p = pList; - if( (pParse->db->flags & SQLITE_EnableTrigger)==0 - && pTab->pTrigger!=0 - ){ - /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that - ** only TEMP triggers are allowed. Truncate the pList so that it - ** includes only TEMP triggers */ - if( pList==pTab->pTrigger ){ - pList = 0; - goto exit_triggers_exist; - } - while( ALWAYS(p->pNext) && p->pNext!=pTab->pTrigger ) p = p->pNext; - p->pNext = 0; - p = pList; - } - do{ - if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){ - mask |= p->tr_tm; - }else if( p->op==TK_RETURNING ){ - /* The first time a RETURNING trigger is seen, the "op" value tells - ** us what time of trigger it should be. */ - assert( sqlite3IsToplevel(pParse) ); - p->op = op; - if( IsVirtual(pTab) ){ - if( op!=TK_INSERT ){ - sqlite3ErrorMsg(pParse, - "%s RETURNING is not available on virtual tables", - op==TK_DELETE ? "DELETE" : "UPDATE"); - } - p->tr_tm = TRIGGER_BEFORE; - }else{ - p->tr_tm = TRIGGER_AFTER; - } - mask |= p->tr_tm; - }else if( p->bReturning && p->op==TK_INSERT && op==TK_UPDATE - && sqlite3IsToplevel(pParse) ){ - /* Also fire a RETURNING trigger for an UPSERT */ - mask |= p->tr_tm; - } - p = p->pNext; - }while( p ); - } -exit_triggers_exist: + if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){ + pList = sqlite3TriggerList(pParse, pTab); + } + assert( pList==0 || IsVirtual(pTab)==0 ); + for(p=pList; p; p=p->pNext){ + if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){ + mask |= p->tr_tm; + } + } if( pMask ){ *pMask = mask; } return (mask ? pList : 0); } -SQLITE_PRIVATE Trigger *sqlite3TriggersExist( - Parse *pParse, /* Parse context */ - Table *pTab, /* The table the contains the triggers */ - int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ - ExprList *pChanges, /* Columns that change in an UPDATE statement */ - int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ -){ - assert( pTab!=0 ); - if( (pTab->pTrigger==0 && !tempTriggersExist(pParse->db)) - || pParse->disableTriggers - ){ - if( pMask ) *pMask = 0; - return 0; - } - return triggersReallyExist(pParse,pTab,op,pChanges,pMask); -} /* ** Convert the pStep->zTarget string into a SrcList and return a pointer ** to that SrcList. ** @@ -153663,269 +124246,41 @@ ** forming the SrcList. This prevents a trigger in one database from ** referring to a target in another database. An exception is when the ** trigger is in TEMP in which case it can refer to any other database it ** wants. */ -SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc( +static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ sqlite3 *db = pParse->db; - SrcList *pSrc; /* SrcList to be returned */ - char *zName = sqlite3DbStrDup(db, pStep->zTarget); - pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - assert( pSrc==0 || pSrc->nSrc==1 ); - assert( zName || pSrc==0 ); + int iDb; /* Index of the database to use */ + SrcList *pSrc; /* SrcList to be returned */ + + pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ - Schema *pSchema = pStep->pTrig->pSchema; - pSrc->a[0].zName = zName; - if( pSchema!=db->aDb[1].pSchema ){ - assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 ); - pSrc->a[0].u4.pSchema = pSchema; - pSrc->a[0].fg.fixedSchema = 1; - } - if( pStep->pFrom ){ - SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0); - if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){ - Select *pSubquery; - Token as; - pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0); - as.n = 0; - as.z = 0; - pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); - } - pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup); - } - }else{ - sqlite3DbFree(db, zName); + assert( pSrc->nSrc>0 ); + pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); + iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); + if( iDb==0 || iDb>=2 ){ + const char *zDb; + assert( iDbnDb ); + zDb = db->aDb[iDb].zDbSName; + pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb); + } } return pSrc; } /* -** Return true if the pExpr term from the RETURNING clause argument -** list is of the form "*". Raise an error if the terms if of the -** form "table.*". -*/ -static int isAsteriskTerm( - Parse *pParse, /* Parsing context */ - Expr *pTerm /* A term in the RETURNING clause */ -){ - assert( pTerm!=0 ); - if( pTerm->op==TK_ASTERISK ) return 1; - if( pTerm->op!=TK_DOT ) return 0; - assert( pTerm->pRight!=0 ); - assert( pTerm->pLeft!=0 ); - if( pTerm->pRight->op!=TK_ASTERISK ) return 0; - sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards"); - return 1; -} - -/* The input list pList is the list of result set terms from a RETURNING -** clause. The table that we are returning from is pTab. -** -** This routine makes a copy of the pList, and at the same time expands -** any "*" wildcards to be the complete set of columns from pTab. -*/ -static ExprList *sqlite3ExpandReturning( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* The arguments to RETURNING */ - Table *pTab /* The table being updated */ -){ - ExprList *pNew = 0; - sqlite3 *db = pParse->db; - int i; - - for(i=0; inExpr; i++){ - Expr *pOldExpr = pList->a[i].pExpr; - if( NEVER(pOldExpr==0) ) continue; - if( isAsteriskTerm(pParse, pOldExpr) ){ - int jj; - for(jj=0; jjnCol; jj++){ - Expr *pNewExpr; - if( IsHiddenColumn(pTab->aCol+jj) ) continue; - pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName); - pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); - if( !db->mallocFailed ){ - struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; - pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName); - pItem->fg.eEName = ENAME_NAME; - } - } - }else{ - Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0); - pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); - if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){ - struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; - pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName); - pItem->fg.eEName = pList->a[i].fg.eEName; - } - } - } - return pNew; -} - -/* If the Expr node is a subquery or an EXISTS operator or an IN operator that -** uses a subquery, and if the subquery is SF_Correlated, then mark the -** expression as EP_VarSelect. -*/ -static int sqlite3ReturningSubqueryVarSelect(Walker *NotUsed, Expr *pExpr){ - UNUSED_PARAMETER(NotUsed); - if( ExprUseXSelect(pExpr) - && (pExpr->x.pSelect->selFlags & SF_Correlated)!=0 - ){ - testcase( ExprHasProperty(pExpr, EP_VarSelect) ); - ExprSetProperty(pExpr, EP_VarSelect); - } - return WRC_Continue; -} - - -/* -** If the SELECT references the table pWalker->u.pTab, then do two things: -** -** (1) Mark the SELECT as as SF_Correlated. -** (2) Set pWalker->eCode to non-zero so that the caller will know -** that (1) has happened. -*/ -static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){ - int i; - SrcList *pSrc; - assert( pSelect!=0 ); - pSrc = pSelect->pSrc; - assert( pSrc!=0 ); - for(i=0; inSrc; i++){ - if( pSrc->a[i].pSTab==pWalker->u.pTab ){ - testcase( pSelect->selFlags & SF_Correlated ); - pSelect->selFlags |= SF_Correlated; - pWalker->eCode = 1; - break; - } - } - return WRC_Continue; -} - -/* -** Scan the expression list that is the argument to RETURNING looking -** for subqueries that depend on the table which is being modified in the -** statement that is hosting the RETURNING clause (pTab). Mark all such -** subqueries as SF_Correlated. If the subqueries are part of an -** expression, mark the expression as EP_VarSelect. -** -** https://sqlite.org/forum/forumpost/2c83569ce8945d39 -*/ -static void sqlite3ProcessReturningSubqueries( - ExprList *pEList, - Table *pTab -){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3ExprWalkNoop; - w.xSelectCallback = sqlite3ReturningSubqueryCorrelated; - w.u.pTab = pTab; - sqlite3WalkExprList(&w, pEList); - if( w.eCode ){ - w.xExprCallback = sqlite3ReturningSubqueryVarSelect; - w.xSelectCallback = sqlite3SelectWalkNoop; - sqlite3WalkExprList(&w, pEList); - } -} - -/* -** Generate code for the RETURNING trigger. Unlike other triggers -** that invoke a subprogram in the bytecode, the code for RETURNING -** is generated in-line. -*/ -static void codeReturningTrigger( - Parse *pParse, /* Parse context */ - Trigger *pTrigger, /* The trigger step that defines the RETURNING */ - Table *pTab, /* The table to code triggers from */ - int regIn /* The first in an array of registers */ -){ - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - ExprList *pNew; - Returning *pReturning; - Select sSelect; - SrcList sFrom; - - assert( v!=0 ); - if( !pParse->bReturning ){ - /* This RETURNING trigger must be for a different statement as - ** this statement lacks a RETURNING clause. */ - return; - } - assert( db->pParse==pParse ); - pReturning = pParse->u1.pReturning; - if( pTrigger != &(pReturning->retTrig) ){ - /* This RETURNING trigger is for a different statement */ - return; - } - memset(&sSelect, 0, sizeof(sSelect)); - memset(&sFrom, 0, sizeof(sFrom)); - sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); - sSelect.pSrc = &sFrom; - sFrom.nSrc = 1; - sFrom.a[0].pSTab = pTab; - sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */ - sFrom.a[0].iCursor = -1; - sqlite3SelectPrep(pParse, &sSelect, 0); - if( pParse->nErr==0 ){ - assert( db->mallocFailed==0 ); - sqlite3GenerateColumnNames(pParse, &sSelect); - } - sqlite3ExprListDelete(db, sSelect.pEList); - pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); - if( pParse->nErr==0 ){ - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - if( pReturning->nRetCol==0 ){ - pReturning->nRetCol = pNew->nExpr; - pReturning->iRetCur = pParse->nTab++; - } - sNC.pParse = pParse; - sNC.uNC.iBaseReg = regIn; - sNC.ncFlags = NC_UBaseReg; - pParse->eTriggerOp = pTrigger->op; - pParse->pTriggerTab = pTab; - if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK - && ALWAYS(!db->mallocFailed) - ){ - int i; - int nCol = pNew->nExpr; - int reg = pParse->nMem+1; - sqlite3ProcessReturningSubqueries(pNew, pTab); - pParse->nMem += nCol+2; - pReturning->iRetReg = reg; - for(i=0; ia[i].pExpr; - assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */ - sqlite3ExprCodeFactorable(pParse, pCol, reg+i); - if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i); - } - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i); - sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1); - sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1); - } - } - sqlite3ExprListDelete(db, pNew); - pParse->eTriggerOp = 0; - pParse->pTriggerTab = 0; -} - - - -/* -** Generate VDBE code for the statements inside the body of a single +** Generate VDBE code for the statements inside the body of a single ** trigger. */ static int codeTriggerProgram( Parse *pParse, /* The parser context */ TriggerStep *pStepList, /* List of statements inside the trigger body */ - int orconf /* Conflict algorithm. (OE_Abort, etc) */ + int orconf /* Conflict algorithm. (OE_Abort, etc) */ ){ TriggerStep *pStep; Vdbe *v = pParse->pVdbe; sqlite3 *db = pParse->db; @@ -153947,46 +124302,34 @@ ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; assert( pParse->okConstFactor==0 ); -#ifndef SQLITE_OMIT_TRACE - if( pStep->zSpan ){ - sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, - sqlite3MPrintf(db, "-- %s", pStep->zSpan), - P4_DYNAMIC); - } -#endif - switch( pStep->op ){ case TK_UPDATE: { - sqlite3Update(pParse, - sqlite3TriggerStepSrc(pParse, pStep), - sqlite3ExprListDup(db, pStep->pExprList, 0), - sqlite3ExprDup(db, pStep->pWhere, 0), - pParse->eOrconf, 0, 0, 0 + sqlite3Update(pParse, + targetSrcList(pParse, pStep), + sqlite3ExprListDup(db, pStep->pExprList, 0), + sqlite3ExprDup(db, pStep->pWhere, 0), + pParse->eOrconf ); - sqlite3VdbeAddOp0(v, OP_ResetCount); break; } case TK_INSERT: { - sqlite3Insert(pParse, - sqlite3TriggerStepSrc(pParse, pStep), - sqlite3SelectDup(db, pStep->pSelect, 0), - sqlite3IdListDup(db, pStep->pIdList), - pParse->eOrconf, - sqlite3UpsertDup(db, pStep->pUpsert) + sqlite3Insert(pParse, + targetSrcList(pParse, pStep), + sqlite3SelectDup(db, pStep->pSelect, 0), + sqlite3IdListDup(db, pStep->pIdList), + pParse->eOrconf ); - sqlite3VdbeAddOp0(v, OP_ResetCount); break; } case TK_DELETE: { - sqlite3DeleteFrom(pParse, - sqlite3TriggerStepSrc(pParse, pStep), - sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 + sqlite3DeleteFrom(pParse, + targetSrcList(pParse, pStep), + sqlite3ExprDup(db, pStep->pWhere, 0) ); - sqlite3VdbeAddOp0(v, OP_ResetCount); break; } default: assert( pStep->op==TK_SELECT ); { SelectDest sDest; Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); @@ -153993,10 +124336,13 @@ sqlite3SelectDestInit(&sDest, SRT_Discard, 0); sqlite3Select(pParse, pSelect, &sDest); sqlite3SelectDelete(db, pSelect); break; } + } + if( pStep->op!=TK_SELECT ){ + sqlite3VdbeAddOp0(v, OP_ResetCount); } } return 0; } @@ -154035,11 +124381,11 @@ sqlite3DbFree(pFrom->db, pFrom->zErrMsg); } } /* -** Create and populate a new TriggerPrg object with a sub-program +** Create and populate a new TriggerPrg object with a sub-program ** implementing trigger pTrigger with ON CONFLICT policy orconf. */ static TriggerPrg *codeRowTrigger( Parse *pParse, /* Current parse context */ Trigger *pTrigger, /* Trigger to code */ @@ -154051,18 +124397,18 @@ TriggerPrg *pPrg; /* Value to return */ Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ Vdbe *v; /* Temporary VM */ NameContext sNC; /* Name context for sub-vdbe */ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ + Parse *pSubParse; /* Parse context for sub-vdbe */ int iEndTrigger = 0; /* Label to jump to if WHEN is false */ - Parse sSubParse; /* Parse context for sub-vdbe */ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); assert( pTop->pVdbe ); /* Allocate the TriggerPrg and SubProgram objects. To ensure that they - ** are freed if an error occurs, link them into the Parse.pTriggerPrg + ** are freed if an error occurs, link them into the Parse.pTriggerPrg ** list of the top-level Parse object sooner rather than later. */ pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg)); if( !pPrg ) return 0; pPrg->pNext = pTop->pTriggerPrg; pTop->pTriggerPrg = pPrg; @@ -154072,84 +124418,83 @@ pPrg->pTrigger = pTrigger; pPrg->orconf = orconf; pPrg->aColmask[0] = 0xffffffff; pPrg->aColmask[1] = 0xffffffff; - /* Allocate and populate a new Parse context to use for coding the + /* Allocate and populate a new Parse context to use for coding the ** trigger sub-program. */ - sqlite3ParseObjectInit(&sSubParse, db); + pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); + if( !pSubParse ) return 0; memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = &sSubParse; - sSubParse.pTriggerTab = pTab; - sSubParse.pToplevel = pTop; - sSubParse.zAuthContext = pTrigger->zName; - sSubParse.eTriggerOp = pTrigger->op; - sSubParse.nQueryLoop = pParse->nQueryLoop; - sSubParse.prepFlags = pParse->prepFlags; - - v = sqlite3GetVdbe(&sSubParse); + sNC.pParse = pSubParse; + pSubParse->db = db; + pSubParse->pTriggerTab = pTab; + pSubParse->pToplevel = pTop; + pSubParse->zAuthContext = pTrigger->zName; + pSubParse->eTriggerOp = pTrigger->op; + pSubParse->nQueryLoop = pParse->nQueryLoop; + + v = sqlite3GetVdbe(pSubParse); if( v ){ - VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", + VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", pTrigger->zName, onErrorText(orconf), (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), (pTrigger->op==TK_INSERT ? "INSERT" : ""), (pTrigger->op==TK_DELETE ? "DELETE" : ""), pTab->zName )); #ifndef SQLITE_OMIT_TRACE - if( pTrigger->zName ){ - sqlite3VdbeChangeP4(v, -1, - sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC - ); - } + sqlite3VdbeChangeP4(v, -1, + sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC + ); #endif /* If one was specified, code the WHEN clause. If it evaluates to false - ** (or NULL) the sub-vdbe is immediately halted by jumping to the + ** (or NULL) the sub-vdbe is immediately halted by jumping to the ** OP_Halt inserted at the end of the program. */ if( pTrigger->pWhen ){ pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); - if( db->mallocFailed==0 - && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) + if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) + && db->mallocFailed==0 ){ - iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse); - sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); + iEndTrigger = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); } sqlite3ExprDelete(db, pWhen); } /* Code the trigger program into the sub-vdbe. */ - codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf); + codeTriggerProgram(pSubParse, pTrigger->step_list, orconf); /* Insert an OP_Halt at the end of the sub-program. */ if( iEndTrigger ){ sqlite3VdbeResolveLabel(v, iEndTrigger); } sqlite3VdbeAddOp0(v, OP_Halt); VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); - transferParseError(pParse, &sSubParse); - if( pParse->nErr==0 ){ - assert( db->mallocFailed==0 ); + transferParseError(pParse, pSubParse); + if( db->mallocFailed==0 ){ pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); } - pProgram->nMem = sSubParse.nMem; - pProgram->nCsr = sSubParse.nTab; + pProgram->nMem = pSubParse->nMem; + pProgram->nCsr = pSubParse->nTab; pProgram->token = (void *)pTrigger; - pPrg->aColmask[0] = sSubParse.oldmask; - pPrg->aColmask[1] = sSubParse.newmask; + pPrg->aColmask[0] = pSubParse->oldmask; + pPrg->aColmask[1] = pSubParse->newmask; sqlite3VdbeDelete(v); - }else{ - transferParseError(pParse, &sSubParse); } - assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg ); - sqlite3ParseObjectReset(&sSubParse); + assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); + assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); + sqlite3ParserReset(pSubParse); + sqlite3StackFree(db, pSubParse); + return pPrg; } - + /* ** Return a pointer to a TriggerPrg object containing the sub-program for ** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such ** TriggerPrg object exists, a new object is allocated and populated before ** being returned. @@ -154167,26 +124512,25 @@ /* It may be that this trigger has already been coded (or is in the ** process of being coded). If this is the case, then an entry with ** a matching TriggerPrg.pTrigger field will be present somewhere ** in the Parse.pTriggerPrg list. Search for such an entry. */ - for(pPrg=pRoot->pTriggerPrg; - pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); + for(pPrg=pRoot->pTriggerPrg; + pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); pPrg=pPrg->pNext ); /* If an existing TriggerPrg could not be located, create a new one. */ if( !pPrg ){ pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); - pParse->db->errByteOffset = -1; } return pPrg; } /* -** Generate code for the trigger program associated with trigger p on +** Generate code for the trigger program associated with trigger p on ** table pTab. The reg, orconf and ignoreJump parameters passed to this ** function are the same as those described in the header function for ** sqlite3CodeRowTrigger() */ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect( @@ -154198,13 +124542,13 @@ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ TriggerPrg *pPrg; pPrg = getRowTrigger(pParse, p, pTab, orconf); - assert( pPrg || pParse->nErr ); + assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); - /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program + /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program ** is a pointer to the sub-vdbe containing the trigger program. */ if( pPrg ){ int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem, @@ -154215,11 +124559,11 @@ /* Set the P5 operand of the OP_Program instruction to non-zero if ** recursive invocation of this trigger program is disallowed. Recursive ** invocation is disallowed if (a) the sub-program is really a trigger, ** not a foreign key action, and (b) the flag to enable recursive triggers ** is clear. */ - sqlite3VdbeChangeP5(v, (u16)bRecursive); + sqlite3VdbeChangeP5(v, (u8)bRecursive); } } /* ** This is called to code the required FOR EACH ROW triggers for an operation @@ -154229,11 +124573,11 @@ ** parameter pChanges is passed the list of columns being modified. ** ** If there are no triggers that fire at the specified time for the specified ** operation on pTab, this function is a no-op. ** -** The reg argument is the address of the first in an array of registers +** The reg argument is the address of the first in an array of registers ** that contain the values substituted for the new.* and old.* references ** in the trigger program. If N is the number of columns in table pTab ** (a copy of pTab->nCol), then registers are populated as follows: ** ** Register Contains @@ -154241,21 +124585,21 @@ ** reg+0 OLD.rowid ** reg+1 OLD.* value of left-most column of pTab ** ... ... ** reg+N OLD.* value of right-most column of pTab ** reg+N+1 NEW.rowid -** reg+N+2 NEW.* value of left-most column of pTab +** reg+N+2 OLD.* value of left-most column of pTab ** ... ... ** reg+N+N+1 NEW.* value of right-most column of pTab ** ** For ON DELETE triggers, the registers containing the NEW.* values will -** never be accessed by the trigger program, so they are not allocated or -** populated by the caller (there is no data to populate them with anyway). +** never be accessed by the trigger program, so they are not allocated or +** populated by the caller (there is no data to populate them with anyway). ** Similarly, for ON INSERT triggers the values stored in the OLD.* registers ** are never accessed, and so are not allocated by the caller. So, for an ** ON INSERT trigger, the value passed to this function as parameter reg -** is not a readable register, although registers (reg+N) through +** is not a readable register, although registers (reg+N) through ** (reg+N+N+1) are. ** ** Parameter orconf is the default conflict resolution algorithm for the ** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump ** is the instruction that control should jump to if a trigger program @@ -154283,45 +124627,37 @@ /* Sanity checking: The schema for the trigger and for the table are ** always defined. The trigger must be in the same schema as the table ** or else it must be a TEMP trigger. */ assert( p->pSchema!=0 ); assert( p->pTabSchema!=0 ); - assert( p->pSchema==p->pTabSchema + assert( p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema ); - /* Determine whether we should code this trigger. One of two choices: - ** 1. The trigger is an exact match to the current DML statement - ** 2. This is a RETURNING trigger for INSERT but we are currently - ** doing the UPDATE part of an UPSERT. - */ - if( (p->op==op || (p->bReturning && p->op==TK_INSERT && op==TK_UPDATE)) - && p->tr_tm==tr_tm + /* Determine whether we should code this trigger */ + if( p->op==op + && p->tr_tm==tr_tm && checkColumnOverlap(p->pColumns, pChanges) ){ - if( !p->bReturning ){ - sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump); - }else if( sqlite3IsToplevel(pParse) ){ - codeReturningTrigger(pParse, p, pTab, reg); - } + sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump); } } } /* -** Triggers may access values stored in the old.* or new.* pseudo-table. -** This function returns a 32-bit bitmask indicating which columns of the -** old.* or new.* tables actually are used by triggers. This information +** Triggers may access values stored in the old.* or new.* pseudo-table. +** This function returns a 32-bit bitmask indicating which columns of the +** old.* or new.* tables actually are used by triggers. This information ** may be used by the caller, for example, to avoid having to load the entire ** old.* record into memory when executing an UPDATE or DELETE command. ** ** Bit 0 of the returned mask is set if the left-most column of the ** table may be accessed using an [old|new].reference. Bit 1 is set if ** the second leftmost column value is required, and so on. If there ** are more than 32 columns in the table, and at least one of the columns ** with an index greater than 32 may be accessed, 0xffffffff is returned. ** -** It is not possible to determine if the old.rowid or new.rowid column is +** It is not possible to determine if the old.rowid or new.rowid column is ** accessed by triggers. The caller must always assume that it is. ** ** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned ** applies to the old.* table. If 1, the new.* table. ** @@ -154343,26 +124679,18 @@ const int op = pChanges ? TK_UPDATE : TK_DELETE; u32 mask = 0; Trigger *p; assert( isNew==1 || isNew==0 ); - if( IsView(pTab) ){ - return 0xffffffff; - } for(p=pTrigger; p; p=p->pNext){ - if( p->op==op - && (tr_tm&p->tr_tm) + if( p->op==op && (tr_tm&p->tr_tm) && checkColumnOverlap(p->pColumns,pChanges) ){ - if( p->bReturning ){ - mask = 0xffffffff; - }else{ - TriggerPrg *pPrg; - pPrg = getRowTrigger(pParse, p, pTab, orconf); - if( pPrg ){ - mask |= pPrg->aColmask[isNew]; - } + TriggerPrg *pPrg; + pPrg = getRowTrigger(pParse, p, pTab, orconf); + if( pPrg ){ + mask |= pPrg->aColmask[isNew]; } } } return mask; @@ -154402,295 +124730,94 @@ ); #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** The most recently coded instruction was an OP_Column to retrieve the -** i-th column of table pTab. This routine sets the P4 parameter of the +** i-th column of table pTab. This routine sets the P4 parameter of the ** OP_Column to the default value, if any. ** -** The default value of a column is specified by a DEFAULT clause in the +** The default value of a column is specified by a DEFAULT clause in the ** column definition. This was either supplied by the user when the table ** was created, or added later to the table definition by an ALTER TABLE ** command. If the latter, then the row-records in the table btree on disk ** may not contain a value for the column and the default value, taken ** from the P4 parameter of the OP_Column instruction, is returned instead. ** If the former, then all row-records are guaranteed to include a value ** for the column and the P4 value is not required. ** -** Column definitions created by an ALTER TABLE command may only have +** Column definitions created by an ALTER TABLE command may only have ** literal default values specified: a number, null or a string. (If a more -** complicated default expression value was provided, it is evaluated +** complicated default expression value was provided, it is evaluated ** when the ALTER TABLE is executed and one of the literal values written -** into the sqlite_schema table.) +** into the sqlite_master table.) ** ** Therefore, the P4 parameter is only required if the default value for ** the column is a literal number, string or null. The sqlite3ValueFromExpr() ** function is capable of transforming these types of expressions into ** sqlite3_value objects. ** -** If column as REAL affinity and the table is an ordinary b-tree table -** (not a virtual table) then the value might have been stored as an -** integer. In that case, add an OP_RealAffinity opcode to make sure -** it has been converted into REAL. +** If parameter iReg is not negative, code an OP_RealAffinity instruction +** on register iReg. This is used when an equivalent integer value is +** stored in place of an 8-byte floating point value in order to save +** space. */ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ - Column *pCol; assert( pTab!=0 ); - assert( pTab->nCol>i ); - pCol = &pTab->aCol[i]; - if( pCol->iDflt ){ + if( !pTab->pSelect ){ sqlite3_value *pValue = 0; u8 enc = ENC(sqlite3VdbeDb(v)); - assert( !IsView(pTab) ); - VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName)); + Column *pCol = &pTab->aCol[i]; + VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); assert( inCol ); - sqlite3ValueFromExpr(sqlite3VdbeDb(v), - sqlite3ColumnExpr(pTab,pCol), enc, + sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue); if( pValue ){ sqlite3VdbeAppendP4(v, pValue, P4_MEM); } } #ifndef SQLITE_OMIT_FLOATING_POINT - if( pCol->affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){ + if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); } #endif } -/* -** Check to see if column iCol of index pIdx references any of the -** columns defined by aXRef and chngRowid. Return true if it does -** and false if not. This is an optimization. False-positives are a -** performance degradation, but false-negatives can result in a corrupt -** index and incorrect answers. -** -** aXRef[j] will be non-negative if column j of the original table is -** being updated. chngRowid will be true if the rowid of the table is -** being updated. -*/ -static int indexColumnIsBeingUpdated( - Index *pIdx, /* The index to check */ - int iCol, /* Which column of the index to check */ - int *aXRef, /* aXRef[j]>=0 if column j is being updated */ - int chngRowid /* true if the rowid is being updated */ -){ - i16 iIdxCol = pIdx->aiColumn[iCol]; - assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ - if( iIdxCol>=0 ){ - return aXRef[iIdxCol]>=0; - } - assert( iIdxCol==XN_EXPR ); - assert( pIdx->aColExpr!=0 ); - assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); - return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, - aXRef,chngRowid); -} - -/* -** Check to see if index pIdx is a partial index whose conditional -** expression might change values due to an UPDATE. Return true if -** the index is subject to change and false if the index is guaranteed -** to be unchanged. This is an optimization. False-positives are a -** performance degradation, but false-negatives can result in a corrupt -** index and incorrect answers. -** -** aXRef[j] will be non-negative if column j of the original table is -** being updated. chngRowid will be true if the rowid of the table is -** being updated. -*/ -static int indexWhereClauseMightChange( - Index *pIdx, /* The index to check */ - int *aXRef, /* aXRef[j]>=0 if column j is being updated */ - int chngRowid /* true if the rowid is being updated */ -){ - if( pIdx->pPartIdxWhere==0 ) return 0; - return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, - aXRef, chngRowid); -} - -/* -** Allocate and return a pointer to an expression of type TK_ROW with -** Expr.iColumn set to value (iCol+1). The resolver will modify the -** expression to be a TK_COLUMN reading column iCol of the first -** table in the source-list (pSrc->a[0]). -*/ -static Expr *exprRowColumn(Parse *pParse, int iCol){ - Expr *pRet = sqlite3PExpr(pParse, TK_ROW, 0, 0); - if( pRet ) pRet->iColumn = iCol+1; - return pRet; -} - -/* -** Assuming both the pLimit and pOrderBy parameters are NULL, this function -** generates VM code to run the query: -** -** SELECT , pChanges FROM pTabList WHERE pWhere -** -** and write the results to the ephemeral table already opened as cursor -** iEph. None of pChanges, pTabList or pWhere are modified or consumed by -** this function, they must be deleted by the caller. -** -** Or, if pLimit and pOrderBy are not NULL, and pTab is not a view: -** -** SELECT , pChanges FROM pTabList -** WHERE pWhere -** GROUP BY -** ORDER BY pOrderBy LIMIT pLimit -** -** If pTab is a view, the GROUP BY clause is omitted. -** -** Exactly how results are written to table iEph, and exactly what -** the in the query above are is determined by the type -** of table pTabList->a[0].pTab. -** -** If the table is a WITHOUT ROWID table, then argument pPk must be its -** PRIMARY KEY. In this case are the primary key columns -** of the table, in order. The results of the query are written to ephemeral -** table iEph as index keys, using OP_IdxInsert. -** -** If the table is actually a view, then are all columns of -** the view. The results are written to the ephemeral table iEph as records -** with automatically assigned integer keys. -** -** If the table is a virtual or ordinary intkey table, then -** is its rowid. For a virtual table, the results are written to iEph as -** records with automatically assigned integer keys For intkey tables, the -** rowid value in is used as the integer key, and the -** remaining fields make up the table record. -*/ -static void updateFromSelect( - Parse *pParse, /* Parse context */ - int iEph, /* Cursor for open eph. table */ - Index *pPk, /* PK if table 0 is WITHOUT ROWID */ - ExprList *pChanges, /* List of expressions to return */ - SrcList *pTabList, /* List of tables to select from */ - Expr *pWhere, /* WHERE clause for query */ - ExprList *pOrderBy, /* ORDER BY clause */ - Expr *pLimit /* LIMIT clause */ -){ - int i; - SelectDest dest; - Select *pSelect = 0; - ExprList *pList = 0; - ExprList *pGrp = 0; - Expr *pLimit2 = 0; - ExprList *pOrderBy2 = 0; - sqlite3 *db = pParse->db; - Table *pTab = pTabList->a[0].pSTab; - SrcList *pSrc; - Expr *pWhere2; - int eDest; - -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( pOrderBy && pLimit==0 ) { - sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE"); - return; - } - pOrderBy2 = sqlite3ExprListDup(db, pOrderBy, 0); - pLimit2 = sqlite3ExprDup(db, pLimit, 0); -#else - UNUSED_PARAMETER(pOrderBy); - UNUSED_PARAMETER(pLimit); -#endif - - pSrc = sqlite3SrcListDup(db, pTabList, 0); - pWhere2 = sqlite3ExprDup(db, pWhere, 0); - - assert( pTabList->nSrc>1 ); - if( pSrc ){ - assert( pSrc->a[0].fg.notCte ); - pSrc->a[0].iCursor = -1; - pSrc->a[0].pSTab->nTabRef--; - pSrc->a[0].pSTab = 0; - } - if( pPk ){ - for(i=0; inKeyCol; i++){ - Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]); -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( pLimit ){ - pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0)); - } -#endif - pList = sqlite3ExprListAppend(pParse, pList, pNew); - } - eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; - }else if( IsView(pTab) ){ - for(i=0; inCol; i++){ - pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); - } - eDest = SRT_Table; - }else{ - eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; - pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0)); -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( pLimit ){ - pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0)); - } -#endif - } - assert( pChanges!=0 || pParse->db->mallocFailed ); - if( pChanges ){ - for(i=0; inExpr; i++){ - pList = sqlite3ExprListAppend(pParse, pList, - sqlite3ExprDup(db, pChanges->a[i].pExpr, 0) - ); - } - } - pSelect = sqlite3SelectNew(pParse, pList, - pSrc, pWhere2, pGrp, 0, pOrderBy2, - SF_UFSrcCheck|SF_IncludeHidden|SF_UpdateFrom, pLimit2 - ); - if( pSelect ) pSelect->selFlags |= SF_OrderByReqd; - sqlite3SelectDestInit(&dest, eDest, iEph); - dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); - sqlite3Select(pParse, pSelect, &dest); - sqlite3SelectDelete(db, pSelect); -} - /* ** Process an UPDATE statement. ** -** UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL; -** \_______/ \_/ \______/ \_____/ \________________/ -** onError | pChanges | pWhere -** \_______________________/ -** pTabList +** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; +** \_______/ \________/ \______/ \________________/ +* onError pTabList pChanges pWhere */ SQLITE_PRIVATE void sqlite3Update( Parse *pParse, /* The parser context */ SrcList *pTabList, /* The table in which we should change things */ ExprList *pChanges, /* Things to be changed */ Expr *pWhere, /* The WHERE clause. May be null */ - int onError, /* How to handle constraint errors */ - ExprList *pOrderBy, /* ORDER BY clause. May be null */ - Expr *pLimit, /* LIMIT clause. May be null */ - Upsert *pUpsert /* ON CONFLICT clause, or null */ + int onError /* How to handle constraint errors */ ){ - int i, j, k; /* Loop counters */ + int i, j; /* Loop counters */ Table *pTab; /* The table to be updated */ int addrTop = 0; /* VDBE instruction address of the start of the loop */ - WhereInfo *pWInfo = 0; /* Information about the WHERE clause */ + WhereInfo *pWInfo; /* Information about the WHERE clause */ Vdbe *v; /* The virtual database engine */ Index *pIdx; /* For looping over indices */ Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */ int nIdx; /* Number of indices that need updating */ - int nAllIdx; /* Total number of indexes */ int iBaseCur; /* Base cursor number */ int iDataCur; /* Cursor for the canonical data btree */ int iIdxCur; /* Cursor for the first index */ sqlite3 *db; /* The database structure */ - int *aRegIdx = 0; /* Registers for to each index and the main table */ + int *aRegIdx = 0; /* First register in array assigned to each index */ int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ u8 *aToOpen; /* 1 for tables and indices to be opened */ u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */ u8 chngRowid; /* Rowid changed in a normal table */ u8 chngKey; /* Either chngPk or chngRowid */ Expr *pRowidExpr = 0; /* Expression defining the new record number */ - int iRowidExpr = -1; /* Index of "rowid=" (or IPK) assignment in pChanges */ AuthContext sContext; /* The authorization context */ NameContext sNC; /* The name-context to resolve expressions in */ int iDb; /* Database containing the table being updated */ int eOnePass; /* ONEPASS_XXX value from where.c */ int hasFK; /* True if foreign key processing is required */ @@ -154709,12 +124836,10 @@ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ int addrOpen = 0; /* Address of OP_OpenEphemeral */ int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */ i16 nPk = 0; /* Number of components of the PRIMARY KEY */ int bReplace = 0; /* True if REPLACE conflict resolution might happen */ - int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */ - int nChangeFrom = 0; /* If there is a FROM, pChanges->nExpr, else 0 */ /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ int regOldRowid = 0; /* The old rowid */ int regNewRowid = 0; /* The new rowid */ @@ -154723,17 +124848,16 @@ int regRowSet = 0; /* Rowset of rows to be updated */ int regKey = 0; /* composite PRIMARY KEY value */ memset(&sContext, 0, sizeof(sContext)); db = pParse->db; - assert( db->pParse==pParse ); - if( pParse->nErr ){ + if( pParse->nErr || db->mallocFailed ){ goto update_cleanup; } - assert( db->mallocFailed==0 ); + assert( pTabList->nSrc==1 ); - /* Locate the table which we want to update. + /* Locate the table which we want to update. */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); @@ -154740,11 +124864,11 @@ /* Figure out if we have any triggers and if the table being ** updated is a view. */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); - isView = IsView(pTab); + isView = pTab->pSelect!=0; assert( pTrigger || tmask==0 ); #else # define pTrigger 0 # define isView 0 # define tmask 0 @@ -154752,143 +124876,88 @@ #ifdef SQLITE_OMIT_VIEW # undef isView # define isView 0 #endif -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x10000 ){ - sqlite3TreeViewLine(0, "In sqlite3Update() at %s:%d", __FILE__, __LINE__); - sqlite3TreeViewUpdate(pParse->pWith, pTabList, pChanges, pWhere, - onError, pOrderBy, pLimit, pUpsert, pTrigger); - } -#endif - - /* If there was a FROM clause, set nChangeFrom to the number of expressions - ** in the change-list. Otherwise, set it to 0. There cannot be a FROM - ** clause if this function is being called to generate code for part of - ** an UPSERT statement. */ - nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0; - assert( nChangeFrom==0 || pUpsert==0 ); - -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( !isView && nChangeFrom==0 ){ - pWhere = sqlite3LimitWhere( - pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" - ); - pOrderBy = 0; - pLimit = 0; - } -#endif - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto update_cleanup; } - if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ + if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ goto update_cleanup; } /* Allocate a cursors for the main database table and for all indices. ** The index cursors might not be used, but if they are used they ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ - iBaseCur = iDataCur = pParse->nTab++; + pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++; iIdxCur = iDataCur+1; pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); - testcase( pPk!=0 && pPk!=pTab->pIndex ); for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ - if( pPk==pIdx ){ + if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ iDataCur = pParse->nTab; + pTabList->a[0].iCursor = iDataCur; } pParse->nTab++; } - if( pUpsert ){ - /* On an UPSERT, reuse the same cursors already opened by INSERT */ - iDataCur = pUpsert->iDataCur; - iIdxCur = pUpsert->iIdxCur; - pParse->nTab = iBaseCur; - } - pTabList->a[0].iCursor = iDataCur; - - /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. + + /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. ** Initialize aXRef[] and aToOpen[] to their default values. */ - aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx+1) + nIdx+2 ); + aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); if( aXRef==0 ) goto update_cleanup; aRegIdx = aXRef+pTab->nCol; - aToOpen = (u8*)(aRegIdx+nIdx+1); + aToOpen = (u8*)(aRegIdx+nIdx); memset(aToOpen, 1, nIdx+1); aToOpen[nIdx+1] = 0; for(i=0; inCol; i++) aXRef[i] = -1; /* Initialize the name-context */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; - sNC.uNC.pUpsert = pUpsert; - sNC.ncFlags = NC_UUpsert; - - /* Begin generating code. */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto update_cleanup; /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRowid = chngPk = 0; for(i=0; inExpr; i++){ - u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName); - /* If this is an UPDATE with a FROM clause, do not resolve expressions - ** here. The call to sqlite3Select() below will do that. */ - if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ + if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ goto update_cleanup; } for(j=0; jnCol; j++){ - if( pTab->aCol[j].hName==hCol - && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0 - ){ + if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ if( j==pTab->iPKey ){ chngRowid = 1; pRowidExpr = pChanges->a[i].pExpr; - iRowidExpr = i; }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ chngPk = 1; } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){ - testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ); - testcase( pTab->aCol[j].colFlags & COLFLAG_STORED ); - sqlite3ErrorMsg(pParse, - "cannot UPDATE generated column \"%s\"", - pTab->aCol[j].zCnName); - goto update_cleanup; - } -#endif aXRef[j] = i; break; } } if( j>=pTab->nCol ){ - if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){ + if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){ j = -1; chngRowid = 1; pRowidExpr = pChanges->a[i].pExpr; - iRowidExpr = i; }else{ - sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName); + sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); pParse->checkSchema = 1; goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, - j<0 ? "ROWID" : pTab->aCol[j].zCnName, + j<0 ? "ROWID" : pTab->aCol[j].zName, db->aDb[iDb].zDbSName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ aXRef[j] = -1; @@ -154899,40 +124968,11 @@ assert( (chngRowid & chngPk)==0 ); assert( chngRowid==0 || chngRowid==1 ); assert( chngPk==0 || chngPk==1 ); chngKey = chngRowid + chngPk; -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - /* Mark generated columns as changing if their generator expressions - ** reference any changing column. The actual aXRef[] value for - ** generated expressions is not used, other than to check to see that it - ** is non-negative, so the value of aXRef[] for generated columns can be - ** set to any non-negative number. We use 99999 so that the value is - ** obvious when looking at aXRef[] in a symbolic debugger. - */ - if( pTab->tabFlags & TF_HasGenerated ){ - int bProgress; - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - do{ - bProgress = 0; - for(i=0; inCol; i++){ - if( aXRef[i]>=0 ) continue; - if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue; - if( sqlite3ExprReferencesUpdatedColumn( - sqlite3ColumnExpr(pTab, &pTab->aCol[i]), - aXRef, chngRowid) - ){ - aXRef[i] = 99999; - bProgress = 1; - } - } - }while( bProgress ); - } -#endif - - /* The SET expressions are not actually used inside the WHERE loop. + /* The SET expressions are not actually used inside the WHERE loop. ** So reset the colUsed mask. Unless this is a virtual table. In that ** case, set all bits of the colUsed mask (to ensure that the virtual ** table implementation makes all columns available). */ pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0; @@ -154940,54 +124980,52 @@ hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); /* There is one entry in the aRegIdx[] array for each index on the table ** being updated. Fill in aRegIdx[] with a register number that will hold ** the key for accessing each index. + ** + ** FIXME: Be smarter about omitting indexes that use expressions. */ - if( onError==OE_Replace ) bReplace = 1; - for(nAllIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nAllIdx++){ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; - if( chngKey || hasFK>1 || pIdx==pPk - || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) - ){ + if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; }else{ reg = 0; for(i=0; inKeyCol; i++){ - if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ + i16 iIdxCol = pIdx->aiColumn[i]; + if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; - if( onError==OE_Default && pIdx->onError==OE_Replace ){ + if( (onError==OE_Replace) + || (onError==OE_Default && pIdx->onError==OE_Replace) + ){ bReplace = 1; } break; } } } - if( reg==0 ) aToOpen[nAllIdx+1] = 0; - aRegIdx[nAllIdx] = reg; + if( reg==0 ) aToOpen[j+1] = 0; + aRegIdx[j] = reg; } - aRegIdx[nAllIdx] = ++pParse->nMem; /* Register storing the table record */ if( bReplace ){ - /* If REPLACE conflict resolution might be invoked, open cursors on all + /* If REPLACE conflict resolution might be invoked, open cursors on all ** indexes in case they are needed to delete records. */ memset(aToOpen, 1, nIdx+1); } + /* Begin generating code. */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); + sqlite3BeginWriteOperation(pParse, 1, iDb); /* Allocate required registers. */ if( !IsVirtual(pTab) ){ - /* For now, regRowSet and aRegIdx[nAllIdx] share the same register. - ** If regRowSet turns out to be needed, then aRegIdx[nAllIdx] will be - ** reallocated. aRegIdx[nAllIdx] is the register in which the main - ** table record is written. regRowSet holds the RowSet for the - ** two-pass update algorithm. */ - assert( aRegIdx[nAllIdx]==pParse->nMem ); - regRowSet = aRegIdx[nAllIdx]; + regRowSet = ++pParse->nMem; regOldRowid = regNewRowid = ++pParse->nMem; if( chngPk || pTrigger || hasFK ){ regOld = pParse->nMem + 1; pParse->nMem += pTab->nCol; } @@ -155005,23 +125043,19 @@ /* If we are trying to update a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) - if( nChangeFrom==0 && isView ){ - sqlite3MaterializeView(pParse, pTab, - pWhere, pOrderBy, pLimit, iDataCur - ); - pOrderBy = 0; - pLimit = 0; + if( isView ){ + sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur); } #endif /* Resolve the column names in all the expressions in the ** WHERE clause. */ - if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pWhere) ){ + if( sqlite3ResolveExprNames(&sNC, pWhere) ){ goto update_cleanup; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* Virtual tables must be handled separately */ @@ -155030,276 +125064,173 @@ pWhere, onError); goto update_cleanup; } #endif - /* Jump to labelBreak to abandon further processing of this UPDATE */ - labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse); - - /* Not an UPSERT. Normal processing. Begin by - ** initialize the count of updated rows */ - if( (db->flags&SQLITE_CountRows)!=0 - && !pParse->pTriggerTab - && !pParse->nested - && !pParse->bReturning - && pUpsert==0 - ){ + /* Initialize the count of updated rows */ + if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } - if( nChangeFrom==0 && HasRowid(pTab) ){ + if( HasRowid(pTab) ){ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); - iEph = pParse->nTab++; - addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet); }else{ - assert( pPk!=0 || HasRowid(pTab) ); - nPk = pPk ? pPk->nKeyCol : 0; + assert( pPk!=0 ); + nPk = pPk->nKeyCol; iPk = pParse->nMem+1; pParse->nMem += nPk; - pParse->nMem += nChangeFrom; regKey = ++pParse->nMem; - if( pUpsert==0 ){ - int nEphCol = nPk + nChangeFrom + (isView ? pTab->nCol : 0); - iEph = pParse->nTab++; - if( pPk ) sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); - addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nEphCol); - if( pPk ){ - KeyInfo *pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pPk); - if( pKeyInfo ){ - pKeyInfo->nAllField = nEphCol; - sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); - } - } - if( nChangeFrom ){ - updateFromSelect( - pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit - ); -#ifndef SQLITE_OMIT_SUBQUERY - if( isView ) iDataCur = iEph; -#endif - } - } - } - - if( nChangeFrom ){ - sqlite3MultiWrite(pParse); - eOnePass = ONEPASS_OFF; - nKey = nPk; - regKey = iPk; - }else{ - if( pUpsert ){ - /* If this is an UPSERT, then all cursors have already been opened by - ** the outer INSERT and the data cursor should be pointing at the row - ** that is to be updated. So bypass the code that searches for the - ** row(s) to be updated. - */ - pWInfo = 0; - eOnePass = ONEPASS_SINGLE; - sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); - bFinishSeek = 0; - }else{ - /* Begin the database scan. - ** - ** Do not consider a single-pass strategy for a multi-row update if - ** there is anything that might disrupt the cursor being used to do - ** the UPDATE: - ** (1) This is a nested UPDATE - ** (2) There are triggers - ** (3) There are FOREIGN KEY constraints - ** (4) There are REPLACE conflict handlers - ** (5) There are subqueries in the WHERE clause - */ - flags = WHERE_ONEPASS_DESIRED; - if( !pParse->nested - && !pTrigger - && !hasFK - && !chngKey - && !bReplace - && (pWhere==0 || !ExprHasProperty(pWhere, EP_Subquery)) - ){ - flags |= WHERE_ONEPASS_MULTIROW; - } - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur); - if( pWInfo==0 ) goto update_cleanup; - - /* A one-pass strategy that might update more than one row may not - ** be used if any column of the index used for the scan is being - ** updated. Otherwise, if there is an index on "b", statements like - ** the following could create an infinite loop: - ** - ** UPDATE t1 SET b=b+1 WHERE b>? - ** - ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI - ** strategy that uses an index for which one or more columns are being - ** updated. */ - eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo); - if( eOnePass!=ONEPASS_SINGLE ){ - sqlite3MultiWrite(pParse); - if( eOnePass==ONEPASS_MULTI ){ - int iCur = aiCurOnePass[1]; - if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ - eOnePass = ONEPASS_OFF; - } - assert( iCur!=iDataCur || !HasRowid(pTab) ); - } - } - } - - if( HasRowid(pTab) ){ - /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF - ** mode, write the rowid into the FIFO. In either of the one-pass modes, - ** leave it in register regOldRowid. */ - sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); - if( eOnePass==ONEPASS_OFF ){ - aRegIdx[nAllIdx] = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid); - }else{ - if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen); - } - }else{ - /* Read the PK of the current row into an array of registers. In - ** ONEPASS_OFF mode, serialize the array into a record and store it in - ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change - ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table - ** is not required) and leave the PK fields in the array of registers. */ - for(i=0; iaiColumn[i]>=0 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, - pPk->aiColumn[i], iPk+i); - } - if( eOnePass ){ - if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen); - nKey = nPk; - regKey = iPk; - }else{ - sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, - sqlite3IndexAffinityStr(db, pPk), nPk); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); - } - } - } - - if( pUpsert==0 ){ - if( nChangeFrom==0 && eOnePass!=ONEPASS_MULTI ){ - sqlite3WhereEnd(pWInfo); - } - - if( !isView ){ - int addrOnce = 0; - int iNotUsed1 = 0; - int iNotUsed2 = 0; - - /* Open every index that needs updating. */ - if( eOnePass!=ONEPASS_OFF ){ - if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; - if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; - } - - if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, - aToOpen, &iNotUsed1, &iNotUsed2); - if( addrOnce ){ - sqlite3VdbeJumpHereOrPopInst(v, addrOnce); - } - } - - /* Top of the update loop */ - if( eOnePass!=ONEPASS_OFF ){ - if( aiCurOnePass[0]!=iDataCur - && aiCurOnePass[1]!=iDataCur -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - && !isView -#endif - ){ - assert( pPk ); - sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); - VdbeCoverage(v); - } - if( eOnePass!=ONEPASS_SINGLE ){ - labelContinue = sqlite3VdbeMakeLabel(pParse); - } - sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); - VdbeCoverageIf(v, pPk==0); - VdbeCoverageIf(v, pPk!=0); - }else if( pPk || nChangeFrom ){ - labelContinue = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); - addrTop = sqlite3VdbeCurrentAddr(v); - if( nChangeFrom ){ - if( !isView ){ - if( pPk ){ - for(i=0; inTab++; + + sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); + addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); + sqlite3VdbeSetP4KeyInfo(pParse, pPk); + } + + /* Begin the database scan. + ** + ** Do not consider a single-pass strategy for a multi-row update if + ** there are any triggers or foreign keys to process, or rows may + ** be deleted as a result of REPLACE conflict handling. Any of these + ** things might disturb a cursor being used to scan through the table + ** or index, causing a single-pass approach to malfunction. */ + flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE; + if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ + flags |= WHERE_ONEPASS_MULTIROW; + } + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur); + if( pWInfo==0 ) goto update_cleanup; + + /* A one-pass strategy that might update more than one row may not + ** be used if any column of the index used for the scan is being + ** updated. Otherwise, if there is an index on "b", statements like + ** the following could create an infinite loop: + ** + ** UPDATE t1 SET b=b+1 WHERE b>? + ** + ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI + ** strategy that uses an index for which one or more columns are being + ** updated. */ + eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); + if( eOnePass==ONEPASS_MULTI ){ + int iCur = aiCurOnePass[1]; + if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ + eOnePass = ONEPASS_OFF; + } + assert( iCur!=iDataCur || !HasRowid(pTab) ); + } + + if( HasRowid(pTab) ){ + /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF + ** mode, write the rowid into the FIFO. In either of the one-pass modes, + ** leave it in register regOldRowid. */ + sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); + if( eOnePass==ONEPASS_OFF ){ + sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); + } + }else{ + /* Read the PK of the current row into an array of registers. In + ** ONEPASS_OFF mode, serialize the array into a record and store it in + ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change + ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table + ** is not required) and leave the PK fields in the array of registers. */ + for(i=0; iaiColumn[i]>=0 ); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); + } + if( eOnePass ){ + sqlite3VdbeChangeToNoop(v, addrOpen); + nKey = nPk; + regKey = iPk; + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, + sqlite3IndexAffinityStr(db, pPk), nPk); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); + } + } + + if( eOnePass!=ONEPASS_MULTI ){ + sqlite3WhereEnd(pWInfo); + } + + labelBreak = sqlite3VdbeMakeLabel(v); + if( !isView ){ + int addrOnce = 0; + + /* Open every index that needs updating. */ + if( eOnePass!=ONEPASS_OFF ){ + if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; + if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; + } + + if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, + 0, 0); + if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + } + + /* Top of the update loop */ + if( eOnePass!=ONEPASS_OFF ){ + if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ + assert( pPk ); + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); + VdbeCoverageNeverTaken(v); + } + if( eOnePass==ONEPASS_SINGLE ){ + labelContinue = labelBreak; + }else{ + labelContinue = sqlite3VdbeMakeLabel(v); + } + sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); + VdbeCoverageIf(v, pPk==0); + VdbeCoverageIf(v, pPk!=0); + }else if( pPk ){ + labelContinue = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); + addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); + VdbeCoverage(v); + }else{ + labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, + regOldRowid); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); + } + + /* If the record number will change, set register regNewRowid to + ** contain the new value. If the record number is not being modified, ** then regNewRowid is the same register as regOldRowid, which is ** already populated. */ assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); if( chngRowid ){ - assert( iRowidExpr>=0 ); - if( nChangeFrom==0 ){ - sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iEph, iRowidExpr, regNewRowid); - } + sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); } /* Compute the old pre-UPDATE content of the row being changed, if that ** information is needed */ if( chngPk || hasFK || pTrigger ){ u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); - oldmask |= sqlite3TriggerColmask(pParse, + oldmask |= sqlite3TriggerColmask(pParse, pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError ); for(i=0; inCol; i++){ - u32 colFlags = pTab->aCol[i].colFlags; - k = sqlite3TableColumnToStorage(pTab, i) + regOld; if( oldmask==0xffffffff || (i<32 && (oldmask & MASKBIT32(i))!=0) - || (colFlags & COLFLAG_PRIMKEY)!=0 + || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){ testcase( oldmask!=0xffffffff && i==31 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i); }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, k); + sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i); } } if( chngRowid==0 && pPk==0 ){ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); -#endif sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); } } /* Populate the array of registers beginning at regNew with the new @@ -155308,146 +125239,104 @@ ** made by triggers. ** ** If there are one or more BEFORE triggers, then do not populate the ** registers associated with columns that are (a) not modified by ** this UPDATE statement and (b) not accessed by new.* references. The - ** values for registers not modified by the UPDATE must be reloaded from - ** the database after the BEFORE triggers are fired anyway (as the trigger + ** values for registers not modified by the UPDATE must be reloaded from + ** the database after the BEFORE triggers are fired anyway (as the trigger ** may have modified them). So not loading those that are not going to ** be used eliminates some redundant opcodes. */ newmask = sqlite3TriggerColmask( pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError ); - for(i=0, k=regNew; inCol; i++, k++){ + for(i=0; inCol; i++){ if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, k); - }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){ - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--; + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); }else{ j = aXRef[i]; if( j>=0 ){ - if( nChangeFrom ){ - int nOff = (isView ? pTab->nCol : nPk); - assert( eOnePass==ONEPASS_OFF ); - sqlite3VdbeAddOp3(v, OP_Column, iEph, nOff+j, k); - }else{ - sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k); - } + sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ - /* This branch loads the value of a column that will not be changed + /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or ** if there are one or more BEFORE triggers that use this value via ** a new.* reference in a trigger program. */ testcase( i==31 ); testcase( i==32 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); - bFinishSeek = 0; + sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, k); + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } } } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pTab->tabFlags & TF_HasGenerated ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - sqlite3ComputeGeneratedColumns(pParse, regNew, pTab); - } -#endif /* Fire any BEFORE UPDATE triggers. This happens before constraints are ** verified. One could argue that this is wrong. */ if( tmask&TRIGGER_BEFORE ){ sqlite3TableAffinity(v, pTab, regNew); - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); - - if( !isView ){ - /* The row-trigger may have deleted the row being updated. In this - ** case, jump to the next row. No updates or AFTER triggers are - ** required. This behavior - what happens when the row being updated - ** is deleted or renamed by a BEFORE trigger - is left undefined in the - ** documentation. - */ - if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey); - VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); - VdbeCoverage(v); - } - - /* After-BEFORE-trigger-reload-loop: - ** If it did not delete it, the BEFORE trigger may still have modified - ** some of the columns of the row being updated. Load the values for - ** all columns not modified by the update statement into their registers - ** in case this has happened. Only unmodified columns are reloaded. - ** The values computed for modified columns use the values before the - ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26) - ** for an example. - */ - for(i=0, k=regNew; inCol; i++, k++){ - if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){ - if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--; - }else if( aXRef[i]<0 && i!=pTab->iPKey ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); - } - } -#ifndef SQLITE_OMIT_GENERATED_COLUMNS - if( pTab->tabFlags & TF_HasGenerated ){ - testcase( pTab->tabFlags & TF_HasVirtual ); - testcase( pTab->tabFlags & TF_HasStored ); - sqlite3ComputeGeneratedColumns(pParse, regNew, pTab); - } -#endif - } - } - - if( !isView ){ - /* Do constraint checks. */ - assert( regOldRowid>0 ); - sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, - regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, - aXRef, 0); - - /* If REPLACE conflict handling may have been used, or if the PK of the - ** row is changing, then the GenerateConstraintChecks() above may have - ** moved cursor iDataCur. Reseek it. */ - if( bReplace || chngKey ){ - if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey); - }else{ - sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); - } - VdbeCoverage(v); - } + sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, + TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); + + /* The row-trigger may have deleted the row being updated. In this + ** case, jump to the next row. No updates or AFTER triggers are + ** required. This behavior - what happens when the row being updated + ** is deleted or renamed by a BEFORE trigger - is left undefined in the + ** documentation. + */ + if( pPk ){ + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); + VdbeCoverage(v); + }else{ + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); + } + + /* If it did not delete it, the row-trigger may still have modified + ** some of the columns of the row being updated. Load the values for + ** all columns not modified by the update statement into their + ** registers in case this has happened. + */ + for(i=0; inCol; i++){ + if( aXRef[i]<0 && i!=pTab->iPKey ){ + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); + } + } + } + + if( !isView ){ + int addr1 = 0; /* Address of jump instruction */ + + /* Do constraint checks. */ + assert( regOldRowid>0 ); + sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, + regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, + aXRef); /* Do FK constraint checks. */ if( hasFK ){ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); } /* Delete the index entries associated with the current record. */ + if( bReplace || chngKey ){ + if( pPk ){ + addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); + }else{ + addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); + } + VdbeCoverageNeverTaken(v); + } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); - /* We must run the OP_FinishSeek opcode to resolve a prior - ** OP_DeferredSeek if there is any possibility that there have been - ** no OP_Column opcodes since the OP_DeferredSeek was issued. But - ** we want to avoid the OP_FinishSeek if possible, as running it - ** costs CPU cycles. */ - if( bFinishSeek ){ - sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur); - } - /* If changing the rowid value, or if there are foreign key constraints ** to process, delete the old record. Otherwise, add a noop OP_Delete ** to invoke the pre-update hook. ** - ** That (regNew==regnewRowid+1) is true is also important for the + ** That (regNew==regnewRowid+1) is true is also important for the ** pre-update hook. If the caller invokes preupdate_new(), the returned ** value is copied from memory cell (regNewRowid+1+iCol), where iCol ** is the column index supplied by the user. */ assert( regNew==regNewRowid+1 ); @@ -155466,81 +125355,83 @@ #else if( hasFK>1 || chngKey ){ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } #endif + if( bReplace || chngKey ){ + sqlite3VdbeJumpHere(v, addr1); + } if( hasFK ){ sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); } - + /* Insert the new index entries and the new record. */ sqlite3CompleteInsertion( - pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, - OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), + pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, + OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), 0, 0 ); /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key - ** to the row just updated. */ + ** to the row just updated. */ if( hasFK ){ sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); } } - /* Increment the row counter + /* Increment the row counter */ - if( regRowCount ){ + if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } - if( pTrigger ){ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); - } + sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, + TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ if( eOnePass==ONEPASS_SINGLE ){ /* Nothing to do at end-of-loop for a single-pass */ }else if( eOnePass==ONEPASS_MULTI ){ sqlite3VdbeResolveLabel(v, labelContinue); sqlite3WhereEnd(pWInfo); - }else{ + }else if( pPk ){ sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); + }else{ + sqlite3VdbeGoto(v, labelContinue); } sqlite3VdbeResolveLabel(v, labelBreak); /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ - if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){ + if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } /* - ** Return the number of rows that were changed, if we are tracking - ** that information. + ** Return the number of rows that were changed. If this routine is + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. */ - if( regRowCount ){ - sqlite3CodeChangeCount(v, regRowCount, "rows updated"); + if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); } update_cleanup: sqlite3AuthContextPop(&sContext); sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */ sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pChanges); sqlite3ExprDelete(db, pWhere); -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) - sqlite3ExprListDelete(db, pOrderBy); - sqlite3ExprDelete(db, pLimit); -#endif return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** they may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ @@ -155553,12 +125444,12 @@ #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Generate code for an UPDATE of a virtual table. ** -** There are two possible strategies - the default and the special -** "onepass" strategy. Onepass is only used if the virtual table +** There are two possible strategies - the default and the special +** "onepass" strategy. Onepass is only used if the virtual table ** implementation indicates that pWhere may match at most one row. ** ** The default strategy is to create an ephemeral table that contains ** for each row to be changed: ** @@ -155586,141 +125477,77 @@ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* Database connection */ const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); - WhereInfo *pWInfo = 0; + WhereInfo *pWInfo; int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ int regArg; /* First register in VUpdate arg array */ int regRec; /* Register in which to assemble record */ - int regRowid; /* Register for ephemeral table rowid */ + int regRowid; /* Register for ephem table rowid */ int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ - int eOnePass; /* True to use onepass strategy */ + int bOnePass; /* True to use onepass strategy */ int addr; /* Address of OP_OpenEphemeral */ - /* Allocate nArg registers in which to gather the arguments for VUpdate. Then + /* Allocate nArg registers to martial the arguments to VUpdate. Then ** create and open the ephemeral table in which the records created from ** these arguments will be temporarily stored. */ assert( v ); ephemTab = pParse->nTab++; addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); regArg = pParse->nMem + 1; pParse->nMem += nArg; - if( pSrc->nSrc>1 ){ - Index *pPk = 0; - Expr *pRow; - ExprList *pList; - if( HasRowid(pTab) ){ - if( pRowid ){ - pRow = sqlite3ExprDup(db, pRowid, 0); - }else{ - pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0); - } - }else{ - i16 iPk; /* PRIMARY KEY column */ - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - assert( pPk->nKeyCol==1 ); - iPk = pPk->aiColumn[0]; - if( aXRef[iPk]>=0 ){ - pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0); - }else{ - pRow = exprRowColumn(pParse, iPk); - } - } - pList = sqlite3ExprListAppend(pParse, 0, pRow); - - for(i=0; inCol; i++){ - if( aXRef[i]>=0 ){ - pList = sqlite3ExprListAppend(pParse, pList, - sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) - ); - }else{ - Expr *pRowExpr = exprRowColumn(pParse, i); - if( pRowExpr ) pRowExpr->op2 = OPFLAG_NOCHNG; - pList = sqlite3ExprListAppend(pParse, pList, pRowExpr); - } - } - - updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0); - sqlite3ExprListDelete(db, pList); - eOnePass = ONEPASS_OFF; - }else{ - regRec = ++pParse->nMem; - regRowid = ++pParse->nMem; - - /* Start scanning the virtual table */ - pWInfo = sqlite3WhereBegin( - pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0 - ); - if( pWInfo==0 ) return; - - /* Populate the argument registers. */ - for(i=0; inCol; i++){ - assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ); - if( aXRef[i]>=0 ){ - sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); - }else{ - sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* For sqlite3_vtab_nochange() */ - } - } - if( HasRowid(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); - if( pRowid ){ - sqlite3ExprCode(pParse, pRowid, regArg+1); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); - } - }else{ - Index *pPk; /* PRIMARY KEY index */ - i16 iPk; /* PRIMARY KEY column */ - pPk = sqlite3PrimaryKeyIndex(pTab); - assert( pPk!=0 ); - assert( pPk->nKeyCol==1 ); - iPk = pPk->aiColumn[0]; - sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg); - sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); - } - - eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); - - /* There is no ONEPASS_MULTI on virtual tables */ - assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); - - if( eOnePass ){ - /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded - ** above. */ - sqlite3VdbeChangeToNoop(v, addr); - sqlite3VdbeAddOp1(v, OP_Close, iCsr); - }else{ - /* Create a record from the argument register contents and insert it into - ** the ephemeral table. */ - sqlite3MultiWrite(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); -#if defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_NULL_TRIM) - /* Signal an assert() within OP_MakeRecord that it is allowed to - ** accept no-change records with serial_type 10 */ - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); -#endif - sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); - } - } - - - if( eOnePass==ONEPASS_OFF ){ + regRec = ++pParse->nMem; + regRowid = ++pParse->nMem; + + /* Start scanning the virtual table */ + pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); + if( pWInfo==0 ) return; + + /* Populate the argument registers. */ + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); + if( pRowid ){ + sqlite3ExprCode(pParse, pRowid, regArg+1); + }else{ + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); + } + for(i=0; inCol; i++){ + if( aXRef[i]>=0 ){ + sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); + }else{ + sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); + } + } + + bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + + if( bOnePass ){ + /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded + ** above. Also, if this is a top-level parse (not a trigger), clear the + ** multi-write flag so that the VM does not open a statement journal */ + sqlite3VdbeChangeToNoop(v, addr); + if( sqlite3IsToplevel(pParse) ){ + pParse->isMultiWrite = 0; + } + }else{ + /* Create a record from the argument register contents and insert it into + ** the ephemeral table. */ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); + sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); + } + + + if( bOnePass==0 ){ /* End the virtual table scan */ - if( pSrc->nSrc==1 ){ - sqlite3WhereEnd(pWInfo); - } + sqlite3WhereEnd(pWInfo); - /* Begin scanning through the ephemeral table. */ + /* Begin scannning through the ephemeral table. */ addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); - /* Extract arguments from the current row of the ephemeral table and + /* Extract arguments from the current row of the ephemeral table and ** invoke the VUpdate method. */ for(i=0; ipNextUpsert; - sqlite3ExprListDelete(db, p->pUpsertTarget); - sqlite3ExprDelete(db, p->pUpsertTargetWhere); - sqlite3ExprListDelete(db, p->pUpsertSet); - sqlite3ExprDelete(db, p->pUpsertWhere); - sqlite3DbFree(db, p->pToFree); - sqlite3DbFree(db, p); - p = pNext; - }while( p ); -} -SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){ - if( p ) upsertDelete(db, p); -} - - -/* -** Duplicate an Upsert object. -*/ -SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){ - if( p==0 ) return 0; - return sqlite3UpsertNew(db, - sqlite3ExprListDup(db, p->pUpsertTarget, 0), - sqlite3ExprDup(db, p->pUpsertTargetWhere, 0), - sqlite3ExprListDup(db, p->pUpsertSet, 0), - sqlite3ExprDup(db, p->pUpsertWhere, 0), - sqlite3UpsertDup(db, p->pNextUpsert) - ); -} - -/* -** Create a new Upsert object. -*/ -SQLITE_PRIVATE Upsert *sqlite3UpsertNew( - sqlite3 *db, /* Determines which memory allocator to use */ - ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */ - Expr *pTargetWhere, /* Optional WHERE clause on the target */ - ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */ - Expr *pWhere, /* WHERE clause for the ON CONFLICT UPDATE */ - Upsert *pNext /* Next ON CONFLICT clause in the list */ -){ - Upsert *pNew; - pNew = sqlite3DbMallocZero(db, sizeof(Upsert)); - if( pNew==0 ){ - sqlite3ExprListDelete(db, pTarget); - sqlite3ExprDelete(db, pTargetWhere); - sqlite3ExprListDelete(db, pSet); - sqlite3ExprDelete(db, pWhere); - sqlite3UpsertDelete(db, pNext); - return 0; - }else{ - pNew->pUpsertTarget = pTarget; - pNew->pUpsertTargetWhere = pTargetWhere; - pNew->pUpsertSet = pSet; - pNew->pUpsertWhere = pWhere; - pNew->isDoUpdate = pSet!=0; - pNew->pNextUpsert = pNext; - } - return pNew; -} - -/* -** Analyze the ON CONFLICT clause described by pUpsert. Resolve all -** symbols in the conflict-target. -** -** Return SQLITE_OK if everything works, or an error code is something -** is wrong. -*/ -SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( - Parse *pParse, /* The parsing context */ - SrcList *pTabList, /* Table into which we are inserting */ - Upsert *pUpsert, /* The ON CONFLICT clauses */ - Upsert *pAll /* Complete list of all ON CONFLICT clauses */ -){ - Table *pTab; /* That table into which we are inserting */ - int rc; /* Result code */ - int iCursor; /* Cursor used by pTab */ - Index *pIdx; /* One of the indexes of pTab */ - ExprList *pTarget; /* The conflict-target clause */ - Expr *pTerm; /* One term of the conflict-target clause */ - NameContext sNC; /* Context for resolving symbolic names */ - Expr sCol[2]; /* Index column converted into an Expr */ - int nClause = 0; /* Counter of ON CONFLICT clauses */ - - assert( pTabList->nSrc==1 ); - assert( pTabList->a[0].pSTab!=0 ); - assert( pUpsert!=0 ); - assert( pUpsert->pUpsertTarget!=0 ); - - /* Resolve all symbolic names in the conflict-target clause, which - ** includes both the list of columns and the optional partial-index - ** WHERE clause. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - for(; pUpsert && pUpsert->pUpsertTarget; - pUpsert=pUpsert->pNextUpsert, nClause++){ - rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); - if( rc ) return rc; - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); - if( rc ) return rc; - - /* Check to see if the conflict target matches the rowid. */ - pTab = pTabList->a[0].pSTab; - pTarget = pUpsert->pUpsertTarget; - iCursor = pTabList->a[0].iCursor; - if( HasRowid(pTab) - && pTarget->nExpr==1 - && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN - && pTerm->iColumn==XN_ROWID - ){ - /* The conflict-target is the rowid of the primary table */ - assert( pUpsert->pUpsertIdx==0 ); - continue; - } - - /* Initialize sCol[0..1] to be an expression parse tree for a - ** single column of an index. The sCol[0] node will be the TK_COLLATE - ** operator and sCol[1] will be the TK_COLUMN operator. Code below - ** will populate the specific collation and column number values - ** prior to comparing against the conflict-target expression. - */ - memset(sCol, 0, sizeof(sCol)); - sCol[0].op = TK_COLLATE; - sCol[0].pLeft = &sCol[1]; - sCol[1].op = TK_COLUMN; - sCol[1].iTable = pTabList->a[0].iCursor; - - /* Check for matches against other indexes */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int ii, jj, nn; - if( !IsUniqueIndex(pIdx) ) continue; - if( pTarget->nExpr!=pIdx->nKeyCol ) continue; - if( pIdx->pPartIdxWhere ){ - if( pUpsert->pUpsertTargetWhere==0 ) continue; - if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere, - pIdx->pPartIdxWhere, iCursor)!=0 ){ - continue; - } - } - nn = pIdx->nKeyCol; - for(ii=0; iiazColl[ii]; - if( pIdx->aiColumn[ii]==XN_EXPR ){ - assert( pIdx->aColExpr!=0 ); - assert( pIdx->aColExpr->nExpr>ii ); - assert( pIdx->bHasExpr ); - pExpr = pIdx->aColExpr->a[ii].pExpr; - if( pExpr->op!=TK_COLLATE ){ - sCol[0].pLeft = pExpr; - pExpr = &sCol[0]; - } - }else{ - sCol[0].pLeft = &sCol[1]; - sCol[1].iColumn = pIdx->aiColumn[ii]; - pExpr = &sCol[0]; - } - for(jj=0; jja[jj].pExpr,pExpr,iCursor)<2 ){ - break; /* Column ii of the index matches column jj of target */ - } - } - if( jj>=nn ){ - /* The target contains no match for column jj of the index */ - break; - } - } - if( iipUpsertIdx = pIdx; - if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){ - /* Really this should be an error. The isDup ON CONFLICT clause will - ** never fire. But this problem was not discovered until three years - ** after multi-CONFLICT upsert was added, and so we silently ignore - ** the problem to prevent breaking applications that might actually - ** have redundant ON CONFLICT clauses. */ - pUpsert->isDup = 1; - } - break; - } - if( pUpsert->pUpsertIdx==0 ){ - char zWhich[16]; - if( nClause==0 && pUpsert->pNextUpsert==0 ){ - zWhich[0] = 0; - }else{ - sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1); - } - sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any " - "PRIMARY KEY or UNIQUE constraint", zWhich); - return SQLITE_ERROR; - } - } - return SQLITE_OK; -} - -/* -** Return true if pUpsert is the last ON CONFLICT clause with a -** conflict target, or if pUpsert is followed by another ON CONFLICT -** clause that targets the INTEGER PRIMARY KEY. -*/ -SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){ - Upsert *pNext; - if( NEVER(pUpsert==0) ) return 0; - pNext = pUpsert->pNextUpsert; - while( 1 /*exit-by-return*/ ){ - if( pNext==0 ) return 1; - if( pNext->pUpsertTarget==0 ) return 1; - if( pNext->pUpsertIdx==0 ) return 1; - if( !pNext->isDup ) return 0; - pNext = pNext->pNextUpsert; - } - return 0; -} - -/* -** Given the list of ON CONFLICT clauses described by pUpsert, and -** a particular index pIdx, return a pointer to the particular ON CONFLICT -** clause that applies to the index. Or, if the index is not subject to -** any ON CONFLICT clause, return NULL. -*/ -SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){ - while( - pUpsert - && pUpsert->pUpsertTarget!=0 - && pUpsert->pUpsertIdx!=pIdx - ){ - pUpsert = pUpsert->pNextUpsert; - } - return pUpsert; -} - -/* -** Generate bytecode that does an UPDATE as part of an upsert. -** -** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK. -** In this case parameter iCur is a cursor open on the table b-tree that -** currently points to the conflicting table row. Otherwise, if pIdx -** is not NULL, then pIdx is the constraint that failed and iCur is a -** cursor points to the conflicting row. -*/ -SQLITE_PRIVATE void sqlite3UpsertDoUpdate( - Parse *pParse, /* The parsing and code-generating context */ - Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */ - Table *pTab, /* The table being updated */ - Index *pIdx, /* The UNIQUE constraint that failed */ - int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */ -){ - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - SrcList *pSrc; /* FROM clause for the UPDATE */ - int iDataCur; - int i; - Upsert *pTop = pUpsert; - - assert( v!=0 ); - assert( pUpsert!=0 ); - iDataCur = pUpsert->iDataCur; - pUpsert = sqlite3UpsertOfIndex(pTop, pIdx); - VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); - if( pIdx && iCur!=iDataCur ){ - if( HasRowid(pTab) ){ - int regRowid = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid); - sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid); - VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, regRowid); - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - int nPk = pPk->nKeyCol; - int iPk = pParse->nMem+1; - pParse->nMem += nPk; - for(i=0; iaiColumn[i]>=0 ); - k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); - sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); - VdbeComment((v, "%s.%s", pIdx->zName, - pTab->aCol[pPk->aiColumn[i]].zCnName)); - } - sqlite3VdbeVerifyAbortable(v, OE_Abort); - i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk); - VdbeCoverage(v); - sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, - "corrupt database", P4_STATIC); - sqlite3MayAbort(pParse); - sqlite3VdbeJumpHere(v, i); - } - } - /* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does. - ** So we have to make a copy before passing it down into sqlite3Update() */ - pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0); - /* excluded.* columns of type REAL need to be converted to a hard real */ - for(i=0; inCol; i++){ - if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i); - } - } - sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0), - sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert); - VdbeNoopComment((v, "End DO UPDATE of UPSERT")); -} - -#endif /* SQLITE_OMIT_UPSERT */ - -/************** End of upsert.c **********************************************/ /************** Begin file vacuum.c ******************************************/ /* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of @@ -156114,18 +125609,12 @@ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); - /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX, - ** or INSERT. Historically there have been attacks that first - ** corrupt the sqlite_schema.sql field with other kinds of statements - ** then run VACUUM to get those statements to execute at inappropriate - ** times. */ - if( zSubSql - && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0) - ){ + if( zSubSql ){ + assert( zSubSql[0]!='S' ); rc = execSql(db, pzErrMsg, zSubSql); if( rc!=SQLITE_OK ) break; } } assert( rc!=SQLITE_ROW ); @@ -156177,21 +125666,20 @@ ** not work if other processes are attached to the original database. ** And a power loss in between deleting the original and renaming the ** transient would cause the database file to appear to be deleted ** following reboot. */ -SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){ +SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ Vdbe *v = sqlite3GetVdbe(pParse); int iDb = 0; - if( v==0 ) goto build_vacuum_end; - if( pParse->nErr ) goto build_vacuum_end; + if( v==0 ) return; if( pNm ){ #ifndef SQLITE_BUG_COMPATIBLE_20160819 /* Default behavior: Report an error if the argument to VACUUM is ** not recognized */ iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm); - if( iDb<0 ) goto build_vacuum_end; + if( iDb<0 ) return; #else /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments ** to VACUUM are silently ignored. This is a back-out of a bug fix that ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270). ** The buggy behavior is required for binary compatibility with some @@ -156199,150 +125687,115 @@ iDb = sqlite3FindDb(pParse->db, pNm); if( iDb<0 ) iDb = 0; #endif } if( iDb!=1 ){ - int iIntoReg = 0; - if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){ - iIntoReg = ++pParse->nMem; - sqlite3ExprCode(pParse, pInto, iIntoReg); - } - sqlite3VdbeAddOp2(v, OP_Vacuum, iDb, iIntoReg); + sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); sqlite3VdbeUsesBtree(v, iDb); } -build_vacuum_end: - sqlite3ExprDelete(pParse->db, pInto); return; } /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( - char **pzErrMsg, /* Write error message here */ - sqlite3 *db, /* Database connection */ - int iDb, /* Which attached DB to vacuum */ - sqlite3_value *pOut /* Write results here, if not NULL. VACUUM INTO */ -){ +SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ - u32 saved_mDbFlags; /* Saved value of db->mDbFlags */ - u64 saved_flags; /* Saved value of db->flags */ - i64 saved_nChange; /* Saved value of db->nChange */ - i64 saved_nTotalChange; /* Saved value of db->nTotalChange */ - u32 saved_openFlags; /* Saved value of db->openFlags */ + int saved_flags; /* Saved value of the db->flags */ + int saved_nChange; /* Saved value of db->nChange */ + int saved_nTotalChange; /* Saved value of db->nTotalChange */ u8 saved_mTrace; /* Saved trace settings */ Db *pDb = 0; /* Database to detach at end of vacuum */ int isMemDb; /* True if vacuuming a :memory: database */ int nRes; /* Bytes of reserved space at the end of each page */ int nDb; /* Number of attached databases */ const char *zDbMain; /* Schema name of database to vacuum */ - const char *zOut; /* Name of output file */ - u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */ - u64 iRandom; /* Random value used for zDbVacuum[] */ - char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */ - if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); - return SQLITE_ERROR; /* IMP: R-12218-18073 */ + return SQLITE_ERROR; } if( db->nVdbeActive>1 ){ sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); - return SQLITE_ERROR; /* IMP: R-15610-35227 */ - } - saved_openFlags = db->openFlags; - if( pOut ){ - if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){ - sqlite3SetString(pzErrMsg, db, "non-text filename"); - return SQLITE_ERROR; - } - zOut = (const char*)sqlite3_value_text(pOut); - db->openFlags &= ~SQLITE_OPEN_READONLY; - db->openFlags |= SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; - }else{ - zOut = ""; - } - - /* Save the current value of the database flags so that it can be + return SQLITE_ERROR; + } + + /* Save the current value of the database flags so that it can be ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; - saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; - db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; - db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder - | SQLITE_Defensive | SQLITE_CountRows); + db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks + | SQLITE_PreferBuiltin | SQLITE_Vacuum); + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); db->mTrace = 0; zDbMain = db->aDb[iDb].zDbSName; pMain = db->aDb[iDb].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); - /* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma + /* Attach the temporary database as 'vacuum_db'. The synchronous pragma ** can be set to 'off' for this file, as it is not recovered if a crash ** occurs anyway. The integrity of the database is maintained by a ** (possibly synchronous) transaction opened on the main database before ** sqlite3BtreeCopyFile() is called. ** - ** An optimization would be to use a non-journaled pager. - ** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but + ** An optimisation would be to use a non-journaled pager. + ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but ** that actually made the VACUUM run slower. Very little journalling ** actually occurs when doing a vacuum since the vacuum_db is initially ** empty. Only the journal header is written. Apparently it takes more ** time to parse and run the PRAGMA to turn journalling off than it does ** to write the journal header file. */ - sqlite3_randomness(sizeof(iRandom),&iRandom); - sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom); nDb = db->nDb; - rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum); - db->openFlags = saved_openFlags; + rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db"); if( rc!=SQLITE_OK ) goto end_of_vacuum; assert( (db->nDb-1)==nDb ); pDb = &db->aDb[nDb]; - assert( strcmp(pDb->zDbSName,zDbVacuum)==0 ); + assert( strcmp(pDb->zDbSName,"vacuum_db")==0 ); pTemp = pDb->pBt; - if( pOut ){ - sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp)); - i64 sz = 0; - if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){ - rc = SQLITE_ERROR; - sqlite3SetString(pzErrMsg, db, "output file already exists"); - goto end_of_vacuum; - } - db->mDbFlags |= DBFLAG_VacuumInto; - - /* For a VACUUM INTO, the pager-flags are set to the same values as - ** they are for the database being vacuumed, except that PAGER_CACHESPILL - ** is always set. */ - pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK); - } - nRes = sqlite3BtreeGetRequestedReserve(pMain); + + /* The call to execSql() to attach the temp database has left the file + ** locked (as there was more than one active statement when the transaction + ** to read the schema was concluded. Unlock it here so that this doesn't + ** cause problems for the call to BtreeSetPageSize() below. */ + sqlite3BtreeCommit(pTemp); + + nRes = sqlite3BtreeGetOptimalReserve(pMain); + + /* A VACUUM cannot change the pagesize of an encrypted database. */ +#ifdef SQLITE_HAS_CODEC + if( db->nextPagesize ){ + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); + int nKey; + char *zKey; + sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey); + if( nKey ) db->nextPagesize = 0; + } +#endif sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); - sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL); + sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); /* Begin a transaction and take an exclusive lock on the main database ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, ** to ensure that we do not try to change the page-size on a WAL database. */ rc = execSql(db, pzErrMsg, "BEGIN"); if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0); + rc = sqlite3BtreeBeginTrans(pMain, 2); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Do not attempt to change the page size for a WAL database */ if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) - ==PAGER_JOURNALMODE_WAL - && pOut==0 - ){ + ==PAGER_JOURNALMODE_WAL ){ db->nextPagesize = 0; } if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0) || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) @@ -156360,19 +125813,19 @@ /* Query the schema of the main database. Create a mirror schema ** in the temporary database. */ db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */ rc = execSqlF(db, pzErrMsg, - "SELECT sql FROM \"%w\".sqlite_schema" + "SELECT sql FROM \"%w\".sqlite_master" " WHERE type='table'AND name<>'sqlite_sequence'" " AND coalesce(rootpage,1)>0", zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = execSqlF(db, pzErrMsg, - "SELECT sql FROM \"%w\".sqlite_schema" - " WHERE type='index'", + "SELECT sql FROM \"%w\".sqlite_master" + " WHERE type='index' AND length(sql)>10", zDbMain ); if( rc!=SQLITE_OK ) goto end_of_vacuum; db->init.iDb = 0; @@ -156379,35 +125832,35 @@ /* Loop through the tables in the main database. For each, do ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ rc = execSqlF(db, pzErrMsg, - "SELECT'INSERT INTO %s.'||quote(name)" + "SELECT'INSERT INTO vacuum_db.'||quote(name)" "||' SELECT*FROM\"%w\".'||quote(name)" - "FROM %s.sqlite_schema " + "FROM vacuum_db.sqlite_master " "WHERE type='table'AND coalesce(rootpage,1)>0", - zDbVacuum, zDbMain, zDbVacuum + zDbMain ); - assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 ); - db->mDbFlags &= ~DBFLAG_Vacuum; + assert( (db->flags & SQLITE_Vacuum)!=0 ); + db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy the triggers, views, and virtual tables from the main database ** over to the temporary database. None of these objects has any ** associated storage, so all we have to do is copy their entries - ** from the schema table. + ** from the SQLITE_MASTER table. */ rc = execSqlF(db, pzErrMsg, - "INSERT INTO %s.sqlite_schema" - " SELECT*FROM \"%w\".sqlite_schema" + "INSERT INTO vacuum_db.sqlite_master" + " SELECT*FROM \"%w\".sqlite_master" " WHERE type IN('view','trigger')" " OR(type='table'AND rootpage=0)", - zDbVacuum, zDbMain + zDbMain ); if( rc ) goto end_of_vacuum; - /* At this point, there is a write transaction open on both the + /* At this point, there is a write transaction open on both the ** vacuum database and the main database. Assuming no error occurs, ** both transactions are closed by this block - the main database ** transaction by sqlite3BtreeCopyFile() and the other by an explicit ** call to sqlite3BtreeCommit(). */ @@ -156427,12 +125880,12 @@ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ BTREE_USER_VERSION, 0, /* Preserve the user version */ BTREE_APPLICATION_ID, 0, /* Preserve the application id */ }; - assert( SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pTemp) ); - assert( pOut!=0 || SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pMain) ); + assert( 1==sqlite3BtreeIsInTrans(pTemp) ); + assert( 1==sqlite3BtreeIsInTrans(pMain) ); /* Copy Btree meta values */ for(i=0; iflags */ db->init.iDb = 0; - db->mDbFlags = saved_mDbFlags; db->flags = saved_flags; db->nChange = saved_nChange; db->nTotalChange = saved_nTotalChange; db->mTrace = saved_mTrace; - sqlite3BtreeSetPageSize(pMain, -1, 0, 1); + sqlite3BtreeSetPageSize(pMain, -1, -1, 1); /* Currently there is an SQL level transaction open on the vacuum ** database. No locks are held on any other files (since the main file ** was committed at the btree level). So it safe to end the transaction ** by manually setting the autoCommit flag to true and detaching the @@ -156484,11 +125929,11 @@ pDb->pBt = 0; pDb->pSchema = 0; } /* This both clears the schemas and reduces the size of the db->aDb[] - ** array. */ + ** array. */ sqlite3ResetAllSchemasOfConnection(db); return rc; } @@ -156513,11 +125958,11 @@ /* #include "sqliteInt.h" */ /* ** Before a virtual table xCreate() or xConnect() method is invoked, the ** sqlite3.pVtabCtx member variable is set to point to an instance of -** this struct allocated on the stack. It is used by the implementation of +** this struct allocated on the stack. It is used by the implementation of ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which ** are invoked only from within xCreate and xConnect methods. */ struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ @@ -156528,52 +125973,36 @@ /* ** Construct and install a Module object for a virtual table. When this ** routine is called, it is guaranteed that all appropriate locks are held ** and the module is not already part of the connection. -** -** If there already exists a module with zName, replace it with the new one. -** If pModule==0, then delete the module zName if it exists. */ SQLITE_PRIVATE Module *sqlite3VtabCreateModule( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ Module *pMod; - Module *pDel; - char *zCopy; - if( pModule==0 ){ - zCopy = (char*)zName; - pMod = 0; - }else{ - int nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); - if( pMod==0 ){ - sqlite3OomFault(db); - return 0; - } - zCopy = (char *)(&pMod[1]); + int nName = sqlite3Strlen30(zName); + pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); + if( pMod ){ + Module *pDel; + char *zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); pMod->zName = zCopy; pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; pMod->pEpoTab = 0; - pMod->nRefModule = 1; - } - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); - if( pDel ){ - if( pDel==pMod ){ + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); + assert( pDel==0 || pDel==pMod ); + if( pDel ){ sqlite3OomFault(db); sqlite3DbFree(db, pDel); pMod = 0; - }else{ - sqlite3VtabEponymousTableClear(db, pDel); - sqlite3VtabModuleUnref(db, pDel); } } return pMod; } @@ -156590,11 +126019,15 @@ void (*xDestroy)(void *) /* Module destructor function */ ){ int rc = SQLITE_OK; sqlite3_mutex_enter(db->mutex); - (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); + if( sqlite3HashFind(&db->aModule, zName) ){ + rc = SQLITE_MISUSE_BKPT; + }else{ + (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); + } rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); sqlite3_mutex_leave(db->mutex); return rc; } @@ -156629,52 +126062,14 @@ if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; #endif return createModule(db, zName, pModule, pAux, xDestroy); } -/* -** External API to drop all virtual-table modules, except those named -** on the azNames list. -*/ -SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){ - HashElem *pThis, *pNext; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){ - Module *pMod = (Module*)sqliteHashData(pThis); - pNext = sqliteHashNext(pThis); - if( azNames ){ - int ii; - for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){} - if( azNames[ii]!=0 ) continue; - } - createModule(db, pMod->zName, 0, 0, 0); - } - return SQLITE_OK; -} - -/* -** Decrement the reference count on a Module object. Destroy the -** module when the reference count reaches zero. -*/ -SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){ - assert( pMod->nRefModule>0 ); - pMod->nRefModule--; - if( pMod->nRefModule==0 ){ - if( pMod->xDestroy ){ - pMod->xDestroy(pMod->pAux); - } - assert( pMod->pEpoTab==0 ); - sqlite3DbFree(db, pMod); - } -} - /* ** Lock the virtual table so that it cannot be disconnected. ** Locks nest. Every lock should have a corresponding unlock. -** If an unlock is omitted, resources leaks will occur. +** If an unlock is omitted, resources leaks will occur. ** ** If a disconnect is attempted while a virtual table is locked, ** the disconnect is deferred until all locks have been removed. */ SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){ @@ -156682,17 +126077,17 @@ } /* ** pTab is a pointer to a Table structure representing a virtual-table. -** Return a pointer to the VTable object used by connection db to access +** Return a pointer to the VTable object used by connection db to access ** this virtual-table, if one has been created, or NULL otherwise. */ SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ VTable *pVtab; assert( IsVirtual(pTab) ); - for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); + for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); return pVtab; } /* ** Decrement the ref-count on a virtual table object. When the ref-count @@ -156701,54 +126096,49 @@ SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){ sqlite3 *db = pVTab->db; assert( db ); assert( pVTab->nRef>0 ); - assert( db->eOpenState==SQLITE_STATE_OPEN - || db->eOpenState==SQLITE_STATE_ZOMBIE ); + assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE ); pVTab->nRef--; if( pVTab->nRef==0 ){ sqlite3_vtab *p = pVTab->pVtab; if( p ){ p->pModule->xDisconnect(p); } - sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); sqlite3DbFree(db, pVTab); } } /* ** Table p is a virtual table. This function moves all elements in the -** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated -** database connections to be disconnected at the next opportunity. +** p->pVTable list to the sqlite3.pDisconnect lists of their associated +** database connections to be disconnected at the next opportunity. ** Except, if argument db is not NULL, then the entry associated with -** connection db is left in the p->u.vtab.p list. +** connection db is left in the p->pVTable list. */ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ VTable *pRet = 0; - VTable *pVTable; - - assert( IsVirtual(p) ); - pVTable = p->u.vtab.p; - p->u.vtab.p = 0; - - /* Assert that the mutex (if any) associated with the BtShared database - ** that contains table p is held by the caller. See header comments + VTable *pVTable = p->pVTable; + p->pVTable = 0; + + /* Assert that the mutex (if any) associated with the BtShared database + ** that contains table p is held by the caller. See header comments ** above function sqlite3VtabUnlockList() for an explanation of why ** this makes it safe to access the sqlite3.pDisconnect list of any - ** database connection that may have an entry in the p->u.vtab.p list. + ** database connection that may have an entry in the p->pVTable list. */ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); while( pVTable ){ sqlite3 *db2 = pVTable->db; VTable *pNext = pVTable->pNext; assert( db2 ); if( db2==db ){ pRet = pVTable; - p->u.vtab.p = pRet; + p->pVTable = pRet; pRet->pNext = 0; }else{ pVTable->pNext = db2->pDisconnect; db2->pDisconnect = pVTable; } @@ -156772,11 +126162,11 @@ assert( IsVirtual(p) ); assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3_mutex_held(db->mutex) ); - for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){ + for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){ if( (*ppVTab)->db==db ){ VTable *pVTab = *ppVTab; *ppVTab = pVTab->pNext; sqlite3VtabUnlock(pVTab); break; @@ -156787,11 +126177,11 @@ /* ** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. ** ** This function may only be called when the mutexes associated with all -** shared b-tree databases opened using connection db are held by the +** shared b-tree databases opened using connection db are held by the ** caller. This is done to protect the sqlite3.pDisconnect list. The ** sqlite3.pDisconnect list is accessed only as follows: ** ** 1) By this function. In this case, all BtShared mutexes and the mutex ** associated with the database handle itself must be held. @@ -156800,21 +126190,22 @@ ** the sqlite3.pDisconnect list. In this case either the BtShared mutex ** associated with the database the virtual table is stored in is held ** or, if the virtual table is stored in a non-sharable database, then ** the database handle mutex is held. ** -** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously +** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously ** by multiple threads. It is thread-safe. */ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){ VTable *p = db->pDisconnect; + db->pDisconnect = 0; assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3_mutex_held(db->mutex) ); if( p ){ - db->pDisconnect = 0; + sqlite3ExpirePreparedStatements(db); do { VTable *pNext = p->pNext; sqlite3VtabUnlock(p); p = pNext; }while( p ); @@ -156825,55 +126216,46 @@ ** Clear any and all virtual-table information from the Table record. ** This routine is called, for example, just before deleting the Table ** record. ** ** Since it is a virtual-table, the Table structure contains a pointer -** to the head of a linked list of VTable structures. Each VTable +** to the head of a linked list of VTable structures. Each VTable ** structure is associated with a single sqlite3* user of the schema. -** The reference count of the VTable structure associated with database -** connection db is decremented immediately (which may lead to the +** The reference count of the VTable structure associated with database +** connection db is decremented immediately (which may lead to the ** structure being xDisconnected and free). Any other VTable structures -** in the list are moved to the sqlite3.pDisconnect list of the associated +** in the list are moved to the sqlite3.pDisconnect list of the associated ** database connection. */ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ - assert( IsVirtual(p) ); - assert( db!=0 ); - if( db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); - if( p->u.vtab.azArg ){ + if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); + if( p->azModuleArg ){ int i; - for(i=0; iu.vtab.nArg; i++){ - if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]); + for(i=0; inModuleArg; i++){ + if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]); } - sqlite3DbFree(db, p->u.vtab.azArg); + sqlite3DbFree(db, p->azModuleArg); } } /* -** Add a new module argument to pTable->u.vtab.azArg[]. +** Add a new module argument to pTable->azModuleArg[]. ** The string is not copied - the pointer is stored. The ** string will be freed automatically when the table is ** deleted. */ -static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){ - sqlite3_int64 nBytes; +static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ + int nBytes = sizeof(char *)*(2+pTable->nModuleArg); char **azModuleArg; - sqlite3 *db = pParse->db; - - assert( IsVirtual(pTable) ); - nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg); - if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName); - } - azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes); + azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); if( azModuleArg==0 ){ sqlite3DbFree(db, zArg); }else{ - int i = pTable->u.vtab.nArg++; + int i = pTable->nModuleArg++; azModuleArg[i] = zArg; azModuleArg[i+1] = 0; - pTable->u.vtab.azArg = azModuleArg; + pTable->azModuleArg = azModuleArg; } } /* ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE @@ -156885,25 +126267,27 @@ Token *pName1, /* Name of new table, or database name */ Token *pName2, /* Name of new table or NULL */ Token *pModuleName, /* Name of the module for the virtual table */ int ifNotExists /* No error if the table already exists */ ){ + int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); pTable = pParse->pNewTable; if( pTable==0 ) return; assert( 0==pTable->pIndex ); - pTable->eTabType = TABTYP_VTAB; db = pParse->db; + iDb = sqlite3SchemaToIndex(db, pTable->pSchema); + assert( iDb>=0 ); - assert( pTable->u.vtab.nArg==0 ); - addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName)); - addModuleArgument(pParse, pTable, 0); - addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName)); + assert( pTable->nModuleArg==0 ); + addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); + addModuleArgument(db, pTable, 0); + addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) || (pParse->sNameToken.z==pName1->z && pName2->z==0) ); pParse->sNameToken.n = (int)( &pModuleName->z[pModuleName->n] - pParse->sNameToken.z @@ -156910,18 +126294,16 @@ ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. ** The first invocation, to obtain permission to INSERT a row into the - ** sqlite_schema table, has already been made by sqlite3StartTable(). + ** sqlite_master table, has already been made by sqlite3StartTable(). ** The second call, to obtain permission to create the table, is made now. */ - if( pTable->u.vtab.azArg ){ - int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); - assert( iDb>=0 ); /* The database the table is being created in */ - sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, - pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName); + if( pTable->azModuleArg ){ + sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, + pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } #endif } /* @@ -156932,11 +126314,11 @@ static void addArgumentToVtab(Parse *pParse){ if( pParse->sArg.z && pParse->pNewTable ){ const char *z = (const char*)pParse->sArg.z; int n = pParse->sArg.n; sqlite3 *db = pParse->db; - addModuleArgument(pParse, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); + addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); } } /* ** The parser calls this routine after the CREATE VIRTUAL TABLE statement @@ -156945,74 +126327,75 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pTab = pParse->pNewTable; /* The table being constructed */ sqlite3 *db = pParse->db; /* The database connection */ if( pTab==0 ) return; - assert( IsVirtual(pTab) ); addArgumentToVtab(pParse); pParse->sArg.z = 0; - if( pTab->u.vtab.nArg<1 ) return; - + if( pTab->nModuleArg<1 ) return; + /* If the CREATE VIRTUAL TABLE statement is being entered for the ** first time (in other words if the virtual table is actually being - ** created now instead of just being read out of sqlite_schema) then + ** created now instead of just being read out of sqlite_master) then ** do additional initialization work and store the statement text - ** in the sqlite_schema table. + ** in the sqlite_master table. */ if( !db->init.busy ){ char *zStmt; char *zWhere; int iDb; int iReg; Vdbe *v; - sqlite3MayAbort(pParse); - /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ if( pEnd ){ pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n; } zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken); - /* A slot for the record has already been allocated in the - ** schema table. We just need to update that slot with all - ** the information we've collected. + /* A slot for the record has already been allocated in the + ** SQLITE_MASTER table. We just need to update that slot with all + ** the information we've collected. ** ** The VM register number pParse->regRowid holds the rowid of an - ** entry in the sqlite_schema table that was created for this vtab + ** entry in the sqlite_master table tht was created for this vtab ** by sqlite3StartTable(). */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3NestedParse(pParse, - "UPDATE %Q." LEGACY_SCHEMA_TABLE " " + "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zDbSName, + db->aDb[iDb].zDbSName, MASTER_NAME, pTab->zName, pTab->zName, zStmt, pParse->regRowid ); + sqlite3DbFree(db, zStmt); v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp0(v, OP_Expire); - zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt); - sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0); - sqlite3DbFree(db, zStmt); + zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); + sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); iReg = ++pParse->nMem; sqlite3VdbeLoadString(v, iReg, pTab->zName); sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); - }else{ - /* If we are rereading the sqlite_schema table create the in-memory - ** record of the table. */ + } + + /* If we are rereading the sqlite_master table create the in-memory + ** record of the table. The xConnect() method is not called until + ** the first time the virtual table is used in an SQL statement. This + ** allows a schema that contains virtual tables to be loaded before + ** the required virtual table implementations are registered. */ + else { Table *pOld; Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; - assert( zName!=0 ); - sqlite3MarkAllShadowTablesOf(db, pTab); + assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); if( pOld ){ sqlite3OomFault(db); assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ return; @@ -157050,70 +126433,61 @@ ** Invoke a virtual table constructor (either xCreate or xConnect). The ** pointer to the function to invoke is passed as the fourth parameter ** to this procedure. */ static int vtabCallConstructor( - sqlite3 *db, + sqlite3 *db, Table *pTab, Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ VtabCtx sCtx; VTable *pVTable; int rc; - const char *const*azArg; - int nArg = pTab->u.vtab.nArg; + const char *const*azArg = (const char *const*)pTab->azModuleArg; + int nArg = pTab->nModuleArg; char *zErr = 0; char *zModuleName; int iDb; VtabCtx *pCtx; - assert( IsVirtual(pTab) ); - azArg = (const char *const*)pTab->u.vtab.azArg; - /* Check that the virtual-table is not already being initialized */ for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ if( pCtx->pTab==pTab ){ - *pzErr = sqlite3MPrintf(db, + *pzErr = sqlite3MPrintf(db, "vtable constructor called recursively: %s", pTab->zName ); return SQLITE_LOCKED; } } - zModuleName = sqlite3DbStrDup(db, pTab->zName); + zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM_BKPT; } - pVTable = sqlite3MallocZero(sizeof(VTable)); + pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); if( !pVTable ){ - sqlite3OomFault(db); sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM_BKPT; } pVTable->db = db; pVTable->pMod = pMod; - pVTable->eVtabRisk = SQLITE_VTABRISK_Normal; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName; + pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; sCtx.pPrior = db->pVtabCtx; sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; - pTab->nTabRef++; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - assert( pTab!=0 ); - assert( pTab->nTabRef>1 || rc!=SQLITE_OK ); - sqlite3DeleteTable(db, pTab); db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ @@ -157127,27 +126501,26 @@ }else if( ALWAYS(pVTable->pVtab) ){ /* Justification of ALWAYS(): A correct vtab constructor must allocate ** the sqlite3_vtab object if successful. */ memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; - pMod->nRefModule++; pVTable->nRef = 1; if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; - *pzErr = sqlite3MPrintf(db, zFormat, zModuleName); + *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; - u16 oooHidden = 0; + u8 oooHidden = 0; /* If everything went according to plan, link the new VTable structure - ** into the linked list headed by pTab->u.vtab.p. Then loop through the + ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from ** the type string. */ - pVTable->pNext = pTab->u.vtab.p; - pTab->u.vtab.p = pVTable; + pVTable->pNext = pTab->pVTable; + pTab->pVTable = pVTable; for(iCol=0; iColnCol; iCol++){ char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); int nType; int i = 0; @@ -157169,11 +126542,10 @@ if( zType[i]=='\0' && i>0 ){ assert(zType[i-1]==' '); zType[i-1] = '\0'; } pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN; - pTab->tabFlags |= TF_HasHidden; oooHidden = TF_OOOHidden; }else{ pTab->tabFlags |= oooHidden; } } @@ -157184,11 +126556,11 @@ return rc; } /* ** This function is invoked by the parser to call the xConnect() method -** of the virtual table pTab. If an error occurs, an error code is returned +** of the virtual table pTab. If an error occurs, an error code is returned ** and an error left in pParse. ** ** This call is a no-op if table pTab is not a virtual table. */ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ @@ -157196,29 +126568,27 @@ const char *zMod; Module *pMod; int rc; assert( pTab ); - assert( IsVirtual(pTab) ); - if( sqlite3GetVTable(db, pTab) ){ + if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){ return SQLITE_OK; } /* Locate the required virtual table module */ - zMod = pTab->u.vtab.azArg[0]; + zMod = pTab->azModuleArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); if( !pMod ){ - const char *zModule = pTab->u.vtab.azArg[0]; + const char *zModule = pTab->azModuleArg[0]; sqlite3ErrorMsg(pParse, "no such module: %s", zModule); rc = SQLITE_ERROR; }else{ char *zErr = 0; rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); - pParse->rc = rc; } sqlite3DbFree(db, zErr); } return rc; @@ -157231,12 +126601,11 @@ const int ARRAY_INCR = 5; /* Grow the sqlite3.aVTrans array if required */ if( (db->nVTrans%ARRAY_INCR)==0 ){ VTable **aVTrans; - sqlite3_int64 nBytes = sizeof(sqlite3_vtab*)* - ((sqlite3_int64)db->nVTrans + ARRAY_INCR); + int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); if( !aVTrans ){ return SQLITE_NOMEM_BKPT; } memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); @@ -157256,11 +126625,11 @@ sqlite3VtabLock(pVTab); } /* ** This function is invoked by the vdbe to call the xCreate method -** of the virtual table named zTab in database iDb. +** of the virtual table named zTab in database iDb. ** ** If an error occurs, *pzErr is set to point to an English language ** description of the error and an SQLITE_XXX error code is returned. ** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. */ @@ -157269,18 +126638,18 @@ Table *pTab; Module *pMod; const char *zMod; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); - assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p ); + assert( pTab && IsVirtual(pTab) && !pTab->pVTable ); /* Locate the required virtual table module */ - zMod = pTab->u.vtab.azArg[0]; + zMod = pTab->azModuleArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); - /* If the module has been registered and includes a Create method, - ** invoke it now. If the module has not been registered, return an + /* If the module has been registered and includes a Create method, + ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); rc = SQLITE_ERROR; @@ -157305,109 +126674,79 @@ ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; + Parse *pParse; int rc = SQLITE_OK; Table *pTab; - Parse sParse; - int initBusy; - int i; - const unsigned char *z; - static const u8 aKeyword[] = { TK_CREATE, TK_TABLE, 0 }; + char *zErr = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif - - /* Verify that the first two keywords in the CREATE TABLE statement - ** really are "CREATE" and "TABLE". If this is not the case, then - ** sqlite3_declare_vtab() is being misused. - */ - z = (const unsigned char*)zCreateTable; - for(i=0; aKeyword[i]; i++){ - int tokenType = 0; - do{ - z += sqlite3GetToken(z, &tokenType); - }while( tokenType==TK_SPACE || tokenType==TK_COMMENT ); - if( tokenType!=aKeyword[i] ){ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error"); - return SQLITE_ERROR; - } - } - sqlite3_mutex_enter(db->mutex); pCtx = db->pVtabCtx; if( !pCtx || pCtx->bDeclared ){ - sqlite3Error(db, SQLITE_MISUSE_BKPT); + sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } - pTab = pCtx->pTab; assert( IsVirtual(pTab) ); - sqlite3ParseObjectInit(&sParse, db); - sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; - sParse.disableTriggers = 1; - /* We should never be able to reach this point while loading the - ** schema. Nevertheless, defend against that (turn off db->init.busy) - ** in case a bug arises. */ - assert( db->init.busy==0 ); - initBusy = db->init.busy; - db->init.busy = 0; - sParse.nQueryLoop = 1; - if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) ){ - assert( sParse.pNewTable!=0 ); - assert( !db->mallocFailed ); - assert( IsOrdinaryTable(sParse.pNewTable) ); - assert( sParse.zErrMsg==0 ); - if( !pTab->aCol ){ - Table *pNew = sParse.pNewTable; - Index *pIdx; - pTab->aCol = pNew->aCol; - assert( IsOrdinaryTable(pNew) ); - sqlite3ExprListDelete(db, pNew->u.tab.pDfltList); - pTab->nNVCol = pTab->nCol = pNew->nCol; - pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); - pNew->nCol = 0; - pNew->aCol = 0; - assert( pTab->pIndex==0 ); - assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 ); - if( !HasRowid(pNew) - && pCtx->pVTable->pMod->pModule->xUpdate!=0 - && sqlite3PrimaryKeyIndex(pNew)->nKeyCol!=1 - ){ - /* WITHOUT ROWID virtual tables must either be read-only (xUpdate==0) - ** or else must have a single-column PRIMARY KEY */ - rc = SQLITE_ERROR; - } - pIdx = pNew->pIndex; - if( pIdx ){ - assert( pIdx->pNext==0 ); - pTab->pIndex = pIdx; - pNew->pIndex = 0; - pIdx->pTable = pTab; - } - } - pCtx->bDeclared = 1; - }else{ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, - (sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg); - sqlite3DbFree(db, sParse.zErrMsg); - rc = SQLITE_ERROR; - } - sParse.eParseMode = PARSE_MODE_NORMAL; - - if( sParse.pVdbe ){ - sqlite3VdbeFinalize(sParse.pVdbe); - } - sqlite3DeleteTable(db, sParse.pNewTable); - sqlite3ParseObjectReset(&sParse); - db->init.busy = initBusy; + pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); + if( pParse==0 ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + pParse->declareVtab = 1; + pParse->db = db; + pParse->nQueryLoop = 1; + + if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) + && pParse->pNewTable + && !db->mallocFailed + && !pParse->pNewTable->pSelect + && !IsVirtual(pParse->pNewTable) + ){ + if( !pTab->aCol ){ + Table *pNew = pParse->pNewTable; + Index *pIdx; + pTab->aCol = pNew->aCol; + pTab->nCol = pNew->nCol; + pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); + pNew->nCol = 0; + pNew->aCol = 0; + assert( pTab->pIndex==0 ); + if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){ + rc = SQLITE_ERROR; + } + pIdx = pNew->pIndex; + if( pIdx ){ + assert( pIdx->pNext==0 ); + pTab->pIndex = pIdx; + pNew->pIndex = 0; + pIdx->pTable = pTab; + } + } + pCtx->bDeclared = 1; + }else{ + sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); + sqlite3DbFree(db, zErr); + rc = SQLITE_ERROR; + } + pParse->declareVtab = 0; + + if( pParse->pVdbe ){ + sqlite3VdbeFinalize(pParse->pVdbe); + } + sqlite3DeleteTable(db, pParse->pNewTable); + sqlite3ParserReset(pParse); + sqlite3StackFree(db, pParse); + } assert( (rc&0xff)==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -157423,36 +126762,30 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ int rc = SQLITE_OK; Table *pTab; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); - if( ALWAYS(pTab!=0) - && ALWAYS(IsVirtual(pTab)) - && ALWAYS(pTab->u.vtab.p!=0) - ){ + if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ VTable *p; int (*xDestroy)(sqlite3_vtab *); - for(p=pTab->u.vtab.p; p; p=p->pNext){ + for(p=pTab->pVTable; p; p=p->pNext){ assert( p->pVtab ); if( p->pVtab->nRef>0 ){ return SQLITE_LOCKED; } } p = vtabDisconnectAll(db, pTab); xDestroy = p->pMod->pModule->xDestroy; - if( xDestroy==0 ) xDestroy = p->pMod->pModule->xDisconnect; - assert( xDestroy!=0 ); - pTab->nTabRef++; + assert( xDestroy!=0 ); /* Checked before the virtual table is created */ rc = xDestroy(p->pVtab); /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ if( rc==SQLITE_OK ){ - assert( pTab->u.vtab.p==p && p->pNext==0 ); + assert( pTab->pVTable==p && p->pNext==0 ); p->pVtab = 0; - pTab->u.vtab.p = 0; + pTab->pVTable = 0; sqlite3VtabUnlock(p); } - sqlite3DeleteTable(db, pTab); } return rc; } @@ -157460,11 +126793,11 @@ ** This function invokes either the xRollback or xCommit method ** of each of the virtual tables in the sqlite3.aVTrans array. The method ** called is identified by the second argument, "offset", which is ** the offset of the method to call in the sqlite3_module structure. ** -** The array is cleared after invoking the callbacks. +** The array is cleared after invoking the callbacks. */ static void callFinaliser(sqlite3 *db, int offset){ int i; if( db->aVTrans ){ VTable **aVTrans = db->aVTrans; @@ -157509,20 +126842,20 @@ db->aVTrans = aVTrans; return rc; } /* -** Invoke the xRollback method of all virtual tables in the +** Invoke the xRollback method of all virtual tables in the ** sqlite3.aVTrans array. Then clear the array itself. */ SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){ callFinaliser(db, offsetof(sqlite3_module,xRollback)); return SQLITE_OK; } /* -** Invoke the xCommit method of all virtual tables in the +** Invoke the xCommit method of all virtual tables in the ** sqlite3.aVTrans array. Then clear the array itself. */ SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){ callFinaliser(db, offsetof(sqlite3_module,xCommit)); return SQLITE_OK; @@ -157540,19 +126873,19 @@ int rc = SQLITE_OK; const sqlite3_module *pModule; /* Special case: If db->aVTrans is NULL and db->nVTrans is greater ** than zero, then this function is being called from within a - ** virtual module xSync() callback. It is illegal to write to + ** virtual module xSync() callback. It is illegal to write to ** virtual module tables in this case, so return SQLITE_LOCKED. */ if( sqlite3VtabInSync(db) ){ return SQLITE_LOCKED; } if( !pVTab ){ return SQLITE_OK; - } + } pModule = pVTab->pVtab->pModule; if( pModule->xBegin ){ int i; @@ -157561,11 +126894,11 @@ if( db->aVTrans[i]==pVTab ){ return SQLITE_OK; } } - /* Invoke the xBegin method. If successful, add the vtab to the + /* Invoke the xBegin method. If successful, add the vtab to the ** sqlite3.aVTrans[] array. */ rc = growVTrans(db); if( rc==SQLITE_OK ){ rc = pModule->xBegin(pVTab->pVtab); if( rc==SQLITE_OK ){ @@ -157585,15 +126918,15 @@ ** Invoke either the xSavepoint, xRollbackTo or xRelease method of all ** virtual tables that currently have an open transaction. Pass iSavepoint ** as the second argument to the virtual table method invoked. ** ** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is -** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is +** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is ** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with ** an open transaction is invoked. ** -** If any virtual table method returns an error code other than SQLITE_OK, +** If any virtual table method returns an error code other than SQLITE_OK, ** processing is abandoned and the error returned to the caller of this ** function immediately. If all calls to virtual table methods are successful, ** SQLITE_OK is returned. */ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ @@ -157606,11 +126939,10 @@ for(i=0; rc==SQLITE_OK && inVTrans; i++){ VTable *pVTab = db->aVTrans[i]; const sqlite3_module *pMod = pVTab->pMod->pModule; if( pVTab->pVtab && pMod->iVersion>=2 ){ int (*xMethod)(sqlite3_vtab *, int); - sqlite3VtabLock(pVTab); switch( op ){ case SAVEPOINT_BEGIN: xMethod = pMod->xSavepoint; pVTab->iSavepoint = iSavepoint+1; break; @@ -157620,16 +126952,12 @@ default: xMethod = pMod->xRelease; break; } if( xMethod && pVTab->iSavepoint>iSavepoint ){ - u64 savedFlags = (db->flags & SQLITE_Defensive); - db->flags &= ~(u64)SQLITE_Defensive; rc = xMethod(pVTab->pVtab, iSavepoint); - db->flags |= savedFlags; } - sqlite3VtabUnlock(pVTab); } } } return rc; } @@ -157641,11 +126969,11 @@ ** table implementation have an opportunity to overload the function. ** ** This routine is used to allow virtual table implementations to ** overload MATCH, LIKE, GLOB, and REGEXP operators. ** -** Return either the pDef argument (indicating no change) or a +** Return either the pDef argument (indicating no change) or a ** new FuncDef structure that is marked as ephemeral using the ** SQLITE_FUNC_EPHEM flag. */ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( sqlite3 *db, /* Database connection for reporting malloc problems */ @@ -157658,41 +126986,37 @@ sqlite3_module *pMod; void (*xSFunc)(sqlite3_context*,int,sqlite3_value**) = 0; void *pArg = 0; FuncDef *pNew; int rc = 0; + char *zLowerName; + unsigned char *z; + /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; - assert( ExprUseYTab(pExpr) ); - pTab = pExpr->y.pTab; - if( NEVER(pTab==0) ) return pDef; + pTab = pExpr->pTab; + if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction==0 ) return pDef; - + /* Call the xFindFunction method on the virtual table implementation - ** to see if the implementation wants to overload this function. - ** - ** Though undocumented, we have historically always invoked xFindFunction - ** with an all lower-case function name. Continue in this tradition to - ** avoid any chance of an incompatibility. + ** to see if the implementation wants to overload this function */ -#ifdef SQLITE_DEBUG - { - int i; - for(i=0; pDef->zName[i]; i++){ - unsigned char x = (unsigned char)pDef->zName[i]; - assert( x==sqlite3UpperToLower[x] ); - } - } -#endif - rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg); + zLowerName = sqlite3DbStrDup(db, pDef->zName); + if( zLowerName ){ + for(z=(unsigned char*)zLowerName; *z; z++){ + *z = sqlite3UpperToLower[*z]; + } + rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg); + sqlite3DbFree(db, zLowerName); + } if( rc==0 ){ return pDef; } /* Create a new ephemeral function definition for the overloaded @@ -157725,11 +127049,11 @@ assert( IsVirtual(pTab) ); for(i=0; inVtabLock; i++){ if( pTab==pToplevel->apVtabLock[i] ) return; } n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); - apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n); + apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); if( apVtabLock ){ pToplevel->apVtabLock = apVtabLock; pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; }else{ sqlite3OomFault(pToplevel->db); @@ -157737,17 +127061,16 @@ } /* ** Check to see if virtual table module pMod can be have an eponymous ** virtual table instance. If it can, create one if one does not already -** exist. Return non-zero if either the eponymous virtual table instance -** exists when this routine returns or if an attempt to create it failed -** and an error message was left in pParse. +** exist. Return non-zero if the eponymous virtual table instance exists +** when this routine returns, and return zero if it does not exist. ** ** An eponymous virtual table instance is one that is named after its ** module, and more importantly, does not require a CREATE VIRTUAL TABLE -** statement in order to come into existence. Eponymous virtual table +** statement in order to come into existance. Eponymous virtual table ** instances always exist. They cannot be DROP-ed. ** ** Any virtual table module for which xConnect and xCreate are the same ** method can have an eponymous virtual table instance. */ @@ -157766,23 +127089,22 @@ sqlite3DbFree(db, pTab); return 0; } pMod->pEpoTab = pTab; pTab->nTabRef = 1; - pTab->eTabType = TABTYP_VTAB; pTab->pSchema = db->aDb[0].pSchema; - assert( pTab->u.vtab.nArg==0 ); + assert( pTab->nModuleArg==0 ); pTab->iPKey = -1; - pTab->tabFlags |= TF_Eponymous; - addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); - addModuleArgument(pParse, pTab, 0); - addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); + addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); + addModuleArgument(db, pTab, 0); + addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); if( rc ){ sqlite3ErrorMsg(pParse, "%s", zErr); sqlite3DbFree(db, zErr); sqlite3VtabEponymousTableClear(db, pMod); + return 0; } return 1; } /* @@ -157791,11 +127113,11 @@ */ SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ Table *pTab = pMod->pEpoTab; if( pTab!=0 ){ /* Mark the table as Ephemeral prior to deleting it, so that the - ** sqlite3DeleteTable() routine will know that it is not stored in + ** sqlite3DeleteTable() routine will know that it is not stored in ** the schema. */ pTab->tabFlags |= TF_Ephemeral; sqlite3DeleteTable(db, pTab); pMod->pEpoTab = 0; } @@ -157807,12 +127129,12 @@ ** ** The results of this routine are undefined unless it is called from ** within an xUpdate method. */ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ - static const unsigned char aMap[] = { - SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE + static const unsigned char aMap[] = { + SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE }; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 ); @@ -157820,53 +127142,39 @@ assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 ); return (int)aMap[db->vtabOnConflict-1]; } /* -** Call from within the xCreate() or xConnect() methods to provide +** Call from within the xCreate() or xConnect() methods to provide ** the SQLite core with additional information about the behavior ** of the virtual table being implemented. */ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ va_list ap; int rc = SQLITE_OK; - VtabCtx *p; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); - p = db->pVtabCtx; - if( !p ){ - rc = SQLITE_MISUSE_BKPT; - }else{ - assert( p->pTab==0 || IsVirtual(p->pTab) ); - va_start(ap, op); - switch( op ){ - case SQLITE_VTAB_CONSTRAINT_SUPPORT: { + va_start(ap, op); + switch( op ){ + case SQLITE_VTAB_CONSTRAINT_SUPPORT: { + VtabCtx *p = db->pVtabCtx; + if( !p ){ + rc = SQLITE_MISUSE_BKPT; + }else{ + assert( p->pTab==0 || IsVirtual(p->pTab) ); p->pVTable->bConstraint = (u8)va_arg(ap, int); - break; - } - case SQLITE_VTAB_INNOCUOUS: { - p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low; - break; - } - case SQLITE_VTAB_DIRECTONLY: { - p->pVTable->eVtabRisk = SQLITE_VTABRISK_High; - break; - } - case SQLITE_VTAB_USES_ALL_SCHEMAS: { - p->pVTable->bAllSchemas = 1; - break; - } - default: { - rc = SQLITE_MISUSE_BKPT; - break; - } - } - va_end(ap); - } + } + break; + } + default: + rc = SQLITE_MISUSE_BKPT; + break; + } + va_end(ap); if( rc!=SQLITE_OK ) sqlite3Error(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -157911,13 +127219,24 @@ ** ** This file contains structure and macro definitions for the query ** planner logic in "where.c". These definitions are broken out into ** a separate source file for easier editing. */ -#ifndef SQLITE_WHEREINT_H -#define SQLITE_WHEREINT_H +/* +** Trace output macros +*/ +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +/***/ int sqlite3WhereTrace; +#endif +#if defined(SQLITE_DEBUG) \ + && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) +# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X +# define WHERETRACE_ENABLED 1 +#else +# define WHERETRACE(K,X) +#endif /* Forward references */ typedef struct WhereClause WhereClause; typedef struct WhereMaskSet WhereMaskSet; @@ -157929,32 +127248,10 @@ typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; -typedef struct WhereMemBlock WhereMemBlock; -typedef struct WhereRightJoin WhereRightJoin; - -/* -** This object is a header on a block of allocated memory that will be -** automatically freed when its WInfo object is destructed. -*/ -struct WhereMemBlock { - WhereMemBlock *pNext; /* Next block in the chain */ - u64 sz; /* Bytes of space */ -}; - -/* -** Extra information attached to a WhereLevel that is a RIGHT JOIN. -*/ -struct WhereRightJoin { - int iMatch; /* Cursor used to determine prior matched rows */ - int regBloom; /* Bloom filter for iRJMatch */ - int regReturn; /* Return register for the interior subroutine */ - int addrSubrtn; /* Starting address for the interior subroutine */ - int endSubrtn; /* The last opcode in the interior subroutine */ -}; /* ** This object contains information needed to implement a single nested ** loop in WHERE clause. ** @@ -157977,33 +127274,27 @@ int addrNxt; /* Jump here to start the next IN combination */ int addrSkip; /* Jump here for next iteration of skip-scan */ int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ - int regBignull; /* big-null flag reg. True if a NULL-scan is needed */ - int addrBignull; /* Jump here for next part of big-null scan */ #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif - int regFilter; /* Bloom filter */ - WhereRightJoin *pRJ; /* Extra information for RIGHT JOIN */ u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ - int p1, p2; /* Operands of the opcode used to end the loop */ + int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on pWLoop->wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ - int iBase; /* Base register of multi-key index record */ - int nPrefix; /* Number of prior entries in the key */ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ - Index *pCoveringIdx; /* Possible covering index for WHERE_MULTI_OR */ + Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; struct WhereLoop *pWLoop; /* The selected WhereLoop object */ Bitmask notReady; /* FROM entries not usable at this level */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS int addrVisit; /* Address at which row is visited */ @@ -158038,43 +127329,35 @@ union { struct { /* Information for internal btree tables */ u16 nEq; /* Number of equality constraints */ u16 nBtm; /* Size of BTM vector */ u16 nTop; /* Size of TOP vector */ - u16 nDistinctCol; /* Index columns used to sort for DISTINCT */ + u16 nIdxCol; /* Index column used for ORDER BY */ Index *pIndex; /* Index used, or NULL */ - ExprList *pOrderBy; /* ORDER BY clause if this is really a subquery */ } btree; struct { /* Information for virtual tables */ int idxNum; /* Index number */ - u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */ - u32 bOmitOffset : 1; /* True to let virtual table handle offset */ - u32 bIdxNumHex : 1; /* Show idxNum as hex in EXPLAIN QUERY PLAN */ + u8 needFree; /* True if sqlite3_free(idxStr) is needed */ i8 isOrdered; /* True if satisfies ORDER BY */ u16 omitMask; /* Terms that may be omitted */ char *idxStr; /* Index identifier string */ - u32 mHandleIn; /* Terms to handle as IN(...) instead of == */ } vtab; } u; u32 wsFlags; /* WHERE_* flags describing the plan */ u16 nLTerm; /* Number of entries in aLTerm[] */ u16 nSkip; /* Number of NULL aLTerm[] entries */ /**** whereLoopXfer() copies fields above ***********************/ # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) u16 nLSlot; /* Number of slots allocated for aLTerm[] */ -#ifdef WHERETRACE_ENABLED - LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not - ** initialized unless pWInfo->bStarUsed */ -#endif WhereTerm **aLTerm; /* WhereTerms used */ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */ }; /* This object holds the prerequisites and the cost of running a ** subquery on one operand of an OR operator in the WHERE clause. -** See WhereOrSet for additional information +** See WhereOrSet for additional information */ struct WhereOrCost { Bitmask prereq; /* Prerequisites */ LogEst rRun; /* Cost of running this subquery */ LogEst nOut; /* Number of outputs for this subquery */ @@ -158111,11 +127394,11 @@ struct WherePath { Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ LogEst nRow; /* Estimated number of rows generated by this path */ LogEst rCost; /* Total cost of this path */ - LogEst rUnsort; /* Total cost of this path ignoring sorting costs */ + LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */ i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */ WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */ }; /* @@ -158122,11 +127405,11 @@ ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by AND operators, ** usually, or sometimes subexpressions separated by OR. ** -** All WhereTerms are collected into a single WhereClause structure. +** All WhereTerms are collected into a single WhereClause structure. ** The following identity holds: ** ** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm ** ** When a term is of the form: @@ -158177,15 +127460,13 @@ u16 eOperator; /* A WO_xx value describing */ u8 nChild; /* Number of children that must disable us */ u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X " */ + int iField; /* Field in (?,?,?) IN (SELECT...) vector */ union { - struct { - int leftColumn; /* Column number of X in "X " */ - int iField; /* Field in (?,?,?) IN (SELECT...) vector */ - } x; /* Opcode other than OP_OR or OP_AND */ + int leftColumn; /* Column number of X in "X " */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ @@ -158192,30 +127473,27 @@ }; /* ** Allowed values of WhereTerm.wtFlags */ -#define TERM_DYNAMIC 0x0001 /* Need to call sqlite3ExprDelete(db, pExpr) */ -#define TERM_VIRTUAL 0x0002 /* Added by the optimizer. Do not code */ -#define TERM_CODED 0x0004 /* This term is already coded */ -#define TERM_COPIED 0x0008 /* Has a child */ -#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */ -#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */ -#define TERM_OK 0x0040 /* Used during OR-clause processing */ -#define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */ -#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */ -#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */ -#define TERM_LIKE 0x0400 /* The original LIKE operator */ -#define TERM_IS 0x0800 /* Term.pExpr is an IS operator */ +#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */ +#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */ +#define TERM_CODED 0x04 /* This term is already coded */ +#define TERM_COPIED 0x08 /* Has a child */ +#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */ +#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */ +#define TERM_OR_OK 0x40 /* Used during OR-clause processing */ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ +#else +# define TERM_VNULL 0x00 /* Disabled if not using stat3 */ +#endif +#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */ +#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ +#define TERM_LIKE 0x400 /* The original LIKE operator */ +#define TERM_IS 0x800 /* Term.pExpr is an IS operator */ #define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ -#define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */ -#ifdef SQLITE_ENABLE_STAT4 -# define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */ -#else -# define TERM_HIGHTRUTH 0 /* Only used with STAT4 */ -#endif -#define TERM_SLICE 0x8000 /* One slice of a row-value/vector comparison */ /* ** An instance of the WhereScan object is used as an iterator for locating ** terms in the WHERE clause that are useful to the query planner. */ @@ -158222,15 +127500,15 @@ struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ WhereClause *pWC; /* WhereClause currently being scanned */ const char *zCollName; /* Required collating sequence, if not NULL */ Expr *pIdxExpr; /* Search for this index expression */ - int k; /* Resume scanning at this->pWC->a[this->k] */ - u32 opMask; /* Acceptable operators */ char idxaff; /* Must match this affinity, if zCollName!=NULL */ - unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */ - unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */ + unsigned char nEquiv; /* Number of entries in aEquiv[] */ + unsigned char iEquiv; /* Next unused slot in aEquiv[] */ + u32 opMask; /* Acceptable operators */ + int k; /* Resume scanning at this->pWC->a[this->k] */ int aiCur[11]; /* Cursors in the equivalence class */ i16 aiColumn[11]; /* Corresponding column number in the eq-class */ }; /* @@ -158247,15 +127525,13 @@ */ struct WhereClause { WhereInfo *pWInfo; /* WHERE clause processing context */ WhereClause *pOuter; /* Outer conjunction */ u8 op; /* Split operator. TK_AND or TK_OR */ - u8 hasOr; /* True if any a[].eOperator is WO_OR */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ - int nBase; /* Number of terms through the last non-Virtual */ - WhereTerm *a; /* Each a[] describes a term of the WHERE clause */ + WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ #else WhereTerm aStatic[8]; /* Initial static space for a[] */ #endif @@ -158280,12 +127556,12 @@ /* ** An instance of the following structure keeps track of a mapping ** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. ** -** The VDBE cursor numbers are small integers contained in -** SrcItem.iCursor and Expr.iTable fields. For any given WHERE +** The VDBE cursor numbers are small integers contained in +** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE ** clause, the cursor numbers might not begin with 0 and they might ** contain gaps in the numbering sequence. But we want to make maximum ** use of the bits in our bitmasks. This structure provides a mapping ** from the sparse cursor numbers into consecutive integers beginning ** with 0. @@ -158308,53 +127584,35 @@ int bVarSelect; /* Used by sqlite3WhereExprUsage() */ int n; /* Number of assigned cursor values */ int ix[BMS]; /* Cursor assigned to each bit */ }; +/* +** Initialize a WhereMaskSet object +*/ +#define initMaskSet(P) (P)->n=0 + /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. */ struct WhereLoopBuilder { WhereInfo *pWInfo; /* Information about this WHERE */ WhereClause *pWC; /* WHERE clause terms */ + ExprList *pOrderBy; /* ORDER BY clause */ WhereLoop *pNew; /* Template WhereLoop */ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 UnpackedRecord *pRec; /* Probe for stat4 (if required) */ int nRecValid; /* Number of valid fields currently in pRec */ #endif - unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */ - unsigned char bldFlags2; /* Second set of SQLITE_BLDF_* flags */ - unsigned int iPlanLimit; /* Search limiter */ + unsigned int bldFlags; /* SQLITE_BLDF_* flags */ }; /* Allowed values for WhereLoopBuider.bldFlags */ -#define SQLITE_BLDF1_INDEXED 0x0001 /* An index is used */ -#define SQLITE_BLDF1_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ - -#define SQLITE_BLDF2_2NDPASS 0x0004 /* Second builder pass needed */ - -/* The WhereLoopBuilder.iPlanLimit is used to limit the number of -** index+constraint combinations the query planner will consider for a -** particular query. If this parameter is unlimited, then certain -** pathological queries can spend excess time in the sqlite3WhereBegin() -** routine. The limit is high enough that is should not impact real-world -** queries. -** -** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is -** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM -** clause is processed, so that every table in a join is guaranteed to be -** able to propose a some index+constraint combinations even if the initial -** baseline limit was exhausted by prior tables of the join. -*/ -#ifndef SQLITE_QUERY_PLANNER_LIMIT -# define SQLITE_QUERY_PLANNER_LIMIT 20000 -#endif -#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR -# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 -#endif +#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ +#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of @@ -158367,39 +127625,28 @@ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set of the query */ -#if WHERETRACE_ENABLED Expr *pWhere; /* The complete WHERE clause */ -#endif - Select *pSelect; /* The entire SELECT statement containing WHERE */ + LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ - LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ u8 nLevel; /* Number of nested loop */ i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ + u8 sorted; /* True if really sorted (not just grouped) */ u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ + u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ - unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */ - unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */ - unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */ - unsigned sorted :1; /* True if really sorted (not just grouped) */ - unsigned bStarDone :1; /* True if check for star-query is complete */ - unsigned bStarUsed :1; /* True if star-query heuristic is used */ - LogEst nRowOut; /* Estimated number of output rows */ -#ifdef WHERETRACE_ENABLED - LogEst rTotalCost; /* Total cost of the solution */ -#endif + u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */ int iTop; /* The very beginning of the WHERE loop */ - int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ - WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ + LogEst nRowOut; /* Estimated number of output rows */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; @@ -158409,48 +127656,32 @@ ** where.c: */ SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); #ifdef WHERETRACE_ENABLED SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC); -SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm); -SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC); #endif SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ); -SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte); -SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte); /* wherecode.c: */ #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -); -SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter( - const Parse *pParse, /* Parse context */ - const WhereInfo *pWInfo, /* WHERE clause */ - const WhereLevel *pLevel /* Bloom filter on this level */ -); -SQLITE_PRIVATE void sqlite3WhereAddExplainText( - Parse *pParse, /* Parse context */ - int addr, - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ + int iLevel, /* Value for "level" column of output */ + int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); #else -# define sqlite3WhereExplainOneScan(u,v,w,x) 0 -# define sqlite3WhereExplainBloomFilter(u,v,w) 0 -# define sqlite3WhereAddExplainText(u,v,w,x,y) +# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS SQLITE_PRIVATE void sqlite3WhereAddScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ @@ -158459,33 +127690,23 @@ ); #else # define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d) #endif SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( - Parse *pParse, /* Parsing context */ - Vdbe *v, /* Prepared statement under construction */ WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ - WhereLevel *pLevel, /* The current level pointer */ Bitmask notReady /* Which tables are currently available */ ); -SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( - WhereInfo *pWInfo, - int iLevel, - WhereLevel *pLevel -); /* whereexpr.c: */ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); -SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause*, Select*); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); -SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); +SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); @@ -158499,27 +127720,27 @@ ** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ ** WO_LT == SQLITE_INDEX_CONSTRAINT_LT ** WO_LE == SQLITE_INDEX_CONSTRAINT_LE ** WO_GT == SQLITE_INDEX_CONSTRAINT_GT ** WO_GE == SQLITE_INDEX_CONSTRAINT_GE +** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH */ #define WO_IN 0x0001 #define WO_EQ 0x0002 #define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) -#define WO_AUX 0x0040 /* Op useful to virtual tables only */ +#define WO_MATCH 0x0040 #define WO_IS 0x0080 #define WO_ISNULL 0x0100 #define WO_OR 0x0200 /* Two or more OR-connected terms */ #define WO_AND 0x0400 /* Two or more AND-connected terms */ #define WO_EQUIV 0x0800 /* Of the form A==B, both columns */ #define WO_NOOP 0x1000 /* This term does not restrict search space */ -#define WO_ROWVAL 0x2000 /* A row-value term */ -#define WO_ALL 0x3fff /* Mask of all possible WO_* values */ +#define WO_ALL 0x1fff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */ /* ** These are definitions of bits in the WhereLoop.wsFlags field. ** The particular combination of bits in each WhereLoop help to @@ -158542,22 +127763,10 @@ #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ -#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ -#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ -#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ -#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ -#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ -#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ -#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */ -#define WHERE_COROUTINE 0x02000000 /* Implemented by co-routine. - ** NB: False-negatives are possible */ -#define WHERE_EXPRIDX 0x04000000 /* Uses an index-on-expressions */ - -#endif /* !defined(SQLITE_WHEREINT_H) */ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN @@ -158567,11 +127776,11 @@ */ static const char *explainIndexColumnName(Index *pIdx, int i){ i = pIdx->aiColumn[i]; if( i==XN_EXPR ) return ""; if( i==XN_ROWID ) return "rowid"; - return pIdx->pTable->aCol[i].zCnName; + return pIdx->pTable->aCol[i].zName; } /* ** This routine is a helper for explainIndexRange() below ** @@ -158589,31 +127798,31 @@ const char *zOp /* Name of the operator */ ){ int i; assert( nTerm>=1 ); - if( bAnd ) sqlite3_str_append(pStr, " AND ", 5); - - if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); - for(i=0; i1 ) sqlite3_str_append(pStr, ")", 1); - - sqlite3_str_append(pStr, zOp, 1); - - if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); - for(i=0; i1 ) sqlite3_str_append(pStr, ")", 1); -} - -/* -** Argument pLevel describes a strategy for scanning table pTab. This + if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5); + + if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); + + sqlite3StrAccumAppend(pStr, zOp, 1); + + if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); + for(i=0; i1 ) sqlite3StrAccumAppend(pStr, ")", 1); +} + +/* +** Argument pLevel describes a strategy for scanning table pTab. This ** function appends text to pStr that describes the subset of table ** rows scanned by the strategy in the form of an SQL expression. ** ** For example, if the query: ** @@ -158629,15 +127838,15 @@ u16 nEq = pLoop->u.btree.nEq; u16 nSkip = pLoop->nSkip; int i, j; if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; - sqlite3_str_append(pStr, " (", 2); + sqlite3StrAccumAppend(pStr, " (", 2); for(i=0; i=nSkip ? "%s=?" : "ANY(%s)", z); + if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); + sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); } j = i; if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ explainAppendTerm(pStr, pIndex, pLoop->u.btree.nBtm, j, i, ">"); @@ -158644,272 +127853,150 @@ i = 1; } if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } - sqlite3_str_append(pStr, ")", 1); -} - -/* -** This function sets the P4 value of an existing OP_Explain opcode to -** text describing the loop in pLevel. If the OP_Explain opcode already has -** a P4 value, it is freed before it is overwritten. -*/ -SQLITE_PRIVATE void sqlite3WhereAddExplainText( - Parse *pParse, /* Parse context */ - int addr, /* Address of OP_Explain opcode */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -){ -#if !defined(SQLITE_DEBUG) - if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) -#endif - { - VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr); - - SrcItem *pItem = &pTabList->a[pLevel->iFrom]; - sqlite3 *db = pParse->db; /* Database handle */ - int isSearch; /* True for a SEARCH. False for SCAN. */ - WhereLoop *pLoop; /* The controlling WhereLoop object */ - u32 flags; /* Flags that describe this loop */ -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) - char *zMsg; /* Text to add to EQP output */ -#endif - StrAccum str; /* EQP output string */ - char zBuf[100]; /* Initial space for EQP output string */ - - if( db->mallocFailed ) return; - - pLoop = pLevel->pWLoop; - flags = pLoop->wsFlags; - - isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 - || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) - || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); - - sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem); - if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ - const char *zFmt = 0; - Index *pIdx; - - assert( pLoop->u.btree.pIndex!=0 ); - pIdx = pLoop->u.btree.pIndex; - assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); - if( !HasRowid(pItem->pSTab) && IsPrimaryKeyIndex(pIdx) ){ - if( isSearch ){ - zFmt = "PRIMARY KEY"; - } - }else if( flags & WHERE_PARTIALIDX ){ - zFmt = "AUTOMATIC PARTIAL COVERING INDEX"; - }else if( flags & WHERE_AUTO_INDEX ){ - zFmt = "AUTOMATIC COVERING INDEX"; - }else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){ - zFmt = "COVERING INDEX %s"; - }else{ - zFmt = "INDEX %s"; - } - if( zFmt ){ - sqlite3_str_append(&str, " USING ", 7); - sqlite3_str_appendf(&str, zFmt, pIdx->zName); - explainIndexRange(&str, pLoop); - } - }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ - char cRangeOp; -#if 0 /* Better output, but breaks many tests */ - const Table *pTab = pItem->pTab; - const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName: - "rowid"; -#else - const char *zRowid = "rowid"; -#endif - sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid); - if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ - cRangeOp = '='; - }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ - sqlite3_str_appendf(&str, ">? AND %s", zRowid); - cRangeOp = '<'; - }else if( flags&WHERE_BTM_LIMIT ){ - cRangeOp = '>'; - }else{ - assert( flags&WHERE_TOP_LIMIT); - cRangeOp = '<'; - } - sqlite3_str_appendf(&str, "%c?)", cRangeOp); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ - sqlite3_str_appendall(&str, " VIRTUAL TABLE INDEX "); - sqlite3_str_appendf(&str, - pLoop->u.vtab.bIdxNumHex ? "0x%x:%s" : "%d:%s", - pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); - } -#endif - if( pItem->fg.jointype & JT_LEFT ){ - sqlite3_str_appendf(&str, " LEFT-JOIN"); - } -#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS - if( pLoop->nOut>=10 ){ - sqlite3_str_appendf(&str, " (~%llu rows)", - sqlite3LogEstToInt(pLoop->nOut)); - }else{ - sqlite3_str_append(&str, " (~1 row)", 9); - } -#endif -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN) - zMsg = sqlite3StrAccumFinish(&str); - sqlite3ExplainBreakpoint("",zMsg); -#endif - - assert( pOp->opcode==OP_Explain ); - assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 ); - sqlite3DbFree(db, pOp->p4.z); - pOp->p4type = P4_DYNAMIC; - pOp->p4.z = sqlite3StrAccumFinish(&str); - } -} - + sqlite3StrAccumAppend(pStr, ")", 1); +} /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN -** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG -** was defined at compile-time. If it is not a no-op, a single OP_Explain -** opcode is added to the output to describe the table scan strategy in pLevel. +** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was +** defined at compile-time. If it is not a no-op, a single OP_Explain opcode +** is added to the output to describe the table scan strategy in pLevel. ** ** If an OP_Explain opcode is added to the VM, its address is returned. ** Otherwise, if no OP_Explain is coded, zero is returned. */ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ + int iLevel, /* Value for "level" column of output */ + int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ){ int ret = 0; -#if !defined(SQLITE_DEBUG) - if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) +#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) + if( pParse->explain==2 ) #endif { - if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - ){ - Vdbe *v = pParse->pVdbe; - int addr = sqlite3VdbeCurrentAddr(v); - ret = sqlite3VdbeAddOp3( - v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun - ); - sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags); - } - } - return ret; -} - -/* -** Add a single OP_Explain opcode that describes a Bloom filter. -** -** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or -** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not -** required and this routine is a no-op. -** -** If an OP_Explain opcode is added to the VM, its address is returned. -** Otherwise, if no OP_Explain is coded, zero is returned. -*/ -SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter( - const Parse *pParse, /* Parse context */ - const WhereInfo *pWInfo, /* WHERE clause */ - const WhereLevel *pLevel /* Bloom filter on this level */ -){ - int ret = 0; - SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom]; - Vdbe *v = pParse->pVdbe; /* VM being constructed */ - sqlite3 *db = pParse->db; /* Database handle */ - char *zMsg; /* Text to add to EQP output */ - int i; /* Loop counter */ - WhereLoop *pLoop; /* The where loop */ - StrAccum str; /* EQP output string */ - char zBuf[100]; /* Initial space for EQP output string */ - - sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem); - pLoop = pLevel->pWLoop; - if( pLoop->wsFlags & WHERE_IPK ){ - const Table *pTab = pItem->pSTab; - if( pTab->iPKey>=0 ){ - sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName); - }else{ - sqlite3_str_appendf(&str, "rowid=?"); - } - }else{ - for(i=pLoop->nSkip; iu.btree.nEq; i++){ - const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i); - if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); - sqlite3_str_appendf(&str, "%s=?", z); - } - } - sqlite3_str_append(&str, ")", 1); - zMsg = sqlite3StrAccumFinish(&str); - ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), - pParse->addrExplain, 0, zMsg,P4_DYNAMIC); - - sqlite3VdbeScanStatus(v, sqlite3VdbeCurrentAddr(v)-1, 0, 0, 0, 0); + struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ + int iId = pParse->iSelectId; /* Select id (left-most output column) */ + int isSearch; /* True for a SEARCH. False for SCAN. */ + WhereLoop *pLoop; /* The controlling WhereLoop object */ + u32 flags; /* Flags that describe this loop */ + char *zMsg; /* Text to add to EQP output */ + StrAccum str; /* EQP output string */ + char zBuf[100]; /* Initial space for EQP output string */ + + pLoop = pLevel->pWLoop; + flags = pLoop->wsFlags; + if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0; + + isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 + || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) + || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); + + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); + sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); + if( pItem->pSelect ){ + sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); + }else{ + sqlite3XPrintf(&str, " TABLE %s", pItem->zName); + } + + if( pItem->zAlias ){ + sqlite3XPrintf(&str, " AS %s", pItem->zAlias); + } + if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ + const char *zFmt = 0; + Index *pIdx; + + assert( pLoop->u.btree.pIndex!=0 ); + pIdx = pLoop->u.btree.pIndex; + assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); + if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){ + if( isSearch ){ + zFmt = "PRIMARY KEY"; + } + }else if( flags & WHERE_PARTIALIDX ){ + zFmt = "AUTOMATIC PARTIAL COVERING INDEX"; + }else if( flags & WHERE_AUTO_INDEX ){ + zFmt = "AUTOMATIC COVERING INDEX"; + }else if( flags & WHERE_IDX_ONLY ){ + zFmt = "COVERING INDEX %s"; + }else{ + zFmt = "INDEX %s"; + } + if( zFmt ){ + sqlite3StrAccumAppend(&str, " USING ", 7); + sqlite3XPrintf(&str, zFmt, pIdx->zName); + explainIndexRange(&str, pLoop); + } + }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ + const char *zRangeOp; + if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ + zRangeOp = "="; + }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ + zRangeOp = ">? AND rowid<"; + }else if( flags&WHERE_BTM_LIMIT ){ + zRangeOp = ">"; + }else{ + assert( flags&WHERE_TOP_LIMIT); + zRangeOp = "<"; + } + sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ + sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", + pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); + } +#endif +#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS + if( pLoop->nOut>=10 ){ + sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); + }else{ + sqlite3StrAccumAppend(&str, " (~1 row)", 9); + } +#endif + zMsg = sqlite3StrAccumFinish(&str); + ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); + } return ret; } #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Configure the VM passed as the first argument with an -** sqlite3_stmt_scanstatus() entry corresponding to the scan used to -** implement level pLvl. Argument pSrclist is a pointer to the FROM +** sqlite3_stmt_scanstatus() entry corresponding to the scan used to +** implement level pLvl. Argument pSrclist is a pointer to the FROM ** clause that the scan reads data from. ** -** If argument addrExplain is not 0, it must be the address of an +** If argument addrExplain is not 0, it must be the address of an ** OP_Explain instruction that describes the same loop. */ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ ){ - if( IS_STMT_SCANSTATUS( sqlite3VdbeDb(v) ) ){ - const char *zObj = 0; - WhereLoop *pLoop = pLvl->pWLoop; - int wsFlags = pLoop->wsFlags; - int viaCoroutine = 0; - - if( (wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ - zObj = pLoop->u.btree.pIndex->zName; - }else{ - zObj = pSrclist->a[pLvl->iFrom].zName; - viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine; - } - sqlite3VdbeScanStatus( - v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj - ); - - if( viaCoroutine==0 ){ - if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){ - sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur); - } - if( wsFlags & WHERE_INDEXED ){ - sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur); - } - }else{ - int addr; - VdbeOp *pOp; - assert( pSrclist->a[pLvl->iFrom].fg.isSubquery ); - addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub; - pOp = sqlite3VdbeGetOp(v, addr-1); - assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine ); - assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr ); - sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1); - } - } + const char *zObj = 0; + WhereLoop *pLoop = pLvl->pWLoop; + if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ + zObj = pLoop->u.btree.pIndex->zName; + }else{ + zObj = pSrclist->a[pLvl->iFrom].zName; + } + sqlite3VdbeScanStatus( + v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj + ); } #endif /* @@ -158943,11 +128030,11 @@ ** \___________/ \______/ \_____/ ** parent child1 child2 ** ** Only the parent term was in the original WHERE clause. The child1 ** and child2 terms were added by the LIKE optimization. If both of -** the virtual child terms are valid, then testing of the parent can be +** the virtual child terms are valid, then testing of the parent can be ** skipped. ** ** Usually the parent term is marked as TERM_CODED. But if the parent ** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead. ** The TERM_LIKECOND marking indicates that the term should be coded inside @@ -158954,42 +128041,35 @@ ** a conditional such that is only evaluated on the second pass of a ** LIKE-optimization loop, when scanning BLOBs instead of strings. */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ int nLoop = 0; - assert( pTerm!=0 ); - while( (pTerm->wtFlags & TERM_CODED)==0 - && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_OuterON)) + while( ALWAYS(pTerm!=0) + && (pTerm->wtFlags & TERM_CODED)==0 + && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 ){ if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){ pTerm->wtFlags |= TERM_LIKECOND; }else{ pTerm->wtFlags |= TERM_CODED; } -#ifdef WHERETRACE_ENABLED - if( (sqlite3WhereTrace & 0x4001)==0x4001 ){ - sqlite3DebugPrintf("DISABLE-"); - sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a))); - } -#endif if( pTerm->iParent<0 ) break; pTerm = &pTerm->pWC->a[pTerm->iParent]; - assert( pTerm!=0 ); pTerm->nChild--; if( pTerm->nChild!=0 ) break; nLoop++; } } /* ** Code an OP_Affinity opcode to apply the column affinity string zAff -** to the n registers starting at base. +** to the n registers starting at base. ** -** As an optimization, SQLITE_AFF_BLOB and SQLITE_AFF_NONE entries (which -** are no-ops) at the beginning and end of zAff are ignored. If all entries -** in zAff are SQLITE_AFF_BLOB or SQLITE_AFF_NONE, then no code gets generated. +** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the +** beginning and end of zAff are ignored. If all entries in zAff are +** SQLITE_AFF_BLOB, then no code gets generated. ** ** This routine makes its own copy of zAff so that the caller is free ** to modify zAff after this routine returns. */ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ @@ -158998,31 +128078,31 @@ assert( pParse->db->mallocFailed ); return; } assert( v!=0 ); - /* Adjust base and n to skip over SQLITE_AFF_BLOB and SQLITE_AFF_NONE - ** entries at the beginning and end of the affinity string. + /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning + ** and end of the affinity string. */ - assert( SQLITE_AFF_NONE0 && zAff[0]<=SQLITE_AFF_BLOB ){ + while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){ n--; base++; zAff++; } - while( n>1 && zAff[n-1]<=SQLITE_AFF_BLOB ){ + while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){ n--; } /* Code the OP_Affinity opcode if there is anything left to do. */ if( n>0 ){ sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); + sqlite3ExprCacheAffinityChange(pParse, base, n); } } /* -** Expression pRight, which is the RHS of a comparison operation, is +** Expression pRight, which is the RHS of a comparison operation, is ** either a vector of n elements or, if n==1, a scalar expression. ** Before the comparison operation, affinity zAff is to be applied ** to the pRight values. This function modifies characters within the ** affinity string to SQLITE_AFF_BLOB if either: ** @@ -159042,299 +128122,14 @@ ){ zAff[i] = SQLITE_AFF_BLOB; } } } - -/* -** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because -** columns might have been rearranged in the result set. This routine -** fixes them up. -** -** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values -** contain the *old* locations of each expression. This is a temporary -** use of u.x.iOrderByCol, not its intended use. The caller must reset -** u.x.iOrderByCol back to zero for all entries in pEList before the -** caller returns. -** -** This routine changes pOrderBy->a[].u.x.iOrderByCol values from -** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based -** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero. -*/ -static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){ - int i, j; - if( pOrderBy==0 ) return; - for(i=0; inExpr; i++){ - int t = pOrderBy->a[i].u.x.iOrderByCol; - if( t==0 ) continue; - for(j=0; jnExpr; j++){ - if( pEList->a[j].u.x.iOrderByCol==t ){ - pOrderBy->a[i].u.x.iOrderByCol = j+1; - break; - } - } - if( j>=pEList->nExpr ){ - pOrderBy->a[i].u.x.iOrderByCol = 0; - } - } -} - - -/* -** pX is an expression of the form: (vector) IN (SELECT ...) -** In other words, it is a vector IN operator with a SELECT clause on the -** LHS. But not all terms in the vector are indexable and the terms might -** not be in the correct order for indexing. -** -** This routine makes a copy of the input pX expression and then adjusts -** the vector on the LHS with corresponding changes to the SELECT so that -** the vector contains only index terms and those terms are in the correct -** order. The modified IN expression is returned. The caller is responsible -** for deleting the returned expression. -** -** Example: -** -** CREATE TABLE t1(a,b,c,d,e,f); -** CREATE INDEX t1x1 ON t1(e,c); -** SELECT * FROM t1 WHERE (a,b,c,d,e) IN (SELECT v,w,x,y,z FROM t2) -** \_______________________________________/ -** The pX expression -** -** Since only columns e and c can be used with the index, in that order, -** the modified IN expression that is returned will be: -** -** (e,c) IN (SELECT z,x FROM t2) -** -** The reduced pX is different from the original (obviously) and thus is -** only used for indexing, to improve performance. The original unaltered -** IN expression must also be run on each output row for correctness. -*/ -static Expr *removeUnindexableInClauseTerms( - Parse *pParse, /* The parsing context */ - int iEq, /* Look at loop terms starting here */ - WhereLoop *pLoop, /* The current loop */ - Expr *pX /* The IN expression to be reduced */ -){ - sqlite3 *db = pParse->db; - Select *pSelect; /* Pointer to the SELECT on the RHS */ - Expr *pNew; - pNew = sqlite3ExprDup(db, pX, 0); - if( db->mallocFailed==0 ){ - for(pSelect=pNew->x.pSelect; pSelect; pSelect=pSelect->pPrior){ - ExprList *pOrigRhs; /* Original unmodified RHS */ - ExprList *pOrigLhs = 0; /* Original unmodified LHS */ - ExprList *pRhs = 0; /* New RHS after modifications */ - ExprList *pLhs = 0; /* New LHS after mods */ - int i; /* Loop counter */ - - assert( ExprUseXSelect(pNew) ); - pOrigRhs = pSelect->pEList; - assert( pNew->pLeft!=0 ); - assert( ExprUseXList(pNew->pLeft) ); - if( pSelect==pNew->x.pSelect ){ - pOrigLhs = pNew->pLeft->x.pList; - } - for(i=iEq; inLTerm; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - int iField; - assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 ); - iField = pLoop->aLTerm[i]->u.x.iField - 1; - if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */ - pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); - pOrigRhs->a[iField].pExpr = 0; - if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1; - if( pOrigLhs ){ - assert( pOrigLhs->a[iField].pExpr!=0 ); - pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr); - pOrigLhs->a[iField].pExpr = 0; - } - } - } - sqlite3ExprListDelete(db, pOrigRhs); - if( pOrigLhs ){ - sqlite3ExprListDelete(db, pOrigLhs); - pNew->pLeft->x.pList = pLhs; - } - pSelect->pEList = pRhs; - pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */ - if( pLhs && pLhs->nExpr==1 ){ - /* Take care here not to generate a TK_VECTOR containing only a - ** single value. Since the parser never creates such a vector, some - ** of the subroutines do not handle this case. */ - Expr *p = pLhs->a[0].pExpr; - pLhs->a[0].pExpr = 0; - sqlite3ExprDelete(db, pNew->pLeft); - pNew->pLeft = p; - } - - /* If either the ORDER BY clause or the GROUP BY clause contains - ** references to result-set columns, those references might now be - ** obsolete. So fix them up. - */ - assert( pRhs!=0 || db->mallocFailed ); - if( pRhs ){ - adjustOrderByCol(pSelect->pOrderBy, pRhs); - adjustOrderByCol(pSelect->pGroupBy, pRhs); - for(i=0; inExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0; - } - -#if 0 - printf("For indexing, change the IN expr:\n"); - sqlite3TreeViewExpr(0, pX, 0); - printf("Into:\n"); - sqlite3TreeViewExpr(0, pNew, 0); -#endif - } - } - return pNew; -} - - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code for a single X IN (....) term of the WHERE clause. -** -** This is a special-case of codeEqualityTerm() that works for IN operators -** only. It is broken out into a subroutine because this case is -** uncommon and by splitting it off into a subroutine, the common case -** runs faster. -** -** The current value for the constraint is left in register iTarget. -** This routine sets up a loop that will iterate over all values of X. -*/ -static SQLITE_NOINLINE void codeINTerm( - Parse *pParse, /* The parsing context */ - WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - WhereLevel *pLevel, /* The level of the FROM clause we are working on */ - int iEq, /* Index of the equality term within this level */ - int bRev, /* True for reverse-order IN operations */ - int iTarget /* Attempt to leave results in this register */ -){ - Expr *pX = pTerm->pExpr; - int eType = IN_INDEX_NOOP; - int iTab; - struct InLoop *pIn; - WhereLoop *pLoop = pLevel->pWLoop; - Vdbe *v = pParse->pVdbe; - int i; - int nEq = 0; - int *aiMap = 0; - - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 - && pLoop->u.btree.pIndex!=0 - && pLoop->u.btree.pIndex->aSortOrder[iEq] - ){ - testcase( iEq==0 ); - testcase( bRev ); - bRev = !bRev; - } - assert( pX->op==TK_IN ); - - for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){ - disableTerm(pLevel, pTerm); - return; - } - } - for(i=iEq;inLTerm; i++){ - assert( pLoop->aLTerm[i]!=0 ); - if( pLoop->aLTerm[i]->pExpr==pX ) nEq++; - } - - iTab = 0; - if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){ - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab); - }else{ - Expr *pExpr = pTerm->pExpr; - if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){ - sqlite3 *db = pParse->db; - pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); - if( !db->mallocFailed ){ - aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab); - pExpr->iTable = iTab; - } - sqlite3ExprDelete(db, pX); - }else{ - int n = sqlite3ExprVectorSize(pX->pLeft); - aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n)); - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab); - } - pX = pExpr; - } - - if( eType==IN_INDEX_INDEX_DESC ){ - testcase( bRev ); - bRev = !bRev; - } - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); - VdbeCoverageIf(v, bRev); - VdbeCoverageIf(v, !bRev); - - assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); - pLoop->wsFlags |= WHERE_IN_ABLE; - if( pLevel->u.in.nIn==0 ){ - pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); - } - if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){ - pLoop->wsFlags |= WHERE_IN_EARLYOUT; - } - - i = pLevel->u.in.nIn; - pLevel->u.in.nIn += nEq; - pLevel->u.in.aInLoop = - sqlite3WhereRealloc(pTerm->pWC->pWInfo, - pLevel->u.in.aInLoop, - sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); - pIn = pLevel->u.in.aInLoop; - if( pIn ){ - int iMap = 0; /* Index in aiMap[] */ - pIn += i; - for(i=iEq;inLTerm; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - int iOut = iTarget + i - iEq; - if( eType==IN_INDEX_ROWID ){ - pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut); - }else{ - int iCol = aiMap ? aiMap[iMap++] : 0; - pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut); - } - sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); - if( i==iEq ){ - pIn->iCur = iTab; - pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; - if( iEq>0 ){ - pIn->iBase = iTarget - i; - pIn->nPrefix = i; - }else{ - pIn->nPrefix = 0; - } - }else{ - pIn->eEndLoopOp = OP_Noop; - } - pIn++; - } - } - testcase( iEq>0 - && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 - && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ); - if( iEq>0 - && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0 - ){ - sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq); - } - }else{ - pLevel->u.in.nIn = 0; - } - sqlite3DbFree(pParse->db, aiMap); -} -#endif - /* ** Generate code for a single equality term of the WHERE clause. An equality -** term can be either X=expr or X IN (...). pTerm is the term to be +** term can be either X=expr or X IN (...). pTerm is the term to be ** coded. ** ** The current value for the constraint is left in a register, the index ** of which is returned. An attempt is made store the result in iTarget but ** this is only guaranteed for TK_ISNULL and TK_IN constraints. If the @@ -159352,42 +128147,163 @@ int iEq, /* Index of the equality term within this level */ int bRev, /* True for reverse-order IN operations */ int iTarget /* Attempt to leave results in this register */ ){ Expr *pX = pTerm->pExpr; + Vdbe *v = pParse->pVdbe; int iReg; /* Register holding results */ assert( pLevel->pWLoop->aLTerm[iEq]==pTerm ); assert( iTarget>0 ); if( pX->op==TK_EQ || pX->op==TK_IS ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ iReg = iTarget; - sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg); + sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE_OMIT_SUBQUERY }else{ + int eType = IN_INDEX_NOOP; + int iTab; + struct InLoop *pIn; + WhereLoop *pLoop = pLevel->pWLoop; + int i; + int nEq = 0; + int *aiMap = 0; + + if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 + && pLoop->u.btree.pIndex!=0 + && pLoop->u.btree.pIndex->aSortOrder[iEq] + ){ + testcase( iEq==0 ); + testcase( bRev ); + bRev = !bRev; + } assert( pX->op==TK_IN ); iReg = iTarget; - codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget); + + for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){ + disableTerm(pLevel, pTerm); + return iTarget; + } + } + for(i=iEq;inLTerm; i++){ + if( ALWAYS(pLoop->aLTerm[i]) && pLoop->aLTerm[i]->pExpr==pX ) nEq++; + } + + if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); + }else{ + Select *pSelect = pX->x.pSelect; + sqlite3 *db = pParse->db; + u16 savedDbOptFlags = db->dbOptFlags; + ExprList *pOrigRhs = pSelect->pEList; + ExprList *pOrigLhs = pX->pLeft->x.pList; + ExprList *pRhs = 0; /* New Select.pEList for RHS */ + ExprList *pLhs = 0; /* New pX->pLeft vector */ + + for(i=iEq;inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iField = pLoop->aLTerm[i]->iField - 1; + Expr *pNewRhs = sqlite3ExprDup(db, pOrigRhs->a[iField].pExpr, 0); + Expr *pNewLhs = sqlite3ExprDup(db, pOrigLhs->a[iField].pExpr, 0); + + pRhs = sqlite3ExprListAppend(pParse, pRhs, pNewRhs); + pLhs = sqlite3ExprListAppend(pParse, pLhs, pNewLhs); + } + } + if( !db->mallocFailed ){ + Expr *pLeft = pX->pLeft; + + if( pSelect->pOrderBy ){ + /* If the SELECT statement has an ORDER BY clause, zero the + ** iOrderByCol variables. These are set to non-zero when an + ** ORDER BY term exactly matches one of the terms of the + ** result-set. Since the result-set of the SELECT statement may + ** have been modified or reordered, these variables are no longer + ** set correctly. Since setting them is just an optimization, + ** it's easiest just to zero them here. */ + ExprList *pOrderBy = pSelect->pOrderBy; + for(i=0; inExpr; i++){ + pOrderBy->a[i].u.x.iOrderByCol = 0; + } + } + + /* Take care here not to generate a TK_VECTOR containing only a + ** single value. Since the parser never creates such a vector, some + ** of the subroutines do not handle this case. */ + if( pLhs->nExpr==1 ){ + pX->pLeft = pLhs->a[0].pExpr; + }else{ + pLeft->x.pList = pLhs; + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); + testcase( aiMap==0 ); + } + pSelect->pEList = pRhs; + db->dbOptFlags |= SQLITE_QueryFlattener; + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); + db->dbOptFlags = savedDbOptFlags; + testcase( aiMap!=0 && aiMap[0]!=0 ); + pSelect->pEList = pOrigRhs; + pLeft->x.pList = pOrigLhs; + pX->pLeft = pLeft; + } + sqlite3ExprListDelete(pParse->db, pLhs); + sqlite3ExprListDelete(pParse->db, pRhs); + } + + if( eType==IN_INDEX_INDEX_DESC ){ + testcase( bRev ); + bRev = !bRev; + } + iTab = pX->iTable; + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); + VdbeCoverageIf(v, bRev); + VdbeCoverageIf(v, !bRev); + assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); + + pLoop->wsFlags |= WHERE_IN_ABLE; + if( pLevel->u.in.nIn==0 ){ + pLevel->addrNxt = sqlite3VdbeMakeLabel(v); + } + + i = pLevel->u.in.nIn; + pLevel->u.in.nIn += nEq; + pLevel->u.in.aInLoop = + sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, + sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); + pIn = pLevel->u.in.aInLoop; + if( pIn ){ + int iMap = 0; /* Index in aiMap[] */ + pIn += i; + for(i=iEq;inLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iOut = iReg + i - iEq; + if( eType==IN_INDEX_ROWID ){ + testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */ + pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut); + }else{ + int iCol = aiMap ? aiMap[iMap++] : 0; + pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut); + } + sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); + if( i==iEq ){ + pIn->iCur = iTab; + pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; + }else{ + pIn->eEndLoopOp = OP_Noop; + } + pIn++; + } + } + }else{ + pLevel->u.in.nIn = 0; + } + sqlite3DbFree(pParse->db, aiMap); #endif } - - /* As an optimization, try to disable the WHERE clause term that is - ** driving the index as it will always be true. The correct answer is - ** obtained regardless, but we might get the answer with fewer CPU cycles - ** by omitting the term. - ** - ** But do not disable the term unless we are certain that the term is - ** not a transitive constraint. For an example of where that does not - ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04) - */ - if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0 - || (pTerm->eOperator & WO_EQUIV)==0 - ){ - disableTerm(pLevel, pTerm); - } - + disableTerm(pLevel, pTerm); return iReg; } /* ** Generate code that will evaluate all == and IN constraints for an @@ -159394,11 +128310,11 @@ ** index scan. ** ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c). ** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10 ** The index has as many as three equality constraints, but in this -** example, the third "c" value is an inequality. So only two +** example, the third "c" value is an inequality. So only two ** constraints are coded. This routine will generate code to evaluate ** a==5 and b IN (1,2,3). The current values for a and b will be stored ** in consecutive registers and the index of the first register is returned. ** ** In the example above nEq==2. But this subroutine works for any value @@ -159461,25 +128377,23 @@ assert( pIdx!=0 ); /* Figure out how many memory cells we will need then allocate them. */ regBase = pParse->nMem + 1; - nReg = nEq + nExtraReg; + nReg = pLoop->u.btree.nEq + nExtraReg; pParse->nMem += nReg; zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); assert( zAff!=0 || pParse->db->mallocFailed ); if( nSkip ){ int iIdxCur = pLevel->iIdxCur; - sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1); sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); j = sqlite3VdbeAddOp0(v, OP_Goto); - assert( pLevel->addrSkip==0 ); pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), iIdxCur, 0, regBase, nSkip); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); sqlite3VdbeJumpHere(v, j); @@ -159486,48 +128400,47 @@ for(j=0; jaiColumn[j]==XN_EXPR ); VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); } - } + } /* Evaluate the equality constraints */ assert( zAff==0 || (int)strlen(zAff)>=nEq ); for(j=nSkip; jaLTerm[j]; assert( pTerm!=0 ); - /* The following testcase is true for indices with redundant columns. + /* The following testcase is true for indices with redundant columns. ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j); if( r1!=regBase+j ){ if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, regBase); regBase = r1; }else{ - sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); + sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } } if( pTerm->eOperator & WO_IN ){ if( pTerm->pExpr->flags & EP_xIsSelect ){ /* No affinity ever needs to be (or should be) applied to a value - ** from the RHS of an "? IN (SELECT ...)" expression. The - ** sqlite3FindInIndex() routine has already ensured that the + ** from the RHS of an "? IN (SELECT ...)" expression. The + ** sqlite3FindInIndex() routine has already ensured that the ** affinity of the comparison has been applied to the value. */ if( zAff ) zAff[j] = SQLITE_AFF_BLOB; } }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ Expr *pRight = pTerm->pExpr->pRight; if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } - if( pParse->nErr==0 ){ - assert( pParse->db->mallocFailed==0 ); + if( zAff ){ if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){ zAff[j] = SQLITE_AFF_BLOB; } if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){ zAff[j] = SQLITE_AFF_BLOB; @@ -159540,11 +128453,11 @@ } #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS /* ** If the most recently coded instruction is a constant range constraint -** (a string literal) that originated from the LIKE optimization, then +** (a string literal) that originated from the LIKE optimization, then ** set P3 and P5 on the OP_String opcode so that the string will be cast ** to a BLOB at appropriate times. ** ** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range ** expression: "x>='ABC' AND x<'abd'". But this requires that the range @@ -159563,13 +128476,13 @@ WhereTerm *pTerm /* The upper or lower bound just coded */ ){ if( pTerm->wtFlags & TERM_LIKEOPT ){ VdbeOp *pOp; assert( pLevel->iLikeRepCntr>0 ); - pOp = sqlite3VdbeGetLastOp(v); + pOp = sqlite3VdbeGetOp(v, -1); assert( pOp!=0 ); - assert( pOp->opcode==OP_String8 + assert( pOp->opcode==OP_String8 || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */ pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */ } } @@ -159598,21 +128511,21 @@ static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){ struct CCurHint *pHint = pWalker->u.pCCurHint; assert( pHint->pIdx!=0 ); if( pExpr->op==TK_COLUMN && pExpr->iTable==pHint->iTabCur - && sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0 + && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0 ){ pWalker->eCode = 1; } return WRC_Continue; } /* ** Test whether or not expression pExpr, which was part of a WHERE clause, ** should be included in the cursor-hint for a table that is on the rhs -** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the +** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the ** expression is not suitable. ** ** An expression is unsuitable if it might evaluate to non NULL even if ** a TK_COLUMN node that does affect the value of the expression is set ** to NULL. For example: @@ -159621,18 +128534,18 @@ ** col IS NOT NULL ** coalesce(col, 1) ** CASE WHEN col THEN 0 ELSE 1 END */ static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_IS - || pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT - || pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE + if( pExpr->op==TK_IS + || pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT + || pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE ){ pWalker->eCode = 1; }else if( pExpr->op==TK_FUNCTION ){ int d1; - char d2[4]; + char d2[3]; if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){ pWalker->eCode = 1; } } @@ -159644,54 +128557,56 @@ ** This function is called on every node of an expression tree used as an ** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN ** that accesses any table other than the one identified by ** CCurHint.iTabCur, then do the following: ** -** 1) allocate a register and code an OP_Column instruction to read +** 1) allocate a register and code an OP_Column instruction to read ** the specified column into the new register, and ** -** 2) transform the expression node to a TK_REGISTER node that reads +** 2) transform the expression node to a TK_REGISTER node that reads ** from the newly populated register. ** -** Also, if the node is a TK_COLUMN that does access the table identified +** Also, if the node is a TK_COLUMN that does access the table idenified ** by pCCurHint.iTabCur, and an index is being used (which we will ** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into ** an access of the index rather than the original table. */ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ int rc = WRC_Continue; - int reg; struct CCurHint *pHint = pWalker->u.pCCurHint; if( pExpr->op==TK_COLUMN ){ if( pExpr->iTable!=pHint->iTabCur ){ - reg = ++pWalker->pParse->nMem; /* Register for column value */ - reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg); + Vdbe *v = pWalker->pParse->pVdbe; + int reg = ++pWalker->pParse->nMem; /* Register for column value */ + sqlite3ExprCodeGetColumnOfTable( + v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg + ); pExpr->op = TK_REGISTER; pExpr->iTable = reg; }else if( pHint->pIdx!=0 ){ pExpr->iTable = pHint->iIdxCur; - pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn); + pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn); assert( pExpr->iColumn>=0 ); } - }else if( pExpr->pAggInfo ){ + }else if( pExpr->op==TK_AGG_FUNCTION ){ + /* An aggregate function in the WHERE clause of a query means this must + ** be a correlated sub-query, and expression pExpr is an aggregate from + ** the parent context. Do not walk the function arguments in this case. + ** + ** todo: It should be possible to replace this node with a TK_REGISTER + ** expression, as the result of the expression must be stored in a + ** register at this point. The same holds for TK_AGG_COLUMN nodes. */ rc = WRC_Prune; - reg = ++pWalker->pParse->nMem; /* Register for column value */ - reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg); - pExpr->op = TK_REGISTER; - pExpr->iTable = reg; - }else if( pExpr->op==TK_TRUEFALSE ){ - /* Do not walk disabled expressions. tag-20230504-1 */ - return WRC_Prune; } return rc; } /* ** Insert an OP_CursorHint instruction if it is appropriate to do so. */ static void codeCursorHint( - SrcItem *pTabItem, /* FROM clause item */ + struct SrcList_item *pTabItem, /* FROM clause item */ WhereInfo *pWInfo, /* The where clause */ WhereLevel *pLevel, /* Which loop to provide hints for */ WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */ ){ Parse *pParse = pWInfo->pParse; @@ -159714,27 +128629,27 @@ sHint.pIdx = pLoop->u.btree.pIndex; memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.u.pCCurHint = &sHint; pWC = &pWInfo->sWC; - for(i=0; inBase; i++){ + for(i=0; inTerm; i++){ pTerm = &pWC->a[i]; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->prereqAll & pLevel->notReady ) continue; - /* Any terms specified as part of the ON(...) clause for any LEFT + /* Any terms specified as part of the ON(...) clause for any LEFT ** JOIN for which the current table is not the rhs are omitted - ** from the cursor-hint. + ** from the cursor-hint. ** - ** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms + ** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms ** that were specified as part of the WHERE clause must be excluded. ** This is to address the following: ** ** SELECT ... t1 LEFT JOIN t2 ON (t1.a=t2.b) WHERE t2.c IS NULL; ** ** Say there is a single row in t2 that matches (t1.a=t2.b), but its - ** t2.c values is not NULL. If the (t2.c IS NULL) constraint is + ** t2.c values is not NULL. If the (t2.c IS NULL) constraint is ** pushed down to the cursor, this row is filtered out, causing ** SQLite to synthesize a row of NULL values. Which does match the ** WHERE clause, and so the query returns a row. Which is incorrect. ** ** For the same reason, WHERE terms such as: @@ -159743,20 +128658,20 @@ ** ** are also excluded. See codeCursorHintIsOrFunction() for details. */ if( pTabItem->fg.jointype & JT_LEFT ){ Expr *pExpr = pTerm->pExpr; - if( !ExprHasProperty(pExpr, EP_OuterON) - || pExpr->w.iJoin!=pTabItem->iCursor + if( !ExprHasProperty(pExpr, EP_FromJoin) + || pExpr->iRightJoinTable!=pTabItem->iCursor ){ sWalker.eCode = 0; sWalker.xExprCallback = codeCursorHintIsOrFunction; sqlite3WalkExpr(&sWalker, pTerm->pExpr); if( sWalker.eCode ) continue; } }else{ - if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue; + if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; } /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize ** the cursor. These terms are not needed as hints for a pure range ** scan (that has no == terms) so omit them. */ @@ -159776,16 +128691,16 @@ sqlite3WalkExpr(&sWalker, pTerm->pExpr); if( sWalker.eCode ) continue; } /* If we survive all prior tests, that means this term is worth hinting */ - pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); + pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); } if( pExpr!=0 ){ sWalker.xExprCallback = codeCursorHintFixExpr; - if( pParse->nErr==0 ) sqlite3WalkExpr(&sWalker, pExpr); - sqlite3VdbeAddOp4(v, OP_CursorHint, + sqlite3WalkExpr(&sWalker, pExpr); + sqlite3VdbeAddOp4(v, OP_CursorHint, (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0, (const char*)pExpr, P4_EXPR); } } #else @@ -159793,32 +128708,24 @@ #endif /* SQLITE_ENABLE_CURSOR_HINTS */ /* ** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains ** a rowid value just read from cursor iIdxCur, open on index pIdx. This -** function generates code to do a deferred seek of cursor iCur to the +** function generates code to do a deferred seek of cursor iCur to the ** rowid stored in register iRowid. ** ** Normally, this is just: ** ** OP_DeferredSeek $iCur $iRowid ** -** Which causes a seek on $iCur to the row with rowid $iRowid. -** ** However, if the scan currently being coded is a branch of an OR-loop and -** the statement currently being coded is a SELECT, then additional information -** is added that might allow OP_Column to omit the seek and instead do its -** lookup on the index, thus avoiding an expensive seek operation. To -** enable this optimization, the P3 of OP_DeferredSeek is set to iIdxCur -** and P4 is set to an array of integers containing one entry for each column -** in the table. For each table column, if the column is the i'th -** column of the index, then the corresponding array entry is set to (i+1). -** If the column does not appear in the index at all, the array entry is set -** to 0. The OP_Column opcode can check this array to see if the column it -** wants is in the index and if it is, it will substitute the index cursor -** and column number and continue with those new values, rather than seeking -** the table cursor. +** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek +** is set to iIdxCur and P4 is set to point to an array of integers +** containing one entry for each column of the table cursor iCur is open +** on. For each table column, if the column is the i'th column of the +** index, then the corresponding array entry is set to (i+1). If the column +** does not appear in the index at all, the array entry is set to 0. */ static void codeDeferredSeek( WhereInfo *pWInfo, /* Where clause context */ Index *pIdx, /* Index scan is using */ int iCur, /* Cursor for IPK b-tree */ @@ -159827,28 +128734,23 @@ Parse *pParse = pWInfo->pParse; /* Parse context */ Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ assert( iIdxCur>0 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); - - pWInfo->bDeferredSeek = 1; + sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); - if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) + if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) ){ int i; Table *pTab = pIdx->pTable; - u32 *ai = (u32*)sqlite3DbMallocZero(pParse->db, sizeof(u32)*(pTab->nCol+1)); + int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1)); if( ai ){ ai[0] = pTab->nCol; for(i=0; inColumn-1; i++){ - int x1, x2; assert( pIdx->aiColumn[i]nCol ); - x1 = pIdx->aiColumn[i]; - x2 = sqlite3TableColumnToStorage(pTab, x1); - testcase( x1!=x2 ); - if( x1>=0 ) ai[x2+1] = i+1; + if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1; } sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); } } } @@ -159862,204 +128764,138 @@ ** this case, generate code to evaluate the expression and leave the ** result in register iReg. */ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ assert( nReg>0 ); - if( p && sqlite3ExprIsVector(p) ){ + if( sqlite3ExprIsVector(p) ){ #ifndef SQLITE_OMIT_SUBQUERY - if( ExprUseXSelect(p) ){ + if( (p->flags & EP_xIsSelect) ){ Vdbe *v = pParse->pVdbe; - int iSelect; - assert( p->op==TK_SELECT ); - iSelect = sqlite3CodeSubselect(pParse, p); + int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0); sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1); }else #endif { int i; - const ExprList *pList; - assert( ExprUseXList(p) ); - pList = p->x.pList; + ExprList *pList = p->x.pList; assert( nReg<=pList->nExpr ); for(i=0; ia[i].pExpr, iReg+i); } } }else{ - assert( nReg==1 || pParse->nErr ); + assert( nReg==1 ); sqlite3ExprCode(pParse, p, iReg); } } -/* -** The pTruth expression is always true because it is the WHERE clause -** a partial index that is driving a query loop. Look through all of the -** WHERE clause terms on the query, and if any of those terms must be -** true because pTruth is true, then mark those WHERE clause terms as -** coded. -*/ -static void whereApplyPartialIndexConstraints( - Expr *pTruth, - int iTabCur, - WhereClause *pWC -){ - int i; - WhereTerm *pTerm; - while( pTruth->op==TK_AND ){ - whereApplyPartialIndexConstraints(pTruth->pLeft, iTabCur, pWC); - pTruth = pTruth->pRight; - } - for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr; - if( pTerm->wtFlags & TERM_CODED ) continue; - pExpr = pTerm->pExpr; - if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){ - pTerm->wtFlags |= TERM_CODED; - } - } -} - -/* -** This routine is called right after An OP_Filter has been generated and -** before the corresponding index search has been performed. This routine -** checks to see if there are additional Bloom filters in inner loops that -** can be checked prior to doing the index lookup. If there are available -** inner-loop Bloom filters, then evaluate those filters now, before the -** index lookup. The idea is that a Bloom filter check is way faster than -** an index lookup, and the Bloom filter might return false, meaning that -** the index lookup can be skipped. -** -** We know that an inner loop uses a Bloom filter because it has the -** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked, -** then clear the WhereLevel.regFilter value to prevent the Bloom filter -** from being checked a second time when the inner loop is evaluated. -*/ -static SQLITE_NOINLINE void filterPullDown( - Parse *pParse, /* Parsing context */ - WhereInfo *pWInfo, /* Complete information about the WHERE clause */ - int iLevel, /* Which level of pWInfo->a[] should be coded */ - int addrNxt, /* Jump here to bypass inner loops */ - Bitmask notReady /* Loops that are not ready */ -){ - while( ++iLevel < pWInfo->nLevel ){ - WhereLevel *pLevel = &pWInfo->a[iLevel]; - WhereLoop *pLoop = pLevel->pWLoop; - if( pLevel->regFilter==0 ) continue; - if( pLevel->pWLoop->nSkip ) continue; - /* ,--- Because sqlite3ConstructBloomFilter() has will not have set - ** vvvvv--' pLevel->regFilter if this were true. */ - if( NEVER(pLoop->prereq & notReady) ) continue; - assert( pLevel->addrBrk==0 ); - pLevel->addrBrk = addrNxt; - if( pLoop->wsFlags & WHERE_IPK ){ - WhereTerm *pTerm = pLoop->aLTerm[0]; - int regRowid; - assert( pTerm!=0 ); - assert( pTerm->pExpr!=0 ); - testcase( pTerm->wtFlags & TERM_VIRTUAL ); - regRowid = sqlite3GetTempReg(pParse); - regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid); - sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt); - VdbeCoverage(pParse->pVdbe); - sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, - addrNxt, regRowid, 1); - VdbeCoverage(pParse->pVdbe); - }else{ - u16 nEq = pLoop->u.btree.nEq; - int r1; - char *zStartAff; - - assert( pLoop->wsFlags & WHERE_INDEXED ); - assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 ); - r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff); - codeApplyAffinity(pParse, r1, nEq, zStartAff); - sqlite3DbFree(pParse->db, zStartAff); - sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, - addrNxt, r1, nEq); - VdbeCoverage(pParse->pVdbe); - } - pLevel->regFilter = 0; - pLevel->addrBrk = 0; - } -} - -/* -** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...) -** operator. Return true if level pLoop is guaranteed to visit only one -** row for each key generated for the index. -*/ -static int whereLoopIsOneRow(WhereLoop *pLoop){ - if( pLoop->u.btree.pIndex->onError - && pLoop->nSkip==0 - && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol - ){ - int ii; - for(ii=0; iiu.btree.nEq; ii++){ - if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){ - return 0; - } - } - return 1; - } - return 0; +/* An instance of the IdxExprTrans object carries information about a +** mapping from an expression on table columns into a column in an index +** down through the Walker. +*/ +typedef struct IdxExprTrans { + Expr *pIdxExpr; /* The index expression */ + int iTabCur; /* The cursor of the corresponding table */ + int iIdxCur; /* The cursor for the index */ + int iIdxCol; /* The column for the index */ +} IdxExprTrans; + +/* The walker node callback used to transform matching expressions into +** a reference to an index column for an index on an expression. +** +** If pExpr matches, then transform it into a reference to the index column +** that contains the value of pExpr. +*/ +static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ + IdxExprTrans *pX = p->u.pIdxTrans; + if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + pExpr->op = TK_COLUMN; + pExpr->iTable = pX->iIdxCur; + pExpr->iColumn = pX->iIdxCol; + pExpr->pTab = 0; + return WRC_Prune; + }else{ + return WRC_Continue; + } +} + +/* +** For an indexes on expression X, locate every instance of expression X in pExpr +** and change that subexpression into a reference to the appropriate column of +** the index. +*/ +static void whereIndexExprTrans( + Index *pIdx, /* The Index */ + int iTabCur, /* Cursor of the table that is being indexed */ + int iIdxCur, /* Cursor of the index itself */ + WhereInfo *pWInfo /* Transform expressions in this WHERE clause */ +){ + int iIdxCol; /* Column number of the index */ + ExprList *aColExpr; /* Expressions that are indexed */ + Walker w; + IdxExprTrans x; + aColExpr = pIdx->aColExpr; + if( aColExpr==0 ) return; /* Not an index on expressions */ + memset(&w, 0, sizeof(w)); + w.xExprCallback = whereIndexExprTransNode; + w.u.pIdxTrans = &x; + x.iTabCur = iTabCur; + x.iIdxCur = iIdxCur; + for(iIdxCol=0; iIdxColnExpr; iIdxCol++){ + if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue; + assert( aColExpr->a[iIdxCol].pExpr!=0 ); + x.iIdxCol = iIdxCol; + x.pIdxExpr = aColExpr->a[iIdxCol].pExpr; + sqlite3WalkExpr(&w, pWInfo->pWhere); + sqlite3WalkExprList(&w, pWInfo->pOrderBy); + sqlite3WalkExprList(&w, pWInfo->pResultSet); + } } /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( - Parse *pParse, /* Parsing context */ - Vdbe *v, /* Prepared statement under construction */ WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ - WhereLevel *pLevel, /* The current level pointer */ Bitmask notReady /* Which tables are currently available */ ){ int j, k; /* Loop counters */ int iCur; /* The VDBE cursor for the table */ int addrNxt; /* Where to jump to continue with the next IN case */ + int omitTable; /* True if we use the index only */ int bRev; /* True if we need to scan in reverse order */ + WhereLevel *pLevel; /* The where level to be coded */ WhereLoop *pLoop; /* The WhereLoop object being coded */ WhereClause *pWC; /* Decomposition of the entire WHERE clause */ WhereTerm *pTerm; /* A WHERE clause term */ + Parse *pParse; /* Parsing context */ sqlite3 *db; /* Database connection */ - SrcItem *pTabItem; /* FROM clause term being coded */ + Vdbe *v; /* The prepared stmt under constructions */ + struct SrcList_item *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ int addrHalt; /* addrBrk for the outermost loop */ int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ Index *pIdx = 0; /* Index used by loop (if any) */ int iLoop; /* Iteration of constraint generator loop */ + pParse = pWInfo->pParse; + v = pParse->pVdbe; pWC = &pWInfo->sWC; db = pParse->db; + pLevel = &pWInfo->a[iLevel]; pLoop = pLevel->pWLoop; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); bRev = (pWInfo->revMask>>iLevel)&1; - VdbeModuleComment((v, "Begin WHERE-loop%d: %s", - iLevel, pTabItem->pSTab->zName)); -#if WHERETRACE_ENABLED /* 0x4001 */ - if( sqlite3WhereTrace & 0x1 ){ - sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n", - iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom); - if( sqlite3WhereTrace & 0x1000 ){ - sqlite3WhereLoopPrint(pLoop, pWC); - } - } - if( (sqlite3WhereTrace & 0x4001)==0x4001 ){ - if( iLevel==0 ){ - sqlite3DebugPrintf("WHERE clause being coded:\n"); - sqlite3TreeViewExpr(0, pWInfo->pWhere, 0); - } - sqlite3DebugPrintf("All WHERE-clause terms before coding:\n"); - sqlite3WhereClausePrint(pWC); - } -#endif + omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0; + VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName)); /* Create labels for the "break" and "continue" instructions ** for the current loop. Jump to addrBrk to break out of a loop. ** Jump to cont to go immediately to the next iteration of the ** loop. @@ -160067,45 +128903,35 @@ ** When there is an IN operator, we also have a "addrNxt" label that ** means to continue with the next IN value combination. When ** there are no IN operators in the constraints, the "addrNxt" label ** is the same as "addrBrk". */ - addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); - addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse); + addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v); + addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v); /* If this is the right table of a LEFT OUTER JOIN, allocate and ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ - assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) - || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0 - ); if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); - VdbeComment((v, "init LEFT JOIN match flag")); + VdbeComment((v, "init LEFT JOIN no-match flag")); } /* Compute a safe address to jump to if we discover that the table for ** this loop is empty and can never contribute content. */ - for(j=iLevel; j>0; j--){ - if( pWInfo->a[j].iLeftJoin ) break; - if( pWInfo->a[j].pRJ ) break; - } + for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){} addrHalt = pWInfo->a[j].addrBrk; /* Special case of a FROM clause subquery implemented as a co-routine */ if( pTabItem->fg.viaCoroutine ){ - int regYield; - Subquery *pSubq; - assert( pTabItem->fg.isSubquery && pTabItem->u4.pSubq!=0 ); - pSubq = pTabItem->u4.pSubq; - regYield = pSubq->regReturn; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub); + int regYield = pTabItem->regReturn; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); VdbeCoverage(v); - VdbeComment((v, "next row of %s", pTabItem->pSTab->zName)); + VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); pLevel->op = OP_Goto; }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ @@ -160113,123 +128939,86 @@ ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; + int iIn; /* Counter for IN constraints */ + sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; jaLTerm[j]; if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ - if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){ - int iTab = pParse->nTab++; - int iCache = ++pParse->nMem; - sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab); - sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache); - }else{ - codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); - addrNotFound = pLevel->addrNxt; - } + codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); + addrNotFound = pLevel->addrNxt; }else{ Expr *pRight = pTerm->pExpr->pRight; codeExprOrVector(pParse, pRight, iTarget, 1); - if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET - && pLoop->u.vtab.bOmitOffset - ){ - assert( pTerm->eOperator==WO_AUX ); - assert( pWInfo->pSelect!=0 ); - assert( pWInfo->pSelect->iOffset>0 ); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pSelect->iOffset); - VdbeComment((v,"Zero OFFSET counter")); - } } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; - /* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed - ** the u.vtab.idxStr. NULL it out to prevent a use-after-free */ - if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0; pLevel->p1 = iCur; pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); - assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); - - for(j=0; ju.in.nIn; + for(j=nConstraint-1; j>=0; j--){ pTerm = pLoop->aLTerm[j]; if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ disableTerm(pLevel, pTerm); - continue; - } - if( (pTerm->eOperator & WO_IN)!=0 - && (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0 - && !db->mallocFailed - ){ + }else if( (pTerm->eOperator & WO_IN)!=0 ){ Expr *pCompare; /* The comparison operator */ Expr *pRight; /* RHS of the comparison */ VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ - int iIn; /* IN loop corresponding to the j-th constraint */ /* Reload the constraint value into reg[iReg+j+2]. The same value ** was loaded into the same register prior to the OP_VFilter, but ** the xFilter implementation might have changed the datatype or - ** encoding of the value in the register, so it *must* be reloaded. - */ - for(iIn=0; ALWAYS(iInu.in.nIn); iIn++){ - pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop); - if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2) - || (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2) - ){ - testcase( pOp->opcode==OP_Rowid ); - sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); - break; - } - } - - /* Generate code that will continue to the next row if - ** the IN constraint is not satisfied - */ + ** encoding of the value in the register, so it *must* be reloaded. */ + assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); + if( !db->mallocFailed ){ + assert( iIn>0 ); + pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop); + assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); + assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 ); + assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 ); + testcase( pOp->opcode==OP_Rowid ); + sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); + } + + /* Generate code that will continue to the next row if + ** the IN constraint is not satisfied */ pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); - if( !db->mallocFailed ){ - int iFld = pTerm->u.x.iField; - Expr *pLeft = pTerm->pExpr->pLeft; - assert( pLeft!=0 ); - if( iFld>0 ){ - assert( pLeft->op==TK_VECTOR ); - assert( ExprUseXList(pLeft) ); - assert( iFld<=pLeft->x.pList->nExpr ); - pCompare->pLeft = pLeft->x.pList->a[iFld-1].pExpr; - }else{ - pCompare->pLeft = pLeft; - } + assert( pCompare!=0 || db->mallocFailed ); + if( pCompare ){ + pCompare->pLeft = pTerm->pExpr->pLeft; pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); if( pRight ){ pRight->iTable = iReg+j+2; - sqlite3ExprIfFalse( - pParse, pCompare, pLevel->addrCont, SQLITE_JUMPIFNULL - ); + sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); } pCompare->pLeft = 0; + sqlite3ExprDelete(db, pCompare); } - sqlite3ExprDelete(db, pCompare); } } - /* These registers need to be preserved in case there is an IN operator ** loop. So we could deallocate the registers here (and potentially ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems ** simpler and safer to simply not reuse the registers. ** ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); */ + sqlite3ExprCachePop(pParse); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ if( (pLoop->wsFlags & WHERE_IPK)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0 @@ -160241,25 +129030,21 @@ */ assert( pLoop->u.btree.nEq==1 ); pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); + assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); iReleaseReg = ++pParse->nMem; iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; - if( pLevel->regFilter ){ - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); - VdbeCoverage(v); - sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, - iRowidReg, 1); - VdbeCoverage(v); - filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); - } sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); + sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( (pLoop->wsFlags & WHERE_IPK)!=0 && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0 ){ /* Case 3: We have an inequality comparison against the ROWID field. @@ -160267,10 +129052,11 @@ int testOp = OP_Noop; int start; int memEndValue = 0; WhereTerm *pStart, *pEnd; + assert( omitTable==0 ); j = 0; pStart = pEnd = 0; if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++]; if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++]; assert( pStart!=0 || pEnd!=0 ); @@ -160283,11 +129069,11 @@ if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ int op; /* Cursor seek operation */ - /* The following constant maps TK_xx codes into corresponding + /* The following constant maps TK_xx codes into corresponding ** seek opcodes. It depends on a particular ordering of TK_xx */ const u8 aMoveOp[] = { /* TK_GT */ OP_SeekGT, /* TK_LE */ OP_SeekLE, @@ -160294,29 +129080,21 @@ /* TK_LT */ OP_SeekLT, /* TK_GE */ OP_SeekGE }; assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ - assert( TK_GE==TK_GT+3 ); /* ... is correct. */ + assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); pX = pStart->pExpr; assert( pX!=0 ); testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ if( sqlite3ExprIsVector(pX->pRight) ){ r1 = rTemp = sqlite3GetTempReg(pParse); codeExprOrVector(pParse, pX->pRight, r1, 1); - testcase( pX->op==TK_GT ); - testcase( pX->op==TK_GE ); - testcase( pX->op==TK_LT ); - testcase( pX->op==TK_LE ); - op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; - assert( pX->op!=TK_GT || op==OP_SeekGE ); - assert( pX->op!=TK_GE || op==OP_SeekGE ); - assert( pX->op!=TK_LT || op==OP_SeekLE ); - assert( pX->op!=TK_LE || op==OP_SeekLE ); + op = aMoveOp[(pX->op - TK_GT) | 0x0001]; }else{ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); disableTerm(pLevel, pStart); op = aMoveOp[(pX->op - TK_GT)]; } @@ -160324,10 +129102,11 @@ VdbeComment((v, "pk")); VdbeCoverageIf(v, pX->op==TK_GT); VdbeCoverageIf(v, pX->op==TK_LE); VdbeCoverageIf(v, pX->op==TK_LT); VdbeCoverageIf(v, pX->op==TK_GE); + sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); @@ -160339,12 +129118,12 @@ assert( (pEnd->wtFlags & TERM_VNULL)==0 ); testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ testcase( pEnd->wtFlags & TERM_VIRTUAL ); memEndValue = ++pParse->nMem; codeExprOrVector(pParse, pX->pRight, memEndValue, 1); - if( 0==sqlite3ExprIsVector(pX->pRight) - && (pX->op==TK_LT || pX->op==TK_GT) + if( 0==sqlite3ExprIsVector(pX->pRight) + && (pX->op==TK_LT || pX->op==TK_GT) ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; } @@ -160358,10 +129137,11 @@ pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); VdbeCoverageIf(v, testOp==OP_Le); VdbeCoverageIf(v, testOp==OP_Lt); VdbeCoverageIf(v, testOp==OP_Ge); VdbeCoverageIf(v, testOp==OP_Gt); @@ -160368,18 +129148,18 @@ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ /* Case 4: A scan using an index. ** - ** The WHERE clause may contain zero or more equality + ** The WHERE clause may contain zero or more equality ** terms ("==" or "IN" operators) that refer to the N ** left-most columns of the index. It may also contain ** inequality constraints (>, <, >= or <=) on the indexed - ** column that immediately follows the N equalities. Only + ** column that immediately follows the N equalities. Only ** the right-most column can be an inequality - the rest must - ** use the "==" and "IN" operators. For example, if the - ** index is on (x,y,z), then the following clauses are all + ** use the "==" and "IN" operators. For example, if the + ** index is on (x,y,z), then the following clauses are all ** optimized: ** ** x=5 ** x=5 AND y=10 ** x=5 AND y<10 @@ -160396,11 +129176,11 @@ ** least one. ** ** This case is also used when there are no WHERE clause ** constraints but an index is selected anyway, in order ** to force the output order to conform to an ORDER BY. - */ + */ static const u8 aStartOp[] = { 0, 0, OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ OP_Last, /* 3: (!start_constraints && startEq && bRev) */ @@ -160430,27 +129210,44 @@ int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ char *zEndAff = 0; /* Affinity for end of range constraint */ u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ - int omitTable; /* True if we use the index only */ - int regBignull = 0; /* big-null flag register */ - int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */ pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; assert( nEq>=pLoop->nSkip ); - /* Find any inequality constraint terms for the start and end - ** of the range. + /* If this loop satisfies a sort order (pOrderBy) request that + ** was passed to this function to implement a "SELECT min(x) ..." + ** query, then the caller will only allow the loop to run for + ** a single iteration. This means that the first row returned + ** should not have a NULL value stored in 'x'. If column 'x' is + ** the first one after the nEq equality constraints in the index, + ** this requires some special handling. + */ + assert( pWInfo->pOrderBy==0 + || pWInfo->pOrderBy->nExpr==1 + || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 ); + if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0 + && pWInfo->nOBSat>0 + && (pIdx->nKeyCol>nEq) + ){ + assert( pLoop->nSkip==0 ); + bSeekPastNull = 1; + nExtraReg = 1; + } + + /* Find any inequality constraint terms for the start and end + ** of the range. */ j = nEq; if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm); /* Like optimization range constraints always occur in pairs */ - assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || + assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop); @@ -160478,48 +129275,22 @@ } } } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); - /* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses - ** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS - ** FIRST). In both cases separate ordered scans are made of those - ** index entries for which the column is null and for those for which - ** it is not. For an ASC sort, the non-NULL entries are scanned first. - ** For DESC, NULL entries are scanned first. - */ - if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0 - && (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0 - ){ - assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 ); - assert( pRangeEnd==0 && pRangeStart==0 ); - testcase( pLoop->nSkip>0 ); - nExtraReg = 1; - bSeekPastNull = 1; - pLevel->regBignull = regBignull = ++pParse->nMem; - if( pLevel->iLeftJoin ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull); - } - pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse); - } - /* If we are doing a reverse order scan on an ascending index, or - ** a forward order scan on a descending index, interchange the + ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ - if( (nEqnColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){ + if( (nEqnKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) + || (bRev && pIdx->nKeyCol==nEq) + ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); SWAP(u8, bSeekPastNull, bStopAtNull); SWAP(u8, nBtm, nTop); } - if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){ - /* In case OP_SeekScan is used, ensure that the index cursor does not - ** point to a valid row for the first iteration of this loop. */ - sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); - } - /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers ** starting at regBase. */ codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd); @@ -160526,11 +129297,11 @@ regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); if( zStartAff && nTop ){ zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); } - addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt); + addrNxt = pLevel->addrNxt; testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); @@ -160550,102 +129321,50 @@ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); } if( zStartAff ){ updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); - } + } nConstraint += nBtm; testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); if( sqlite3ExprIsVector(pRight)==0 ){ disableTerm(pLevel, pRangeStart); }else{ startEq = 1; } bSeekPastNull = 0; }else if( bSeekPastNull ){ - startEq = 0; - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - start_constraints = 1; - nConstraint++; - }else if( regBignull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - start_constraints = 1; - nConstraint++; + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + nConstraint++; + startEq = 0; + start_constraints = 1; } codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){ /* The skip-scan logic inside the call to codeAllEqualityConstraints() ** above has already left the cursor sitting on the correct row, ** so no further seeking is needed */ }else{ - if( regBignull ){ - sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); - VdbeComment((v, "NULL-scan pass ctr")); - } - if( pLevel->regFilter ){ - sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, - regBase, nEq); - VdbeCoverage(v); - filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); - } - op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); - if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){ - assert( regBignull==0 ); - /* TUNING: The OP_SeekScan opcode seeks to reduce the number - ** of expensive seek operations by replacing a single seek with - ** 1 or more step operations. The question is, how many steps - ** should we try before giving up and going with a seek. The cost - ** of a seek is proportional to the logarithm of the of the number - ** of entries in the tree, so basing the number of steps to try - ** on the estimated number of rows in the btree seems like a good - ** guess. */ - addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan, - (pIdx->aiRowLogEst[0]+9)/10); - if( pRangeStart || pRangeEnd ){ - sqlite3VdbeChangeP5(v, 1); - sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1); - addrSeekScan = 0; - } - VdbeCoverage(v); - } sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); VdbeCoverage(v); VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); - - assert( bSeekPastNull==0 || bStopAtNull==0 ); - if( regBignull ){ - assert( bSeekPastNull==1 || bStopAtNull==1 ); - assert( bSeekPastNull==!bStopAtNull ); - assert( bStopAtNull==startEq ); - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - op = aStartOp[(nConstraint>1)*4 + 2 + bRev]; - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, - nConstraint-startEq); - VdbeCoverage(v); - VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); - VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); - VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); - VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); - assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE); - } } /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; - assert( pLevel->p2==0 ); if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; - assert( addrSeekScan==0 ); + sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); codeExprOrVector(pParse, pRight, regBase+nEq, nTop); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -160665,101 +129384,66 @@ disableTerm(pLevel, pRangeEnd); }else{ endEq = 1; } }else if( bStopAtNull ){ - if( regBignull==0 ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - endEq = 0; - } + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + endEq = 0; nConstraint++; } - if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff); - if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff); + sqlite3DbFree(db, zStartAff); + sqlite3DbFree(db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ - if( regBignull ){ - /* Except, skip the end-of-range check while doing the NULL-scan */ - sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); - VdbeComment((v, "If NULL-scan 2nd pass")); - VdbeCoverage(v); - } op = aEndOp[bRev*2 + endEq]; sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); - testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); - testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); - testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); - if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan); - } - if( regBignull ){ - /* During a NULL-scan, check to see if we have reached the end of - ** the NULLs */ - assert( bSeekPastNull==!bStopAtNull ); - assert( bSeekPastNull+bStopAtNull==1 ); - assert( nConstraint+bSeekPastNull>0 ); - sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2); - VdbeComment((v, "If NULL-scan 1st pass")); - VdbeCoverage(v); - op = aEndOp[bRev*2 + bSeekPastNull]; - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, - nConstraint+bSeekPastNull); testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } - if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){ - sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq); - } - /* Seek the table cursor, if required */ - omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 - && (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0; if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); + if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || ( + (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE) + && (pWInfo->eOnePass==ONEPASS_SINGLE) + )){ + iRowidReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); + VdbeCoverage(v); + }else{ + codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); + } }else if( iCur!=iIdxCur ){ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); for(j=0; jnKeyCol; j++){ - k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]); + k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); } sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } - if( pLevel->iLeftJoin==0 ){ - /* If a partial index is driving the loop, try to eliminate WHERE clause - ** terms from the query that must be true due to the WHERE clause of - ** the partial index. - ** - ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work - ** for a LEFT JOIN. - */ - if( pIdx->pPartIdxWhere ){ - whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC); - } - }else{ - testcase( pIdx->pPartIdxWhere ); - /* The following assert() is not a requirement, merely an observation: - ** The OR-optimization doesn't work for the right hand table of - ** a LEFT JOIN: */ - assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ); - } + /* If pIdx is an index on one or more expressions, then look through + ** all the expressions in pWInfo and try to transform matching expressions + ** into reference to index columns. + */ + whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); + /* Record the instruction used to terminate the loop. */ - if( (pLoop->wsFlags & WHERE_ONEROW) - || (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop)) - ){ + if( pLoop->wsFlags & WHERE_ONEROW ){ pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; }else{ pLevel->op = OP_Next; @@ -160825,16 +129509,17 @@ int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ int regRowset = 0; /* Register for RowSet object */ int regRowid = 0; /* Register holding rowid */ - int iLoopBody = sqlite3VdbeMakeLabel(pParse);/* Start of loop body */ + int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */ int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ + u16 wctrlFlags; /* Flags for sub-WHERE clause */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ - Table *pTab = pTabItem->pSTab; + Table *pTab = pTabItem->pTab; pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->eOperator & WO_OR ); assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); @@ -160846,13 +129531,13 @@ ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). */ if( pWInfo->nLevel>1 ){ int nNotReady; /* The number of notReady tables */ - SrcItem *origSrc; /* Original list of tables */ + struct SrcList_item *origSrc; /* Original list of tables */ nNotReady = pWInfo->nLevel - iLevel - 1; - pOrTab = sqlite3DbMallocRawNN(db, + pOrTab = sqlite3StackAllocRaw(db, sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0])); if( pOrTab==0 ) return notReady; pOrTab->nAlloc = (u8)(nNotReady + 1); pOrTab->nSrc = pOrTab->nAlloc; memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); @@ -160862,19 +129547,19 @@ } }else{ pOrTab = pWInfo->pTabList; } - /* Initialize the rowset register to contain NULL. An SQL NULL is + /* Initialize the rowset register to contain NULL. An SQL NULL is ** equivalent to an empty rowset. Or, create an ephemeral index ** capable of holding primary keys in the case of a WITHOUT ROWID. ** - ** Also initialize regReturn to contain the address of the instruction + ** Also initialize regReturn to contain the address of the instruction ** immediately following the OP_Return at the bottom of the loop. This ** is required in a few obscure LEFT JOIN cases where control jumps - ** over the top of the loop into the body of it. In this case the - ** correct response for the end-of-loop code (the OP_Return) is to + ** over the top of the loop into the body of it. In this case the + ** correct response for the end-of-loop code (the OP_Return) is to ** fall through to the next instruction, just as an OP_Next does if ** called on an uninitialized cursor. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ if( HasRowid(pTab) ){ @@ -160889,123 +129574,92 @@ regRowid = ++pParse->nMem; } iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y - ** Then for every term xN, evaluate as the subexpression: xN AND y + ** Then for every term xN, evaluate as the subexpression: xN AND z ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite3WhereBegin() below. ** ** Actually, each subexpression is converted to "xN AND w" where w is ** the "interesting" terms of z - terms that did not originate in the - ** ON or USING clause of a LEFT JOIN, and terms that are usable as + ** ON or USING clause of a LEFT JOIN, and terms that are usable as ** indices. ** ** This optimization also only applies if the (x1 OR x2 OR ...) term ** is not contained in the ON clause of a LEFT JOIN. ** See ticket http://www.sqlite.org/src/info/f2369304e4 - ** - ** 2022-02-04: Do not push down slices of a row-value comparison. - ** In other words, "w" or "y" may not be a slice of a vector. Otherwise, - ** the initialization of the right-hand operand of the vector comparison - ** might not occur, or might occur only in an OR branch that is not - ** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1. - ** - ** 2022-03-03: Do not push down expressions that involve subqueries. - ** The subquery might get coded as a subroutine. Any table-references - ** in the subquery might be resolved to index-references for the index on - ** the OR branch in which the subroutine is coded. But if the subroutine - ** is invoked from a different OR branch that uses a different index, such - ** index-references will not work. tag-20220303a - ** https://sqlite.org/forum/forumpost/36937b197273d403 */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTermnTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; + if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); - testcase( pWC->a[iTerm].wtFlags & TERM_SLICE ); - if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){ - continue; - } + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; - if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */ + testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); - pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr); + pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ - /* The extra 0x10000 bit on the opcode is masked off and does not - ** become part of the new Expr.op. However, it does make the - ** op==TK_AND comparison inside of sqlite3PExpr() false, and this - ** prevents sqlite3PExpr() from applying the AND short-circuit - ** optimization, which we do not want here. */ - pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr); + pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr); } } /* Run a separate WHERE clause for each term of the OR clause. After ** eliminating duplicates from other WHERE clauses, the action for each ** sub-WHERE clause is to to invoke the main loop body as a subroutine. */ - ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); + wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ - Expr *pDelete; /* Local copy of OR clause term */ int jmp1 = 0; /* Address of jump operation */ - testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pOrExpr, EP_OuterON) - ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */ - pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDelete); - continue; - } - if( pAndExpr ){ + if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ - ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1)); - WHERETRACE(0xffffffff, ("Subplan for OR-clause:\n")); - pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0, - WHERE_OR_SUBCLAUSE, iCovCur); - assert( pSubWInfo || pParse->nErr ); + WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); + pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, + wctrlFlags, iCovCur); + assert( pSubWInfo || pParse->nErr || db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; int addrExplain = sqlite3WhereExplainOneScan( - pParse, pOrTab, &pSubWInfo->a[0], 0 + pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same ** row will be skipped in subsequent sub-WHERE clauses. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ + int r; int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); if( HasRowid(pTab) ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid); + r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, - regRowid, iSet); + r,iSet); VdbeCoverage(v); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); int nPk = pPk->nKeyCol; int iPk; - int r; /* Read the PK into an array of temp registers. */ r = sqlite3GetTempRange(pParse, nPk); for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); + sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk); } /* Check if the temp table already contains this key. If so, ** the row has already been included in the result set and ** can be ignored (by jumping past the Gosub below). Otherwise, @@ -161012,13 +129666,13 @@ ** insert the key into the temp table and proceed with processing ** the row. ** ** Use some of the same optimizations as OP_RowSetTest: If iSet ** is zero, assume that the key cannot already be present in - ** the temp table. And if iSet is -1, assume that there is no - ** need to insert the key into the temp table, as it will never - ** be tested for. */ + ** the temp table. And if iSet is -1, assume that there is no + ** need to insert the key into the temp table, as it will never + ** be tested for. */ if( iSet ){ jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); VdbeCoverage(v); } if( iSet>=0 ){ @@ -161053,12 +129707,12 @@ ** be possible to use that index as a covering index. ** ** If the call to sqlite3WhereBegin() above resulted in a scan that ** uses an index, and this is either the first OR-connected term ** processed or the index is the same as that used by all previous - ** terms, set pCov to the candidate covering index. Otherwise, set - ** pCov to NULL to indicate that no candidate covering index will + ** terms, set pCov to the candidate covering index. Otherwise, set + ** pCov to NULL to indicate that no candidate covering index will ** be available. */ pSubLoop = pSubWInfo->a[0].pWLoop; assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0 @@ -161068,44 +129722,27 @@ assert( pSubWInfo->a[0].iIdxCur==iCovCur ); pCov = pSubLoop->u.btree.pIndex; }else{ pCov = 0; } - if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){ - pWInfo->bDeferredSeek = 1; - } /* Finish the loop through table entries that match term pOrTerm. */ sqlite3WhereEnd(pSubWInfo); - ExplainQueryPlanPop(pParse); } - sqlite3ExprDelete(db, pDelete); } } - ExplainQueryPlanPop(pParse); - assert( pLevel->pWLoop==pLoop ); - assert( (pLoop->wsFlags & WHERE_MULTI_OR)!=0 ); - assert( (pLoop->wsFlags & WHERE_IN_ABLE)==0 ); - pLevel->u.pCoveringIdx = pCov; + pLevel->u.pCovidx = pCov; if( pCov ) pLevel->iIdxCur = iCovCur; if( pAndExpr ){ pAndExpr->pLeft = 0; sqlite3ExprDelete(db, pAndExpr); } sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeGoto(v, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); - /* Set the P2 operand of the OP_Return opcode that will end the current - ** loop to point to this spot, which is the top of the next containing - ** loop. The byte-code formatter will use that P2 value as a hint to - ** indent everything in between the this point and the final OP_Return. - ** See tag-20220407a in vdbe.c and shell.c */ - assert( pLevel->op==OP_Return ); - pLevel->p2 = sqlite3VdbeCurrentAddr(v); - - if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); } + if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab); if( !untestedTerms ) disableTerm(pLevel, pTerm); }else #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ { @@ -161141,20 +129778,14 @@ ** constraints to be generated. The value of stack variable iLoop ** determines the constraints coded by each iteration, as follows: ** ** iLoop==1: Code only expressions that are entirely covered by pIdx. ** iLoop==2: Code remaining expressions that do not contain correlated - ** sub-queries. + ** sub-queries. ** iLoop==3: Code all remaining expressions. ** ** An effort is made to skip unnecessary iterations of the loop. - ** - ** This optimization of causing simple query restrictions to occur before - ** more complex one is call the "push-down" optimization in MySQL. Here - ** in SQLite, the name is "MySQL push-down", since there is also another - ** totally unrelated optimization called "WHERE-clause push-down". - ** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware. */ iLoop = (pIdx ? 1 : 2); do{ int iNext = 0; /* Next value for iLoop */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ @@ -161169,61 +129800,43 @@ pWInfo->untestedTerms = 1; continue; } pE = pTerm->pExpr; assert( pE!=0 ); - if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){ - if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){ - /* Defer processing WHERE clause constraints until after outer - ** join processing. tag-20220513a */ - continue; - }else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT - && !ExprHasProperty(pE,EP_OuterON) ){ - continue; - }else{ - Bitmask m = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin); - if( m & pLevel->notReady ){ - /* An ON clause that is not ripe */ - continue; - } - } - } + if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ + continue; + } + if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ iNext = 2; continue; } if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){ if( iNext==0 ) iNext = 3; continue; } - if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){ + if( pTerm->wtFlags & TERM_LIKECOND ){ /* If the TERM_LIKECOND flag is set, that means that the range search ** is sufficient to guarantee that the LIKE operator is true, so we ** can skip the call to the like(A,B) function. But this only works ** for strings. So do not skip the call to the function on the pass ** that compares BLOBs. */ #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS continue; #else u32 x = pLevel->iLikeRepCntr; - if( x>0 ){ - skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); - VdbeCoverageIf(v, (x&1)==1); - VdbeCoverageIf(v, (x&1)==0); - } + assert( x>0 ); + skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1)); + VdbeCoverage(v); #endif } -#ifdef WHERETRACE_ENABLED /* 0xffffffff */ +#ifdef WHERETRACE_ENABLED /* 0xffff */ if( sqlite3WhereTrace ){ VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d", pWC->nTerm-j, pTerm, iLoop)); } - if( sqlite3WhereTrace & 0x4000 ){ - sqlite3DebugPrintf("Coding auxiliary constraint:\n"); - sqlite3WhereTermPrint(pTerm, pWC->nTerm-j); - } #endif sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); pTerm->wtFlags |= TERM_CODED; } @@ -161236,252 +129849,59 @@ ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" ** and we are coding the t1 loop and the t2 loop has not yet coded, ** then we cannot use the "t1.a=t2.b" constraint, but we can code ** the implied "t1.a=123" constraint. */ - for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){ + for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE, sEAlt; WhereTerm *pAlt; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; if( pTerm->leftCursor!=iCur ) continue; - if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ) continue; + if( pLevel->iLeftJoin ) continue; pE = pTerm->pExpr; -#ifdef WHERETRACE_ENABLED /* 0x4001 */ - if( (sqlite3WhereTrace & 0x4001)==0x4001 ){ - sqlite3DebugPrintf("Coding transitive constraint:\n"); - sqlite3WhereTermPrint(pTerm, pWC->nTerm-j); - } -#endif - assert( !ExprHasProperty(pE, EP_OuterON) ); + assert( !ExprHasProperty(pE, EP_FromJoin) ); assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady, + pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN|WO_IS, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; - if( (pAlt->eOperator & WO_IN) - && ExprUseXSelect(pAlt->pExpr) - && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) - ){ - continue; - } testcase( pAlt->eOperator & WO_EQ ); testcase( pAlt->eOperator & WO_IS ); testcase( pAlt->eOperator & WO_IN ); VdbeModuleComment((v, "begin transitive constraint")); sEAlt = *pAlt->pExpr; sEAlt.pLeft = pE->pLeft; sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL); - pAlt->wtFlags |= TERM_CODED; - } - - /* For a RIGHT OUTER JOIN, record the fact that the current row has - ** been matched at least once. - */ - if( pLevel->pRJ ){ - Table *pTab; - int nPk; - int r; - int jmp1 = 0; - WhereRightJoin *pRJ = pLevel->pRJ; - - /* pTab is the right-hand table of the RIGHT JOIN. Generate code that - ** will record that the current row of that table has been matched at - ** least once. This is accomplished by storing the PK for the row in - ** both the iMatch index and the regBloom Bloom filter. - */ - pTab = pWInfo->pTabList->a[pLevel->iFrom].pSTab; - if( HasRowid(pTab) ){ - r = sqlite3GetTempRange(pParse, 2); - sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1); - nPk = 1; - }else{ - int iPk; - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - nPk = pPk->nKeyCol; - r = sqlite3GetTempRange(pParse, nPk+1); - for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk); - } - } - jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk); - VdbeCoverage(v); - VdbeComment((v, "match against %s", pTab->zName)); - sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk); - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3VdbeJumpHere(v, jmp1); - sqlite3ReleaseTempRange(pParse, r, nPk+1); } /* For a LEFT OUTER JOIN, generate code that will record the fact that - ** at least one row of the right table has matched the left table. + ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); - if( pLevel->pRJ==0 ){ - goto code_outer_join_constraints; /* WHERE clause constraints */ - } - } - - if( pLevel->pRJ ){ - /* Create a subroutine used to process all interior loops and code - ** of the RIGHT JOIN. During normal operation, the subroutine will - ** be in-line with the rest of the code. But at the end, a separate - ** loop will run that invokes this subroutine for unmatched rows - ** of pTab, with all tables to left begin set to NULL. - */ - WhereRightJoin *pRJ = pLevel->pRJ; - sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn); - pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v); - assert( pParse->withinRJSubrtn < 255 ); - pParse->withinRJSubrtn++; - - /* WHERE clause constraints must be deferred until after outer join - ** row elimination has completed, since WHERE clause constraints apply - ** to the results of the OUTER JOIN. The following loop generates the - ** appropriate WHERE clause constraint checks. tag-20220513a. - */ - code_outer_join_constraints: - for(pTerm=pWC->a, j=0; jnBase; j++, pTerm++){ + sqlite3ExprCacheClear(pParse); + for(pTerm=pWC->a, j=0; jnTerm; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ assert( pWInfo->untestedTerms ); continue; } - if( pTabItem->fg.jointype & JT_LTORJ ) continue; assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } } -#if WHERETRACE_ENABLED /* 0x4001 */ - if( sqlite3WhereTrace & 0x4000 ){ - sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n", - iLevel); - sqlite3WhereClausePrint(pWC); - } - if( sqlite3WhereTrace & 0x1 ){ - sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n", - iLevel, (u64)pLevel->notReady); - } -#endif return pLevel->notReady; } -/* -** Generate the code for the loop that finds all non-matched terms -** for a RIGHT JOIN. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( - WhereInfo *pWInfo, - int iLevel, - WhereLevel *pLevel -){ - Parse *pParse = pWInfo->pParse; - Vdbe *v = pParse->pVdbe; - WhereRightJoin *pRJ = pLevel->pRJ; - Expr *pSubWhere = 0; - WhereClause *pWC = &pWInfo->sWC; - WhereInfo *pSubWInfo; - WhereLoop *pLoop = pLevel->pWLoop; - SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; - SrcList sFrom; - Bitmask mAll = 0; - int k; - - ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName)); - sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, - pRJ->regReturn); - for(k=0; ka[k].pWLoop->iTab == pWInfo->a[k].iFrom ); - pRight = &pWInfo->pTabList->a[pWInfo->a[k].iFrom]; - mAll |= pWInfo->a[k].pWLoop->maskSelf; - if( pRight->fg.viaCoroutine ){ - Subquery *pSubq; - assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 ); - pSubq = pRight->u4.pSubq; - assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 ); - sqlite3VdbeAddOp3( - v, OP_Null, 0, pSubq->regResult, - pSubq->regResult + pSubq->pSelect->pEList->nExpr-1 - ); - } - sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); - iIdxCur = pWInfo->a[k].iIdxCur; - if( iIdxCur ){ - sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); - } - } - if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){ - mAll |= pLoop->maskSelf; - for(k=0; knTerm; k++){ - WhereTerm *pTerm = &pWC->a[k]; - if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_SLICE))!=0 - && pTerm->eOperator!=WO_ROWVAL - ){ - break; - } - if( pTerm->prereqAll & ~mAll ) continue; - if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue; - pSubWhere = sqlite3ExprAnd(pParse, pSubWhere, - sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); - } - } - sFrom.nSrc = 1; - sFrom.nAlloc = 1; - memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem)); - sFrom.a[0].fg.jointype = 0; - assert( pParse->withinRJSubrtn < 100 ); - pParse->withinRJSubrtn++; - pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0, - WHERE_RIGHT_JOIN, 0); - if( pSubWInfo ){ - int iCur = pLevel->iTabCur; - int r = ++pParse->nMem; - int nPk; - int jmp; - int addrCont = sqlite3WhereContinueLabel(pSubWInfo); - Table *pTab = pTabItem->pSTab; - if( HasRowid(pTab) ){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r); - nPk = 1; - }else{ - int iPk; - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - nPk = pPk->nKeyCol; - pParse->nMem += nPk - 1; - for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); - } - } - jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk); - VdbeCoverage(v); - sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, jmp); - sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn); - sqlite3WhereEnd(pSubWInfo); - } - sqlite3ExprDelete(pParse->db, pSubWhere); - ExplainQueryPlanPop(pParse); - assert( pParse->withinRJSubrtn>0 ); - pParse->withinRJSubrtn--; -} - /************** End of wherecode.c *******************************************/ /************** Begin file whereexpr.c ***************************************/ /* ** 2015-06-08 ** @@ -161495,11 +129915,11 @@ ************************************************************************* ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** ** This file was originally part of where.c but was split out to improve -** readability and editability. This file contains utility routines for +** readability and editabiliity. This file contains utility routines for ** analyzing Expr objects in the WHERE clause. */ /* #include "sqliteInt.h" */ /* #include "whereInt.h" */ @@ -161546,29 +129966,31 @@ int idx; testcase( wtFlags & TERM_VIRTUAL ); if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; sqlite3 *db = pWC->pWInfo->pParse->db; - pWC->a = sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 ); + pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ if( wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, p); } pWC->a = pOld; return 0; } memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); - pWC->nSlot = pWC->nSlot*2; + if( pOld!=pWC->aStatic ){ + sqlite3DbFree(db, pOld); + } + pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; - if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm; if( p && ExprHasProperty(p, EP_Unlikely) ){ pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; }else{ pTerm->truthProb = 1; } - pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p); + pTerm->pExpr = sqlite3ExprSkipCollate(p); pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; memset(&pTerm->eOperator, 0, sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); @@ -161583,29 +130005,41 @@ static int allowedOp(int op){ assert( TK_GT>TK_EQ && TK_GTTK_EQ && TK_LTTK_EQ && TK_LETK_GE ) return 0; - if( op>=TK_EQ ) return 1; - return op==TK_IN || op==TK_ISNULL || op==TK_IS; + return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS; } /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". +** +** If left/right precedence rules come into play when determining the +** collating sequence, then COLLATE operators are adjusted to ensure +** that the collating sequence does not change. For example: +** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on +** the left hand side of a comparison overrides any collation sequence +** attached to the right. For the same reason the EP_Collate flag +** is not commuted. */ -static u16 exprCommute(Parse *pParse, Expr *pExpr){ - if( pExpr->pLeft->op==TK_VECTOR - || pExpr->pRight->op==TK_VECTOR - || sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight) != - sqlite3BinaryCompareCollSeq(pParse, pExpr->pRight, pExpr->pLeft) - ){ - pExpr->flags ^= EP_Commuted; +static void exprCommute(Parse *pParse, Expr *pExpr){ + u16 expRight = (pExpr->pRight->flags & EP_Collate); + u16 expLeft = (pExpr->pLeft->flags & EP_Collate); + assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); + if( expRight==expLeft ){ + /* Either X and Y both have COLLATE operator or neither do */ + if( expRight ){ + /* Both X and Y have COLLATE operators. Make sure X is always + ** used by clearing the EP_Collate flag from Y. */ + pExpr->pRight->flags &= ~EP_Collate; + }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ + /* Neither X nor Y have COLLATE operators, but X has a non-default + ** collating sequence. So add the EP_Collate marker on X to cause + ** it to be searched first. */ + pExpr->pLeft->flags |= EP_Collate; + } } SWAP(Expr*,pExpr->pRight,pExpr->pLeft); if( pExpr->op>=TK_GT ){ assert( TK_LT==TK_GT+2 ); assert( TK_GE==TK_LE+2 ); @@ -161612,29 +130046,27 @@ assert( TK_GT>TK_EQ ); assert( TK_GTop>=TK_GT && pExpr->op<=TK_GE ); pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; } - return 0; } /* ** Translate from TK_xx operator to WO_xx bitmask. */ static u16 operatorMask(int op){ u16 c; assert( allowedOp(op) ); - if( op>=TK_EQ ){ - assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); - c = (u16)(WO_EQ<<(op-TK_EQ)); - }else if( op==TK_IN ){ + if( op==TK_IN ){ c = WO_IN; }else if( op==TK_ISNULL ){ c = WO_ISNULL; - }else{ - assert( op==TK_IS ); + }else if( op==TK_IS ){ c = WO_IS; + }else{ + assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); + c = (u16)(WO_EQ<<(op-TK_EQ)); } assert( op!=TK_ISNULL || c==WO_ISNULL ); assert( op!=TK_IN || c==WO_IN ); assert( op!=TK_EQ || c==WO_EQ ); assert( op!=TK_LT || c==WO_LT ); @@ -161664,28 +130096,27 @@ Expr *pExpr, /* Test this expression */ Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */ int *pisComplete, /* True if the only wildcard is % in the last character */ int *pnoCase /* True if uppercase is equivalent to lowercase */ ){ - const u8 *z = 0; /* String on RHS of LIKE operator */ + const char *z = 0; /* String on RHS of LIKE operator */ Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ ExprList *pList; /* List of operands to the LIKE operator */ - u8 c; /* One character in z[] */ + int c; /* One character in z[] */ int cnt; /* Number of non-wildcard prefix characters */ - u8 wc[4]; /* Wildcard characters */ + char wc[3]; /* Wildcard characters */ sqlite3 *db = pParse->db; /* Database connection */ sqlite3_value *pVal = 0; int op; /* Opcode of pRight */ int rc; /* Result code to return */ - if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){ + if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ return 0; } #ifdef SQLITE_EBCDIC if( *pnoCase ) return 0; #endif - assert( ExprUseXList(pExpr) ); pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); op = pRight->op; @@ -161692,125 +130123,55 @@ if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ Vdbe *pReprepare = pParse->pReprepare; int iCol = pRight->iColumn; pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB); if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ - z = sqlite3_value_text(pVal); + z = (char *)sqlite3_value_text(pVal); } sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); }else if( op==TK_STRING ){ - assert( !ExprHasProperty(pRight, EP_IntValue) ); - z = (u8*)pRight->u.zToken; + z = pRight->u.zToken; } if( z ){ - /* Count the number of prefix bytes prior to the first wildcard, - ** U+fffd character, or malformed utf-8. If the underlying database - ** has a UTF16LE encoding, then only consider ASCII characters. Note that - ** the encoding of z[] is UTF8 - we are dealing with only UTF8 here in this - ** code, but the database engine itself might be processing content using a - ** different encoding. */ + + /* If the RHS begins with a digit or a minus sign, then the LHS must + ** be an ordinary column (not a virtual table column) with TEXT affinity. + ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false + ** even though "lhs LIKE rhs" is true. But if the RHS does not start + ** with a digit or '-', then "lhs LIKE rhs" will always be false if + ** the LHS is numeric and so the optimization still works. + */ + if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || IsVirtual(pLeft->pTab) /* Value might be numeric */ + ){ + sqlite3ValueFree(pVal); + return 0; + } + } cnt = 0; while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; - if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){ - cnt++; - }else if( c>=0x80 ){ - const u8 *z2 = z+cnt-1; - if( c==0xff || sqlite3Utf8Read(&z2)==0xfffd /* bad utf-8 */ - || ENC(db)==SQLITE_UTF16LE - ){ - cnt--; - break; - }else{ - cnt = (int)(z2-z); - } - } - } - - /* The optimization is possible only if (1) the pattern does not begin - ** with a wildcard and if (2) the non-wildcard prefix does not end with - ** an (illegal 0xff) character, or (3) the pattern does not consist of - ** a single escape character. The second condition is necessary so - ** that we can increment the prefix key to find an upper bound for the - ** range search. The third is because the caller assumes that the pattern - ** consists of at least one character after all escapes have been - ** removed. */ - if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){ + } + if( cnt!=0 && 255!=(u8)z[cnt-1] ){ Expr *pPrefix; - - /* A "complete" match if the pattern ends with "*" or "%" */ - *pisComplete = c==wc[0] && z[cnt+1]==0 && ENC(db)!=SQLITE_UTF16LE; - - /* Get the pattern prefix. Remove all escapes from the prefix. */ - pPrefix = sqlite3Expr(db, TK_STRING, (char*)z); - if( pPrefix ){ - int iFrom, iTo; - char *zNew; - assert( !ExprHasProperty(pPrefix, EP_IntValue) ); - zNew = pPrefix->u.zToken; - zNew[cnt] = 0; - for(iFrom=iTo=0; iFrom0 ); - - /* If the LHS is not an ordinary column with TEXT affinity, then the - ** pattern prefix boundaries (both the start and end boundaries) must - ** not look like a number. Otherwise the pattern might be treated as - ** a number, which will invalidate the LIKE optimization. - ** - ** Getting this right has been a persistent source of bugs in the - ** LIKE optimization. See, for example: - ** 2018-09-10 https://sqlite.org/src/info/c94369cae9b561b1 - ** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28 - ** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07 - ** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975 - ** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a - */ - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || (ALWAYS( ExprUseYTab(pLeft) ) - && ALWAYS(pLeft->y.pTab) - && IsVirtual(pLeft->y.pTab)) /* Might be numeric */ - ){ - int isNum; - double rDummy; - isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); - if( isNum<=0 ){ - if( iTo==1 && zNew[0]=='-' ){ - isNum = +1; - }else{ - zNew[iTo-1]++; - isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); - zNew[iTo-1]--; - } - } - if( isNum>0 ){ - sqlite3ExprDelete(db, pPrefix); - sqlite3ValueFree(pVal); - return 0; - } - } - } + *pisComplete = c==wc[0] && z[cnt+1]==0; + pPrefix = sqlite3Expr(db, TK_STRING, z); + if( pPrefix ) pPrefix->u.zToken[cnt] = 0; *ppPrefix = pPrefix; - - /* If the RHS pattern is a bound parameter, make arrangements to - ** reprepare the statement when that parameter is rebound */ if( op==TK_VARIABLE ){ Vdbe *v = pParse->pVdbe; sqlite3VdbeSetVarmask(v, pRight->iColumn); - assert( !ExprHasProperty(pRight, EP_IntValue) ); if( *pisComplete && pRight->u.zToken[1] ){ /* If the rhs of the LIKE expression is a variable, and the current ** value of the variable means there is no need to invoke the LIKE ** function, then no OP_Variable will be added to the program. ** This causes problems for the sqlite3_bind_parameter_name() ** API. To work around them, add a dummy OP_Variable here. - */ + */ int r1 = sqlite3GetTempReg(pParse); sqlite3ExprCodeTarget(pParse, pRight, r1); sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0); sqlite3ReleaseTempReg(pParse, r1); } @@ -161827,143 +130188,52 @@ #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* -** Check to see if the pExpr expression is a form that needs to be passed -** to the xBestIndex method of virtual tables. Forms of interest include: -** -** Expression Virtual Table Operator -** ----------------------- --------------------------------- -** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH -** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB -** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE -** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP -** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE -** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE -** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT -** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT -** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL -** -** In every case, "column" must be a column of a virtual table. If there -** is a match, set *ppLeft to the "column" expression, set *ppRight to the -** "expr" expression (even though in forms (6) and (8) the column is on the -** right and the expression is on the left). Also set *peOp2 to the -** appropriate virtual table operator. The return value is 1 or 2 if there -** is a match. The usual return is 1, but if the RHS is also a column -** of virtual table in forms (5) or (7) then return 2. -** -** If the expression matches none of the patterns above, return 0. -*/ -static int isAuxiliaryVtabOperator( - sqlite3 *db, /* Parsing context */ +** Check to see if the given expression is of the form +** +** column OP expr +** +** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a +** column of a virtual table. +** +** If it is then return TRUE. If not, return FALSE. +*/ +static int isMatchOfColumn( Expr *pExpr, /* Test this expression */ - unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ - Expr **ppLeft, /* Column expression to left of MATCH/op2 */ - Expr **ppRight /* Expression to left of MATCH/op2 */ -){ - if( pExpr->op==TK_FUNCTION ){ - static const struct Op2 { - const char *zOp; - unsigned char eOp2; - } aOp[] = { - { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, - { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, - { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, - { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } - }; - ExprList *pList; - Expr *pCol; /* Column reference */ - int i; - - assert( ExprUseXList(pExpr) ); - pList = pExpr->x.pList; - if( pList==0 || pList->nExpr!=2 ){ - return 0; - } - - /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a - ** virtual table on their second argument, which is the same as - ** the left-hand side operand in their in-fix form. - ** - ** vtab_column MATCH expression - ** MATCH(expression,vtab_column) - */ - pCol = pList->a[1].pExpr; - assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) ); - if( ExprIsVtab(pCol) ){ - for(i=0; iu.zToken, aOp[i].zOp)==0 ){ - *peOp2 = aOp[i].eOp2; - *ppRight = pList->a[0].pExpr; - *ppLeft = pCol; - return 1; - } - } - } - - /* We can also match against the first column of overloaded - ** functions where xFindFunction returns a value of at least - ** SQLITE_INDEX_CONSTRAINT_FUNCTION. - ** - ** OVERLOADED(vtab_column,expression) - ** - ** Historically, xFindFunction expected to see lower-case function - ** names. But for this use case, xFindFunction is expected to deal - ** with function names in an arbitrary case. - */ - pCol = pList->a[0].pExpr; - assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) ); - assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) ); - if( ExprIsVtab(pCol) ){ - sqlite3_vtab *pVtab; - sqlite3_module *pMod; - void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); - void *pNotUsed; - pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; - assert( pVtab!=0 ); - assert( pVtab->pModule!=0 ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pMod = (sqlite3_module *)pVtab->pModule; - if( pMod->xFindFunction!=0 ){ - i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); - if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ - *peOp2 = i; - *ppRight = pList->a[1].pExpr; - *ppLeft = pCol; - return 1; - } - } - } - }else if( pExpr->op>=TK_EQ ){ - /* Comparison operators are a common case. Save a few comparisons for - ** that common case by terminating early. */ - assert( TK_NE < TK_EQ ); - assert( TK_ISNOT < TK_EQ ); - assert( TK_NOTNULL < TK_EQ ); - return 0; - }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ - int res = 0; - Expr *pLeft = pExpr->pLeft; - Expr *pRight = pExpr->pRight; - assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) ); - if( ExprIsVtab(pLeft) ){ - res++; - } - assert( pRight==0 || pRight->op!=TK_COLUMN - || (ExprUseYTab(pRight) && pRight->y.pTab!=0) ); - if( pRight && ExprIsVtab(pRight) ){ - res++; - SWAP(Expr*, pLeft, pRight); - } - *ppLeft = pLeft; - *ppRight = pRight; - if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE; - if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT; - if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL; - return res; + unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */ +){ + static const struct Op2 { + const char *zOp; + unsigned char eOp2; + } aOp[] = { + { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, + { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, + { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, + { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } + }; + ExprList *pList; + Expr *pCol; /* Column reference */ + int i; + + if( pExpr->op!=TK_FUNCTION ){ + return 0; + } + pList = pExpr->x.pList; + if( pList==0 || pList->nExpr!=2 ){ + return 0; + } + pCol = pList->a[1].pExpr; + if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ + return 0; + } + for(i=0; iu.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; + return 1; + } } return 0; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -161970,13 +130240,13 @@ /* ** If the pBase expression originated in the ON or USING clause of ** a join, then transfer the appropriate markings over to derived. */ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ - if( pDerived && ExprHasProperty(pBase, EP_OuterON|EP_InnerON) ){ - pDerived->flags |= pBase->flags & (EP_OuterON|EP_InnerON); - pDerived->w.iJoin = pBase->w.iJoin; + if( pDerived ){ + pDerived->flags |= pBase->flags & EP_FromJoin; + pDerived->iRightJoinTable = pBase->iRightJoinTable; } } /* ** Mark term iChild as being a child of term iParent @@ -162018,11 +130288,11 @@ ** x=y OR x=y --> x=y ** x<=y OR x x<=y ** ** The following is NOT generated: ** -** xy --> x!=y +** xy --> x!=y */ static void whereCombineDisjuncts( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* The complete WHERE clause */ WhereTerm *pOne, /* First disjunct */ @@ -162032,11 +130302,10 @@ sqlite3 *db; /* Database connection (for malloc) */ Expr *pNew; /* New virtual expression */ int op; /* Operator for the combined expression */ int idxNew; /* Index in pWC of the next virtual term */ - if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return; if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); @@ -162116,14 +130385,14 @@ ** ** WhereTerm.eOperator = WO_OR ** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T ** ** A subterm is "indexable" if it is of the form -** "T.C " where C is any column of table T and +** "T.C " where C is any column of table T and ** is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN". ** A subterm is also indexable if it is an AND of two or more -** subsubterms at least one of which is indexable. Indexable AND +** subsubterms at least one of which is indexable. Indexable AND ** subterms have their eOperator set to WO_AND and they have ** u.pAndInfo set to a dynamically allocated WhereAndTerm object. ** ** From another point of view, "indexable" means that the subterm could ** potentially be used with an index if an appropriate index exists. @@ -162201,22 +130470,21 @@ int j; Bitmask b = 0; pOrTerm->u.pAndInfo = pAndInfo; pOrTerm->wtFlags |= TERM_ANDINFO; pOrTerm->eOperator = WO_AND; - pOrTerm->leftCursor = -1; pAndWC = &pAndInfo->wc; memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic)); sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); sqlite3WhereExprAnalyze(pSrc, pAndWC); pAndWC->pOuter = pWC; if( !db->mallocFailed ){ for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ assert( pAndTerm->pExpr ); - if( allowedOp(pAndTerm->pExpr->op) - || pAndTerm->eOperator==WO_AUX + if( allowedOp(pAndTerm->pExpr->op) + || pAndTerm->eOperator==WO_MATCH ){ b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); } } } @@ -162244,15 +130512,11 @@ /* ** Record the set of tables that satisfy case 3. The set might be ** empty. */ pOrInfo->indexable = indexable; - pTerm->eOperator = WO_OR; - pTerm->leftCursor = -1; - if( indexable ){ - pWC->hasOr = 1; - } + pTerm->eOperator = indexable==0 ? 0 : WO_OR; /* For a two-way OR, attempt to implementation case 2. */ if( indexable && pOrWc->nTerm==2 ){ int iOne = 0; @@ -162298,15 +130562,14 @@ ** will be recorded in iCursor and iColumn. There might not be any ** such table and column. Set okToChngToIN if an appropriate table ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ - Expr *pLeft = 0; pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); - pOrTerm->wtFlags &= ~TERM_OK; + pOrTerm->wtFlags &= ~TERM_OR_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ assert( j==1 ); continue; @@ -162313,21 +130576,19 @@ } if( (chngToIN & sqlite3WhereGetMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){ /* This term must be of the form t1.a==t2.b where t2 is in the ** chngToIN set but t1 is not. This term will be either preceded - ** or followed by an inverted copy (t2.b==t1.a). Skip this term + ** or follwed by an inverted copy (t2.b==t1.a). Skip this term ** and use its inversion. */ testcase( pOrTerm->wtFlags & TERM_COPIED ); testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); continue; } - assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); - iColumn = pOrTerm->u.x.leftColumn; + iColumn = pOrTerm->u.leftColumn; iCursor = pOrTerm->leftCursor; - pLeft = pOrTerm->pExpr->pLeft; break; } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ @@ -162341,16 +130602,13 @@ /* We have found a candidate table and column. Check to see if that ** table and column is common to every term in the OR clause */ okToChngToIN = 1; for(; i>=0 && okToChngToIN; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); - assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); if( pOrTerm->leftCursor!=iCursor ){ - pOrTerm->wtFlags &= ~TERM_OK; - }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR - && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1) - )){ + pOrTerm->wtFlags &= ~TERM_OR_OK; + }else if( pOrTerm->u.leftColumn!=iColumn ){ okToChngToIN = 0; }else{ int affLeft, affRight; /* If the right-hand side is also a column, then the affinities ** of both right and left sides must be such that no type @@ -162359,32 +130617,31 @@ affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); if( affRight!=0 && affRight!=affLeft ){ okToChngToIN = 0; }else{ - pOrTerm->wtFlags |= TERM_OK; + pOrTerm->wtFlags |= TERM_OR_OK; } } } } /* At this point, okToChngToIN is true if original pTerm satisfies - ** case 1. In that case, construct a new virtual term that is + ** case 1. In that case, construct a new virtual term that is ** pTerm converted into an IN operator. */ if( okToChngToIN ){ Expr *pDup; /* A transient duplicate expression */ ExprList *pList = 0; /* The RHS of the IN operator */ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ - if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue; + if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; assert( pOrTerm->eOperator & WO_EQ ); - assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); assert( pOrTerm->leftCursor==iCursor ); - assert( pOrTerm->u.x.leftColumn==iColumn ); + assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); @@ -162391,20 +130648,21 @@ pDup = sqlite3ExprDup(db, pLeft, 0); pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); if( pNew ){ int idxNew; transferJoinMarkings(pNew, pExpr); - assert( ExprUseXList(pNew) ); + assert( !ExprHasProperty(pNew, EP_xIsSelect) ); pNew->x.pList = pList; idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); - /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */ + pTerm = &pWC->a[idxTerm]; markTermAsChild(pWC, idxNew, idxTerm); }else{ sqlite3ExprListDelete(db, pList); } + pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ @@ -162424,23 +130682,28 @@ ** returned when it should not be, then incorrect answers might result. */ static int termIsEquivalence(Parse *pParse, Expr *pExpr){ char aff1, aff2; CollSeq *pColl; + const char *zColl1, *zColl2; if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; - if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; + if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; aff1 = sqlite3ExprAffinity(pExpr->pLeft); aff2 = sqlite3ExprAffinity(pExpr->pRight); if( aff1!=aff2 && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2)) ){ return 0; } - pColl = sqlite3ExprCompareCollSeq(pParse, pExpr); - if( sqlite3IsBinary(pColl) ) return 1; - return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight); + pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); + if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; + pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); + zColl1 = pColl ? pColl->zName : 0; + pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); + zColl2 = pColl ? pColl->zName : 0; + return sqlite3_stricmp(zColl1, zColl2)==0; } /* ** Recursively walk the expressions of a SELECT statement and generate ** a bitmask indicating which tables are used in that expression @@ -162456,19 +130719,12 @@ mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere); mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving); if( ALWAYS(pSrc!=0) ){ int i; for(i=0; inSrc; i++){ - if( pSrc->a[i].fg.isSubquery ){ - mask |= exprSelectUsage(pMaskSet, pSrc->a[i].u4.pSubq->pSelect); - } - if( pSrc->a[i].fg.isUsing==0 ){ - mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn); - } - if( pSrc->a[i].fg.isTabFunc ){ - mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg); - } + mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect); + mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn); } } pS = pS->pPrior; } return mask; @@ -162487,72 +130743,58 @@ ** true even if that particular column is not indexed, because the column ** might be added to an automatic index later. */ static SQLITE_NOINLINE int exprMightBeIndexed2( SrcList *pFrom, /* The FROM clause */ + Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ int *aiCurCol, /* Write the referenced table cursor and column here */ - Expr *pExpr, /* An operand of a comparison operator */ - int j /* Start looking with the j-th pFrom entry */ + Expr *pExpr /* An operand of a comparison operator */ ){ Index *pIdx; int i; int iCur; - do{ - iCur = pFrom->a[j].iCursor; - for(pIdx=pFrom->a[j].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->aColExpr==0 ) continue; - for(i=0; inKeyCol; i++){ - if( pIdx->aiColumn[i]!=XN_EXPR ) continue; - assert( pIdx->bHasExpr ); - if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 - && !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr) - ){ - aiCurCol[0] = iCur; - aiCurCol[1] = XN_EXPR; - return 1; - } - } - } - }while( ++j < pFrom->nSrc ); + for(i=0; mPrereq>1; i++, mPrereq>>=1){} + iCur = pFrom->a[i].iCursor; + for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->aColExpr==0 ) continue; + for(i=0; inKeyCol; i++){ + if( pIdx->aiColumn[i]!=XN_EXPR ) continue; + if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ + aiCurCol[0] = iCur; + aiCurCol[1] = XN_EXPR; + return 1; + } + } + } return 0; } static int exprMightBeIndexed( SrcList *pFrom, /* The FROM clause */ + Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ int *aiCurCol, /* Write the referenced table cursor & column here */ Expr *pExpr, /* An operand of a comparison operator */ int op /* The specific comparison operator */ ){ - int i; - - /* If this expression is a vector to the left or right of a - ** inequality constraint (>, <, >= or <=), perform the processing + /* If this expression is a vector to the left or right of a + ** inequality constraint (>, <, >= or <=), perform the processing ** on the first element of the vector. */ assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE ); assert( TK_ISop==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ - assert( ExprUseXList(pExpr) ); pExpr = pExpr->x.pList->a[0].pExpr; } if( pExpr->op==TK_COLUMN ){ aiCurCol[0] = pExpr->iTable; aiCurCol[1] = pExpr->iColumn; return 1; } - - for(i=0; inSrc; i++){ - Index *pIdx; - for(pIdx=pFrom->a[i].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->aColExpr ){ - return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i); - } - } - } - return 0; -} - + if( mPrereq==0 ) return 0; /* No table references */ + if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */ + return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr); +} /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm @@ -162577,86 +130819,55 @@ ){ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ WhereTerm *pTerm; /* The term to be analyzed */ WhereMaskSet *pMaskSet; /* Set of table index masks */ Expr *pExpr; /* The expression to be analyzed */ - Bitmask prereqLeft; /* Prerequisites of the pExpr->pLeft */ - Bitmask prereqAll; /* Prerequisites of pExpr */ + Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ + Bitmask prereqAll; /* Prerequesites of pExpr */ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ int noCase = 0; /* uppercase equivalent to lowercase */ int op; /* Top-level operator. pExpr->op */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection */ - unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */ + unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */ int nLeft; /* Number of elements on left side vector */ if( db->mallocFailed ){ return; } - assert( pWC->nTerm > idxTerm ); pTerm = &pWC->a[idxTerm]; pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; - assert( pExpr!=0 ); /* Because malloc() has not failed */ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); - pMaskSet->bVarSelect = 0; prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); if( sqlite3ExprCheckIN(pParse, pExpr) ) return; - if( ExprUseXSelect(pExpr) ){ + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); }else{ pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); } - prereqAll = prereqLeft | pTerm->prereqRight; + }else if( op==TK_ISNULL ){ + pTerm->prereqRight = 0; }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); - if( pExpr->pLeft==0 - || ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow) - || pExpr->x.pList!=0 - ){ - prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); - }else{ - prereqAll = prereqLeft | pTerm->prereqRight; - } - } + } + pMaskSet->bVarSelect = 0; + prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr); if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; - -#ifdef SQLITE_DEBUG - if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){ - printf("\n*** Incorrect prereqAll computed for:\n"); - sqlite3TreeViewExpr(0,pExpr,0); - assert( 0 ); - } -#endif - - if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){ - Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin); - if( ExprHasProperty(pExpr, EP_OuterON) ){ - prereqAll |= x; - extraRight = x-1; /* ON clause terms may not be used with an index - ** on left table of a LEFT JOIN. Ticket #3015 */ - if( (prereqAll>>1)>=x ){ - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); - return; - } - }else if( (prereqAll>>1)>=x ){ - /* The ON clause of an INNER JOIN references a table to its right. - ** Most other SQL database engines raise an error. But SQLite versions - ** 3.0 through 3.38 just put the ON clause constraint into the WHERE - ** clause and carried on. Beginning with 3.39, raise an error only - ** if there is a RIGHT or FULL JOIN in the query. This makes SQLite - ** more like other systems, and also preserves legacy. */ - if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); - return; - } - ExprClearProperty(pExpr, EP_InnerON); + if( ExprHasProperty(pExpr, EP_FromJoin) ){ + Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); + prereqAll |= x; + extraRight = x-1; /* ON clause terms may not be used with an index + ** on left table of a LEFT JOIN. Ticket #3015 */ + if( (prereqAll>>1)>=x ){ + sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); + return; } } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; @@ -162665,32 +130876,29 @@ int aiCurCol[2]; Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; - if( pTerm->u.x.iField>0 ){ + if( pTerm->iField>0 ){ assert( op==TK_IN ); assert( pLeft->op==TK_VECTOR ); - assert( ExprUseXList(pLeft) ); - pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr; + pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr; } - if( exprMightBeIndexed(pSrc, aiCurCol, pLeft, op) ){ + if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){ pTerm->leftCursor = aiCurCol[0]; - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - pTerm->u.x.leftColumn = aiCurCol[1]; + pTerm->u.leftColumn = aiCurCol[1]; pTerm->eOperator = operatorMask(op) & opMask; } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; - if( pRight - && exprMightBeIndexed(pSrc, aiCurCol, pRight, op) - && !ExprHasProperty(pRight, EP_FixedCol) + if( pRight + && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op) ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ - assert( pTerm->u.x.iField==0 ); + assert( pTerm->iField==0 ); if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite3ExprDup(db, pExpr, 0); if( db->mallocFailed ){ sqlite3ExprDelete(db, pDup); @@ -162710,29 +130918,17 @@ } }else{ pDup = pExpr; pNew = pTerm; } - pNew->wtFlags |= exprCommute(pParse, pDup); + exprCommute(pParse, pDup); pNew->leftCursor = aiCurCol[0]; - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - pNew->u.x.leftColumn = aiCurCol[1]; + pNew->u.leftColumn = aiCurCol[1]; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; - }else - if( op==TK_ISNULL - && !ExprHasProperty(pExpr,EP_OuterON) - && 0==sqlite3ExprCanBeNull(pLeft) - ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pExpr->op = TK_TRUEFALSE; /* See tag-20230504-1 */ - pExpr->u.zToken = "false"; - ExprSetProperty(pExpr, EP_IsFalse); - pTerm->prereqAll = 0; - pTerm->eOperator = 0; } } #ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION /* If a term is the BETWEEN operator, create two new virtual terms @@ -162749,21 +130945,19 @@ ** term. That means that if the BETWEEN term is coded, the children are ** skipped. Or, if the children are satisfied by an index, the original ** BETWEEN term is skipped. */ else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){ - ExprList *pList; + ExprList *pList = pExpr->x.pList; int i; static const u8 ops[] = {TK_GE, TK_LE}; - assert( ExprUseXList(pExpr) ); - pList = pExpr->x.pList; assert( pList!=0 ); assert( pList->nExpr==2 ); for(i=0; i<2; i++){ Expr *pNewExpr; int idxNew; - pNewExpr = sqlite3PExpr(pParse, ops[i], + pNewExpr = sqlite3PExpr(pParse, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0), sqlite3ExprDup(db, pList->a[i].pExpr, 0)); transferJoinMarkings(pNewExpr, pExpr); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); @@ -162782,46 +130976,10 @@ assert( pWC->op==TK_AND ); exprAnalyzeOrTerm(pSrc, pWC, idxTerm); pTerm = &pWC->a[idxTerm]; } #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ - /* The form "x IS NOT NULL" can sometimes be evaluated more efficiently - ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a - ** virtual term of that form. - ** - ** The virtual term must be tagged with TERM_VNULL. - */ - else if( pExpr->op==TK_NOTNULL ){ - if( pExpr->pLeft->op==TK_COLUMN - && pExpr->pLeft->iColumn>=0 - && !ExprHasProperty(pExpr, EP_OuterON) - ){ - Expr *pNewExpr; - Expr *pLeft = pExpr->pLeft; - int idxNew; - WhereTerm *pNewTerm; - - pNewExpr = sqlite3PExpr(pParse, TK_GT, - sqlite3ExprDup(db, pLeft, 0), - sqlite3ExprAlloc(db, TK_NULL, 0, 0)); - - idxNew = whereClauseInsert(pWC, pNewExpr, - TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); - if( idxNew ){ - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = 0; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.x.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_GT; - markTermAsChild(pWC, idxNew, idxTerm); - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; - } - } - } - #ifndef SQLITE_OMIT_LIKE_OPTIMIZATION /* Add constraints to reduce the search space on a LIKE or GLOB ** operator. ** @@ -162833,12 +130991,11 @@ ** termination condition "abd". If case is not significant (the default ** for LIKE) then the lower-bound is made all uppercase and the upper- ** bound is made all lowercase so that the bounds also work when comparing ** BLOBs. */ - else if( pExpr->op==TK_FUNCTION - && pWC->op==TK_AND + if( pWC->op==TK_AND && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; @@ -162846,16 +131003,12 @@ int idxNew1; int idxNew2; const char *zCollSeqName; /* Name of collating sequence */ const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC; - assert( ExprUseXList(pExpr) ); pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite3ExprDup(db, pStr1, 0); - assert( pStr1==0 || !ExprHasProperty(pStr1, EP_IntValue) ); - assert( pStr2==0 || !ExprHasProperty(pStr2, EP_IntValue) ); - /* Convert the lower bound to upper-case and the upper bound to ** lower-case (upper-case is less than lower-case in ASCII) so that ** the range constraints also work for BLOBs */ @@ -162868,164 +131021,180 @@ pStr2->u.zToken[i] = sqlite3Tolower(c); } } if( !db->mallocFailed ){ - u8 *pC; /* Last character before the first wildcard */ + u8 c, *pC; /* Last character before the first wildcard */ pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; + c = *pC; if( noCase ){ /* The point is to increment the last character before the first ** wildcard. But if we increment '@', that will push it into the - ** alphabetic range where case conversions will mess up the + ** alphabetic range where case conversions will mess up the ** inequality. To avoid this, make sure to also run the full ** LIKE on all candidate expressions by clearing the isComplete flag */ - if( *pC=='A'-1 ) isComplete = 0; - *pC = sqlite3UpperToLower[*pC]; - } - - /* Increment the value of the last utf8 character in the prefix. */ - while( *pC==0xBF && pC>(u8*)pStr2->u.zToken ){ - *pC = 0x80; - pC--; - } - assert( *pC!=0xFF ); /* isLikeOrGlob() guarantees this */ - (*pC)++; - } - zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY; + if( c=='A'-1 ) isComplete = 0; + c = sqlite3UpperToLower[c]; + } + *pC = c + 1; + } + zCollSeqName = noCase ? "NOCASE" : "BINARY"; pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), pStr1); transferJoinMarkings(pNewExpr1, pExpr); idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); + exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), pStr2); transferJoinMarkings(pNewExpr2, pExpr); idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); - exprAnalyze(pSrc, pWC, idxNew1); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; if( isComplete ){ markTermAsChild(pWC, idxNew1, idxTerm); markTermAsChild(pWC, idxNew2, idxTerm); } } #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Add a WO_MATCH auxiliary term to the constraint set if the + ** current expression is of the form: column MATCH expr. + ** This information is used by the xBestIndex methods of + ** virtual tables. The native query optimizer does not attempt + ** to do anything with MATCH functions. + */ + if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){ + int idxNew; + Expr *pRight, *pLeft; + WhereTerm *pNewTerm; + Bitmask prereqColumn, prereqExpr; + + pRight = pExpr->x.pList->a[0].pExpr; + pLeft = pExpr->x.pList->a[1].pExpr; + prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); + prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); + if( (prereqExpr & prereqColumn)==0 ){ + Expr *pNewExpr; + pNewExpr = sqlite3PExpr(pParse, TK_MATCH, + 0, sqlite3ExprDup(db, pRight, 0)); + if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ + ExprSetProperty(pNewExpr, EP_FromJoin); + } + idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + pNewTerm = &pWC->a[idxNew]; + pNewTerm->prereqRight = prereqExpr; + pNewTerm->leftCursor = pLeft->iTable; + pNewTerm->u.leftColumn = pLeft->iColumn; + pNewTerm->eOperator = WO_MATCH; + pNewTerm->eMatchOp = eOp2; + markTermAsChild(pWC, idxNew, idxTerm); + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags |= TERM_COPIED; + pNewTerm->prereqAll = pTerm->prereqAll; + } + } +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create ** new terms for each component comparison - "a = ?" and "b = ?". The ** new terms completely replace the original vector comparison, which is ** no longer used. ** ** This is only required if at least one side of the comparison operation - ** is not a sub-select. - ** - ** tag-20220128a - */ - if( (pExpr->op==TK_EQ || pExpr->op==TK_IS) - && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 - && sqlite3ExprVectorSize(pExpr->pRight)==nLeft - && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 - || (pExpr->pRight->flags & EP_xIsSelect)==0) - && pWC->op==TK_AND - ){ - int i; - for(i=0; ipLeft, i, nLeft); - Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft); - - pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); - transferJoinMarkings(pNew, pExpr); - idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE); - exprAnalyze(pSrc, pWC, idxNew); - } - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */ - pTerm->eOperator = WO_ROWVAL; - } - - /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create - ** a virtual term for each vector component. The expression object - ** used by each such virtual term is pExpr (the full vector IN(...) - ** expression). The WhereTerm.u.x.iField variable identifies the index within - ** the vector on the LHS that the virtual term represents. - ** - ** This only works if the RHS is a simple SELECT (not a compound) that does - ** not use window functions. - */ - else if( pExpr->op==TK_IN - && pTerm->u.x.iField==0 - && pExpr->pLeft->op==TK_VECTOR - && ALWAYS( ExprUseXSelect(pExpr) ) - && (pExpr->x.pSelect->pPrior==0 || (pExpr->x.pSelect->selFlags & SF_Values)) -#ifndef SQLITE_OMIT_WINDOWFUNC - && pExpr->x.pSelect->pWin==0 -#endif - && pWC->op==TK_AND - ){ - int i; - for(i=0; ipLeft); i++){ - int idxNew; - idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE); - pWC->a[idxNew].u.x.iField = i+1; - exprAnalyze(pSrc, pWC, idxNew); - markTermAsChild(pWC, idxNew, idxTerm); - } - } - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Add a WO_AUX auxiliary term to the constraint set if the - ** current expression is of the form "column OP expr" where OP - ** is an operator that gets passed into virtual tables but which is - ** not normally optimized for ordinary tables. In other words, OP - ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL. - ** This information is used by the xBestIndex methods of - ** virtual tables. The native query optimizer does not attempt - ** to do anything with MATCH functions. - */ - else if( pWC->op==TK_AND ){ - Expr *pRight = 0, *pLeft = 0; - int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); - while( res-- > 0 ){ - int idxNew; - WhereTerm *pNewTerm; - Bitmask prereqColumn, prereqExpr; - - prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); - prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); - if( (prereqExpr & prereqColumn)==0 ){ - Expr *pNewExpr; - pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, sqlite3ExprDup(db, pRight, 0)); - if( ExprHasProperty(pExpr, EP_OuterON) && pNewExpr ){ - ExprSetProperty(pNewExpr, EP_OuterON); - pNewExpr->w.iJoin = pExpr->w.iJoin; - } - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = prereqExpr; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.x.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_AUX; - pNewTerm->eMatchOp = eOp2; - markTermAsChild(pWC, idxNew, idxTerm); - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; - } - SWAP(Expr*, pLeft, pRight); - } - } -#endif /* SQLITE_OMIT_VIRTUALTABLE */ + ** is not a sub-select. */ + if( pWC->op==TK_AND + && (pExpr->op==TK_EQ || pExpr->op==TK_IS) + && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 + && sqlite3ExprVectorSize(pExpr->pRight)==nLeft + && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 + || (pExpr->pRight->flags & EP_xIsSelect)==0) + ){ + int i; + for(i=0; ipLeft, i); + Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); + + pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); + transferJoinMarkings(pNew, pExpr); + idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); + } + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->eOperator = 0; + } + + /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create + ** a virtual term for each vector component. The expression object + ** used by each such virtual term is pExpr (the full vector IN(...) + ** expression). The WhereTerm.iField variable identifies the index within + ** the vector on the LHS that the virtual term represents. + ** + ** This only works if the RHS is a simple SELECT, not a compound + */ + if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0 + && pExpr->pLeft->op==TK_VECTOR + && pExpr->x.pSelect->pPrior==0 + ){ + int i; + for(i=0; ipLeft); i++){ + int idxNew; + idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); + pWC->a[idxNew].iField = i+1; + exprAnalyze(pSrc, pWC, idxNew); + markTermAsChild(pWC, idxNew, idxTerm); + } + } + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* When sqlite_stat3 histogram data is available an operator of the + ** form "x IS NOT NULL" can sometimes be evaluated more efficiently + ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a + ** virtual term of that form. + ** + ** Note that the virtual term must be tagged with TERM_VNULL. + */ + if( pExpr->op==TK_NOTNULL + && pExpr->pLeft->op==TK_COLUMN + && pExpr->pLeft->iColumn>=0 + && OptimizationEnabled(db, SQLITE_Stat34) + ){ + Expr *pNewExpr; + Expr *pLeft = pExpr->pLeft; + int idxNew; + WhereTerm *pNewTerm; + + pNewExpr = sqlite3PExpr(pParse, TK_GT, + sqlite3ExprDup(db, pLeft, 0), + sqlite3ExprAlloc(db, TK_NULL, 0, 0)); + + idxNew = whereClauseInsert(pWC, pNewExpr, + TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); + if( idxNew ){ + pNewTerm = &pWC->a[idxNew]; + pNewTerm->prereqRight = 0; + pNewTerm->leftCursor = pLeft->iTable; + pNewTerm->u.leftColumn = pLeft->iColumn; + pNewTerm->eOperator = WO_GT; + markTermAsChild(pWC, idxNew, idxTerm); + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags |= TERM_COPIED; + pNewTerm->prereqAll = pTerm->prereqAll; + } + } +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ testcase( pTerm!=&pWC->a[idxTerm] ); @@ -163054,151 +131223,31 @@ ** In the previous sentence and in the diagram, "slot[]" refers to ** the WhereClause.a[] array. The slot[] array grows as needed to contain ** all terms of the WHERE clause. */ SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ - Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr); + Expr *pE2 = sqlite3ExprSkipCollate(pExpr); pWC->op = op; - assert( pE2!=0 || pExpr==0 ); if( pE2==0 ) return; if( pE2->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ sqlite3WhereSplit(pWC, pE2->pLeft, op); sqlite3WhereSplit(pWC, pE2->pRight, op); } } -/* -** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or -** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the -** where-clause passed as the first argument. The value for the term -** is found in register iReg. -** -** In the common case where the value is a simple integer -** (example: "LIMIT 5 OFFSET 10") then the expression codes as a -** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value(). -** If not, then it codes as a TK_REGISTER expression. -*/ -static void whereAddLimitExpr( - WhereClause *pWC, /* Add the constraint to this WHERE clause */ - int iReg, /* Register that will hold value of the limit/offset */ - Expr *pExpr, /* Expression that defines the limit/offset */ - int iCsr, /* Cursor to which the constraint applies */ - int eMatchOp /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */ -){ - Parse *pParse = pWC->pWInfo->pParse; - sqlite3 *db = pParse->db; - Expr *pNew; - int iVal = 0; - - if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){ - Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0); - if( pVal==0 ) return; - ExprSetProperty(pVal, EP_IntValue); - pVal->u.iValue = iVal; - pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); - }else{ - Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0); - if( pVal==0 ) return; - pVal->iTable = iReg; - pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); - } - if( pNew ){ - WhereTerm *pTerm; - int idx; - idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL); - pTerm = &pWC->a[idx]; - pTerm->leftCursor = iCsr; - pTerm->eOperator = WO_AUX; - pTerm->eMatchOp = eMatchOp; - } -} - -/* -** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the -** SELECT statement passed as the second argument. These terms are only -** added if: -** -** 1. The SELECT statement has a LIMIT clause, and -** 2. The SELECT statement is not an aggregate or DISTINCT query, and -** 3. The SELECT statement has exactly one object in its from clause, and -** that object is a virtual table, and -** 4. There are no terms in the WHERE clause that will not be passed -** to the virtual table xBestIndex method. -** 5. The ORDER BY clause, if any, will be made available to the xBestIndex -** method. -** -** LIMIT and OFFSET terms are ignored by most of the planner code. They -** exist only so that they may be passed to the xBestIndex method of the -** single virtual table in the FROM clause of the SELECT. -*/ -SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){ - assert( p!=0 && p->pLimit!=0 ); /* 1 -- checked by caller */ - if( p->pGroupBy==0 - && (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */ - && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pSTab)) /* 3 */ - ){ - ExprList *pOrderBy = p->pOrderBy; - int iCsr = p->pSrc->a[0].iCursor; - int ii; - - /* Check condition (4). Return early if it is not met. */ - for(ii=0; iinTerm; ii++){ - if( pWC->a[ii].wtFlags & TERM_CODED ){ - /* This term is a vector operation that has been decomposed into - ** other, subsequent terms. It can be ignored. See tag-20220128a */ - assert( pWC->a[ii].wtFlags & TERM_VIRTUAL ); - assert( pWC->a[ii].eOperator==WO_ROWVAL ); - continue; - } - if( pWC->a[ii].nChild ){ - /* If this term has child terms, then they are also part of the - ** pWC->a[] array. So this term can be ignored, as a LIMIT clause - ** will only be added if each of the child terms passes the - ** (leftCursor==iCsr) test below. */ - continue; - } - if( pWC->a[ii].leftCursor!=iCsr ) return; - if( pWC->a[ii].prereqRight!=0 ) return; - } - - /* Check condition (5). Return early if it is not met. */ - if( pOrderBy ){ - for(ii=0; iinExpr; ii++){ - Expr *pExpr = pOrderBy->a[ii].pExpr; - if( pExpr->op!=TK_COLUMN ) return; - if( pExpr->iTable!=iCsr ) return; - if( pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) return; - } - } - - /* All conditions are met. Add the terms to the where-clause object. */ - assert( p->pLimit->op==TK_LIMIT ); - if( p->iOffset!=0 && (p->selFlags & SF_Compound)==0 ){ - whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight, - iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET); - } - if( p->iOffset==0 || (p->selFlags & SF_Compound)==0 ){ - whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, - iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); - } - } -} - /* ** Initialize a preallocated WhereClause structure. */ SQLITE_PRIVATE void sqlite3WhereClauseInit( WhereClause *pWC, /* The WhereClause to be initialized */ WhereInfo *pWInfo /* The WHERE processing context */ ){ pWC->pWInfo = pWInfo; - pWC->hasOr = 0; pWC->pOuter = 0; pWC->nTerm = 0; - pWC->nBase = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; } /* @@ -163205,112 +131254,54 @@ ** Deallocate a WhereClause structure. The WhereClause structure ** itself is not freed. This routine is the inverse of ** sqlite3WhereClauseInit(). */ SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ + int i; + WhereTerm *a; sqlite3 *db = pWC->pWInfo->pParse->db; - assert( pWC->nTerm>=pWC->nBase ); - if( pWC->nTerm>0 ){ - WhereTerm *a = pWC->a; - WhereTerm *aLast = &pWC->a[pWC->nTerm-1]; -#ifdef SQLITE_DEBUG - int i; - /* Verify that every term past pWC->nBase is virtual */ - for(i=pWC->nBase; inTerm; i++){ - assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 ); - } -#endif - while(1){ - assert( a->eMatchOp==0 || a->eOperator==WO_AUX ); - if( a->wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, a->pExpr); - } - if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){ - if( a->wtFlags & TERM_ORINFO ){ - assert( (a->wtFlags & TERM_ANDINFO)==0 ); - whereOrInfoDelete(db, a->u.pOrInfo); - }else{ - assert( (a->wtFlags & TERM_ANDINFO)!=0 ); - whereAndInfoDelete(db, a->u.pAndInfo); - } - } - if( a==aLast ) break; - a++; - } + for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ + if( a->wtFlags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, a->pExpr); + } + if( a->wtFlags & TERM_ORINFO ){ + whereOrInfoDelete(db, a->u.pOrInfo); + }else if( a->wtFlags & TERM_ANDINFO ){ + whereAndInfoDelete(db, a->u.pAndInfo); + } + } + if( pWC->a!=pWC->aStatic ){ + sqlite3DbFree(db, pWC->a); } } /* ** These routines walk (recursively) an expression tree and generate ** a bitmask indicating which tables are used in that expression ** tree. -** -** sqlite3WhereExprUsage(MaskSet, Expr) -> -** -** Return a Bitmask of all tables referenced by Expr. Expr can be -** be NULL, in which case 0 is returned. -** -** sqlite3WhereExprUsageNN(MaskSet, Expr) -> -** -** Same as sqlite3WhereExprUsage() except that Expr must not be -** NULL. The "NN" suffix on the name stands for "Not Null". -** -** sqlite3WhereExprListUsage(MaskSet, ExprList) -> -** -** Return a Bitmask of all tables referenced by every expression -** in the expression list ExprList. ExprList can be NULL, in which -** case 0 is returned. -** -** sqlite3WhereExprUsageFull(MaskSet, ExprList) -> -** -** Internal use only. Called only by sqlite3WhereExprUsageNN() for -** complex expressions that require pushing register values onto -** the stack. Many calls to sqlite3WhereExprUsageNN() do not need -** the more complex analysis done by this routine. Hence, the -** computations done by this routine are broken out into a separate -** "no-inline" function to avoid the stack push overhead in the -** common case where it is not needed. */ -static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull( - WhereMaskSet *pMaskSet, - Expr *p -){ +SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ Bitmask mask; + if( p==0 ) return 0; + if( p->op==TK_COLUMN ){ + return sqlite3WhereGetMask(pMaskSet, p->iTable); + } mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; - if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); + assert( !ExprHasProperty(p, EP_TokenOnly) ); + if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); if( p->pRight ){ - mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight); + mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight); assert( p->x.pList==0 ); - }else if( ExprUseXSelect(p) ){ + }else if( ExprHasProperty(p, EP_xIsSelect) ){ if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; mask |= exprSelectUsage(pMaskSet, p->x.pSelect); }else if( p->x.pList ){ mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && ExprUseYWin(p) ){ - assert( p->y.pWin!=0 ); - mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition); - mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy); - mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter); - } -#endif return mask; } -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ - if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ - return sqlite3WhereGetMask(pMaskSet, p->iTable); - }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ - assert( p->op!=TK_IF_NULL_ROW ); - return 0; - } - return sqlite3WhereExprUsageFull(pMaskSet, p); -} -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ - return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; -} SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){ int i; Bitmask mask = 0; if( pList ){ for(i=0; inExpr; i++){ @@ -163320,11 +131311,11 @@ return mask; } /* -** Call exprAnalyze on all terms in a WHERE clause. +** Call exprAnalyze on all terms in a WHERE clause. ** ** Note that exprAnalyze() might add new virtual terms onto the ** end of the WHERE clause. We do not want to analyze these new ** virtual terms, so start analyzing at the end and work forward ** so that the added virtual terms are never processed. @@ -163339,33 +131330,31 @@ } } /* ** For table-valued-functions, transform the function arguments into -** new WHERE clause terms. +** new WHERE clause terms. ** ** Each function argument translates into an equality constraint against ** a HIDDEN column in the table. */ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( Parse *pParse, /* Parsing context */ - SrcItem *pItem, /* The FROM clause term to process */ + struct SrcList_item *pItem, /* The FROM clause term to process */ WhereClause *pWC /* Xfer function arguments to here */ ){ Table *pTab; int j, k; ExprList *pArgs; Expr *pColRef; Expr *pTerm; if( pItem->fg.isTabFunc==0 ) return; - pTab = pItem->pSTab; + pTab = pItem->pTab; assert( pTab!=0 ); pArgs = pItem->u1.pFuncArg; if( pArgs==0 ) return; for(j=k=0; jnExpr; j++){ - Expr *pRhs; - u32 joinType; while( knCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} if( k>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", pTab->zName, j); return; @@ -163372,25 +131361,13 @@ } pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; - assert( ExprUseYTab(pColRef) ); - pColRef->y.pTab = pTab; - pItem->colUsed |= sqlite3ExprColUsed(pColRef); - pRhs = sqlite3PExpr(pParse, TK_UPLUS, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); - pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); - if( pItem->fg.jointype & (JT_LEFT|JT_RIGHT) ){ - testcase( pItem->fg.jointype & JT_LEFT ); /* testtag-20230227a */ - testcase( pItem->fg.jointype & JT_RIGHT ); /* testtag-20230227b */ - joinType = EP_OuterON; - }else{ - testcase( pItem->fg.jointype & JT_LTORJ ); /* testtag-20230227c */ - joinType = EP_InnerON; - } - sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType); + pColRef->pTab = pTab; + pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, + sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } /************** End of whereexpr.c *******************************************/ @@ -163414,33 +131391,18 @@ ** indices, you might also think of this module as the "query optimizer". */ /* #include "sqliteInt.h" */ /* #include "whereInt.h" */ -/* -** Extra information appended to the end of sqlite3_index_info but not -** visible to the xBestIndex function, at least not directly. The -** sqlite3_vtab_collation() interface knows how to reach it, however. -** -** This object is not an API and can be changed from one release to the -** next. As long as allocateIndexInfo() and sqlite3_vtab_collation() -** agree on the structure, all will be well. -*/ -typedef struct HiddenIndexInfo HiddenIndexInfo; -struct HiddenIndexInfo { - WhereClause *pWC; /* The Where clause being analyzed */ - Parse *pParse; /* The parsing context */ - int eDistinct; /* Value to return from sqlite3_vtab_distinct() */ - u32 mIn; /* Mask of terms that are IN (...) */ - u32 mHandleIn; /* Terms that vtab will handle as IN (...) */ - sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST - ** because extra space is allocated to hold up - ** to nTerm such values */ -}; - /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); + +/* Test variable that can be set to enable WHERE tracing */ +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +/***/ int sqlite3WhereTrace = 0; +#endif + /* ** Return the estimated number of output rows from a WHERE clause */ SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ @@ -163454,80 +131416,27 @@ SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ return pWInfo->eDistinct; } /* -** Return the number of ORDER BY terms that are satisfied by the -** WHERE clause. A return of 0 means that the output must be -** completely sorted. A return equal to the number of ORDER BY -** terms means that no sorting is needed at all. A return that -** is positive but less than the number of ORDER BY terms means that -** block sorting is required. +** Return TRUE if the WHERE clause returns rows in ORDER BY order. +** Return FALSE if the output needs to be sorted. */ SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ - return pWInfo->nOBSat<0 ? 0 : pWInfo->nOBSat; -} - -/* -** In the ORDER BY LIMIT optimization, if the inner-most loop is known -** to emit rows in increasing order, and if the last row emitted by the -** inner-most loop did not fit within the sorter, then we can skip all -** subsequent rows for the current iteration of the inner loop (because they -** will not fit in the sorter either) and continue with the second inner -** loop - the loop immediately outside the inner-most. -** -** When a row does not fit in the sorter (because the sorter already -** holds LIMIT+OFFSET rows that are smaller), then a jump is made to the -** label returned by this function. -** -** If the ORDER BY LIMIT optimization applies, the jump destination should -** be the continuation for the second-inner-most loop. If the ORDER BY -** LIMIT optimization does not apply, then the jump destination should -** be the continuation for the inner-most loop. -** -** It is always safe for this routine to return the continuation of the -** inner-most loop, in the sense that a correct answer will result. -** Returning the continuation the second inner loop is an optimization -** that might make the code run a little faster, but should not change -** the final answer. -*/ -SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ - WhereLevel *pInner; - if( !pWInfo->bOrderedInnerLoop ){ - /* The ORDER BY LIMIT optimization does not apply. Jump to the - ** continuation of the inner-most loop. */ - return pWInfo->iContinue; - } - pInner = &pWInfo->a[pWInfo->nLevel-1]; - assert( pInner->addrNxt!=0 ); - return pInner->pRJ ? pWInfo->iContinue : pInner->addrNxt; -} - -/* -** While generating code for the min/max optimization, after handling -** the aggregate-step call to min() or max(), check to see if any -** additional looping is required. If the output order is such that -** we are certain that the correct answer has already been found, then -** code an OP_Goto to by pass subsequent processing. -** -** Any extra OP_Goto that is coded here is an optimization. The -** correct answer should be obtained regardless. This OP_Goto just -** makes the answer appear faster. -*/ -SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){ - WhereLevel *pInner; - int i; - if( !pWInfo->bOrderedInnerLoop ) return; - if( pWInfo->nOBSat==0 ) return; - for(i=pWInfo->nLevel-1; i>=0; i--){ - pInner = &pWInfo->a[i]; - if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){ - sqlite3VdbeGoto(v, pInner->addrNxt); - return; - } - } - sqlite3VdbeGoto(v, pWInfo->iBreak); + return pWInfo->nOBSat; +} + +/* +** Return TRUE if the innermost loop of the WHERE clause implementation +** returns rows in ORDER BY order for complete run of the inner loop. +** +** Across multiple iterations of outer loops, the output rows need not be +** sorted. As long as rows are sorted for just the innermost loop, this +** routine can return TRUE. +*/ +SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){ + return pWInfo->bOrderedInnerLoop; } /* ** Return the VDBE address or label to jump to in order to continue ** immediately with the next row of a WHERE clause. @@ -163545,14 +131454,14 @@ return pWInfo->iBreak; } /* ** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to -** operate directly on the rowids returned by a WHERE clause. Return +** operate directly on the rowis returned by a WHERE clause. Return ** ONEPASS_SINGLE (1) if the statement can operation directly because only ** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass -** optimization can be used on multiple +** optimization can be used on multiple ** ** If the ONEPASS optimization is used (if this routine returns true) ** then also write the indices of open cursors used by ONEPASS ** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data ** table and iaCur[1] gets the cursor used by an auxiliary index. @@ -163572,18 +131481,10 @@ } #endif return pWInfo->eOnePass; } -/* -** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move -** the data cursor to the row selected by the index cursor. -*/ -SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){ - return pWInfo->bDeferredSeek; -} - /* ** Move the content of pSrc into pDest */ static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ pDest->n = pSrc->n; @@ -163635,47 +131536,18 @@ ** iCursor is not in the set. */ SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ int i; assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 ); - assert( iCursor>=-1 ); - if( pMaskSet->ix[0]==iCursor ){ - return 1; - } - for(i=1; in; i++){ + for(i=0; in; i++){ if( pMaskSet->ix[i]==iCursor ){ return MASKBIT(i); } } return 0; } -/* Allocate memory that is automatically freed when pWInfo is freed. -*/ -SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){ - WhereMemBlock *pBlock; - pBlock = sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock)); - if( pBlock ){ - pBlock->pNext = pWInfo->pMemToFree; - pBlock->sz = nByte; - pWInfo->pMemToFree = pBlock; - pBlock++; - } - return (void*)pBlock; -} -SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){ - void *pNew = sqlite3WhereMalloc(pWInfo, nByte); - if( pNew && pOld ){ - WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld; - pOldBlk--; - assert( pOldBlk->szsz); - } - return pNew; -} - /* ** Create a new mask for cursor iCursor. ** ** There is one cursor per table in the FROM clause. The number of ** tables in the FROM clause is limited by a test early in the @@ -163685,58 +131557,10 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){ assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); pMaskSet->ix[pMaskSet->n++] = iCursor; } -/* -** If the right-hand branch of the expression is a TK_COLUMN, then return -** a pointer to the right-hand branch. Otherwise, return NULL. -*/ -static Expr *whereRightSubexprIsColumn(Expr *p){ - p = sqlite3ExprSkipCollateAndLikely(p->pRight); - if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ - return p; - } - return 0; -} - -/* -** Term pTerm is guaranteed to be a WO_IN term. It may be a component term -** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)". -** This function checks to see if the term is compatible with an index -** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so, -** it returns a pointer to the name of the collation sequence (e.g. "BINARY" -** or "NOCASE") used by the comparison in pTerm. If it is not compatible -** with affinity idxaff, NULL is returned. -*/ -static SQLITE_NOINLINE const char *indexInAffinityOk( - Parse *pParse, - WhereTerm *pTerm, - u8 idxaff -){ - Expr *pX = pTerm->pExpr; - Expr inexpr; - - assert( pTerm->eOperator & WO_IN ); - - if( sqlite3ExprIsVector(pX->pLeft) ){ - int iField = pTerm->u.x.iField - 1; - inexpr.flags = 0; - inexpr.op = TK_EQ; - inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr; - assert( ExprUseXSelect(pX) ); - inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr; - pX = &inexpr; - } - - if( sqlite3IndexAffinityOk(pX, idxaff) ){ - CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX); - return pRet ? pRet->zName : sqlite3StrBINARY; - } - return 0; -} - /* ** Advance to the next WhereTerm that matches according to the criteria ** established when the pScan object was initialized by whereScanInit(). ** Return NULL if there are no more matching WhereTerms. */ @@ -163752,24 +131576,22 @@ pWC = pScan->pWC; while(1){ iColumn = pScan->aiColumn[pScan->iEquiv-1]; iCur = pScan->aiCur[pScan->iEquiv-1]; assert( pWC!=0 ); - assert( iCur>=0 ); do{ for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 ); if( pTerm->leftCursor==iCur - && pTerm->u.x.leftColumn==iColumn + && pTerm->u.leftColumn==iColumn && (iColumn!=XN_EXPR || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, pScan->pIdxExpr,iCur)==0) - && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON)) + && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaiCur) - && (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0 + && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN ){ int j; for(j=0; jnEquiv; j++){ if( pScan->aiCur[j]==pX->iTable && pScan->aiColumn[j]==pX->iColumn ){ @@ -163783,54 +131605,34 @@ } } if( (pTerm->eOperator & pScan->opMask)!=0 ){ /* Verify the affinity and collating sequence match */ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ - const char *zCollName; + CollSeq *pColl; Parse *pParse = pWC->pWInfo->pParse; pX = pTerm->pExpr; - - if( (pTerm->eOperator & WO_IN) ){ - zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff); - if( !zCollName ) continue; - }else{ - CollSeq *pColl; - if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ - continue; - } - assert(pX->pLeft); - pColl = sqlite3ExprCompareCollSeq(pParse, pX); - zCollName = pColl ? pColl->zName : sqlite3StrBINARY; - } - - if( sqlite3StrICmp(zCollName, pScan->zCollName) ){ + if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ + continue; + } + assert(pX->pLeft); + pColl = sqlite3BinaryCompareCollSeq(pParse, + pX->pLeft, pX->pRight); + if( pColl==0 ) pColl = pParse->db->pDfltColl; + if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ continue; } } if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0 - && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0)) - && pX->op==TK_COLUMN + && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN && pX->iTable==pScan->aiCur[0] && pX->iColumn==pScan->aiColumn[0] ){ testcase( pTerm->eOperator & WO_IS ); continue; } pScan->pWC = pWC; pScan->k = k+1; -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x20000 ){ - int ii; - sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d", - pTerm, pScan->nEquiv); - for(ii=0; iinEquiv; ii++){ - sqlite3DebugPrintf(" {%d:%d}", - pScan->aiCur[ii], pScan->aiColumn[ii]); - } - sqlite3DebugPrintf("\n"); - } -#endif return pTerm; } } } pWC = pWC->pOuter; @@ -163842,21 +131644,10 @@ pScan->iEquiv++; } return 0; } -/* -** This is whereScanInit() for the case of an index on an expression. -** It is factored out into a separate tail-recursion subroutine so that -** the normal whereScanInit() routine, which is a high-runner, does not -** need to push registers onto the stack as part of its prologue. -*/ -static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){ - pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr); - return whereScanNext(pScan); -} - /* ** Initialize a WHERE clause scanner object. Return a pointer to the ** first match. Return NULL if there are no matches. ** ** The scanner will be searching the WHERE clause pWC. It will look @@ -163885,43 +131676,41 @@ pScan->pOrigWC = pWC; pScan->pWC = pWC; pScan->pIdxExpr = 0; pScan->idxaff = 0; pScan->zCollName = 0; - pScan->opMask = opMask; - pScan->k = 0; - pScan->aiCur[0] = iCur; - pScan->nEquiv = 1; - pScan->iEquiv = 1; if( pIdx ){ int j = iColumn; iColumn = pIdx->aiColumn[j]; - if( iColumn==pIdx->pTable->iPKey ){ + if( iColumn==XN_EXPR ){ + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + pScan->zCollName = pIdx->azColl[j]; + }else if( iColumn==pIdx->pTable->iPKey ){ iColumn = XN_ROWID; }else if( iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; - }else if( iColumn==XN_EXPR ){ - pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - pScan->zCollName = pIdx->azColl[j]; - pScan->aiColumn[0] = XN_EXPR; - return whereScanInitIndexExpr(pScan); } }else if( iColumn==XN_EXPR ){ return 0; } + pScan->opMask = opMask; + pScan->k = 0; + pScan->aiCur[0] = iCur; pScan->aiColumn[0] = iColumn; + pScan->nEquiv = 1; + pScan->iEquiv = 1; return whereScanNext(pScan); } /* ** Search for a term in the WHERE clause that is of the form "X " ** where X is a reference to the iColumn of table iCur or of index pIdx ** if pIdx!=0 and is one of the WO_xx operator codes specified by ** the op parameter. Return a pointer to the term. Return 0 if not found. ** -** If pIdx!=0 then it must be one of the indexes of table iCur. +** If pIdx!=0 then it must be one of the indexes of table iCur. ** Search for terms matching the iColumn-th column of pIdx ** rather than the iColumn-th column of table iCur. ** ** The term returned might by Y= if there is another constraint in ** the WHERE clause that specifies that X=Y. Any such constraints will be @@ -163981,18 +131770,17 @@ ){ int i; const char *zColl = pIdx->azColl[iCol]; for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr); - if( ALWAYS(p!=0) - && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) + Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); + if( p->op==TK_COLUMN && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase ){ - CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr); - if( 0==sqlite3StrICmp(pColl->zName, zColl) ){ + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); + if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){ return i; } } } @@ -164031,29 +131819,27 @@ WhereClause *pWC, /* The WHERE clause */ ExprList *pDistinct /* The result set that needs to be DISTINCT */ ){ Table *pTab; Index *pIdx; - int i; + int i; int iBase; /* If there is more than one table or sub-select in the FROM clause of - ** this query, then it will not be possible to show that the DISTINCT + ** this query, then it will not be possible to show that the DISTINCT ** clause is redundant. */ if( pTabList->nSrc!=1 ) return 0; iBase = pTabList->a[0].iCursor; - pTab = pTabList->a[0].pSTab; + pTab = pTabList->a[0].pTab; - /* If any of the expressions is an IPK column on table iBase, then return + /* If any of the expressions is an IPK column on table iBase, then return ** true. Note: The (p->iTable==iBase) part of this test may be false if the ** current SELECT is a correlated sub-query. */ for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr); - if( NEVER(p==0) ) continue; - if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue; - if( p->iTable==iBase && p->iColumn<0 ) return 1; + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); + if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; } /* Loop through all indices on the table, checking each to see if it makes ** the DISTINCT qualifier redundant. It does so if: ** @@ -164067,11 +131853,10 @@ ** 3. All of those index columns for which the WHERE clause does not ** contain a "col=X" term are subject to a NOT NULL constraint. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( !IsUniqueIndex(pIdx) ) continue; - if( pIdx->pPartIdxWhere ) continue; for(i=0; inKeyCol; i++){ if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){ if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break; if( indexColumnNotNull(pIdx, i)==0 ) break; } @@ -164095,62 +131880,47 @@ /* ** Convert OP_Column opcodes to OP_Copy in previously generated code. ** ** This routine runs over generated VDBE code and translates OP_Column -** opcodes into OP_Copy when the table is being accessed via co-routine +** opcodes into OP_Copy when the table is being accessed via co-routine ** instead of via table lookup. ** -** If the iAutoidxCur is not zero, then any OP_Rowid instructions on -** cursor iTabCur are transformed into OP_Sequence opcode for the -** iAutoidxCur cursor, in order to generate unique rowids for the -** automatic index being generated. +** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on +** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero, +** then each OP_Rowid is transformed into an instruction to increment the +** value stored in its output register. */ static void translateColumnToCopy( Parse *pParse, /* Parsing context */ int iStart, /* Translate from this opcode to the end */ int iTabCur, /* OP_Column/OP_Rowid references to this table */ int iRegister, /* The first column is in this register */ - int iAutoidxCur /* If non-zero, cursor of autoindex being generated */ + int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */ ){ Vdbe *v = pParse->pVdbe; VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); int iEnd = sqlite3VdbeCurrentAddr(v); if( pParse->db->mallocFailed ) return; -#ifdef SQLITE_DEBUG - if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ - printf("CHECKING for column-to-copy on cursor %d for %d..%d\n", - iTabCur, iStart, iEnd); - } -#endif for(; iStartp1!=iTabCur ) continue; if( pOp->opcode==OP_Column ){ -#ifdef SQLITE_DEBUG - if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE OP_Column to OP_Copy at %d\n", iStart); - } -#endif pOp->opcode = OP_Copy; pOp->p1 = pOp->p2 + iRegister; pOp->p2 = pOp->p3; pOp->p3 = 0; - pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */ }else if( pOp->opcode==OP_Rowid ){ -#ifdef SQLITE_DEBUG - if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE OP_Rowid to OP_Sequence at %d\n", iStart); - } -#endif - pOp->opcode = OP_Sequence; - pOp->p1 = iAutoidxCur; -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( iAutoidxCur==0 ){ + if( bIncrRowid ){ + /* Increment the value stored in the P2 operand of the OP_Rowid. */ + pOp->opcode = OP_AddImm; + pOp->p1 = pOp->p2; + pOp->p2 = 1; + }else{ pOp->opcode = OP_Null; + pOp->p1 = 0; pOp->p3 = 0; } -#endif } } } /* @@ -164158,41 +131928,31 @@ ** structure. Used for testing and debugging only. If neither ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines ** are no-ops. */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) -static void whereTraceIndexInfoInputs( - sqlite3_index_info *p, /* The IndexInfo object */ - Table *pTab /* The TABLE that is the virtual table */ -){ +static void TRACE_IDX_INPUTS(sqlite3_index_info *p){ int i; - if( (sqlite3WhereTrace & 0x10)==0 ) return; - sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName); + if( !sqlite3WhereTrace ) return; for(i=0; inConstraint; i++){ - sqlite3DebugPrintf( - " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n", + sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", i, p->aConstraint[i].iColumn, p->aConstraint[i].iTermOffset, p->aConstraint[i].op, - p->aConstraint[i].usable, - sqlite3_vtab_collation(p,i)); + p->aConstraint[i].usable); } for(i=0; inOrderBy; i++){ sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", i, p->aOrderBy[i].iColumn, p->aOrderBy[i].desc); } } -static void whereTraceIndexInfoOutputs( - sqlite3_index_info *p, /* The IndexInfo object */ - Table *pTab /* The TABLE that is the virtual table */ -){ +static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ int i; - if( (sqlite3WhereTrace & 0x10)==0 ) return; - sqlite3DebugPrintf("sqlite3_index_info outputs for %s:\n", pTab->zName); + if( !sqlite3WhereTrace ) return; for(i=0; inConstraint; i++){ sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", i, p->aConstraintUsage[i].argvIndex, p->aConstraintUsage[i].omit); @@ -164202,185 +131962,49 @@ sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); } #else -#define whereTraceIndexInfoInputs(A,B) -#define whereTraceIndexInfoOutputs(A,B) +#define TRACE_IDX_INPUTS(A) +#define TRACE_IDX_OUTPUTS(A) #endif - -/* -** We know that pSrc is an operand of an outer join. Return true if -** pTerm is a constraint that is compatible with that join. -** -** pTerm must be EP_OuterON if pSrc is the right operand of an -** outer join. pTerm can be either EP_OuterON or EP_InnerON if pSrc -** is the left operand of a RIGHT join. -** -** See https://sqlite.org/forum/forumpost/206d99a16dd9212f -** for an example of a WHERE clause constraints that may not be used on -** the right table of a RIGHT JOIN because the constraint implies a -** not-NULL condition on the left table of the RIGHT JOIN. -*/ -static int constraintCompatibleWithOuterJoin( - const WhereTerm *pTerm, /* WHERE clause term to check */ - const SrcItem *pSrc /* Table we are trying to access */ -){ - assert( (pSrc->fg.jointype&(JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ); /* By caller */ - testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT ); - testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ ); - testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) - testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) ); - if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) - || pTerm->pExpr->w.iJoin != pSrc->iCursor - ){ - return 0; - } - if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0 - && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON)) - ){ - return 0; - } - return 1; -} - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Return true if column iCol of table pTab seem like it might be a -** good column to use as part of a query-time index. -** -** Current algorithm (subject to improvement!): -** -** 1. If iCol is already the left-most column of some other index, -** then return false. -** -** 2. If iCol is part of an existing index that has an aiRowLogEst of -** more than 20, then return false. -** -** 3. If no disqualifying conditions above are found, return true. -** -** 2025-01-03: I experimented with a new rule that returns false if the -** the datatype of the column is "BOOLEAN". This did not improve -** performance on any queries at hand, but it did burn CPU cycles, so the -** idea was not committed. -*/ -static SQLITE_NOINLINE int columnIsGoodIndexCandidate( - const Table *pTab, - int iCol -){ - const Index *pIdx; - for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){ - int j; - for(j=0; jnKeyCol; j++){ - if( pIdx->aiColumn[j]==iCol ){ - if( j==0 ) return 0; - if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0; - break; - } - } - } - return 1; -} -#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - - #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* ** Return TRUE if the WHERE clause term pTerm is of a form where it ** could be used with an index to access pSrc, assuming an appropriate ** index existed. */ static int termCanDriveIndex( - const WhereTerm *pTerm, /* WHERE clause term to check */ - const SrcItem *pSrc, /* Table we are trying to access */ - const Bitmask notReady /* Tables in outer loops of the join */ + WhereTerm *pTerm, /* WHERE clause term to check */ + struct SrcList_item *pSrc, /* Table we are trying to access */ + Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; - int leftCol; - if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0; - assert( (pSrc->fg.jointype & JT_RIGHT)==0 ); - if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 - && !constraintCompatibleWithOuterJoin(pTerm,pSrc) - ){ - return 0; /* See https://sqlite.org/forum/forumpost/51e6959f61 */ - } if( (pTerm->prereqRight & notReady)!=0 ) return 0; - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - leftCol = pTerm->u.x.leftColumn; - if( leftCol<0 ) return 0; - aff = pSrc->pSTab->aCol[leftCol].affinity; + if( pTerm->u.leftColumn<0 ) return 0; + aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; testcase( pTerm->pExpr->op==TK_IS ); - return columnIsGoodIndexCandidate(pSrc->pSTab, leftCol); + return 1; } #endif #ifndef SQLITE_OMIT_AUTOMATIC_INDEX - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -/* -** Argument pIdx represents an automatic index that the current statement -** will create and populate. Add an OP_Explain with text of the form: -** -** CREATE AUTOMATIC INDEX ON
                () [WHERE ] -** -** This is only required if sqlite3_stmt_scanstatus() is enabled, to -** associate an SQLITE_SCANSTAT_NCYCLE and SQLITE_SCANSTAT_NLOOP -** values with. In order to avoid breaking legacy code and test cases, -** the OP_Explain is not added if this is an EXPLAIN QUERY PLAN command. -*/ -static void explainAutomaticIndex( - Parse *pParse, - Index *pIdx, /* Automatic index to explain */ - int bPartial, /* True if pIdx is a partial index */ - int *pAddrExplain /* OUT: Address of OP_Explain */ -){ - if( IS_STMT_SCANSTATUS(pParse->db) && pParse->explain!=2 ){ - Table *pTab = pIdx->pTable; - const char *zSep = ""; - char *zText = 0; - int ii = 0; - sqlite3_str *pStr = sqlite3_str_new(pParse->db); - sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName); - assert( pIdx->nColumn>1 ); - assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID || !HasRowid(pTab) ); - for(ii=0; ii<(pIdx->nColumn-1); ii++){ - const char *zName = 0; - int iCol = pIdx->aiColumn[ii]; - - zName = pTab->aCol[iCol].zCnName; - sqlite3_str_appendf(pStr, "%s%s", zSep, zName); - zSep = ", "; - } - zText = sqlite3_str_finish(pStr); - if( zText==0 ){ - sqlite3OomFault(pParse->db); - }else{ - *pAddrExplain = sqlite3VdbeExplain( - pParse, 0, "%s)%s", zText, (bPartial ? " WHERE " : "") - ); - sqlite3_free(zText); - } - } -} -#else -# define explainAutomaticIndex(a,b,c,d) -#endif - /* ** Generate code to construct the Index object for an automatic index ** and to set up the WhereLevel object pLevel so that the code generator ** makes use of the automatic index. */ -static SQLITE_NOINLINE void constructAutomaticIndex( +static void constructAutomaticIndex( Parse *pParse, /* The parsing context */ WhereClause *pWC, /* The WHERE clause */ - const Bitmask notReady, /* Mask of cursors that are not available */ + struct SrcList_item *pSrc, /* The FROM clause term to get the next index */ + Bitmask notReady, /* Mask of cursors that are not available */ WhereLevel *pLevel /* Write new index here */ ){ int nKeyCol; /* Number of columns in the constructed index */ WhereTerm *pTerm; /* A single term of the WHERE clause */ WhereTerm *pWCEnd; /* End of pWC->a[] */ @@ -164396,21 +132020,16 @@ CollSeq *pColl; /* Collating sequence to on a column */ WhereLoop *pLoop; /* The Loop object */ char *zNotUsed; /* Extra space on the end of pIdx */ Bitmask idxCols; /* Bitmap of columns used for indexing */ Bitmask extraCols; /* Bitmap of additional columns */ - u8 sentWarning = 0; /* True if a warning has been issued */ - u8 useBloomFilter = 0; /* True to also add a Bloom filter */ + u8 sentWarning = 0; /* True if a warnning has been issued */ Expr *pPartial = 0; /* Partial Index Expression */ int iContinue = 0; /* Jump here to skip excluded rows */ - SrcList *pTabList; /* The complete FROM clause */ - SrcItem *pSrc; /* The FROM clause term to get the next index */ + struct SrcList_item *pTabItem; /* FROM clause term being indexed */ int addrCounter = 0; /* Address where integer counter is initialized */ int regBase; /* Array of registers where record is assembled */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExp = 0; /* Address of OP_Explain */ -#endif /* Generate code to skip over the creation and initialization of the ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); @@ -164417,39 +132036,35 @@ addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ nKeyCol = 0; - pTabList = pWC->pWInfo->pTabList; - pSrc = &pTabList->a[pLevel->iFrom]; - pTable = pSrc->pSTab; + pTable = pSrc->pTab; pWCEnd = &pWC->a[pWC->nTerm]; pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTermpExpr; - /* Make the automatic index a partial index if there are terms in the - ** WHERE clause (or the ON clause of a LEFT join) that constrain which - ** rows of the target table (pSrc) that can be used. */ - if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0) - ){ - pPartial = sqlite3ExprAnd(pParse, pPartial, + assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ + || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ + || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ + if( pLoop->prereq==0 + && (pTerm->wtFlags & TERM_VIRTUAL)==0 + && !ExprHasProperty(pExpr, EP_FromJoin) + && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ + pPartial = sqlite3ExprAnd(pParse->db, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); } if( termCanDriveIndex(pTerm, pSrc, notReady) ){ - int iCol; - Bitmask cMask; - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - iCol = pTerm->u.x.leftColumn; - cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + int iCol = pTerm->u.leftColumn; + Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS ); testcase( iCol==BMS-1 ); if( !sentWarning ){ sqlite3_log(SQLITE_WARNING_AUTOINDEX, "automatic index on %s(%s)", pTable->zName, - pTable->aCol[iCol].zCnName); + pTable->aCol[iCol].zName); sentWarning = 1; } if( (idxCols & cMask)==0 ){ if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){ goto end_auto_index_create; @@ -164457,11 +132072,11 @@ pLoop->aLTerm[nKeyCol++] = pTerm; idxCols |= cMask; } } } - assert( nKeyCol>0 || pParse->db->mallocFailed ); + assert( nKeyCol>0 ); pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol; pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED | WHERE_AUTO_INDEX; /* Count the number of additional columns needed to create a @@ -164470,28 +132085,11 @@ ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used ** if they go out of sync. */ - if( IsView(pTable) ){ - extraCols = ALLBITS & ~idxCols; - }else{ - extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); - } - if( !HasRowid(pTable) ){ - /* For WITHOUT ROWID tables, ensure that all PRIMARY KEY columns are - ** either in the idxCols mask or in the extraCols mask */ - for(i=0; inCol; i++){ - if( (pTable->aCol[i].colFlags & COLFLAG_PRIMKEY)==0 ) continue; - if( i>=BMS-1 ){ - extraCols |= MASKBIT(BMS-1); - break; - } - if( idxCols & MASKBIT(i) ) continue; - extraCols |= MASKBIT(i); - } - } + extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); mxBitCol = MIN(BMS-1,pTable->nCol); testcase( pTable->nCol==BMS-1 ); testcase( pTable->nCol==BMS-2 ); for(i=0; icolUsed & MASKBIT(BMS-1) ){ nKeyCol += pTable->nCol - BMS + 1; } /* Construct the Index object to describe this index */ - pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable), - 0, &zNotUsed); + pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed); if( pIdx==0 ) goto end_auto_index_create; pLoop->u.btree.pIndex = pIdx; pIdx->zName = "auto-index"; pIdx->pTable = pTable; n = 0; idxCols = 0; for(pTerm=pWC->a; pTermeOperator & (WO_OR|WO_AND))==0 ); - iCol = pTerm->u.x.leftColumn; - cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + int iCol = pTerm->u.leftColumn; + Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS-1 ); testcase( iCol==BMS ); if( (idxCols & cMask)==0 ){ Expr *pX = pTerm->pExpr; idxCols |= cMask; - pIdx->aiColumn[n] = pTerm->u.x.leftColumn; - pColl = sqlite3ExprCompareCollSeq(pParse, pX); - assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */ + pIdx->aiColumn[n] = pTerm->u.leftColumn; + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; n++; - if( ALWAYS(pX->pLeft!=0) - && sqlite3ExprAffinity(pX->pLeft)!=SQLITE_AFF_TEXT - ){ - /* TUNING: only use a Bloom filter on an automatic index - ** if one or more key columns has the ability to hold numeric - ** values, since strings all have the same hash in the Bloom - ** filter implementation and hence a Bloom filter on a text column - ** is not usually helpful. */ - useBloomFilter = 1; - } } } } assert( (u32)n==pLoop->u.btree.nEq ); @@ -164556,536 +132139,250 @@ pIdx->azColl[n] = sqlite3StrBINARY; n++; } } assert( n==nKeyCol ); - if( HasRowid(pTable) ){ - pIdx->aiColumn[n] = XN_ROWID; - pIdx->azColl[n] = sqlite3StrBINARY; - } + pIdx->aiColumn[n] = XN_ROWID; + pIdx->azColl[n] = sqlite3StrBINARY; /* Create the automatic index */ - explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp); assert( pLevel->iIdxCur>=0 ); pLevel->iIdxCur = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); - if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) && useBloomFilter ){ - sqlite3WhereExplainBloomFilter(pParse, pWC->pWInfo, pLevel); - pLevel->regFilter = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter); - } /* Fill the automatic index with content */ - assert( pSrc == &pWC->pWInfo->pTabList->a[pLevel->iFrom] ); - if( pSrc->fg.viaCoroutine ){ - int regYield; - Subquery *pSubq; - assert( pSrc->fg.isSubquery ); - pSubq = pSrc->u4.pSubq; - assert( pSubq!=0 ); - regYield = pSubq->regReturn; + sqlite3ExprCachePush(pParse); + pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; + if( pTabItem->fg.viaCoroutine ){ + int regYield = pTabItem->regReturn; addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub); + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); VdbeCoverage(v); - VdbeComment((v, "next row of %s", pSrc->pSTab->zName)); + VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); }else{ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); } if( pPartial ){ - iContinue = sqlite3VdbeMakeLabel(pParse); + iContinue = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL); pLoop->wsFlags |= WHERE_PARTIALIDX; } regRecord = sqlite3GetTempReg(pParse); regBase = sqlite3GenerateIndexKey( pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 ); - if( pLevel->regFilter ){ - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, - regBase, pLoop->u.btree.nEq); - } - sqlite3VdbeScanStatusCounters(v, addrExp, addrExp, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); - if( pSrc->fg.viaCoroutine ){ - assert( pSrc->fg.isSubquery && pSrc->u4.pSubq!=0 ); + if( pTabItem->fg.viaCoroutine ){ sqlite3VdbeChangeP2(v, addrCounter, regBase+n); testcase( pParse->db->mallocFailed ); - assert( pLevel->iIdxCur>0 ); translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, - pSrc->u4.pSubq->regResult, pLevel->iIdxCur); + pTabItem->regResult, 1); sqlite3VdbeGoto(v, addrTop); - pSrc->fg.viaCoroutine = 0; + pTabItem->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); } + sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeJumpHere(v, addrTop); sqlite3ReleaseTempReg(pParse, regRecord); - + sqlite3ExprCachePop(pParse); + /* Jump here when skipping the initialization */ sqlite3VdbeJumpHere(v, addrInit); - sqlite3VdbeScanStatusRange(v, addrExp, addrExp, -1); end_auto_index_create: sqlite3ExprDelete(pParse->db, pPartial); } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - -/* -** Generate bytecode that will initialize a Bloom filter that is appropriate -** for pLevel. -** -** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER -** flag set, initialize a Bloomfilter for them as well. Except don't do -** this recursive initialization if the SQLITE_BloomPulldown optimization has -** been turned off. -** -** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared -** from the loop, but the regFilter value is set to a register that implements -** the Bloom filter. When regFilter is positive, the -** sqlite3WhereCodeOneLoopStart() will generate code to test the Bloom filter -** and skip the subsequence B-Tree seek if the Bloom filter indicates that -** no matching rows exist. -** -** This routine may only be called if it has previously been determined that -** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit -** is set. -*/ -static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( - WhereInfo *pWInfo, /* The WHERE clause */ - int iLevel, /* Index in pWInfo->a[] that is pLevel */ - WhereLevel *pLevel, /* Make a Bloom filter for this FROM term */ - Bitmask notReady /* Loops that are not ready */ -){ - int addrOnce; /* Address of opening OP_Once */ - int addrTop; /* Address of OP_Rewind */ - int addrCont; /* Jump here to skip a row */ - const WhereTerm *pTerm; /* For looping over WHERE clause terms */ - const WhereTerm *pWCEnd; /* Last WHERE clause term */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ - Vdbe *v = pParse->pVdbe; /* VDBE under construction */ - WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */ - int iCur; /* Cursor for table getting the filter */ - IndexedExpr *saved_pIdxEpr; /* saved copy of Parse.pIdxEpr */ - IndexedExpr *saved_pIdxPartExpr; /* saved copy of Parse.pIdxPartExpr */ - - saved_pIdxEpr = pParse->pIdxEpr; - saved_pIdxPartExpr = pParse->pIdxPartExpr; - pParse->pIdxEpr = 0; - pParse->pIdxPartExpr = 0; - - assert( pLoop!=0 ); - assert( v!=0 ); - assert( pLoop->wsFlags & WHERE_BLOOMFILTER ); - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ); - - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - do{ - const SrcList *pTabList; - const SrcItem *pItem; - const Table *pTab; - u64 sz; - int iSrc; - sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel); - addrCont = sqlite3VdbeMakeLabel(pParse); - iCur = pLevel->iTabCur; - pLevel->regFilter = ++pParse->nMem; - - /* The Bloom filter is a Blob held in a register. Initialize it - ** to zero-filled blob of at least 80K bits, but maybe more if the - ** estimated size of the table is larger. We could actually - ** measure the size of the table at run-time using OP_Count with - ** P3==1 and use that value to initialize the blob. But that makes - ** testing complicated. By basing the blob size on the value in the - ** sqlite_stat1 table, testing is much easier. - */ - pTabList = pWInfo->pTabList; - iSrc = pLevel->iFrom; - pItem = &pTabList->a[iSrc]; - assert( pItem!=0 ); - pTab = pItem->pSTab; - assert( pTab!=0 ); - sz = sqlite3LogEstToInt(pTab->nRowLogEst); - if( sz<10000 ){ - sz = 10000; - }else if( sz>10000000 ){ - sz = 10000000; - } - sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); - - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; - for(pTerm=pWInfo->sWC.a; pTermpExpr; - if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc, 0) - ){ - sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); - } - } - if( pLoop->wsFlags & WHERE_IPK ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); - sqlite3ReleaseTempReg(pParse, r1); - }else{ - Index *pIdx = pLoop->u.btree.pIndex; - int n = pLoop->u.btree.nEq; - int r1 = sqlite3GetTempRange(pParse, n); - int jj; - for(jj=0; jjpTable==pItem->pSTab ); - sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj); - } - sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); - sqlite3ReleaseTempRange(pParse, r1, n); - } - sqlite3VdbeResolveLabel(v, addrCont); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrTop); - pLoop->wsFlags &= ~WHERE_BLOOMFILTER; - if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break; - while( ++iLevel < pWInfo->nLevel ){ - const SrcItem *pTabItem; - pLevel = &pWInfo->a[iLevel]; - pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; - if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue; - pLoop = pLevel->pWLoop; - if( NEVER(pLoop==0) ) continue; - if( pLoop->prereq & notReady ) continue; - if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN)) - ==WHERE_BLOOMFILTER - ){ - /* This is a candidate for bloom-filter pull-down (early evaluation). - ** The test that WHERE_COLUMN_IN is omitted is important, as we are - ** not able to do early evaluation of bloom filters that make use of - ** the IN operator */ - break; - } - } - }while( iLevel < pWInfo->nLevel ); - sqlite3VdbeJumpHere(v, addrOnce); - pParse->pIdxEpr = saved_pIdxEpr; - pParse->pIdxPartExpr = saved_pIdxPartExpr; -} - #ifndef SQLITE_OMIT_VIRTUALTABLE /* -** Return term iTerm of the WhereClause passed as the first argument. Terms -** are numbered from 0 upwards, starting with the terms in pWC->a[], then -** those in pWC->pOuter->a[] (if any), and so on. -*/ -static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){ - WhereClause *p; - for(p=pWC; p; p=p->pOuter){ - if( iTermnTerm ) return &p->a[iTerm]; - iTerm -= p->nTerm; - } - return 0; -} - -/* -** Allocate and populate an sqlite3_index_info structure. It is the +** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure -** by passing the pointer returned by this function to freeIndexInfo(). +** by passing the pointer returned by this function to sqlite3_free(). */ static sqlite3_index_info *allocateIndexInfo( - WhereInfo *pWInfo, /* The WHERE clause */ - WhereClause *pWC, /* The WHERE clause being analyzed */ + Parse *pParse, + WhereClause *pWC, Bitmask mUnusable, /* Ignore terms with these prereqs */ - SrcItem *pSrc, /* The FROM clause term that is the vtab */ + struct SrcList_item *pSrc, + ExprList *pOrderBy, u16 *pmNoOmit /* Mask of terms not to omit */ ){ int i, j; int nTerm; - Parse *pParse = pWInfo->pParse; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_orderby *pIdxOrderBy; struct sqlite3_index_constraint_usage *pUsage; - struct HiddenIndexInfo *pHidden; WhereTerm *pTerm; int nOrderBy; sqlite3_index_info *pIdxInfo; u16 mNoOmit = 0; - const Table *pTab; - int eDistinct = 0; - ExprList *pOrderBy = pWInfo->pOrderBy; - WhereClause *p; - - assert( pSrc!=0 ); - pTab = pSrc->pSTab; - assert( pTab!=0 ); - assert( IsVirtual(pTab) ); - - /* Find all WHERE clause constraints referring to this virtual table. - ** Mark each term with the TERM_OK flag. Set nTerm to the number of - ** terms found. - */ - for(p=pWC, nTerm=0; p; p=p->pOuter){ - for(i=0, pTerm=p->a; inTerm; i++, pTerm++){ - pTerm->wtFlags &= ~TERM_OK; - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - assert( pTerm->u.x.leftColumn>=XN_ROWID ); - assert( pTerm->u.x.leftColumnnCol ); - if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 - && !constraintCompatibleWithOuterJoin(pTerm,pSrc) - ){ - continue; - } - nTerm++; - pTerm->wtFlags |= TERM_OK; - } - } - - /* If the ORDER BY clause contains only columns in the current + + /* Count the number of possible WHERE clause constraints referring + ** to this virtual table */ + for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + if( pTerm->leftCursor != pSrc->iCursor ) continue; + if( pTerm->prereqRight & mUnusable ) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); + testcase( pTerm->eOperator & WO_IN ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_IS ); + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; + assert( pTerm->u.leftColumn>=(-1) ); + nTerm++; + } + + /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. */ nOrderBy = 0; if( pOrderBy ){ int n = pOrderBy->nExpr; for(i=0; ia[i].pExpr; - Expr *pE2; - - /* Skip over constant terms in the ORDER BY clause */ - if( sqlite3ExprIsConstant(0, pExpr) ){ - continue; - } - - /* Virtual tables are unable to deal with NULLS FIRST */ - if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break; - - /* First case - a direct column references without a COLLATE operator */ - if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){ - assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumnnCol ); - continue; - } - - /* 2nd case - a column reference with a COLLATE operator. Only match - ** of the COLLATE operator matches the collation of the column. */ - if( pExpr->op==TK_COLLATE - && (pE2 = pExpr->pLeft)->op==TK_COLUMN - && pE2->iTable==pSrc->iCursor - ){ - const char *zColl; /* The collating sequence name */ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( pExpr->u.zToken!=0 ); - assert( pE2->iColumn>=XN_ROWID && pE2->iColumnnCol ); - pExpr->iColumn = pE2->iColumn; - if( pE2->iColumn<0 ) continue; /* Collseq does not matter for rowid */ - zColl = sqlite3ColumnColl(&pTab->aCol[pE2->iColumn]); - if( zColl==0 ) zColl = sqlite3StrBINARY; - if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; - } - - /* No matches cause a break out of the loop */ - break; - } - if( i==n ){ - nOrderBy = n; - if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){ - eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); - }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ - eDistinct = 1; - } + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + } + if( i==n){ + nOrderBy = n; } } /* Allocate the sqlite3_index_info structure */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) - + sizeof(sqlite3_value*)*nTerm ); + + sizeof(*pIdxOrderBy)*nOrderBy ); if( pIdxInfo==0 ){ sqlite3ErrorMsg(pParse, "out of memory"); return 0; } - pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; - pIdxCons = (struct sqlite3_index_constraint*)&pHidden->aRhs[nTerm]; + + /* Initialize the structure. The sqlite3_index_info structure contains + ** many fields that are declared "const" to prevent xBestIndex from + ** changing them. We have to do some funky casting in order to + ** initialize those fields. + */ + pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - pIdxInfo->aConstraint = pIdxCons; - pIdxInfo->aOrderBy = pIdxOrderBy; - pIdxInfo->aConstraintUsage = pUsage; - pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; - if( HasRowid(pTab)==0 ){ - /* Ensure that all bits associated with PK columns are set. This is to - ** ensure they are available for cases like RIGHT joins or OR loops. */ - Index *pPk = sqlite3PrimaryKeyIndex((Table*)pTab); - assert( pPk!=0 ); - for(i=0; inKeyCol; i++){ - int iCol = pPk->aiColumn[i]; - assert( iCol>=0 ); - if( iCol>=BMS-1 ) iCol = BMS-1; - pIdxInfo->colUsed |= MASKBIT(iCol); - } - } - pHidden->pWC = pWC; - pHidden->pParse = pParse; - pHidden->eDistinct = eDistinct; - pHidden->mIn = 0; - for(p=pWC, i=j=0; p; p=p->pOuter){ - int nLast = i+p->nTerm;; - for(pTerm=p->a; iwtFlags & TERM_OK)==0 ) continue; - pIdxCons[j].iColumn = pTerm->u.x.leftColumn; - pIdxCons[j].iTermOffset = i; - op = pTerm->eOperator & WO_ALL; - if( op==WO_IN ){ - if( (pTerm->wtFlags & TERM_SLICE)==0 ){ - pHidden->mIn |= SMASKBIT32(j); - } - op = WO_EQ; - } - if( op==WO_AUX ){ - pIdxCons[j].op = pTerm->eMatchOp; - }else if( op & (WO_ISNULL|WO_IS) ){ - if( op==WO_ISNULL ){ - pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; - }else{ - pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; - } - }else{ - pIdxCons[j].op = (u8)op; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) ); - - if( op & (WO_LT|WO_LE|WO_GT|WO_GE) - && sqlite3ExprIsVector(pTerm->pExpr->pRight) - ){ - testcase( j!=i ); - if( j<16 ) mNoOmit |= (1 << j); - if( op==WO_LT ) pIdxCons[j].op = WO_LE; - if( op==WO_GT ) pIdxCons[j].op = WO_GE; - } - } - - j++; - } - } - assert( j==nTerm ); - pIdxInfo->nConstraint = j; - for(i=j=0; ia[i].pExpr; - if( sqlite3ExprIsConstant(0, pExpr) ) continue; - assert( pExpr->op==TK_COLUMN - || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN - && pExpr->iColumn==pExpr->pLeft->iColumn) ); - pIdxOrderBy[j].iColumn = pExpr->iColumn; - pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC; - j++; - } - pIdxInfo->nOrderBy = j; + *(int*)&pIdxInfo->nConstraint = nTerm; + *(int*)&pIdxInfo->nOrderBy = nOrderBy; + *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; + *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; + *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = + pUsage; + + for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + u8 op; + if( pTerm->leftCursor != pSrc->iCursor ) continue; + if( pTerm->prereqRight & mUnusable ) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); + testcase( pTerm->eOperator & WO_IN ); + testcase( pTerm->eOperator & WO_IS ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; + assert( pTerm->u.leftColumn>=(-1) ); + pIdxCons[j].iColumn = pTerm->u.leftColumn; + pIdxCons[j].iTermOffset = i; + op = (u8)pTerm->eOperator & WO_ALL; + if( op==WO_IN ) op = WO_EQ; + if( op==WO_MATCH ){ + op = pTerm->eMatchOp; + } + pIdxCons[j].op = op; + /* The direct assignment in the previous line is possible only because + ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The + ** following asserts verify this fact. */ + assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); + assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); + assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); + assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); + assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); + assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); + assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); + + if( op & (WO_LT|WO_LE|WO_GT|WO_GE) + && sqlite3ExprIsVector(pTerm->pExpr->pRight) + ){ + if( i<16 ) mNoOmit |= (1 << i); + if( op==WO_LT ) pIdxCons[j].op = WO_LE; + if( op==WO_GT ) pIdxCons[j].op = WO_GE; + } + + j++; + } + for(i=0; ia[i].pExpr; + pIdxOrderBy[i].iColumn = pExpr->iColumn; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + } *pmNoOmit = mNoOmit; return pIdxInfo; } -/* -** Free and zero the sqlite3_index_info.idxStr value if needed. -*/ -static void freeIdxStr(sqlite3_index_info *pIdxInfo){ - if( pIdxInfo->needToFreeIdxStr ){ - sqlite3_free(pIdxInfo->idxStr); - pIdxInfo->idxStr = 0; - pIdxInfo->needToFreeIdxStr = 0; - } -} - -/* -** Free an sqlite3_index_info structure allocated by allocateIndexInfo() -** and possibly modified by xBestIndex methods. -*/ -static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){ - HiddenIndexInfo *pHidden; - int i; - assert( pIdxInfo!=0 ); - pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - assert( pHidden->pParse!=0 ); - assert( pHidden->pParse->db==db ); - for(i=0; inConstraint; i++){ - sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */ - pHidden->aRhs[i] = 0; - } - freeIdxStr(pIdxInfo); - sqlite3DbFree(db, pIdxInfo); -} - /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** -** If an error occurs, pParse is populated with an error message and an -** appropriate error code is returned. A return of SQLITE_CONSTRAINT from -** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that -** the current configuration of "unusable" flags in sqlite3_index_info can -** not result in a valid plan. +** If an error occurs, pParse is populated with an error message and a +** non-zero value is returned. Otherwise, 0 is returned and the output +** part of the sqlite3_index_info structure is left populated. ** ** Whether or not an error is returned, it is the responsibility of the ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ + sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; int rc; - sqlite3_vtab *pVtab; - assert( IsVirtual(pTab) ); - pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; - whereTraceIndexInfoInputs(p, pTab); - pParse->db->nSchemaLock++; + TRACE_IDX_INPUTS(p); rc = pVtab->pModule->xBestIndex(pVtab, p); - pParse->db->nSchemaLock--; - whereTraceIndexInfoOutputs(p, pTab); + TRACE_IDX_OUTPUTS(p); - if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ + if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); } } - if( pTab->u.vtab.p->bAllSchemas ){ - sqlite3VtabUsesAllSchemas(pParse); - } sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; - return rc; + +#if 0 + /* This error is now caught by the caller. + ** Search for "xBestIndex malfunction" below */ + for(i=0; inConstraint; i++){ + if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ + sqlite3ErrorMsg(pParse, + "table %s: xBestIndex returned an invalid plan", pTab->zName); + } + } +#endif + + return pParse->nErr; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: ** ** aStat[0] Est. number of rows less than pRec @@ -165092,12 +132389,12 @@ ** aStat[1] Est. number of rows equal to pRec ** ** Return the index of the sample that is the smallest sample that ** is greater than or equal to pRec. Note that this index is not an index ** into the aSample[] array - it is an index into a virtual set of samples -** based on the contents of aSample[] and the number of fields in record -** pRec. +** based on the contents of aSample[] and the number of fields in record +** pRec. */ static int whereKeyStats( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ UnpackedRecord *pRec, /* Vector of values to consider */ @@ -165117,12 +132414,11 @@ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( pParse ); #endif assert( pRec!=0 ); assert( pIdx->nSample>0 ); - assert( pRec->nField>0 ); - + assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); /* Do a binary search to find the first sample greater than or equal ** to pRec. If pRec contains a single field, the set of samples to search ** is simply the aSample[] array. If the samples in aSample[] contain more ** than one fields, all fields following the first are ignored. @@ -165130,50 +132426,45 @@ ** If pRec contains N fields, where N is more than one, then as well as the ** samples in aSample[] (truncated to N fields), the search also has to ** consider prefixes of those samples. For example, if the set of samples ** in aSample is: ** - ** aSample[0] = (a, 5) - ** aSample[1] = (a, 10) - ** aSample[2] = (b, 5) - ** aSample[3] = (c, 100) + ** aSample[0] = (a, 5) + ** aSample[1] = (a, 10) + ** aSample[2] = (b, 5) + ** aSample[3] = (c, 100) ** aSample[4] = (c, 105) ** - ** Then the search space should ideally be the samples above and the - ** unique prefixes [a], [b] and [c]. But since that is hard to organize, + ** Then the search space should ideally be the samples above and the + ** unique prefixes [a], [b] and [c]. But since that is hard to organize, ** the code actually searches this set: ** - ** 0: (a) - ** 1: (a, 5) - ** 2: (a, 10) - ** 3: (a, 10) - ** 4: (b) - ** 5: (b, 5) - ** 6: (c) - ** 7: (c, 100) + ** 0: (a) + ** 1: (a, 5) + ** 2: (a, 10) + ** 3: (a, 10) + ** 4: (b) + ** 5: (b, 5) + ** 6: (c) + ** 7: (c, 100) ** 8: (c, 105) ** 9: (c, 105) ** ** For each sample in the aSample[] array, N samples are present in the - ** effective sample array. In the above, samples 0 and 1 are based on + ** effective sample array. In the above, samples 0 and 1 are based on ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. ** ** Often, sample i of each block of N effective samples has (i+1) fields. ** Except, each sample may be extended to ensure that it is greater than or - ** equal to the previous sample in the array. For example, in the above, - ** sample 2 is the first sample of a block of N samples, so at first it - ** appears that it should be 1 field in size. However, that would make it - ** smaller than sample 1, so the binary search would not work. As a result, - ** it is extended to two fields. The duplicates that this creates do not + ** equal to the previous sample in the array. For example, in the above, + ** sample 2 is the first sample of a block of N samples, so at first it + ** appears that it should be 1 field in size. However, that would make it + ** smaller than sample 1, so the binary search would not work. As a result, + ** it is extended to two fields. The duplicates that this creates do not ** cause any problems. */ - if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ - nField = pIdx->nKeyCol; - }else{ - nField = pIdx->nColumn; - } - nField = MIN(pRec->nField, nField); + nField = pRec->nField; iCol = 0; iSample = pIdx->nSample * nField; do{ int iSamp; /* Index in aSample[] of test sample */ int n; /* Number of fields in test sample */ @@ -165180,11 +132471,11 @@ iTest = (iMin+iSample)/2; iSamp = iTest / nField; if( iSamp>0 ){ /* The proposed effective sample is a prefix of sample aSample[iSamp]. - ** Specifically, the shortest prefix of at least (1 + iTest%nField) + ** Specifically, the shortest prefix of at least (1 + iTest%nField) ** fields that is greater than the previous effective sample. */ for(n=(iTest % nField) + 1; nnSample ); assert( iCol==nField-1 ); pRec->nField = nField; - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) - || pParse->db->mallocFailed + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) + || pParse->db->mallocFailed ); }else{ /* Unless i==pIdx->nSample, indicating that pRec is larger than ** all samples in the aSample[] array, pRec must be smaller than the ** (iCol+1) field prefix of sample i. */ assert( i<=pIdx->nSample && i>=0 ); pRec->nField = iCol+1; - assert( i==pIdx->nSample + assert( i==pIdx->nSample || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 || pParse->db->mallocFailed ); /* if i==0 and iCol==0, then record pRec is smaller than all samples ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must @@ -165235,16 +132526,16 @@ ** be greater than or equal to the (iCol) field prefix of sample i. ** If (i>0), then pRec must also be greater than sample (i-1). */ if( iCol>0 ){ pRec->nField = iCol; assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 - || pParse->db->mallocFailed || CORRUPT_DB ); + || pParse->db->mallocFailed ); } if( i>0 ){ pRec->nField = nField; assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 - || pParse->db->mallocFailed || CORRUPT_DB ); + || pParse->db->mallocFailed ); } } } #endif /* ifdef SQLITE_DEBUG */ @@ -165252,16 +132543,16 @@ /* Record pRec is equal to sample i */ assert( iCol==nField-1 ); aStat[0] = aSample[i].anLt[iCol]; aStat[1] = aSample[i].anEq[iCol]; }else{ - /* At this point, the (iCol+1) field prefix of aSample[i] is the first + /* At this point, the (iCol+1) field prefix of aSample[i] is the first ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec ** is larger than all samples in the array. */ tRowcnt iUpper, iGap; if( i>=pIdx->nSample ){ - iUpper = pIdx->nRowEst0; + iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); }else{ iUpper = aSample[i].anLt[iCol]; } if( iLower>=iUpper ){ @@ -165280,15 +132571,15 @@ /* Restore the pRec->nField value before returning. */ pRec->nField = nField; return i; } -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* ** If it is not NULL, pTerm is a term that provides an upper or lower -** bound on a range scan. Without considering pTerm, it is estimated +** bound on a range scan. Without considering pTerm, it is estimated ** that the scan will visit nNew rows. This function returns the number ** estimated to be visited after taking pTerm into account. ** ** If the user explicitly specified a likelihood() value for this term, ** then the return value is the likelihood multiplied by the number of @@ -165306,38 +132597,37 @@ } return nRet; } -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Return the affinity for a single column of an index. */ SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ assert( iCol>=0 && iColnColumn ); if( !pIdx->zColAff ){ if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; } - assert( pIdx->zColAff[iCol]!=0 ); return pIdx->zColAff[iCol]; } #endif -#ifdef SQLITE_ENABLE_STAT4 -/* +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* ** This function is called to estimate the number of rows visited by a ** range-scan on a skip-scan index. For example: ** ** CREATE INDEX i1 ON t1(a, b, c); ** SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?; ** -** Value pLoop->nOut is currently set to the estimated number of rows -** visited for scanning (a=? AND b=?). This function reduces that estimate +** Value pLoop->nOut is currently set to the estimated number of rows +** visited for scanning (a=? AND b=?). This function reduces that estimate ** by some factor to account for the (c BETWEEN ? AND ?) expression based -** on the stat4 data for the index. this scan will be performed multiple -** times (once for each (a,b) combination that matches a=?) is dealt with +** on the stat4 data for the index. this scan will be peformed multiple +** times (once for each (a,b) combination that matches a=?) is dealt with ** by the caller. ** ** It does this by scanning through all stat4 samples, comparing values ** extracted from pLower and pUpper with the corresponding column in each ** sample. If L and U are the number of samples found to be less than or @@ -165354,11 +132644,11 @@ ** Normally, this function sets *pbDone to 1 before returning. However, ** if no value can be extracted from either pLower or pUpper (and so the ** estimate of the number of rows delivered remains unchanged), *pbDone ** is left as is. ** -** If an error occurs, an SQLite error code is returned. Otherwise, +** If an error occurs, an SQLite error code is returned. Otherwise, ** SQLITE_OK. */ static int whereRangeSkipScanEst( Parse *pParse, /* Parsing & code generating context */ WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ @@ -165372,11 +132662,11 @@ int nLower = -1; int nUpper = p->nSample+1; int rc = SQLITE_OK; u8 aff = sqlite3IndexColumnAffinity(db, p, nEq); CollSeq *pColl; - + sqlite3_value *p1 = 0; /* Value extracted from pLower */ sqlite3_value *p2 = 0; /* Value extracted from pUpper */ sqlite3_value *pVal = 0; /* Value extracted from record */ pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]); @@ -165404,20 +132694,20 @@ } } nDiff = (nUpper - nLower); if( nDiff<=0 ) nDiff = 1; - /* If there is both an upper and lower bound specified, and the + /* If there is both an upper and lower bound specified, and the ** comparisons indicate that they are close together, use the fallback ** method (assume that the scan visits 1/64 of the rows) for estimating ** the number of rows visited. Otherwise, estimate the number of rows ** using the method described in the header comment for this function. */ if( nDiff!=1 || pUpper==0 || pLower==0 ){ int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff)); pLoop->nOut -= nAdjust; *pbDone = 1; - WHERETRACE(0x20, ("range skip-scan regions: %u..%u adjust=%d est=%d\n", + WHERETRACE(0x10, ("range skip-scan regions: %u..%u adjust=%d est=%d\n", nLower, nUpper, nAdjust*-1, pLoop->nOut)); } }else{ assert( *pbDone==0 ); @@ -165427,11 +132717,11 @@ sqlite3ValueFree(p2); sqlite3ValueFree(pVal); return rc; } -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* ** This function is used to estimate the number of rows that will be visited ** by scanning an index for a range of values. The range may have an upper ** bound, a lower bound, or both. The WHERE clause terms that set the upper @@ -165451,25 +132741,25 @@ ** equality constraints optimized by the proposed index scan. For example, ** assuming index p is on t1(a, b), and the SQL query is: ** ** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... ** -** then nEq is set to 1 (as the range restricted column, b, is the second +** then nEq is set to 1 (as the range restricted column, b, is the second ** left-most column of the index). Or, if the query is: ** ** ... FROM t1 WHERE a > ? AND a < ? ... ** ** then nEq is set to 0. ** ** When this function is called, *pnOut is set to the sqlite3LogEst() of the -** number of rows that the index scan is expected to visit without -** considering the range constraints. If nEq is 0, then *pnOut is the number of +** number of rows that the index scan is expected to visit without +** considering the range constraints. If nEq is 0, then *pnOut is the number of ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) ** to account for the range constraints pLower and pUpper. -** +** ** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be -** used, a single range inequality reduces the search space by a factor of 4. +** used, a single range inequality reduces the search space by a factor of 4. ** and a pair of constraints (x>? AND xnOut; LogEst nNew; -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 Index *p = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; - if( p->nSample>0 && ALWAYS(nEqnSampleCol) - && OptimizationEnabled(pParse->db, SQLITE_Stat4) - ){ + if( p->nSample>0 && nEqnSampleCol ){ if( nEq==pBuilder->nRecValid ){ UnpackedRecord *pRec = pBuilder->pRec; tRowcnt a[2]; int nBtm = pLoop->u.btree.nBtm; int nTop = pLoop->u.btree.nTop; - /* Variable iLower will be set to the estimate of the number of rows in + /* Variable iLower will be set to the estimate of the number of rows in ** the index that are less than the lower bound of the range query. The ** lower bound being the concatenation of $P and $L, where $P is the ** key-prefix formed by the nEq values matched against the nEq left-most ** columns of the index, and $L is the value in pLower. ** ** Or, if pLower is NULL or $L cannot be extracted from it (because it ** is not a simple variable or literal value), the lower bound of the ** range is $P. Due to a quirk in the way whereKeyStats() works, even - ** if $L is available, whereKeyStats() is called for both ($P) and + ** if $L is available, whereKeyStats() is called for both ($P) and ** ($P:$L) and the larger of the two returned values is used. ** ** Similarly, iUpper is to be set to the estimate of the number of rows ** less than the upper bound of the range query. Where the upper bound ** is either ($P) or ($P:$U). Again, even if $U is available, both values @@ -165526,11 +132814,11 @@ /* Determine iLower and iUpper using ($P) only. */ if( nEq==0 ){ iLower = 0; iUpper = p->nRowEst0; }else{ - /* Note: this call could be optimized away - since the same values must + /* Note: this call could be optimized away - since the same values must ** have been requested when testing key $P in whereEqualScanEst(). */ whereKeyStats(pParse, p, pRec, 0, a); iLower = a[0]; iUpper = a[0] + a[1]; } @@ -165583,20 +132871,19 @@ if( iUpper>iLower ){ nNew = sqlite3LogEst(iUpper - iLower); /* TUNING: If both iUpper and iLower are derived from the same ** sample, then assume they are 4x more selective. This brings ** the estimated selectivity more in line with what it would be - ** if estimated without the use of STAT4 tables. */ - if( iLwrIdx==iUprIdx ){ nNew -= 20; } - assert( 20==sqlite3LogEst(4) ); + ** if estimated without the use of STAT3/4 tables. */ + if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) ); }else{ nNew = 10; assert( 10==sqlite3LogEst(2) ); } if( nNewwtFlags & TERM_VNULL)==0 || pParse->nErr>0 ); + assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); nNew = whereRangeAdjust(pLower, nOut); nNew = whereRangeAdjust(pUpper, nNew); /* TUNING: If there is both an upper and lower limit and neither limit ** has an application-defined likelihood(), assume the range is ** reduced by an additional 75%. This means that, by default, an open-ended ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to - ** match 1/64 of the index. */ + ** match 1/64 of the index. */ if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){ nNew -= 20; } nOut -= (pLower!=0) + (pUpper!=0); if( nNew<10 ) nNew = 10; if( nNewnOut>nOut ){ - WHERETRACE(0x20,("Range scan lowers nOut from %d to %d\n", + WHERETRACE(0x10,("Range scan lowers nOut from %d to %d\n", pLoop->nOut, nOut)); } #endif pLoop->nOut = (LogEst)nOut; return rc; } -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Estimate the number of rows that will be returned based on ** an equality constraint x=VALUE and where that VALUE occurs in ** the histogram data. This only works when x is the left-most -** column of an index and sqlite_stat4 histogram data is available +** column of an index and sqlite_stat3 histogram data is available ** for that index. When pExpr==NULL that means the constraint is ** "x IS NULL" instead of "x=VALUE". ** -** Write the estimated row count into *pnRow and return SQLITE_OK. +** Write the estimated row count into *pnRow and return SQLITE_OK. ** If unable to make an estimate, leave *pnRow unchanged and return ** non-zero. ** ** This routine can fail if it is unable to load a collating sequence ** required for string comparison, or if unable to allocate memory @@ -165690,27 +132977,27 @@ if( rc!=SQLITE_OK ) return rc; if( bOk==0 ) return SQLITE_NOTFOUND; pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x20,("equality scan regions %s(%d): %d\n", + WHERETRACE(0x10,("equality scan regions %s(%d): %d\n", p->zName, nEq-1, (int)a[1])); *pnRow = a[1]; - + return rc; } -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Estimate the number of rows that will be returned based on ** an IN constraint where the right-hand side of the IN operator ** is a list of values. Example: ** ** WHERE x IN (1,2,3,4) ** -** Write the estimated row count into *pnRow and return SQLITE_OK. +** Write the estimated row count into *pnRow and return SQLITE_OK. ** If unable to make an estimate, leave *pnRow unchanged and return ** non-zero. ** ** This routine can fail if it is unable to load a collating sequence ** required for string comparison, or if unable to allocate memory @@ -165738,114 +133025,83 @@ nRowEst += nEst; pBuilder->nRecValid = nRecValid; } if( rc==SQLITE_OK ){ - if( nRowEst > (tRowcnt)nRow0 ) nRowEst = nRow0; + if( nRowEst > nRow0 ) nRowEst = nRow0; *pnRow = nRowEst; - WHERETRACE(0x20,("IN row estimate: est=%d\n", nRowEst)); + WHERETRACE(0x10,("IN row estimate: est=%d\n", nRowEst)); } assert( pBuilder->nRecValid==nRecValid ); return rc; } -#endif /* SQLITE_ENABLE_STAT4 */ +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ -#if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG) +#ifdef WHERETRACE_ENABLED /* ** Print the content of a WhereTerm object */ -SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){ +static void whereTermPrint(WhereTerm *pTerm, int iTerm){ if( pTerm==0 ){ sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm); }else{ - char zType[8]; + char zType[4]; char zLeft[50]; - memcpy(zType, "....", 5); + memcpy(zType, "...", 4); if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; - if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) zType[2] = 'L'; - if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C'; + if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; if( pTerm->eOperator & WO_SINGLE ){ - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}", - pTerm->leftCursor, pTerm->u.x.leftColumn); + pTerm->leftCursor, pTerm->u.leftColumn); }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){ - sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx", + sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", pTerm->u.pOrInfo->indexable); }else{ sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); } sqlite3DebugPrintf( - "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x", - iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags); - /* The 0x10000 .wheretrace flag causes extra information to be - ** shown about each Term */ - if( sqlite3WhereTrace & 0x10000 ){ - sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx", - pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight); - } - if( (pTerm->eOperator & (WO_OR|WO_AND))==0 && pTerm->u.x.iField ){ - sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField); - } - if( pTerm->iParent>=0 ){ - sqlite3DebugPrintf(" iParent=%d", pTerm->iParent); - } - sqlite3DebugPrintf("\n"); + "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x", + iTerm, pTerm, zType, zLeft, pTerm->truthProb, + pTerm->eOperator, pTerm->wtFlags); + if( pTerm->iField ){ + sqlite3DebugPrintf(" iField=%d\n", pTerm->iField); + }else{ + sqlite3DebugPrintf("\n"); + } sqlite3TreeViewExpr(0, pTerm->pExpr, 0); } } -SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){ - sqlite3WhereTermPrint(pTerm, 0); -} #endif #ifdef WHERETRACE_ENABLED /* ** Show the complete content of a WhereClause */ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){ int i; for(i=0; inTerm; i++){ - sqlite3WhereTermPrint(&pWC->a[i], i); + whereTermPrint(&pWC->a[i], i); } } #endif #ifdef WHERETRACE_ENABLED /* ** Print a WhereLoop object for debugging purposes -** -** Format example: -** -** .--- Position in WHERE clause rSetup, rRun, nOut ---. -** | | -** | .--- selfMask nTerm ------. | -** | | | | -** | | .-- prereq Idx wsFlags----. | | -** | | | Name | | | -** | | | __|__ nEq ---. ___|__ | __|__ -** | / \ / \ / \ | / \ / \ / \ -** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31 */ -SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){ - WhereInfo *pWInfo; - if( pWC ){ - pWInfo = pWC->pWInfo; - int nb = 1+(pWInfo->pTabList->nSrc+3)/4; - SrcItem *pItem = pWInfo->pTabList->a + p->iTab; - Table *pTab = pItem->pSTab; - Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; - sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, - p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); - sqlite3DebugPrintf(" %12s", - pItem->zAlias ? pItem->zAlias : pTab->zName); - }else{ - pWInfo = 0; - sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d", - p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab); - } +static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ + WhereInfo *pWInfo = pWC->pWInfo; + int nb = 1+(pWInfo->pTabList->nSrc+3)/4; + struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab; + Table *pTab = pItem->pTab; + Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; + sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, + p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); + sqlite3DebugPrintf(" %12s", + pItem->zAlias ? pItem->zAlias : pTab->zName); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ const char *zName; if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ int i = sqlite3Strlen30(zName) - 1; @@ -165857,43 +133113,29 @@ sqlite3DebugPrintf("%20s",""); } }else{ char *z; if( p->u.vtab.idxStr ){ - z = sqlite3_mprintf("(%d,\"%s\",%#x)", + z = sqlite3_mprintf("(%d,\"%s\",%x)", p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask); }else{ z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask); } sqlite3DebugPrintf(" %-19s", z); sqlite3_free(z); } if( p->wsFlags & WHERE_SKIPSCAN ){ - sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); - }else{ - sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm); - } - if( pWInfo && pWInfo->bStarUsed && p->rStarDelta!=0 ){ - sqlite3DebugPrintf(" cost %d,%d,%d delta=%d\n", - p->rSetup, p->rRun, p->nOut, p->rStarDelta); - }else{ - sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); - } - if( p->nLTerm && (sqlite3WhereTrace & 0x4000)!=0 ){ + sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); + }else{ + sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); + } + sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); + if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ int i; for(i=0; inLTerm; i++){ - sqlite3WhereTermPrint(p->aLTerm[i], i); - } - } -} -SQLITE_PRIVATE void sqlite3ShowWhereLoop(const WhereLoop *p){ - if( p ) sqlite3WhereLoopPrint(p, 0); -} -SQLITE_PRIVATE void sqlite3ShowWhereLoopList(const WhereLoop *p){ - while( p ){ - sqlite3ShowWhereLoop(p); - p = p->pNextLoop; + whereTermPrint(p->aLTerm[i], i); + } } } #endif /* @@ -165923,22 +133165,16 @@ } } } /* -** Deallocate internal memory used by a WhereLoop object. Leave the -** object in an initialized state, as if it had been newly allocated. +** Deallocate internal memory used by a WhereLoop object */ static void whereLoopClear(sqlite3 *db, WhereLoop *p){ - if( p->aLTerm!=p->aLTermSpace ){ - sqlite3DbFreeNN(db, p->aLTerm); - p->aLTerm = p->aLTermSpace; - p->nLSlot = ArraySize(p->aLTermSpace); - } + if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm); whereLoopClearUnion(db, p); - p->nLTerm = 0; - p->wsFlags = 0; + whereLoopInit(p); } /* ** Increase the memory allocation for pLoop->aLTerm[] to be at least n. */ @@ -165958,14 +133194,12 @@ /* ** Transfer content from the second pLoop into the first. */ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ whereLoopClearUnion(db, pTo); - if( pFrom->nLTerm > pTo->nLSlot - && whereLoopResize(db, pTo, pFrom->nLTerm) - ){ - memset(pTo, 0, WHERE_LOOP_XFER_SZ); + if( whereLoopResize(db, pTo, pFrom->nLTerm) ){ + memset(&pTo->u, 0, sizeof(pTo->u)); return SQLITE_NOMEM_BKPT; } memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ @@ -165978,95 +133212,79 @@ /* ** Delete a WhereLoop object */ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ - assert( db!=0 ); whereLoopClear(db, p); - sqlite3DbNNFreeNN(db, p); + sqlite3DbFreeNN(db, p); } /* ** Free a WhereInfo structure */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - assert( pWInfo!=0 ); - assert( db!=0 ); - sqlite3WhereClauseClear(&pWInfo->sWC); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); - } - while( pWInfo->pMemToFree ){ - WhereMemBlock *pNext = pWInfo->pMemToFree->pNext; - sqlite3DbNNFreeNN(db, pWInfo->pMemToFree); - pWInfo->pMemToFree = pNext; - } - sqlite3DbNNFreeNN(db, pWInfo); + if( ALWAYS(pWInfo) ){ + int i; + for(i=0; inLevel; i++){ + WhereLevel *pLevel = &pWInfo->a[i]; + if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ + sqlite3DbFree(db, pLevel->u.in.aInLoop); + } + } + sqlite3WhereClauseClear(&pWInfo->sWC); + while( pWInfo->pLoops ){ + WhereLoop *p = pWInfo->pLoops; + pWInfo->pLoops = p->pNextLoop; + whereLoopDelete(db, p); + } + sqlite3DbFreeNN(db, pWInfo); + } } /* -** Return TRUE if X is a proper subset of Y but is of equal or less cost. -** In other words, return true if all constraints of X are also part of Y -** and Y has additional constraints that might speed the search that X lacks -** but the cost of running X is not more than the cost of running Y. -** -** In other words, return true if the cost relationship between X and Y -** is inverted and needs to be adjusted. -** -** Case 1: -** -** (1a) X and Y use the same index. -** (1b) X has fewer == terms than Y -** (1c) Neither X nor Y use skip-scan -** (1d) X does not have a a greater cost than Y -** -** Case 2: -** -** (2a) X has the same or lower cost, or returns the same or fewer rows, -** than Y. -** (2b) X uses fewer WHERE clause terms than Y -** (2c) Every WHERE clause term used by X is also used by Y -** (2d) X skips at least as many columns as Y -** (2e) If X is a covering index, than Y is too +** Return TRUE if all of the following are true: +** +** (1) X has the same or lower cost that Y +** (2) X is a proper subset of Y +** (3) X skips at least as many columns as Y +** +** By "proper subset" we mean that X uses fewer WHERE clause terms +** than Y and that every WHERE clause term used by X is also used +** by Y. +** +** If X is a proper subset of Y then Y is a better choice and ought +** to have a lower cost. This routine returns TRUE when that cost +** relationship is inverted and needs to be adjusted. The third rule +** was added because if X uses skip-scan less than Y it still might +** deserve a lower cost even if it is a proper subset of Y. */ static int whereLoopCheaperProperSubset( const WhereLoop *pX, /* First WhereLoop to compare */ const WhereLoop *pY /* Compare against this WhereLoop */ ){ int i, j; - if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; /* (1d) and (2a) */ - assert( (pX->wsFlags & WHERE_VIRTUALTABLE)==0 ); - assert( (pY->wsFlags & WHERE_VIRTUALTABLE)==0 ); - if( pX->u.btree.nEq < pY->u.btree.nEq /* (1b) */ - && pX->u.btree.pIndex==pY->u.btree.pIndex /* (1a) */ - && pX->nSkip==0 && pY->nSkip==0 /* (1c) */ - ){ - return 1; /* Case 1 is true */ - } if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ - return 0; /* (2b) */ + return 0; /* X is not a subset of Y */ } - if( pY->nSkip > pX->nSkip ) return 0; /* (2d) */ + if( pY->nSkip > pX->nSkip ) return 0; + if( pX->rRun >= pY->rRun ){ + if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */ + if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */ + } for(i=pX->nLTerm-1; i>=0; i--){ if( pX->aLTerm[i]==0 ) continue; for(j=pY->nLTerm-1; j>=0; j--){ if( pY->aLTerm[j]==pX->aLTerm[i] ) break; } - if( j<0 ) return 0; /* (2c) */ + if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ } - if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 - && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ - return 0; /* (2e) */ - } - return 1; /* Case 2 is true */ + return 1; /* All conditions meet */ } /* -** Try to adjust the cost and number of output rows of WhereLoop pTemplate -** upwards or downwards so that: +** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so +** that: ** ** (1) pTemplate costs less than any other WhereLoops that are a proper ** subset of pTemplate ** ** (2) pTemplate costs more than any other WhereLoops for which pTemplate @@ -166080,27 +133298,23 @@ if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; for(; p; p=p->pNextLoop){ if( p->iTab!=pTemplate->iTab ) continue; if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; if( whereLoopCheaperProperSubset(p, pTemplate) ){ - /* Adjust pTemplate cost downward so that it is cheaper than its + /* Adjust pTemplate cost downward so that it is cheaper than its ** subset p. */ WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", - pTemplate->rRun, pTemplate->nOut, - MIN(p->rRun, pTemplate->rRun), - MIN(p->nOut - 1, pTemplate->nOut))); - pTemplate->rRun = MIN(p->rRun, pTemplate->rRun); - pTemplate->nOut = MIN(p->nOut - 1, pTemplate->nOut); + pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1)); + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut - 1; }else if( whereLoopCheaperProperSubset(pTemplate, p) ){ /* Adjust pTemplate cost upward so that it is costlier than p since ** pTemplate is a proper subset of p */ WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", - pTemplate->rRun, pTemplate->nOut, - MAX(p->rRun, pTemplate->rRun), - MAX(p->nOut + 1, pTemplate->nOut))); - pTemplate->rRun = MAX(p->rRun, pTemplate->rRun); - pTemplate->nOut = MAX(p->nOut + 1, pTemplate->nOut); + pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1)); + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut + 1; } } } /* @@ -166130,19 +133344,19 @@ continue; } /* In the current implementation, the rSetup value is either zero ** or the cost of building an automatic index (NlogN) and the NlogN ** is the same for compatible WhereLoops. */ - assert( p->rSetup==0 || pTemplate->rSetup==0 + assert( p->rSetup==0 || pTemplate->rSetup==0 || p->rSetup==pTemplate->rSetup ); /* whereLoopAddBtree() always generates and inserts the automatic index ** case first. Hence compatible candidate WhereLoops never have a larger ** rSetup. Call this SETUP-INVARIANT */ assert( p->rSetup>=pTemplate->rSetup ); - /* Any loop using an application-defined index (or PRIMARY KEY or + /* Any loop using an appliation-defined index (or PRIMARY KEY or ** UNIQUE constraint) with one or more == constraints is better ** than an automatic index. Unless it is a skip-scan. */ if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && (pTemplate->nSkip)==0 && (pTemplate->wsFlags & WHERE_INDEXED)!=0 @@ -166165,11 +133379,11 @@ return 0; /* Discard pTemplate */ } /* If pTemplate is always better than p, then cause p to be overwritten ** with pTemplate. pTemplate is better than p if: - ** (1) pTemplate has no more dependencies than p, and + ** (1) pTemplate has no more dependences than p, and ** (2) pTemplate has an equal or lower cost than p. */ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ && p->rRun>=pTemplate->rRun /* (2a) */ && p->nOut>=pTemplate->nOut /* (2b) */ @@ -166195,11 +133409,11 @@ ** information is gathered in the pBuilder->pOrSet object. This special ** processing mode is used only for OR clause processing. ** ** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we ** still might overwrite similar loops with the new template if the -** new template is better. Loops may be overwritten if the following +** new template is better. Loops may be overwritten if the following ** conditions are met: ** ** (1) They have the same iTab. ** (2) They have the same iSortIdx. ** (3) The template has same or fewer dependencies than the current loop @@ -166209,20 +133423,10 @@ WhereLoop **ppPrev, *p; WhereInfo *pWInfo = pBuilder->pWInfo; sqlite3 *db = pWInfo->pParse->db; int rc; - /* Stop the search once we hit the query planner search limit */ - if( pBuilder->iPlanLimit==0 ){ - WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); - if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; - return SQLITE_DONE; - } - pBuilder->iPlanLimit--; - - whereLoopAdjustCost(pWInfo->pLoops, pTemplate); - /* If pBuilder->pOrSet is defined, then only keep track of the costs ** and prereqs. */ if( pBuilder->pOrSet!=0 ){ if( pTemplate->nLTerm ){ @@ -166233,31 +133437,32 @@ whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, pTemplate->nOut); #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); - sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC); + whereLoopPrint(pTemplate, pBuilder->pWC); } #endif } return SQLITE_OK; } /* Look for an existing WhereLoop to replace with pTemplate */ + whereLoopAdjustCost(pWInfo->pLoops, pTemplate); ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate); if( ppPrev==0 ){ /* There already exists a WhereLoop on the list that is better ** than pTemplate, so just ignore pTemplate */ #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ sqlite3DebugPrintf(" skip: "); - sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC); + whereLoopPrint(pTemplate, pBuilder->pWC); } #endif - return SQLITE_OK; + return SQLITE_OK; }else{ p = *ppPrev; } /* If we reach this point it means that either p[] should be overwritten @@ -166266,16 +133471,16 @@ */ #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ if( p!=0 ){ sqlite3DebugPrintf("replace: "); - sqlite3WhereLoopPrint(p, pBuilder->pWC); + whereLoopPrint(p, pBuilder->pWC); sqlite3DebugPrintf(" with: "); }else{ sqlite3DebugPrintf(" add: "); } - sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC); + whereLoopPrint(pTemplate, pBuilder->pWC); } #endif if( p==0 ){ /* Allocate a new WhereLoop to add to the end of the list */ *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); @@ -166283,11 +133488,11 @@ whereLoopInit(p); p->pNextLoop = 0; }else{ /* We will be overwriting WhereLoop p[]. But before we do, first ** go through the rest of the list and delete any other entries besides - ** p[] that are also supplanted by pTemplate */ + ** p[] that are also supplated by pTemplate */ WhereLoop **ppTail = &p->pNextLoop; WhereLoop *pToDel; while( *ppTail ){ ppTail = whereLoopFindLesser(ppTail, pTemplate); if( ppTail==0 ) break; @@ -166295,20 +133500,20 @@ if( pToDel==0 ) break; *ppTail = pToDel->pNextLoop; #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ sqlite3DebugPrintf(" delete: "); - sqlite3WhereLoopPrint(pToDel, pBuilder->pWC); + whereLoopPrint(pToDel, pBuilder->pWC); } #endif whereLoopDelete(db, pToDel); } } rc = whereLoopXfer(db, p, pTemplate); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ Index *pIndex = p->u.btree.pIndex; - if( pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK ){ + if( pIndex && pIndex->tnum==0 ){ p->u.btree.pIndex = 0; } } return rc; } @@ -166347,77 +133552,50 @@ WhereLoop *pLoop, /* The loop to adjust downward */ LogEst nRow /* Number of rows in the entire table */ ){ WhereTerm *pTerm, *pX; Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); - int i, j; + int i, j, k; LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); - for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){ - assert( pTerm!=0 ); - if( (pTerm->prereqAll & notAllowed)!=0 ) continue; + for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ + if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break; if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; - if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue; + if( (pTerm->prereqAll & notAllowed)!=0 ) continue; for(j=pLoop->nLTerm-1; j>=0; j--){ pX = pLoop->aLTerm[j]; if( pX==0 ) continue; if( pX==pTerm ) break; if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; } if( j<0 ){ - sqlite3ProgressCheck(pWC->pWInfo->pParse); - if( pLoop->maskSelf==pTerm->prereqAll ){ - /* If there are extra terms in the WHERE clause not used by an index - ** that depend only on the table being scanned, and that will tend to - ** cause many rows to be omitted, then mark that table as - ** "self-culling". - ** - ** 2022-03-24: Self-culling only applies if either the extra terms - ** are straight comparison operators that are non-true with NULL - ** operand, or if the loop is not an OUTER JOIN. - */ - if( (pTerm->eOperator & 0x3f)!=0 - || (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype - & (JT_LEFT|JT_LTORJ))==0 - ){ - pLoop->wsFlags |= WHERE_SELFCULL; - } - } if( pTerm->truthProb<=0 ){ /* If a truth probability is specified using the likelihood() hints, ** then use the probability provided by the application. */ pLoop->nOut += pTerm->truthProb; }else{ /* In the absence of explicit truth probabilities, use heuristics to ** guess a reasonable truth probability. */ pLoop->nOut--; - if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 - && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */ - ){ + if( pTerm->eOperator&(WO_EQ|WO_IS) ){ Expr *pRight = pTerm->pExpr->pRight; - int k = 0; testcase( pTerm->pExpr->op==TK_IS ); - if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){ + if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){ k = 10; }else{ k = 20; } - if( iReducewtFlags |= TERM_HEURTRUTH; - iReduce = k; - } + if( iReducenOut > nRow-iReduce ){ - pLoop->nOut = nRow - iReduce; - } + if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; } -/* +/* ** Term pTerm is a vector range comparison operation. The first comparison ** in the vector can be optimized using column nEq of the index. This ** function returns the total number of vector elements that can be used ** as part of the range comparison. ** @@ -166442,33 +133620,30 @@ int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft); int i; nCmp = MIN(nCmp, (pIdx->nColumn - nEq)); for(i=1; ipExpr->pLeft) ); - pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr; - pRhs = pTerm->pExpr->pRight; - if( ExprUseXSelect(pRhs) ){ + Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr; + Expr *pRhs = pTerm->pExpr->pRight; + if( pRhs->flags & EP_xIsSelect ){ pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; }else{ pRhs = pRhs->x.pList->a[i].pExpr; } /* Check that the LHS of the comparison is a column reference to ** the right column of the right source table. And that the sort ** order of the index column is the same as the sort order of the ** leftmost index column. */ - if( pLhs->op!=TK_COLUMN - || pLhs->iTable!=iCur - || pLhs->iColumn!=pIdx->aiColumn[i+nEq] + if( pLhs->op!=TK_COLUMN + || pLhs->iTable!=iCur + || pLhs->iColumn!=pIdx->aiColumn[i+nEq] || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq] ){ break; } @@ -166483,38 +133658,38 @@ } return i; } /* -** Adjust the cost C by the costMult factor T. This only occurs if +** Adjust the cost C by the costMult facter T. This only occurs if ** compiled with -DSQLITE_ENABLE_COSTMULT */ #ifdef SQLITE_ENABLE_COSTMULT # define ApplyCostMultiplier(C,T) C += T #else # define ApplyCostMultiplier(C,T) #endif /* -** We have so far matched pBuilder->pNew->u.btree.nEq terms of the +** We have so far matched pBuilder->pNew->u.btree.nEq terms of the ** index pIndex. Try to match one more. ** -** When this function is called, pBuilder->pNew->nOut contains the -** number of rows expected to be visited by filtering using the nEq -** terms only. If it is modified, this value is restored before this +** When this function is called, pBuilder->pNew->nOut contains the +** number of rows expected to be visited by filtering using the nEq +** terms only. If it is modified, this value is restored before this ** function returns. ** -** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is -** a fake index used for the INTEGER PRIMARY KEY. +** If pProbe->tnum==0, that means pIndex is a fake index used for the +** INTEGER PRIMARY KEY. */ static int whereLoopAddBtreeIndex( WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ - SrcItem *pSrc, /* FROM clause term being analyzed */ + struct SrcList_item *pSrc, /* FROM clause term being analyzed */ Index *pProbe, /* An index on pSrc */ LogEst nInMul /* log(Number of iterations due to IN) */ ){ - WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyze context */ + WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ WhereTerm *pTerm; /* A WhereTerm under consideration */ int opMask; /* Valid operators for constraints */ @@ -166531,36 +133706,25 @@ LogEst rSize; /* Number of rows in the table */ LogEst rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ pNew = pBuilder->pNew; - assert( db->mallocFailed==0 || pParse->nErr>0 ); - if( pParse->nErr ){ - return pParse->rc; - } - WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n", - pProbe->pTable->zName,pProbe->zName, - pNew->u.btree.nEq, pNew->nSkip, pNew->rRun)); + if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; + WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n", + pProbe->zName, pNew->u.btree.nEq)); assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else{ assert( pNew->u.btree.nBtm==0 ); opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; } - if( pProbe->bUnordered || pProbe->bLowQual ){ - if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); - if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){ - opMask &= ~(WO_EQ|WO_IN|WO_IS); - } - } + if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); assert( pNew->u.btree.nEqnColumn ); - assert( pNew->u.btree.nEqnKeyCol - || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY ); saved_nEq = pNew->u.btree.nEq; saved_nBtm = pNew->u.btree.nBtm; saved_nTop = pNew->u.btree.nTop; saved_nSkip = pNew->nSkip; @@ -166576,11 +133740,11 @@ for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ LogEst rCostIdx; LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */ int nIn = 0; -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nRecValid = pBuilder->nRecValid; #endif if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) && indexColumnNotNull(pProbe, saved_nEq) ){ @@ -166590,42 +133754,46 @@ /* Do not allow the upper bound of a LIKE optimization range constraint ** to mix with a lower range bound from some other source */ if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; - if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 - && !constraintCompatibleWithOuterJoin(pTerm,pSrc) + /* Do not allow IS constraints from the WHERE clause to be used by the + ** right table of a LEFT JOIN. Only constraints in the ON clause are + ** allowed */ + if( (pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + && (eOp & (WO_IS|WO_ISNULL))!=0 ){ + testcase( eOp & WO_IS ); + testcase( eOp & WO_ISNULL ); continue; } + if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ - pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE; + pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; }else{ - pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED; + pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; } pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->u.btree.nBtm = saved_nBtm; pNew->u.btree.nTop = saved_nTop; pNew->nLTerm = saved_nLTerm; - if( pNew->nLTerm>=pNew->nLSlot - && whereLoopResize(db, pNew, pNew->nLTerm+1) - ){ - break; /* OOM while trying to enlarge the pNew->aLTerm array */ - } + if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTerm; pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; assert( nInMul==0 - || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 - || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 - || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 + || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 + || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 + || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 ); if( eOp & WO_IN ){ Expr *pExpr = pTerm->pExpr; - if( ExprUseXSelect(pExpr) ){ + pNew->wsFlags |= WHERE_COLUMN_IN; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ int i; nIn = 46; assert( 46==sqlite3LogEst(25) ); /* The expression may actually be of the form (x, y) IN (SELECT...). @@ -166637,118 +133805,70 @@ if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; } }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); - } - if( pProbe->hasStat1 && rLogSize>=10 ){ - LogEst M, logK, x; - /* Let: - ** N = the total number of rows in the table - ** K = the number of entries on the RHS of the IN operator - ** M = the number of rows in the table that match terms to the - ** to the left in the same index. If the IN operator is on - ** the left-most index column, M==N. - ** - ** Given the definitions above, it is better to omit the IN operator - ** from the index lookup and instead do a scan of the M elements, - ** testing each scanned row against the IN operator separately, if: - ** - ** M*log(K) < K*log(N) - ** - ** Our estimates for M, K, and N might be inaccurate, so we build in - ** a safety margin of 2 (LogEst: 10) that favors using the IN operator - ** with the index, as using an index has better worst-case behavior. - ** If we do not have real sqlite_stat1 data, always prefer to use - ** the index. Do not bother with this optimization on very small - ** tables (less than 2 rows) as it is pointless in that case. - */ - M = pProbe->aiRowLogEst[saved_nEq]; - logK = estLog(nIn); - /* TUNING v----- 10 to bias toward indexed IN */ - x = M + logK + 10 - (nIn + rLogSize); - if( x>=0 ){ - WHERETRACE(0x40, - ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d) " - "prefers indexed lookup\n", - saved_nEq, M, logK, nIn, rLogSize, x)); - }else if( nInMul<2 && OptimizationEnabled(db, SQLITE_SeekScan) ){ - WHERETRACE(0x40, - ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d" - " nInMul=%d) prefers skip-scan\n", - saved_nEq, M, logK, nIn, rLogSize, x, nInMul)); - pNew->wsFlags |= WHERE_IN_SEEKSCAN; - }else{ - WHERETRACE(0x40, - ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d" - " nInMul=%d) prefers normal scan\n", - saved_nEq, M, logK, nIn, rLogSize, x, nInMul)); - continue; - } - } - pNew->wsFlags |= WHERE_COLUMN_IN; + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ + } }else if( eOp & (WO_EQ|WO_IS) ){ int iCol = pProbe->aiColumn[saved_nEq]; pNew->wsFlags |= WHERE_COLUMN_EQ; assert( saved_nEq==pNew->u.btree.nEq ); - if( iCol==XN_ROWID - || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) + if( iCol==XN_ROWID + || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ - if( iCol==XN_ROWID || pProbe->uniqNotNull - || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ)) - ){ + if( iCol>=0 && pProbe->uniqNotNull==0 ){ + pNew->wsFlags |= WHERE_UNQ_WANTED; + }else{ pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags |= WHERE_UNQ_WANTED; } } - if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS; }else if( eOp & WO_ISNULL ){ pNew->wsFlags |= WHERE_COLUMN_NULL; + }else if( eOp & (WO_GT|WO_GE) ){ + testcase( eOp & WO_GT ); + testcase( eOp & WO_GE ); + pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; + pNew->u.btree.nBtm = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); + pBtm = pTerm; + pTop = 0; + if( pTerm->wtFlags & TERM_LIKEOPT ){ + /* Range contraints that come from the LIKE optimization are + ** always used in pairs. */ + pTop = &pTerm[1]; + assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); + assert( pTop->wtFlags & TERM_LIKEOPT ); + assert( pTop->eOperator==WO_LT ); + if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ + pNew->aLTerm[pNew->nLTerm++] = pTop; + pNew->wsFlags |= WHERE_TOP_LIMIT; + pNew->u.btree.nTop = 1; + } }else{ - int nVecLen = whereRangeVectorLen( + assert( eOp & (WO_LT|WO_LE) ); + testcase( eOp & WO_LT ); + testcase( eOp & WO_LE ); + pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; + pNew->u.btree.nTop = whereRangeVectorLen( pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm ); - if( eOp & (WO_GT|WO_GE) ){ - testcase( eOp & WO_GT ); - testcase( eOp & WO_GE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; - pNew->u.btree.nBtm = nVecLen; - pBtm = pTerm; - pTop = 0; - if( pTerm->wtFlags & TERM_LIKEOPT ){ - /* Range constraints that come from the LIKE optimization are - ** always used in pairs. */ - pTop = &pTerm[1]; - assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); - assert( pTop->wtFlags & TERM_LIKEOPT ); - assert( pTop->eOperator==WO_LT ); - if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ - pNew->aLTerm[pNew->nLTerm++] = pTop; - pNew->wsFlags |= WHERE_TOP_LIMIT; - pNew->u.btree.nTop = 1; - } - }else{ - assert( eOp & (WO_LT|WO_LE) ); - testcase( eOp & WO_LT ); - testcase( eOp & WO_LE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; - pNew->u.btree.nTop = nVecLen; - pTop = pTerm; - pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? - pNew->aLTerm[pNew->nLTerm-2] : 0; - } + pTop = pTerm; + pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? + pNew->aLTerm[pNew->nLTerm-2] : 0; } /* At this point pNew->nOut is set to the number of rows expected to ** be visited by the index scan before considering term pTerm, or the - ** values of nIn and nInMul. In other words, assuming that all + ** values of nIn and nInMul. In other words, assuming that all ** "x IN(...)" terms are replaced with "x = ?". This block updates ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */ assert( pNew->nOut==saved_nOut ); if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - /* Adjust nOut using stat4 data. Or, if there is no stat4 + /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4 ** data, using some other estimate. */ whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); }else{ int nEq = ++pNew->u.btree.nEq; assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) ); @@ -166758,17 +133878,16 @@ assert( (eOp & WO_IN) || nIn==0 ); testcase( eOp & WO_IN ); pNew->nOut += pTerm->truthProb; pNew->nOut -= nIn; }else{ -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 tRowcnt nOut = 0; - if( nInMul==0 - && pProbe->nSample - && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol) - && ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr)) - && OptimizationEnabled(db, SQLITE_Stat4) + if( nInMul==0 + && pProbe->nSample + && pNew->u.btree.nEq<=pProbe->nSampleCol + && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) ){ Expr *pExpr = pTerm->pExpr; if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ testcase( eOp & WO_EQ ); testcase( eOp & WO_IS ); @@ -166779,76 +133898,35 @@ } if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ if( nOut ){ pNew->nOut = sqlite3LogEst(nOut); - if( nEq==1 - /* TUNING: Mark terms as "low selectivity" if they seem likely - ** to be true for half or more of the rows in the table. - ** See tag-202002240-1 */ - && pNew->nOut+10 > pProbe->aiRowLogEst[0] - ){ -#if WHERETRACE_ENABLED /* 0x01 */ - if( sqlite3WhereTrace & 0x20 ){ - sqlite3DebugPrintf( - "STAT4 determines term has low selectivity:\n"); - sqlite3WhereTermPrint(pTerm, 999); - } -#endif - pTerm->wtFlags |= TERM_HIGHTRUTH; - if( pTerm->wtFlags & TERM_HEURTRUTH ){ - /* If the term has previously been used with an assumption of - ** higher selectivity, then set the flag to rerun the - ** loop computations. */ - pBuilder->bldFlags2 |= SQLITE_BLDF2_2NDPASS; - } - } if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; pNew->nOut -= nIn; } } if( nOut==0 ) #endif { pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]); if( eOp & WO_ISNULL ){ - /* TUNING: If there is no likelihood() value, assume that a - ** "col IS NULL" expression matches twice as many rows + /* TUNING: If there is no likelihood() value, assume that a + ** "col IS NULL" expression matches twice as many rows ** as (col=?). */ pNew->nOut += 10; } } } } - /* Set rCostIdx to the estimated cost of visiting selected rows in the - ** index. The estimate is the sum of two values: - ** 1. The cost of doing one search-by-key to find the first matching - ** entry - ** 2. Stepping forward in the index pNew->nOut times to find all - ** additional matching entries. - */ - assert( pSrc->pSTab->szTabRow>0 ); - if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ - /* The pProbe->szIdxRow is low for an IPK table since the interior - ** pages are small. Thus szIdxRow gives a good estimate of seek cost. - ** But the leaf pages are full-size, so pProbe->szIdxRow would badly - ** under-estimate the scanning cost. */ - rCostIdx = pNew->nOut + 16; - }else{ - rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pSTab->szTabRow; - } - rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx); - - /* Estimate the cost of running the loop. If all data is coming - ** from the index, then this is just the cost of doing the index - ** lookup and scan. But if some data is coming out of the main table, - ** we also have to add in the cost of doing pNew->nOut searches to - ** locate the row in the main table that corresponds to the index entry. - */ - pNew->rRun = rCostIdx; - if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){ + /* Set rCostIdx to the cost of visiting selected rows in index. Add + ** it to pNew->rRun, which is currently set to the cost of the index + ** seek only. Then, if this is a non-covering index, add the cost of + ** visiting the rows in the main table. */ + rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; + pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); + if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); } ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult); nOutUnadjusted = pNew->nOut; @@ -166863,20 +133941,15 @@ pNew->nOut = nOutUnadjusted; } if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 && pNew->u.btree.nEqnColumn - && (pNew->u.btree.nEqnKeyCol || - pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY) ){ - if( pNew->u.btree.nEq>3 ){ - sqlite3ProgressCheck(pParse); - } whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); } pNew->nOut = saved_nOut; -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 pBuilder->nRecValid = nRecValid; #endif } pNew->prereq = saved_prereq; pNew->u.btree.nEq = saved_nEq; @@ -166887,25 +133960,22 @@ pNew->nOut = saved_nOut; pNew->nLTerm = saved_nLTerm; /* Consider using a skip-scan if there are no WHERE clause constraints ** available for the left-most terms of the index, and if the average - ** number of repeats in the left-most terms is at least 18. + ** number of repeats in the left-most terms is at least 18. ** ** The magic number 18 is selected on the basis that scanning 17 rows ** is almost always quicker than an index seek (even though if the index ** contains fewer than 2^17 rows we assume otherwise in other parts of - ** the code). And, even if it is not, it should not be too much slower. + ** the code). And, even if it is not, it should not be too much slower. ** On the other hand, the extra seeks could end up being significantly ** more expensive. */ assert( 42==sqlite3LogEst(18) ); if( saved_nEq==saved_nSkip && saved_nEq+1nKeyCol - && saved_nEq==pNew->nLTerm && pProbe->noSkipScan==0 - && pProbe->hasStat1!=0 - && OptimizationEnabled(db, SQLITE_SkipScan) && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK ){ LogEst nIter; pNew->u.btree.nEq++; @@ -166922,12 +133992,12 @@ pNew->u.btree.nEq = saved_nEq; pNew->nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; } - WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", - pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); + WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n", + pProbe->zName, saved_nEq, rc)); return rc; } /* ** Return True if it is possible that pIndex might be useful in @@ -166947,300 +134017,68 @@ int ii, jj; if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr); - if( NEVER(pExpr==0) ) continue; - if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) - && pExpr->iTable==iCursor - ){ + Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); + if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ if( pExpr->iColumn<0 ) return 1; for(jj=0; jjnKeyCol; jj++){ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; } }else if( (aColExpr = pIndex->aColExpr)!=0 ){ for(jj=0; jjnKeyCol; jj++){ if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; - if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ + if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ return 1; } } } } return 0; } + +/* +** Return a bitmask where 1s indicate that the corresponding column of +** the table is used by an index. Only the first 63 columns are considered. +*/ +static Bitmask columnsInIndex(Index *pIdx){ + Bitmask m = 0; + int j; + for(j=pIdx->nColumn-1; j>=0; j--){ + int x = pIdx->aiColumn[j]; + if( x>=0 ){ + testcase( x==BMS-1 ); + testcase( x==BMS-2 ); + if( xpWInfo->pParse; + Parse *pParse = pWC->pWInfo->pParse; while( pWhere->op==TK_AND ){ - if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0; + if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0; pWhere = pWhere->pRight; } + if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0; for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr; - pExpr = pTerm->pExpr; - if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab) - && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON)) - && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) - && (pTerm->wtFlags & TERM_VNULL)==0 + Expr *pExpr = pTerm->pExpr; + if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) + && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) ){ return 1; } } return 0; } - -/* -** pIdx is an index containing expressions. Check it see if any of the -** expressions in the index match the pExpr expression. -*/ -static int exprIsCoveredByIndex( - const Expr *pExpr, - const Index *pIdx, - int iTabCur -){ - int i; - for(i=0; inColumn; i++){ - if( pIdx->aiColumn[i]==XN_EXPR - && sqlite3ExprCompare(0, pExpr, pIdx->aColExpr->a[i].pExpr, iTabCur)==0 - ){ - return 1; - } - } - return 0; -} - -/* -** Structure passed to the whereIsCoveringIndex Walker callback. -*/ -typedef struct CoveringIndexCheck CoveringIndexCheck; -struct CoveringIndexCheck { - Index *pIdx; /* The index */ - int iTabCur; /* Cursor number for the corresponding table */ - u8 bExpr; /* Uses an indexed expression */ - u8 bUnidx; /* Uses an unindexed column not within an indexed expr */ -}; - -/* -** Information passed in is pWalk->u.pCovIdxCk. Call it pCk. -** -** If the Expr node references the table with cursor pCk->iTabCur, then -** make sure that column is covered by the index pCk->pIdx. We know that -** all columns less than 63 (really BMS-1) are covered, so we don't need -** to check them. But we do need to check any column at 63 or greater. -** -** If the index does not cover the column, then set pWalk->eCode to -** non-zero and return WRC_Abort to stop the search. -** -** If this node does not disprove that the index can be a covering index, -** then just return WRC_Continue, to continue the search. -** -** If pCk->pIdx contains indexed expressions and one of those expressions -** matches pExpr, then prune the search. -*/ -static int whereIsCoveringIndexWalkCallback(Walker *pWalk, Expr *pExpr){ - int i; /* Loop counter */ - const Index *pIdx; /* The index of interest */ - const i16 *aiColumn; /* Columns contained in the index */ - u16 nColumn; /* Number of columns in the index */ - CoveringIndexCheck *pCk; /* Info about this search */ - - pCk = pWalk->u.pCovIdxCk; - pIdx = pCk->pIdx; - if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) ){ - /* if( pExpr->iColumn<(BMS-1) && pIdx->bHasExpr==0 ) return WRC_Continue;*/ - if( pExpr->iTable!=pCk->iTabCur ) return WRC_Continue; - pIdx = pWalk->u.pCovIdxCk->pIdx; - aiColumn = pIdx->aiColumn; - nColumn = pIdx->nColumn; - for(i=0; iiColumn ) return WRC_Continue; - } - pCk->bUnidx = 1; - return WRC_Abort; - }else if( pIdx->bHasExpr - && exprIsCoveredByIndex(pExpr, pIdx, pWalk->u.pCovIdxCk->iTabCur) ){ - pCk->bExpr = 1; - return WRC_Prune; - } - return WRC_Continue; -} - - -/* -** pIdx is an index that covers all of the low-number columns used by -** pWInfo->pSelect (columns from 0 through 62) or an index that has -** expressions terms. Hence, we cannot determine whether or not it is -** a covering index by using the colUsed bitmasks. We have to do a search -** to see if the index is covering. This routine does that search. -** -** The return value is one of these: -** -** 0 The index is definitely not a covering index -** -** WHERE_IDX_ONLY The index is definitely a covering index -** -** WHERE_EXPRIDX The index is likely a covering index, but it is -** difficult to determine precisely because of the -** expressions that are indexed. Score it as a -** covering index, but still keep the main table open -** just in case we need it. -** -** This routine is an optimization. It is always safe to return zero. -** But returning one of the other two values when zero should have been -** returned can lead to incorrect bytecode and assertion faults. -*/ -static SQLITE_NOINLINE u32 whereIsCoveringIndex( - WhereInfo *pWInfo, /* The WHERE clause context */ - Index *pIdx, /* Index that is being tested */ - int iTabCur /* Cursor for the table being indexed */ -){ - int i, rc; - struct CoveringIndexCheck ck; - Walker w; - if( pWInfo->pSelect==0 ){ - /* We don't have access to the full query, so we cannot check to see - ** if pIdx is covering. Assume it is not. */ - return 0; - } - if( pIdx->bHasExpr==0 ){ - for(i=0; inColumn; i++){ - if( pIdx->aiColumn[i]>=BMS-1 ) break; - } - if( i>=pIdx->nColumn ){ - /* pIdx does not index any columns greater than 62, but we know from - ** colMask that columns greater than 62 are used, so this is not a - ** covering index */ - return 0; - } - } - ck.pIdx = pIdx; - ck.iTabCur = iTabCur; - ck.bExpr = 0; - ck.bUnidx = 0; - memset(&w, 0, sizeof(w)); - w.xExprCallback = whereIsCoveringIndexWalkCallback; - w.xSelectCallback = sqlite3SelectWalkNoop; - w.u.pCovIdxCk = &ck; - sqlite3WalkSelect(&w, pWInfo->pSelect); - if( ck.bUnidx ){ - rc = 0; - }else if( ck.bExpr ){ - rc = WHERE_EXPRIDX; - }else{ - rc = WHERE_IDX_ONLY; - } - return rc; -} - -/* -** This is an sqlite3ParserAddCleanup() callback that is invoked to -** free the Parse->pIdxEpr list when the Parse object is destroyed. -*/ -static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){ - IndexedExpr **pp = (IndexedExpr**)pObject; - while( *pp!=0 ){ - IndexedExpr *p = *pp; - *pp = p->pIENext; - sqlite3ExprDelete(db, p->pExpr); - sqlite3DbFreeNN(db, p); - } -} - -/* -** This function is called for a partial index - one with a WHERE clause - in -** two scenarios. In both cases, it determines whether or not the WHERE -** clause on the index implies that a column of the table may be safely -** replaced by a constant expression. For example, in the following -** SELECT: -** -** CREATE INDEX i1 ON t1(b, c) WHERE a=; -** SELECT a, b, c FROM t1 WHERE a= AND b=?; -** -** The "a" in the select-list may be replaced by , iff: -** -** (a) is a constant expression, and -** (b) The (a=) comparison uses the BINARY collation sequence, and -** (c) Column "a" has an affinity other than NONE or BLOB. -** -** If argument pItem is NULL, then pMask must not be NULL. In this case this -** function is being called as part of determining whether or not pIdx -** is a covering index. This function clears any bits in (*pMask) -** corresponding to columns that may be replaced by constants as described -** above. -** -** Otherwise, if pItem is not NULL, then this function is being called -** as part of coding a loop that uses index pIdx. In this case, add entries -** to the Parse.pIdxPartExpr list for each column that can be replaced -** by a constant. -*/ -static void wherePartIdxExpr( - Parse *pParse, /* Parse context */ - Index *pIdx, /* Partial index being processed */ - Expr *pPart, /* WHERE clause being processed */ - Bitmask *pMask, /* Mask to clear bits in */ - int iIdxCur, /* Cursor number for index */ - SrcItem *pItem /* The FROM clause entry for the table */ -){ - assert( pItem==0 || (pItem->fg.jointype & JT_RIGHT)==0 ); - assert( (pItem==0 || pMask==0) && (pMask!=0 || pItem!=0) ); - - if( pPart->op==TK_AND ){ - wherePartIdxExpr(pParse, pIdx, pPart->pRight, pMask, iIdxCur, pItem); - pPart = pPart->pLeft; - } - - if( (pPart->op==TK_EQ || pPart->op==TK_IS) ){ - Expr *pLeft = pPart->pLeft; - Expr *pRight = pPart->pRight; - u8 aff; - - if( pLeft->op!=TK_COLUMN ) return; - if( !sqlite3ExprIsConstant(0, pRight) ) return; - if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; - if( pLeft->iColumn<0 ) return; - aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; - if( aff>=SQLITE_AFF_TEXT ){ - if( pItem ){ - sqlite3 *db = pParse->db; - IndexedExpr *p = (IndexedExpr*)sqlite3DbMallocRaw(db, sizeof(*p)); - if( p ){ - int bNullRow = (pItem->fg.jointype&(JT_LEFT|JT_LTORJ))!=0; - p->pExpr = sqlite3ExprDup(db, pRight, 0); - p->iDataCur = pItem->iCursor; - p->iIdxCur = iIdxCur; - p->iIdxCol = pLeft->iColumn; - p->bMaybeNullRow = bNullRow; - p->pIENext = pParse->pIdxPartExpr; - p->aff = aff; - pParse->pIdxPartExpr = p; - if( p->pIENext==0 ){ - void *pArg = (void*)&pParse->pIdxPartExpr; - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); - } - } - }else if( pLeft->iColumn<(BMS-1) ){ - *pMask &= ~((Bitmask)1 << pLeft->iColumn); - } - } - } -} - /* ** Add all WhereLoop objects for a single table of the join where the table ** is identified by pBuilder->pNew->iTab. That table is guaranteed to be ** a b-tree table, not a virtual table. @@ -167252,22 +134090,22 @@ ** ** cost = nRow * 3.0 // full-table scan ** cost = nRow * K // scan of covering index ** cost = nRow * (K+3.0) // scan of non-covering index ** -** where K is a value between 1.1 and 3.0 set based on the relative +** where K is a value between 1.1 and 3.0 set based on the relative ** estimated average size of the index and table records. ** ** For an index scan, where nVisit is the number of index rows visited -** by the scan, and nSeek is the number of seek operations required on +** by the scan, and nSeek is the number of seek operations required on ** the index b-tree: ** ** cost = nSeek * (log(nRow) + K * nVisit) // covering index ** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index ** -** Normally, nSeek is 1. nSeek values greater than 1 come about if the -** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when +** Normally, nSeek is 1. nSeek values greater than 1 come about if the +** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when ** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans. ** ** The estimated values (nRow, nVisit, nSeek) often contain a large amount ** of uncertainty. For this reason, scoring is designed to pick plans that ** "do the least harm" if the estimates are inaccurate. For example, a @@ -167276,39 +134114,39 @@ ** performance of using an index is far better than the worst-case performance ** of a full table scan. */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq /* Extra prerequisites for using this table */ + Bitmask mPrereq /* Extra prerequesites for using this table */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ Index sPk; /* A fake index object for the primary key */ LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */ i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */ SrcList *pTabList; /* The FROM clause */ - SrcItem *pSrc; /* The FROM clause btree term to add */ + struct SrcList_item *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ LogEst rSize; /* number of rows in the table */ + LogEst rLogSize; /* Logarithm of the number of rows in the table */ WhereClause *pWC; /* The parsed WHERE clause */ Table *pTab; /* Table being queried */ - + pNew = pBuilder->pNew; pWInfo = pBuilder->pWInfo; pTabList = pWInfo->pTabList; pSrc = pTabList->a + pNew->iTab; - pTab = pSrc->pSTab; + pTab = pSrc->pTab; pWC = pBuilder->pWC; - assert( !IsVirtual(pSrc->pSTab) ); + assert( !IsVirtual(pSrc->pTab) ); - if( pSrc->fg.isIndexedBy ){ - assert( pSrc->fg.isCte==0 ); + if( pSrc->pIBIndex ){ /* An INDEXED BY clause specifies a particular index to use */ - pProbe = pSrc->u2.pIBIndex; + pProbe = pSrc->pIBIndex; }else if( !HasRowid(pTab) ){ pProbe = pTab->pIndex; }else{ /* There is no INDEXED BY clause. Create a fake Index object in local ** variable sPk to represent the rowid primary key index. Make this @@ -167320,40 +134158,38 @@ sPk.nColumn = 1; sPk.aiColumn = &aiColumnPk; sPk.aiRowLogEst = aiRowEstPk; sPk.onError = OE_Replace; sPk.pTable = pTab; - sPk.szIdxRow = 3; /* TUNING: Interior rows of IPK table are very small */ - sPk.idxType = SQLITE_IDXTYPE_IPK; + sPk.szIdxRow = pTab->szTabRow; aiRowEstPk[0] = pTab->nRowLogEst; aiRowEstPk[1] = 0; - pFirst = pSrc->pSTab->pIndex; + pFirst = pSrc->pTab->pIndex; if( pSrc->fg.notIndexed==0 ){ /* The real indices of the table are only considered if the ** NOT INDEXED qualifier is omitted from the FROM clause */ sPk.pNext = pFirst; } pProbe = &sPk; } rSize = pTab->nRowLogEst; + rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet /* Not part of an OR optimization */ - && (pWInfo->wctrlFlags & (WHERE_RIGHT_JOIN|WHERE_OR_SUBCLAUSE))==0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 - && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */ + && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ + && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ && !pSrc->fg.isCorrelated /* Not a correlated subquery */ && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ - && (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */ ){ /* Generate auto-index WhereLoops */ - LogEst rLogSize; /* Logarithm of the number of rows in the table */ WhereTerm *pTerm; WhereTerm *pWCEnd = pWC->a + pWC->nTerm; - rLogSize = estLog(rSize); for(pTerm=pWC->a; rc==SQLITE_OK && pTermprereqRight & pNew->maskSelf ) continue; if( termCanDriveIndex(pTerm, pSrc, 0) ){ pNew->u.btree.nEq = 1; pNew->nSkip = 0; @@ -167361,21 +134197,18 @@ pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is ** estimated to be X*N*log2(N) where N is the number of rows in ** the table being indexed and where X is 7 (LogEst=28) for normal - ** tables or 0.5 (LogEst=-10) for views and subqueries. The value + ** tables or 1.375 (LogEst=4) for views and subqueries. The value ** of X is smaller for views and subqueries so that the query planner ** will be more aggressive about generating automatic indexes for ** those objects, since there is no opportunity to add schema ** indexes on subqueries and views. */ - pNew->rSetup = rLogSize + rSize; - if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){ - pNew->rSetup += 28; - }else{ - pNew->rSetup -= 25; /* Greatly reduced setup cost for auto indexes - ** on ephemeral materializations of views */ + pNew->rSetup = rLogSize + rSize + 4; + if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ + pNew->rSetup += 24; } ApplyCostMultiplier(pNew->rSetup, pTab->costMult); if( pNew->rSetup<0 ) pNew->rSetup = 0; /* TUNING: Each index lookup yields 20 rows in the table. This ** is more than the usual guess of 10 rows, since we have no way @@ -167389,23 +134222,18 @@ } } } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - /* Loop over all indices. If there was an INDEXED BY clause, then only - ** consider index pProbe. */ - for(; rc==SQLITE_OK && pProbe; - pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++ - ){ + /* Loop over all indices + */ + for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ if( pProbe->pPartIdxWhere!=0 - && !whereUsablePartialIndex(pSrc->iCursor, pSrc->fg.jointype, pWC, - pProbe->pPartIdxWhere) - ){ + && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){ testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ continue; /* Partial index inappropriate for this query */ } - if( pProbe->bNoQuery ) continue; rSize = pProbe->aiRowLogEst[0]; pNew->u.btree.nEq = 0; pNew->u.btree.nBtm = 0; pNew->u.btree.nTop = 0; pNew->nSkip = 0; @@ -167413,96 +134241,40 @@ pNew->iSortIdx = 0; pNew->rSetup = 0; pNew->prereq = mPrereq; pNew->nOut = rSize; pNew->u.btree.pIndex = pProbe; - pNew->u.btree.pOrderBy = 0; b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); - /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 ); - if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ + if( pProbe->tnum<=0 ){ /* Integer primary key index */ pNew->wsFlags = WHERE_IPK; /* Full table scan */ pNew->iSortIdx = b ? iSortIdx : 0; - /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an - ** extra cost designed to discourage the use of full table scans, - ** since index lookups have better worst-case performance if our - ** stat guesses are wrong. Reduce the 3.0 penalty slightly - ** (to 2.75) if we have valid STAT4 information for the table. - ** At 2.75, a full table scan is preferred over using an index on - ** a column with just two distinct values where each value has about - ** an equal number of appearances. Without STAT4 data, we still want - ** to use an index in that case, since the constraint might be for - ** the scarcer of the two values, and in that case an index lookup is - ** better. - */ -#ifdef SQLITE_ENABLE_STAT4 - pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0); -#else + /* TUNING: Cost of full table scan is (N*3.0). */ pNew->rRun = rSize + 16; -#endif ApplyCostMultiplier(pNew->rRun, pTab->costMult); whereLoopOutputAdjust(pWC, pNew, rSize); - if( pSrc->fg.isSubquery ){ - if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE; - pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy; - } rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; }else{ Bitmask m; if( pProbe->isCovering ){ - m = 0; - pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; - }else{ - m = pSrc->colUsed & pProbe->colNotIdxed; - if( pProbe->pPartIdxWhere ){ - wherePartIdxExpr( - pWInfo->pParse, pProbe, pProbe->pPartIdxWhere, &m, 0, 0 - ); - } - pNew->wsFlags = WHERE_INDEXED; - if( m==TOPBIT || (pProbe->bHasExpr && !pProbe->bHasVCol && m!=0) ){ - u32 isCov = whereIsCoveringIndex(pWInfo, pProbe, pSrc->iCursor); - if( isCov==0 ){ - WHERETRACE(0x200, - ("-> %s is not a covering index" - " according to whereIsCoveringIndex()\n", pProbe->zName)); - assert( m!=0 ); - }else{ - m = 0; - pNew->wsFlags |= isCov; - if( isCov & WHERE_IDX_ONLY ){ - WHERETRACE(0x200, - ("-> %s is a covering expression index" - " according to whereIsCoveringIndex()\n", pProbe->zName)); - }else{ - assert( isCov==WHERE_EXPRIDX ); - WHERETRACE(0x200, - ("-> %s might be a covering expression index" - " according to whereIsCoveringIndex()\n", pProbe->zName)); - } - } - }else if( m==0 - && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700)) - ){ - WHERETRACE(0x200, - ("-> %s a covering index according to bitmasks\n", - pProbe->zName, m==0 ? "is" : "is not")); - pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; - } + pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; + m = 0; + }else{ + m = pSrc->colUsed & ~columnsInIndex(pProbe); + pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; } /* Full scan via index */ if( b || !HasRowid(pTab) || pProbe->pPartIdxWhere!=0 - || pSrc->fg.isIndexedBy || ( m==0 && pProbe->bUnordered==0 && (pProbe->szIdxRowszTabRow) && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 && sqlite3GlobalConfig.bUseCis @@ -167537,72 +134309,45 @@ }else{ nLookup--; if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19; } } - + pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup); } ApplyCostMultiplier(pNew->rRun, pTab->costMult); whereLoopOutputAdjust(pWC, pNew, rSize); - if( (pSrc->fg.jointype & JT_RIGHT)!=0 && pProbe->aColExpr ){ - /* Do not do an SCAN of a index-on-expression in a RIGHT JOIN - ** because the cursor used to access the index might not be - ** positioned to the correct row during the right-join no-match - ** loop. */ - }else{ - rc = whereLoopInsert(pBuilder, pNew); - } + rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; } } - pBuilder->bldFlags1 = 0; + pBuilder->bldFlags = 0; rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); - if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){ + if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){ /* If a non-unique index is used, or if a prefix of the key for ** unique index is used (making the index functionally non-unique) ** then the sqlite_stat1 data becomes important for scoring the ** plan */ - pTab->tabFlags |= TF_MaybeReanalyze; + pTab->tabFlags |= TF_StatsUsed; } -#ifdef SQLITE_ENABLE_STAT4 +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3Stat4ProbeFree(pBuilder->pRec); pBuilder->nRecValid = 0; pBuilder->pRec = 0; #endif + + /* If there was an INDEXED BY clause, then only that one index is + ** considered. */ + if( pSrc->pIBIndex ) break; } return rc; } #ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Return true if pTerm is a virtual table LIMIT or OFFSET term. -*/ -static int isLimitTerm(WhereTerm *pTerm){ - assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 ); - return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT - && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET; -} - -/* -** Return true if the first nCons constraints in the pUsage array are -** marked as in-use (have argvIndex>0). False otherwise. -*/ -static int allConstraintsUsed( - struct sqlite3_index_constraint_usage *aUsage, - int nCons -){ - int ii; - for(ii=0; iipNew->iTab. This ** function marks a subset of those constraints usable, invokes the ** xBestIndex method and adds the returned plan to pBuilder. @@ -167626,38 +134371,35 @@ Bitmask mPrereq, /* Mask of tables that must be used. */ Bitmask mUsable, /* Mask of usable tables */ u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ u16 mNoOmit, /* Do not omit these constraints */ - int *pbIn, /* OUT: True if plan uses an IN(...) op */ - int *pbRetryLimit /* OUT: Retry without LIMIT/OFFSET */ + int *pbIn /* OUT: True if plan uses an IN(...) op */ ){ WhereClause *pWC = pBuilder->pWC; - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; int i; int mxTerm; int rc = SQLITE_OK; WhereLoop *pNew = pBuilder->pNew; Parse *pParse = pBuilder->pWInfo->pParse; - SrcItem *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; + struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; int nConstraint = pIdxInfo->nConstraint; assert( (mUsable & mPrereq)==mPrereq ); *pbIn = 0; pNew->prereq = mPrereq; - /* Set the usable flag on the subset of constraints identified by + /* Set the usable flag on the subset of constraints identified by ** arguments mUsable and mExclude. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; iiTermOffset); + WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset]; pIdxCons->usable = 0; - if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight + if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight && (pTerm->eOperator & mExclude)==0 - && (pbRetryLimit || !isLimitTerm(pTerm)) ){ pIdxCons->usable = 1; } } @@ -167668,119 +134410,69 @@ pIdxInfo->idxNum = 0; pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; pIdxInfo->idxFlags = 0; - pHidden->mHandleIn = 0; + pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; /* Invoke the virtual table xBestIndex() method */ - rc = vtabBestIndex(pParse, pSrc->pSTab, pIdxInfo); - if( rc ){ - if( rc==SQLITE_CONSTRAINT ){ - /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means - ** that the particular combination of parameters provided is unusable. - ** Make no entries in the loop table. - */ - WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n")); - freeIdxStr(pIdxInfo); - return SQLITE_OK; - } - return rc; - } + rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); + if( rc ) return rc; mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); - memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint ); - memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab)); + for(i=0; iaLTerm[i] = 0; + pNew->u.vtab.omitMask = 0; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i=0 ){ WhereTerm *pTerm; int j = pIdxCons->iTermOffset; if( iTerm>=nConstraint || j<0 - || (pTerm = termFromWhereClause(pWC, j))==0 + || j>=pWC->nTerm || pNew->aLTerm[iTerm]!=0 || pIdxCons->usable==0 ){ - sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName); - freeIdxStr(pIdxInfo); - return SQLITE_ERROR; + rc = SQLITE_ERROR; + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); + return rc; } testcase( iTerm==nConstraint-1 ); testcase( j==0 ); testcase( j==pWC->nTerm-1 ); + pTerm = &pWC->a[j]; pNew->prereq |= pTerm->prereqRight; assert( iTermnLSlot ); pNew->aLTerm[iTerm] = pTerm; if( iTerm>mxTerm ) mxTerm = iTerm; testcase( iTerm==15 ); testcase( iTerm==16 ); - if( pUsage[i].omit ){ - if( i<16 && ((1<u.vtab.omitMask |= 1<eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){ - pNew->u.vtab.bOmitOffset = 1; - } - } - if( SMASKBIT32(i) & pHidden->mHandleIn ){ - pNew->u.vtab.mHandleIn |= MASKBIT32(iTerm); - }else if( (pTerm->eOperator & WO_IN)!=0 ){ + if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0 ){ /* A virtual table that is constrained by an IN clause may not ** consume the ORDER BY clause because (1) the order of IN terms ** is not necessarily related to the order of output terms and ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } - - /* Unless pbRetryLimit is non-NULL, there should be no LIMIT/OFFSET - ** terms. And if there are any, they should follow all other terms. */ - assert( pbRetryLimit || !isLimitTerm(pTerm) ); - assert( !isLimitTerm(pTerm) || i>=nConstraint-2 ); - assert( !isLimitTerm(pTerm) || i==nConstraint-1 || isLimitTerm(pTerm+1) ); - - if( isLimitTerm(pTerm) && (*pbIn || !allConstraintsUsed(pUsage, i)) ){ - /* If there is an IN(...) term handled as an == (separate call to - ** xFilter for each value on the RHS of the IN) and a LIMIT or - ** OFFSET term handled as well, the plan is unusable. Similarly, - ** if there is a LIMIT/OFFSET and there are other unused terms, - ** the plan cannot be used. In these cases set variable *pbRetryLimit - ** to true to tell the caller to retry with LIMIT and OFFSET - ** disabled. */ - freeIdxStr(pIdxInfo); - *pbRetryLimit = 1; - return SQLITE_OK; - } - } - } - - pNew->nLTerm = mxTerm+1; - for(i=0; i<=mxTerm; i++){ - if( pNew->aLTerm[i]==0 ){ - /* The non-zero argvIdx values must be contiguous. Raise an - ** error if they are not */ - sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName); - freeIdxStr(pIdxInfo); - return SQLITE_ERROR; - } - } + } + } + pNew->u.vtab.omitMask &= ~mNoOmit; + + pNew->nLTerm = mxTerm+1; assert( pNew->nLTerm<=pNew->nLSlot ); pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; pIdxInfo->needToFreeIdxStr = 0; pNew->u.vtab.idxStr = pIdxInfo->idxStr; pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? pIdxInfo->nOrderBy : 0); - pNew->u.vtab.bIdxNumHex = (pIdxInfo->idxFlags&SQLITE_INDEX_SCAN_HEX)!=0; pNew->rSetup = 0; pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated @@ -167793,134 +134485,17 @@ rc = whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite3_free(pNew->u.vtab.idxStr); pNew->u.vtab.needFree = 0; } - WHERETRACE(0xffffffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n", + WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n", *pbIn, (sqlite3_uint64)mPrereq, (sqlite3_uint64)(pNew->prereq & ~mPrereq))); return rc; } -/* -** Return the collating sequence for a constraint passed into xBestIndex. -** -** pIdxInfo must be an sqlite3_index_info structure passed into xBestIndex. -** This routine depends on there being a HiddenIndexInfo structure immediately -** following the sqlite3_index_info structure. -** -** Return a pointer to the collation name: -** -** 1. If there is an explicit COLLATE operator on the constraint, return it. -** -** 2. Else, if the column has an alternative collation, return that. -** -** 3. Otherwise, return "BINARY". -*/ -SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - const char *zRet = 0; - if( iCons>=0 && iConsnConstraint ){ - CollSeq *pC = 0; - int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset; - Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr; - if( pX->pLeft ){ - pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX); - } - zRet = (pC ? pC->zName : sqlite3StrBINARY); - } - return zRet; -} - -/* -** Return true if constraint iCons is really an IN(...) constraint, or -** false otherwise. If iCons is an IN(...) constraint, set (if bHandle!=0) -** or clear (if bHandle==0) the flag to handle it using an iterator. -*/ -SQLITE_API int sqlite3_vtab_in(sqlite3_index_info *pIdxInfo, int iCons, int bHandle){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - u32 m = SMASKBIT32(iCons); - if( m & pHidden->mIn ){ - if( bHandle==0 ){ - pHidden->mHandleIn &= ~m; - }else if( bHandle>0 ){ - pHidden->mHandleIn |= m; - } - return 1; - } - return 0; -} - -/* -** This interface is callable from within the xBestIndex callback only. -** -** If possible, set (*ppVal) to point to an object containing the value -** on the right-hand-side of constraint iCons. -*/ -SQLITE_API int sqlite3_vtab_rhs_value( - sqlite3_index_info *pIdxInfo, /* Copy of first argument to xBestIndex */ - int iCons, /* Constraint for which RHS is wanted */ - sqlite3_value **ppVal /* Write value extracted here */ -){ - HiddenIndexInfo *pH = (HiddenIndexInfo*)&pIdxInfo[1]; - sqlite3_value *pVal = 0; - int rc = SQLITE_OK; - if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ - rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */ - }else{ - if( pH->aRhs[iCons]==0 ){ - WhereTerm *pTerm = termFromWhereClause( - pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset - ); - rc = sqlite3ValueFromExpr( - pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db), - SQLITE_AFF_BLOB, &pH->aRhs[iCons] - ); - testcase( rc!=SQLITE_OK ); - } - pVal = pH->aRhs[iCons]; - } - *ppVal = pVal; - - if( rc==SQLITE_OK && pVal==0 ){ /* IMP: R-19933-32160 */ - rc = SQLITE_NOTFOUND; /* IMP: R-36424-56542 */ - } - - return rc; -} - -/* -** Return true if ORDER BY clause may be handled as DISTINCT. -*/ -SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 ); - return pHidden->eDistinct; -} - -/* -** Cause the prepared statement that is associated with a call to -** xBestIndex to potentially use all schemas. If the statement being -** prepared is read-only, then just start read transactions on all -** schemas. But if this is a write operation, start writes on all -** schemas. -** -** This is used by the (built-in) sqlite_dbpage virtual table. -*/ -SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse *pParse){ - int nDb = pParse->db->nDb; - int i; - for(i=0; iwriteMask) ){ - for(i=0; ipNew->iTab. That table is guaranteed to be a virtual table. ** @@ -167927,22 +134502,22 @@ ** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and ** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause ** entries that occur before the virtual table in the FROM clause and are ** separated from it by at least one LEFT or CROSS JOIN. Similarly, the ** mUnusable mask contains all FROM clause entries that occur after the -** virtual table and are separated from it by at least one LEFT or -** CROSS JOIN. +** virtual table and are separated from it by at least one LEFT or +** CROSS JOIN. ** ** For example, if the query were: ** ** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6; ** ** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6). ** -** All the tables in mPrereq must be scanned before the current virtual -** table. So any terms for which all prerequisites are satisfied by -** mPrereq may be specified as "usable" in all calls to xBestIndex. +** All the tables in mPrereq must be scanned before the current virtual +** table. So any terms for which all prerequisites are satisfied by +** mPrereq may be specified as "usable" in all calls to xBestIndex. ** Conversely, all tables in mUnusable must be scanned after the current ** virtual table, so any terms for which the prerequisites overlap with ** mUnusable should always be configured as "not-usable" for xBestIndex. */ static int whereLoopAddVirtual( @@ -167952,94 +134527,86 @@ ){ int rc = SQLITE_OK; /* Return code */ WhereInfo *pWInfo; /* WHERE analysis context */ Parse *pParse; /* The parsing context */ WhereClause *pWC; /* The WHERE clause */ - SrcItem *pSrc; /* The FROM clause term to search */ + struct SrcList_item *pSrc; /* The FROM clause term to search */ sqlite3_index_info *p; /* Object to pass to xBestIndex() */ int nConstraint; /* Number of constraints in p */ int bIn; /* True if plan uses IN(...) operator */ WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ u16 mNoOmit; - int bRetry = 0; /* True to retry with LIMIT/OFFSET disabled */ assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; pWC = pBuilder->pWC; pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; - assert( IsVirtual(pSrc->pSTab) ); - p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit); + assert( IsVirtual(pSrc->pTab) ); + p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, + &mNoOmit); if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; pNew->nLTerm = 0; pNew->u.vtab.needFree = 0; nConstraint = p->nConstraint; if( whereLoopResize(pParse->db, pNew, nConstraint) ){ - freeIndexInfo(pParse->db, p); + sqlite3DbFree(pParse->db, p); return SQLITE_NOMEM_BKPT; } /* First call xBestIndex() with all constraints usable. */ - WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pSTab->zName)); - WHERETRACE(0x800, (" VirtualOne: all usable\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry - ); - if( bRetry ){ - assert( rc==SQLITE_OK ); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, 0 - ); - } + WHERETRACE(0x40, (" VirtualOne: all usable\n")); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); /* If the call to xBestIndex() with all terms enabled produced a plan - ** that does not require any source tables (IOW: a plan with mBest==0) - ** and does not use an IN(...) operator, then there is no point in making - ** any further calls to xBestIndex() since they will all return the same - ** result (if the xBestIndex() implementation is sane). */ - if( rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn) ){ + ** that does not require any source tables (IOW: a plan with mBest==0), + ** then there is no point in making any further calls to xBestIndex() + ** since they will all return the same result (if the xBestIndex() + ** implementation is sane). */ + if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){ int seenZero = 0; /* True if a plan with no prereqs seen */ int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ Bitmask mPrev = 0; Bitmask mBestNoIn = 0; /* If the plan produced by the earlier call uses an IN(...) term, call ** xBestIndex again, this time with IN(...) terms disabled. */ if( bIn ){ - WHERETRACE(0x800, (" VirtualOne: all usable w/o IN\n")); + WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0); + pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn); assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ seenZero = 1; seenZeroNoIN = 1; } } - /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) + /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) ** in the set of terms that apply to the current virtual table. */ while( rc==SQLITE_OK ){ int i; Bitmask mNext = ALLBITS; assert( mNext>0 ); for(i=0; iaConstraint[i].iTermOffset; - Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq; + Bitmask mThis = ( + pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq + ); if( mThis>mPrev && mThisprereq==mPrereq ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; } } @@ -168046,39 +134613,39 @@ /* If the calls to xBestIndex() in the above loop did not find a plan ** that requires no source tables at all (i.e. one guaranteed to be ** usable), make a call here with all source tables disabled */ if( rc==SQLITE_OK && seenZero==0 ){ - WHERETRACE(0x800, (" VirtualOne: all disabled\n")); + WHERETRACE(0x40, (" VirtualOne: all disabled\n")); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0); + pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn); if( bIn==0 ) seenZeroNoIN = 1; } /* If the calls to xBestIndex() have so far failed to find a plan ** that requires no source tables at all and does not use an IN(...) ** operator, make a final call to obtain one here. */ if( rc==SQLITE_OK && seenZeroNoIN==0 ){ - WHERETRACE(0x800, (" VirtualOne: all disabled and w/o IN\n")); + WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0); + pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); } } - freeIndexInfo(pParse->db, p); - WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pSTab->zName, rc)); + if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); + sqlite3DbFreeNN(pParse->db, p); return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Add WhereLoop entries to handle OR terms. This works for either ** btrees or virtual tables. */ static int whereLoopAddOr( - WhereLoopBuilder *pBuilder, - Bitmask mPrereq, + WhereLoopBuilder *pBuilder, + Bitmask mPrereq, Bitmask mUnusable ){ WhereInfo *pWInfo = pBuilder->pWInfo; WhereClause *pWC; WhereLoop *pNew; @@ -168086,71 +134653,67 @@ int rc = SQLITE_OK; int iCur; WhereClause tempWC; WhereLoopBuilder sSubBuild; WhereOrSet sSum, sCur; - SrcItem *pItem; - + struct SrcList_item *pItem; + pWC = pBuilder->pWC; pWCEnd = pWC->a + pWC->nTerm; pNew = pBuilder->pNew; memset(&sSum, 0, sizeof(sSum)); pItem = pWInfo->pTabList->a + pNew->iTab; iCur = pItem->iCursor; - /* The multi-index OR optimization does not work for RIGHT and FULL JOIN */ - if( pItem->fg.jointype & JT_RIGHT ) return SQLITE_OK; - for(pTerm=pWC->a; pTermeOperator & WO_OR)!=0 - && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 + && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int once = 1; int i, j; - + sSubBuild = *pBuilder; + sSubBuild.pOrderBy = 0; sSubBuild.pOrSet = &sCur; - WHERETRACE(0x400, ("Begin processing OR-clause %p\n", pTerm)); + WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm)); for(pOrTerm=pOrWC->a; pOrTermeOperator & WO_AND)!=0 ){ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; }else if( pOrTerm->leftCursor==iCur ){ tempWC.pWInfo = pWC->pWInfo; tempWC.pOuter = pWC; tempWC.op = TK_AND; tempWC.nTerm = 1; - tempWC.nBase = 1; tempWC.a = pOrTerm; sSubBuild.pWC = &tempWC; }else{ continue; } sCur.n = 0; #ifdef WHERETRACE_ENABLED - WHERETRACE(0x400, ("OR-term %d of %p has %d subterms:\n", + WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm)); - if( sqlite3WhereTrace & 0x20000 ){ + if( sqlite3WhereTrace & 0x400 ){ sqlite3WhereClausePrint(sSubBuild.pWC); } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pSTab) ){ + if( IsVirtual(pItem->pTab) ){ rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable); }else #endif { rc = whereLoopAddBtree(&sSubBuild, mPrereq); } if( rc==SQLITE_OK ){ rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable); } - testcase( rc==SQLITE_NOMEM && sCur.n>0 ); - testcase( rc==SQLITE_DONE ); + assert( rc==SQLITE_OK || sCur.n==0 ); if( sCur.n==0 ){ sSum.n = 0; break; }else if( once ){ whereOrMove(&sSum, &sCur); @@ -168176,12 +134739,12 @@ memset(&pNew->u, 0, sizeof(pNew->u)); for(i=0; rc==SQLITE_OK && irRun = sSum.a[i].rRun + 1; pNew->nOut = sSum.a[i].nOut; pNew->prereq = sSum.a[i].prereq; rc = whereLoopInsert(pBuilder, pNew); } - WHERETRACE(0x400, ("End processing OR-clause %p\n", pTerm)); + WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm)); } } return rc; } /* -** Add all WhereLoop objects for all tables +** Add all WhereLoop objects for all tables */ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo = pBuilder->pWInfo; Bitmask mPrereq = 0; Bitmask mPrior = 0; int iTab; SrcList *pTabList = pWInfo->pTabList; - SrcItem *pItem; - SrcItem *pEnd = &pTabList->a[pWInfo->nLevel]; + struct SrcList_item *pItem; + struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel]; sqlite3 *db = pWInfo->pParse->db; int rc = SQLITE_OK; - int bFirstPastRJ = 0; - int hasRightJoin = 0; WhereLoop *pNew; - + u8 priorJointype = 0; /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; - - /* Verify that pNew has already been initialized */ - assert( pNew->nLTerm==0 ); - assert( pNew->wsFlags==0 ); - assert( pNew->nLSlot>=ArraySize(pNew->aLTermSpace) ); - assert( pNew->aLTerm!=0 ); - - pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; + whereLoopInit(pNew); for(iTab=0, pItem=pTabList->a; pItemiTab = iTab; - pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); - if( bFirstPastRJ - || (pItem->fg.jointype & (JT_OUTER|JT_CROSS|JT_LTORJ))!=0 - ){ - /* Add prerequisites to prevent reordering of FROM clause terms - ** across CROSS joins and outer joins. The bFirstPastRJ boolean - ** prevents the right operand of a RIGHT JOIN from being swapped with - ** other elements even further to the right. - ** - ** The JT_LTORJ case and the hasRightJoin flag work together to - ** prevent FROM-clause terms from moving from the right side of - ** a LEFT JOIN over to the left side of that join if the LEFT JOIN - ** is itself on the left side of a RIGHT JOIN. - */ - if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1; - mPrereq |= mPrior; - bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0; - }else if( !hasRightJoin ){ - mPrereq = 0; - } + if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ + /* This condition is true when pItem is the FROM clause term on the + ** right-hand-side of a LEFT or CROSS JOIN. */ + mPrereq = mPrior; + } + priorJointype = pItem->fg.jointype; #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pSTab) ){ - SrcItem *p; + if( IsVirtual(pItem->pTab) ){ + struct SrcList_item *p; for(p=&pItem[1]; pfg.jointype & (JT_OUTER|JT_CROSS)) ){ + if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){ mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); } } rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ { rc = whereLoopAddBtree(pBuilder, mPrereq); } - if( rc==SQLITE_OK && pBuilder->pWC->hasOr ){ + if( rc==SQLITE_OK ){ rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); } mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ){ - if( rc==SQLITE_DONE ){ - /* We hit the query planner search limit set by iPlanLimit */ - sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); - rc = SQLITE_OK; - }else{ - break; - } - } + if( rc || db->mallocFailed ) break; } whereLoopClear(db, pNew); return rc; } -/* Implementation of the order-by-subquery optimization: -** -** WhereLoop pLoop, which the iLoop-th term of the nested loop, is really -** a subquery or CTE that has an ORDER BY clause. See if any of the terms -** in the subquery ORDER BY clause will satisfy pOrderBy from the outer -** query. Mark off all satisfied terms (by setting bits in *pOBSat) and -** return TRUE if they do. If not, return false. -** -** Example: -** -** CREATE TABLE t1(a,b,c, PRIMARY KEY(a,b)); -** CREATE TABLE t2(x,y); -** WITH t3(p,q) AS MATERIALIZED (SELECT x+y, x-y FROM t2 ORDER BY x+y) -** SELECT * FROM t3 JOIN t1 ON a=q ORDER BY p, b; -** -** The CTE named "t3" comes out in the natural order of "p", so the first -** first them of "ORDER BY p,b" is satisfied by a sequential scan of "t3" -** and sorting only needs to occur on the second term "b". -** -** Limitations: -** -** (1) The optimization is not applied if the outer ORDER BY contains -** a COLLATE clause. The optimization might be applied if the -** outer ORDER BY uses NULLS FIRST, NULLS LAST, ASC, and/or DESC as -** long as the subquery ORDER BY does the same. But if the -** outer ORDER BY uses COLLATE, even a redundant COLLATE, the -** optimization is bypassed. -** -** (2) The subquery ORDER BY terms must exactly match subquery result -** columns, including any COLLATE annotations. This routine relies -** on iOrderByCol to do matching between order by terms and result -** columns, and iOrderByCol will not be set if the result column -** and ORDER BY collations differ. -** -** (3) The subquery and outer ORDER BY can be in opposite directions as -** long as the subquery is materialized. If the subquery is -** implemented as a co-routine, the sort orders must be in the same -** direction because there is no way to run a co-routine backwards. -*/ -static SQLITE_NOINLINE int wherePathMatchSubqueryOB( - WhereInfo *pWInfo, /* The WHERE clause */ - WhereLoop *pLoop, /* The nested loop term that is a subquery */ - int iLoop, /* Which level of the nested loop. 0==outermost */ - int iCur, /* Cursor used by the this loop */ - ExprList *pOrderBy, /* The ORDER BY clause on the whole query */ - Bitmask *pRevMask, /* When loops need to go in reverse order */ - Bitmask *pOBSat /* Which terms of pOrderBy are satisfied so far */ -){ - int iOB; /* Index into pOrderBy->a[] */ - int jSub; /* Index into pSubOB->a[] */ - u8 rev = 0; /* True if iOB and jSub sort in opposite directions */ - u8 revIdx = 0; /* Sort direction for jSub */ - Expr *pOBExpr; /* Current term of outer ORDER BY */ - ExprList *pSubOB; /* Complete ORDER BY on the subquery */ - - pSubOB = pLoop->u.btree.pOrderBy; - assert( pSubOB!=0 ); - for(iOB=0; (MASKBIT(iOB) & *pOBSat)!=0; iOB++){} - for(jSub=0; jSubnExpr && iOBnExpr; jSub++, iOB++){ - if( pSubOB->a[jSub].u.x.iOrderByCol==0 ) break; - pOBExpr = pOrderBy->a[iOB].pExpr; - if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break; - if( pOBExpr->iTable!=iCur ) break; - if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break; - if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){ - u8 sfOB = pOrderBy->a[iOB].fg.sortFlags; /* sortFlags for iOB */ - u8 sfSub = pSubOB->a[jSub].fg.sortFlags; /* sortFlags for jSub */ - if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){ - break; - } - revIdx = sfSub & KEYINFO_ORDER_DESC; - if( jSub>0 ){ - if( (rev^revIdx)!=(sfOB & KEYINFO_ORDER_DESC) ){ - break; - } - }else{ - rev = revIdx ^ (sfOB & KEYINFO_ORDER_DESC); - if( rev ){ - if( (pLoop->wsFlags & WHERE_COROUTINE)!=0 ){ - /* Cannot run a co-routine in reverse order */ - break; - } - *pRevMask |= MASKBIT(iLoop); - } - } - } - *pOBSat |= MASKBIT(iOB); - } - return jSub>0; -} - /* ** Examine a WherePath (with the addition of the extra WhereLoop of the 6th ** parameters) to see if it outputs rows in the requested ORDER BY ** (or GROUP BY) without requiring a separate sort operation. Return N: -** +** ** N>0: N terms of the ORDER BY clause are satisfied ** N==0: No terms of the ORDER BY clause are satisfied -** N<0: Unknown yet how many terms of ORDER BY might be satisfied. +** N<0: Unknown yet how many terms of ORDER BY might be satisfied. ** ** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as ** strict. With GROUP BY and DISTINCT the only requirement is that ** equivalent rows appear immediately adjacent to one another. GROUP BY ** and DISTINCT do not require rows to appear in any particular order as long ** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT -** the pOrderBy terms can be matched in any order. With ORDER BY, the +** the pOrderBy terms can be matched in any order. With ORDER BY, the ** pOrderBy terms must be matched in strict left-to-right order. */ static i8 wherePathSatisfiesOrderBy( WhereInfo *pWInfo, /* The WHERE clause */ ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ @@ -168436,11 +134877,11 @@ ** We say the WhereLoop is "order-distinct" if the set of columns from ** that WhereLoop that are in the ORDER BY clause are different for every ** row of the WhereLoop. Every one-row WhereLoop is automatically ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause ** is not order-distinct. To be order-distinct is not quite the same as being - ** UNIQUE since a UNIQUE column or index can have multiple rows that + ** UNIQUE since a UNIQUE column or index can have multiple rows that ** are NULL and NULL values are equivalent for the purpose of order-distinct. ** To be order-distinct, the columns must be UNIQUE and NOT NULL. ** ** The rowid for a table is always UNIQUE and NOT NULL so whenever the ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is @@ -168456,30 +134897,24 @@ isOrderDistinct = 1; obDone = MASKBIT(nOrderBy)-1; orderDistinctMask = 0; ready = 0; eqOpMask = WO_EQ | WO_IS | WO_ISNULL; - if( wctrlFlags & (WHERE_ORDERBY_LIMIT|WHERE_ORDERBY_MAX|WHERE_ORDERBY_MIN) ){ - eqOpMask |= WO_IN; - } + if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN; for(iLoop=0; isOrderDistinct && obSat0 ) ready |= pLoop->maskSelf; if( iLoopaLoop[iLoop]; if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue; }else{ pLoop = pLast; } if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered - && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) - ){ - obSat = obDone; - } + if( pLoop->u.vtab.isOrdered ) obSat = obDone; break; - }else if( wctrlFlags & WHERE_DISTINCTBY ){ - pLoop->u.btree.nDistinctCol = 0; + }else{ + pLoop->u.btree.nIdxCol = 0; } iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; /* Mark off any ORDER BY term X that is a column in the table of ** the current loop for which there is term in the WHERE @@ -168486,67 +134921,52 @@ ** clause of the form X IS NULL or X=? that reference only outer ** loops. */ for(i=0; ia[i].pExpr); - if( NEVER(pOBExpr==0) ) continue; - if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue; + pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr); + if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, ~ready, eqOpMask, 0); if( pTerm==0 ) continue; if( pTerm->eOperator==WO_IN ){ - /* IN terms are only valid for sorting in the ORDER BY LIMIT + /* IN terms are only valid for sorting in the ORDER BY LIMIT ** optimization, and then only if they are actually used ** by the query plan */ - assert( wctrlFlags & - (WHERE_ORDERBY_LIMIT|WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ); + assert( wctrlFlags & WHERE_ORDERBY_LIMIT ); for(j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++){} if( j>=pLoop->nLTerm ) continue; } if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ - Parse *pParse = pWInfo->pParse; - CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[i].pExpr); - CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr); - assert( pColl1 ); - if( pColl2==0 || sqlite3StrICmp(pColl1->zName, pColl2->zName) ){ - continue; - } + const char *z1, *z2; + pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); + if( !pColl ) pColl = db->pDfltColl; + z1 = pColl->zName; + pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr); + if( !pColl ) pColl = db->pDfltColl; + z2 = pColl->zName; + if( sqlite3StrICmp(z1, z2)!=0 ) continue; testcase( pTerm->pExpr->op==TK_IS ); } obSat |= MASKBIT(i); } if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){ if( pLoop->wsFlags & WHERE_IPK ){ - if( pLoop->u.btree.pOrderBy - && OptimizationEnabled(db, SQLITE_OrderBySubq) - && wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur, - pOrderBy,pRevMask, &obSat) - ){ - nColumn = 0; - isOrderDistinct = 0; - }else{ - nColumn = 1; - } pIndex = 0; nKeyCol = 0; + nColumn = 1; }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){ return 0; }else{ nKeyCol = pIndex->nKeyCol; nColumn = pIndex->nColumn; assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); assert( pIndex->aiColumn[nColumn-1]==XN_ROWID || !HasRowid(pIndex->pTable)); - /* All relevant terms of the index must also be non-NULL in order - ** for isOrderDistinct to be true. So the isOrderDistinct value - ** computed here might be a false positive. Corrections will be - ** made at tag-20210426-1 below */ - isOrderDistinct = IsUniqueIndex(pIndex) - && (pLoop->wsFlags & WHERE_SKIPSCAN)==0; + isOrderDistinct = IsUniqueIndex(pIndex); } /* Loop through all columns of the index and deal with the ones ** that are not constrained by == or IN. */ @@ -168553,36 +134973,30 @@ rev = revSet = 0; distinctColumns = 0; for(j=0; j=pLoop->u.btree.nEq + assert( j>=pLoop->u.btree.nEq || (pLoop->aLTerm[j]==0)==(jnSkip) ); if( ju.btree.nEq && j>=pLoop->nSkip ){ u16 eOp = pLoop->aLTerm[j]->eOperator; /* Skip over == and IS and ISNULL terms. (Also skip IN terms when - ** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL - ** terms imply that the index is not UNIQUE NOT NULL in which case - ** the loop need to be marked as not order-distinct because it can - ** have repeated NULL rows. + ** doing WHERE_ORDERBY_LIMIT processing). ** - ** If the current term is a column of an ((?,?) IN (SELECT...)) + ** If the current term is a column of an ((?,?) IN (SELECT...)) ** expression for which the SELECT returns more than one column, ** check that it is the only column used by this loop. Otherwise, ** if it is one of two or more, none of the columns can be - ** considered to match an ORDER BY term. - */ + ** considered to match an ORDER BY term. */ if( (eOp & eqOpMask)!=0 ){ - if( eOp & (WO_ISNULL|WO_IS) ){ - testcase( eOp & WO_ISNULL ); - testcase( eOp & WO_IS ); + if( eOp & WO_ISNULL ){ testcase( isOrderDistinct ); isOrderDistinct = 0; } - continue; + continue; }else if( ALWAYS(eOp & WO_IN) ){ /* ALWAYS() justification: eOp is an equality operator due to the ** ju.btree.nEq constraint above. Any equality other ** than WO_IN is captured by the previous "if". So this one ** always has to be WO_IN. */ @@ -168600,85 +135014,68 @@ /* Get the column number in the table (iColumn) and sort order ** (revIdx) for the j-th column of the index. */ if( pIndex ){ iColumn = pIndex->aiColumn[j]; - revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC; - if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; + revIdx = pIndex->aSortOrder[j]; + if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; }else{ iColumn = XN_ROWID; revIdx = 0; } /* An unconstrained column that might be NULL means that this - ** WhereLoop is not well-ordered. tag-20210426-1 + ** WhereLoop is not well-ordered */ - if( isOrderDistinct ){ - if( iColumn>=0 - && j>=pLoop->u.btree.nEq - && pIndex->pTable->aCol[iColumn].notNull==0 - ){ - isOrderDistinct = 0; - } - if( iColumn==XN_EXPR ){ - isOrderDistinct = 0; - } + if( isOrderDistinct + && iColumn>=0 + && j>=pLoop->u.btree.nEq + && pIndex->pTable->aCol[iColumn].notNull==0 + ){ + isOrderDistinct = 0; } /* Find the ORDER BY term that corresponds to the j-th column - ** of the index and mark that ORDER BY term having been satisfied. + ** of the index and mark that ORDER BY term off */ isMatch = 0; for(i=0; bOnce && ia[i].pExpr); + pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr); testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); - if( NEVER(pOBExpr==0) ) continue; if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( iColumn>=XN_ROWID ){ - if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue; + if( iColumn>=(-1) ){ + if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; if( pOBExpr->iColumn!=iColumn ) continue; }else{ - Expr *pIxExpr = pIndex->aColExpr->a[j].pExpr; - if( sqlite3ExprCompareSkip(pOBExpr, pIxExpr, iCur) ){ + if( sqlite3ExprCompare(0, + pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ continue; } } - if( iColumn!=XN_ROWID ){ - pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); + if( iColumn>=0 ){ + pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); + if( !pColl ) pColl = db->pDfltColl; if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue; } - if( wctrlFlags & WHERE_DISTINCTBY ){ - pLoop->u.btree.nDistinctCol = j+1; - } + pLoop->u.btree.nIdxCol = j+1; isMatch = 1; break; } if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){ /* Make sure the sort order is compatible in an ORDER BY clause. ** Sort order is irrelevant for a GROUP BY clause. */ if( revSet ){ - if( (rev ^ revIdx) - != (pOrderBy->a[i].fg.sortFlags&KEYINFO_ORDER_DESC) - ){ - isMatch = 0; - } + if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0; }else{ - rev = revIdx ^ (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC); + rev = revIdx ^ pOrderBy->a[i].sortOrder; if( rev ) *pRevMask |= MASKBIT(iLoop); revSet = 1; } } - if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){ - if( j==pLoop->u.btree.nEq ){ - pLoop->wsFlags |= WHERE_BIGNULL_SORT; - }else{ - isMatch = 0; - } - } if( isMatch ){ if( iColumn==XN_ROWID ){ testcase( distinctColumns==0 ); distinctColumns = 1; } @@ -168705,21 +135102,21 @@ Expr *p; Bitmask mTerm; if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); - if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue; + if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } } } /* End the loop over all WhereLoops from outer-most down to inner-most */ if( obSat==obDone ) return (i8)nOrderBy; if( !isOrderDistinct ){ for(i=nOrderBy-1; i>0; i--){ - Bitmask m = ALWAYS(iwctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY) ); + assert( pWInfo->wctrlFlags & WHERE_GROUPBY ); assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP ); return pWInfo->sorted; } #ifdef WHERETRACE_ENABLED @@ -168766,284 +135163,47 @@ return zName; } #endif /* -** Return the cost of sorting nRow rows, assuming that the keys have +** Return the cost of sorting nRow rows, assuming that the keys have ** nOrderby columns and that the first nSorted columns are already in ** order. */ static LogEst whereSortingCost( - WhereInfo *pWInfo, /* Query planning context */ - LogEst nRow, /* Estimated number of rows to sort */ - int nOrderBy, /* Number of ORDER BY clause terms */ - int nSorted /* Number of initial ORDER BY terms naturally in order */ + WhereInfo *pWInfo, + LogEst nRow, + int nOrderBy, + int nSorted ){ - /* Estimated cost of a full external sort, where N is + /* TUNING: Estimated cost of a full external sort, where N is ** the number of rows to sort is: ** - ** cost = (K * N * log(N)). - ** - ** Or, if the order-by clause has X terms but only the last Y - ** terms are out of order, then block-sorting will reduce the + ** cost = (3.0 * N * log(N)). + ** + ** Or, if the order-by clause has X terms but only the last Y + ** terms are out of order, then block-sorting will reduce the ** sorting cost to: ** - ** cost = (K * N * log(N)) * (Y/X) - ** - ** The constant K is at least 2.0 but will be larger if there are a - ** large number of columns to be sorted, as the sorting time is - ** proportional to the amount of content to be sorted. The algorithm - ** does not currently distinguish between fat columns (BLOBs and TEXTs) - ** and skinny columns (INTs). It just uses the number of columns as - ** an approximation for the row width. - ** - ** And extra factor of 2.0 or 3.0 is added to the sorting cost if the sort - ** is built using OP_IdxInsert and OP_Sort rather than with OP_SorterInsert. - */ - LogEst rSortCost, nCol; - assert( pWInfo->pSelect!=0 ); - assert( pWInfo->pSelect->pEList!=0 ); - /* TUNING: sorting cost proportional to the number of output columns: */ - nCol = sqlite3LogEst((pWInfo->pSelect->pEList->nExpr+59)/30); - rSortCost = nRow + nCol; - if( nSorted>0 ){ - /* Scale the result by (Y/X) */ - rSortCost += sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; - } + ** cost = (3.0 * N * log(N)) * (Y/X) + ** + ** The (Y/X) term is implemented using stack variable rScale + ** below. */ + LogEst rScale, rSortCost; + assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); + rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; + rSortCost = nRow + rScale + 16; /* Multiple by log(M) where M is the number of output rows. - ** Use the LIMIT for M if it is smaller. Or if this sort is for - ** a DISTINCT operator, M will be the number of distinct output - ** rows, so fudge it downwards a bit. - */ - if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 ){ - rSortCost += 10; /* TUNING: Extra 2.0x if using LIMIT */ - if( nSorted!=0 ){ - rSortCost += 6; /* TUNING: Extra 1.5x if also using partial sort */ - } - if( pWInfo->iLimitiLimit; - } - }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){ - /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT - ** reduces the number of output rows by a factor of 2 */ - if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); } + ** Use the LIMIT for M if it is smaller */ + if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimitiLimit; } rSortCost += estLog(nRow); return rSortCost; } -/* -** Compute the maximum number of paths in the solver algorithm, for -** queries that have three or more terms in the FROM clause. Queries with -** two or fewer FROM clause terms are handled by the caller. -** -** Query planning is NP-hard. We must limit the number of paths at -** each step of the solver search algorithm to avoid exponential behavior. -** -** The value returned is a tuning parameter. Currently the value is: -** -** 18 for star queries -** 12 otherwise -** -** For the purposes of this heuristic, a star-query is defined as a query -** with a large central table that is joined using an INNER JOIN, -** not CROSS or OUTER JOINs, against four or more smaller tables. -** The central table is called the "fact" table. The smaller tables -** that get joined are "dimension tables". Also, any table that is -** self-joined cannot be a dimension table; we assume that dimension -** tables may only be joined against fact tables. -** -** SIDE EFFECT: (and really the whole point of this subroutine) -** -** If pWInfo describes a star-query, then the cost for SCANs of dimension -** WhereLoops is increased to be slightly larger than the cost of a SCAN -** in the fact table. Only SCAN costs are increased. SEARCH costs are -** unchanged. This heuristic helps keep fact tables in outer loops. Without -** this heuristic, paths with fact tables in outer loops tend to get pruned -** by the mxChoice limit on the number of paths, resulting in poor query -** plans. See the starschema1.test test module for examples of queries -** that need this heuristic to find good query plans. -** -** This heuristic can be completely disabled, so that no query is -** considered a star-query, using SQLITE_TESTCTRL_OPTIMIZATION to -** disable the SQLITE_StarQuery optimization. In the CLI, the command -** to do that is: ".testctrl opt -starquery". -** -** HISTORICAL NOTES: -** -** This optimization was first added on 2024-05-09 by check-in 38db9b5c83d. -** The original optimization reduced the cost and output size estimate for -** fact tables to help them move to outer loops. But months later (as people -** started upgrading) performance regression reports started caming in, -** including: -** -** forum post b18ef983e68d06d1 (2024-12-21) -** forum post 0025389d0860af82 (2025-01-14) -** forum post d87570a145599033 (2025-01-17) -** -** To address these, the criteria for a star-query was tightened to exclude -** cases where the fact and dimensions are separated by an outer join, and -** the affect of star-schema detection was changed to increase the rRun cost -** on just full table scans of dimension tables, rather than reducing costs -** in the all access methods of the fact table. -*/ -static int computeMxChoice(WhereInfo *pWInfo){ - int nLoop = pWInfo->nLevel; /* Number of terms in the join */ - WhereLoop *pWLoop; /* For looping over WhereLoops */ - -#ifdef SQLITE_DEBUG - /* The star-query detection code below makes use of the following - ** properties of the WhereLoop list, so verify them before - ** continuing: - ** (1) .maskSelf is the bitmask corresponding to .iTab - ** (2) The WhereLoop list is in ascending .iTab order - */ - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - assert( pWLoop->maskSelf==MASKBIT(pWLoop->iTab) ); - assert( pWLoop->pNextLoop==0 || pWLoop->iTab<=pWLoop->pNextLoop->iTab ); - } -#endif /* SQLITE_DEBUG */ - - if( nLoop>=5 - && !pWInfo->bStarDone - && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery) - ){ - SrcItem *aFromTabs; /* All terms of the FROM clause */ - int iFromIdx; /* Term of FROM clause is the candidate fact-table */ - Bitmask m; /* Bitmask for candidate fact-table */ - Bitmask mSelfJoin = 0; /* Tables that cannot be dimension tables */ - WhereLoop *pStart; /* Where to start searching for dimension-tables */ - - pWInfo->bStarDone = 1; /* Only do this computation once */ - - /* Look for fact tables with four or more dimensions where the - ** dimension tables are not separately from the fact tables by an outer - ** or cross join. Adjust cost weights if found. - */ - assert( !pWInfo->bStarUsed ); - aFromTabs = pWInfo->pTabList->a; - pStart = pWInfo->pLoops; - for(iFromIdx=0, m=1; iFromIdxfg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ - /* If the candidate fact-table is the right table of an outer join - ** restrict the search for dimension-tables to be tables to the right - ** of the fact-table. */ - if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */ - while( pStart && pStart->iTab<=iFromIdx ){ - pStart = pStart->pNextLoop; - } - } - for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ - /* Fact-tables and dimension-tables cannot be separated by an - ** outer join (at least for the definition of fact- and dimension- - ** used by this heuristic). */ - break; - } - if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */ - && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */ - && (pWLoop->maskSelf & mSelfJoin)==0 /* Not a self-join */ - ){ - if( aFromTabs[pWLoop->iTab].pSTab==pFactTab->pSTab ){ - mSelfJoin |= m; - }else{ - nDep++; - mSeen |= pWLoop->maskSelf; - } - } - } - if( nDep<=3 ) continue; - - /* If we reach this point, it means that pFactTab is a fact table - ** with four or more dimensions connected by inner joins. Proceed - ** to make cost adjustments. */ - -#ifdef WHERETRACE_ENABLED - /* Make sure rStarDelta values are initialized */ - if( !pWInfo->bStarUsed ){ - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - pWLoop->rStarDelta = 0; - } - } -#endif - pWInfo->bStarUsed = 1; - - /* Compute the maximum cost of any WhereLoop for the - ** fact table plus one epsilon */ - mxRun = LOGEST_MIN; - for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( pWLoop->iTabiTab>iFromIdx ) break; - if( pWLoop->rRun>mxRun ) mxRun = pWLoop->rRun; - } - if( ALWAYS(mxRunpNextLoop){ - if( (pWLoop->maskSelf & mSeen)==0 ) continue; - if( pWLoop->nLTerm ) continue; - if( pWLoop->rRuniTab; - sqlite3DebugPrintf( - "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n", - pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab, - pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, - iFromIdx, mxRun - ); - } - pWLoop->rStarDelta = mxRun - pWLoop->rRun; -#endif /* WHERETRACE_ENABLED */ - pWLoop->rRun = mxRun; - } - } - } -#ifdef WHERETRACE_ENABLED /* 0x80000 */ - if( (sqlite3WhereTrace & 0x80000)!=0 && pWInfo->bStarUsed ){ - sqlite3DebugPrintf("WhereLoops changed by star-query heuristic:\n"); - for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( pWLoop->rStarDelta ){ - sqlite3WhereLoopPrint(pWLoop, &pWInfo->sWC); - } - } - } -#endif - } - return pWInfo->bStarUsed ? 18 : 12; -} - -/* -** Two WhereLoop objects, pCandidate and pBaseline, are known to have the -** same cost. Look deep into each to see if pCandidate is even slightly -** better than pBaseline. Return false if it is, if pCandidate is is preferred. -** Return true if pBaseline is preferred or if we cannot tell the difference. -** -** Result Meaning -** -------- ---------------------------------------------------------- -** true We cannot tell the difference in pCandidate and pBaseline -** false pCandidate seems like a better choice than pBaseline -*/ -static SQLITE_NOINLINE int whereLoopIsNoBetter( - const WhereLoop *pCandidate, - const WhereLoop *pBaseline -){ - if( (pCandidate->wsFlags & WHERE_INDEXED)==0 ) return 1; - if( (pBaseline->wsFlags & WHERE_INDEXED)==0 ) return 1; - if( pCandidate->u.btree.pIndex->szIdxRow < - pBaseline->u.btree.pIndex->szIdxRow ) return 0; - return 1; -} - /* ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine ** attempts to find the lowest cost path that visits each WhereLoop ** once. This path is then loaded into the pWInfo->a[].pWLoop fields. ** @@ -169056,16 +135216,17 @@ */ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ int mxChoice; /* Maximum number of simultaneous paths tracked */ int nLoop; /* Number of terms in the join */ Parse *pParse; /* Parsing context */ + sqlite3 *db; /* The database connection */ int iLoop; /* Loop counter over the terms of the join */ int ii, jj; /* Loop counters */ int mxI = 0; /* Index of next entry to replace */ int nOrderBy; /* Number of ORDER BY clause terms */ LogEst mxCost = 0; /* Maximum cost of a set of paths */ - LogEst mxUnsort = 0; /* Maximum unsorted cost of a set of path */ + LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ WherePath *aFrom; /* All nFrom paths at the previous level */ WherePath *aTo; /* The nTo best paths at the current level */ WherePath *pFrom; /* An element of aFrom[] that we are working on */ WherePath *pTo; /* An element of aTo[] that we are working on */ @@ -169074,32 +135235,18 @@ LogEst *aSortCost = 0; /* Sorting and partial sorting costs */ char *pSpace; /* Temporary memory used by this routine */ int nSpace; /* Bytes of space allocated at pSpace */ pParse = pWInfo->pParse; + db = pParse->db; nLoop = pWInfo->nLevel; - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n", - nRowEst, pParse->nQueryLoop)); - /* TUNING: mxChoice is the maximum number of possible paths to preserve - ** at each step. Based on the number of loops in the FROM clause: - ** - ** nLoop mxChoice - ** ----- -------- - ** 1 1 // the most common case - ** 2 5 - ** 3+ 12 or 18 // see computeMxChoice() - */ - if( nLoop<=1 ){ - mxChoice = 1; - }else if( nLoop==2 ){ - mxChoice = 5; - }else if( pParse->nErr ){ - mxChoice = 1; - }else{ - mxChoice = computeMxChoice(pWInfo); - } + /* TUNING: For simple queries, only the best path is tracked. + ** For 2-way joins, the 5 best paths are followed. + ** For joins of 3 or more tables, track the 10 best paths */ + mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10); assert( nLoop<=pWInfo->pTabList->nSrc ); + WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this ** case the purpose of this call is to estimate the number of rows returned ** by the overall query. Once this estimate has been obtained, the caller ** will invoke this function a second time, passing the estimate as the @@ -169111,11 +135258,11 @@ } /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; nSpace += sizeof(LogEst) * nOrderBy; - pSpace = sqlite3StackAllocRawNN(pParse->db, nSpace); + pSpace = sqlite3DbMallocRawNN(db, nSpace); if( pSpace==0 ) return SQLITE_NOMEM_BKPT; aTo = (WherePath*)pSpace; aFrom = aTo+mxChoice; memset(aFrom, 0, sizeof(aFrom[0])); pX = (WhereLoop**)(aFrom+mxChoice); @@ -169125,11 +135272,11 @@ if( nOrderBy ){ /* If there is an ORDER BY clause and it is not being ignored, set up ** space for the aSortCost[] array. Each element of the aSortCost array ** is either zero - meaning it has not yet been initialized - or the ** cost of sorting nRowEst rows of data where the first X terms of - ** the ORDER BY clause are already in order, where X is the array + ** the ORDER BY clause are already in order, where X is the array ** index. */ aSortCost = (LogEst*)pX; memset(aSortCost, 0, sizeof(LogEst) * nOrderBy); } assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] ); @@ -169146,11 +135293,11 @@ if( nOrderBy ){ /* If nLoop is zero, then there are no FROM terms in the query. Since ** in this case the query may return a maximum of one row, the results ** are already in the requested order. Set isOrdered to nOrderBy to ** indicate this. Or, if nLoop is greater than zero, set isOrdered to - ** -1, indicating that the result set may or may not be ordered, + ** -1, indicating that the result set may or may not be ordered, ** depending on the loops added to the current plan. */ aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy; } /* Compute successively longer WherePaths using the previous generation @@ -169160,38 +135307,30 @@ nTo = 0; for(ii=0, pFrom=aFrom; iipLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ LogEst nOut; /* Rows visited by (pFrom+pWLoop) */ LogEst rCost; /* Cost of path (pFrom+pWLoop) */ - LogEst rUnsort; /* Unsorted cost of (pFrom+pWLoop) */ - i8 isOrdered; /* isOrdered for (pFrom+pWLoop) */ + LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */ + i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */ Bitmask maskNew; /* Mask of src visited by (..) */ - Bitmask revMask; /* Mask of rev-order loops for (..) */ + Bitmask revMask = 0; /* Mask of rev-order loops for (..) */ if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){ + if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){ /* Do not use an automatic index if the this loop is expected - ** to run less than 1.25 times. It is tempting to also exclude - ** automatic index usage on an outer loop, but sometimes an automatic - ** index is useful in the outer loop of a correlated subquery. */ + ** to run less than 2 times. */ assert( 10==sqlite3LogEst(2) ); continue; } - - /* At this point, pWLoop is a candidate to be the next loop. + /* At this point, pWLoop is a candidate to be the next loop. ** Compute its cost */ - rUnsort = pWLoop->rRun + pFrom->nRow; - if( pWLoop->rSetup ){ - rUnsort = sqlite3LogEstAdd(pWLoop->rSetup, rUnsort); - } - rUnsort = sqlite3LogEstAdd(rUnsort, pFrom->rUnsort); + rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); + rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted); nOut = pFrom->nRow + pWLoop->nOut; maskNew = pFrom->maskLoop | pWLoop->maskSelf; - isOrdered = pFrom->isOrdered; if( isOrdered<0 ){ - revMask = 0; isOrdered = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, iLoop, pWLoop, &revMask); }else{ revMask = pFrom->revLoop; @@ -169200,23 +135339,19 @@ if( aSortCost[isOrdered]==0 ){ aSortCost[isOrdered] = whereSortingCost( pWInfo, nRowEst, nOrderBy, isOrdered ); } - /* TUNING: Add a small extra penalty (3) to sorting as an - ** extra encouragement to the query planner to select a plan - ** where the rows emerge in the correct order without any sorting - ** required. */ - rCost = sqlite3LogEstAdd(rUnsort, aSortCost[isOrdered]) + 3; + rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]); WHERETRACE(0x002, ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n", - aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy, - rUnsort, rCost)); + aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy, + rUnsorted, rCost)); }else{ - rCost = rUnsort; - rUnsort -= 2; /* TUNING: Slight bias in favor of no-sort plans */ + rCost = rUnsorted; + rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */ } /* Check to see if pWLoop should be added to the set of ** mxChoice best-so-far paths. ** @@ -169226,11 +135361,10 @@ ** ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range ** of legal values for isOrdered, -1..64. */ - testcase( nTo==0 ); for(jj=0, pTo=aTo; jjmaskLoop==maskNew && ((pTo->isOrdered^isOrdered)&0x80)==0 ){ testcase( jj==nTo-1 ); @@ -169238,19 +135372,19 @@ } } if( jj>=nTo ){ /* None of the existing best-so-far paths match the candidate. */ if( nTo>=mxChoice - && (rCost>mxCost || (rCost==mxCost && rUnsort>=mxUnsort)) + && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted)) ){ /* The current candidate is no better than any of the mxChoice ** paths currently in the best-so-far buffer. So discard ** this candidate as not viable. */ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); } #endif continue; } @@ -169265,38 +135399,39 @@ } pTo = &aTo[jj]; #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); } #endif }else{ /* Control reaches here if best-so-far path pTo=aTo[jj] covers the ** same set of loops and has the same isOrdered setting as the ** candidate path. Check to see if the candidate should replace ** pTo or if the candidate should be skipped. - ** + ** ** The conditional is an expanded vector comparison equivalent to: - ** (pTo->rCost,pTo->nRow,pTo->rUnsort) <= (rCost,nOut,rUnsort) + ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted) */ - if( (pTo->rCostrCost==rCost && pTo->nRowrCost==rCost && pTo->nRow==nOut && pTo->rUnsortrCost==rCost && pTo->nRow==nOut && pTo->rUnsort==rUnsort - && whereLoopIsNoBetter(pWLoop, pTo->aLoop[iLoop]) ) + if( pTo->rCostrCost==rCost + && (pTo->nRownRow==nOut && pTo->rUnsorted<=rUnsorted) + ) + ) ){ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( "Skip %s cost=%-3d,%3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); + pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); } #endif /* Discard the candidate path from further consideration */ testcase( pTo->rCost==rCost ); continue; @@ -169306,72 +135441,57 @@ ** pTo path. Replace pTo with the candidate. */ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( "Update %s cost=%-3d,%3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort, + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); + pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); } #endif } /* pWLoop is a winner. Add it to the set of best so far */ pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; pTo->revLoop = revMask; pTo->nRow = nOut; pTo->rCost = rCost; - pTo->rUnsort = rUnsort; + pTo->rUnsorted = rUnsorted; pTo->isOrdered = isOrdered; memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); pTo->aLoop[iLoop] = pWLoop; if( nTo>=mxChoice ){ mxI = 0; mxCost = aTo[0].rCost; - mxUnsort = aTo[0].nRow; + mxUnsorted = aTo[0].nRow; for(jj=1, pTo=&aTo[1]; jjrCost>mxCost - || (pTo->rCost==mxCost && pTo->rUnsort>mxUnsort) + if( pTo->rCost>mxCost + || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted) ){ mxCost = pTo->rCost; - mxUnsort = pTo->rUnsort; + mxUnsorted = pTo->rUnsorted; mxI = jj; } } } } } #ifdef WHERETRACE_ENABLED /* >=2 */ if( sqlite3WhereTrace & 0x02 ){ - LogEst rMin, rFloor = 0; - int nDone = 0; - int nProgress; sqlite3DebugPrintf("---- after round %d ----\n", iLoop); - do{ - nProgress = 0; - rMin = 0x7fff; - for(ii=0, pTo=aTo; iirCost>rFloor && pTo->rCostrCost; - } - for(ii=0, pTo=aTo; iirCost==rMin ){ - sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?'); - if( pTo->isOrdered>0 ){ - sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop); - }else{ - sqlite3DebugPrintf("\n"); - } - nDone++; - nProgress++; - } - } - rFloor = rMin; - }while( nDone0 ); + for(ii=0, pTo=aTo; iirCost, pTo->nRow, + pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?'); + if( pTo->isOrdered>0 ){ + sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop); + }else{ + sqlite3DebugPrintf("\n"); + } + } } #endif /* Swap the roles of aFrom and aTo for the next generation */ pFrom = aTo; @@ -169380,14 +135500,14 @@ nFrom = nTo; } if( nFrom==0 ){ sqlite3ErrorMsg(pParse, "no query solution"); - sqlite3StackFreeNN(pParse->db, pSpace); + sqlite3DbFreeNN(db, pSpace); return SQLITE_ERROR; } - + /* Find the lowest cost path. pFrom will be left pointing to that path */ pFrom = aFrom; for(ii=1; iirCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; } @@ -169409,27 +135529,23 @@ WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); if( rc==pWInfo->pResultSet->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } } - pWInfo->bOrderedInnerLoop = 0; if( pWInfo->pOrderBy ){ - pWInfo->nOBSat = pFrom->isOrdered; if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } - /* vvv--- See check-in [12ad822d9b827777] on 2023-03-16 ---vvv */ - assert( pWInfo->pSelect->pOrderBy==0 - || pWInfo->nOBSat <= pWInfo->pSelect->pOrderBy->nExpr ); }else{ + pWInfo->nOBSat = pFrom->isOrdered; pWInfo->revMask = pFrom->revLoop; if( pWInfo->nOBSat<=0 ){ pWInfo->nOBSat = 0; if( nLoop>0 ){ u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; - if( (wsFlags & WHERE_ONEROW)==0 + if( (wsFlags & WHERE_ONEROW)==0 && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) ){ Bitmask m = 0; int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); @@ -169439,160 +135555,70 @@ pWInfo->bOrderedInnerLoop = 1; pWInfo->revMask = m; } } } - }else if( nLoop - && pWInfo->nOBSat==1 - && (pWInfo->wctrlFlags & (WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX))!=0 - ){ - pWInfo->bOrderedInnerLoop = 1; } } if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 ){ Bitmask revMask = 0; - int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, + int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask ); assert( pWInfo->sorted==0 ); if( nOrder==pWInfo->pOrderBy->nExpr ){ pWInfo->sorted = 1; pWInfo->revMask = revMask; } } } + pWInfo->nRowOut = pFrom->nRow; -#ifdef WHERETRACE_ENABLED - pWInfo->rTotalCost = pFrom->rCost; -#endif /* Free temporary memory and return success */ - sqlite3StackFreeNN(pParse->db, pSpace); + sqlite3DbFreeNN(db, pSpace); return SQLITE_OK; } -/* -** This routine implements a heuristic designed to improve query planning. -** This routine is called in between the first and second call to -** wherePathSolver(). Hence the name "Interstage" "Heuristic". -** -** The first call to wherePathSolver() (hereafter just "solver()") computes -** the best path without regard to the order of the outputs. The second call -** to the solver() builds upon the first call to try to find an alternative -** path that satisfies the ORDER BY clause. -** -** This routine looks at the results of the first solver() run, and for -** every FROM clause term in the resulting query plan that uses an equality -** constraint against an index, disable other WhereLoops for that same -** FROM clause term that would try to do a full-table scan. This prevents -** an index search from being converted into a full-table scan in order to -** satisfy an ORDER BY clause, since even though we might get slightly better -** performance using the full-scan without sorting if the output size -** estimates are very precise, we might also get severe performance -** degradation using the full-scan if the output size estimate is too large. -** It is better to err on the side of caution. -** -** Except, if the first solver() call generated a full-table scan in an outer -** loop then stop this analysis at the first full-scan, since the second -** solver() run might try to swap that full-scan for another in order to -** get the output into the correct order. In other words, we allow a -** rewrite like this: -** -** First Solver() Second Solver() -** |-- SCAN t1 |-- SCAN t2 -** |-- SEARCH t2 `-- SEARCH t1 -** `-- SORT USING B-TREE -** -** The purpose of this routine is to disallow rewrites such as: -** -** First Solver() Second Solver() -** |-- SEARCH t1 |-- SCAN t2 <--- bad! -** |-- SEARCH t2 `-- SEARCH t1 -** `-- SORT USING B-TREE -** -** See test cases in test/whereN.test for the real-world query that -** originally provoked this heuristic. -*/ -static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){ - int i; -#ifdef WHERETRACE_ENABLED - int once = 0; -#endif - for(i=0; inLevel; i++){ - WhereLoop *p = pWInfo->a[i].pWLoop; - if( p==0 ) break; - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue; - if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){ - u8 iTab = p->iTab; - WhereLoop *pLoop; - for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){ - if( pLoop->iTab!=iTab ) continue; - if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){ - /* Auto-index and index-constrained loops allowed to remain */ - continue; - } -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x80 ){ - if( once==0 ){ - sqlite3DebugPrintf("Loops disabled by interstage heuristic:\n"); - once = 1; - } - sqlite3WhereLoopPrint(pLoop, &pWInfo->sWC); - } -#endif /* WHERETRACE_ENABLED */ - pLoop->prereq = ALLBITS; /* Prevent 2nd solver() from using this one */ - } - }else{ - break; - } - } -} - /* ** Most queries use only a single table (they are not joins) and have ** simple == constraints against indexed fields. This routine attempts ** to plan those simple cases using much less ceremony than the ** general-purpose query planner, and thereby yield faster sqlite3_prepare() ** times for the common case. ** ** Return non-zero on success, if this query can be handled by this -** no-frills query planner. Return zero if this query needs the +** no-frills query planner. Return zero if this query needs the ** general-purpose query planner. */ static int whereShortCut(WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo; - SrcItem *pItem; + struct SrcList_item *pItem; WhereClause *pWC; WhereTerm *pTerm; WhereLoop *pLoop; int iCur; int j; Table *pTab; Index *pIdx; - WhereScan scan; pWInfo = pBuilder->pWInfo; if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0; assert( pWInfo->pTabList->nSrc>=1 ); pItem = pWInfo->pTabList->a; - pTab = pItem->pSTab; + pTab = pItem->pTab; if( IsVirtual(pTab) ) return 0; - if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){ - testcase( pItem->fg.isIndexedBy ); - testcase( pItem->fg.notIndexed ); - return 0; - } + if( pItem->fg.isIndexedBy ) return 0; iCur = pItem->iCursor; pWC = &pWInfo->sWC; pLoop = pBuilder->pNew; pLoop->wsFlags = 0; pLoop->nSkip = 0; - pTerm = whereScanInit(&scan, pWC, iCur, -1, WO_EQ|WO_IS, 0); - while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan); + pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0); if( pTerm ){ testcase( pTerm->eOperator & WO_IS ); pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; pLoop->aLTerm[0] = pTerm; pLoop->nLTerm = 1; @@ -169602,24 +135628,23 @@ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int opMask; assert( pLoop->aLTermSpace==pLoop->aLTerm ); if( !IsUniqueIndex(pIdx) - || pIdx->pPartIdxWhere!=0 - || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) + || pIdx->pPartIdxWhere!=0 + || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) ) continue; opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ; for(j=0; jnKeyCol; j++){ - pTerm = whereScanInit(&scan, pWC, iCur, j, opMask, pIdx); - while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan); + pTerm = sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx); if( pTerm==0 ) break; testcase( pTerm->eOperator & WO_IS ); pLoop->aLTerm[j] = pTerm; } if( j!=pIdx->nKeyCol ) continue; pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; - if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){ + if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ pLoop->wsFlags |= WHERE_IDX_ONLY; } pLoop->nLTerm = j; pLoop->u.btree.nEq = j; pLoop->u.btree.pIndex = pIdx; @@ -169637,18 +135662,12 @@ pWInfo->nRowOut = 1; if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr; if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - if( scan.iEquiv>1 ) pLoop->wsFlags |= WHERE_TRANSCONS; #ifdef SQLITE_DEBUG pLoop->cId = '0'; -#endif -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x02 ){ - sqlite3DebugPrintf("whereShortCut() used to compute solution\n"); - } #endif return 1; } return 0; } @@ -169663,295 +135682,23 @@ } return WRC_Continue; } /* -** Return true if the expression contains no non-deterministic SQL -** functions. Do not consider non-deterministic SQL functions that are +** Return true if the expression contains no non-deterministic SQL +** functions. Do not consider non-deterministic SQL functions that are ** part of sub-select statements. */ static int exprIsDeterministic(Expr *p){ Walker w; memset(&w, 0, sizeof(w)); w.eCode = 1; w.xExprCallback = exprNodeIsDeterministic; - w.xSelectCallback = sqlite3SelectWalkFail; sqlite3WalkExpr(&w, p); return w.eCode; } - -#ifdef WHERETRACE_ENABLED -/* -** Display all WhereLoops in pWInfo -*/ -static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){ - if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */ - WhereLoop *p; - int i; - static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" - "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; - for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ - p->cId = zLabel[i%(sizeof(zLabel)-1)]; - sqlite3WhereLoopPrint(p, pWC); - } - } -} -# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C) -#else -# define WHERETRACE_ALL_LOOPS(W,C) -#endif - -/* Attempt to omit tables from a join that do not affect the result. -** For a table to not affect the result, the following must be true: -** -** 1) The query must not be an aggregate. -** 2) The table must be the RHS of a LEFT JOIN. -** 3) Either the query must be DISTINCT, or else the ON or USING clause -** must contain a constraint that limits the scan of the table to -** at most a single row. -** 4) The table must not be referenced by any part of the query apart -** from its own USING or ON clause. -** 5) The table must not have an inner-join ON or USING clause if there is -** a RIGHT JOIN anywhere in the query. Otherwise the ON/USING clause -** might move from the right side to the left side of the RIGHT JOIN. -** Note: Due to (2), this condition can only arise if the table is -** the right-most table of a subquery that was flattened into the -** main query and that subquery was the right-hand operand of an -** inner join that held an ON or USING clause. -** 6) The ORDER BY clause has 63 or fewer terms -** 7) The omit-noop-join optimization is enabled. -** -** Items (1), (6), and (7) are checked by the caller. -** -** For example, given: -** -** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); -** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); -** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); -** -** then table t2 can be omitted from the following: -** -** SELECT v1, v3 FROM t1 -** LEFT JOIN t2 ON (t1.ipk=t2.ipk) -** LEFT JOIN t3 ON (t1.ipk=t3.ipk) -** -** or from: -** -** SELECT DISTINCT v1, v3 FROM t1 -** LEFT JOIN t2 -** LEFT JOIN t3 ON (t1.ipk=t3.ipk) -*/ -static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( - WhereInfo *pWInfo, - Bitmask notReady -){ - int i; - Bitmask tabUsed; - int hasRightJoin; - - /* Preconditions checked by the caller */ - assert( pWInfo->nLevel>=2 ); - assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_OmitNoopJoin) ); - - /* These two preconditions checked by the caller combine to guarantee - ** condition (1) of the header comment */ - assert( pWInfo->pResultSet!=0 ); - assert( 0==(pWInfo->wctrlFlags & WHERE_AGG_DISTINCT) ); - - tabUsed = sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet); - if( pWInfo->pOrderBy ){ - tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy); - } - hasRightJoin = (pWInfo->pTabList->a[0].fg.jointype & JT_LTORJ)!=0; - for(i=pWInfo->nLevel-1; i>=1; i--){ - WhereTerm *pTerm, *pEnd; - SrcItem *pItem; - WhereLoop *pLoop; - Bitmask m1; - pLoop = pWInfo->a[i].pWLoop; - pItem = &pWInfo->pTabList->a[pLoop->iTab]; - if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue; - if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0 - && (pLoop->wsFlags & WHERE_ONEROW)==0 - ){ - continue; - } - if( (tabUsed & pLoop->maskSelf)!=0 ) continue; - pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm; - for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - if( !ExprHasProperty(pTerm->pExpr, EP_OuterON) - || pTerm->pExpr->w.iJoin!=pItem->iCursor - ){ - break; - } - } - if( hasRightJoin - && ExprHasProperty(pTerm->pExpr, EP_InnerON) - && NEVER(pTerm->pExpr->w.iJoin==pItem->iCursor) - ){ - break; /* restriction (5) */ - } - } - if( pTerm omit unused FROM-clause term %c\n",pLoop->cId)); - m1 = MASKBIT(i)-1; - testcase( ((pWInfo->revMask>>1) & ~m1)!=0 ); - pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1); - notReady &= ~pLoop->maskSelf; - for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - pTerm->wtFlags |= TERM_CODED; - } - } - if( i!=pWInfo->nLevel-1 ){ - int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); - memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); - } - pWInfo->nLevel--; - assert( pWInfo->nLevel>0 ); - } - return notReady; -} - -/* -** Check to see if there are any SEARCH loops that might benefit from -** using a Bloom filter. Consider a Bloom filter if: -** -** (1) The SEARCH happens more than N times where N is the number -** of rows in the table that is being considered for the Bloom -** filter. -** (2) Some searches are expected to find zero rows. (This is determined -** by the WHERE_SELFCULL flag on the term.) -** (3) Bloom-filter processing is not disabled. (Checked by the -** caller.) -** (4) The size of the table being searched is known by ANALYZE. -** -** This block of code merely checks to see if a Bloom filter would be -** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the -** WhereLoop. The implementation of the Bloom filter comes further -** down where the code for each WhereLoop is generated. -*/ -static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( - const WhereInfo *pWInfo -){ - int i; - LogEst nSearch = 0; - - assert( pWInfo->nLevel>=2 ); - assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) ); - for(i=0; inLevel; i++){ - WhereLoop *pLoop = pWInfo->a[i].pWLoop; - const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); - SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; - Table *pTab = pItem->pSTab; - if( (pTab->tabFlags & TF_HasStat1)==0 ) break; - pTab->tabFlags |= TF_MaybeReanalyze; - if( i>=1 - && (pLoop->wsFlags & reqFlags)==reqFlags - /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ - && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) - ){ - if( nSearch > pTab->nRowLogEst ){ - testcase( pItem->fg.jointype & JT_LEFT ); - pLoop->wsFlags |= WHERE_BLOOMFILTER; - pLoop->wsFlags &= ~WHERE_IDX_ONLY; - WHERETRACE(0xffffffff, ( - "-> use Bloom-filter on loop %c because there are ~%.1e " - "lookups into %s which has only ~%.1e rows\n", - pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName, - (double)sqlite3LogEstToInt(pTab->nRowLogEst))); - } - } - nSearch += pLoop->nOut; - } -} - -/* -** The index pIdx is used by a query and contains one or more expressions. -** In other words pIdx is an index on an expression. iIdxCur is the cursor -** number for the index and iDataCur is the cursor number for the corresponding -** table. -** -** This routine adds IndexedExpr entries to the Parse->pIdxEpr field for -** each of the expressions in the index so that the expression code generator -** will know to replace occurrences of the indexed expression with -** references to the corresponding column of the index. -*/ -static SQLITE_NOINLINE void whereAddIndexedExpr( - Parse *pParse, /* Add IndexedExpr entries to pParse->pIdxEpr */ - Index *pIdx, /* The index-on-expression that contains the expressions */ - int iIdxCur, /* Cursor number for pIdx */ - SrcItem *pTabItem /* The FROM clause entry for the table */ -){ - int i; - IndexedExpr *p; - Table *pTab; - assert( pIdx->bHasExpr ); - pTab = pIdx->pTable; - for(i=0; inColumn; i++){ - Expr *pExpr; - int j = pIdx->aiColumn[i]; - if( j==XN_EXPR ){ - pExpr = pIdx->aColExpr->a[i].pExpr; - }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ - pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); - }else{ - continue; - } - if( sqlite3ExprIsConstant(0,pExpr) ) continue; - p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); - if( p==0 ) break; - p->pIENext = pParse->pIdxEpr; -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x200 ){ - sqlite3DebugPrintf("New pParse->pIdxEpr term {%d,%d}\n", iIdxCur, i); - if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(pExpr); - } -#endif - p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); - p->iDataCur = pTabItem->iCursor; - p->iIdxCur = iIdxCur; - p->iIdxCol = i; - p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; - if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){ - p->aff = pIdx->zColAff[i]; - } -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - p->zIdxName = pIdx->zName; -#endif - pParse->pIdxEpr = p; - if( p->pIENext==0 ){ - void *pArg = (void*)&pParse->pIdxEpr; - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); - } - } -} - -/* -** Set the reverse-scan order mask to one for all tables in the query -** with the exception of MATERIALIZED common table expressions that have -** their own internal ORDER BY clauses. -** -** This implements the PRAGMA reverse_unordered_selects=ON setting. -** (Also SQLITE_DBCONFIG_REVERSE_SCANORDER). -*/ -static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){ - int ii; - for(ii=0; iipTabList->nSrc; ii++){ - SrcItem *pItem = &pWInfo->pTabList->a[ii]; - if( !pItem->fg.isCte - || pItem->u2.pCteUse->eM10d!=M10d_Yes - || NEVER(pItem->fg.isSubquery==0) - || pItem->u4.pSubq->pSelect->pOrderBy==0 - ){ - pWInfo->revMask |= MASKBIT(ii); - } - } -} - /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains ** information needed to terminate the loop. Later, the calling routine ** should invoke sqlite3WhereEnd() with the return value of this function @@ -170006,11 +135753,11 @@ ** inner loops (or around the "..." if the test occurs within the inner- ** most loop) ** ** OUTER JOINS ** -** An outer join of tables t1 and t2 is conceptually coded as follows: +** An outer join of tables t1 and t2 is conceptally coded as follows: ** ** foreach row1 in t1 do ** flag = 0 ** foreach row2 in t2 do ** start: @@ -170028,11 +135775,11 @@ ** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause ** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement ** if there is one. If there is no ORDER BY clause or if this routine ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. ** -** The iIdxCur parameter is the cursor number of an index. If +** The iIdxCur parameter is the cursor number of an index. If ** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index ** to use for OR clause processing. The WHERE clause should use this ** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is ** the first cursor in an array of cursors for all indices. iIdxCur should ** be used to compute the appropriate cursor depending on which index is @@ -170042,11 +135789,10 @@ Parse *pParse, /* The parser context */ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ - Select *pSelect, /* The entire SELECT statement */ u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number ** If WHERE_USE_LIMIT, then the limit amount */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ @@ -170062,12 +135808,12 @@ sqlite3 *db; /* Database connection */ int rc; /* Return code */ u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( - (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 )); /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */ assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 || (wctrlFlags & WHERE_USE_LIMIT)==0 ); @@ -170076,26 +135822,29 @@ db = pParse->db; memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); - if( pOrderBy && pOrderBy->nExpr>=BMS ){ - pOrderBy = 0; + if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; + sWLB.pOrderBy = pOrderBy; + + /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via + ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ + if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ wctrlFlags &= ~WHERE_WANT_DISTINCT; - wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */ } /* The number of tables in the FROM clause is limited by the number of - ** bits in a Bitmask + ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); if( pTabList->nSrc>BMS ){ sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); return 0; } - /* This function normally generates a nested loop for all tables in + /* This function normally generates a nested loop for all tables in ** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should ** only generate code for the first table in pTabList and assume that ** any cursors associated with subsequent tables are uninitialized. */ nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc; @@ -170105,43 +135854,33 @@ ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ - nByteWInfo = ROUND8P(sizeof(WhereInfo)); - if( nTabList>1 ){ - nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel)); - } + nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite3DbFree(db, pWInfo); pWInfo = 0; goto whereBeginError; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->pOrderBy = pOrderBy; -#if WHERETRACE_ENABLED pWInfo->pWhere = pWhere; -#endif pWInfo->pResultSet = pResultSet; pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; pWInfo->nLevel = nTabList; - pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse); + pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; - pWInfo->pSelect = pSelect; - memset(&pWInfo->nOBSat, 0, + memset(&pWInfo->nOBSat, 0, offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; - pMaskSet->n = 0; - pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be - ** a valid cursor number, to avoid an initial - ** test for pMaskSet->n==0 in sqlite3WhereGetMask() */ sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); whereLoopInit(sWLB.pNew); @@ -170150,116 +135889,77 @@ #endif /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ + initMaskSet(pMaskSet); sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); - + /* Special case: No FROM clause */ if( nTabList==0 ){ if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; - if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 - && OptimizationEnabled(db, SQLITE_DistinctOpt) - ){ + if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - if( ALWAYS(pWInfo->pSelect) - && (pWInfo->pSelect->selFlags & SF_MultiValue)==0 - ){ - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); - } - }else{ - /* Assign a bit from the bitmask to every term in the FROM clause. - ** - ** The N-th term of the FROM clause is assigned a bitmask of 1<nSrc tables in - ** pTabList, not just the first nTabList tables. nTabList is normally - ** equal to pTabList->nSrc but might be shortened to 1 if the - ** WHERE_OR_SUBCLAUSE flag is set. - */ - ii = 0; - do{ - createMask(pMaskSet, pTabList->a[ii].iCursor); - sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); - }while( (++ii)nSrc ); - #ifdef SQLITE_DEBUG - { - Bitmask mx = 0; - for(ii=0; iinSrc; ii++){ - Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); - assert( m>=mx ); - mx = m; - } - } - #endif - } + } + + /* Assign a bit from the bitmask to every term in the FROM clause. + ** + ** The N-th term of the FROM clause is assigned a bitmask of 1<nSrc tables in + ** pTabList, not just the first nTabList tables. nTabList is normally + ** equal to pTabList->nSrc but might be shortened to 1 if the + ** WHERE_OR_SUBCLAUSE flag is set. + */ + for(ii=0; iinSrc; ii++){ + createMask(pMaskSet, pTabList->a[ii].iCursor); + sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); + } +#ifdef SQLITE_DEBUG + { + Bitmask mx = 0; + for(ii=0; iinSrc; ii++){ + Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); + assert( m>=mx ); + mx = m; + } + } +#endif /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); - if( pSelect && pSelect->pLimit ){ - sqlite3WhereAddLimit(&pWInfo->sWC, pSelect); - } - if( pParse->nErr ) goto whereBeginError; - - /* The False-WHERE-Term-Bypass optimization: - ** - ** If there are WHERE terms that are false, then no rows will be output, - ** so skip over all of the code generated here. - ** - ** Conditions: - ** - ** (1) The WHERE term must not refer to any tables in the join. - ** (2) The term must not come from an ON clause on the - ** right-hand side of a LEFT or FULL JOIN. - ** (3) The term must not come from an ON clause, or there must be - ** no RIGHT or FULL OUTER joins in pTabList. - ** (4) If the expression contains non-deterministic functions - ** that are not within a sub-select. This is not required - ** for correctness but rather to preserves SQLite's legacy - ** behaviour in the following two cases: - ** - ** WHERE random()>0; -- eval random() once per row - ** WHERE (SELECT random())>0; -- eval random() just once overall - ** - ** Note that the Where term need not be a constant in order for this - ** optimization to apply, though it does need to be constant relative to - ** the current subquery (condition 1). The term might include variables - ** from outer queries so that the value of the term changes from one - ** invocation of the current subquery to the next. - */ - for(ii=0; iinBase; ii++){ - WhereTerm *pT = &sWLB.pWC->a[ii]; /* A term of the WHERE clause */ - Expr *pX; /* The expression of pT */ - if( pT->wtFlags & TERM_VIRTUAL ) continue; - pX = pT->pExpr; - assert( pX!=0 ); - assert( pT->prereqAll!=0 || !ExprHasProperty(pX, EP_OuterON) ); - if( pT->prereqAll==0 /* Conditions (1) and (2) */ - && (nTabList==0 || exprIsDeterministic(pX)) /* Condition (4) */ - && !(ExprHasProperty(pX, EP_InnerON) /* Condition (3) */ - && (pTabList->a[0].fg.jointype & JT_LTORJ)!=0 ) - ){ - sqlite3ExprIfFalse(pParse, pX, pWInfo->iBreak, SQLITE_JUMPIFNULL); + if( db->mallocFailed ) goto whereBeginError; + + /* Special case: WHERE terms that do not refer to any tables in the join + ** (constant expressions). Evaluate each such term, and jump over all the + ** generated code if the result is not true. + ** + ** Do not do this if the expression contains non-deterministic functions + ** that are not within a sub-select. This is not strictly required, but + ** preserves SQLite's legacy behaviour in the following two cases: + ** + ** FROM ... WHERE random()>0; -- eval random() once per row + ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall + */ + for(ii=0; iinTerm; ii++){ + WhereTerm *pT = &sWLB.pWC->a[ii]; + if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ + sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); pT->wtFlags |= TERM_CODED; } } if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ - /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via - ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ - wctrlFlags &= ~WHERE_WANT_DISTINCT; - pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT; - }else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ + if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; }else if( pOrderBy==0 ){ /* Try to ORDER BY the result set to make distinct processing easier */ pWInfo->wctrlFlags |= WHERE_DISTINCTBY; @@ -170267,89 +135967,55 @@ } } /* Construct the WhereLoop objects */ #if defined(WHERETRACE_ENABLED) - if( sqlite3WhereTrace & 0xffffffff ){ + if( sqlite3WhereTrace & 0xffff ){ sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags); if( wctrlFlags & WHERE_USE_LIMIT ){ sqlite3DebugPrintf(", limit: %d", iAuxArg); } sqlite3DebugPrintf(")\n"); - if( sqlite3WhereTrace & 0x8000 ){ - Select sSelect; - memset(&sSelect, 0, sizeof(sSelect)); - sSelect.selFlags = SF_WhereBegin; - sSelect.pSrc = pTabList; - sSelect.pWhere = pWhere; - sSelect.pOrderBy = pOrderBy; - sSelect.pEList = pResultSet; - sqlite3TreeViewSelect(0, &sSelect, 0); - } - if( sqlite3WhereTrace & 0x4000 ){ /* Display all WHERE clause terms */ - sqlite3DebugPrintf("---- WHERE clause at start of analysis:\n"); - sqlite3WhereClausePrint(sWLB.pWC); - } + } + if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ + sqlite3WhereClausePrint(sWLB.pWC); } #endif if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; - -#ifdef SQLITE_ENABLE_STAT4 - /* If one or more WhereTerm.truthProb values were used in estimating - ** loop parameters, but then those truthProb values were subsequently - ** changed based on STAT4 information while computing subsequent loops, - ** then we need to rerun the whole loop building process so that all - ** loops will be built using the revised truthProb values. */ - if( sWLB.bldFlags2 & SQLITE_BLDF2_2NDPASS ){ - WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC); - WHERETRACE(0xffffffff, - ("**** Redo all loop computations due to" - " TERM_HIGHTRUTH changes ****\n")); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); - } - rc = whereLoopAddAll(&sWLB); - if( rc ) goto whereBeginError; + +#ifdef WHERETRACE_ENABLED + if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */ + WhereLoop *p; + int i; + static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" + "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; + for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ + p->cId = zLabel[i%(sizeof(zLabel)-1)]; + whereLoopPrint(p, sWLB.pWC); + } } #endif - WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC); - + wherePathSolver(pWInfo, 0); if( db->mallocFailed ) goto whereBeginError; if( pWInfo->pOrderBy ){ - whereInterstageHeuristic(pWInfo); - wherePathSolver(pWInfo, pWInfo->nRowOut<0 ? 1 : pWInfo->nRowOut+1); + wherePathSolver(pWInfo, pWInfo->nRowOut+1); if( db->mallocFailed ) goto whereBeginError; } - - /* TUNING: Assume that a DISTINCT clause on a subquery reduces - ** the output size by a factor of 8 (LogEst -30). - */ - if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ - WHERETRACE(0x0080,("nRowOut reduced from %d to %d due to DISTINCT\n", - pWInfo->nRowOut, pWInfo->nRowOut-30)); - pWInfo->nRowOut -= 30; - } - - } - assert( pWInfo->pTabList!=0 ); + } if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - whereReverseScanOrder(pWInfo); + pWInfo->revMask = ALLBITS; } - if( pParse->nErr ){ + if( pParse->nErr || NEVER(db->mallocFailed) ){ goto whereBeginError; } - assert( db->mallocFailed==0 ); #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace ){ - sqlite3DebugPrintf("---- Solution cost=%d, nRow=%d", - pWInfo->rTotalCost, pWInfo->nRowOut); + sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); if( pWInfo->nOBSat>0 ){ sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); } switch( pWInfo->eDistinct ){ case WHERE_DISTINCT_UNIQUE: { @@ -170365,86 +136031,63 @@ break; } } sqlite3DebugPrintf("\n"); for(ii=0; iinLevel; ii++){ - sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC); + whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC); } } #endif - - /* Attempt to omit tables from a join that do not affect the result. - ** See the comment on whereOmitNoopJoin() for further information. - ** - ** This query optimization is factored out into a separate "no-inline" - ** procedure to keep the sqlite3WhereBegin() procedure from becoming - ** too large. If sqlite3WhereBegin() becomes too large, that prevents - ** some C-compiler optimizers from in-lining the - ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to - ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons. - */ - notReady = ~(Bitmask)0; - if( pWInfo->nLevel>=2 /* Must be a join, or this opt8n is pointless */ - && pResultSet!=0 /* Condition (1) */ - && 0==(wctrlFlags & (WHERE_AGG_DISTINCT|WHERE_KEEP_ALL_JOINS)) /* (1),(6) */ - && OptimizationEnabled(db, SQLITE_OmitNoopJoin) /* (7) */ - ){ - notReady = whereOmitNoopJoin(pWInfo, notReady); - nTabList = pWInfo->nLevel; - assert( nTabList>0 ); - } - - /* Check to see if there are any SEARCH loops that might benefit from - ** using a Bloom filter. - */ + /* Attempt to omit tables from the join that do not effect the result */ if( pWInfo->nLevel>=2 - && OptimizationEnabled(db, SQLITE_BloomFilter) + && pResultSet!=0 + && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ - whereCheckIfBloomFilterIsUseful(pWInfo); - } - -#if defined(WHERETRACE_ENABLED) - if( sqlite3WhereTrace & 0x4000 ){ /* Display all terms of the WHERE clause */ - sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n"); - sqlite3WhereClausePrint(sWLB.pWC); - } - WHERETRACE(0xffffffff,("*** Optimizer Finished ***\n")); -#endif + Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); + if( sWLB.pOrderBy ){ + tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); + } + while( pWInfo->nLevel>=2 ){ + WhereTerm *pTerm, *pEnd; + pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; + if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break; + if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 + && (pLoop->wsFlags & WHERE_ONEROW)==0 + ){ + break; + } + if( (tabUsed & pLoop->maskSelf)!=0 ) break; + pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; + for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + ){ + break; + } + } + if( pTerm drop loop %c not used\n", pLoop->cId)); + pWInfo->nLevel--; + nTabList--; + } + } + WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. - ** - ** A one-pass approach can be used if the caller has requested one - ** and either (a) the scan visits at most one row or (b) each - ** of the following are true: - ** - ** * the caller has indicated that a one-pass approach can be used - ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and - ** * the table is not a virtual table, and - ** * either the scan does not use the OR optimization or the caller - ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified - ** for DELETE). - ** - ** The last qualification is because an UPDATE statement uses - ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can - ** use a one-pass approach, and this is not set accurately for scans - ** that use the OR optimization. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ int wsFlags = pWInfo->a[0].pWLoop->wsFlags; int bOnerow = (wsFlags & WHERE_ONEROW)!=0; - assert( !(wsFlags&WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pSTab) ); - if( bOnerow || ( - 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) - && !IsVirtual(pTabList->a[0].pSTab) - && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) - && OptimizationEnabled(db, SQLITE_OnePass) - )){ + if( bOnerow + || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0 + && 0==(wsFlags & WHERE_VIRTUALTABLE)) + ){ pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; - if( HasRowid(pTabList->a[0].pSTab) && (wsFlags & WHERE_IDX_ONLY) ){ + if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ bFordelete = OPFLAG_FORDELETE; } pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY); } @@ -170455,17 +136098,17 @@ ** searching those tables. */ for(ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom]; - pTab = pTabItem->pSTab; + pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; - if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){ + if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); @@ -170473,39 +136116,30 @@ sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else if( IsVirtual(pTab) ){ /* noop */ }else #endif - if( ((pLoop->wsFlags & WHERE_IDX_ONLY)==0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0) - || (pTabItem->fg.jointype & (JT_LTORJ|JT_RIGHT))!=0 - ){ + if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ int op = OP_OpenRead; if( pWInfo->eOnePass!=ONEPASS_OFF ){ op = OP_OpenWrite; pWInfo->aiCurOnePass[0] = pTabItem->iCursor; }; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); assert( pTabItem->iCursor==pLevel->iTabCur ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); - if( pWInfo->eOnePass==ONEPASS_OFF - && pTab->nColtabFlags & (TF_HasGenerated|TF_WithoutRowid))==0 - && (pLoop->wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))==0 - ){ - /* If we know that only a prefix of the record will be used, - ** it is advantageous to reduce the "column count" field in - ** the P4 operand of the OP_OpenRead/Write opcode. */ + if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nColcolUsed; int n = 0; for(; b; b=b>>1, n++){} sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } #ifdef SQLITE_ENABLE_CURSOR_HINTS - if( pLoop->u.btree.pIndex!=0 && (pTab->tabFlags & TF_WithoutRowid)==0 ){ + if( pLoop->u.btree.pIndex!=0 ){ sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); }else #endif { sqlite3VdbeChangeP5(v, bFordelete); @@ -170519,21 +136153,21 @@ } if( pLoop->wsFlags & WHERE_INDEXED ){ Index *pIx = pLoop->u.btree.pIndex; int iIndexCur; int op = OP_OpenRead; - /* iAuxArg is always set to a positive value if ONEPASS is possible */ + /* iAuxArg is always set if to a positive value if ONEPASS is possible */ assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){ /* This is one term of an OR-optimization using the PRIMARY KEY of a ** WITHOUT ROWID table. No need for a separate index */ iIndexCur = pLevel->iTabCur; op = 0; }else if( pWInfo->eOnePass!=ONEPASS_OFF ){ - Index *pJ = pTabItem->pSTab->pIndex; + Index *pJ = pTabItem->pTab->pIndex; iIndexCur = iAuxArg; assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); while( ALWAYS(pJ) && pJ!=pIx ){ iIndexCur++; pJ = pJ->pNext; @@ -170543,34 +136177,23 @@ }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){ iIndexCur = iAuxArg; op = OP_ReopenIdx; }else{ iIndexCur = pParse->nTab++; - if( pIx->bHasExpr && OptimizationEnabled(db, SQLITE_IndexedExpr) ){ - whereAddIndexedExpr(pParse, pIx, iIndexCur, pTabItem); - } - if( pIx->pPartIdxWhere && (pTabItem->fg.jointype & JT_RIGHT)==0 ){ - wherePartIdxExpr( - pParse, pIx, pIx->pPartIdxWhere, 0, iIndexCur, pTabItem - ); - } } pLevel->iIdxCur = iIndexCur; - assert( pIx!=0 ); assert( pIx->pSchema==pTab->pSchema ); assert( iIndexCur>=0 ); if( op ){ sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIx); if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 - && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0 - && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); + sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */ } VdbeComment((v, "%s", pIx->zName)); #ifdef SQLITE_ENABLE_COLUMN_USED_MASK { u64 colUsed = 0; @@ -170587,135 +136210,57 @@ } #endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ } } if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); - if( (pTabItem->fg.jointype & JT_RIGHT)!=0 - && (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0 - ){ - WhereRightJoin *pRJ = pLevel->pRJ; - pRJ->iMatch = pParse->nTab++; - pRJ->regBloom = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom); - pRJ->regReturn = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn); - assert( pTab==pTabItem->pSTab ); - if( HasRowid(pTab) ){ - KeyInfo *pInfo; - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1); - pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0); - if( pInfo ){ - pInfo->aColl[0] = 0; - pInfo->aSortFlags[0] = 0; - sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO); - } - }else{ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol); - sqlite3VdbeSetP4KeyInfo(pParse, pPk); - } - pLoop->wsFlags &= ~WHERE_IDX_ONLY; - /* The nature of RIGHT JOIN processing is such that it messes up - ** the output order. So omit any ORDER BY/GROUP BY elimination - ** optimizations. We need to do an actual sort for RIGHT JOIN. */ - pWInfo->nOBSat = 0; - pWInfo->eDistinct = WHERE_DISTINCT_UNORDERED; - } } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; /* Generate the code to do the search. Each iteration of the for ** loop below generates code for a single nested loop of the VM ** program. */ + notReady = ~(Bitmask)0; for(ii=0; iinErr ) goto whereBeginError; pLevel = &pWInfo->a[ii]; wsFlags = pLevel->pWLoop->wsFlags; - pSrc = &pTabList->a[pLevel->iFrom]; - if( pSrc->fg.isMaterialized ){ - Subquery *pSubq; - int iOnce = 0; - assert( pSrc->fg.isSubquery ); - pSubq = pSrc->u4.pSubq; - if( pSrc->fg.isCorrelated==0 ){ - iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - }else{ - iOnce = 0; - } - sqlite3VdbeAddOp2(v, OP_Gosub, pSubq->regReturn, pSubq->addrFillSub); - VdbeComment((v, "materialize %!S", pSrc)); - if( iOnce ) sqlite3VdbeJumpHere(v, iOnce); - } - assert( pTabList == pWInfo->pTabList ); - if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){ - if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){ #ifndef SQLITE_OMIT_AUTOMATIC_INDEX - constructAutomaticIndex(pParse, &pWInfo->sWC, notReady, pLevel); -#endif - }else{ - sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady); - } + if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ + constructAutomaticIndex(pParse, &pWInfo->sWC, + &pTabList->a[pLevel->iFrom], notReady, pLevel); if( db->mallocFailed ) goto whereBeginError; } +#endif addrExplain = sqlite3WhereExplainOneScan( - pParse, pTabList, pLevel, wctrlFlags + pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags ); pLevel->addrBody = sqlite3VdbeCurrentAddr(v); - notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady); + notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); pWInfo->iContinue = pLevel->addrCont; if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){ sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain); } } /* Done. */ VdbeModuleComment((v, "Begin WHERE-core")); - pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v); return pWInfo; /* Jump here if malloc fails */ whereBeginError: if( pWInfo ){ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); } -#ifdef WHERETRACE_ENABLED - /* Prevent harmless compiler warnings about debugging routines - ** being declared but never used */ - sqlite3ShowWhereLoopList(0); -#endif /* WHERETRACE_ENABLED */ return 0; } /* -** Part of sqlite3WhereEnd() will rewrite opcodes to reference the -** index rather than the main table. In SQLITE_DEBUG mode, we want -** to trace those changes if PRAGMA vdbe_addoptrace=on. This routine -** does that. -*/ -#ifndef SQLITE_DEBUG -# define OpcodeRewriteTrace(D,K,P) /* no-op */ -#else -# define OpcodeRewriteTrace(D,K,P) sqlite3WhereOpcodeRewriteTrace(D,K,P) - static void sqlite3WhereOpcodeRewriteTrace( - sqlite3 *db, - int pc, - VdbeOp *pOp - ){ - if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return; - sqlite3VdbePrintOp(0, pc, pOp); - sqlite3ShowWhereTerm(0); /* So compiler won't complain about unused func */ - } -#endif - -/* -** Generate the end of the WHERE loop. See comments on +** Generate the end of the WHERE loop. See comments on ** sqlite3WhereBegin() for additional information. */ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ Parse *pParse = pWInfo->pParse; Vdbe *v = pParse->pVdbe; @@ -170722,41 +136267,28 @@ int i; WhereLevel *pLevel; WhereLoop *pLoop; SrcList *pTabList = pWInfo->pTabList; sqlite3 *db = pParse->db; - int iEnd = sqlite3VdbeCurrentAddr(v); - int nRJ = 0; /* Generate loop termination code. */ VdbeModuleComment((v, "End WHERE-core")); + sqlite3ExprCacheClear(pParse); for(i=pWInfo->nLevel-1; i>=0; i--){ int addr; pLevel = &pWInfo->a[i]; - if( pLevel->pRJ ){ - /* Terminate the subroutine that forms the interior of the loop of - ** the RIGHT JOIN table */ - WhereRightJoin *pRJ = pLevel->pRJ; - sqlite3VdbeResolveLabel(v, pLevel->addrCont); - pLevel->addrCont = 0; - pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1); - VdbeCoverage(v); - nRJ++; - } pLoop = pLevel->pWLoop; if( pLevel->op!=OP_Noop ){ #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT int addrSeek = 0; Index *pIdx; int n; if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED - && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ && (pLoop->wsFlags & WHERE_INDEXED)!=0 && (pIdx = pLoop->u.btree.pIndex)->hasStat1 - && (n = pLoop->u.btree.nDistinctCol)>0 + && (n = pLoop->u.btree.nIdxCol)>0 && pIdx->aiRowLogEst[n]>=36 ){ int r1 = pParse->nMem+1; int j, op; for(j=0; jp2); } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ /* The common case: Advance to the next row */ - if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont); + sqlite3VdbeResolveLabel(v, pLevel->addrCont); sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeChangeP5(v, pLevel->p5); VdbeCoverage(v); VdbeCoverageIf(v, pLevel->op==OP_Next); VdbeCoverageIf(v, pLevel->op==OP_Prev); VdbeCoverageIf(v, pLevel->op==OP_VNext); - if( pLevel->regBignull ){ - sqlite3VdbeResolveLabel(v, pLevel->addrBignull); - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1); - VdbeCoverage(v); - } #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); #endif - }else if( pLevel->addrCont ){ + }else{ sqlite3VdbeResolveLabel(v, pLevel->addrCont); } - if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){ + if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; int j; sqlite3VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ - assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull - || pParse->db->mallocFailed ); sqlite3VdbeJumpHere(v, pIn->addrInTop+1); if( pIn->eEndLoopOp!=OP_Noop ){ - if( pIn->nPrefix ){ - int bEarlyOut = - (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 - && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0; - if( pLevel->iLeftJoin ){ - /* For LEFT JOIN queries, cursor pIn->iCur may not have been - ** opened yet. This occurs for WHERE clauses such as - ** "a = ? AND b IN (...)", where the index is on (a, b). If - ** the RHS of the (a=?) is NULL, then the "b IN (...)" may - ** never have been coded, but the body of the loop run to - ** return the null-row. So, if the cursor is not open yet, - ** jump over the OP_Next or OP_Prev instruction about to - ** be coded. */ - sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur, - sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut); - VdbeCoverage(v); - } - if( bEarlyOut ){ - sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, - sqlite3VdbeCurrentAddr(v)+2, - pIn->iBase, pIn->nPrefix); - VdbeCoverage(v); - /* Retarget the OP_IsNull against the left operand of IN so - ** it jumps past the OP_IfNoHope. This is because the - ** OP_IsNull also bypasses the OP_Affinity opcode that is - ** required by OP_IfNoHope. */ - sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - } - } sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); VdbeCoverage(v); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); } sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); - if( pLevel->pRJ ){ - sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1); - VdbeCoverage(v); - } if( pLevel->addrSkip ){ sqlite3VdbeGoto(v, pLevel->addrSkip); VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); sqlite3VdbeJumpHere(v, pLevel->addrSkip); sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); @@ -170856,31 +136348,15 @@ if( pLevel->iLeftJoin ){ int ws = pLoop->wsFlags; addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); if( (ws & WHERE_IDX_ONLY)==0 ){ - SrcItem *pSrc = &pTabList->a[pLevel->iFrom]; - assert( pLevel->iTabCur==pSrc->iCursor ); - if( pSrc->fg.viaCoroutine ){ - int m, n; - assert( pSrc->fg.isSubquery ); - n = pSrc->u4.pSubq->regResult; - assert( pSrc->pSTab!=0 ); - m = pSrc->pSTab->nCol; - sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1); - } - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); - } - if( (ws & WHERE_INDEXED) - || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx) - ){ - if( ws & WHERE_MULTI_OR ){ - Index *pIx = pLevel->u.pCoveringIdx; - int iDb = sqlite3SchemaToIndex(db, pIx->pSchema); - sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIx); - } + sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); + } + if( (ws & WHERE_INDEXED) + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) + ){ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); }else{ @@ -170887,3320 +136363,124 @@ sqlite3VdbeGoto(v, pLevel->addrFirst); } sqlite3VdbeJumpHere(v, addr); } VdbeModuleComment((v, "End WHERE-loop%d: %s", i, - pWInfo->pTabList->a[pLevel->iFrom].pSTab->zName)); + pWInfo->pTabList->a[pLevel->iFrom].pTab->zName)); } + + /* The "break" point is here, just past the end of the outer loop. + ** Set it. + */ + sqlite3VdbeResolveLabel(v, pWInfo->iBreak); assert( pWInfo->nLevel<=pTabList->nSrc ); for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ int k, last; - VdbeOp *pOp, *pLastOp; + VdbeOp *pOp; Index *pIdx = 0; - SrcItem *pTabItem = &pTabList->a[pLevel->iFrom]; - Table *pTab = pTabItem->pSTab; + struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; + Table *pTab = pTabItem->pTab; assert( pTab!=0 ); pLoop = pLevel->pWLoop; - /* Do RIGHT JOIN processing. Generate code that will output the - ** unmatched rows of the right operand of the RIGHT JOIN with - ** all of the columns of the left operand set to NULL. - */ - if( pLevel->pRJ ){ - sqlite3WhereRightJoinLoop(pWInfo, i, pLevel); - continue; - } - /* For a co-routine, change all OP_Column references to the table of ** the co-routine into OP_Copy of result contained in a register. ** OP_Rowid becomes OP_Null. */ if( pTabItem->fg.viaCoroutine ){ testcase( pParse->db->mallocFailed ); - assert( pTabItem->fg.isSubquery ); - assert( pTabItem->u4.pSubq->regResult>=0 ); translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, - pTabItem->u4.pSubq->regResult, 0); + pTabItem->regResult, 0); continue; } /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases ** this optimization prevents the table from ever being read, which can ** yield a significant performance boost. - ** + ** ** Calls to the code generator in between sqlite3WhereBegin and ** sqlite3WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){ pIdx = pLoop->u.btree.pIndex; }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ - pIdx = pLevel->u.pCoveringIdx; + pIdx = pLevel->u.pCovidx; } if( pIdx + && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable)) && !db->mallocFailed ){ - if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){ - last = iEnd; - }else{ - last = pWInfo->iEndWhere; - } - if( pIdx->bHasExpr ){ - IndexedExpr *p = pParse->pIdxEpr; - while( p ){ - if( p->iIdxCur==pLevel->iIdxCur ){ -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace & 0x200 ){ - sqlite3DebugPrintf("Disable pParse->pIdxEpr term {%d,%d}\n", - p->iIdxCur, p->iIdxCol); - if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(p->pExpr); - } -#endif - p->iDataCur = -1; - p->iIdxCur = -1; - } - p = p->pIENext; - } - } - k = pLevel->addrBody + 1; -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE cursor %d->%d in opcode range %d..%d\n", - pLevel->iTabCur, pLevel->iIdxCur, k, last-1); - } - /* Proof that the "+1" on the k value above is safe */ - pOp = sqlite3VdbeGetOp(v, k - 1); - assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur ); - assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur ); - assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur ); -#endif + last = sqlite3VdbeCurrentAddr(v); + k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); - pLastOp = pOp + (last - k); - assert( pOp<=pLastOp ); - do{ - if( pOp->p1!=pLevel->iTabCur ){ - /* no-op */ - }else if( pOp->opcode==OP_Column -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - || pOp->opcode==OP_Offset -#endif - ){ + for(; kp1!=pLevel->iTabCur ) continue; + if( pOp->opcode==OP_Column ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - if( pOp->opcode==OP_Offset ){ - /* Do not need to translate the column number */ - }else -#endif if( !HasRowid(pTab) ){ Index *pPk = sqlite3PrimaryKeyIndex(pTab); x = pPk->aiColumn[x]; assert( x>=0 ); - }else{ - testcase( x!=sqlite3StorageColumnToTable(pTab,x) ); - x = sqlite3StorageColumnToTable(pTab,x); } - x = sqlite3TableColumnToIndex(pIdx, x); + x = sqlite3ColumnOfIndex(pIdx, x); if( x>=0 ){ pOp->p2 = x; pOp->p1 = pLevel->iIdxCur; - OpcodeRewriteTrace(db, k, pOp); - }else if( pLoop->wsFlags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){ - if( pLoop->wsFlags & WHERE_IDX_ONLY ){ - /* An error. pLoop is supposed to be a covering index loop, - ** and yet the VM code refers to a column of the table that - ** is not part of the index. */ - sqlite3ErrorMsg(pParse, "internal query planner error"); - pParse->rc = SQLITE_INTERNAL; - }else{ - /* The WHERE_EXPRIDX flag is set by the planner when it is likely - ** that pLoop is a covering index loop, but it is not possible - ** to be 100% sure. In this case, any OP_Explain opcode - ** corresponding to this loop describes the index as a "COVERING - ** INDEX". But, pOp proves that pLoop is not actually a covering - ** index loop. So clear the WHERE_EXPRIDX flag and rewrite the - ** text that accompanies the OP_Explain opcode, if any. */ - pLoop->wsFlags &= ~WHERE_EXPRIDX; - sqlite3WhereAddExplainText(pParse, - pLevel->addrBody-1, - pTabList, - pLevel, - pWInfo->wctrlFlags - ); - } - } + } + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 + || pWInfo->eOnePass ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; - OpcodeRewriteTrace(db, k, pOp); }else if( pOp->opcode==OP_IfNullRow ){ pOp->p1 = pLevel->iIdxCur; - OpcodeRewriteTrace(db, k, pOp); - } -#ifdef SQLITE_DEBUG - k++; -#endif - }while( (++pOp)flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n"); -#endif - } - } - - /* The "break" point is here, just past the end of the outer loop. - ** Set it. - */ - sqlite3VdbeResolveLabel(v, pWInfo->iBreak); + } + } + } + } /* Final cleanup */ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); - pParse->withinRJSubrtn -= nRJ; return; } /************** End of where.c ***********************************************/ -/************** Begin file window.c ******************************************/ -/* -** 2018 May 08 -** -** 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. -** -************************************************************************* -*/ -/* #include "sqliteInt.h" */ - -#ifndef SQLITE_OMIT_WINDOWFUNC - -/* -** SELECT REWRITING -** -** Any SELECT statement that contains one or more window functions in -** either the select list or ORDER BY clause (the only two places window -** functions may be used) is transformed by function sqlite3WindowRewrite() -** in order to support window function processing. For example, with the -** schema: -** -** CREATE TABLE t1(a, b, c, d, e, f, g); -** -** the statement: -** -** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM t1 ORDER BY e; -** -** is transformed to: -** -** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM ( -** SELECT a, e, c, d, b FROM t1 ORDER BY c, d -** ) ORDER BY e; -** -** The flattening optimization is disabled when processing this transformed -** SELECT statement. This allows the implementation of the window function -** (in this case max()) to process rows sorted in order of (c, d), which -** makes things easier for obvious reasons. More generally: -** -** * FROM, WHERE, GROUP BY and HAVING clauses are all moved to -** the sub-query. -** -** * ORDER BY, LIMIT and OFFSET remain part of the parent query. -** -** * Terminals from each of the expression trees that make up the -** select-list and ORDER BY expressions in the parent query are -** selected by the sub-query. For the purposes of the transformation, -** terminals are column references and aggregate functions. -** -** If there is more than one window function in the SELECT that uses -** the same window declaration (the OVER bit), then a single scan may -** be used to process more than one window function. For example: -** -** SELECT max(b) OVER (PARTITION BY c ORDER BY d), -** min(e) OVER (PARTITION BY c ORDER BY d) -** FROM t1; -** -** is transformed in the same way as the example above. However: -** -** SELECT max(b) OVER (PARTITION BY c ORDER BY d), -** min(e) OVER (PARTITION BY a ORDER BY b) -** FROM t1; -** -** Must be transformed to: -** -** SELECT max(b) OVER (PARTITION BY c ORDER BY d) FROM ( -** SELECT e, min(e) OVER (PARTITION BY a ORDER BY b), c, d, b FROM -** SELECT a, e, c, d, b FROM t1 ORDER BY a, b -** ) ORDER BY c, d -** ) ORDER BY e; -** -** so that both min() and max() may process rows in the order defined by -** their respective window declarations. -** -** INTERFACE WITH SELECT.C -** -** When processing the rewritten SELECT statement, code in select.c calls -** sqlite3WhereBegin() to begin iterating through the results of the -** sub-query, which is always implemented as a co-routine. It then calls -** sqlite3WindowCodeStep() to process rows and finish the scan by calling -** sqlite3WhereEnd(). -** -** sqlite3WindowCodeStep() generates VM code so that, for each row returned -** by the sub-query a sub-routine (OP_Gosub) coded by select.c is invoked. -** When the sub-routine is invoked: -** -** * The results of all window-functions for the row are stored -** in the associated Window.regResult registers. -** -** * The required terminal values are stored in the current row of -** temp table Window.iEphCsr. -** -** In some cases, depending on the window frame and the specific window -** functions invoked, sqlite3WindowCodeStep() caches each entire partition -** in a temp table before returning any rows. In other cases it does not. -** This detail is encapsulated within this file, the code generated by -** select.c is the same in either case. -** -** BUILT-IN WINDOW FUNCTIONS -** -** This implementation features the following built-in window functions: -** -** row_number() -** rank() -** dense_rank() -** percent_rank() -** cume_dist() -** ntile(N) -** lead(expr [, offset [, default]]) -** lag(expr [, offset [, default]]) -** first_value(expr) -** last_value(expr) -** nth_value(expr, N) -** -** These are the same built-in window functions supported by Postgres. -** Although the behaviour of aggregate window functions (functions that -** can be used as either aggregates or window functions) allows them to -** be implemented using an API, built-in window functions are much more -** esoteric. Additionally, some window functions (e.g. nth_value()) -** may only be implemented by caching the entire partition in memory. -** As such, some built-in window functions use the same API as aggregate -** window functions and some are implemented directly using VDBE -** instructions. Additionally, for those functions that use the API, the -** window frame is sometimes modified before the SELECT statement is -** rewritten. For example, regardless of the specified window frame, the -** row_number() function always uses: -** -** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -** -** See sqlite3WindowUpdate() for details. -** -** As well as some of the built-in window functions, aggregate window -** functions min() and max() are implemented using VDBE instructions if -** the start of the window frame is declared as anything other than -** UNBOUNDED PRECEDING. -*/ - -/* -** Implementation of built-in window function row_number(). Assumes that the -** window frame has been coerced to: -** -** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -*/ -static void row_numberStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ) (*p)++; - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void row_numberValueFunc(sqlite3_context *pCtx){ - i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - sqlite3_result_int64(pCtx, (p ? *p : 0)); -} - -/* -** Context object type used by rank(), dense_rank(), percent_rank() and -** cume_dist(). -*/ -struct CallCount { - i64 nValue; - i64 nStep; - i64 nTotal; -}; - -/* -** Implementation of built-in window function dense_rank(). Assumes that -** the window frame has been set to: -** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -*/ -static void dense_rankStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ) p->nStep = 1; - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void dense_rankValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - if( p->nStep ){ - p->nValue++; - p->nStep = 0; - } - sqlite3_result_int64(pCtx, p->nValue); - } -} - -/* -** Implementation of built-in window function nth_value(). This -** implementation is used in "slow mode" only - when the EXCLUDE clause -** is not set to the default value "NO OTHERS". -*/ -struct NthValueCtx { - i64 nStep; - sqlite3_value *pValue; -}; -static void nth_valueStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - i64 iVal; - switch( sqlite3_value_numeric_type(apArg[1]) ){ - case SQLITE_INTEGER: - iVal = sqlite3_value_int64(apArg[1]); - break; - case SQLITE_FLOAT: { - double fVal = sqlite3_value_double(apArg[1]); - if( ((i64)fVal)!=fVal ) goto error_out; - iVal = (i64)fVal; - break; - } - default: - goto error_out; - } - if( iVal<=0 ) goto error_out; - - p->nStep++; - if( iVal==p->nStep ){ - p->pValue = sqlite3_value_dup(apArg[0]); - if( !p->pValue ){ - sqlite3_result_error_nomem(pCtx); - } - } - } - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); - return; - - error_out: - sqlite3_result_error( - pCtx, "second argument to nth_value must be a positive integer", -1 - ); -} -static void nth_valueFinalizeFunc(sqlite3_context *pCtx){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, 0); - if( p && p->pValue ){ - sqlite3_result_value(pCtx, p->pValue); - sqlite3_value_free(p->pValue); - p->pValue = 0; - } -} -#define nth_valueInvFunc noopStepFunc -#define nth_valueValueFunc noopValueFunc - -static void first_valueStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->pValue==0 ){ - p->pValue = sqlite3_value_dup(apArg[0]); - if( !p->pValue ){ - sqlite3_result_error_nomem(pCtx); - } - } - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void first_valueFinalizeFunc(sqlite3_context *pCtx){ - struct NthValueCtx *p; - p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->pValue ){ - sqlite3_result_value(pCtx, p->pValue); - sqlite3_value_free(p->pValue); - p->pValue = 0; - } -} -#define first_valueInvFunc noopStepFunc -#define first_valueValueFunc noopValueFunc - -/* -** Implementation of built-in window function rank(). Assumes that -** the window frame has been set to: -** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -*/ -static void rankStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nStep++; - if( p->nValue==0 ){ - p->nValue = p->nStep; - } - } - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); -} -static void rankValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - sqlite3_result_int64(pCtx, p->nValue); - p->nValue = 0; - } -} - -/* -** Implementation of built-in window function percent_rank(). Assumes that -** the window frame has been set to: -** -** GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -*/ -static void percent_rankStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nTotal++; - } -} -static void percent_rankInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - p->nStep++; -} -static void percent_rankValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nValue = p->nStep; - if( p->nTotal>1 ){ - double r = (double)p->nValue / (double)(p->nTotal-1); - sqlite3_result_double(pCtx, r); - }else{ - sqlite3_result_double(pCtx, 0.0); - } - } -} -#define percent_rankFinalizeFunc percent_rankValueFunc - -/* -** Implementation of built-in window function cume_dist(). Assumes that -** the window frame has been set to: -** -** GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING -*/ -static void cume_distStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - p->nTotal++; - } -} -static void cume_distInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==0 ); - UNUSED_PARAMETER(apArg); - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - p->nStep++; -} -static void cume_distValueFunc(sqlite3_context *pCtx){ - struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, 0); - if( p ){ - double r = (double)(p->nStep) / (double)(p->nTotal); - sqlite3_result_double(pCtx, r); - } -} -#define cume_distFinalizeFunc cume_distValueFunc - -/* -** Context object for ntile() window function. -*/ -struct NtileCtx { - i64 nTotal; /* Total rows in partition */ - i64 nParam; /* Parameter passed to ntile(N) */ - i64 iRow; /* Current row */ -}; - -/* -** Implementation of ntile(). This assumes that the window frame has -** been coerced to: -** -** ROWS CURRENT ROW AND UNBOUNDED FOLLOWING -*/ -static void ntileStepFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NtileCtx *p; - assert( nArg==1 ); UNUSED_PARAMETER(nArg); - p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p ){ - if( p->nTotal==0 ){ - p->nParam = sqlite3_value_int64(apArg[0]); - if( p->nParam<=0 ){ - sqlite3_result_error( - pCtx, "argument of ntile must be a positive integer", -1 - ); - } - } - p->nTotal++; - } -} -static void ntileInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct NtileCtx *p; - assert( nArg==1 ); UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); - p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - p->iRow++; -} -static void ntileValueFunc(sqlite3_context *pCtx){ - struct NtileCtx *p; - p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->nParam>0 ){ - int nSize = (p->nTotal / p->nParam); - if( nSize==0 ){ - sqlite3_result_int64(pCtx, p->iRow+1); - }else{ - i64 nLarge = p->nTotal - p->nParam*nSize; - i64 iSmall = nLarge*(nSize+1); - i64 iRow = p->iRow; - - assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal ); - - if( iRowpVal); - p->pVal = sqlite3_value_dup(apArg[0]); - if( p->pVal==0 ){ - sqlite3_result_error_nomem(pCtx); - }else{ - p->nVal++; - } - } -} -static void last_valueInvFunc( - sqlite3_context *pCtx, - int nArg, - sqlite3_value **apArg -){ - struct LastValueCtx *p; - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(apArg); - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( ALWAYS(p) ){ - p->nVal--; - if( p->nVal==0 ){ - sqlite3_value_free(p->pVal); - p->pVal = 0; - } - } -} -static void last_valueValueFunc(sqlite3_context *pCtx){ - struct LastValueCtx *p; - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, 0); - if( p && p->pVal ){ - sqlite3_result_value(pCtx, p->pVal); - } -} -static void last_valueFinalizeFunc(sqlite3_context *pCtx){ - struct LastValueCtx *p; - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->pVal ){ - sqlite3_result_value(pCtx, p->pVal); - sqlite3_value_free(p->pVal); - p->pVal = 0; - } -} - -/* -** Static names for the built-in window function names. These static -** names are used, rather than string literals, so that FuncDef objects -** can be associated with a particular window function by direct -** comparison of the zName pointer. Example: -** -** if( pFuncDef->zName==row_valueName ){ ... } -*/ -static const char row_numberName[] = "row_number"; -static const char dense_rankName[] = "dense_rank"; -static const char rankName[] = "rank"; -static const char percent_rankName[] = "percent_rank"; -static const char cume_distName[] = "cume_dist"; -static const char ntileName[] = "ntile"; -static const char last_valueName[] = "last_value"; -static const char nth_valueName[] = "nth_value"; -static const char first_valueName[] = "first_value"; -static const char leadName[] = "lead"; -static const char lagName[] = "lag"; - -/* -** No-op implementations of xStep() and xFinalize(). Used as place-holders -** for built-in window functions that never call those interfaces. -** -** The noopValueFunc() is called but is expected to do nothing. The -** noopStepFunc() is never called, and so it is marked with NO_TEST to -** let the test coverage routine know not to expect this function to be -** invoked. -*/ -static void noopStepFunc( /*NO_TEST*/ - sqlite3_context *p, /*NO_TEST*/ - int n, /*NO_TEST*/ - sqlite3_value **a /*NO_TEST*/ -){ /*NO_TEST*/ - UNUSED_PARAMETER(p); /*NO_TEST*/ - UNUSED_PARAMETER(n); /*NO_TEST*/ - UNUSED_PARAMETER(a); /*NO_TEST*/ - assert(0); /*NO_TEST*/ -} /*NO_TEST*/ -static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ } - -/* Window functions that use all window interfaces: xStep, xFinal, -** xValue, and xInverse */ -#define WINDOWFUNCALL(name,nArg,extra) { \ - nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ - name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \ - name ## InvFunc, name ## Name, {0} \ -} - -/* Window functions that are implemented using bytecode and thus have -** no-op routines for their methods */ -#define WINDOWFUNCNOOP(name,nArg,extra) { \ - nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ - noopStepFunc, noopValueFunc, noopValueFunc, \ - noopStepFunc, name ## Name, {0} \ -} - -/* Window functions that use all window interfaces: xStep, the -** same routine for xFinalize and xValue and which never call -** xInverse. */ -#define WINDOWFUNCX(name,nArg,extra) { \ - nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ - name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \ - noopStepFunc, name ## Name, {0} \ -} - - -/* -** Register those built-in window functions that are not also aggregates. -*/ -SQLITE_PRIVATE void sqlite3WindowFunctions(void){ - static FuncDef aWindowFuncs[] = { - WINDOWFUNCX(row_number, 0, 0), - WINDOWFUNCX(dense_rank, 0, 0), - WINDOWFUNCX(rank, 0, 0), - WINDOWFUNCALL(percent_rank, 0, 0), - WINDOWFUNCALL(cume_dist, 0, 0), - WINDOWFUNCALL(ntile, 1, 0), - WINDOWFUNCALL(last_value, 1, 0), - WINDOWFUNCALL(nth_value, 2, 0), - WINDOWFUNCALL(first_value, 1, 0), - WINDOWFUNCNOOP(lead, 1, 0), - WINDOWFUNCNOOP(lead, 2, 0), - WINDOWFUNCNOOP(lead, 3, 0), - WINDOWFUNCNOOP(lag, 1, 0), - WINDOWFUNCNOOP(lag, 2, 0), - WINDOWFUNCNOOP(lag, 3, 0), - }; - sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs)); -} - -static Window *windowFind(Parse *pParse, Window *pList, const char *zName){ - Window *p; - for(p=pList; p; p=p->pNextWin){ - if( sqlite3StrICmp(p->zName, zName)==0 ) break; - } - if( p==0 ){ - sqlite3ErrorMsg(pParse, "no such window: %s", zName); - } - return p; -} - -/* -** This function is called immediately after resolving the function name -** for a window function within a SELECT statement. Argument pList is a -** linked list of WINDOW definitions for the current SELECT statement. -** Argument pFunc is the function definition just resolved and pWin -** is the Window object representing the associated OVER clause. This -** function updates the contents of pWin as follows: -** -** * If the OVER clause referred to a named window (as in "max(x) OVER win"), -** search list pList for a matching WINDOW definition, and update pWin -** accordingly. If no such WINDOW clause can be found, leave an error -** in pParse. -** -** * If the function is a built-in window function that requires the -** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top -** of this file), pWin is updated here. -*/ -SQLITE_PRIVATE void sqlite3WindowUpdate( - Parse *pParse, - Window *pList, /* List of named windows for this SELECT */ - Window *pWin, /* Window frame to update */ - FuncDef *pFunc /* Window function definition */ -){ - if( pWin->zName && pWin->eFrmType==0 ){ - Window *p = windowFind(pParse, pList, pWin->zName); - if( p==0 ) return; - pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); - pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0); - pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0); - pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); - pWin->eStart = p->eStart; - pWin->eEnd = p->eEnd; - pWin->eFrmType = p->eFrmType; - pWin->eExclude = p->eExclude; - }else{ - sqlite3WindowChain(pParse, pWin, pList); - } - if( (pWin->eFrmType==TK_RANGE) - && (pWin->pStart || pWin->pEnd) - && (pWin->pOrderBy==0 || pWin->pOrderBy->nExpr!=1) - ){ - sqlite3ErrorMsg(pParse, - "RANGE with offset PRECEDING/FOLLOWING requires one ORDER BY expression" - ); - }else - if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){ - sqlite3 *db = pParse->db; - if( pWin->pFilter ){ - sqlite3ErrorMsg(pParse, - "FILTER clause may only be used with aggregate window functions" - ); - }else{ - struct WindowUpdate { - const char *zFunc; - int eFrmType; - int eStart; - int eEnd; - } aUp[] = { - { row_numberName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT }, - { dense_rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT }, - { rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT }, - { percent_rankName, TK_GROUPS, TK_CURRENT, TK_UNBOUNDED }, - { cume_distName, TK_GROUPS, TK_FOLLOWING, TK_UNBOUNDED }, - { ntileName, TK_ROWS, TK_CURRENT, TK_UNBOUNDED }, - { leadName, TK_ROWS, TK_UNBOUNDED, TK_UNBOUNDED }, - { lagName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT }, - }; - int i; - for(i=0; izName==aUp[i].zFunc ){ - sqlite3ExprDelete(db, pWin->pStart); - sqlite3ExprDelete(db, pWin->pEnd); - pWin->pEnd = pWin->pStart = 0; - pWin->eFrmType = aUp[i].eFrmType; - pWin->eStart = aUp[i].eStart; - pWin->eEnd = aUp[i].eEnd; - pWin->eExclude = 0; - if( pWin->eStart==TK_FOLLOWING ){ - pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1"); - } - break; - } - } - } - } - pWin->pWFunc = pFunc; -} - -/* -** Context object passed through sqlite3WalkExprList() to -** selectWindowRewriteExprCb() by selectWindowRewriteEList(). -*/ -typedef struct WindowRewrite WindowRewrite; -struct WindowRewrite { - Window *pWin; - SrcList *pSrc; - ExprList *pSub; - Table *pTab; - Select *pSubSelect; /* Current sub-select, if any */ -}; - -/* -** Callback function used by selectWindowRewriteEList(). If necessary, -** this function appends to the output expression-list and updates -** expression (*ppExpr) in place. -*/ -static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ - struct WindowRewrite *p = pWalker->u.pRewrite; - Parse *pParse = pWalker->pParse; - assert( p!=0 ); - assert( p->pWin!=0 ); - - /* If this function is being called from within a scalar sub-select - ** that used by the SELECT statement being processed, only process - ** TK_COLUMN expressions that refer to it (the outer SELECT). Do - ** not process aggregates or window functions at all, as they belong - ** to the scalar sub-select. */ - if( p->pSubSelect ){ - if( pExpr->op!=TK_COLUMN ){ - return WRC_Continue; - }else{ - int nSrc = p->pSrc->nSrc; - int i; - for(i=0; iiTable==p->pSrc->a[i].iCursor ) break; - } - if( i==nSrc ) return WRC_Continue; - } - } - - switch( pExpr->op ){ - - case TK_FUNCTION: - if( !ExprHasProperty(pExpr, EP_WinFunc) ){ - break; - }else{ - Window *pWin; - for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ - if( pExpr->y.pWin==pWin ){ - assert( pWin->pOwner==pExpr ); - return WRC_Prune; - } - } - } - /* no break */ deliberate_fall_through - - case TK_IF_NULL_ROW: - case TK_AGG_FUNCTION: - case TK_COLUMN: { - int iCol = -1; - if( pParse->db->mallocFailed ) return WRC_Abort; - if( p->pSub ){ - int i; - for(i=0; ipSub->nExpr; i++){ - if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){ - iCol = i; - break; - } - } - } - if( iCol<0 ){ - Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0); - if( pDup && pDup->op==TK_AGG_FUNCTION ) pDup->op = TK_FUNCTION; - p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup); - } - if( p->pSub ){ - int f = pExpr->flags & EP_Collate; - assert( ExprHasProperty(pExpr, EP_Static)==0 ); - ExprSetProperty(pExpr, EP_Static); - sqlite3ExprDelete(pParse->db, pExpr); - ExprClearProperty(pExpr, EP_Static); - memset(pExpr, 0, sizeof(Expr)); - - pExpr->op = TK_COLUMN; - pExpr->iColumn = (iCol<0 ? p->pSub->nExpr-1: iCol); - pExpr->iTable = p->pWin->iEphCsr; - pExpr->y.pTab = p->pTab; - pExpr->flags = f; - } - if( pParse->db->mallocFailed ) return WRC_Abort; - break; - } - - default: /* no-op */ - break; - } - - return WRC_Continue; -} -static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){ - struct WindowRewrite *p = pWalker->u.pRewrite; - Select *pSave = p->pSubSelect; - if( pSave==pSelect ){ - return WRC_Continue; - }else{ - p->pSubSelect = pSelect; - sqlite3WalkSelect(pWalker, pSelect); - p->pSubSelect = pSave; - } - return WRC_Prune; -} - - -/* -** Iterate through each expression in expression-list pEList. For each: -** -** * TK_COLUMN, -** * aggregate function, or -** * window function with a Window object that is not a member of the -** Window list passed as the second argument (pWin). -** -** Append the node to output expression-list (*ppSub). And replace it -** with a TK_COLUMN that reads the (N-1)th element of table -** pWin->iEphCsr, where N is the number of elements in (*ppSub) after -** appending the new one. -*/ -static void selectWindowRewriteEList( - Parse *pParse, - Window *pWin, - SrcList *pSrc, - ExprList *pEList, /* Rewrite expressions in this list */ - Table *pTab, - ExprList **ppSub /* IN/OUT: Sub-select expression-list */ -){ - Walker sWalker; - WindowRewrite sRewrite; - - assert( pWin!=0 ); - memset(&sWalker, 0, sizeof(Walker)); - memset(&sRewrite, 0, sizeof(WindowRewrite)); - - sRewrite.pSub = *ppSub; - sRewrite.pWin = pWin; - sRewrite.pSrc = pSrc; - sRewrite.pTab = pTab; - - sWalker.pParse = pParse; - sWalker.xExprCallback = selectWindowRewriteExprCb; - sWalker.xSelectCallback = selectWindowRewriteSelectCb; - sWalker.u.pRewrite = &sRewrite; - - (void)sqlite3WalkExprList(&sWalker, pEList); - - *ppSub = sRewrite.pSub; -} - -/* -** Append a copy of each expression in expression-list pAppend to -** expression list pList. Return a pointer to the result list. -*/ -static ExprList *exprListAppendList( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to append. Might be NULL */ - ExprList *pAppend, /* List of values to append. Might be NULL */ - int bIntToNull -){ - if( pAppend ){ - int i; - int nInit = pList ? pList->nExpr : 0; - for(i=0; inExpr; i++){ - sqlite3 *db = pParse->db; - Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - break; - } - if( bIntToNull ){ - int iDummy; - Expr *pSub; - pSub = sqlite3ExprSkipCollateAndLikely(pDup); - if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){ - pSub->op = TK_NULL; - pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); - pSub->u.zToken = 0; - } - } - pList = sqlite3ExprListAppend(pParse, pList, pDup); - if( pList ) pList->a[nInit+i].fg.sortFlags = pAppend->a[i].fg.sortFlags; - } - } - return pList; -} - -/* -** When rewriting a query, if the new subquery in the FROM clause -** contains TK_AGG_FUNCTION nodes that refer to an outer query, -** then we have to increase the Expr->op2 values of those nodes -** due to the extra subquery layer that was added. -** -** See also the incrAggDepth() routine in resolve.c -*/ -static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION - && pExpr->op2>=pWalker->walkerDepth - ){ - pExpr->op2++; - } - return WRC_Continue; -} - -static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3ErrorMsg(pWalker->pParse, - "misuse of aggregate: %s()", pExpr->u.zToken); - } - return WRC_Continue; -} - -/* -** If the SELECT statement passed as the second argument does not invoke -** any SQL window functions, this function is a no-op. Otherwise, it -** rewrites the SELECT statement so that window function xStep functions -** are invoked in the correct order as described under "SELECT REWRITING" -** at the top of this file. -*/ -SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ - int rc = SQLITE_OK; - if( p->pWin - && p->pPrior==0 - && ALWAYS((p->selFlags & SF_WinRewrite)==0) - && ALWAYS(!IN_RENAME_OBJECT) - ){ - Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3 *db = pParse->db; - Select *pSub = 0; /* The subquery */ - SrcList *pSrc = p->pSrc; - Expr *pWhere = p->pWhere; - ExprList *pGroupBy = p->pGroupBy; - Expr *pHaving = p->pHaving; - ExprList *pSort = 0; - - ExprList *pSublist = 0; /* Expression list for sub-query */ - Window *pMWin = p->pWin; /* Main window object */ - Window *pWin; /* Window object iterator */ - Table *pTab; - Walker w; - - u32 selFlags = p->selFlags; - - pTab = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTab==0 ){ - return sqlite3ErrorToParser(db, SQLITE_NOMEM); - } - sqlite3AggInfoPersistWalkerInit(&w, pParse); - sqlite3WalkSelect(&w, p); - if( (p->selFlags & SF_Aggregate)==0 ){ - w.xExprCallback = disallowAggregatesInOrderByCb; - w.xSelectCallback = 0; - sqlite3WalkExprList(&w, p->pOrderBy); - } - - p->pSrc = 0; - p->pWhere = 0; - p->pGroupBy = 0; - p->pHaving = 0; - p->selFlags &= ~SF_Aggregate; - p->selFlags |= SF_WinRewrite; - - /* Create the ORDER BY clause for the sub-select. This is the concatenation - ** of the window PARTITION and ORDER BY clauses. Then, if this makes it - ** redundant, remove the ORDER BY from the parent SELECT. */ - pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1); - pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1); - if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){ - int nSave = pSort->nExpr; - pSort->nExpr = p->pOrderBy->nExpr; - if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ - sqlite3ExprListDelete(db, p->pOrderBy); - p->pOrderBy = 0; - } - pSort->nExpr = nSave; - } - - /* Assign a cursor number for the ephemeral table used to buffer rows. - ** The OpenEphemeral instruction is coded later, after it is known how - ** many columns the table will have. */ - pMWin->iEphCsr = pParse->nTab++; - pParse->nTab += 3; - - selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, pTab, &pSublist); - selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, pTab, &pSublist); - pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0); - - /* Append the PARTITION BY and ORDER BY expressions to the to the - ** sub-select expression list. They are required to figure out where - ** boundaries for partitions and sets of peer rows lie. */ - pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition, 0); - pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0); - - /* Append the arguments passed to each window function to the - ** sub-select expression list. Also allocate two registers for each - ** window function - one for the accumulator, another for interim - ** results. */ - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - ExprList *pArgs; - assert( ExprUseXList(pWin->pOwner) ); - assert( pWin->pWFunc!=0 ); - pArgs = pWin->pOwner->x.pList; - if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){ - selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); - pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pWin->bExprArgs = 1; - }else{ - pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pSublist = exprListAppendList(pParse, pSublist, pArgs, 0); - } - if( pWin->pFilter ){ - Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); - pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); - } - pWin->regAccum = ++pParse->nMem; - pWin->regResult = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - } - - /* If there is no ORDER BY or PARTITION BY clause, and the window - ** function accepts zero arguments, and there are no other columns - ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible - ** that pSublist is still NULL here. Add a constant expression here to - ** keep everything legal in this case. - */ - if( pSublist==0 ){ - pSublist = sqlite3ExprListAppend(pParse, 0, - sqlite3Expr(db, TK_INTEGER, "0") - ); - } - - pSub = sqlite3SelectNew( - pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0 - ); - TREETRACE(0x40,pParse,pSub, - ("New window-function subquery in FROM clause of (%u/%p)\n", - p->selId, p)); - p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside - ** of sqlite3DbMallocRawNN() called from - ** sqlite3SrcListAppend() */ - if( p->pSrc==0 ){ - sqlite3SelectDelete(db, pSub); - }else if( sqlite3SrcItemAttachSubquery(pParse, &p->pSrc->a[0], pSub, 0) ){ - Table *pTab2; - p->pSrc->a[0].fg.isCorrelated = 1; - sqlite3SrcListAssignCursors(pParse, p->pSrc); - pSub->selFlags |= SF_Expanded|SF_OrderByReqd; - pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE); - pSub->selFlags |= (selFlags & SF_Aggregate); - if( pTab2==0 ){ - /* Might actually be some other kind of error, but in that case - ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get - ** the correct error message regardless. */ - rc = SQLITE_NOMEM; - }else{ - memcpy(pTab, pTab2, sizeof(Table)); - pTab->tabFlags |= TF_Ephemeral; - p->pSrc->a[0].pSTab = pTab; - pTab = pTab2; - memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3WindowExtraAggFuncDepth; - w.xSelectCallback = sqlite3WalkerDepthIncrease; - w.xSelectCallback2 = sqlite3WalkerDepthDecrease; - sqlite3WalkSelect(&w, pSub); - } - } - if( db->mallocFailed ) rc = SQLITE_NOMEM; - - /* Defer deleting the temporary table pTab because if an error occurred, - ** there could still be references to that table embedded in the - ** result-set or ORDER BY clause of the SELECT statement p. */ - sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab); - } - - assert( rc==SQLITE_OK || pParse->nErr!=0 ); - return rc; -} - -/* -** Unlink the Window object from the Select to which it is attached, -** if it is attached. -*/ -SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window *p){ - if( p->ppThis ){ - *p->ppThis = p->pNextWin; - if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis; - p->ppThis = 0; - } -} - -/* -** Free the Window object passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){ - if( p ){ - sqlite3WindowUnlinkFromSelect(p); - sqlite3ExprDelete(db, p->pFilter); - sqlite3ExprListDelete(db, p->pPartition); - sqlite3ExprListDelete(db, p->pOrderBy); - sqlite3ExprDelete(db, p->pEnd); - sqlite3ExprDelete(db, p->pStart); - sqlite3DbFree(db, p->zName); - sqlite3DbFree(db, p->zBase); - sqlite3DbFree(db, p); - } -} - -/* -** Free the linked list of Window objects starting at the second argument. -*/ -SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){ - while( p ){ - Window *pNext = p->pNextWin; - sqlite3WindowDelete(db, p); - p = pNext; - } -} - -/* -** The argument expression is an PRECEDING or FOLLOWING offset. The -** value should be a non-negative integer. If the value is not a -** constant, change it to NULL. The fact that it is then a non-negative -** integer will be caught later. But it is important not to leave -** variable values in the expression tree. -*/ -static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ - if( 0==sqlite3ExprIsConstant(0,pExpr) ){ - if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr); - sqlite3ExprDelete(pParse->db, pExpr); - pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); - } - return pExpr; -} - -/* -** Allocate and return a new Window object describing a Window Definition. -*/ -SQLITE_PRIVATE Window *sqlite3WindowAlloc( - Parse *pParse, /* Parsing context */ - int eType, /* Frame type. TK_RANGE, TK_ROWS, TK_GROUPS, or 0 */ - int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */ - Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */ - int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */ - Expr *pEnd, /* End window size if TK_FOLLOWING or PRECEDING */ - u8 eExclude /* EXCLUDE clause */ -){ - Window *pWin = 0; - int bImplicitFrame = 0; - - /* Parser assures the following: */ - assert( eType==0 || eType==TK_RANGE || eType==TK_ROWS || eType==TK_GROUPS ); - assert( eStart==TK_CURRENT || eStart==TK_PRECEDING - || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING ); - assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING - || eEnd==TK_UNBOUNDED || eEnd==TK_PRECEDING ); - assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) ); - assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) ); - - if( eType==0 ){ - bImplicitFrame = 1; - eType = TK_RANGE; - } - - /* Additionally, the - ** starting boundary type may not occur earlier in the following list than - ** the ending boundary type: - ** - ** UNBOUNDED PRECEDING - ** PRECEDING - ** CURRENT ROW - ** FOLLOWING - ** UNBOUNDED FOLLOWING - ** - ** The parser ensures that "UNBOUNDED PRECEDING" cannot be used as an ending - ** boundary, and than "UNBOUNDED FOLLOWING" cannot be used as a starting - ** frame boundary. - */ - if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING) - || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT)) - ){ - sqlite3ErrorMsg(pParse, "unsupported frame specification"); - goto windowAllocErr; - } - - pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( pWin==0 ) goto windowAllocErr; - pWin->eFrmType = eType; - pWin->eStart = eStart; - pWin->eEnd = eEnd; - if( eExclude==0 && OptimizationDisabled(pParse->db, SQLITE_WindowFunc) ){ - eExclude = TK_NO; - } - pWin->eExclude = eExclude; - pWin->bImplicitFrame = bImplicitFrame; - pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd); - pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart); - return pWin; - -windowAllocErr: - sqlite3ExprDelete(pParse->db, pEnd); - sqlite3ExprDelete(pParse->db, pStart); - return 0; -} - -/* -** Attach PARTITION and ORDER BY clauses pPartition and pOrderBy to window -** pWin. Also, if parameter pBase is not NULL, set pWin->zBase to the -** equivalent nul-terminated string. -*/ -SQLITE_PRIVATE Window *sqlite3WindowAssemble( - Parse *pParse, - Window *pWin, - ExprList *pPartition, - ExprList *pOrderBy, - Token *pBase -){ - if( pWin ){ - pWin->pPartition = pPartition; - pWin->pOrderBy = pOrderBy; - if( pBase ){ - pWin->zBase = sqlite3DbStrNDup(pParse->db, pBase->z, pBase->n); - } - }else{ - sqlite3ExprListDelete(pParse->db, pPartition); - sqlite3ExprListDelete(pParse->db, pOrderBy); - } - return pWin; -} - -/* -** Window *pWin has just been created from a WINDOW clause. Token pBase -** is the base window. Earlier windows from the same WINDOW clause are -** stored in the linked list starting at pWin->pNextWin. This function -** either updates *pWin according to the base specification, or else -** leaves an error in pParse. -*/ -SQLITE_PRIVATE void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){ - if( pWin->zBase ){ - sqlite3 *db = pParse->db; - Window *pExist = windowFind(pParse, pList, pWin->zBase); - if( pExist ){ - const char *zErr = 0; - /* Check for errors */ - if( pWin->pPartition ){ - zErr = "PARTITION clause"; - }else if( pExist->pOrderBy && pWin->pOrderBy ){ - zErr = "ORDER BY clause"; - }else if( pExist->bImplicitFrame==0 ){ - zErr = "frame specification"; - } - if( zErr ){ - sqlite3ErrorMsg(pParse, - "cannot override %s of window: %s", zErr, pWin->zBase - ); - }else{ - pWin->pPartition = sqlite3ExprListDup(db, pExist->pPartition, 0); - if( pExist->pOrderBy ){ - assert( pWin->pOrderBy==0 ); - pWin->pOrderBy = sqlite3ExprListDup(db, pExist->pOrderBy, 0); - } - sqlite3DbFree(db, pWin->zBase); - pWin->zBase = 0; - } - } - } -} - -/* -** Attach window object pWin to expression p. -*/ -SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ - if( p ){ - assert( p->op==TK_FUNCTION ); - assert( pWin ); - assert( ExprIsFullSize(p) ); - p->y.pWin = pWin; - ExprSetProperty(p, EP_WinFunc|EP_FullSize); - pWin->pOwner = p; - if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){ - sqlite3ErrorMsg(pParse, - "DISTINCT is not supported for window functions" - ); - } - }else{ - sqlite3WindowDelete(pParse->db, pWin); - } -} - -/* -** Possibly link window pWin into the list at pSel->pWin (window functions -** to be processed as part of SELECT statement pSel). The window is linked -** in if either (a) there are no other windows already linked to this -** SELECT, or (b) the windows already linked use a compatible window frame. -*/ -SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){ - if( pSel ){ - if( 0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0) ){ - pWin->pNextWin = pSel->pWin; - if( pSel->pWin ){ - pSel->pWin->ppThis = &pWin->pNextWin; - } - pSel->pWin = pWin; - pWin->ppThis = &pSel->pWin; - }else{ - if( sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){ - pSel->selFlags |= SF_MultiPart; - } - } - } -} - -/* -** Return 0 if the two window objects are identical, 1 if they are -** different, or 2 if it cannot be determined if the objects are identical -** or not. Identical window objects can be processed in a single scan. -*/ -SQLITE_PRIVATE int sqlite3WindowCompare( - const Parse *pParse, - const Window *p1, - const Window *p2, - int bFilter -){ - int res; - if( NEVER(p1==0) || NEVER(p2==0) ) return 1; - if( p1->eFrmType!=p2->eFrmType ) return 1; - if( p1->eStart!=p2->eStart ) return 1; - if( p1->eEnd!=p2->eEnd ) return 1; - if( p1->eExclude!=p2->eExclude ) return 1; - if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1; - if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; - if( (res = sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1)) ){ - return res; - } - if( (res = sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1)) ){ - return res; - } - if( bFilter ){ - if( (res = sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1)) ){ - return res; - } - } - return 0; -} - - -/* -** This is called by code in select.c before it calls sqlite3WhereBegin() -** to begin iterating through the sub-query results. It is used to allocate -** and initialize registers and cursors used by sqlite3WindowCodeStep(). -*/ -SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){ - Window *pWin; - int nEphExpr; - Window *pMWin; - Vdbe *v; - - assert( pSelect->pSrc->a[0].fg.isSubquery ); - nEphExpr = pSelect->pSrc->a[0].u4.pSubq->pSelect->pEList->nExpr; - pMWin = pSelect->pWin; - v = sqlite3GetVdbe(pParse); - - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr); - - /* Allocate registers to use for PARTITION BY values, if any. Initialize - ** said registers to NULL. */ - if( pMWin->pPartition ){ - int nExpr = pMWin->pPartition->nExpr; - pMWin->regPart = pParse->nMem+1; - pParse->nMem += nExpr; - sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1); - } - - pMWin->regOne = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regOne); - - if( pMWin->eExclude ){ - pMWin->regStartRowid = ++pParse->nMem; - pMWin->regEndRowid = ++pParse->nMem; - pMWin->csrApp = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid); - sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->csrApp, pMWin->iEphCsr); - return; - } - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *p = pWin->pWFunc; - if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ - /* The inline versions of min() and max() require a single ephemeral - ** table and 3 registers. The registers are used as follows: - ** - ** regApp+0: slot to copy min()/max() argument to for MakeRecord - ** regApp+1: integer value used to ensure keys are unique - ** regApp+2: output of MakeRecord - */ - ExprList *pList; - KeyInfo *pKeyInfo; - assert( ExprUseXList(pWin->pOwner) ); - pList = pWin->pOwner->x.pList; - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); - pWin->csrApp = pParse->nTab++; - pWin->regApp = pParse->nMem+1; - pParse->nMem += 3; - if( pKeyInfo && pWin->pWFunc->zName[1]=='i' ){ - assert( pKeyInfo->aSortFlags[0]==0 ); - pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC; - } - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); - sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } - else if( p->zName==nth_valueName || p->zName==first_valueName ){ - /* Allocate two registers at pWin->regApp. These will be used to - ** store the start and end index of the current frame. */ - pWin->regApp = pParse->nMem+1; - pWin->csrApp = pParse->nTab++; - pParse->nMem += 2; - sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); - } - else if( p->zName==leadName || p->zName==lagName ){ - pWin->csrApp = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); - } - } -} - -#define WINDOW_STARTING_INT 0 -#define WINDOW_ENDING_INT 1 -#define WINDOW_NTH_VALUE_INT 2 -#define WINDOW_STARTING_NUM 3 -#define WINDOW_ENDING_NUM 4 - -/* -** A "PRECEDING " (eCond==0) or "FOLLOWING " (eCond==1) or the -** value of the second argument to nth_value() (eCond==2) has just been -** evaluated and the result left in register reg. This function generates VM -** code to check that the value is a non-negative integer and throws an -** exception if it is not. -*/ -static void windowCheckValue(Parse *pParse, int reg, int eCond){ - static const char *azErr[] = { - "frame starting offset must be a non-negative integer", - "frame ending offset must be a non-negative integer", - "second argument to nth_value must be a positive integer", - "frame starting offset must be a non-negative number", - "frame ending offset must be a non-negative number", - }; - static int aOp[] = { OP_Ge, OP_Ge, OP_Gt, OP_Ge, OP_Ge }; - Vdbe *v = sqlite3GetVdbe(pParse); - int regZero = sqlite3GetTempReg(pParse); - assert( eCond>=0 && eCond=WINDOW_STARTING_NUM ){ - int regString = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); - sqlite3VdbeAddOp3(v, OP_Ge, regString, sqlite3VdbeCurrentAddr(v)+2, reg); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC|SQLITE_JUMPIFNULL); - VdbeCoverage(v); - assert( eCond==3 || eCond==4 ); - VdbeCoverageIf(v, eCond==3); - VdbeCoverageIf(v, eCond==4); - }else{ - sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - assert( eCond==0 || eCond==1 || eCond==2 ); - VdbeCoverageIf(v, eCond==0); - VdbeCoverageIf(v, eCond==1); - VdbeCoverageIf(v, eCond==2); - } - sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC); - VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */ - VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */ - VdbeCoverageNeverNullIf(v, eCond==2); - VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */ - VdbeCoverageNeverNullIf(v, eCond==4); /* the OP_Ge */ - sqlite3MayAbort(pParse); - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); - sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); - sqlite3ReleaseTempReg(pParse, regZero); -} - -/* -** Return the number of arguments passed to the window-function associated -** with the object passed as the only argument to this function. -*/ -static int windowArgCount(Window *pWin){ - const ExprList *pList; - assert( ExprUseXList(pWin->pOwner) ); - pList = pWin->pOwner->x.pList; - return (pList ? pList->nExpr : 0); -} - -typedef struct WindowCodeArg WindowCodeArg; -typedef struct WindowCsrAndReg WindowCsrAndReg; - -/* -** See comments above struct WindowCodeArg. -*/ -struct WindowCsrAndReg { - int csr; /* Cursor number */ - int reg; /* First in array of peer values */ -}; - -/* -** A single instance of this structure is allocated on the stack by -** sqlite3WindowCodeStep() and a pointer to it passed to the various helper -** routines. This is to reduce the number of arguments required by each -** helper function. -** -** regArg: -** Each window function requires an accumulator register (just as an -** ordinary aggregate function does). This variable is set to the first -** in an array of accumulator registers - one for each window function -** in the WindowCodeArg.pMWin list. -** -** eDelete: -** The window functions implementation sometimes caches the input rows -** that it processes in a temporary table. If it is not zero, this -** variable indicates when rows may be removed from the temp table (in -** order to reduce memory requirements - it would always be safe just -** to leave them there). Possible values for eDelete are: -** -** WINDOW_RETURN_ROW: -** An input row can be discarded after it is returned to the caller. -** -** WINDOW_AGGINVERSE: -** An input row can be discarded after the window functions xInverse() -** callbacks have been invoked in it. -** -** WINDOW_AGGSTEP: -** An input row can be discarded after the window functions xStep() -** callbacks have been invoked in it. -** -** start,current,end -** Consider a window-frame similar to the following: -** -** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING) -** -** The windows functions implementation caches the input rows in a temp -** table, sorted by "a, b" (it actually populates the cache lazily, and -** aggressively removes rows once they are no longer required, but that's -** a mere detail). It keeps three cursors open on the temp table. One -** (current) that points to the next row to return to the query engine -** once its window function values have been calculated. Another (end) -** points to the next row to call the xStep() method of each window function -** on (so that it is 2 groups ahead of current). And a third (start) that -** points to the next row to call the xInverse() method of each window -** function on. -** -** Each cursor (start, current and end) consists of a VDBE cursor -** (WindowCsrAndReg.csr) and an array of registers (starting at -** WindowCodeArg.reg) that always contains a copy of the peer values -** read from the corresponding cursor. -** -** Depending on the window-frame in question, all three cursors may not -** be required. In this case both WindowCodeArg.csr and reg are set to -** 0. -*/ -struct WindowCodeArg { - Parse *pParse; /* Parse context */ - Window *pMWin; /* First in list of functions being processed */ - Vdbe *pVdbe; /* VDBE object */ - int addrGosub; /* OP_Gosub to this address to return one row */ - int regGosub; /* Register used with OP_Gosub(addrGosub) */ - int regArg; /* First in array of accumulator registers */ - int eDelete; /* See above */ - int regRowid; - - WindowCsrAndReg start; - WindowCsrAndReg current; - WindowCsrAndReg end; -}; - -/* -** Generate VM code to read the window frames peer values from cursor csr into -** an array of registers starting at reg. -*/ -static void windowReadPeerValues( - WindowCodeArg *p, - int csr, - int reg -){ - Window *pMWin = p->pMWin; - ExprList *pOrderBy = pMWin->pOrderBy; - if( pOrderBy ){ - Vdbe *v = sqlite3GetVdbe(p->pParse); - ExprList *pPart = pMWin->pPartition; - int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); - int i; - for(i=0; inExpr; i++){ - sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i); - } - } -} - -/* -** Generate VM code to invoke either xStep() (if bInverse is 0) or -** xInverse (if bInverse is non-zero) for each window function in the -** linked list starting at pMWin. Or, for built-in window functions -** that do not use the standard function API, generate the required -** inline VM code. -** -** If argument csr is greater than or equal to 0, then argument reg is -** the first register in an array of registers guaranteed to be large -** enough to hold the array of arguments for each function. In this case -** the arguments are extracted from the current row of csr into the -** array of registers before invoking OP_AggStep or OP_AggInverse -** -** Or, if csr is less than zero, then the array of registers at reg is -** already populated with all columns from the current row of the sub-query. -** -** If argument regPartSize is non-zero, then it is a register containing the -** number of rows in the current partition. -*/ -static void windowAggStep( - WindowCodeArg *p, - Window *pMWin, /* Linked list of window functions */ - int csr, /* Read arguments from this cursor */ - int bInverse, /* True to invoke xInverse instead of xStep */ - int reg /* Array of registers */ -){ - Parse *pParse = p->pParse; - Vdbe *v = sqlite3GetVdbe(pParse); - Window *pWin; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - int regArg; - int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin); - int i; - int addrIf = 0; - - assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED ); - - /* All OVER clauses in the same window function aggregate step must - ** be the same. */ - assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)!=1 ); - - for(i=0; izName!=nth_valueName ){ - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i); - } - } - regArg = reg; - - if( pWin->pFilter ){ - int regTmp; - assert( ExprUseXList(pWin->pOwner) ); - assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr ); - assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 ); - regTmp = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); - addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); - VdbeCoverage(v); - sqlite3ReleaseTempReg(pParse, regTmp); - } - - if( pMWin->regStartRowid==0 - && (pFunc->funcFlags & SQLITE_FUNC_MINMAX) - && (pWin->eStart!=TK_UNBOUNDED) - ){ - int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg); - VdbeCoverage(v); - if( bInverse==0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1); - sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp); - sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2); - }else{ - sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1); - VdbeCoverageNeverTaken(v); - sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - } - sqlite3VdbeJumpHere(v, addrIsNull); - }else if( pWin->regApp ){ - assert( pWin->pFilter==0 ); - assert( pFunc->zName==nth_valueName - || pFunc->zName==first_valueName - ); - assert( bInverse==0 || bInverse==1 ); - sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1); - }else if( pFunc->xSFunc!=noopStepFunc ){ - if( pWin->bExprArgs ){ - int iOp = sqlite3VdbeCurrentAddr(v); - int iEnd; - - assert( ExprUseXList(pWin->pOwner) ); - nArg = pWin->pOwner->x.pList->nExpr; - regArg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0); - - for(iEnd=sqlite3VdbeCurrentAddr(v); iOpopcode==OP_Column && pOp->p1==pMWin->iEphCsr ){ - pOp->p1 = csr; - } - } - } - if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ - CollSeq *pColl; - assert( nArg>0 ); - assert( ExprUseXList(pWin->pOwner) ); - pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); - sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep, - bInverse, regArg, pWin->regAccum); - sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u16)nArg); - if( pWin->bExprArgs ){ - sqlite3ReleaseTempRange(pParse, regArg, nArg); - } - } - - if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); - } -} - -/* -** Values that may be passed as the second argument to windowCodeOp(). -*/ -#define WINDOW_RETURN_ROW 1 -#define WINDOW_AGGINVERSE 2 -#define WINDOW_AGGSTEP 3 - -/* -** Generate VM code to invoke either xValue() (bFin==0) or xFinalize() -** (bFin==1) for each window function in the linked list starting at -** pMWin. Or, for built-in window-functions that do not use the standard -** API, generate the equivalent VM code. -*/ -static void windowAggFinal(WindowCodeArg *p, int bFin){ - Parse *pParse = p->pParse; - Window *pMWin = p->pMWin; - Vdbe *v = sqlite3GetVdbe(pParse); - Window *pWin; - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - if( pMWin->regStartRowid==0 - && (pWin->pWFunc->funcFlags & SQLITE_FUNC_MINMAX) - && (pWin->eStart!=TK_UNBOUNDED) - ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - }else if( pWin->regApp ){ - assert( pMWin->regStartRowid==0 ); - }else{ - int nArg = windowArgCount(pWin); - if( bFin ){ - sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, nArg); - sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF); - sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - }else{ - sqlite3VdbeAddOp3(v, OP_AggValue,pWin->regAccum,nArg,pWin->regResult); - sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF); - } - } - } -} - -/* -** Generate code to calculate the current values of all window functions in the -** p->pMWin list by doing a full scan of the current window frame. Store the -** results in the Window.regResult registers, ready to return the upper -** layer. -*/ -static void windowFullScan(WindowCodeArg *p){ - Window *pWin; - Parse *pParse = p->pParse; - Window *pMWin = p->pMWin; - Vdbe *v = p->pVdbe; - - int regCRowid = 0; /* Current rowid value */ - int regCPeer = 0; /* Current peer values */ - int regRowid = 0; /* AggStep rowid value */ - int regPeer = 0; /* AggStep peer values */ - - int nPeer; - int lblNext; - int lblBrk; - int addrNext; - int csr; - - VdbeModuleComment((v, "windowFullScan begin")); - - assert( pMWin!=0 ); - csr = pMWin->csrApp; - nPeer = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); - - lblNext = sqlite3VdbeMakeLabel(pParse); - lblBrk = sqlite3VdbeMakeLabel(pParse); - - regCRowid = sqlite3GetTempReg(pParse); - regRowid = sqlite3GetTempReg(pParse); - if( nPeer ){ - regCPeer = sqlite3GetTempRange(pParse, nPeer); - regPeer = sqlite3GetTempRange(pParse, nPeer); - } - - sqlite3VdbeAddOp2(v, OP_Rowid, pMWin->iEphCsr, regCRowid); - windowReadPeerValues(p, pMWin->iEphCsr, regCPeer); - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - } - - sqlite3VdbeAddOp3(v, OP_SeekGE, csr, lblBrk, pMWin->regStartRowid); - VdbeCoverage(v); - addrNext = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Rowid, csr, regRowid); - sqlite3VdbeAddOp3(v, OP_Gt, pMWin->regEndRowid, lblBrk, regRowid); - VdbeCoverageNeverNull(v); - - if( pMWin->eExclude==TK_CURRENT ){ - sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, lblNext, regRowid); - VdbeCoverageNeverNull(v); - }else if( pMWin->eExclude!=TK_NO ){ - int addr; - int addrEq = 0; - KeyInfo *pKeyInfo = 0; - - if( pMWin->pOrderBy ){ - pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pMWin->pOrderBy, 0, 0); - } - if( pMWin->eExclude==TK_TIES ){ - addrEq = sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, 0, regRowid); - VdbeCoverageNeverNull(v); - } - if( pKeyInfo ){ - windowReadPeerValues(p, csr, regPeer); - sqlite3VdbeAddOp3(v, OP_Compare, regPeer, regCPeer, nPeer); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - addr = sqlite3VdbeCurrentAddr(v)+1; - sqlite3VdbeAddOp3(v, OP_Jump, addr, lblNext, addr); - VdbeCoverageEqNe(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblNext); - } - if( addrEq ) sqlite3VdbeJumpHere(v, addrEq); - } - - windowAggStep(p, pMWin, csr, 0, p->regArg); - - sqlite3VdbeResolveLabel(v, lblNext); - sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addrNext-1); - sqlite3VdbeJumpHere(v, addrNext+1); - sqlite3ReleaseTempReg(pParse, regRowid); - sqlite3ReleaseTempReg(pParse, regCRowid); - if( nPeer ){ - sqlite3ReleaseTempRange(pParse, regPeer, nPeer); - sqlite3ReleaseTempRange(pParse, regCPeer, nPeer); - } - - windowAggFinal(p, 1); - VdbeModuleComment((v, "windowFullScan end")); -} - -/* -** Invoke the sub-routine at regGosub (generated by code in select.c) to -** return the current row of Window.iEphCsr. If all window functions are -** aggregate window functions that use the standard API, a single -** OP_Gosub instruction is all that this routine generates. Extra VM code -** for per-row processing is only generated for the following built-in window -** functions: -** -** nth_value() -** first_value() -** lag() -** lead() -*/ -static void windowReturnOneRow(WindowCodeArg *p){ - Window *pMWin = p->pMWin; - Vdbe *v = p->pVdbe; - - if( pMWin->regStartRowid ){ - windowFullScan(p); - }else{ - Parse *pParse = p->pParse; - Window *pWin; - - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - assert( ExprUseXList(pWin->pOwner) ); - if( pFunc->zName==nth_valueName - || pFunc->zName==first_valueName - ){ - int csr = pWin->csrApp; - int lbl = sqlite3VdbeMakeLabel(pParse); - int tmpReg = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - - if( pFunc->zName==nth_valueName ){ - sqlite3VdbeAddOp3(v, OP_Column,pMWin->iEphCsr,pWin->iArgCol+1,tmpReg); - windowCheckValue(pParse, tmpReg, 2); - }else{ - sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); - } - sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); - sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); - VdbeCoverageNeverNull(v); - sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg); - VdbeCoverageNeverTaken(v); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); - sqlite3VdbeResolveLabel(v, lbl); - sqlite3ReleaseTempReg(pParse, tmpReg); - } - else if( pFunc->zName==leadName || pFunc->zName==lagName ){ - int nArg = pWin->pOwner->x.pList->nExpr; - int csr = pWin->csrApp; - int lbl = sqlite3VdbeMakeLabel(pParse); - int tmpReg = sqlite3GetTempReg(pParse); - int iEph = pMWin->iEphCsr; - - if( nArg<3 ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iEph,pWin->iArgCol+2,pWin->regResult); - } - sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); - if( nArg<2 ){ - int val = (pFunc->zName==leadName ? 1 : -1); - sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); - }else{ - int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract); - int tmpReg2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); - sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); - sqlite3ReleaseTempReg(pParse, tmpReg2); - } - - sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); - sqlite3VdbeResolveLabel(v, lbl); - sqlite3ReleaseTempReg(pParse, tmpReg); - } - } - } - sqlite3VdbeAddOp2(v, OP_Gosub, p->regGosub, p->addrGosub); -} - -/* -** Generate code to set the accumulator register for each window function -** in the linked list passed as the second argument to NULL. And perform -** any equivalent initialization required by any built-in window functions -** in the list. -*/ -static int windowInitAccum(Parse *pParse, Window *pMWin){ - Vdbe *v = sqlite3GetVdbe(pParse); - int regArg; - int nArg = 0; - Window *pWin; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - assert( pWin->regAccum ); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); - nArg = MAX(nArg, windowArgCount(pWin)); - if( pMWin->regStartRowid==0 ){ - if( pFunc->zName==nth_valueName || pFunc->zName==first_valueName ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } - - if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ - assert( pWin->eStart!=TK_UNBOUNDED ); - sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } - } - } - regArg = pParse->nMem+1; - pParse->nMem += nArg; - return regArg; -} - -/* -** Return true if the current frame should be cached in the ephemeral table, -** even if there are no xInverse() calls required. -*/ -static int windowCacheFrame(Window *pMWin){ - Window *pWin; - if( pMWin->regStartRowid ) return 1; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pWFunc; - if( (pFunc->zName==nth_valueName) - || (pFunc->zName==first_valueName) - || (pFunc->zName==leadName) - || (pFunc->zName==lagName) - ){ - return 1; - } - } - return 0; -} - -/* -** regOld and regNew are each the first register in an array of size -** pOrderBy->nExpr. This function generates code to compare the two -** arrays of registers using the collation sequences and other comparison -** parameters specified by pOrderBy. -** -** If the two arrays are not equal, the contents of regNew is copied to -** regOld and control falls through. Otherwise, if the contents of the arrays -** are equal, an OP_Goto is executed. The address of the OP_Goto is returned. -*/ -static void windowIfNewPeer( - Parse *pParse, - ExprList *pOrderBy, - int regNew, /* First in array of new values */ - int regOld, /* First in array of old values */ - int addr /* Jump here */ -){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( pOrderBy ){ - int nVal = pOrderBy->nExpr; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); - sqlite3VdbeAddOp3(v, OP_Compare, regOld, regNew, nVal); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, - sqlite3VdbeCurrentAddr(v)+1, addr, sqlite3VdbeCurrentAddr(v)+1 - ); - VdbeCoverageEqNe(v); - sqlite3VdbeAddOp3(v, OP_Copy, regNew, regOld, nVal-1); - }else{ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); - } -} - -/* -** This function is called as part of generating VM programs for RANGE -** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for -** the ORDER BY term in the window, and that argument op is OP_Ge, it generates -** code equivalent to: -** -** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl; -** -** The value of parameter op may also be OP_Gt or OP_Le. In these cases the -** operator in the above pseudo-code is replaced with ">" or "<=", respectively. -** -** If the sort-order for the ORDER BY term in the window is DESC, then the -** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is -** subtracted. And the comparison operator is inverted to - ">=" becomes "<=", -** ">" becomes "<", and so on. So, with DESC sort order, if the argument op -** is OP_Ge, the generated code is equivalent to: -** -** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl; -** -** A special type of arithmetic is used such that if csr1.peerVal is not -** a numeric type (real or integer), then the result of the addition -** or subtraction is a a copy of csr1.peerVal. -*/ -static void windowCodeRangeTest( - WindowCodeArg *p, - int op, /* OP_Ge, OP_Gt, or OP_Le */ - int csr1, /* Cursor number for cursor 1 */ - int regVal, /* Register containing non-negative number */ - int csr2, /* Cursor number for cursor 2 */ - int lbl /* Jump destination if condition is true */ -){ - Parse *pParse = p->pParse; - Vdbe *v = sqlite3GetVdbe(pParse); - ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */ - int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */ - int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */ - int regString = ++pParse->nMem; /* Reg. for constant value '' */ - int arith = OP_Add; /* OP_Add or OP_Subtract */ - int addrGe; /* Jump destination */ - int addrDone = sqlite3VdbeMakeLabel(pParse); /* Address past OP_Ge */ - CollSeq *pColl; - - /* Read the peer-value from each cursor into a register */ - windowReadPeerValues(p, csr1, reg1); - windowReadPeerValues(p, csr2, reg2); - - assert( op==OP_Ge || op==OP_Gt || op==OP_Le ); - assert( pOrderBy && pOrderBy->nExpr==1 ); - if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_DESC ){ - switch( op ){ - case OP_Ge: op = OP_Le; break; - case OP_Gt: op = OP_Lt; break; - default: assert( op==OP_Le ); op = OP_Ge; break; - } - arith = OP_Subtract; - } - - VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl", - reg1, (arith==OP_Add ? "+" : "-"), regVal, - ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2 - )); - - /* If the BIGNULL flag is set for the ORDER BY, then it is required to - ** consider NULL values to be larger than all other values, instead of - ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this - ** (and adding that capability causes a performance regression), so - ** instead if the BIGNULL flag is set then cases where either reg1 or - ** reg2 are NULL are handled separately in the following block. The code - ** generated is equivalent to: - ** - ** if( reg1 IS NULL ){ - ** if( op==OP_Ge ) goto lbl; - ** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl; - ** if( op==OP_Le && reg2 IS NULL ) goto lbl; - ** }else if( reg2 IS NULL ){ - ** if( op==OP_Le ) goto lbl; - ** } - ** - ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is - ** not taken, control jumps over the comparison operator coded below this - ** block. */ - if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){ - /* This block runs if reg1 contains a NULL. */ - int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v); - switch( op ){ - case OP_Ge: - sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl); - break; - case OP_Gt: - sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl); - VdbeCoverage(v); - break; - case OP_Le: - sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); - VdbeCoverage(v); - break; - default: assert( op==OP_Lt ); /* no-op */ break; - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone); - - /* This block runs if reg1 is not NULL, but reg2 is. */ - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp2(v, OP_IsNull, reg2, - (op==OP_Gt || op==OP_Ge) ? addrDone : lbl); - VdbeCoverage(v); - } - - /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1). - ** This block adds (or subtracts for DESC) the numeric value in regVal - ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob), - ** then leave reg1 as it is. In pseudo-code, this is implemented as: - ** - ** if( reg1>='' ) goto addrGe; - ** reg1 = reg1 +/- regVal - ** addrGe: - ** - ** Since all strings and blobs are greater-than-or-equal-to an empty string, - ** the add/subtract is skipped for these, as required. If reg1 is a NULL, - ** then the arithmetic is performed, but since adding or subtracting from - ** NULL is always NULL anyway, this case is handled as required too. */ - sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); - addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1); - VdbeCoverage(v); - if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){ - sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1); - sqlite3VdbeJumpHere(v, addrGe); - - /* Compare registers reg2 and reg1, taking the jump if required. Note that - ** control skips over this test if the BIGNULL flag is set and either - ** reg1 or reg2 contain a NULL value. */ - sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v); - pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr); - sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - sqlite3VdbeResolveLabel(v, addrDone); - - assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le ); - testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge); - testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt); - testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le); - testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt); - sqlite3ReleaseTempReg(pParse, reg1); - sqlite3ReleaseTempReg(pParse, reg2); - - VdbeModuleComment((v, "CodeRangeTest: end")); -} - -/* -** Helper function for sqlite3WindowCodeStep(). Each call to this function -** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE -** operation. Refer to the header comment for sqlite3WindowCodeStep() for -** details. -*/ -static int windowCodeOp( - WindowCodeArg *p, /* Context object */ - int op, /* WINDOW_RETURN_ROW, AGGSTEP or AGGINVERSE */ - int regCountdown, /* Register for OP_IfPos countdown */ - int jumpOnEof /* Jump here if stepped cursor reaches EOF */ -){ - int csr, reg; - Parse *pParse = p->pParse; - Window *pMWin = p->pMWin; - int ret = 0; - Vdbe *v = p->pVdbe; - int addrContinue = 0; - int bPeer = (pMWin->eFrmType!=TK_ROWS); - - int lblDone = sqlite3VdbeMakeLabel(pParse); - int addrNextRange = 0; - - /* Special case - WINDOW_AGGINVERSE is always a no-op if the frame - ** starts with UNBOUNDED PRECEDING. */ - if( op==WINDOW_AGGINVERSE && pMWin->eStart==TK_UNBOUNDED ){ - assert( regCountdown==0 && jumpOnEof==0 ); - return 0; - } - - if( regCountdown>0 ){ - if( pMWin->eFrmType==TK_RANGE ){ - addrNextRange = sqlite3VdbeCurrentAddr(v); - assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP ); - if( op==WINDOW_AGGINVERSE ){ - if( pMWin->eStart==TK_FOLLOWING ){ - windowCodeRangeTest( - p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone - ); - }else{ - windowCodeRangeTest( - p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone - ); - } - }else{ - windowCodeRangeTest( - p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone - ); - } - }else{ - sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1); - VdbeCoverage(v); - } - } - - if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){ - windowAggFinal(p, 0); - } - addrContinue = sqlite3VdbeCurrentAddr(v); - - /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or - ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the - ** start cursor does not advance past the end cursor within the - ** temporary table. It otherwise might, if (a>b). Also ensure that, - ** if the input cursor is still finding new rows, that the end - ** cursor does not go past it to EOF. */ - if( pMWin->eStart==pMWin->eEnd && regCountdown - && pMWin->eFrmType==TK_RANGE - ){ - int regRowid1 = sqlite3GetTempReg(pParse); - int regRowid2 = sqlite3GetTempReg(pParse); - if( op==WINDOW_AGGINVERSE ){ - sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1); - sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2); - sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1); - VdbeCoverage(v); - }else if( p->regRowid ){ - sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1); - sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1); - VdbeCoverageNeverNull(v); - } - sqlite3ReleaseTempReg(pParse, regRowid1); - sqlite3ReleaseTempReg(pParse, regRowid2); - assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ); - } - - switch( op ){ - case WINDOW_RETURN_ROW: - csr = p->current.csr; - reg = p->current.reg; - windowReturnOneRow(p); - break; - - case WINDOW_AGGINVERSE: - csr = p->start.csr; - reg = p->start.reg; - if( pMWin->regStartRowid ){ - assert( pMWin->regEndRowid ); - sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1); - }else{ - windowAggStep(p, pMWin, csr, 1, p->regArg); - } - break; - - default: - assert( op==WINDOW_AGGSTEP ); - csr = p->end.csr; - reg = p->end.reg; - if( pMWin->regStartRowid ){ - assert( pMWin->regEndRowid ); - sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1); - }else{ - windowAggStep(p, pMWin, csr, 0, p->regArg); - } - break; - } - - if( op==p->eDelete ){ - sqlite3VdbeAddOp1(v, OP_Delete, csr); - sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); - } - - if( jumpOnEof ){ - sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - ret = sqlite3VdbeAddOp0(v, OP_Goto); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer); - VdbeCoverage(v); - if( bPeer ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone); - } - } - - if( bPeer ){ - int nReg = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); - int regTmp = (nReg ? sqlite3GetTempRange(pParse, nReg) : 0); - windowReadPeerValues(p, csr, regTmp); - windowIfNewPeer(pParse, pMWin->pOrderBy, regTmp, reg, addrContinue); - sqlite3ReleaseTempRange(pParse, regTmp, nReg); - } - - if( addrNextRange ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange); - } - sqlite3VdbeResolveLabel(v, lblDone); - return ret; -} - - -/* -** Allocate and return a duplicate of the Window object indicated by the -** third argument. Set the Window.pOwner field of the new object to -** pOwner. -*/ -SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ - Window *pNew = 0; - if( ALWAYS(p) ){ - pNew = sqlite3DbMallocZero(db, sizeof(Window)); - if( pNew ){ - pNew->zName = sqlite3DbStrDup(db, p->zName); - pNew->zBase = sqlite3DbStrDup(db, p->zBase); - pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); - pNew->pWFunc = p->pWFunc; - pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); - pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); - pNew->eFrmType = p->eFrmType; - pNew->eEnd = p->eEnd; - pNew->eStart = p->eStart; - pNew->eExclude = p->eExclude; - pNew->regResult = p->regResult; - pNew->regAccum = p->regAccum; - pNew->iArgCol = p->iArgCol; - pNew->iEphCsr = p->iEphCsr; - pNew->bExprArgs = p->bExprArgs; - pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); - pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); - pNew->pOwner = pOwner; - pNew->bImplicitFrame = p->bImplicitFrame; - } - } - return pNew; -} - -/* -** Return a copy of the linked list of Window objects passed as the -** second argument. -*/ -SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){ - Window *pWin; - Window *pRet = 0; - Window **pp = &pRet; - - for(pWin=p; pWin; pWin=pWin->pNextWin){ - *pp = sqlite3WindowDup(db, 0, pWin); - if( *pp==0 ) break; - pp = &((*pp)->pNextWin); - } - - return pRet; -} - -/* -** Return true if it can be determined at compile time that expression -** pExpr evaluates to a value that, when cast to an integer, is greater -** than zero. False otherwise. -** -** If an OOM error occurs, this function sets the Parse.db.mallocFailed -** flag and returns zero. -*/ -static int windowExprGtZero(Parse *pParse, Expr *pExpr){ - int ret = 0; - sqlite3 *db = pParse->db; - sqlite3_value *pVal = 0; - sqlite3ValueFromExpr(db, pExpr, db->enc, SQLITE_AFF_NUMERIC, &pVal); - if( pVal && sqlite3_value_int(pVal)>0 ){ - ret = 1; - } - sqlite3ValueFree(pVal); - return ret; -} - -/* -** sqlite3WhereBegin() has already been called for the SELECT statement -** passed as the second argument when this function is invoked. It generates -** code to populate the Window.regResult register for each window function -** and invoke the sub-routine at instruction addrGosub once for each row. -** sqlite3WhereEnd() is always called before returning. -** -** This function handles several different types of window frames, which -** require slightly different processing. The following pseudo code is -** used to implement window frames of the form: -** -** ROWS BETWEEN PRECEDING AND FOLLOWING -** -** Other window frame types use variants of the following: -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** -** if( first row of partition ){ -** // Rewind three cursors, all open on the eph table. -** Rewind(csrEnd); -** Rewind(csrStart); -** Rewind(csrCurrent); -** -** regEnd = // FOLLOWING expression -** regStart = // PRECEDING expression -** }else{ -** // First time this branch is taken, the eph table contains two -** // rows. The first row in the partition, which all three cursors -** // currently point to, and the following row. -** AGGSTEP -** if( (regEnd--)<=0 ){ -** RETURN_ROW -** if( (regStart--)<=0 ){ -** AGGINVERSE -** } -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** RETURN ROW -** if( csrCurrent is EOF ) break; -** if( (regStart--)<=0 ){ -** AggInverse(csrStart) -** Next(csrStart) -** } -** } -** -** The pseudo-code above uses the following shorthand: -** -** AGGSTEP: invoke the aggregate xStep() function for each window function -** with arguments read from the current row of cursor csrEnd, then -** step cursor csrEnd forward one row (i.e. sqlite3BtreeNext()). -** -** RETURN_ROW: return a row to the caller based on the contents of the -** current row of csrCurrent and the current state of all -** aggregates. Then step cursor csrCurrent forward one row. -** -** AGGINVERSE: invoke the aggregate xInverse() function for each window -** functions with arguments read from the current row of cursor -** csrStart. Then step csrStart forward one row. -** -** There are two other ROWS window frames that are handled significantly -** differently from the above - "BETWEEN PRECEDING AND PRECEDING" -** and "BETWEEN FOLLOWING AND FOLLOWING". These are special -** cases because they change the order in which the three cursors (csrStart, -** csrCurrent and csrEnd) iterate through the ephemeral table. Cases that -** use UNBOUNDED or CURRENT ROW are much simpler variations on one of these -** three. -** -** ROWS BETWEEN PRECEDING AND PRECEDING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** if( (regEnd--)<=0 ){ -** AGGSTEP -** } -** RETURN_ROW -** if( (regStart--)<=0 ){ -** AGGINVERSE -** } -** } -** } -** flush: -** if( (regEnd--)<=0 ){ -** AGGSTEP -** } -** RETURN_ROW -** -** -** ROWS BETWEEN FOLLOWING AND FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = regEnd - -** }else{ -** AGGSTEP -** if( (regEnd--)<=0 ){ -** RETURN_ROW -** } -** if( (regStart--)<=0 ){ -** AGGINVERSE -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** if( (regEnd--)<=0 ){ -** RETURN_ROW -** if( eof ) break; -** } -** if( (regStart--)<=0 ){ -** AGGINVERSE -** if( eof ) break -** } -** } -** while( !eof csrCurrent ){ -** RETURN_ROW -** } -** -** For the most part, the patterns above are adapted to support UNBOUNDED by -** assuming that it is equivalent to "infinity PRECEDING/FOLLOWING" and -** CURRENT ROW by assuming that it is equivalent to "0 PRECEDING/FOLLOWING". -** This is optimized of course - branches that will never be taken and -** conditions that are always true are omitted from the VM code. The only -** exceptional case is: -** -** ROWS BETWEEN FOLLOWING AND UNBOUNDED FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regStart = -** }else{ -** AGGSTEP -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** if( (regStart--)<=0 ){ -** AGGINVERSE -** if( eof ) break -** } -** RETURN_ROW -** } -** while( !eof csrCurrent ){ -** RETURN_ROW -** } -** -** Also requiring special handling are the cases: -** -** ROWS BETWEEN PRECEDING AND PRECEDING -** ROWS BETWEEN FOLLOWING AND FOLLOWING -** -** when (expr1 < expr2). This is detected at runtime, not by this function. -** To handle this case, the pseudo-code programs depicted above are modified -** slightly to be: -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** if( regEnd < regStart ){ -** RETURN_ROW -** delete eph table contents -** continue -** } -** ... -** -** The new "continue" statement in the above jumps to the next iteration -** of the outer loop - the one started by sqlite3WhereBegin(). -** -** The various GROUPS cases are implemented using the same patterns as -** ROWS. The VM code is modified slightly so that: -** -** 1. The else branch in the main loop is only taken if the row just -** added to the ephemeral table is the start of a new group. In -** other words, it becomes: -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else if( new group ){ -** ... -** } -** } -** -** 2. Instead of processing a single row, each RETURN_ROW, AGGSTEP or -** AGGINVERSE step processes the current row of the relevant cursor and -** all subsequent rows belonging to the same group. -** -** RANGE window frames are a little different again. As for GROUPS, the -** main loop runs once per group only. And RETURN_ROW, AGGSTEP and AGGINVERSE -** deal in groups instead of rows. As for ROWS and GROUPS, there are three -** basic cases: -** -** RANGE BETWEEN PRECEDING AND FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** AGGSTEP -** while( (csrCurrent.key + regEnd) < csrEnd.key ){ -** RETURN_ROW -** while( csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** RETURN ROW -** if( csrCurrent is EOF ) break; -** while( csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** } -** } -** -** In the above notation, "csr.key" means the current value of the ORDER BY -** expression (there is only ever 1 for a RANGE that uses an FOLLOWING -** or PRECEDING AND PRECEDING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** while( (csrEnd.key + regEnd) <= csrCurrent.key ){ -** AGGSTEP -** } -** while( (csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** RETURN_ROW -** } -** } -** flush: -** while( (csrEnd.key + regEnd) <= csrCurrent.key ){ -** AGGSTEP -** } -** while( (csrStart.key + regStart) < csrCurrent.key ){ -** AGGINVERSE -** } -** RETURN_ROW -** -** RANGE BETWEEN FOLLOWING AND FOLLOWING -** -** ... loop started by sqlite3WhereBegin() ... -** if( new partition ){ -** Gosub flush -** } -** Insert new row into eph table. -** if( first row of partition ){ -** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) -** regEnd = -** regStart = -** }else{ -** AGGSTEP -** while( (csrCurrent.key + regEnd) < csrEnd.key ){ -** while( (csrCurrent.key + regStart) > csrStart.key ){ -** AGGINVERSE -** } -** RETURN_ROW -** } -** } -** } -** flush: -** AGGSTEP -** while( 1 ){ -** while( (csrCurrent.key + regStart) > csrStart.key ){ -** AGGINVERSE -** if( eof ) break "while( 1 )" loop. -** } -** RETURN_ROW -** } -** while( !eof csrCurrent ){ -** RETURN_ROW -** } -** -** The text above leaves out many details. Refer to the code and comments -** below for a more complete picture. -*/ -SQLITE_PRIVATE void sqlite3WindowCodeStep( - Parse *pParse, /* Parse context */ - Select *p, /* Rewritten SELECT statement */ - WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */ - int regGosub, /* Register for OP_Gosub */ - int addrGosub /* OP_Gosub here to return each row */ -){ - Window *pMWin = p->pWin; - ExprList *pOrderBy = pMWin->pOrderBy; - Vdbe *v = sqlite3GetVdbe(pParse); - int csrWrite; /* Cursor used to write to eph. table */ - int csrInput = p->pSrc->a[0].iCursor; /* Cursor of sub-select */ - int nInput = p->pSrc->a[0].pSTab->nCol; /* Number of cols returned by sub */ - int iInput; /* To iterate through sub cols */ - int addrNe; /* Address of OP_Ne */ - int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */ - int addrInteger = 0; /* Address of OP_Integer */ - int addrEmpty; /* Address of OP_Rewind in flush: */ - int regNew; /* Array of registers holding new input row */ - int regRecord; /* regNew array in record form */ - int regNewPeer = 0; /* Peer values for new row (part of regNew) */ - int regPeer = 0; /* Peer values for current row */ - int regFlushPart = 0; /* Register for "Gosub flush_partition" */ - WindowCodeArg s; /* Context object for sub-routines */ - int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */ - int regStart = 0; /* Value of PRECEDING */ - int regEnd = 0; /* Value of FOLLOWING */ - - assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT - || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED - ); - assert( pMWin->eEnd==TK_FOLLOWING || pMWin->eEnd==TK_CURRENT - || pMWin->eEnd==TK_UNBOUNDED || pMWin->eEnd==TK_PRECEDING - ); - assert( pMWin->eExclude==0 || pMWin->eExclude==TK_CURRENT - || pMWin->eExclude==TK_GROUP || pMWin->eExclude==TK_TIES - || pMWin->eExclude==TK_NO - ); - - lblWhereEnd = sqlite3VdbeMakeLabel(pParse); - - /* Fill in the context object */ - memset(&s, 0, sizeof(WindowCodeArg)); - s.pParse = pParse; - s.pMWin = pMWin; - s.pVdbe = v; - s.regGosub = regGosub; - s.addrGosub = addrGosub; - s.current.csr = pMWin->iEphCsr; - csrWrite = s.current.csr+1; - s.start.csr = s.current.csr+2; - s.end.csr = s.current.csr+3; - - /* Figure out when rows may be deleted from the ephemeral table. There - ** are four options - they may never be deleted (eDelete==0), they may - ** be deleted as soon as they are no longer part of the window frame - ** (eDelete==WINDOW_AGGINVERSE), they may be deleted as after the row - ** has been returned to the caller (WINDOW_RETURN_ROW), or they may - ** be deleted after they enter the frame (WINDOW_AGGSTEP). */ - switch( pMWin->eStart ){ - case TK_FOLLOWING: - if( pMWin->eFrmType!=TK_RANGE - && windowExprGtZero(pParse, pMWin->pStart) - ){ - s.eDelete = WINDOW_RETURN_ROW; - } - break; - case TK_UNBOUNDED: - if( windowCacheFrame(pMWin)==0 ){ - if( pMWin->eEnd==TK_PRECEDING ){ - if( pMWin->eFrmType!=TK_RANGE - && windowExprGtZero(pParse, pMWin->pEnd) - ){ - s.eDelete = WINDOW_AGGSTEP; - } - }else{ - s.eDelete = WINDOW_RETURN_ROW; - } - } - break; - default: - s.eDelete = WINDOW_AGGINVERSE; - break; - } - - /* Allocate registers for the array of values from the sub-query, the - ** same values in record form, and the rowid used to insert said record - ** into the ephemeral table. */ - regNew = pParse->nMem+1; - pParse->nMem += nInput; - regRecord = ++pParse->nMem; - s.regRowid = ++pParse->nMem; - - /* If the window frame contains an " PRECEDING" or " FOLLOWING" - ** clause, allocate registers to store the results of evaluating each - ** . */ - if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){ - regStart = ++pParse->nMem; - } - if( pMWin->eEnd==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING ){ - regEnd = ++pParse->nMem; - } - - /* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of - ** registers to store copies of the ORDER BY expressions (peer values) - ** for the main loop, and for each cursor (start, current and end). */ - if( pMWin->eFrmType!=TK_ROWS ){ - int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); - regNewPeer = regNew + pMWin->nBufferCol; - if( pMWin->pPartition ) regNewPeer += pMWin->pPartition->nExpr; - regPeer = pParse->nMem+1; pParse->nMem += nPeer; - s.start.reg = pParse->nMem+1; pParse->nMem += nPeer; - s.current.reg = pParse->nMem+1; pParse->nMem += nPeer; - s.end.reg = pParse->nMem+1; pParse->nMem += nPeer; - } - - /* Load the column values for the row returned by the sub-select - ** into an array of registers starting at regNew. Assemble them into - ** a record in register regRecord. */ - for(iInput=0; iInputpPartition ){ - int addr; - ExprList *pPart = pMWin->pPartition; - int nPart = pPart->nExpr; - int regNewPart = regNew + pMWin->nBufferCol; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); - - regFlushPart = ++pParse->nMem; - addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart, nPart); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); - VdbeCoverageEqNe(v); - addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart); - VdbeComment((v, "call flush_partition")); - sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); - } - - /* Insert the new row into the ephemeral table */ - sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid); - addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid); - VdbeCoverageNeverNull(v); - - /* This block is run for the first row of each partition */ - s.regArg = windowInitAccum(pParse, pMWin); - - if( regStart ){ - sqlite3ExprCode(pParse, pMWin->pStart, regStart); - windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0)); - } - if( regEnd ){ - sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); - windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0)); - } - - if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){ - int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le); - int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd); - VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound */ - VdbeCoverageNeverNullIf(v, op==OP_Le); /* values previously checked */ - windowAggFinal(&s, 0); - sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr); - windowReturnOneRow(&s); - sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); - sqlite3VdbeJumpHere(v, addrGe); - } - if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && regEnd ){ - assert( pMWin->eEnd==TK_FOLLOWING ); - sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart); - } - - if( pMWin->eStart!=TK_UNBOUNDED ){ - sqlite3VdbeAddOp1(v, OP_Rewind, s.start.csr); - } - sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr); - sqlite3VdbeAddOp1(v, OP_Rewind, s.end.csr); - if( regPeer && pOrderBy ){ - sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, pOrderBy->nExpr-1); - sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.start.reg, pOrderBy->nExpr-1); - sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.current.reg, pOrderBy->nExpr-1); - sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.end.reg, pOrderBy->nExpr-1); - } - - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); - - sqlite3VdbeJumpHere(v, addrNe); - - /* Beginning of the block executed for the second and subsequent rows. */ - if( regPeer ){ - windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer, lblWhereEnd); - } - if( pMWin->eStart==TK_FOLLOWING ){ - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eEnd!=TK_UNBOUNDED ){ - if( pMWin->eFrmType==TK_RANGE ){ - int lbl = sqlite3VdbeMakeLabel(pParse); - int addrNext = sqlite3VdbeCurrentAddr(v); - windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); - sqlite3VdbeResolveLabel(v, lbl); - }else{ - windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 0); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - } - } - }else - if( pMWin->eEnd==TK_PRECEDING ){ - int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE); - windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); - if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - if( !bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - }else{ - int addr = 0; - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eEnd!=TK_UNBOUNDED ){ - if( pMWin->eFrmType==TK_RANGE ){ - int lbl = 0; - addr = sqlite3VdbeCurrentAddr(v); - if( regEnd ){ - lbl = sqlite3VdbeMakeLabel(pParse); - windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); - } - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - if( regEnd ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); - sqlite3VdbeResolveLabel(v, lbl); - } - }else{ - if( regEnd ){ - addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1); - VdbeCoverage(v); - } - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - if( regEnd ) sqlite3VdbeJumpHere(v, addr); - } - } - } - - /* End of the main input loop */ - sqlite3VdbeResolveLabel(v, lblWhereEnd); - sqlite3WhereEnd(pWInfo); - - /* Fall through */ - if( pMWin->pPartition ){ - addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart); - sqlite3VdbeJumpHere(v, addrGosubFlush); - } - - s.regRowid = 0; - addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite); - VdbeCoverage(v); - if( pMWin->eEnd==TK_PRECEDING ){ - int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE); - windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); - if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); - }else if( pMWin->eStart==TK_FOLLOWING ){ - int addrStart; - int addrBreak1; - int addrBreak2; - int addrBreak3; - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eFrmType==TK_RANGE ){ - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); - addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); - }else - if( pMWin->eEnd==TK_UNBOUNDED ){ - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1); - addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1); - }else{ - assert( pMWin->eEnd==TK_FOLLOWING ); - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1); - addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); - sqlite3VdbeJumpHere(v, addrBreak2); - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak3 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); - sqlite3VdbeJumpHere(v, addrBreak1); - sqlite3VdbeJumpHere(v, addrBreak3); - }else{ - int addrBreak; - int addrStart; - windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - addrStart = sqlite3VdbeCurrentAddr(v); - addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); - windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); - sqlite3VdbeJumpHere(v, addrBreak); - } - sqlite3VdbeJumpHere(v, addrEmpty); - - sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); - if( pMWin->pPartition ){ - if( pMWin->regStartRowid ){ - sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid); - } - sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); - } -} - -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/************** End of window.c **********************************************/ /************** Begin file parse.c *******************************************/ -/* This file is automatically generated by Lemon from input grammar -** source file "parse.y". -*/ /* -** 2001-09-15 +** 2000-05-29 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains SQLite's SQL parser. +** Driver template for the LEMON parser generator. ** -** The canonical source code to this file ("parse.y") is a Lemon grammar -** file that specifies the input grammar and actions to take while parsing. -** That input file is processed by Lemon to generate a C-language -** implementation of a parser for the given grammar. You might be reading -** this comment as part of the translated C-code. Edits should be made -** to the original parse.y sources. +** The "lemon" program processes an LALR(1) input grammar file, then uses +** this template to construct a parser. The "lemon" program inserts text +** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the +** interstitial "-" characters) contained in this template is changed into +** the value of the %name directive from the grammar. Otherwise, the content +** of this template is copied straight through into the generate parser +** source file. +** +** The following is the concatenation of all %include directives from the +** input grammar file: */ +/* #include */ +/************ Begin %include sections from the grammar ************************/ /* #include "sqliteInt.h" */ /* ** Disable all error recovery processing in the parser push-down @@ -174236,10 +136516,19 @@ ** Alternative datatype for the argument to the malloc() routine passed ** into sqlite3ParserAlloc(). The default is size_t. */ #define YYMALLOCARGTYPE u64 +/* +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. +*/ +struct LimitVal { + Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ + Expr *pOffset; /* The OFFSET expression. NULL if there is none */ +}; + /* ** An instance of the following structure describes the event of a ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, ** TK_DELETE, or TK_INSTEAD. If the event is of the form ** @@ -174247,151 +136536,136 @@ ** ** Then the "b" IdList records the list "a,b,c". */ struct TrigEvent { int a; IdList * b; }; -struct FrameBound { int eType; Expr *pExpr; }; - -/* -** Generate a syntax error -*/ -static void parserSyntaxError(Parse *pParse, Token *p){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p); -} - /* ** Disable lookaside memory allocation for objects that might be ** shared across database connections. */ static void disableLookaside(Parse *pParse){ - sqlite3 *db = pParse->db; pParse->disableLookaside++; - DisableLookaside; -} - -#if !defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) \ - && defined(SQLITE_UDL_CAPABLE_PARSER) -/* -** Issue an error message if an ORDER BY or LIMIT clause occurs on an -** UPDATE or DELETE statement. -*/ -static void updateDeleteLimitError( - Parse *pParse, - ExprList *pOrderBy, - Expr *pLimit -){ - if( pOrderBy ){ - sqlite3ErrorMsg(pParse, "syntax error near \"ORDER BY\""); - }else{ - sqlite3ErrorMsg(pParse, "syntax error near \"LIMIT\""); - } - sqlite3ExprListDelete(pParse->db, pOrderBy); - sqlite3ExprDelete(pParse->db, pLimit); -} -#endif /* SQLITE_ENABLE_UPDATE_DELETE_LIMIT */ + pParse->db->lookaside.bDisable++; +} /* ** For a compound SELECT statement, make sure p->pPrior->pNext==p for ** all elements in the list. And make sure list length does not exceed ** SQLITE_LIMIT_COMPOUND_SELECT. */ static void parserDoubleLinkSelect(Parse *pParse, Select *p){ - assert( p!=0 ); if( p->pPrior ){ - Select *pNext = 0, *pLoop = p; - int mxSelect, cnt = 1; - while(1){ + Select *pNext = 0, *pLoop; + int mxSelect, cnt = 0; + for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ pLoop->pNext = pNext; pLoop->selFlags |= SF_Compound; - pNext = pLoop; - pLoop = pLoop->pPrior; - if( pLoop==0 ) break; - cnt++; - if( pLoop->pOrderBy || pLoop->pLimit ){ - sqlite3ErrorMsg(pParse,"%s clause should come after %s not before", - pLoop->pOrderBy!=0 ? "ORDER BY" : "LIMIT", - sqlite3SelectOpName(pNext->op)); - break; - } - } - if( (p->selFlags & (SF_MultiValue|SF_Values))==0 - && (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 - && cnt>mxSelect + } + if( (p->selFlags & SF_MultiValue)==0 && + (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 && + cnt>mxSelect ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } } } - /* Attach a With object describing the WITH clause to a Select - ** object describing the query for which the WITH clause is a prefix. - */ - static Select *attachWithToSelect(Parse *pParse, Select *pSelect, With *pWith){ - if( pSelect ){ - pSelect->pWith = pWith; - parserDoubleLinkSelect(pParse, pSelect); - }else{ - sqlite3WithDelete(pParse->db, pWith); - } - return pSelect; - } - - /* Memory allocator for parser stack resizing. This is a thin wrapper around - ** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate - ** testing. - */ - static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){ - return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); - } - - - /* Construct a new Expr object from a single token */ - static Expr *tokenExpr(Parse *pParse, int op, Token t){ + /* This is a utility routine used to set the ExprSpan.zStart and + ** ExprSpan.zEnd values of pOut so that the span covers the complete + ** range of text beginning with pStart and going to the end of pEnd. + */ + static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ + pOut->zStart = pStart->z; + pOut->zEnd = &pEnd->z[pEnd->n]; + } + + /* Construct a new Expr object from a single identifier. Use the + ** new Expr to populate pOut. Set the span of pOut to be the identifier + ** that created the expression. + */ + static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); if( p ){ - /* memset(p, 0, sizeof(Expr)); */ + memset(p, 0, sizeof(Expr)); p->op = (u8)op; - p->affExpr = 0; p->flags = EP_Leaf; - ExprClearVVAProperties(p); - /* p->iAgg = -1; // Not required */ - p->pLeft = p->pRight = 0; - p->pAggInfo = 0; - memset(&p->x, 0, sizeof(p->x)); - memset(&p->y, 0, sizeof(p->y)); - p->op2 = 0; - p->iTable = 0; - p->iColumn = 0; + p->iAgg = -1; p->u.zToken = (char*)&p[1]; memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = 0; - p->w.iOfst = (int)(t.z - pParse->zTail); if( sqlite3Isquote(p->u.zToken[0]) ){ - sqlite3DequoteExpr(p); + if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted; + sqlite3Dequote(p->u.zToken); } #if SQLITE_MAX_EXPR_DEPTH>0 p->nHeight = 1; -#endif - if( IN_RENAME_OBJECT ){ - return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t); - } +#endif } - return p; + pOut->pExpr = p; + pOut->zStart = t.z; + pOut->zEnd = &t.z[t.n]; } + /* This routine constructs a binary expression node out of two ExprSpan + ** objects and uses the result to populate a new ExprSpan object. + */ + static void spanBinaryExpr( + Parse *pParse, /* The parsing context. Errors accumulate here */ + int op, /* The binary operation */ + ExprSpan *pLeft, /* The left operand, and output */ + ExprSpan *pRight /* The right operand */ + ){ + pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr); + pLeft->zEnd = pRight->zEnd; + } + + /* If doNot is true, then add a TK_NOT Expr-node wrapper around the + ** outside of *ppExpr. + */ + static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ + if( doNot ){ + pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0); + } + } + + /* Construct an expression node for a unary postfix operator + */ + static void spanUnaryPostfix( + Parse *pParse, /* Parsing context to record errors */ + int op, /* The operator */ + ExprSpan *pOperand, /* The operand, and output */ + Token *pPostOp /* The operand token for setting the span */ + ){ + pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); + pOperand->zEnd = &pPostOp->z[pPostOp->n]; + } /* A routine to convert a binary TK_IS or TK_ISNOT expression into a ** unary TK_ISNULL or TK_NOTNULL expression. */ static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ sqlite3 *db = pParse->db; - if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){ + if( pA && pY && pY->op==TK_NULL ){ pA->op = (u8)op; sqlite3ExprDelete(db, pA->pRight); pA->pRight = 0; } } + + /* Construct an expression node for a unary prefix operator + */ + static void spanUnaryPrefix( + ExprSpan *pOut, /* Write the new expression node here */ + Parse *pParse, /* Parsing context to record errors */ + int op, /* The operator */ + ExprSpan *pOperand, /* The operand */ + Token *pPreOp /* The operand token for setting the span */ + ){ + pOut->zStart = pPreOp->z; + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); + pOut->zEnd = pOperand->zEnd; + } /* Add a single new term to an ExprList that is used to store a ** list of identifiers. Report an error if the ID list contains ** a COLLATE clause or an ASC or DESC keyword, except ignore the ** error while parsing a legacy schema. @@ -174411,206 +136685,16 @@ pIdToken->n, pIdToken->z); } sqlite3ExprListSetName(pParse, p, pIdToken, 1); return p; } - -#if TK_SPAN>255 -# error too many tokens in the grammar -#endif /**************** End of %include directives **********************************/ -/* These constants specify the various numeric values for terminal symbols. -***************** Begin token definitions *************************************/ -#ifndef TK_SEMI -#define TK_SEMI 1 -#define TK_EXPLAIN 2 -#define TK_QUERY 3 -#define TK_PLAN 4 -#define TK_BEGIN 5 -#define TK_TRANSACTION 6 -#define TK_DEFERRED 7 -#define TK_IMMEDIATE 8 -#define TK_EXCLUSIVE 9 -#define TK_COMMIT 10 -#define TK_END 11 -#define TK_ROLLBACK 12 -#define TK_SAVEPOINT 13 -#define TK_RELEASE 14 -#define TK_TO 15 -#define TK_TABLE 16 -#define TK_CREATE 17 -#define TK_IF 18 -#define TK_NOT 19 -#define TK_EXISTS 20 -#define TK_TEMP 21 -#define TK_LP 22 -#define TK_RP 23 -#define TK_AS 24 -#define TK_COMMA 25 -#define TK_WITHOUT 26 -#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_ISNOT 46 -#define TK_MATCH 47 -#define TK_LIKE_KW 48 -#define TK_BETWEEN 49 -#define TK_IN 50 -#define TK_ISNULL 51 -#define TK_NOTNULL 52 -#define TK_NE 53 -#define TK_EQ 54 -#define TK_GT 55 -#define TK_LE 56 -#define TK_LT 57 -#define TK_GE 58 -#define TK_ESCAPE 59 -#define TK_ID 60 -#define TK_COLUMNKW 61 -#define TK_DO 62 -#define TK_FOR 63 -#define TK_IGNORE 64 -#define TK_INITIALLY 65 -#define TK_INSTEAD 66 -#define TK_NO 67 -#define TK_KEY 68 -#define TK_OF 69 -#define TK_OFFSET 70 -#define TK_PRAGMA 71 -#define TK_RAISE 72 -#define TK_RECURSIVE 73 -#define TK_REPLACE 74 -#define TK_RESTRICT 75 -#define TK_ROW 76 -#define TK_ROWS 77 -#define TK_TRIGGER 78 -#define TK_VACUUM 79 -#define TK_VIEW 80 -#define TK_VIRTUAL 81 -#define TK_WITH 82 -#define TK_NULLS 83 -#define TK_FIRST 84 -#define TK_LAST 85 -#define TK_CURRENT 86 -#define TK_FOLLOWING 87 -#define TK_PARTITION 88 -#define TK_PRECEDING 89 -#define TK_RANGE 90 -#define TK_UNBOUNDED 91 -#define TK_EXCLUDE 92 -#define TK_GROUPS 93 -#define TK_OTHERS 94 -#define TK_TIES 95 -#define TK_GENERATED 96 -#define TK_ALWAYS 97 -#define TK_MATERIALIZED 98 -#define TK_REINDEX 99 -#define TK_RENAME 100 -#define TK_CTIME_KW 101 -#define TK_ANY 102 -#define TK_BITAND 103 -#define TK_BITOR 104 -#define TK_LSHIFT 105 -#define TK_RSHIFT 106 -#define TK_PLUS 107 -#define TK_MINUS 108 -#define TK_STAR 109 -#define TK_SLASH 110 -#define TK_REM 111 -#define TK_CONCAT 112 -#define TK_PTR 113 -#define TK_COLLATE 114 -#define TK_BITNOT 115 -#define TK_ON 116 -#define TK_INDEXED 117 -#define TK_STRING 118 -#define TK_JOIN_KW 119 -#define TK_CONSTRAINT 120 -#define TK_DEFAULT 121 -#define TK_NULL 122 -#define TK_PRIMARY 123 -#define TK_UNIQUE 124 -#define TK_CHECK 125 -#define TK_REFERENCES 126 -#define TK_AUTOINCR 127 -#define TK_INSERT 128 -#define TK_DELETE 129 -#define TK_UPDATE 130 -#define TK_SET 131 -#define TK_DEFERRABLE 132 -#define TK_FOREIGN 133 -#define TK_DROP 134 -#define TK_UNION 135 -#define TK_ALL 136 -#define TK_EXCEPT 137 -#define TK_INTERSECT 138 -#define TK_SELECT 139 -#define TK_VALUES 140 -#define TK_DISTINCT 141 -#define TK_DOT 142 -#define TK_FROM 143 -#define TK_JOIN 144 -#define TK_USING 145 -#define TK_ORDER 146 -#define TK_GROUP 147 -#define TK_HAVING 148 -#define TK_LIMIT 149 -#define TK_WHERE 150 -#define TK_RETURNING 151 -#define TK_INTO 152 -#define TK_NOTHING 153 -#define TK_FLOAT 154 -#define TK_BLOB 155 -#define TK_INTEGER 156 -#define TK_VARIABLE 157 -#define TK_CASE 158 -#define TK_WHEN 159 -#define TK_THEN 160 -#define TK_ELSE 161 -#define TK_INDEX 162 -#define TK_ALTER 163 -#define TK_ADD 164 -#define TK_WINDOW 165 -#define TK_OVER 166 -#define TK_FILTER 167 -#define TK_COLUMN 168 -#define TK_AGG_FUNCTION 169 -#define TK_AGG_COLUMN 170 -#define TK_TRUEFALSE 171 -#define TK_FUNCTION 172 -#define TK_UPLUS 173 -#define TK_UMINUS 174 -#define TK_TRUTH 175 -#define TK_REGISTER 176 -#define TK_VECTOR 177 -#define TK_SELECT_COLUMN 178 -#define TK_IF_NULL_ROW 179 -#define TK_ASTERISK 180 -#define TK_SPAN 181 -#define TK_ERROR 182 -#define TK_QNUMBER 183 -#define TK_SPACE 184 -#define TK_COMMENT 185 -#define TK_ILLEGAL 186 -#endif -/**************** End token definitions ***************************************/ +/* These constants specify the various numeric values for terminal symbols +** in a format understandable to "makeheaders". This section is blank unless +** "lemon" is run with the "-m" command-line option. +***************** Begin makeheaders token definitions *************************/ +/**************** End makeheaders token definitions ***************************/ /* The next sections is a series of control #defines. ** various aspects of the generated parser. ** YYCODETYPE is the data type used to store the integer codes ** that represent terminal and non-terminal symbols. @@ -174631,107 +136715,78 @@ ** value associated with a terminal or non-terminal ** symbols. For example, for an "ID" terminal symbol, ** the minor type might be the name of the identifier. ** Each non-terminal can have a different minor type. ** Terminal symbols all have the same minor type, though. -** This macros defines the minor type for terminal +** This macros defines the minor type for terminal ** symbols. ** YYMINORTYPE is the data type used for all minor types. ** This is typically a union of many types, one of ** which is sqlite3ParserTOKENTYPE. The entry in the union ** for terminal symbols is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument -** sqlite3ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser -** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context -** YYREALLOC Name of the realloc() function to use -** YYFREE Name of the free() function to use -** YYDYNSTACK True if stack space should be extended on heap ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar -** YYNTOKEN Number of terminal symbols ** YY_MAX_SHIFT Maximum value for shift actions ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions +** YY_MIN_REDUCE Maximum value for reduce actions ** YY_ERROR_ACTION The yy_action[] code for syntax error ** YY_ACCEPT_ACTION The yy_action[] code for accept ** YY_NO_ACTION The yy_action[] code for no-op -** YY_MIN_REDUCE Minimum value for reduce actions -** YY_MAX_REDUCE Maximum value for reduce actions -** YY_MIN_DSTRCTR Minimum symbol value that has a destructor -** YY_MAX_DSTRCTR Maximum symbol value that has a destructor */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ -#define YYCODETYPE unsigned short int -#define YYNOCODE 323 +#define YYCODETYPE unsigned char +#define YYNOCODE 252 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 102 +#define YYWILDCARD 69 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - u32 yy9; - struct TrigEvent yy28; - With* yy125; - IdList* yy204; - struct FrameBound yy205; - TriggerStep* yy319; - const char* yy342; - Cte* yy361; - ExprList* yy402; - Upsert* yy403; - OnOrUsing yy421; - u8 yy444; - struct {int value; int mask;} yy481; - Window* yy483; - int yy502; - SrcList* yy563; - Expr* yy590; - Select* yy637; + Expr* yy72; + TriggerStep* yy145; + ExprList* yy148; + SrcList* yy185; + ExprSpan yy190; + int yy194; + Select* yy243; + IdList* yy254; + With* yy285; + struct TrigEvent yy332; + struct LimitVal yy354; + struct {int value; int mask;} yy497; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 #endif -#define sqlite3ParserARG_SDECL -#define sqlite3ParserARG_PDECL -#define sqlite3ParserARG_PARAM -#define sqlite3ParserARG_FETCH -#define sqlite3ParserARG_STORE -#define YYREALLOC parserStackRealloc -#define YYFREE sqlite3_free -#define YYDYNSTACK 1 -#define sqlite3ParserCTX_SDECL Parse *pParse; -#define sqlite3ParserCTX_PDECL ,Parse *pParse -#define sqlite3ParserCTX_PARAM ,pParse -#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; -#define sqlite3ParserCTX_STORE yypParser->pParse=pParse; +#define sqlite3ParserARG_SDECL Parse *pParse; +#define sqlite3ParserARG_PDECL ,Parse *pParse +#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse +#define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYFALLBACK 1 -#define YYNSTATE 583 -#define YYNRULE 409 -#define YYNRULE_WITH_ACTION 344 -#define YYNTOKEN 187 -#define YY_MAX_SHIFT 582 -#define YY_MIN_SHIFTREDUCE 845 -#define YY_MAX_SHIFTREDUCE 1253 -#define YY_ERROR_ACTION 1254 -#define YY_ACCEPT_ACTION 1255 -#define YY_NO_ACTION 1256 -#define YY_MIN_REDUCE 1257 -#define YY_MAX_REDUCE 1665 -#define YY_MIN_DSTRCTR 206 -#define YY_MAX_DSTRCTR 320 +#define YYNSTATE 455 +#define YYNRULE 329 +#define YY_MAX_SHIFT 454 +#define YY_MIN_SHIFTREDUCE 664 +#define YY_MAX_SHIFTREDUCE 992 +#define YY_MIN_REDUCE 993 +#define YY_MAX_REDUCE 1321 +#define YY_ERROR_ACTION 1322 +#define YY_ACCEPT_ACTION 1323 +#define YY_NO_ACTION 1324 /************* End control #defines *******************************************/ -#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** ** Applications can choose to define yytestcase() in the %include section @@ -174741,64 +136796,54 @@ */ #ifndef yytestcase # define yytestcase(X) #endif -/* Macro to determine if stack space has the ability to grow using -** heap memory. -*/ -#if YYSTACKDEPTH<=0 || YYDYNSTACK -# define YYGROWABLESTACK 1 -#else -# define YYGROWABLESTACK 0 -#endif - -/* Guarantee a minimum number of initial stack slots. -*/ -#if YYSTACKDEPTH<=0 -# undef YYSTACKDEPTH -# define YYSTACKDEPTH 2 /* Need a minimum stack size */ -#endif - /* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an -** action integer. +** action integer. ** ** Suppose the action integer is N. Then the action is determined as ** follows ** ** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead ** token onto the stack and goto state N. ** ** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then ** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. +** +** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE +** and YY_MAX_REDUCE ** ** N == YY_ERROR_ACTION A syntax error has occurred. ** ** N == YY_ACCEPT_ACTION The parser accepts its input. ** ** N == YY_NO_ACTION No such action. Denotes unused ** slots in the yy_action[] table. ** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE -** ** The action table is constructed as a single large table named yy_action[]. ** Given state S and lookahead X, the action is computed as either: ** ** (A) N = yy_action[ yy_shift_ofst[S] + X ] ** (B) N = yy_default[S] ** -** The (A) formula is preferred. The B formula is used instead if -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The yy_shift_ofst[S]+X value is out of range, or +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** ** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array. +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. ** ** The following are the tables generated in this section: ** ** yy_action[] A single table containing all actions. ** yy_lookahead[] A table containing the lookahead for each entry in @@ -174808,653 +136853,473 @@ ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2207) +#define YY_ACTTAB_COUNT (1565) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 130, 127, 234, 282, 282, 1328, 576, 1307, 460, 289, - /* 10 */ 289, 576, 1622, 381, 576, 1328, 573, 576, 562, 413, - /* 20 */ 1300, 1542, 573, 481, 562, 524, 460, 459, 558, 82, - /* 30 */ 82, 983, 294, 375, 51, 51, 498, 61, 61, 984, - /* 40 */ 82, 82, 1577, 137, 138, 91, 7, 1228, 1228, 1063, - /* 50 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 413, - /* 60 */ 288, 288, 182, 288, 288, 481, 536, 288, 288, 130, - /* 70 */ 127, 234, 432, 573, 525, 562, 573, 557, 562, 1290, - /* 80 */ 573, 421, 562, 137, 138, 91, 559, 1228, 1228, 1063, - /* 90 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 296, - /* 100 */ 460, 398, 1249, 134, 134, 134, 134, 133, 133, 132, - /* 110 */ 132, 132, 131, 128, 451, 451, 1050, 1050, 1064, 1067, - /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174, - /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 481, 1341, - /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132, - /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 498, 1228, - /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, - /* 170 */ 136, 1204, 862, 1281, 288, 288, 283, 288, 288, 523, - /* 180 */ 523, 1250, 139, 578, 7, 578, 1345, 573, 1169, 562, - /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 573, 547, - /* 200 */ 562, 1169, 245, 1541, 1169, 245, 133, 133, 132, 132, - /* 210 */ 132, 131, 128, 451, 302, 134, 134, 134, 134, 133, - /* 220 */ 133, 132, 132, 132, 131, 128, 451, 1575, 1204, 1205, - /* 230 */ 1204, 7, 470, 550, 455, 413, 550, 455, 130, 127, - /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132, - /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 483, 137, - /* 260 */ 138, 91, 1019, 1228, 1228, 1063, 1066, 1053, 1053, 135, - /* 270 */ 135, 136, 136, 136, 136, 1085, 576, 1204, 132, 132, - /* 280 */ 132, 131, 128, 451, 93, 214, 134, 134, 134, 134, - /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 401, 19, - /* 300 */ 19, 134, 134, 134, 134, 133, 133, 132, 132, 132, - /* 310 */ 131, 128, 451, 1498, 426, 267, 344, 467, 332, 134, - /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128, - /* 330 */ 451, 1281, 576, 6, 1204, 1205, 1204, 257, 576, 413, - /* 340 */ 511, 508, 507, 1279, 94, 1019, 464, 1204, 551, 551, - /* 350 */ 506, 1224, 1571, 44, 38, 51, 51, 411, 576, 413, - /* 360 */ 45, 51, 51, 137, 138, 91, 530, 1228, 1228, 1063, - /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 398, - /* 380 */ 1148, 82, 82, 137, 138, 91, 39, 1228, 1228, 1063, - /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 344, - /* 400 */ 44, 288, 288, 375, 1204, 1205, 1204, 209, 1204, 1224, - /* 410 */ 320, 567, 471, 576, 573, 576, 562, 576, 316, 264, - /* 420 */ 231, 46, 160, 134, 134, 134, 134, 133, 133, 132, - /* 430 */ 132, 132, 131, 128, 451, 303, 82, 82, 82, 82, - /* 440 */ 82, 82, 442, 134, 134, 134, 134, 133, 133, 132, - /* 450 */ 132, 132, 131, 128, 451, 1582, 544, 320, 567, 1250, - /* 460 */ 874, 1582, 380, 382, 413, 1204, 1205, 1204, 360, 182, - /* 470 */ 288, 288, 1576, 557, 1339, 557, 7, 557, 1277, 472, - /* 480 */ 346, 526, 531, 573, 556, 562, 439, 1511, 137, 138, - /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, - /* 500 */ 136, 136, 136, 136, 465, 1511, 1513, 532, 413, 288, - /* 510 */ 288, 423, 512, 288, 288, 411, 288, 288, 874, 130, - /* 520 */ 127, 234, 573, 1107, 562, 1204, 573, 1107, 562, 573, - /* 530 */ 560, 562, 137, 138, 91, 1293, 1228, 1228, 1063, 1066, - /* 540 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 134, 134, - /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, - /* 560 */ 493, 503, 1292, 1204, 257, 288, 288, 511, 508, 507, - /* 570 */ 1204, 1628, 1169, 123, 568, 275, 4, 506, 573, 1511, - /* 580 */ 562, 331, 1204, 1205, 1204, 1169, 548, 548, 1169, 261, - /* 590 */ 571, 7, 134, 134, 134, 134, 133, 133, 132, 132, - /* 600 */ 132, 131, 128, 451, 108, 533, 130, 127, 234, 1204, - /* 610 */ 448, 447, 413, 1451, 452, 983, 886, 96, 1598, 1233, - /* 620 */ 1204, 1205, 1204, 984, 1235, 1450, 565, 1204, 1205, 1204, - /* 630 */ 229, 522, 1234, 534, 1333, 1333, 137, 138, 91, 1449, - /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, - /* 650 */ 136, 136, 373, 1595, 971, 1040, 413, 1236, 418, 1236, - /* 660 */ 879, 121, 121, 948, 373, 1595, 1204, 1205, 1204, 122, - /* 670 */ 1204, 452, 577, 452, 363, 417, 1028, 882, 373, 1595, - /* 680 */ 137, 138, 91, 462, 1228, 1228, 1063, 1066, 1053, 1053, - /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134, - /* 700 */ 133, 133, 132, 132, 132, 131, 128, 451, 1028, 1028, - /* 710 */ 1030, 1031, 35, 570, 570, 570, 197, 423, 1040, 198, - /* 720 */ 1204, 123, 568, 1204, 4, 320, 567, 1204, 1205, 1204, - /* 730 */ 40, 388, 576, 384, 882, 1029, 423, 1188, 571, 1028, - /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 750 */ 128, 451, 529, 1568, 1204, 19, 19, 1204, 575, 492, - /* 760 */ 413, 157, 452, 489, 1187, 1331, 1331, 5, 1204, 949, - /* 770 */ 431, 1028, 1028, 1030, 565, 22, 22, 1204, 1205, 1204, - /* 780 */ 1204, 1205, 1204, 477, 137, 138, 91, 212, 1228, 1228, - /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, - /* 800 */ 1188, 48, 111, 1040, 413, 1204, 213, 970, 1041, 121, - /* 810 */ 121, 1204, 1205, 1204, 1204, 1205, 1204, 122, 221, 452, - /* 820 */ 577, 452, 44, 487, 1028, 1204, 1205, 1204, 137, 138, - /* 830 */ 91, 378, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, - /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133, - /* 850 */ 132, 132, 132, 131, 128, 451, 1028, 1028, 1030, 1031, - /* 860 */ 35, 461, 1204, 1205, 1204, 1569, 1040, 377, 214, 1149, - /* 870 */ 1657, 535, 1657, 437, 902, 320, 567, 1568, 364, 320, - /* 880 */ 567, 412, 329, 1029, 519, 1188, 3, 1028, 134, 134, - /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, - /* 900 */ 1659, 399, 1169, 307, 893, 307, 515, 576, 413, 214, - /* 910 */ 498, 944, 1024, 540, 903, 1169, 943, 392, 1169, 1028, - /* 920 */ 1028, 1030, 406, 298, 1204, 50, 1149, 1658, 413, 1658, - /* 930 */ 145, 145, 137, 138, 91, 293, 1228, 1228, 1063, 1066, - /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 1188, 1147, - /* 950 */ 514, 1568, 137, 138, 91, 1505, 1228, 1228, 1063, 1066, - /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 323, - /* 970 */ 435, 539, 111, 1506, 274, 291, 372, 517, 367, 516, - /* 980 */ 262, 1204, 1205, 1204, 1574, 481, 363, 576, 7, 1569, - /* 990 */ 1568, 377, 134, 134, 134, 134, 133, 133, 132, 132, - /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 576, 232, 576, - /* 1010 */ 19, 19, 134, 134, 134, 134, 133, 133, 132, 132, - /* 1020 */ 132, 131, 128, 451, 1169, 433, 576, 1207, 19, 19, - /* 1030 */ 19, 19, 19, 19, 1627, 576, 911, 1169, 47, 120, - /* 1040 */ 1169, 117, 413, 306, 498, 438, 1125, 206, 336, 19, - /* 1050 */ 19, 1435, 49, 449, 449, 449, 1368, 315, 81, 81, - /* 1060 */ 576, 304, 413, 1570, 207, 377, 137, 138, 91, 115, - /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, - /* 1080 */ 136, 136, 576, 82, 82, 1207, 137, 138, 91, 1340, - /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, - /* 1100 */ 136, 136, 1569, 386, 377, 82, 82, 463, 1126, 1552, - /* 1110 */ 333, 463, 335, 131, 128, 451, 1569, 161, 377, 16, - /* 1120 */ 317, 387, 428, 1127, 448, 447, 134, 134, 134, 134, - /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576, - /* 1140 */ 1105, 10, 445, 267, 576, 1554, 134, 134, 134, 134, - /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 532, 576, - /* 1160 */ 922, 576, 19, 19, 576, 1573, 576, 147, 147, 7, - /* 1170 */ 923, 1236, 498, 1236, 576, 487, 413, 552, 285, 1224, - /* 1180 */ 969, 215, 82, 82, 66, 66, 1435, 67, 67, 21, - /* 1190 */ 21, 1110, 1110, 495, 334, 297, 413, 53, 53, 297, - /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053, - /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 1336, 1311, 446, - /* 1220 */ 137, 138, 91, 227, 1228, 1228, 1063, 1066, 1053, 1053, - /* 1230 */ 135, 135, 136, 136, 136, 136, 574, 1224, 936, 936, - /* 1240 */ 137, 126, 91, 141, 1228, 1228, 1063, 1066, 1053, 1053, - /* 1250 */ 135, 135, 136, 136, 136, 136, 533, 429, 472, 346, - /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 1270 */ 128, 451, 576, 457, 233, 343, 1435, 403, 498, 1550, - /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 1290 */ 128, 451, 576, 324, 576, 82, 82, 487, 576, 969, - /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, - /* 1310 */ 128, 451, 288, 288, 546, 68, 68, 54, 54, 553, - /* 1320 */ 413, 69, 69, 351, 6, 573, 944, 562, 410, 409, - /* 1330 */ 1435, 943, 450, 545, 260, 259, 258, 576, 158, 576, - /* 1340 */ 413, 222, 1180, 479, 969, 138, 91, 430, 1228, 1228, - /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, - /* 1360 */ 70, 70, 71, 71, 576, 1126, 91, 576, 1228, 1228, - /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, - /* 1380 */ 1127, 166, 850, 851, 852, 1282, 419, 72, 72, 108, - /* 1390 */ 73, 73, 1310, 358, 1180, 1128, 576, 305, 576, 123, - /* 1400 */ 568, 494, 4, 488, 134, 134, 134, 134, 133, 133, - /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 55, - /* 1420 */ 55, 56, 56, 576, 134, 134, 134, 134, 133, 133, - /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 1104, 233, 1104, - /* 1440 */ 452, 1602, 582, 2, 1259, 576, 57, 57, 576, 321, - /* 1450 */ 576, 155, 565, 1435, 485, 353, 576, 356, 1341, 59, - /* 1460 */ 59, 576, 44, 969, 569, 419, 576, 238, 60, 60, - /* 1470 */ 261, 74, 74, 75, 75, 287, 231, 576, 1366, 76, - /* 1480 */ 76, 1040, 420, 184, 20, 20, 576, 121, 121, 77, - /* 1490 */ 77, 97, 218, 288, 288, 122, 125, 452, 577, 452, - /* 1500 */ 143, 143, 1028, 576, 520, 576, 573, 576, 562, 144, - /* 1510 */ 144, 474, 227, 1244, 478, 123, 568, 576, 4, 320, - /* 1520 */ 567, 245, 411, 576, 443, 411, 78, 78, 62, 62, - /* 1530 */ 79, 79, 571, 319, 1028, 1028, 1030, 1031, 35, 418, - /* 1540 */ 63, 63, 576, 290, 411, 9, 80, 80, 1144, 576, - /* 1550 */ 400, 576, 486, 455, 576, 1223, 452, 576, 325, 342, - /* 1560 */ 576, 111, 576, 1188, 242, 64, 64, 473, 565, 576, - /* 1570 */ 23, 576, 170, 170, 171, 171, 576, 87, 87, 328, - /* 1580 */ 65, 65, 542, 83, 83, 146, 146, 541, 123, 568, - /* 1590 */ 341, 4, 84, 84, 168, 168, 576, 1040, 576, 148, - /* 1600 */ 148, 576, 1380, 121, 121, 571, 1021, 576, 266, 576, - /* 1610 */ 424, 122, 576, 452, 577, 452, 576, 553, 1028, 142, - /* 1620 */ 142, 169, 169, 576, 162, 162, 528, 889, 371, 452, - /* 1630 */ 152, 152, 151, 151, 1379, 149, 149, 109, 370, 150, - /* 1640 */ 150, 565, 576, 480, 576, 266, 86, 86, 576, 1092, - /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 482, 576, 266, 466, - /* 1660 */ 543, 123, 568, 1616, 4, 88, 88, 85, 85, 475, - /* 1670 */ 1040, 52, 52, 222, 901, 900, 121, 121, 571, 1188, - /* 1680 */ 58, 58, 244, 1032, 122, 889, 452, 577, 452, 908, - /* 1690 */ 909, 1028, 300, 347, 504, 111, 263, 361, 165, 111, - /* 1700 */ 111, 1088, 452, 263, 974, 1153, 266, 1092, 986, 987, - /* 1710 */ 942, 939, 125, 125, 565, 1103, 872, 1103, 159, 941, - /* 1720 */ 1309, 125, 1557, 1028, 1028, 1030, 1031, 35, 542, 337, - /* 1730 */ 1530, 205, 1529, 541, 499, 1589, 490, 348, 1376, 352, - /* 1740 */ 355, 1032, 357, 1040, 359, 1324, 1308, 366, 563, 121, - /* 1750 */ 121, 376, 1188, 1389, 1434, 1362, 280, 122, 1374, 452, - /* 1760 */ 577, 452, 167, 1439, 1028, 1289, 1280, 1268, 1267, 1269, - /* 1770 */ 1609, 1359, 312, 313, 314, 397, 12, 237, 224, 1421, - /* 1780 */ 295, 1416, 1409, 1426, 339, 484, 340, 509, 1371, 1612, - /* 1790 */ 1372, 1425, 1244, 404, 301, 228, 1028, 1028, 1030, 1031, - /* 1800 */ 35, 1601, 1192, 454, 345, 1307, 292, 369, 1502, 1501, - /* 1810 */ 270, 396, 396, 395, 277, 393, 1370, 1369, 859, 1549, - /* 1820 */ 186, 123, 568, 235, 4, 1188, 391, 210, 211, 223, - /* 1830 */ 1547, 239, 1241, 327, 422, 96, 220, 195, 571, 180, - /* 1840 */ 188, 326, 468, 469, 190, 191, 502, 192, 193, 566, - /* 1850 */ 247, 109, 1430, 491, 199, 251, 102, 281, 402, 476, - /* 1860 */ 405, 1496, 452, 497, 253, 1422, 13, 1428, 14, 1427, - /* 1870 */ 203, 1507, 241, 500, 565, 354, 407, 92, 95, 1270, - /* 1880 */ 175, 254, 518, 43, 1327, 255, 1326, 1325, 436, 1518, - /* 1890 */ 350, 1318, 104, 229, 893, 1626, 440, 441, 1625, 408, - /* 1900 */ 240, 1296, 268, 1040, 310, 269, 1297, 527, 444, 121, - /* 1910 */ 121, 368, 1295, 1594, 1624, 311, 1394, 122, 1317, 452, - /* 1920 */ 577, 452, 374, 1580, 1028, 1393, 140, 553, 11, 90, - /* 1930 */ 568, 385, 4, 116, 318, 414, 1579, 110, 1483, 537, - /* 1940 */ 320, 567, 1350, 555, 42, 579, 571, 1349, 1198, 383, - /* 1950 */ 276, 390, 216, 389, 278, 279, 1028, 1028, 1030, 1031, - /* 1960 */ 35, 172, 580, 1265, 458, 1260, 415, 416, 185, 156, - /* 1970 */ 452, 1534, 1535, 173, 1533, 1532, 89, 308, 225, 226, - /* 1980 */ 846, 174, 565, 453, 217, 1188, 322, 236, 1102, 154, - /* 1990 */ 1100, 330, 187, 176, 1223, 243, 189, 925, 338, 246, - /* 2000 */ 1116, 194, 177, 425, 178, 427, 98, 196, 99, 100, - /* 2010 */ 101, 1040, 179, 1119, 1115, 248, 249, 121, 121, 163, - /* 2020 */ 24, 250, 349, 1238, 496, 122, 1108, 452, 577, 452, - /* 2030 */ 1192, 454, 1028, 266, 292, 200, 252, 201, 861, 396, - /* 2040 */ 396, 395, 277, 393, 15, 501, 859, 370, 292, 256, - /* 2050 */ 202, 554, 505, 396, 396, 395, 277, 393, 103, 239, - /* 2060 */ 859, 327, 25, 26, 1028, 1028, 1030, 1031, 35, 326, - /* 2070 */ 362, 510, 891, 239, 365, 327, 513, 904, 105, 309, - /* 2080 */ 164, 181, 27, 326, 106, 521, 107, 1185, 1069, 1155, - /* 2090 */ 17, 1154, 230, 1188, 284, 286, 265, 204, 125, 1171, - /* 2100 */ 241, 28, 978, 972, 29, 41, 1175, 1179, 175, 1173, - /* 2110 */ 30, 43, 31, 8, 241, 1178, 32, 1160, 208, 549, - /* 2120 */ 33, 111, 175, 1083, 1070, 43, 1068, 1072, 240, 113, - /* 2130 */ 114, 34, 561, 118, 1124, 271, 1073, 36, 18, 572, - /* 2140 */ 1033, 873, 240, 124, 37, 935, 272, 273, 1617, 183, - /* 2150 */ 153, 394, 1194, 1193, 1256, 1256, 1256, 1256, 1256, 1256, - /* 2160 */ 1256, 1256, 1256, 414, 1256, 1256, 1256, 1256, 320, 567, - /* 2170 */ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 414, 1256, 1256, - /* 2180 */ 1256, 1256, 320, 567, 1256, 1256, 1256, 1256, 1256, 1256, - /* 2190 */ 1256, 1256, 458, 1256, 1256, 1256, 1256, 1256, 1256, 1256, - /* 2200 */ 1256, 1256, 1256, 1256, 1256, 1256, 458, + /* 0 */ 324, 410, 342, 747, 747, 203, 939, 353, 969, 98, + /* 10 */ 98, 98, 98, 91, 96, 96, 96, 96, 95, 95, + /* 20 */ 94, 94, 94, 93, 350, 1323, 155, 155, 2, 808, + /* 30 */ 971, 971, 98, 98, 98, 98, 20, 96, 96, 96, + /* 40 */ 96, 95, 95, 94, 94, 94, 93, 350, 92, 89, + /* 50 */ 178, 99, 100, 90, 847, 850, 839, 839, 97, 97, + /* 60 */ 98, 98, 98, 98, 350, 96, 96, 96, 96, 95, + /* 70 */ 95, 94, 94, 94, 93, 350, 324, 339, 969, 262, + /* 80 */ 364, 251, 212, 169, 287, 404, 282, 403, 199, 786, + /* 90 */ 242, 411, 21, 950, 378, 280, 93, 350, 787, 95, + /* 100 */ 95, 94, 94, 94, 93, 350, 971, 971, 96, 96, + /* 110 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 808, + /* 120 */ 328, 242, 411, 1235, 826, 1235, 132, 99, 100, 90, + /* 130 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, + /* 140 */ 449, 96, 96, 96, 96, 95, 95, 94, 94, 94, + /* 150 */ 93, 350, 324, 819, 348, 347, 120, 818, 120, 75, + /* 160 */ 52, 52, 950, 951, 952, 1084, 977, 146, 360, 262, + /* 170 */ 369, 261, 950, 975, 954, 976, 92, 89, 178, 370, + /* 180 */ 230, 370, 971, 971, 1141, 360, 359, 101, 818, 818, + /* 190 */ 820, 383, 24, 1286, 380, 427, 412, 368, 978, 379, + /* 200 */ 978, 1032, 324, 99, 100, 90, 847, 850, 839, 839, + /* 210 */ 97, 97, 98, 98, 98, 98, 372, 96, 96, 96, + /* 220 */ 96, 95, 95, 94, 94, 94, 93, 350, 950, 132, + /* 230 */ 890, 449, 971, 971, 890, 60, 94, 94, 94, 93, + /* 240 */ 350, 950, 951, 952, 954, 103, 360, 950, 384, 333, + /* 250 */ 697, 52, 52, 99, 100, 90, 847, 850, 839, 839, + /* 260 */ 97, 97, 98, 98, 98, 98, 1022, 96, 96, 96, + /* 270 */ 96, 95, 95, 94, 94, 94, 93, 350, 324, 454, + /* 280 */ 995, 449, 227, 61, 157, 243, 343, 114, 1025, 1211, + /* 290 */ 147, 826, 950, 372, 1071, 950, 319, 950, 951, 952, + /* 300 */ 194, 10, 10, 401, 398, 397, 1211, 1213, 971, 971, + /* 310 */ 757, 171, 170, 157, 396, 336, 950, 951, 952, 697, + /* 320 */ 819, 310, 153, 950, 818, 320, 82, 23, 80, 99, + /* 330 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98, + /* 340 */ 98, 98, 888, 96, 96, 96, 96, 95, 95, 94, + /* 350 */ 94, 94, 93, 350, 324, 818, 818, 820, 277, 231, + /* 360 */ 300, 950, 951, 952, 950, 951, 952, 1211, 194, 25, + /* 370 */ 449, 401, 398, 397, 950, 354, 300, 449, 950, 74, + /* 380 */ 449, 1, 396, 132, 971, 971, 950, 224, 224, 808, + /* 390 */ 10, 10, 950, 951, 952, 1290, 132, 52, 52, 414, + /* 400 */ 52, 52, 1063, 1063, 338, 99, 100, 90, 847, 850, + /* 410 */ 839, 839, 97, 97, 98, 98, 98, 98, 1114, 96, + /* 420 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 350, + /* 430 */ 324, 1113, 427, 417, 701, 427, 426, 1260, 1260, 262, + /* 440 */ 369, 261, 950, 950, 951, 952, 752, 950, 951, 952, + /* 450 */ 449, 751, 449, 1058, 1037, 950, 951, 952, 442, 706, + /* 460 */ 971, 971, 1058, 393, 92, 89, 178, 446, 446, 446, + /* 470 */ 51, 51, 52, 52, 438, 773, 1024, 92, 89, 178, + /* 480 */ 172, 99, 100, 90, 847, 850, 839, 839, 97, 97, + /* 490 */ 98, 98, 98, 98, 198, 96, 96, 96, 96, 95, + /* 500 */ 95, 94, 94, 94, 93, 350, 324, 427, 407, 909, + /* 510 */ 694, 950, 951, 952, 92, 89, 178, 224, 224, 157, + /* 520 */ 241, 221, 418, 299, 771, 910, 415, 374, 449, 414, + /* 530 */ 58, 323, 1061, 1061, 1242, 378, 971, 971, 378, 772, + /* 540 */ 448, 911, 362, 735, 296, 681, 9, 9, 52, 52, + /* 550 */ 234, 329, 234, 256, 416, 736, 280, 99, 100, 90, + /* 560 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, + /* 570 */ 449, 96, 96, 96, 96, 95, 95, 94, 94, 94, + /* 580 */ 93, 350, 324, 422, 72, 449, 827, 120, 367, 449, + /* 590 */ 10, 10, 5, 301, 203, 449, 177, 969, 253, 419, + /* 600 */ 255, 771, 200, 175, 233, 10, 10, 836, 836, 36, + /* 610 */ 36, 1289, 971, 971, 724, 37, 37, 348, 347, 424, + /* 620 */ 203, 260, 771, 969, 232, 930, 1316, 870, 337, 1316, + /* 630 */ 421, 848, 851, 99, 100, 90, 847, 850, 839, 839, + /* 640 */ 97, 97, 98, 98, 98, 98, 268, 96, 96, 96, + /* 650 */ 96, 95, 95, 94, 94, 94, 93, 350, 324, 840, + /* 660 */ 449, 978, 813, 978, 1200, 449, 909, 969, 715, 349, + /* 670 */ 349, 349, 928, 177, 449, 930, 1317, 254, 198, 1317, + /* 680 */ 12, 12, 910, 402, 449, 27, 27, 250, 971, 971, + /* 690 */ 118, 716, 162, 969, 38, 38, 268, 176, 911, 771, + /* 700 */ 432, 1265, 939, 353, 39, 39, 316, 991, 324, 99, + /* 710 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98, + /* 720 */ 98, 98, 928, 96, 96, 96, 96, 95, 95, 94, + /* 730 */ 94, 94, 93, 350, 449, 329, 449, 357, 971, 971, + /* 740 */ 1041, 316, 929, 340, 893, 893, 386, 669, 670, 671, + /* 750 */ 275, 1318, 317, 992, 40, 40, 41, 41, 268, 99, + /* 760 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98, + /* 770 */ 98, 98, 449, 96, 96, 96, 96, 95, 95, 94, + /* 780 */ 94, 94, 93, 350, 324, 449, 355, 449, 992, 449, + /* 790 */ 1016, 330, 42, 42, 786, 270, 449, 273, 449, 228, + /* 800 */ 449, 298, 449, 787, 449, 28, 28, 29, 29, 31, + /* 810 */ 31, 449, 1141, 449, 971, 971, 43, 43, 44, 44, + /* 820 */ 45, 45, 11, 11, 46, 46, 887, 78, 887, 268, + /* 830 */ 268, 105, 105, 47, 47, 99, 100, 90, 847, 850, + /* 840 */ 839, 839, 97, 97, 98, 98, 98, 98, 449, 96, + /* 850 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 350, + /* 860 */ 324, 449, 117, 449, 1073, 158, 449, 691, 48, 48, + /* 870 */ 229, 1241, 449, 1250, 449, 414, 449, 334, 449, 245, + /* 880 */ 449, 33, 33, 49, 49, 449, 50, 50, 246, 1141, + /* 890 */ 971, 971, 34, 34, 122, 122, 123, 123, 124, 124, + /* 900 */ 56, 56, 268, 81, 249, 35, 35, 197, 196, 195, + /* 910 */ 324, 99, 100, 90, 847, 850, 839, 839, 97, 97, + /* 920 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95, + /* 930 */ 95, 94, 94, 94, 93, 350, 449, 691, 449, 1141, + /* 940 */ 971, 971, 968, 1207, 106, 106, 268, 1209, 268, 1266, + /* 950 */ 2, 886, 268, 886, 335, 1040, 53, 53, 107, 107, + /* 960 */ 324, 99, 100, 90, 847, 850, 839, 839, 97, 97, + /* 970 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95, + /* 980 */ 95, 94, 94, 94, 93, 350, 449, 1070, 449, 1066, + /* 990 */ 971, 971, 1039, 267, 108, 108, 445, 330, 331, 133, + /* 1000 */ 223, 175, 301, 225, 385, 1255, 104, 104, 121, 121, + /* 1010 */ 324, 99, 88, 90, 847, 850, 839, 839, 97, 97, + /* 1020 */ 98, 98, 98, 98, 1141, 96, 96, 96, 96, 95, + /* 1030 */ 95, 94, 94, 94, 93, 350, 449, 346, 449, 167, + /* 1040 */ 971, 971, 925, 810, 371, 318, 202, 202, 373, 263, + /* 1050 */ 394, 202, 74, 208, 721, 722, 119, 119, 112, 112, + /* 1060 */ 324, 406, 100, 90, 847, 850, 839, 839, 97, 97, + /* 1070 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95, + /* 1080 */ 95, 94, 94, 94, 93, 350, 449, 752, 449, 344, + /* 1090 */ 971, 971, 751, 278, 111, 111, 74, 714, 713, 704, + /* 1100 */ 286, 877, 749, 1279, 257, 77, 109, 109, 110, 110, + /* 1110 */ 1230, 285, 1134, 90, 847, 850, 839, 839, 97, 97, + /* 1120 */ 98, 98, 98, 98, 1233, 96, 96, 96, 96, 95, + /* 1130 */ 95, 94, 94, 94, 93, 350, 86, 444, 449, 3, + /* 1140 */ 1193, 449, 1069, 132, 351, 120, 1013, 86, 444, 780, + /* 1150 */ 3, 1091, 202, 376, 447, 351, 1229, 120, 55, 55, + /* 1160 */ 449, 57, 57, 822, 873, 447, 449, 208, 449, 704, + /* 1170 */ 449, 877, 237, 433, 435, 120, 439, 428, 361, 120, + /* 1180 */ 54, 54, 132, 449, 433, 826, 52, 52, 26, 26, + /* 1190 */ 30, 30, 381, 132, 408, 443, 826, 689, 264, 389, + /* 1200 */ 116, 269, 272, 32, 32, 83, 84, 120, 274, 120, + /* 1210 */ 120, 276, 85, 351, 451, 450, 83, 84, 818, 1054, + /* 1220 */ 1038, 427, 429, 85, 351, 451, 450, 120, 120, 818, + /* 1230 */ 377, 218, 281, 822, 1107, 1140, 86, 444, 409, 3, + /* 1240 */ 1087, 1098, 430, 431, 351, 302, 303, 1146, 1021, 818, + /* 1250 */ 818, 820, 821, 19, 447, 1015, 1004, 1003, 1005, 1273, + /* 1260 */ 818, 818, 820, 821, 19, 289, 159, 291, 293, 7, + /* 1270 */ 315, 173, 259, 433, 1129, 363, 252, 1232, 375, 1037, + /* 1280 */ 295, 434, 168, 986, 399, 826, 284, 1204, 1203, 205, + /* 1290 */ 1276, 308, 1249, 86, 444, 983, 3, 1247, 332, 144, + /* 1300 */ 130, 351, 72, 135, 59, 83, 84, 756, 137, 365, + /* 1310 */ 1126, 447, 85, 351, 451, 450, 139, 226, 818, 140, + /* 1320 */ 156, 62, 314, 314, 313, 215, 311, 366, 392, 678, + /* 1330 */ 433, 185, 141, 1234, 142, 160, 148, 1136, 1198, 382, + /* 1340 */ 189, 67, 826, 180, 388, 248, 1218, 1099, 219, 818, + /* 1350 */ 818, 820, 821, 19, 247, 190, 266, 154, 390, 271, + /* 1360 */ 191, 192, 83, 84, 1006, 405, 1057, 182, 321, 85, + /* 1370 */ 351, 451, 450, 1056, 183, 818, 341, 132, 181, 706, + /* 1380 */ 1055, 420, 76, 444, 1029, 3, 322, 1028, 283, 1048, + /* 1390 */ 351, 1095, 1027, 1288, 1047, 71, 204, 6, 288, 290, + /* 1400 */ 447, 1096, 1094, 1093, 79, 292, 818, 818, 820, 821, + /* 1410 */ 19, 294, 297, 437, 345, 441, 102, 1184, 1077, 433, + /* 1420 */ 238, 425, 73, 305, 239, 304, 325, 240, 423, 306, + /* 1430 */ 307, 826, 213, 1012, 22, 945, 452, 214, 216, 217, + /* 1440 */ 453, 1001, 115, 996, 125, 126, 235, 127, 665, 352, + /* 1450 */ 326, 83, 84, 358, 166, 244, 179, 327, 85, 351, + /* 1460 */ 451, 450, 134, 356, 818, 113, 885, 806, 883, 136, + /* 1470 */ 128, 138, 738, 258, 184, 899, 143, 145, 63, 64, + /* 1480 */ 65, 66, 129, 902, 187, 186, 898, 8, 13, 188, + /* 1490 */ 265, 891, 149, 202, 980, 818, 818, 820, 821, 19, + /* 1500 */ 150, 387, 161, 680, 285, 391, 151, 395, 400, 193, + /* 1510 */ 68, 14, 236, 279, 15, 69, 717, 825, 131, 824, + /* 1520 */ 853, 70, 746, 16, 413, 750, 4, 174, 220, 222, + /* 1530 */ 152, 779, 857, 774, 201, 77, 74, 868, 17, 854, + /* 1540 */ 852, 908, 18, 907, 207, 206, 934, 163, 436, 210, + /* 1550 */ 935, 164, 209, 165, 440, 856, 823, 690, 87, 211, + /* 1560 */ 309, 312, 1281, 940, 1280, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 241, - /* 10 */ 242, 195, 217, 221, 195, 235, 254, 195, 256, 19, - /* 20 */ 225, 298, 254, 195, 256, 206, 213, 214, 206, 218, - /* 30 */ 219, 31, 206, 195, 218, 219, 195, 218, 219, 39, - /* 40 */ 218, 219, 313, 43, 44, 45, 317, 47, 48, 49, - /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19, - /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 277, - /* 70 */ 278, 279, 234, 254, 255, 256, 254, 255, 256, 218, - /* 80 */ 254, 240, 256, 43, 44, 45, 264, 47, 48, 49, - /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 271, - /* 100 */ 287, 22, 23, 103, 104, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 113, 114, 114, 47, 48, 49, 50, - /* 120 */ 187, 188, 189, 190, 191, 192, 190, 87, 192, 89, - /* 130 */ 197, 19, 199, 197, 318, 199, 320, 25, 195, 206, - /* 140 */ 299, 271, 206, 103, 104, 105, 106, 107, 108, 109, - /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 195, 47, - /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 170 */ 58, 60, 21, 195, 241, 242, 215, 241, 242, 312, - /* 180 */ 313, 102, 70, 205, 317, 207, 242, 254, 77, 256, - /* 190 */ 254, 122, 256, 55, 56, 57, 58, 59, 254, 88, - /* 200 */ 256, 90, 269, 240, 93, 269, 107, 108, 109, 110, - /* 210 */ 111, 112, 113, 114, 271, 103, 104, 105, 106, 107, - /* 220 */ 108, 109, 110, 111, 112, 113, 114, 313, 117, 118, - /* 230 */ 119, 317, 81, 195, 301, 19, 195, 301, 277, 278, - /* 240 */ 279, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 195, 43, - /* 260 */ 44, 45, 74, 47, 48, 49, 50, 51, 52, 53, - /* 270 */ 54, 55, 56, 57, 58, 124, 195, 60, 109, 110, - /* 280 */ 111, 112, 113, 114, 68, 195, 103, 104, 105, 106, - /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 208, 218, - /* 300 */ 219, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 310 */ 112, 113, 114, 162, 233, 24, 128, 129, 130, 103, - /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 330 */ 114, 195, 195, 215, 117, 118, 119, 120, 195, 19, - /* 340 */ 123, 124, 125, 207, 24, 74, 246, 60, 310, 311, - /* 350 */ 133, 60, 311, 82, 22, 218, 219, 257, 195, 19, - /* 360 */ 73, 218, 219, 43, 44, 45, 206, 47, 48, 49, - /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 22, - /* 380 */ 23, 218, 219, 43, 44, 45, 54, 47, 48, 49, - /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 128, - /* 400 */ 82, 241, 242, 195, 117, 118, 119, 289, 60, 118, - /* 410 */ 139, 140, 294, 195, 254, 195, 256, 195, 255, 259, - /* 420 */ 260, 73, 22, 103, 104, 105, 106, 107, 108, 109, - /* 430 */ 110, 111, 112, 113, 114, 206, 218, 219, 218, 219, - /* 440 */ 218, 219, 234, 103, 104, 105, 106, 107, 108, 109, - /* 450 */ 110, 111, 112, 113, 114, 318, 319, 139, 140, 102, - /* 460 */ 60, 318, 319, 221, 19, 117, 118, 119, 23, 195, - /* 470 */ 241, 242, 313, 255, 206, 255, 317, 255, 206, 129, - /* 480 */ 130, 206, 264, 254, 264, 256, 264, 195, 43, 44, - /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54, - /* 500 */ 55, 56, 57, 58, 246, 213, 214, 19, 19, 241, - /* 510 */ 242, 195, 23, 241, 242, 257, 241, 242, 118, 277, - /* 520 */ 278, 279, 254, 29, 256, 60, 254, 33, 256, 254, - /* 530 */ 206, 256, 43, 44, 45, 218, 47, 48, 49, 50, - /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104, - /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 560 */ 66, 19, 218, 60, 120, 241, 242, 123, 124, 125, - /* 570 */ 60, 232, 77, 19, 20, 26, 22, 133, 254, 287, - /* 580 */ 256, 265, 117, 118, 119, 90, 312, 313, 93, 47, - /* 590 */ 36, 317, 103, 104, 105, 106, 107, 108, 109, 110, - /* 600 */ 111, 112, 113, 114, 116, 117, 277, 278, 279, 60, - /* 610 */ 107, 108, 19, 276, 60, 31, 23, 152, 195, 116, - /* 620 */ 117, 118, 119, 39, 121, 276, 72, 117, 118, 119, - /* 630 */ 166, 167, 129, 145, 237, 238, 43, 44, 45, 276, - /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 650 */ 57, 58, 315, 316, 144, 101, 19, 154, 116, 156, - /* 660 */ 23, 107, 108, 109, 315, 316, 117, 118, 119, 115, - /* 670 */ 60, 117, 118, 119, 132, 200, 122, 60, 315, 316, - /* 680 */ 43, 44, 45, 272, 47, 48, 49, 50, 51, 52, - /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106, - /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155, - /* 710 */ 156, 157, 158, 212, 213, 214, 22, 195, 101, 22, - /* 720 */ 60, 19, 20, 60, 22, 139, 140, 117, 118, 119, - /* 730 */ 22, 251, 195, 253, 117, 118, 195, 183, 36, 122, - /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 750 */ 113, 114, 195, 195, 60, 218, 219, 60, 195, 284, - /* 760 */ 19, 25, 60, 288, 23, 237, 238, 22, 60, 109, - /* 770 */ 233, 154, 155, 156, 72, 218, 219, 117, 118, 119, - /* 780 */ 117, 118, 119, 116, 43, 44, 45, 265, 47, 48, - /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 800 */ 183, 243, 25, 101, 19, 60, 265, 144, 23, 107, - /* 810 */ 108, 117, 118, 119, 117, 118, 119, 115, 151, 117, - /* 820 */ 118, 119, 82, 195, 122, 117, 118, 119, 43, 44, - /* 830 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, - /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108, - /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157, - /* 860 */ 158, 121, 117, 118, 119, 307, 101, 309, 195, 22, - /* 870 */ 23, 195, 25, 19, 35, 139, 140, 195, 24, 139, - /* 880 */ 140, 208, 195, 118, 109, 183, 22, 122, 103, 104, - /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 900 */ 304, 305, 77, 230, 127, 232, 67, 195, 19, 195, - /* 910 */ 195, 136, 23, 88, 75, 90, 141, 203, 93, 154, - /* 920 */ 155, 156, 208, 295, 60, 243, 22, 23, 19, 25, - /* 930 */ 218, 219, 43, 44, 45, 100, 47, 48, 49, 50, - /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 183, 102, - /* 950 */ 96, 195, 43, 44, 45, 240, 47, 48, 49, 50, - /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 134, - /* 970 */ 131, 146, 25, 286, 120, 121, 122, 123, 124, 125, - /* 980 */ 126, 117, 118, 119, 313, 195, 132, 195, 317, 307, - /* 990 */ 195, 309, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1000 */ 111, 112, 113, 114, 195, 195, 102, 195, 195, 195, - /* 1010 */ 218, 219, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1020 */ 111, 112, 113, 114, 77, 233, 195, 60, 218, 219, - /* 1030 */ 218, 219, 218, 219, 23, 195, 25, 90, 243, 159, - /* 1040 */ 93, 161, 19, 233, 195, 233, 23, 233, 16, 218, - /* 1050 */ 219, 195, 243, 212, 213, 214, 262, 263, 218, 219, - /* 1060 */ 195, 271, 19, 307, 233, 309, 43, 44, 45, 160, - /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1080 */ 57, 58, 195, 218, 219, 118, 43, 44, 45, 240, - /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1100 */ 57, 58, 307, 195, 309, 218, 219, 263, 12, 195, - /* 1110 */ 78, 267, 80, 112, 113, 114, 307, 22, 309, 24, - /* 1120 */ 255, 281, 266, 27, 107, 108, 103, 104, 105, 106, - /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 195, - /* 1140 */ 11, 22, 255, 24, 195, 195, 103, 104, 105, 106, - /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 19, 195, - /* 1160 */ 64, 195, 218, 219, 195, 313, 195, 218, 219, 317, - /* 1170 */ 74, 154, 195, 156, 195, 195, 19, 233, 23, 60, - /* 1180 */ 25, 24, 218, 219, 218, 219, 195, 218, 219, 218, - /* 1190 */ 219, 128, 129, 130, 162, 263, 19, 218, 219, 267, - /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52, - /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 240, 228, 255, - /* 1220 */ 43, 44, 45, 25, 47, 48, 49, 50, 51, 52, - /* 1230 */ 53, 54, 55, 56, 57, 58, 135, 118, 137, 138, - /* 1240 */ 43, 44, 45, 22, 47, 48, 49, 50, 51, 52, - /* 1250 */ 53, 54, 55, 56, 57, 58, 117, 266, 129, 130, - /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1270 */ 113, 114, 195, 195, 119, 295, 195, 206, 195, 195, - /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1290 */ 113, 114, 195, 195, 195, 218, 219, 195, 195, 144, - /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1310 */ 113, 114, 241, 242, 67, 218, 219, 218, 219, 146, - /* 1320 */ 19, 218, 219, 240, 215, 254, 136, 256, 107, 108, - /* 1330 */ 195, 141, 255, 86, 128, 129, 130, 195, 165, 195, - /* 1340 */ 19, 143, 95, 272, 25, 44, 45, 266, 47, 48, - /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1360 */ 218, 219, 218, 219, 195, 12, 45, 195, 47, 48, - /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1380 */ 27, 23, 7, 8, 9, 210, 211, 218, 219, 116, - /* 1390 */ 218, 219, 228, 16, 147, 42, 195, 295, 195, 19, - /* 1400 */ 20, 266, 22, 294, 103, 104, 105, 106, 107, 108, - /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 218, - /* 1420 */ 219, 218, 219, 195, 103, 104, 105, 106, 107, 108, - /* 1430 */ 109, 110, 111, 112, 113, 114, 195, 154, 119, 156, - /* 1440 */ 60, 189, 190, 191, 192, 195, 218, 219, 195, 197, - /* 1450 */ 195, 199, 72, 195, 19, 78, 195, 80, 206, 218, - /* 1460 */ 219, 195, 82, 144, 210, 211, 195, 15, 218, 219, - /* 1470 */ 47, 218, 219, 218, 219, 259, 260, 195, 261, 218, - /* 1480 */ 219, 101, 302, 303, 218, 219, 195, 107, 108, 218, - /* 1490 */ 219, 150, 151, 241, 242, 115, 25, 117, 118, 119, - /* 1500 */ 218, 219, 122, 195, 146, 195, 254, 195, 256, 218, - /* 1510 */ 219, 246, 25, 61, 246, 19, 20, 195, 22, 139, - /* 1520 */ 140, 269, 257, 195, 266, 257, 218, 219, 218, 219, - /* 1530 */ 218, 219, 36, 246, 154, 155, 156, 157, 158, 116, - /* 1540 */ 218, 219, 195, 22, 257, 49, 218, 219, 23, 195, - /* 1550 */ 25, 195, 117, 301, 195, 25, 60, 195, 195, 23, - /* 1560 */ 195, 25, 195, 183, 24, 218, 219, 130, 72, 195, - /* 1570 */ 22, 195, 218, 219, 218, 219, 195, 218, 219, 195, - /* 1580 */ 218, 219, 86, 218, 219, 218, 219, 91, 19, 20, - /* 1590 */ 153, 22, 218, 219, 218, 219, 195, 101, 195, 218, - /* 1600 */ 219, 195, 195, 107, 108, 36, 23, 195, 25, 195, - /* 1610 */ 62, 115, 195, 117, 118, 119, 195, 146, 122, 218, - /* 1620 */ 219, 218, 219, 195, 218, 219, 19, 60, 122, 60, - /* 1630 */ 218, 219, 218, 219, 195, 218, 219, 150, 132, 218, - /* 1640 */ 219, 72, 195, 23, 195, 25, 218, 219, 195, 60, - /* 1650 */ 154, 155, 156, 157, 158, 86, 23, 195, 25, 195, - /* 1660 */ 91, 19, 20, 142, 22, 218, 219, 218, 219, 130, - /* 1670 */ 101, 218, 219, 143, 121, 122, 107, 108, 36, 183, - /* 1680 */ 218, 219, 142, 60, 115, 118, 117, 118, 119, 7, - /* 1690 */ 8, 122, 153, 23, 23, 25, 25, 23, 23, 25, - /* 1700 */ 25, 23, 60, 25, 23, 98, 25, 118, 84, 85, - /* 1710 */ 23, 23, 25, 25, 72, 154, 23, 156, 25, 23, - /* 1720 */ 228, 25, 195, 154, 155, 156, 157, 158, 86, 195, - /* 1730 */ 195, 258, 195, 91, 291, 322, 195, 195, 195, 195, - /* 1740 */ 195, 118, 195, 101, 195, 195, 195, 195, 238, 107, - /* 1750 */ 108, 195, 183, 195, 195, 195, 290, 115, 195, 117, - /* 1760 */ 118, 119, 244, 195, 122, 195, 195, 195, 195, 195, - /* 1770 */ 195, 258, 258, 258, 258, 193, 245, 300, 216, 274, - /* 1780 */ 247, 270, 270, 274, 296, 296, 248, 222, 262, 198, - /* 1790 */ 262, 274, 61, 274, 248, 231, 154, 155, 156, 157, - /* 1800 */ 158, 0, 1, 2, 247, 227, 5, 221, 221, 221, - /* 1810 */ 142, 10, 11, 12, 13, 14, 262, 262, 17, 202, - /* 1820 */ 300, 19, 20, 300, 22, 183, 247, 251, 251, 245, - /* 1830 */ 202, 30, 38, 32, 202, 152, 151, 22, 36, 43, - /* 1840 */ 236, 40, 18, 202, 239, 239, 18, 239, 239, 283, - /* 1850 */ 201, 150, 236, 202, 236, 201, 159, 202, 248, 248, - /* 1860 */ 248, 248, 60, 63, 201, 275, 273, 275, 273, 275, - /* 1870 */ 22, 286, 71, 223, 72, 202, 223, 297, 297, 202, - /* 1880 */ 79, 201, 116, 82, 220, 201, 220, 220, 65, 293, - /* 1890 */ 292, 229, 22, 166, 127, 226, 24, 114, 226, 223, - /* 1900 */ 99, 222, 202, 101, 285, 92, 220, 308, 83, 107, - /* 1910 */ 108, 220, 220, 316, 220, 285, 268, 115, 229, 117, - /* 1920 */ 118, 119, 223, 321, 122, 268, 149, 146, 22, 19, - /* 1930 */ 20, 202, 22, 159, 282, 134, 321, 148, 280, 147, - /* 1940 */ 139, 140, 252, 141, 25, 204, 36, 252, 13, 251, - /* 1950 */ 196, 248, 250, 249, 196, 6, 154, 155, 156, 157, - /* 1960 */ 158, 209, 194, 194, 163, 194, 306, 306, 303, 224, - /* 1970 */ 60, 215, 215, 209, 215, 215, 215, 224, 216, 216, - /* 1980 */ 4, 209, 72, 3, 22, 183, 164, 15, 23, 16, - /* 1990 */ 23, 140, 152, 131, 25, 24, 143, 20, 16, 145, - /* 2000 */ 1, 143, 131, 62, 131, 37, 54, 152, 54, 54, - /* 2010 */ 54, 101, 131, 117, 1, 34, 142, 107, 108, 5, - /* 2020 */ 22, 116, 162, 76, 41, 115, 69, 117, 118, 119, - /* 2030 */ 1, 2, 122, 25, 5, 69, 142, 116, 20, 10, - /* 2040 */ 11, 12, 13, 14, 24, 19, 17, 132, 5, 126, - /* 2050 */ 22, 141, 68, 10, 11, 12, 13, 14, 22, 30, - /* 2060 */ 17, 32, 22, 22, 154, 155, 156, 157, 158, 40, - /* 2070 */ 23, 68, 60, 30, 24, 32, 97, 28, 22, 68, - /* 2080 */ 23, 37, 34, 40, 150, 22, 25, 23, 23, 23, - /* 2090 */ 22, 98, 142, 183, 23, 23, 34, 22, 25, 89, - /* 2100 */ 71, 34, 117, 144, 34, 22, 76, 76, 79, 87, - /* 2110 */ 34, 82, 34, 44, 71, 94, 34, 23, 25, 24, - /* 2120 */ 34, 25, 79, 23, 23, 82, 23, 23, 99, 143, - /* 2130 */ 143, 22, 25, 25, 23, 22, 11, 22, 22, 25, - /* 2140 */ 23, 23, 99, 22, 22, 136, 142, 142, 142, 25, - /* 2150 */ 23, 15, 1, 1, 323, 323, 323, 323, 323, 323, - /* 2160 */ 323, 323, 323, 134, 323, 323, 323, 323, 139, 140, - /* 2170 */ 323, 323, 323, 323, 323, 323, 323, 134, 323, 323, - /* 2180 */ 323, 323, 139, 140, 323, 323, 323, 323, 323, 323, - /* 2190 */ 323, 323, 163, 323, 323, 323, 323, 323, 323, 323, - /* 2200 */ 323, 323, 323, 323, 323, 323, 163, 323, 323, 323, - /* 2210 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2220 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2230 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2240 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2250 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2260 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2270 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2280 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2290 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2300 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2310 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2320 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2330 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, - /* 2340 */ 323, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2350 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2360 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2370 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2380 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2390 */ 187, 187, 187, 187, -}; -#define YY_SHIFT_COUNT (582) -#define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2152) -static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 2029, 1801, 2043, 1380, 1380, 318, 271, 1496, 1569, 1642, - /* 10 */ 702, 702, 702, 740, 318, 318, 318, 318, 318, 0, - /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702, - /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 503, 503, - /* 40 */ 111, 111, 217, 287, 348, 610, 610, 736, 736, 736, - /* 50 */ 736, 40, 112, 320, 340, 445, 489, 593, 637, 741, - /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177, - /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, - /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554, - /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702, - /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198, - /* 150 */ 183, 99, 169, 549, 610, 151, 542, 610, 610, 1017, - /* 160 */ 1017, 610, 1001, 350, 464, 464, 464, 586, 1, 1, - /* 170 */ 2207, 2207, 854, 854, 854, 465, 694, 694, 694, 694, - /* 180 */ 1096, 1096, 825, 549, 847, 904, 610, 610, 610, 610, - /* 190 */ 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, - /* 200 */ 610, 610, 610, 610, 610, 488, 947, 947, 610, 1129, - /* 210 */ 495, 495, 1139, 1139, 967, 967, 1173, 2207, 2207, 2207, - /* 220 */ 2207, 2207, 2207, 2207, 617, 765, 765, 697, 444, 708, - /* 230 */ 660, 745, 510, 663, 864, 610, 610, 610, 610, 610, - /* 240 */ 610, 610, 610, 610, 610, 188, 610, 610, 610, 610, - /* 250 */ 610, 610, 610, 610, 610, 610, 610, 610, 839, 839, - /* 260 */ 839, 610, 610, 610, 1155, 610, 610, 610, 1119, 1247, - /* 270 */ 610, 1353, 610, 610, 610, 610, 610, 610, 610, 610, - /* 280 */ 1063, 494, 1101, 291, 291, 291, 291, 1319, 1101, 1101, - /* 290 */ 775, 1221, 1375, 1452, 667, 1341, 1198, 1341, 1435, 1487, - /* 300 */ 667, 667, 1487, 667, 1198, 1435, 777, 1011, 1423, 584, - /* 310 */ 584, 584, 1273, 1273, 1273, 1273, 1471, 1471, 880, 1530, - /* 320 */ 1190, 1095, 1731, 1731, 1668, 1668, 1794, 1794, 1668, 1683, - /* 330 */ 1685, 1815, 1796, 1824, 1824, 1824, 1824, 1668, 1828, 1701, - /* 340 */ 1685, 1685, 1701, 1815, 1796, 1701, 1796, 1701, 1668, 1828, - /* 350 */ 1697, 1800, 1668, 1828, 1848, 1668, 1828, 1668, 1828, 1848, - /* 360 */ 1766, 1766, 1766, 1823, 1870, 1870, 1848, 1766, 1767, 1766, - /* 370 */ 1823, 1766, 1766, 1727, 1872, 1783, 1783, 1848, 1668, 1813, - /* 380 */ 1813, 1825, 1825, 1777, 1781, 1906, 1668, 1774, 1777, 1789, - /* 390 */ 1792, 1701, 1919, 1935, 1935, 1949, 1949, 1949, 2207, 2207, - /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, - /* 410 */ 2207, 2207, 2207, 69, 1032, 79, 357, 1377, 1206, 400, - /* 420 */ 1525, 835, 332, 1540, 1437, 1539, 1536, 1548, 1583, 1620, - /* 430 */ 1633, 1670, 1671, 1674, 1567, 1553, 1682, 1506, 1675, 1358, - /* 440 */ 1607, 1589, 1678, 1681, 1624, 1687, 1688, 1283, 1561, 1693, - /* 450 */ 1696, 1623, 1521, 1976, 1980, 1962, 1822, 1972, 1973, 1965, - /* 460 */ 1967, 1851, 1840, 1862, 1969, 1969, 1971, 1853, 1977, 1854, - /* 470 */ 1982, 1999, 1858, 1871, 1969, 1873, 1941, 1968, 1969, 1855, - /* 480 */ 1952, 1954, 1955, 1956, 1881, 1896, 1981, 1874, 2013, 2014, - /* 490 */ 1998, 1905, 1860, 1957, 2008, 1966, 1947, 1983, 1894, 1921, - /* 500 */ 2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047, - /* 510 */ 2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057, - /* 520 */ 2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1950, - /* 530 */ 2071, 2072, 1985, 2062, 2075, 1959, 2073, 2067, 2070, 2076, - /* 540 */ 2078, 2010, 2030, 2022, 2069, 2031, 2021, 2082, 2094, 2083, - /* 550 */ 2095, 2093, 2096, 2086, 1986, 1987, 2100, 2073, 2101, 2103, - /* 560 */ 2104, 2109, 2107, 2108, 2111, 2113, 2125, 2115, 2116, 2117, - /* 570 */ 2118, 2121, 2122, 2114, 2009, 2004, 2005, 2006, 2124, 2127, - /* 580 */ 2136, 2151, 2152, -}; -#define YY_REDUCE_COUNT (412) -#define YY_REDUCE_MIN (-277) -#define YY_REDUCE_MAX (1772) + /* 0 */ 19, 115, 19, 117, 118, 24, 1, 2, 27, 79, + /* 10 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + /* 20 */ 90, 91, 92, 93, 94, 144, 145, 146, 147, 58, + /* 30 */ 49, 50, 79, 80, 81, 82, 22, 84, 85, 86, + /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 221, 222, + /* 50 */ 223, 70, 71, 72, 73, 74, 75, 76, 77, 78, + /* 60 */ 79, 80, 81, 82, 94, 84, 85, 86, 87, 88, + /* 70 */ 89, 90, 91, 92, 93, 94, 19, 94, 97, 108, + /* 80 */ 109, 110, 99, 100, 101, 102, 103, 104, 105, 32, + /* 90 */ 119, 120, 78, 27, 152, 112, 93, 94, 41, 88, + /* 100 */ 89, 90, 91, 92, 93, 94, 49, 50, 84, 85, + /* 110 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 58, + /* 120 */ 157, 119, 120, 163, 68, 163, 65, 70, 71, 72, + /* 130 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + /* 140 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92, + /* 150 */ 93, 94, 19, 97, 88, 89, 196, 101, 196, 26, + /* 160 */ 172, 173, 96, 97, 98, 210, 100, 22, 152, 108, + /* 170 */ 109, 110, 27, 107, 27, 109, 221, 222, 223, 219, + /* 180 */ 238, 219, 49, 50, 152, 169, 170, 54, 132, 133, + /* 190 */ 134, 228, 232, 171, 231, 207, 208, 237, 132, 237, + /* 200 */ 134, 179, 19, 70, 71, 72, 73, 74, 75, 76, + /* 210 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86, + /* 220 */ 87, 88, 89, 90, 91, 92, 93, 94, 27, 65, + /* 230 */ 30, 152, 49, 50, 34, 52, 90, 91, 92, 93, + /* 240 */ 94, 96, 97, 98, 97, 22, 230, 27, 48, 217, + /* 250 */ 27, 172, 173, 70, 71, 72, 73, 74, 75, 76, + /* 260 */ 77, 78, 79, 80, 81, 82, 172, 84, 85, 86, + /* 270 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 148, + /* 280 */ 149, 152, 218, 24, 152, 154, 207, 156, 172, 152, + /* 290 */ 22, 68, 27, 152, 163, 27, 164, 96, 97, 98, + /* 300 */ 99, 172, 173, 102, 103, 104, 169, 170, 49, 50, + /* 310 */ 90, 88, 89, 152, 113, 186, 96, 97, 98, 96, + /* 320 */ 97, 160, 57, 27, 101, 164, 137, 196, 139, 70, + /* 330 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + /* 340 */ 81, 82, 11, 84, 85, 86, 87, 88, 89, 90, + /* 350 */ 91, 92, 93, 94, 19, 132, 133, 134, 23, 218, + /* 360 */ 152, 96, 97, 98, 96, 97, 98, 230, 99, 22, + /* 370 */ 152, 102, 103, 104, 27, 244, 152, 152, 27, 26, + /* 380 */ 152, 22, 113, 65, 49, 50, 27, 194, 195, 58, + /* 390 */ 172, 173, 96, 97, 98, 185, 65, 172, 173, 206, + /* 400 */ 172, 173, 190, 191, 186, 70, 71, 72, 73, 74, + /* 410 */ 75, 76, 77, 78, 79, 80, 81, 82, 175, 84, + /* 420 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 430 */ 19, 175, 207, 208, 23, 207, 208, 119, 120, 108, + /* 440 */ 109, 110, 27, 96, 97, 98, 116, 96, 97, 98, + /* 450 */ 152, 121, 152, 179, 180, 96, 97, 98, 250, 106, + /* 460 */ 49, 50, 188, 19, 221, 222, 223, 168, 169, 170, + /* 470 */ 172, 173, 172, 173, 250, 124, 172, 221, 222, 223, + /* 480 */ 26, 70, 71, 72, 73, 74, 75, 76, 77, 78, + /* 490 */ 79, 80, 81, 82, 50, 84, 85, 86, 87, 88, + /* 500 */ 89, 90, 91, 92, 93, 94, 19, 207, 208, 12, + /* 510 */ 23, 96, 97, 98, 221, 222, 223, 194, 195, 152, + /* 520 */ 199, 23, 19, 225, 26, 28, 152, 152, 152, 206, + /* 530 */ 209, 164, 190, 191, 241, 152, 49, 50, 152, 124, + /* 540 */ 152, 44, 219, 46, 152, 21, 172, 173, 172, 173, + /* 550 */ 183, 107, 185, 16, 163, 58, 112, 70, 71, 72, + /* 560 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + /* 570 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92, + /* 580 */ 93, 94, 19, 207, 130, 152, 23, 196, 64, 152, + /* 590 */ 172, 173, 22, 152, 24, 152, 98, 27, 61, 96, + /* 600 */ 63, 26, 211, 212, 186, 172, 173, 49, 50, 172, + /* 610 */ 173, 23, 49, 50, 26, 172, 173, 88, 89, 186, + /* 620 */ 24, 238, 124, 27, 238, 22, 23, 103, 187, 26, + /* 630 */ 152, 73, 74, 70, 71, 72, 73, 74, 75, 76, + /* 640 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86, + /* 650 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 101, + /* 660 */ 152, 132, 23, 134, 140, 152, 12, 97, 36, 168, + /* 670 */ 169, 170, 69, 98, 152, 22, 23, 140, 50, 26, + /* 680 */ 172, 173, 28, 51, 152, 172, 173, 193, 49, 50, + /* 690 */ 22, 59, 24, 97, 172, 173, 152, 152, 44, 124, + /* 700 */ 46, 0, 1, 2, 172, 173, 22, 23, 19, 70, + /* 710 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + /* 720 */ 81, 82, 69, 84, 85, 86, 87, 88, 89, 90, + /* 730 */ 91, 92, 93, 94, 152, 107, 152, 193, 49, 50, + /* 740 */ 181, 22, 23, 111, 108, 109, 110, 7, 8, 9, + /* 750 */ 16, 247, 248, 69, 172, 173, 172, 173, 152, 70, + /* 760 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + /* 770 */ 81, 82, 152, 84, 85, 86, 87, 88, 89, 90, + /* 780 */ 91, 92, 93, 94, 19, 152, 242, 152, 69, 152, + /* 790 */ 166, 167, 172, 173, 32, 61, 152, 63, 152, 193, + /* 800 */ 152, 152, 152, 41, 152, 172, 173, 172, 173, 172, + /* 810 */ 173, 152, 152, 152, 49, 50, 172, 173, 172, 173, + /* 820 */ 172, 173, 172, 173, 172, 173, 132, 138, 134, 152, + /* 830 */ 152, 172, 173, 172, 173, 70, 71, 72, 73, 74, + /* 840 */ 75, 76, 77, 78, 79, 80, 81, 82, 152, 84, + /* 850 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 860 */ 19, 152, 22, 152, 195, 24, 152, 27, 172, 173, + /* 870 */ 193, 193, 152, 152, 152, 206, 152, 217, 152, 152, + /* 880 */ 152, 172, 173, 172, 173, 152, 172, 173, 152, 152, + /* 890 */ 49, 50, 172, 173, 172, 173, 172, 173, 172, 173, + /* 900 */ 172, 173, 152, 138, 152, 172, 173, 108, 109, 110, + /* 910 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, + /* 920 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, + /* 930 */ 89, 90, 91, 92, 93, 94, 152, 97, 152, 152, + /* 940 */ 49, 50, 26, 193, 172, 173, 152, 152, 152, 146, + /* 950 */ 147, 132, 152, 134, 217, 181, 172, 173, 172, 173, + /* 960 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, + /* 970 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, + /* 980 */ 89, 90, 91, 92, 93, 94, 152, 193, 152, 193, + /* 990 */ 49, 50, 181, 193, 172, 173, 166, 167, 245, 246, + /* 1000 */ 211, 212, 152, 22, 217, 152, 172, 173, 172, 173, + /* 1010 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, + /* 1020 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, + /* 1030 */ 89, 90, 91, 92, 93, 94, 152, 187, 152, 123, + /* 1040 */ 49, 50, 23, 23, 23, 26, 26, 26, 23, 23, + /* 1050 */ 23, 26, 26, 26, 7, 8, 172, 173, 172, 173, + /* 1060 */ 19, 90, 71, 72, 73, 74, 75, 76, 77, 78, + /* 1070 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, + /* 1080 */ 89, 90, 91, 92, 93, 94, 152, 116, 152, 217, + /* 1090 */ 49, 50, 121, 23, 172, 173, 26, 100, 101, 27, + /* 1100 */ 101, 27, 23, 122, 152, 26, 172, 173, 172, 173, + /* 1110 */ 152, 112, 163, 72, 73, 74, 75, 76, 77, 78, + /* 1120 */ 79, 80, 81, 82, 163, 84, 85, 86, 87, 88, + /* 1130 */ 89, 90, 91, 92, 93, 94, 19, 20, 152, 22, + /* 1140 */ 23, 152, 163, 65, 27, 196, 163, 19, 20, 23, + /* 1150 */ 22, 213, 26, 19, 37, 27, 152, 196, 172, 173, + /* 1160 */ 152, 172, 173, 27, 23, 37, 152, 26, 152, 97, + /* 1170 */ 152, 97, 210, 56, 163, 196, 163, 163, 100, 196, + /* 1180 */ 172, 173, 65, 152, 56, 68, 172, 173, 172, 173, + /* 1190 */ 172, 173, 152, 65, 163, 163, 68, 23, 152, 234, + /* 1200 */ 26, 152, 152, 172, 173, 88, 89, 196, 152, 196, + /* 1210 */ 196, 152, 95, 96, 97, 98, 88, 89, 101, 152, + /* 1220 */ 152, 207, 208, 95, 96, 97, 98, 196, 196, 101, + /* 1230 */ 96, 233, 152, 97, 152, 152, 19, 20, 207, 22, + /* 1240 */ 152, 152, 152, 191, 27, 152, 152, 152, 152, 132, + /* 1250 */ 133, 134, 135, 136, 37, 152, 152, 152, 152, 152, + /* 1260 */ 132, 133, 134, 135, 136, 210, 197, 210, 210, 198, + /* 1270 */ 150, 184, 239, 56, 201, 214, 214, 201, 239, 180, + /* 1280 */ 214, 227, 198, 38, 176, 68, 175, 175, 175, 122, + /* 1290 */ 155, 200, 159, 19, 20, 40, 22, 159, 159, 22, + /* 1300 */ 70, 27, 130, 243, 240, 88, 89, 90, 189, 18, + /* 1310 */ 201, 37, 95, 96, 97, 98, 192, 5, 101, 192, + /* 1320 */ 220, 240, 10, 11, 12, 13, 14, 159, 18, 17, + /* 1330 */ 56, 158, 192, 201, 192, 220, 189, 189, 201, 159, + /* 1340 */ 158, 137, 68, 31, 45, 33, 236, 159, 159, 132, + /* 1350 */ 133, 134, 135, 136, 42, 158, 235, 22, 177, 159, + /* 1360 */ 158, 158, 88, 89, 159, 107, 174, 55, 177, 95, + /* 1370 */ 96, 97, 98, 174, 62, 101, 47, 65, 66, 106, + /* 1380 */ 174, 125, 19, 20, 174, 22, 177, 176, 174, 182, + /* 1390 */ 27, 216, 174, 174, 182, 107, 159, 22, 215, 215, + /* 1400 */ 37, 216, 216, 216, 137, 215, 132, 133, 134, 135, + /* 1410 */ 136, 215, 159, 177, 94, 177, 129, 224, 205, 56, + /* 1420 */ 226, 126, 128, 203, 229, 204, 114, 229, 127, 202, + /* 1430 */ 201, 68, 25, 162, 26, 13, 161, 153, 153, 6, + /* 1440 */ 151, 151, 178, 151, 165, 165, 178, 165, 4, 3, + /* 1450 */ 249, 88, 89, 141, 22, 142, 15, 249, 95, 96, + /* 1460 */ 97, 98, 246, 67, 101, 16, 23, 120, 23, 131, + /* 1470 */ 111, 123, 20, 16, 125, 1, 123, 131, 78, 78, + /* 1480 */ 78, 78, 111, 96, 122, 35, 1, 5, 22, 107, + /* 1490 */ 140, 53, 53, 26, 60, 132, 133, 134, 135, 136, + /* 1500 */ 107, 43, 24, 20, 112, 19, 22, 52, 52, 105, + /* 1510 */ 22, 22, 52, 23, 22, 22, 29, 23, 39, 23, + /* 1520 */ 23, 26, 116, 22, 26, 23, 22, 122, 23, 23, + /* 1530 */ 22, 96, 11, 124, 35, 26, 26, 23, 35, 23, + /* 1540 */ 23, 23, 35, 23, 22, 26, 23, 22, 24, 122, + /* 1550 */ 23, 22, 26, 22, 24, 23, 23, 23, 22, 122, + /* 1560 */ 23, 15, 122, 1, 122, +}; +#define YY_SHIFT_USE_DFLT (1565) +#define YY_SHIFT_COUNT (454) +#define YY_SHIFT_MIN (-114) +#define YY_SHIFT_MAX (1562) +static const short yy_shift_ofst[] = { + /* 0 */ 5, 1117, 1312, 1128, 1274, 1274, 1274, 1274, 61, -19, + /* 10 */ 57, 57, 183, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + /* 20 */ 66, 66, 201, -29, 331, 318, 133, 259, 335, 411, + /* 30 */ 487, 563, 639, 689, 765, 841, 891, 891, 891, 891, + /* 40 */ 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, + /* 50 */ 891, 891, 891, 941, 891, 991, 1041, 1041, 1217, 1274, + /* 60 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + /* 70 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + /* 80 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + /* 90 */ 1363, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + /* 100 */ 1274, 1274, 1274, 1274, -70, -47, -47, -47, -47, -47, + /* 110 */ 24, 11, 146, 296, 524, 444, 529, 529, 296, 3, + /* 120 */ 2, -30, 1565, 1565, 1565, -17, -17, -17, 145, 145, + /* 130 */ 497, 497, 265, 603, 653, 296, 296, 296, 296, 296, + /* 140 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + /* 150 */ 296, 296, 296, 296, 296, 701, 1078, 147, 147, 2, + /* 160 */ 164, 164, 164, 164, 164, 164, 1565, 1565, 1565, 223, + /* 170 */ 56, 56, 268, 269, 220, 347, 351, 415, 359, 296, + /* 180 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + /* 190 */ 296, 296, 296, 296, 296, 632, 632, 632, 296, 296, + /* 200 */ 498, 296, 296, 296, 570, 296, 296, 654, 296, 296, + /* 210 */ 296, 296, 296, 296, 296, 296, 296, 296, 636, 200, + /* 220 */ 596, 596, 596, 575, -114, 971, 740, 454, 503, 503, + /* 230 */ 1134, 454, 1134, 353, 588, 628, 762, 503, 189, 762, + /* 240 */ 762, 916, 330, 668, 1245, 1167, 1167, 1255, 1255, 1167, + /* 250 */ 1277, 1230, 1172, 1291, 1291, 1291, 1291, 1167, 1310, 1172, + /* 260 */ 1277, 1230, 1230, 1172, 1167, 1310, 1204, 1299, 1167, 1167, + /* 270 */ 1310, 1335, 1167, 1310, 1167, 1310, 1335, 1258, 1258, 1258, + /* 280 */ 1329, 1335, 1258, 1273, 1258, 1329, 1258, 1258, 1256, 1288, + /* 290 */ 1256, 1288, 1256, 1288, 1256, 1288, 1167, 1375, 1167, 1267, + /* 300 */ 1335, 1320, 1320, 1335, 1287, 1295, 1294, 1301, 1172, 1407, + /* 310 */ 1408, 1422, 1422, 1433, 1433, 1433, 1565, 1565, 1565, 1565, + /* 320 */ 1565, 1565, 1565, 1565, 558, 537, 684, 719, 734, 799, + /* 330 */ 840, 1019, 14, 1020, 1021, 1025, 1026, 1027, 1070, 1072, + /* 340 */ 997, 1047, 999, 1079, 1126, 1074, 1141, 694, 819, 1174, + /* 350 */ 1136, 981, 1444, 1446, 1432, 1313, 1441, 1396, 1449, 1443, + /* 360 */ 1445, 1347, 1338, 1359, 1348, 1452, 1349, 1457, 1474, 1353, + /* 370 */ 1346, 1400, 1401, 1402, 1403, 1371, 1387, 1450, 1362, 1485, + /* 380 */ 1482, 1466, 1382, 1350, 1438, 1467, 1439, 1434, 1458, 1393, + /* 390 */ 1478, 1483, 1486, 1392, 1404, 1484, 1455, 1488, 1489, 1490, + /* 400 */ 1492, 1456, 1487, 1493, 1460, 1479, 1494, 1496, 1497, 1495, + /* 410 */ 1406, 1501, 1502, 1504, 1498, 1405, 1505, 1506, 1435, 1499, + /* 420 */ 1508, 1409, 1509, 1503, 1510, 1507, 1514, 1509, 1516, 1517, + /* 430 */ 1518, 1519, 1520, 1522, 1521, 1523, 1525, 1524, 1526, 1527, + /* 440 */ 1529, 1530, 1526, 1532, 1531, 1533, 1534, 1536, 1427, 1437, + /* 450 */ 1440, 1442, 1537, 1546, 1562, +}; +#define YY_REDUCE_USE_DFLT (-174) +#define YY_REDUCE_COUNT (323) +#define YY_REDUCE_MIN (-173) +#define YY_REDUCE_MAX (1292) static const short yy_reduce_ofst[] = { - /* 0 */ -67, 1252, -64, -178, -181, 160, 1071, 143, -184, 137, - /* 10 */ 218, 220, 222, -174, 229, 268, 272, 275, 324, -208, - /* 20 */ 242, -277, -39, 81, 537, 792, 810, 812, -189, 814, - /* 30 */ 831, 163, 865, 944, 887, 840, 964, 1077, -187, 292, - /* 40 */ -133, 274, 673, 558, 682, 795, 809, -238, -232, -238, - /* 50 */ -232, 329, 329, 329, 329, 329, 329, 329, 329, 329, - /* 60 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - /* 70 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - /* 80 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 557, - /* 90 */ 712, 949, 966, 969, 971, 979, 1097, 1099, 1103, 1142, - /* 100 */ 1144, 1169, 1172, 1201, 1203, 1228, 1241, 1250, 1253, 1255, - /* 110 */ 1261, 1266, 1271, 1282, 1291, 1308, 1310, 1312, 1322, 1328, - /* 120 */ 1347, 1354, 1356, 1359, 1362, 1365, 1367, 1374, 1376, 1381, - /* 130 */ 1401, 1403, 1406, 1412, 1414, 1417, 1421, 1428, 1447, 1449, - /* 140 */ 1453, 1462, 329, 329, 329, 329, 329, 329, 329, 329, - /* 150 */ 329, 329, 329, -22, -159, 475, -220, 756, 38, 501, - /* 160 */ 841, 714, 329, 118, 337, 349, 363, -56, 329, 329, - /* 170 */ 329, 329, -205, -205, -205, 687, -172, -130, -57, 790, - /* 180 */ 397, 528, -271, 136, 596, 596, 90, 316, 522, 541, - /* 190 */ -37, 715, 849, 977, 628, 856, 980, 991, 1081, 1102, - /* 200 */ 1135, 1083, -162, 208, 1258, 794, -86, 159, 41, 1109, - /* 210 */ 671, 852, 844, 932, 1175, 1254, 480, 1180, 100, 258, - /* 220 */ 1265, 1268, 1216, 1287, -139, 317, 344, 63, 339, 423, - /* 230 */ 563, 636, 676, 813, 908, 914, 950, 1078, 1084, 1098, - /* 240 */ 1363, 1384, 1407, 1439, 1464, 411, 1527, 1534, 1535, 1537, - /* 250 */ 1541, 1542, 1543, 1544, 1545, 1547, 1549, 1550, 990, 1164, - /* 260 */ 1492, 1551, 1552, 1556, 1217, 1558, 1559, 1560, 1473, 1413, - /* 270 */ 1563, 1510, 1568, 563, 1570, 1571, 1572, 1573, 1574, 1575, - /* 280 */ 1443, 1466, 1518, 1513, 1514, 1515, 1516, 1217, 1518, 1518, - /* 290 */ 1531, 1562, 1582, 1477, 1505, 1511, 1533, 1512, 1488, 1538, - /* 300 */ 1509, 1517, 1546, 1519, 1557, 1489, 1565, 1564, 1578, 1586, - /* 310 */ 1587, 1588, 1526, 1528, 1554, 1555, 1576, 1577, 1566, 1579, - /* 320 */ 1584, 1591, 1520, 1523, 1617, 1628, 1580, 1581, 1632, 1585, - /* 330 */ 1590, 1593, 1604, 1605, 1606, 1608, 1609, 1641, 1649, 1610, - /* 340 */ 1592, 1594, 1611, 1595, 1616, 1612, 1618, 1613, 1651, 1654, - /* 350 */ 1596, 1598, 1655, 1663, 1650, 1673, 1680, 1677, 1684, 1653, - /* 360 */ 1664, 1666, 1667, 1662, 1669, 1672, 1676, 1686, 1679, 1691, - /* 370 */ 1689, 1692, 1694, 1597, 1599, 1619, 1630, 1699, 1700, 1602, - /* 380 */ 1615, 1648, 1657, 1690, 1698, 1658, 1729, 1652, 1695, 1702, - /* 390 */ 1704, 1703, 1741, 1754, 1758, 1768, 1769, 1771, 1660, 1661, - /* 400 */ 1665, 1752, 1756, 1757, 1759, 1760, 1764, 1745, 1753, 1762, - /* 410 */ 1763, 1761, 1772, + /* 0 */ -119, 1014, 131, 1031, -12, 225, 228, 300, -40, -45, + /* 10 */ 243, 256, 293, 129, 218, 418, 79, 376, 433, 298, + /* 20 */ 16, 137, 367, 323, -38, 391, -173, -173, -173, -173, + /* 30 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173, + /* 40 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173, + /* 50 */ -173, -173, -173, -173, -173, -173, -173, -173, 374, 437, + /* 60 */ 443, 508, 513, 522, 532, 582, 584, 620, 633, 635, + /* 70 */ 637, 644, 646, 648, 650, 652, 659, 661, 696, 709, + /* 80 */ 711, 714, 720, 722, 724, 726, 728, 733, 772, 784, + /* 90 */ 786, 822, 834, 836, 884, 886, 922, 934, 936, 986, + /* 100 */ 989, 1008, 1016, 1018, -173, -173, -173, -173, -173, -173, + /* 110 */ -173, -173, -173, 544, -37, 274, 299, 501, 161, -173, + /* 120 */ 193, -173, -173, -173, -173, 22, 22, 22, 64, 141, + /* 130 */ 212, 342, 208, 504, 504, 132, 494, 606, 677, 678, + /* 140 */ 750, 794, 796, -58, 32, 383, 660, 737, 386, 787, + /* 150 */ 800, 441, 872, 224, 850, 803, 949, 624, 830, 669, + /* 160 */ 961, 979, 983, 1011, 1013, 1032, 753, 789, 321, 94, + /* 170 */ 116, 304, 375, 210, 388, 392, 478, 545, 649, 721, + /* 180 */ 727, 736, 752, 795, 853, 952, 958, 1004, 1040, 1046, + /* 190 */ 1049, 1050, 1056, 1059, 1067, 559, 774, 811, 1068, 1080, + /* 200 */ 938, 1082, 1083, 1088, 962, 1089, 1090, 1052, 1093, 1094, + /* 210 */ 1095, 388, 1096, 1103, 1104, 1105, 1106, 1107, 965, 998, + /* 220 */ 1055, 1057, 1058, 938, 1069, 1071, 1120, 1073, 1061, 1062, + /* 230 */ 1033, 1076, 1039, 1108, 1087, 1099, 1111, 1066, 1054, 1112, + /* 240 */ 1113, 1091, 1084, 1135, 1060, 1133, 1138, 1064, 1081, 1139, + /* 250 */ 1100, 1119, 1109, 1124, 1127, 1140, 1142, 1168, 1173, 1132, + /* 260 */ 1115, 1147, 1148, 1137, 1180, 1182, 1110, 1121, 1188, 1189, + /* 270 */ 1197, 1181, 1200, 1202, 1205, 1203, 1191, 1192, 1199, 1206, + /* 280 */ 1207, 1209, 1210, 1211, 1214, 1212, 1218, 1219, 1175, 1183, + /* 290 */ 1185, 1184, 1186, 1190, 1187, 1196, 1237, 1193, 1253, 1194, + /* 300 */ 1236, 1195, 1198, 1238, 1213, 1221, 1220, 1227, 1229, 1271, + /* 310 */ 1275, 1284, 1285, 1289, 1290, 1292, 1201, 1208, 1216, 1279, + /* 320 */ 1280, 1264, 1268, 1282, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254, - /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397, - /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254, - /* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254, - /* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254, - /* 60 */ 1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420, - /* 70 */ 1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, - /* 80 */ 1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, - /* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 140 */ 1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, - /* 150 */ 1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, - /* 160 */ 1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, - /* 170 */ 1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, - /* 180 */ 1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 200 */ 1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, - /* 210 */ 1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, - /* 220 */ 1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, - /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, - /* 240 */ 1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, - /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, - /* 280 */ 1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, - /* 290 */ 1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, - /* 300 */ 1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, - /* 310 */ 1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, - /* 320 */ 1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, - /* 330 */ 1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, - /* 340 */ 1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, - /* 350 */ 1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, - /* 360 */ 1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, - /* 370 */ 1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, - /* 380 */ 1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, - /* 390 */ 1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, - /* 400 */ 1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, - /* 410 */ 1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, - /* 420 */ 1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, - /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 440 */ 1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 450 */ 1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, - /* 460 */ 1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, - /* 470 */ 1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, - /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, - /* 490 */ 1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, - /* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 510 */ 1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 530 */ 1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, - /* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 550 */ 1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, - /* 560 */ 1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, - /* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254, - /* 580 */ 1266, 1254, 1254, + /* 0 */ 1270, 1260, 1260, 1260, 1193, 1193, 1193, 1193, 1260, 1088, + /* 10 */ 1117, 1117, 1244, 1322, 1322, 1322, 1322, 1322, 1322, 1192, + /* 20 */ 1322, 1322, 1322, 1322, 1260, 1092, 1123, 1322, 1322, 1322, + /* 30 */ 1322, 1194, 1195, 1322, 1322, 1322, 1243, 1245, 1133, 1132, + /* 40 */ 1131, 1130, 1226, 1104, 1128, 1121, 1125, 1194, 1188, 1189, + /* 50 */ 1187, 1191, 1195, 1322, 1124, 1158, 1172, 1157, 1322, 1322, + /* 60 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 70 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 80 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 90 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 100 */ 1322, 1322, 1322, 1322, 1166, 1171, 1178, 1170, 1167, 1160, + /* 110 */ 1159, 1161, 1162, 1322, 1011, 1059, 1322, 1322, 1322, 1163, + /* 120 */ 1322, 1164, 1175, 1174, 1173, 1251, 1278, 1277, 1322, 1322, + /* 130 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 140 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 150 */ 1322, 1322, 1322, 1322, 1322, 1270, 1260, 1017, 1017, 1322, + /* 160 */ 1260, 1260, 1260, 1260, 1260, 1260, 1256, 1092, 1083, 1322, + /* 170 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 180 */ 1248, 1246, 1322, 1208, 1322, 1322, 1322, 1322, 1322, 1322, + /* 190 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 200 */ 1322, 1322, 1322, 1322, 1088, 1322, 1322, 1322, 1322, 1322, + /* 210 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1272, 1322, 1221, + /* 220 */ 1088, 1088, 1088, 1090, 1072, 1082, 997, 1127, 1106, 1106, + /* 230 */ 1311, 1127, 1311, 1034, 1292, 1031, 1117, 1106, 1190, 1117, + /* 240 */ 1117, 1089, 1082, 1322, 1314, 1097, 1097, 1313, 1313, 1097, + /* 250 */ 1138, 1062, 1127, 1068, 1068, 1068, 1068, 1097, 1008, 1127, + /* 260 */ 1138, 1062, 1062, 1127, 1097, 1008, 1225, 1308, 1097, 1097, + /* 270 */ 1008, 1201, 1097, 1008, 1097, 1008, 1201, 1060, 1060, 1060, + /* 280 */ 1049, 1201, 1060, 1034, 1060, 1049, 1060, 1060, 1110, 1105, + /* 290 */ 1110, 1105, 1110, 1105, 1110, 1105, 1097, 1196, 1097, 1322, + /* 300 */ 1201, 1205, 1205, 1201, 1122, 1111, 1120, 1118, 1127, 1014, + /* 310 */ 1052, 1275, 1275, 1271, 1271, 1271, 1319, 1319, 1256, 1287, + /* 320 */ 1287, 1036, 1036, 1287, 1322, 1322, 1322, 1322, 1322, 1322, + /* 330 */ 1282, 1322, 1210, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 340 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 350 */ 1322, 1143, 1322, 993, 1253, 1322, 1322, 1252, 1322, 1322, + /* 360 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 370 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1310, 1322, + /* 380 */ 1322, 1322, 1322, 1322, 1322, 1224, 1223, 1322, 1322, 1322, + /* 390 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 400 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 410 */ 1074, 1322, 1322, 1322, 1296, 1322, 1322, 1322, 1322, 1322, + /* 420 */ 1322, 1322, 1119, 1322, 1112, 1322, 1322, 1301, 1322, 1322, + /* 430 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1262, 1322, + /* 440 */ 1322, 1322, 1261, 1322, 1322, 1322, 1322, 1322, 1145, 1322, + /* 450 */ 1144, 1148, 1322, 1002, 1322, }; /********** End of lemon-generated parsing tables *****************************/ -/* The next table maps tokens (terminal symbols) into fallback tokens. +/* The next table maps tokens (terminal symbols) into fallback tokens. ** If a construct like the following: -** +** ** %fallback ID X Y Z. ** ** appears in the grammar, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and @@ -175466,195 +137331,77 @@ */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ 0, /* SEMI => nothing */ - 60, /* EXPLAIN => ID */ - 60, /* QUERY => ID */ - 60, /* PLAN => ID */ - 60, /* BEGIN => ID */ + 27, /* EXPLAIN => ID */ + 27, /* QUERY => ID */ + 27, /* PLAN => ID */ + 27, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ - 60, /* DEFERRED => ID */ - 60, /* IMMEDIATE => ID */ - 60, /* EXCLUSIVE => ID */ + 27, /* DEFERRED => ID */ + 27, /* IMMEDIATE => ID */ + 27, /* EXCLUSIVE => ID */ 0, /* COMMIT => nothing */ - 60, /* END => ID */ - 60, /* ROLLBACK => ID */ - 60, /* SAVEPOINT => ID */ - 60, /* RELEASE => ID */ + 27, /* END => ID */ + 27, /* ROLLBACK => ID */ + 27, /* SAVEPOINT => ID */ + 27, /* RELEASE => ID */ 0, /* TO => nothing */ 0, /* TABLE => nothing */ 0, /* CREATE => nothing */ - 60, /* IF => ID */ + 27, /* IF => ID */ 0, /* NOT => nothing */ 0, /* EXISTS => nothing */ - 60, /* TEMP => ID */ + 27, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ + 27, /* WITHOUT => ID */ 0, /* COMMA => nothing */ - 60, /* WITHOUT => ID */ - 60, /* ABORT => ID */ - 60, /* ACTION => ID */ - 60, /* AFTER => ID */ - 60, /* ANALYZE => ID */ - 60, /* ASC => ID */ - 60, /* ATTACH => ID */ - 60, /* BEFORE => ID */ - 60, /* BY => ID */ - 60, /* CASCADE => ID */ - 60, /* CAST => ID */ - 60, /* CONFLICT => ID */ - 60, /* DATABASE => ID */ - 60, /* DESC => ID */ - 60, /* DETACH => ID */ - 60, /* EACH => ID */ - 60, /* FAIL => ID */ - 0, /* OR => nothing */ - 0, /* AND => nothing */ - 0, /* IS => nothing */ - 0, /* ISNOT => nothing */ - 60, /* MATCH => ID */ - 60, /* LIKE_KW => ID */ - 0, /* BETWEEN => nothing */ - 0, /* IN => nothing */ - 0, /* ISNULL => nothing */ - 0, /* NOTNULL => nothing */ - 0, /* NE => nothing */ - 0, /* EQ => nothing */ - 0, /* GT => nothing */ - 0, /* LE => nothing */ - 0, /* LT => nothing */ - 0, /* GE => nothing */ - 0, /* ESCAPE => nothing */ 0, /* ID => nothing */ - 60, /* COLUMNKW => ID */ - 60, /* DO => ID */ - 60, /* FOR => ID */ - 60, /* IGNORE => ID */ - 60, /* INITIALLY => ID */ - 60, /* INSTEAD => ID */ - 60, /* NO => ID */ - 60, /* KEY => ID */ - 60, /* OF => ID */ - 60, /* OFFSET => ID */ - 60, /* PRAGMA => ID */ - 60, /* RAISE => ID */ - 60, /* RECURSIVE => ID */ - 60, /* REPLACE => ID */ - 60, /* RESTRICT => ID */ - 60, /* ROW => ID */ - 60, /* ROWS => ID */ - 60, /* TRIGGER => ID */ - 60, /* VACUUM => ID */ - 60, /* VIEW => ID */ - 60, /* VIRTUAL => ID */ - 60, /* WITH => ID */ - 60, /* NULLS => ID */ - 60, /* FIRST => ID */ - 60, /* LAST => ID */ - 60, /* CURRENT => ID */ - 60, /* FOLLOWING => ID */ - 60, /* PARTITION => ID */ - 60, /* PRECEDING => ID */ - 60, /* RANGE => ID */ - 60, /* UNBOUNDED => ID */ - 60, /* EXCLUDE => ID */ - 60, /* GROUPS => ID */ - 60, /* OTHERS => ID */ - 60, /* TIES => ID */ - 60, /* GENERATED => ID */ - 60, /* ALWAYS => ID */ - 60, /* MATERIALIZED => ID */ - 60, /* REINDEX => ID */ - 60, /* RENAME => ID */ - 60, /* CTIME_KW => ID */ - 0, /* ANY => nothing */ - 0, /* BITAND => nothing */ - 0, /* BITOR => nothing */ - 0, /* LSHIFT => nothing */ - 0, /* RSHIFT => nothing */ - 0, /* PLUS => nothing */ - 0, /* MINUS => nothing */ - 0, /* STAR => nothing */ - 0, /* SLASH => nothing */ - 0, /* REM => nothing */ - 0, /* CONCAT => nothing */ - 0, /* PTR => nothing */ - 0, /* COLLATE => nothing */ - 0, /* BITNOT => nothing */ - 0, /* ON => nothing */ - 0, /* INDEXED => nothing */ - 0, /* STRING => nothing */ - 0, /* JOIN_KW => nothing */ - 0, /* CONSTRAINT => nothing */ - 0, /* DEFAULT => nothing */ - 0, /* NULL => nothing */ - 0, /* PRIMARY => nothing */ - 0, /* UNIQUE => nothing */ - 0, /* CHECK => nothing */ - 0, /* REFERENCES => nothing */ - 0, /* AUTOINCR => nothing */ - 0, /* INSERT => nothing */ - 0, /* DELETE => nothing */ - 0, /* UPDATE => nothing */ - 0, /* SET => nothing */ - 0, /* DEFERRABLE => nothing */ - 0, /* FOREIGN => nothing */ - 0, /* DROP => nothing */ - 0, /* UNION => nothing */ - 0, /* ALL => nothing */ - 0, /* EXCEPT => nothing */ - 0, /* INTERSECT => nothing */ - 0, /* SELECT => nothing */ - 0, /* VALUES => nothing */ - 0, /* DISTINCT => nothing */ - 0, /* DOT => nothing */ - 0, /* FROM => nothing */ - 0, /* JOIN => nothing */ - 0, /* USING => nothing */ - 0, /* ORDER => nothing */ - 0, /* GROUP => nothing */ - 0, /* HAVING => nothing */ - 0, /* LIMIT => nothing */ - 0, /* WHERE => nothing */ - 0, /* RETURNING => nothing */ - 0, /* INTO => nothing */ - 0, /* NOTHING => nothing */ - 0, /* FLOAT => nothing */ - 0, /* BLOB => nothing */ - 0, /* INTEGER => nothing */ - 0, /* VARIABLE => nothing */ - 0, /* CASE => nothing */ - 0, /* WHEN => nothing */ - 0, /* THEN => nothing */ - 0, /* ELSE => nothing */ - 0, /* INDEX => nothing */ - 0, /* ALTER => nothing */ - 0, /* ADD => nothing */ - 0, /* WINDOW => nothing */ - 0, /* OVER => nothing */ - 0, /* FILTER => nothing */ - 0, /* COLUMN => nothing */ - 0, /* AGG_FUNCTION => nothing */ - 0, /* AGG_COLUMN => nothing */ - 0, /* TRUEFALSE => nothing */ - 0, /* FUNCTION => nothing */ - 0, /* UPLUS => nothing */ - 0, /* UMINUS => nothing */ - 0, /* TRUTH => nothing */ - 0, /* REGISTER => nothing */ - 0, /* VECTOR => nothing */ - 0, /* SELECT_COLUMN => nothing */ - 0, /* IF_NULL_ROW => nothing */ - 0, /* ASTERISK => nothing */ - 0, /* SPAN => nothing */ - 0, /* ERROR => nothing */ - 0, /* QNUMBER => nothing */ - 0, /* SPACE => nothing */ - 0, /* COMMENT => nothing */ - 0, /* ILLEGAL => nothing */ + 27, /* ABORT => ID */ + 27, /* ACTION => ID */ + 27, /* AFTER => ID */ + 27, /* ANALYZE => ID */ + 27, /* ASC => ID */ + 27, /* ATTACH => ID */ + 27, /* BEFORE => ID */ + 27, /* BY => ID */ + 27, /* CASCADE => ID */ + 27, /* CAST => ID */ + 27, /* COLUMNKW => ID */ + 27, /* CONFLICT => ID */ + 27, /* DATABASE => ID */ + 27, /* DESC => ID */ + 27, /* DETACH => ID */ + 27, /* EACH => ID */ + 27, /* FAIL => ID */ + 27, /* FOR => ID */ + 27, /* IGNORE => ID */ + 27, /* INITIALLY => ID */ + 27, /* INSTEAD => ID */ + 27, /* LIKE_KW => ID */ + 27, /* MATCH => ID */ + 27, /* NO => ID */ + 27, /* KEY => ID */ + 27, /* OF => ID */ + 27, /* OFFSET => ID */ + 27, /* PRAGMA => ID */ + 27, /* RAISE => ID */ + 27, /* RECURSIVE => ID */ + 27, /* REPLACE => ID */ + 27, /* RESTRICT => ID */ + 27, /* ROW => ID */ + 27, /* TRIGGER => ID */ + 27, /* VACUUM => ID */ + 27, /* VIEW => ID */ + 27, /* VIRTUAL => ID */ + 27, /* WITH => ID */ + 27, /* REINDEX => ID */ + 27, /* RENAME => ID */ + 27, /* CTIME_KW => ID */ }; #endif /* YYFALLBACK */ /* The following structure represents a single element of the ** parser's stack. Information stored includes: @@ -175690,29 +137437,32 @@ #endif #ifndef YYNOERRORRECOVERY int yyerrcnt; /* Shifts left before out of the error */ #endif sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ - sqlite3ParserCTX_SDECL /* A place to hold %extra_context */ - yyStackEntry *yystackEnd; /* Last entry in the stack */ - yyStackEntry *yystack; /* The parser stack */ - yyStackEntry yystk0[YYSTACKDEPTH]; /* Initial stack space */ +#if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ + yyStackEntry yystk0; /* First stack entry */ +#else + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ + yyStackEntry *yystackEnd; /* Last entry in the stack */ +#endif }; typedef struct yyParser yyParser; -/* #include */ #ifndef NDEBUG /* #include */ static FILE *yyTraceFILE = 0; static char *yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG -/* +/* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL +** by making either argument NULL ** ** Inputs: **
                  **
                • A FILE* to which trace output should be written. ** If NULL, then tracing is turned off. @@ -175730,339 +137480,79 @@ if( yyTraceFILE==0 ) yyTracePrompt = 0; else if( yyTracePrompt==0 ) yyTraceFILE = 0; } #endif /* NDEBUG */ -#if defined(YYCOVERAGE) || !defined(NDEBUG) +#ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ -static const char *const yyTokenName[] = { - /* 0 */ "$", - /* 1 */ "SEMI", - /* 2 */ "EXPLAIN", - /* 3 */ "QUERY", - /* 4 */ "PLAN", - /* 5 */ "BEGIN", - /* 6 */ "TRANSACTION", - /* 7 */ "DEFERRED", - /* 8 */ "IMMEDIATE", - /* 9 */ "EXCLUSIVE", - /* 10 */ "COMMIT", - /* 11 */ "END", - /* 12 */ "ROLLBACK", - /* 13 */ "SAVEPOINT", - /* 14 */ "RELEASE", - /* 15 */ "TO", - /* 16 */ "TABLE", - /* 17 */ "CREATE", - /* 18 */ "IF", - /* 19 */ "NOT", - /* 20 */ "EXISTS", - /* 21 */ "TEMP", - /* 22 */ "LP", - /* 23 */ "RP", - /* 24 */ "AS", - /* 25 */ "COMMA", - /* 26 */ "WITHOUT", - /* 27 */ "ABORT", - /* 28 */ "ACTION", - /* 29 */ "AFTER", - /* 30 */ "ANALYZE", - /* 31 */ "ASC", - /* 32 */ "ATTACH", - /* 33 */ "BEFORE", - /* 34 */ "BY", - /* 35 */ "CASCADE", - /* 36 */ "CAST", - /* 37 */ "CONFLICT", - /* 38 */ "DATABASE", - /* 39 */ "DESC", - /* 40 */ "DETACH", - /* 41 */ "EACH", - /* 42 */ "FAIL", - /* 43 */ "OR", - /* 44 */ "AND", - /* 45 */ "IS", - /* 46 */ "ISNOT", - /* 47 */ "MATCH", - /* 48 */ "LIKE_KW", - /* 49 */ "BETWEEN", - /* 50 */ "IN", - /* 51 */ "ISNULL", - /* 52 */ "NOTNULL", - /* 53 */ "NE", - /* 54 */ "EQ", - /* 55 */ "GT", - /* 56 */ "LE", - /* 57 */ "LT", - /* 58 */ "GE", - /* 59 */ "ESCAPE", - /* 60 */ "ID", - /* 61 */ "COLUMNKW", - /* 62 */ "DO", - /* 63 */ "FOR", - /* 64 */ "IGNORE", - /* 65 */ "INITIALLY", - /* 66 */ "INSTEAD", - /* 67 */ "NO", - /* 68 */ "KEY", - /* 69 */ "OF", - /* 70 */ "OFFSET", - /* 71 */ "PRAGMA", - /* 72 */ "RAISE", - /* 73 */ "RECURSIVE", - /* 74 */ "REPLACE", - /* 75 */ "RESTRICT", - /* 76 */ "ROW", - /* 77 */ "ROWS", - /* 78 */ "TRIGGER", - /* 79 */ "VACUUM", - /* 80 */ "VIEW", - /* 81 */ "VIRTUAL", - /* 82 */ "WITH", - /* 83 */ "NULLS", - /* 84 */ "FIRST", - /* 85 */ "LAST", - /* 86 */ "CURRENT", - /* 87 */ "FOLLOWING", - /* 88 */ "PARTITION", - /* 89 */ "PRECEDING", - /* 90 */ "RANGE", - /* 91 */ "UNBOUNDED", - /* 92 */ "EXCLUDE", - /* 93 */ "GROUPS", - /* 94 */ "OTHERS", - /* 95 */ "TIES", - /* 96 */ "GENERATED", - /* 97 */ "ALWAYS", - /* 98 */ "MATERIALIZED", - /* 99 */ "REINDEX", - /* 100 */ "RENAME", - /* 101 */ "CTIME_KW", - /* 102 */ "ANY", - /* 103 */ "BITAND", - /* 104 */ "BITOR", - /* 105 */ "LSHIFT", - /* 106 */ "RSHIFT", - /* 107 */ "PLUS", - /* 108 */ "MINUS", - /* 109 */ "STAR", - /* 110 */ "SLASH", - /* 111 */ "REM", - /* 112 */ "CONCAT", - /* 113 */ "PTR", - /* 114 */ "COLLATE", - /* 115 */ "BITNOT", - /* 116 */ "ON", - /* 117 */ "INDEXED", - /* 118 */ "STRING", - /* 119 */ "JOIN_KW", - /* 120 */ "CONSTRAINT", - /* 121 */ "DEFAULT", - /* 122 */ "NULL", - /* 123 */ "PRIMARY", - /* 124 */ "UNIQUE", - /* 125 */ "CHECK", - /* 126 */ "REFERENCES", - /* 127 */ "AUTOINCR", - /* 128 */ "INSERT", - /* 129 */ "DELETE", - /* 130 */ "UPDATE", - /* 131 */ "SET", - /* 132 */ "DEFERRABLE", - /* 133 */ "FOREIGN", - /* 134 */ "DROP", - /* 135 */ "UNION", - /* 136 */ "ALL", - /* 137 */ "EXCEPT", - /* 138 */ "INTERSECT", - /* 139 */ "SELECT", - /* 140 */ "VALUES", - /* 141 */ "DISTINCT", - /* 142 */ "DOT", - /* 143 */ "FROM", - /* 144 */ "JOIN", - /* 145 */ "USING", - /* 146 */ "ORDER", - /* 147 */ "GROUP", - /* 148 */ "HAVING", - /* 149 */ "LIMIT", - /* 150 */ "WHERE", - /* 151 */ "RETURNING", - /* 152 */ "INTO", - /* 153 */ "NOTHING", - /* 154 */ "FLOAT", - /* 155 */ "BLOB", - /* 156 */ "INTEGER", - /* 157 */ "VARIABLE", - /* 158 */ "CASE", - /* 159 */ "WHEN", - /* 160 */ "THEN", - /* 161 */ "ELSE", - /* 162 */ "INDEX", - /* 163 */ "ALTER", - /* 164 */ "ADD", - /* 165 */ "WINDOW", - /* 166 */ "OVER", - /* 167 */ "FILTER", - /* 168 */ "COLUMN", - /* 169 */ "AGG_FUNCTION", - /* 170 */ "AGG_COLUMN", - /* 171 */ "TRUEFALSE", - /* 172 */ "FUNCTION", - /* 173 */ "UPLUS", - /* 174 */ "UMINUS", - /* 175 */ "TRUTH", - /* 176 */ "REGISTER", - /* 177 */ "VECTOR", - /* 178 */ "SELECT_COLUMN", - /* 179 */ "IF_NULL_ROW", - /* 180 */ "ASTERISK", - /* 181 */ "SPAN", - /* 182 */ "ERROR", - /* 183 */ "QNUMBER", - /* 184 */ "SPACE", - /* 185 */ "COMMENT", - /* 186 */ "ILLEGAL", - /* 187 */ "input", - /* 188 */ "cmdlist", - /* 189 */ "ecmd", - /* 190 */ "cmdx", - /* 191 */ "explain", - /* 192 */ "cmd", - /* 193 */ "transtype", - /* 194 */ "trans_opt", - /* 195 */ "nm", - /* 196 */ "savepoint_opt", - /* 197 */ "create_table", - /* 198 */ "create_table_args", - /* 199 */ "createkw", - /* 200 */ "temp", - /* 201 */ "ifnotexists", - /* 202 */ "dbnm", - /* 203 */ "columnlist", - /* 204 */ "conslist_opt", - /* 205 */ "table_option_set", - /* 206 */ "select", - /* 207 */ "table_option", - /* 208 */ "columnname", - /* 209 */ "carglist", - /* 210 */ "typetoken", - /* 211 */ "typename", - /* 212 */ "signed", - /* 213 */ "plus_num", - /* 214 */ "minus_num", - /* 215 */ "scanpt", - /* 216 */ "scantok", - /* 217 */ "ccons", - /* 218 */ "term", - /* 219 */ "expr", - /* 220 */ "onconf", - /* 221 */ "sortorder", - /* 222 */ "autoinc", - /* 223 */ "eidlist_opt", - /* 224 */ "refargs", - /* 225 */ "defer_subclause", - /* 226 */ "generated", - /* 227 */ "refarg", - /* 228 */ "refact", - /* 229 */ "init_deferred_pred_opt", - /* 230 */ "conslist", - /* 231 */ "tconscomma", - /* 232 */ "tcons", - /* 233 */ "sortlist", - /* 234 */ "eidlist", - /* 235 */ "defer_subclause_opt", - /* 236 */ "orconf", - /* 237 */ "resolvetype", - /* 238 */ "raisetype", - /* 239 */ "ifexists", - /* 240 */ "fullname", - /* 241 */ "selectnowith", - /* 242 */ "oneselect", - /* 243 */ "wqlist", - /* 244 */ "multiselect_op", - /* 245 */ "distinct", - /* 246 */ "selcollist", - /* 247 */ "from", - /* 248 */ "where_opt", - /* 249 */ "groupby_opt", - /* 250 */ "having_opt", - /* 251 */ "orderby_opt", - /* 252 */ "limit_opt", - /* 253 */ "window_clause", - /* 254 */ "values", - /* 255 */ "nexprlist", - /* 256 */ "mvalues", - /* 257 */ "sclp", - /* 258 */ "as", - /* 259 */ "seltablist", - /* 260 */ "stl_prefix", - /* 261 */ "joinop", - /* 262 */ "on_using", - /* 263 */ "indexed_by", - /* 264 */ "exprlist", - /* 265 */ "xfullname", - /* 266 */ "idlist", - /* 267 */ "indexed_opt", - /* 268 */ "nulls", - /* 269 */ "with", - /* 270 */ "where_opt_ret", - /* 271 */ "setlist", - /* 272 */ "insert_cmd", - /* 273 */ "idlist_opt", - /* 274 */ "upsert", - /* 275 */ "returning", - /* 276 */ "filter_over", - /* 277 */ "likeop", - /* 278 */ "between_op", - /* 279 */ "in_op", - /* 280 */ "paren_exprlist", - /* 281 */ "case_operand", - /* 282 */ "case_exprlist", - /* 283 */ "case_else", - /* 284 */ "uniqueflag", - /* 285 */ "collate", - /* 286 */ "vinto", - /* 287 */ "nmnum", - /* 288 */ "trigger_decl", - /* 289 */ "trigger_cmd_list", - /* 290 */ "trigger_time", - /* 291 */ "trigger_event", - /* 292 */ "foreach_clause", - /* 293 */ "when_clause", - /* 294 */ "trigger_cmd", - /* 295 */ "trnm", - /* 296 */ "tridxby", - /* 297 */ "database_kw_opt", - /* 298 */ "key_opt", - /* 299 */ "add_column_fullname", - /* 300 */ "kwcolumn_opt", - /* 301 */ "create_vtab", - /* 302 */ "vtabarglist", - /* 303 */ "vtabarg", - /* 304 */ "vtabargtoken", - /* 305 */ "lp", - /* 306 */ "anylist", - /* 307 */ "wqitem", - /* 308 */ "wqas", - /* 309 */ "withnm", - /* 310 */ "windowdefn_list", - /* 311 */ "windowdefn", - /* 312 */ "window", - /* 313 */ "frame_opt", - /* 314 */ "part_opt", - /* 315 */ "filter_clause", - /* 316 */ "over_clause", - /* 317 */ "range_or_rows", - /* 318 */ "frame_bound", - /* 319 */ "frame_bound_s", - /* 320 */ "frame_bound_e", - /* 321 */ "frame_exclude_opt", - /* 322 */ "frame_exclude", -}; -#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ +static const char *const yyTokenName[] = { + "$", "SEMI", "EXPLAIN", "QUERY", + "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", + "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", + "ROLLBACK", "SAVEPOINT", "RELEASE", "TO", + "TABLE", "CREATE", "IF", "NOT", + "EXISTS", "TEMP", "LP", "RP", + "AS", "WITHOUT", "COMMA", "ID", + "ABORT", "ACTION", "AFTER", "ANALYZE", + "ASC", "ATTACH", "BEFORE", "BY", + "CASCADE", "CAST", "COLUMNKW", "CONFLICT", + "DATABASE", "DESC", "DETACH", "EACH", + "FAIL", "FOR", "IGNORE", "INITIALLY", + "INSTEAD", "LIKE_KW", "MATCH", "NO", + "KEY", "OF", "OFFSET", "PRAGMA", + "RAISE", "RECURSIVE", "REPLACE", "RESTRICT", + "ROW", "TRIGGER", "VACUUM", "VIEW", + "VIRTUAL", "WITH", "REINDEX", "RENAME", + "CTIME_KW", "ANY", "OR", "AND", + "IS", "BETWEEN", "IN", "ISNULL", + "NOTNULL", "NE", "EQ", "GT", + "LE", "LT", "GE", "ESCAPE", + "BITAND", "BITOR", "LSHIFT", "RSHIFT", + "PLUS", "MINUS", "STAR", "SLASH", + "REM", "CONCAT", "COLLATE", "BITNOT", + "INDEXED", "STRING", "JOIN_KW", "CONSTRAINT", + "DEFAULT", "NULL", "PRIMARY", "UNIQUE", + "CHECK", "REFERENCES", "AUTOINCR", "ON", + "INSERT", "DELETE", "UPDATE", "SET", + "DEFERRABLE", "FOREIGN", "DROP", "UNION", + "ALL", "EXCEPT", "INTERSECT", "SELECT", + "VALUES", "DISTINCT", "DOT", "FROM", + "JOIN", "USING", "ORDER", "GROUP", + "HAVING", "LIMIT", "WHERE", "INTO", + "FLOAT", "BLOB", "INTEGER", "VARIABLE", + "CASE", "WHEN", "THEN", "ELSE", + "INDEX", "ALTER", "ADD", "error", + "input", "cmdlist", "ecmd", "explain", + "cmdx", "cmd", "transtype", "trans_opt", + "nm", "savepoint_opt", "create_table", "create_table_args", + "createkw", "temp", "ifnotexists", "dbnm", + "columnlist", "conslist_opt", "table_options", "select", + "columnname", "carglist", "typetoken", "typename", + "signed", "plus_num", "minus_num", "ccons", + "term", "expr", "onconf", "sortorder", + "autoinc", "eidlist_opt", "refargs", "defer_subclause", + "refarg", "refact", "init_deferred_pred_opt", "conslist", + "tconscomma", "tcons", "sortlist", "eidlist", + "defer_subclause_opt", "orconf", "resolvetype", "raisetype", + "ifexists", "fullname", "selectnowith", "oneselect", + "with", "multiselect_op", "distinct", "selcollist", + "from", "where_opt", "groupby_opt", "having_opt", + "orderby_opt", "limit_opt", "values", "nexprlist", + "exprlist", "sclp", "as", "seltablist", + "stl_prefix", "joinop", "indexed_opt", "on_opt", + "using_opt", "idlist", "setlist", "insert_cmd", + "idlist_opt", "likeop", "between_op", "in_op", + "paren_exprlist", "case_operand", "case_exprlist", "case_else", + "uniqueflag", "collate", "nmnum", "trigger_decl", + "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", + "when_clause", "trigger_cmd", "trnm", "tridxby", + "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt", + "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", + "lp", "anylist", "wqlist", +}; +#endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *const yyRuleName[] = { @@ -176083,443 +137573,355 @@ /* 14 */ "createkw ::= CREATE", /* 15 */ "ifnotexists ::=", /* 16 */ "ifnotexists ::= IF NOT EXISTS", /* 17 */ "temp ::= TEMP", /* 18 */ "temp ::=", - /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_option_set", + /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_options", /* 20 */ "create_table_args ::= AS select", - /* 21 */ "table_option_set ::=", - /* 22 */ "table_option_set ::= table_option_set COMMA table_option", - /* 23 */ "table_option ::= WITHOUT nm", - /* 24 */ "table_option ::= nm", - /* 25 */ "columnname ::= nm typetoken", - /* 26 */ "typetoken ::=", - /* 27 */ "typetoken ::= typename LP signed RP", - /* 28 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 29 */ "typename ::= typename ID|STRING", - /* 30 */ "scanpt ::=", - /* 31 */ "scantok ::=", - /* 32 */ "ccons ::= CONSTRAINT nm", - /* 33 */ "ccons ::= DEFAULT scantok term", - /* 34 */ "ccons ::= DEFAULT LP expr RP", - /* 35 */ "ccons ::= DEFAULT PLUS scantok term", - /* 36 */ "ccons ::= DEFAULT MINUS scantok term", - /* 37 */ "ccons ::= DEFAULT scantok ID|INDEXED", - /* 38 */ "ccons ::= NOT NULL onconf", - /* 39 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 40 */ "ccons ::= UNIQUE onconf", - /* 41 */ "ccons ::= CHECK LP expr RP", - /* 42 */ "ccons ::= REFERENCES nm eidlist_opt refargs", - /* 43 */ "ccons ::= defer_subclause", - /* 44 */ "ccons ::= COLLATE ID|STRING", - /* 45 */ "generated ::= LP expr RP", - /* 46 */ "generated ::= LP expr RP ID", - /* 47 */ "autoinc ::=", - /* 48 */ "autoinc ::= AUTOINCR", - /* 49 */ "refargs ::=", - /* 50 */ "refargs ::= refargs refarg", - /* 51 */ "refarg ::= MATCH nm", - /* 52 */ "refarg ::= ON INSERT refact", - /* 53 */ "refarg ::= ON DELETE refact", - /* 54 */ "refarg ::= ON UPDATE refact", - /* 55 */ "refact ::= SET NULL", - /* 56 */ "refact ::= SET DEFAULT", - /* 57 */ "refact ::= CASCADE", - /* 58 */ "refact ::= RESTRICT", - /* 59 */ "refact ::= NO ACTION", - /* 60 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 61 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 62 */ "init_deferred_pred_opt ::=", - /* 63 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 64 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 65 */ "conslist_opt ::=", - /* 66 */ "tconscomma ::= COMMA", - /* 67 */ "tcons ::= CONSTRAINT nm", - /* 68 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", - /* 69 */ "tcons ::= UNIQUE LP sortlist RP onconf", - /* 70 */ "tcons ::= CHECK LP expr RP onconf", - /* 71 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", - /* 72 */ "defer_subclause_opt ::=", - /* 73 */ "onconf ::=", - /* 74 */ "onconf ::= ON CONFLICT resolvetype", - /* 75 */ "orconf ::=", - /* 76 */ "orconf ::= OR resolvetype", - /* 77 */ "resolvetype ::= IGNORE", - /* 78 */ "resolvetype ::= REPLACE", - /* 79 */ "cmd ::= DROP TABLE ifexists fullname", - /* 80 */ "ifexists ::= IF EXISTS", - /* 81 */ "ifexists ::=", - /* 82 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", - /* 83 */ "cmd ::= DROP VIEW ifexists fullname", - /* 84 */ "cmd ::= select", - /* 85 */ "select ::= WITH wqlist selectnowith", - /* 86 */ "select ::= WITH RECURSIVE wqlist selectnowith", - /* 87 */ "select ::= selectnowith", - /* 88 */ "selectnowith ::= selectnowith multiselect_op oneselect", - /* 89 */ "multiselect_op ::= UNION", - /* 90 */ "multiselect_op ::= UNION ALL", - /* 91 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 92 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 93 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt", - /* 94 */ "values ::= VALUES LP nexprlist RP", - /* 95 */ "oneselect ::= mvalues", - /* 96 */ "mvalues ::= values COMMA LP nexprlist RP", - /* 97 */ "mvalues ::= mvalues COMMA LP nexprlist RP", - /* 98 */ "distinct ::= DISTINCT", - /* 99 */ "distinct ::= ALL", - /* 100 */ "distinct ::=", - /* 101 */ "sclp ::=", - /* 102 */ "selcollist ::= sclp scanpt expr scanpt as", - /* 103 */ "selcollist ::= sclp scanpt STAR", - /* 104 */ "selcollist ::= sclp scanpt nm DOT STAR", - /* 105 */ "as ::= AS nm", - /* 106 */ "as ::=", - /* 107 */ "from ::=", - /* 108 */ "from ::= FROM seltablist", - /* 109 */ "stl_prefix ::= seltablist joinop", - /* 110 */ "stl_prefix ::=", - /* 111 */ "seltablist ::= stl_prefix nm dbnm as on_using", - /* 112 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", - /* 113 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", - /* 114 */ "seltablist ::= stl_prefix LP select RP as on_using", - /* 115 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", - /* 116 */ "dbnm ::=", - /* 117 */ "dbnm ::= DOT nm", - /* 118 */ "fullname ::= nm", - /* 119 */ "fullname ::= nm DOT nm", - /* 120 */ "xfullname ::= nm", - /* 121 */ "xfullname ::= nm DOT nm", - /* 122 */ "xfullname ::= nm DOT nm AS nm", - /* 123 */ "xfullname ::= nm AS nm", - /* 124 */ "joinop ::= COMMA|JOIN", - /* 125 */ "joinop ::= JOIN_KW JOIN", - /* 126 */ "joinop ::= JOIN_KW nm JOIN", - /* 127 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 128 */ "on_using ::= ON expr", - /* 129 */ "on_using ::= USING LP idlist RP", - /* 130 */ "on_using ::=", - /* 131 */ "indexed_opt ::=", - /* 132 */ "indexed_by ::= INDEXED BY nm", - /* 133 */ "indexed_by ::= NOT INDEXED", - /* 134 */ "orderby_opt ::=", - /* 135 */ "orderby_opt ::= ORDER BY sortlist", - /* 136 */ "sortlist ::= sortlist COMMA expr sortorder nulls", - /* 137 */ "sortlist ::= expr sortorder nulls", - /* 138 */ "sortorder ::= ASC", - /* 139 */ "sortorder ::= DESC", - /* 140 */ "sortorder ::=", - /* 141 */ "nulls ::= NULLS FIRST", - /* 142 */ "nulls ::= NULLS LAST", - /* 143 */ "nulls ::=", - /* 144 */ "groupby_opt ::=", - /* 145 */ "groupby_opt ::= GROUP BY nexprlist", - /* 146 */ "having_opt ::=", - /* 147 */ "having_opt ::= HAVING expr", - /* 148 */ "limit_opt ::=", - /* 149 */ "limit_opt ::= LIMIT expr", - /* 150 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 151 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 152 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret", - /* 153 */ "where_opt ::=", - /* 154 */ "where_opt ::= WHERE expr", - /* 155 */ "where_opt_ret ::=", - /* 156 */ "where_opt_ret ::= WHERE expr", - /* 157 */ "where_opt_ret ::= RETURNING selcollist", - /* 158 */ "where_opt_ret ::= WHERE expr RETURNING selcollist", - /* 159 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret", - /* 160 */ "setlist ::= setlist COMMA nm EQ expr", - /* 161 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 162 */ "setlist ::= nm EQ expr", - /* 163 */ "setlist ::= LP idlist RP EQ expr", - /* 164 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", - /* 165 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning", - /* 166 */ "upsert ::=", - /* 167 */ "upsert ::= RETURNING selcollist", - /* 168 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert", - /* 169 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert", - /* 170 */ "upsert ::= ON CONFLICT DO NOTHING returning", - /* 171 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning", - /* 172 */ "returning ::= RETURNING selcollist", - /* 173 */ "insert_cmd ::= INSERT orconf", - /* 174 */ "insert_cmd ::= REPLACE", - /* 175 */ "idlist_opt ::=", - /* 176 */ "idlist_opt ::= LP idlist RP", - /* 177 */ "idlist ::= idlist COMMA nm", - /* 178 */ "idlist ::= nm", - /* 179 */ "expr ::= LP expr RP", - /* 180 */ "expr ::= ID|INDEXED|JOIN_KW", - /* 181 */ "expr ::= nm DOT nm", - /* 182 */ "expr ::= nm DOT nm DOT nm", - /* 183 */ "term ::= NULL|FLOAT|BLOB", - /* 184 */ "term ::= STRING", - /* 185 */ "term ::= INTEGER", - /* 186 */ "expr ::= VARIABLE", - /* 187 */ "expr ::= expr COLLATE ID|STRING", - /* 188 */ "expr ::= CAST LP expr AS typetoken RP", - /* 189 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP", - /* 190 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP", - /* 191 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP", - /* 192 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over", - /* 193 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over", - /* 194 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over", - /* 195 */ "term ::= CTIME_KW", - /* 196 */ "expr ::= LP nexprlist COMMA expr RP", - /* 197 */ "expr ::= expr AND expr", - /* 198 */ "expr ::= expr OR expr", - /* 199 */ "expr ::= expr LT|GT|GE|LE expr", - /* 200 */ "expr ::= expr EQ|NE expr", - /* 201 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 202 */ "expr ::= expr PLUS|MINUS expr", - /* 203 */ "expr ::= expr STAR|SLASH|REM expr", - /* 204 */ "expr ::= expr CONCAT expr", - /* 205 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 206 */ "expr ::= expr likeop expr", - /* 207 */ "expr ::= expr likeop expr ESCAPE expr", - /* 208 */ "expr ::= expr ISNULL|NOTNULL", - /* 209 */ "expr ::= expr NOT NULL", - /* 210 */ "expr ::= expr IS expr", - /* 211 */ "expr ::= expr IS NOT expr", - /* 212 */ "expr ::= expr IS NOT DISTINCT FROM expr", - /* 213 */ "expr ::= expr IS DISTINCT FROM expr", - /* 214 */ "expr ::= NOT expr", - /* 215 */ "expr ::= BITNOT expr", - /* 216 */ "expr ::= PLUS|MINUS expr", - /* 217 */ "expr ::= expr PTR expr", - /* 218 */ "between_op ::= BETWEEN", - /* 219 */ "between_op ::= NOT BETWEEN", - /* 220 */ "expr ::= expr between_op expr AND expr", - /* 221 */ "in_op ::= IN", - /* 222 */ "in_op ::= NOT IN", - /* 223 */ "expr ::= expr in_op LP exprlist RP", - /* 224 */ "expr ::= LP select RP", - /* 225 */ "expr ::= expr in_op LP select RP", - /* 226 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 227 */ "expr ::= EXISTS LP select RP", - /* 228 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 229 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 230 */ "case_exprlist ::= WHEN expr THEN expr", - /* 231 */ "case_else ::= ELSE expr", - /* 232 */ "case_else ::=", - /* 233 */ "case_operand ::=", - /* 234 */ "exprlist ::=", - /* 235 */ "nexprlist ::= nexprlist COMMA expr", - /* 236 */ "nexprlist ::= expr", - /* 237 */ "paren_exprlist ::=", - /* 238 */ "paren_exprlist ::= LP exprlist RP", - /* 239 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 240 */ "uniqueflag ::= UNIQUE", - /* 241 */ "uniqueflag ::=", - /* 242 */ "eidlist_opt ::=", - /* 243 */ "eidlist_opt ::= LP eidlist RP", - /* 244 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 245 */ "eidlist ::= nm collate sortorder", - /* 246 */ "collate ::=", - /* 247 */ "collate ::= COLLATE ID|STRING", - /* 248 */ "cmd ::= DROP INDEX ifexists fullname", - /* 249 */ "cmd ::= VACUUM vinto", - /* 250 */ "cmd ::= VACUUM nm vinto", - /* 251 */ "vinto ::= INTO expr", - /* 252 */ "vinto ::=", - /* 253 */ "cmd ::= PRAGMA nm dbnm", - /* 254 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 255 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 256 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 257 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 258 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 259 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 260 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 262 */ "trigger_time ::= BEFORE|AFTER", - /* 263 */ "trigger_time ::= INSTEAD OF", - /* 264 */ "trigger_time ::=", - /* 265 */ "trigger_event ::= DELETE|INSERT", - /* 266 */ "trigger_event ::= UPDATE", - /* 267 */ "trigger_event ::= UPDATE OF idlist", - /* 268 */ "when_clause ::=", - /* 269 */ "when_clause ::= WHEN expr", - /* 270 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 271 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 272 */ "trnm ::= nm DOT nm", - /* 273 */ "tridxby ::= INDEXED BY nm", - /* 274 */ "tridxby ::= NOT INDEXED", - /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", - /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", - /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", - /* 278 */ "trigger_cmd ::= scanpt select scanpt", - /* 279 */ "expr ::= RAISE LP IGNORE RP", - /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP", - /* 281 */ "raisetype ::= ROLLBACK", - /* 282 */ "raisetype ::= ABORT", - /* 283 */ "raisetype ::= FAIL", - /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 286 */ "cmd ::= DETACH database_kw_opt expr", - /* 287 */ "key_opt ::=", - /* 288 */ "key_opt ::= KEY expr", - /* 289 */ "cmd ::= REINDEX", - /* 290 */ "cmd ::= REINDEX nm dbnm", - /* 291 */ "cmd ::= ANALYZE", - /* 292 */ "cmd ::= ANALYZE nm dbnm", - /* 293 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 294 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 295 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 296 */ "add_column_fullname ::= fullname", - /* 297 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 298 */ "cmd ::= create_vtab", - /* 299 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 300 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 301 */ "vtabarg ::=", - /* 302 */ "vtabargtoken ::= ANY", - /* 303 */ "vtabargtoken ::= lp anylist RP", - /* 304 */ "lp ::= LP", - /* 305 */ "with ::= WITH wqlist", - /* 306 */ "with ::= WITH RECURSIVE wqlist", - /* 307 */ "wqas ::= AS", - /* 308 */ "wqas ::= AS MATERIALIZED", - /* 309 */ "wqas ::= AS NOT MATERIALIZED", - /* 310 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", - /* 311 */ "withnm ::= nm", - /* 312 */ "wqlist ::= wqitem", - /* 313 */ "wqlist ::= wqlist COMMA wqitem", - /* 314 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 315 */ "windowdefn ::= nm AS LP window RP", - /* 316 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 317 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 318 */ "window ::= ORDER BY sortlist frame_opt", - /* 319 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 320 */ "window ::= nm frame_opt", - /* 321 */ "frame_opt ::=", - /* 322 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 323 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 324 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 325 */ "frame_bound_s ::= frame_bound", - /* 326 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 327 */ "frame_bound_e ::= frame_bound", - /* 328 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 329 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 330 */ "frame_bound ::= CURRENT ROW", - /* 331 */ "frame_exclude_opt ::=", - /* 332 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 333 */ "frame_exclude ::= NO OTHERS", - /* 334 */ "frame_exclude ::= CURRENT ROW", - /* 335 */ "frame_exclude ::= GROUP|TIES", - /* 336 */ "window_clause ::= WINDOW windowdefn_list", - /* 337 */ "filter_over ::= filter_clause over_clause", - /* 338 */ "filter_over ::= over_clause", - /* 339 */ "filter_over ::= filter_clause", - /* 340 */ "over_clause ::= OVER LP window RP", - /* 341 */ "over_clause ::= OVER nm", - /* 342 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 343 */ "term ::= QNUMBER", - /* 344 */ "input ::= cmdlist", - /* 345 */ "cmdlist ::= cmdlist ecmd", - /* 346 */ "cmdlist ::= ecmd", - /* 347 */ "ecmd ::= SEMI", - /* 348 */ "ecmd ::= cmdx SEMI", - /* 349 */ "ecmd ::= explain cmdx SEMI", - /* 350 */ "trans_opt ::=", - /* 351 */ "trans_opt ::= TRANSACTION", - /* 352 */ "trans_opt ::= TRANSACTION nm", - /* 353 */ "savepoint_opt ::= SAVEPOINT", - /* 354 */ "savepoint_opt ::=", - /* 355 */ "cmd ::= create_table create_table_args", - /* 356 */ "table_option_set ::= table_option", - /* 357 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 358 */ "columnlist ::= columnname carglist", - /* 359 */ "nm ::= ID|INDEXED|JOIN_KW", - /* 360 */ "nm ::= STRING", - /* 361 */ "typetoken ::= typename", - /* 362 */ "typename ::= ID|STRING", - /* 363 */ "signed ::= plus_num", - /* 364 */ "signed ::= minus_num", - /* 365 */ "carglist ::= carglist ccons", - /* 366 */ "carglist ::=", - /* 367 */ "ccons ::= NULL onconf", - /* 368 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 369 */ "ccons ::= AS generated", - /* 370 */ "conslist_opt ::= COMMA conslist", - /* 371 */ "conslist ::= conslist tconscomma tcons", - /* 372 */ "conslist ::= tcons", - /* 373 */ "tconscomma ::=", - /* 374 */ "defer_subclause_opt ::= defer_subclause", - /* 375 */ "resolvetype ::= raisetype", - /* 376 */ "selectnowith ::= oneselect", - /* 377 */ "oneselect ::= values", - /* 378 */ "sclp ::= selcollist COMMA", - /* 379 */ "as ::= ID|STRING", - /* 380 */ "indexed_opt ::= indexed_by", - /* 381 */ "returning ::=", - /* 382 */ "expr ::= term", - /* 383 */ "likeop ::= LIKE_KW|MATCH", - /* 384 */ "case_operand ::= expr", - /* 385 */ "exprlist ::= nexprlist", - /* 386 */ "nmnum ::= plus_num", - /* 387 */ "nmnum ::= nm", - /* 388 */ "nmnum ::= ON", - /* 389 */ "nmnum ::= DELETE", - /* 390 */ "nmnum ::= DEFAULT", - /* 391 */ "plus_num ::= INTEGER|FLOAT", - /* 392 */ "foreach_clause ::=", - /* 393 */ "foreach_clause ::= FOR EACH ROW", - /* 394 */ "trnm ::= nm", - /* 395 */ "tridxby ::=", - /* 396 */ "database_kw_opt ::= DATABASE", - /* 397 */ "database_kw_opt ::=", - /* 398 */ "kwcolumn_opt ::=", - /* 399 */ "kwcolumn_opt ::= COLUMNKW", - /* 400 */ "vtabarglist ::= vtabarg", - /* 401 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 402 */ "vtabarg ::= vtabarg vtabargtoken", - /* 403 */ "anylist ::=", - /* 404 */ "anylist ::= anylist LP anylist RP", - /* 405 */ "anylist ::= anylist ANY", - /* 406 */ "with ::=", - /* 407 */ "windowdefn_list ::= windowdefn", - /* 408 */ "window ::= frame_opt", + /* 21 */ "table_options ::=", + /* 22 */ "table_options ::= WITHOUT nm", + /* 23 */ "columnname ::= nm typetoken", + /* 24 */ "typetoken ::=", + /* 25 */ "typetoken ::= typename LP signed RP", + /* 26 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 27 */ "typename ::= typename ID|STRING", + /* 28 */ "ccons ::= CONSTRAINT nm", + /* 29 */ "ccons ::= DEFAULT term", + /* 30 */ "ccons ::= DEFAULT LP expr RP", + /* 31 */ "ccons ::= DEFAULT PLUS term", + /* 32 */ "ccons ::= DEFAULT MINUS term", + /* 33 */ "ccons ::= DEFAULT ID|INDEXED", + /* 34 */ "ccons ::= NOT NULL onconf", + /* 35 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 36 */ "ccons ::= UNIQUE onconf", + /* 37 */ "ccons ::= CHECK LP expr RP", + /* 38 */ "ccons ::= REFERENCES nm eidlist_opt refargs", + /* 39 */ "ccons ::= defer_subclause", + /* 40 */ "ccons ::= COLLATE ID|STRING", + /* 41 */ "autoinc ::=", + /* 42 */ "autoinc ::= AUTOINCR", + /* 43 */ "refargs ::=", + /* 44 */ "refargs ::= refargs refarg", + /* 45 */ "refarg ::= MATCH nm", + /* 46 */ "refarg ::= ON INSERT refact", + /* 47 */ "refarg ::= ON DELETE refact", + /* 48 */ "refarg ::= ON UPDATE refact", + /* 49 */ "refact ::= SET NULL", + /* 50 */ "refact ::= SET DEFAULT", + /* 51 */ "refact ::= CASCADE", + /* 52 */ "refact ::= RESTRICT", + /* 53 */ "refact ::= NO ACTION", + /* 54 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 55 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 56 */ "init_deferred_pred_opt ::=", + /* 57 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 58 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 59 */ "conslist_opt ::=", + /* 60 */ "tconscomma ::= COMMA", + /* 61 */ "tcons ::= CONSTRAINT nm", + /* 62 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", + /* 63 */ "tcons ::= UNIQUE LP sortlist RP onconf", + /* 64 */ "tcons ::= CHECK LP expr RP onconf", + /* 65 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", + /* 66 */ "defer_subclause_opt ::=", + /* 67 */ "onconf ::=", + /* 68 */ "onconf ::= ON CONFLICT resolvetype", + /* 69 */ "orconf ::=", + /* 70 */ "orconf ::= OR resolvetype", + /* 71 */ "resolvetype ::= IGNORE", + /* 72 */ "resolvetype ::= REPLACE", + /* 73 */ "cmd ::= DROP TABLE ifexists fullname", + /* 74 */ "ifexists ::= IF EXISTS", + /* 75 */ "ifexists ::=", + /* 76 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", + /* 77 */ "cmd ::= DROP VIEW ifexists fullname", + /* 78 */ "cmd ::= select", + /* 79 */ "select ::= with selectnowith", + /* 80 */ "selectnowith ::= selectnowith multiselect_op oneselect", + /* 81 */ "multiselect_op ::= UNION", + /* 82 */ "multiselect_op ::= UNION ALL", + /* 83 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 84 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 85 */ "values ::= VALUES LP nexprlist RP", + /* 86 */ "values ::= values COMMA LP exprlist RP", + /* 87 */ "distinct ::= DISTINCT", + /* 88 */ "distinct ::= ALL", + /* 89 */ "distinct ::=", + /* 90 */ "sclp ::=", + /* 91 */ "selcollist ::= sclp expr as", + /* 92 */ "selcollist ::= sclp STAR", + /* 93 */ "selcollist ::= sclp nm DOT STAR", + /* 94 */ "as ::= AS nm", + /* 95 */ "as ::=", + /* 96 */ "from ::=", + /* 97 */ "from ::= FROM seltablist", + /* 98 */ "stl_prefix ::= seltablist joinop", + /* 99 */ "stl_prefix ::=", + /* 100 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", + /* 101 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", + /* 102 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", + /* 103 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", + /* 104 */ "dbnm ::=", + /* 105 */ "dbnm ::= DOT nm", + /* 106 */ "fullname ::= nm dbnm", + /* 107 */ "joinop ::= COMMA|JOIN", + /* 108 */ "joinop ::= JOIN_KW JOIN", + /* 109 */ "joinop ::= JOIN_KW nm JOIN", + /* 110 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 111 */ "on_opt ::= ON expr", + /* 112 */ "on_opt ::=", + /* 113 */ "indexed_opt ::=", + /* 114 */ "indexed_opt ::= INDEXED BY nm", + /* 115 */ "indexed_opt ::= NOT INDEXED", + /* 116 */ "using_opt ::= USING LP idlist RP", + /* 117 */ "using_opt ::=", + /* 118 */ "orderby_opt ::=", + /* 119 */ "orderby_opt ::= ORDER BY sortlist", + /* 120 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 121 */ "sortlist ::= expr sortorder", + /* 122 */ "sortorder ::= ASC", + /* 123 */ "sortorder ::= DESC", + /* 124 */ "sortorder ::=", + /* 125 */ "groupby_opt ::=", + /* 126 */ "groupby_opt ::= GROUP BY nexprlist", + /* 127 */ "having_opt ::=", + /* 128 */ "having_opt ::= HAVING expr", + /* 129 */ "limit_opt ::=", + /* 130 */ "limit_opt ::= LIMIT expr", + /* 131 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 132 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 133 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", + /* 134 */ "where_opt ::=", + /* 135 */ "where_opt ::= WHERE expr", + /* 136 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", + /* 137 */ "setlist ::= setlist COMMA nm EQ expr", + /* 138 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 139 */ "setlist ::= nm EQ expr", + /* 140 */ "setlist ::= LP idlist RP EQ expr", + /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", + /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", + /* 143 */ "insert_cmd ::= INSERT orconf", + /* 144 */ "insert_cmd ::= REPLACE", + /* 145 */ "idlist_opt ::=", + /* 146 */ "idlist_opt ::= LP idlist RP", + /* 147 */ "idlist ::= idlist COMMA nm", + /* 148 */ "idlist ::= nm", + /* 149 */ "expr ::= LP expr RP", + /* 150 */ "expr ::= ID|INDEXED", + /* 151 */ "expr ::= JOIN_KW", + /* 152 */ "expr ::= nm DOT nm", + /* 153 */ "expr ::= nm DOT nm DOT nm", + /* 154 */ "term ::= NULL|FLOAT|BLOB", + /* 155 */ "term ::= STRING", + /* 156 */ "term ::= INTEGER", + /* 157 */ "expr ::= VARIABLE", + /* 158 */ "expr ::= expr COLLATE ID|STRING", + /* 159 */ "expr ::= CAST LP expr AS typetoken RP", + /* 160 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 161 */ "expr ::= ID|INDEXED LP STAR RP", + /* 162 */ "term ::= CTIME_KW", + /* 163 */ "expr ::= LP nexprlist COMMA expr RP", + /* 164 */ "expr ::= expr AND expr", + /* 165 */ "expr ::= expr OR expr", + /* 166 */ "expr ::= expr LT|GT|GE|LE expr", + /* 167 */ "expr ::= expr EQ|NE expr", + /* 168 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 169 */ "expr ::= expr PLUS|MINUS expr", + /* 170 */ "expr ::= expr STAR|SLASH|REM expr", + /* 171 */ "expr ::= expr CONCAT expr", + /* 172 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 173 */ "expr ::= expr likeop expr", + /* 174 */ "expr ::= expr likeop expr ESCAPE expr", + /* 175 */ "expr ::= expr ISNULL|NOTNULL", + /* 176 */ "expr ::= expr NOT NULL", + /* 177 */ "expr ::= expr IS expr", + /* 178 */ "expr ::= expr IS NOT expr", + /* 179 */ "expr ::= NOT expr", + /* 180 */ "expr ::= BITNOT expr", + /* 181 */ "expr ::= MINUS expr", + /* 182 */ "expr ::= PLUS expr", + /* 183 */ "between_op ::= BETWEEN", + /* 184 */ "between_op ::= NOT BETWEEN", + /* 185 */ "expr ::= expr between_op expr AND expr", + /* 186 */ "in_op ::= IN", + /* 187 */ "in_op ::= NOT IN", + /* 188 */ "expr ::= expr in_op LP exprlist RP", + /* 189 */ "expr ::= LP select RP", + /* 190 */ "expr ::= expr in_op LP select RP", + /* 191 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 192 */ "expr ::= EXISTS LP select RP", + /* 193 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 194 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 195 */ "case_exprlist ::= WHEN expr THEN expr", + /* 196 */ "case_else ::= ELSE expr", + /* 197 */ "case_else ::=", + /* 198 */ "case_operand ::= expr", + /* 199 */ "case_operand ::=", + /* 200 */ "exprlist ::=", + /* 201 */ "nexprlist ::= nexprlist COMMA expr", + /* 202 */ "nexprlist ::= expr", + /* 203 */ "paren_exprlist ::=", + /* 204 */ "paren_exprlist ::= LP exprlist RP", + /* 205 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 206 */ "uniqueflag ::= UNIQUE", + /* 207 */ "uniqueflag ::=", + /* 208 */ "eidlist_opt ::=", + /* 209 */ "eidlist_opt ::= LP eidlist RP", + /* 210 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 211 */ "eidlist ::= nm collate sortorder", + /* 212 */ "collate ::=", + /* 213 */ "collate ::= COLLATE ID|STRING", + /* 214 */ "cmd ::= DROP INDEX ifexists fullname", + /* 215 */ "cmd ::= VACUUM", + /* 216 */ "cmd ::= VACUUM nm", + /* 217 */ "cmd ::= PRAGMA nm dbnm", + /* 218 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 219 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 220 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 221 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 222 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 223 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 224 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 225 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 226 */ "trigger_time ::= BEFORE|AFTER", + /* 227 */ "trigger_time ::= INSTEAD OF", + /* 228 */ "trigger_time ::=", + /* 229 */ "trigger_event ::= DELETE|INSERT", + /* 230 */ "trigger_event ::= UPDATE", + /* 231 */ "trigger_event ::= UPDATE OF idlist", + /* 232 */ "when_clause ::=", + /* 233 */ "when_clause ::= WHEN expr", + /* 234 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 235 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 236 */ "trnm ::= nm DOT nm", + /* 237 */ "tridxby ::= INDEXED BY nm", + /* 238 */ "tridxby ::= NOT INDEXED", + /* 239 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 240 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", + /* 241 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 242 */ "trigger_cmd ::= select", + /* 243 */ "expr ::= RAISE LP IGNORE RP", + /* 244 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 245 */ "raisetype ::= ROLLBACK", + /* 246 */ "raisetype ::= ABORT", + /* 247 */ "raisetype ::= FAIL", + /* 248 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 249 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 250 */ "cmd ::= DETACH database_kw_opt expr", + /* 251 */ "key_opt ::=", + /* 252 */ "key_opt ::= KEY expr", + /* 253 */ "cmd ::= REINDEX", + /* 254 */ "cmd ::= REINDEX nm dbnm", + /* 255 */ "cmd ::= ANALYZE", + /* 256 */ "cmd ::= ANALYZE nm dbnm", + /* 257 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 258 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 259 */ "add_column_fullname ::= fullname", + /* 260 */ "cmd ::= create_vtab", + /* 261 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 262 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 263 */ "vtabarg ::=", + /* 264 */ "vtabargtoken ::= ANY", + /* 265 */ "vtabargtoken ::= lp anylist RP", + /* 266 */ "lp ::= LP", + /* 267 */ "with ::=", + /* 268 */ "with ::= WITH wqlist", + /* 269 */ "with ::= WITH RECURSIVE wqlist", + /* 270 */ "wqlist ::= nm eidlist_opt AS LP select RP", + /* 271 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 272 */ "input ::= cmdlist", + /* 273 */ "cmdlist ::= cmdlist ecmd", + /* 274 */ "cmdlist ::= ecmd", + /* 275 */ "ecmd ::= SEMI", + /* 276 */ "ecmd ::= explain cmdx SEMI", + /* 277 */ "explain ::=", + /* 278 */ "trans_opt ::=", + /* 279 */ "trans_opt ::= TRANSACTION", + /* 280 */ "trans_opt ::= TRANSACTION nm", + /* 281 */ "savepoint_opt ::= SAVEPOINT", + /* 282 */ "savepoint_opt ::=", + /* 283 */ "cmd ::= create_table create_table_args", + /* 284 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 285 */ "columnlist ::= columnname carglist", + /* 286 */ "nm ::= ID|INDEXED", + /* 287 */ "nm ::= STRING", + /* 288 */ "nm ::= JOIN_KW", + /* 289 */ "typetoken ::= typename", + /* 290 */ "typename ::= ID|STRING", + /* 291 */ "signed ::= plus_num", + /* 292 */ "signed ::= minus_num", + /* 293 */ "carglist ::= carglist ccons", + /* 294 */ "carglist ::=", + /* 295 */ "ccons ::= NULL onconf", + /* 296 */ "conslist_opt ::= COMMA conslist", + /* 297 */ "conslist ::= conslist tconscomma tcons", + /* 298 */ "conslist ::= tcons", + /* 299 */ "tconscomma ::=", + /* 300 */ "defer_subclause_opt ::= defer_subclause", + /* 301 */ "resolvetype ::= raisetype", + /* 302 */ "selectnowith ::= oneselect", + /* 303 */ "oneselect ::= values", + /* 304 */ "sclp ::= selcollist COMMA", + /* 305 */ "as ::= ID|STRING", + /* 306 */ "expr ::= term", + /* 307 */ "likeop ::= LIKE_KW|MATCH", + /* 308 */ "exprlist ::= nexprlist", + /* 309 */ "nmnum ::= plus_num", + /* 310 */ "nmnum ::= nm", + /* 311 */ "nmnum ::= ON", + /* 312 */ "nmnum ::= DELETE", + /* 313 */ "nmnum ::= DEFAULT", + /* 314 */ "plus_num ::= INTEGER|FLOAT", + /* 315 */ "foreach_clause ::=", + /* 316 */ "foreach_clause ::= FOR EACH ROW", + /* 317 */ "trnm ::= nm", + /* 318 */ "tridxby ::=", + /* 319 */ "database_kw_opt ::= DATABASE", + /* 320 */ "database_kw_opt ::=", + /* 321 */ "kwcolumn_opt ::=", + /* 322 */ "kwcolumn_opt ::= COLUMNKW", + /* 323 */ "vtabarglist ::= vtabarg", + /* 324 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 325 */ "vtabarg ::= vtabarg vtabargtoken", + /* 326 */ "anylist ::=", + /* 327 */ "anylist ::= anylist LP anylist RP", + /* 328 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ -#if YYGROWABLESTACK +#if YYSTACKDEPTH<=0 /* ** Try to increase the size of the parser stack. Return the number ** of errors. Return 0 on success. */ static int yyGrowStack(yyParser *p){ - int oldSize = 1 + (int)(p->yystackEnd - p->yystack); int newSize; int idx; yyStackEntry *pNew; - newSize = oldSize*2 + 100; - idx = (int)(p->yytos - p->yystack); - if( p->yystack==p->yystk0 ){ - pNew = YYREALLOC(0, newSize*sizeof(pNew[0])); - if( pNew==0 ) return 1; - memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0])); + newSize = p->yystksz*2 + 100; + idx = p->yytos ? (int)(p->yytos - p->yystack) : 0; + if( p->yystack==&p->yystk0 ){ + pNew = malloc(newSize*sizeof(pNew[0])); + if( pNew ) pNew[0] = p->yystk0; }else{ - pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0])); - if( pNew==0 ) return 1; + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); } - p->yystack = pNew; - p->yytos = &p->yystack[idx]; + if( pNew ){ + p->yystack = pNew; + p->yytos = &p->yystack[idx]; #ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", - yyTracePrompt, oldSize, newSize); - } -#endif - p->yystackEnd = &p->yystack[newSize-1]; - return 0; -} -#endif /* YYGROWABLESTACK */ - -#if !YYGROWABLESTACK -/* For builds that do no have a growable stack, yyGrowStack always -** returns an error. -*/ -# define yyGrowStack(X) 1 + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", + yyTracePrompt, p->yystksz, newSize); + } +#endif + p->yystksz = newSize; + } + return pNew==0; +} #endif /* Datatype of the argument to the memory allocated passed as the ** second argument to sqlite3ParserAlloc() below. This can be changed by ** putting an appropriate #define in the %include section of the input @@ -176529,28 +137931,37 @@ # define YYMALLOCARGTYPE size_t #endif /* Initialize a new parser that has already been allocated. */ -SQLITE_PRIVATE void sqlite3ParserInit(void *yypRawParser sqlite3ParserCTX_PDECL){ - yyParser *yypParser = (yyParser*)yypRawParser; - sqlite3ParserCTX_STORE +SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ + yyParser *pParser = (yyParser*)yypParser; #ifdef YYTRACKMAXSTACKDEPTH - yypParser->yyhwm = 0; + pParser->yyhwm = 0; #endif - yypParser->yystack = yypParser->yystk0; - yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; +#if YYSTACKDEPTH<=0 + pParser->yytos = NULL; + pParser->yystack = NULL; + pParser->yystksz = 0; + if( yyGrowStack(pParser) ){ + pParser->yystack = &pParser->yystk0; + pParser->yystksz = 1; + } +#endif #ifndef YYNOERRORRECOVERY - yypParser->yyerrcnt = -1; + pParser->yyerrcnt = -1; #endif - yypParser->yytos = yypParser->yystack; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; + pParser->yytos = pParser->yystack; + pParser->yystack[0].stateno = 0; + pParser->yystack[0].major = 0; +#if YYSTACKDEPTH>0 + pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; +#endif } #ifndef sqlite3Parser_ENGINEALWAYSONSTACK -/* +/* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** ** Inputs: @@ -176558,140 +137969,115 @@ ** ** Outputs: ** A pointer to a parser. This pointer is used in subsequent calls ** to sqlite3Parser and sqlite3ParserFree. */ -SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) sqlite3ParserCTX_PDECL){ - yyParser *yypParser; - yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( yypParser ){ - sqlite3ParserCTX_STORE - sqlite3ParserInit(yypParser sqlite3ParserCTX_PARAM); - } - return (void*)yypParser; +SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ + yyParser *pParser; + pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + if( pParser ) sqlite3ParserInit(pParser); + return pParser; } #endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ /* The following function deletes the "minor type" or semantic value ** associated with a symbol. The symbol can be either a terminal ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is -** a pointer to the value to be deleted. The code used to do the +** a pointer to the value to be deleted. The code used to do the ** deletions is derived from the %destructor and/or %token_destructor ** directives of the input grammar. */ static void yy_destructor( yyParser *yypParser, /* The parser */ YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH + sqlite3ParserARG_FETCH; switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is + ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 206: /* select */ - case 241: /* selectnowith */ - case 242: /* oneselect */ - case 254: /* values */ - case 256: /* mvalues */ -{ -sqlite3SelectDelete(pParse->db, (yypminor->yy637)); -} - break; - case 218: /* term */ - case 219: /* expr */ - case 248: /* where_opt */ - case 250: /* having_opt */ - case 270: /* where_opt_ret */ - case 281: /* case_operand */ - case 283: /* case_else */ - case 286: /* vinto */ - case 293: /* when_clause */ - case 298: /* key_opt */ - case 315: /* filter_clause */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy590)); -} - break; - case 223: /* eidlist_opt */ - case 233: /* sortlist */ - case 234: /* eidlist */ - case 246: /* selcollist */ - case 249: /* groupby_opt */ - case 251: /* orderby_opt */ - case 255: /* nexprlist */ - case 257: /* sclp */ - case 264: /* exprlist */ - case 271: /* setlist */ - case 280: /* paren_exprlist */ - case 282: /* case_exprlist */ - case 314: /* part_opt */ -{ -sqlite3ExprListDelete(pParse->db, (yypminor->yy402)); -} - break; - case 240: /* fullname */ - case 247: /* from */ - case 259: /* seltablist */ - case 260: /* stl_prefix */ - case 265: /* xfullname */ -{ -sqlite3SrcListDelete(pParse->db, (yypminor->yy563)); -} - break; - case 243: /* wqlist */ -{ -sqlite3WithDelete(pParse->db, (yypminor->yy125)); -} - break; - case 253: /* window_clause */ - case 310: /* windowdefn_list */ -{ -sqlite3WindowListDelete(pParse->db, (yypminor->yy483)); -} - break; - case 266: /* idlist */ - case 273: /* idlist_opt */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy204)); -} - break; - case 276: /* filter_over */ - case 311: /* windowdefn */ - case 312: /* window */ - case 313: /* frame_opt */ - case 316: /* over_clause */ -{ -sqlite3WindowDelete(pParse->db, (yypminor->yy483)); -} - break; - case 289: /* trigger_cmd_list */ - case 294: /* trigger_cmd */ -{ -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy319)); -} - break; - case 291: /* trigger_event */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy28).b); -} - break; - case 318: /* frame_bound */ - case 319: /* frame_bound_s */ - case 320: /* frame_bound_e */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy205).pExpr); + case 163: /* select */ + case 194: /* selectnowith */ + case 195: /* oneselect */ + case 206: /* values */ +{ +sqlite3SelectDelete(pParse->db, (yypminor->yy243)); +} + break; + case 172: /* term */ + case 173: /* expr */ +{ +sqlite3ExprDelete(pParse->db, (yypminor->yy190).pExpr); +} + break; + case 177: /* eidlist_opt */ + case 186: /* sortlist */ + case 187: /* eidlist */ + case 199: /* selcollist */ + case 202: /* groupby_opt */ + case 204: /* orderby_opt */ + case 207: /* nexprlist */ + case 208: /* exprlist */ + case 209: /* sclp */ + case 218: /* setlist */ + case 224: /* paren_exprlist */ + case 226: /* case_exprlist */ +{ +sqlite3ExprListDelete(pParse->db, (yypminor->yy148)); +} + break; + case 193: /* fullname */ + case 200: /* from */ + case 211: /* seltablist */ + case 212: /* stl_prefix */ +{ +sqlite3SrcListDelete(pParse->db, (yypminor->yy185)); +} + break; + case 196: /* with */ + case 250: /* wqlist */ +{ +sqlite3WithDelete(pParse->db, (yypminor->yy285)); +} + break; + case 201: /* where_opt */ + case 203: /* having_opt */ + case 215: /* on_opt */ + case 225: /* case_operand */ + case 227: /* case_else */ + case 236: /* when_clause */ + case 241: /* key_opt */ +{ +sqlite3ExprDelete(pParse->db, (yypminor->yy72)); +} + break; + case 216: /* using_opt */ + case 217: /* idlist */ + case 220: /* idlist_opt */ +{ +sqlite3IdListDelete(pParse->db, (yypminor->yy254)); +} + break; + case 232: /* trigger_cmd_list */ + case 237: /* trigger_cmd */ +{ +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy145)); +} + break; + case 234: /* trigger_event */ +{ +sqlite3IdListDelete(pParse->db, (yypminor->yy332).b); } break; /********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } @@ -176721,35 +138107,18 @@ /* ** Clear all secondary memory allocations from the parser */ SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){ yyParser *pParser = (yyParser*)p; - - /* In-lined version of calling yy_pop_parser_stack() for each - ** element left in the stack */ - yyStackEntry *yytos = pParser->yytos; - while( yytos>pParser->yystack ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - if( yytos->major>=YY_MIN_DSTRCTR ){ - yy_destructor(pParser, yytos->major, &yytos->minor); - } - yytos--; - } - -#if YYGROWABLESTACK - if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack); + while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); #endif } #ifndef sqlite3Parser_ENGINEALWAYSONSTACK -/* +/* ** Deallocate and destroy a parser. Destructors are called for ** all stack elements before shutting the parser down. ** ** If the YYPARSEFREENEVERNULL macro exists (for example because it ** is defined in a %include section of the input grammar) then it is @@ -176775,77 +138144,32 @@ yyParser *pParser = (yyParser*)p; return pParser->yyhwm; } #endif -/* This array of booleans keeps track of the parser statement -** coverage. The element yycoverage[X][Y] is set when the parser -** is in state X and has a lookahead token Y. In a well-tested -** systems, every element of this matrix should end up being set. -*/ -#if defined(YYCOVERAGE) -static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; -#endif - -/* -** Write into out a description of every state/lookahead combination that -** -** (1) has not been used by the parser, and -** (2) is not a syntax error. -** -** Return the number of missed state/lookahead combinations. -*/ -#if defined(YYCOVERAGE) -SQLITE_PRIVATE int sqlite3ParserCoverage(FILE *out){ - int stateno, iLookAhead, i; - int nMissed = 0; - for(stateno=0; statenoYY_MAX_SHIFT ) return stateno; + int stateno = pParser->yytos->stateno; + + if( stateno>=YY_MIN_REDUCE ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); -#if defined(YYCOVERAGE) - yycoverage[stateno][iLookAhead] = 1; -#endif do{ i = yy_shift_ofst[stateno]; - assert( i>=0 ); - assert( i<=YY_ACTTAB_COUNT ); - assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); assert( iLookAhead!=YYNOCODE ); - assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - assert( i<(int)YY_NLOOKAHEAD ); - if( yy_lookahead[i]!=iLookAhead ){ + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - assert( iLookAhead %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } @@ -176856,12 +138180,19 @@ } #endif #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); - if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j0 + ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); @@ -176871,22 +138202,21 @@ } } #endif /* YYWILDCARD */ return yy_default[stateno]; }else{ - assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) ); return yy_action[i]; } }while(1); } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. */ -static YYACTIONTYPE yy_find_reduce_action( - YYACTIONTYPE stateno, /* Current state number */ +static int yy_find_reduce_action( + int stateno, /* Current state number */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; #ifdef YYERRORSYMBOL if( stateno>YY_REDUCE_COUNT ){ @@ -176894,10 +138224,11 @@ } #else assert( stateno<=YY_REDUCE_COUNT ); #endif i = yy_reduce_ofst[stateno]; + assert( i!=YY_REDUCE_USE_DFLT ); assert( iLookAhead!=YYNOCODE ); i += iLookAhead; #ifdef YYERRORSYMBOL if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ return yy_default[stateno]; @@ -176911,12 +138242,11 @@ /* ** The following routine is called if the stack overflows. */ static void yyStackOverflow(yyParser *yypParser){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH + sqlite3ParserARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif @@ -176923,44 +138253,42 @@ while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ - sqlite3OomFault(pParse->db); + sqlite3ErrorMsg(pParse, "parser stack overflow"); /******** End %stack_overflow code ********************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ - sqlite3ParserCTX_STORE + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ } /* ** Print tracing information for a SHIFT action */ #ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ +static void yyTraceShift(yyParser *yypParser, int yyNewState){ if( yyTraceFILE ){ if( yyNewStateyytos->major], + fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n", + yyTracePrompt,yyTokenName[yypParser->yytos->major], yyNewState); }else{ - fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", - yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], - yyNewState - YY_MIN_REDUCE); + fprintf(yyTraceFILE,"%sShift '%s'\n", + yyTracePrompt,yyTokenName[yypParser->yytos->major]); } } } #else -# define yyTraceShift(X,Y,Z) +# define yyTraceShift(X,Y) #endif /* ** Perform a shift action. */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ - YYACTIONTYPE yyNewState, /* The new state to shift in */ - YYCODETYPE yyMajor, /* The major token to shift in */ + int yyNewState, /* The new state to shift in */ + int yyMajor, /* The major token to shift in */ sqlite3ParserTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; yypParser->yytos++; #ifdef YYTRACKMAXSTACKDEPTH @@ -176967,884 +138295,422 @@ if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ yypParser->yyhwm++; assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); } #endif - yytos = yypParser->yytos; - if( yytos>yypParser->yystackEnd ){ +#if YYSTACKDEPTH>0 + if( yypParser->yytos>yypParser->yystackEnd ){ + yypParser->yytos--; + yyStackOverflow(yypParser); + return; + } +#else + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ if( yyGrowStack(yypParser) ){ yypParser->yytos--; yyStackOverflow(yypParser); return; } - yytos = yypParser->yytos; - assert( yytos <= yypParser->yystackEnd ); } +#endif if( yyNewState > YY_MAX_SHIFT ){ yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; } - yytos->stateno = yyNewState; - yytos->major = yyMajor; + yytos = yypParser->yytos; + yytos->stateno = (YYACTIONTYPE)yyNewState; + yytos->major = (YYCODETYPE)yyMajor; yytos->minor.yy0 = yyMinor; - yyTraceShift(yypParser, yyNewState, "Shift"); -} - -/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side -** of that rule */ -static const YYCODETYPE yyRuleInfoLhs[] = { - 191, /* (0) explain ::= EXPLAIN */ - 191, /* (1) explain ::= EXPLAIN QUERY PLAN */ - 190, /* (2) cmdx ::= cmd */ - 192, /* (3) cmd ::= BEGIN transtype trans_opt */ - 193, /* (4) transtype ::= */ - 193, /* (5) transtype ::= DEFERRED */ - 193, /* (6) transtype ::= IMMEDIATE */ - 193, /* (7) transtype ::= EXCLUSIVE */ - 192, /* (8) cmd ::= COMMIT|END trans_opt */ - 192, /* (9) cmd ::= ROLLBACK trans_opt */ - 192, /* (10) cmd ::= SAVEPOINT nm */ - 192, /* (11) cmd ::= RELEASE savepoint_opt nm */ - 192, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - 197, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - 199, /* (14) createkw ::= CREATE */ - 201, /* (15) ifnotexists ::= */ - 201, /* (16) ifnotexists ::= IF NOT EXISTS */ - 200, /* (17) temp ::= TEMP */ - 200, /* (18) temp ::= */ - 198, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ - 198, /* (20) create_table_args ::= AS select */ - 205, /* (21) table_option_set ::= */ - 205, /* (22) table_option_set ::= table_option_set COMMA table_option */ - 207, /* (23) table_option ::= WITHOUT nm */ - 207, /* (24) table_option ::= nm */ - 208, /* (25) columnname ::= nm typetoken */ - 210, /* (26) typetoken ::= */ - 210, /* (27) typetoken ::= typename LP signed RP */ - 210, /* (28) typetoken ::= typename LP signed COMMA signed RP */ - 211, /* (29) typename ::= typename ID|STRING */ - 215, /* (30) scanpt ::= */ - 216, /* (31) scantok ::= */ - 217, /* (32) ccons ::= CONSTRAINT nm */ - 217, /* (33) ccons ::= DEFAULT scantok term */ - 217, /* (34) ccons ::= DEFAULT LP expr RP */ - 217, /* (35) ccons ::= DEFAULT PLUS scantok term */ - 217, /* (36) ccons ::= DEFAULT MINUS scantok term */ - 217, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ - 217, /* (38) ccons ::= NOT NULL onconf */ - 217, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - 217, /* (40) ccons ::= UNIQUE onconf */ - 217, /* (41) ccons ::= CHECK LP expr RP */ - 217, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ - 217, /* (43) ccons ::= defer_subclause */ - 217, /* (44) ccons ::= COLLATE ID|STRING */ - 226, /* (45) generated ::= LP expr RP */ - 226, /* (46) generated ::= LP expr RP ID */ - 222, /* (47) autoinc ::= */ - 222, /* (48) autoinc ::= AUTOINCR */ - 224, /* (49) refargs ::= */ - 224, /* (50) refargs ::= refargs refarg */ - 227, /* (51) refarg ::= MATCH nm */ - 227, /* (52) refarg ::= ON INSERT refact */ - 227, /* (53) refarg ::= ON DELETE refact */ - 227, /* (54) refarg ::= ON UPDATE refact */ - 228, /* (55) refact ::= SET NULL */ - 228, /* (56) refact ::= SET DEFAULT */ - 228, /* (57) refact ::= CASCADE */ - 228, /* (58) refact ::= RESTRICT */ - 228, /* (59) refact ::= NO ACTION */ - 225, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - 225, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 229, /* (62) init_deferred_pred_opt ::= */ - 229, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - 229, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 204, /* (65) conslist_opt ::= */ - 231, /* (66) tconscomma ::= COMMA */ - 232, /* (67) tcons ::= CONSTRAINT nm */ - 232, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - 232, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ - 232, /* (70) tcons ::= CHECK LP expr RP onconf */ - 232, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 235, /* (72) defer_subclause_opt ::= */ - 220, /* (73) onconf ::= */ - 220, /* (74) onconf ::= ON CONFLICT resolvetype */ - 236, /* (75) orconf ::= */ - 236, /* (76) orconf ::= OR resolvetype */ - 237, /* (77) resolvetype ::= IGNORE */ - 237, /* (78) resolvetype ::= REPLACE */ - 192, /* (79) cmd ::= DROP TABLE ifexists fullname */ - 239, /* (80) ifexists ::= IF EXISTS */ - 239, /* (81) ifexists ::= */ - 192, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - 192, /* (83) cmd ::= DROP VIEW ifexists fullname */ - 192, /* (84) cmd ::= select */ - 206, /* (85) select ::= WITH wqlist selectnowith */ - 206, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ - 206, /* (87) select ::= selectnowith */ - 241, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ - 244, /* (89) multiselect_op ::= UNION */ - 244, /* (90) multiselect_op ::= UNION ALL */ - 244, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ - 242, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - 242, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - 254, /* (94) values ::= VALUES LP nexprlist RP */ - 242, /* (95) oneselect ::= mvalues */ - 256, /* (96) mvalues ::= values COMMA LP nexprlist RP */ - 256, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */ - 245, /* (98) distinct ::= DISTINCT */ - 245, /* (99) distinct ::= ALL */ - 245, /* (100) distinct ::= */ - 257, /* (101) sclp ::= */ - 246, /* (102) selcollist ::= sclp scanpt expr scanpt as */ - 246, /* (103) selcollist ::= sclp scanpt STAR */ - 246, /* (104) selcollist ::= sclp scanpt nm DOT STAR */ - 258, /* (105) as ::= AS nm */ - 258, /* (106) as ::= */ - 247, /* (107) from ::= */ - 247, /* (108) from ::= FROM seltablist */ - 260, /* (109) stl_prefix ::= seltablist joinop */ - 260, /* (110) stl_prefix ::= */ - 259, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */ - 259, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - 259, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - 259, /* (114) seltablist ::= stl_prefix LP select RP as on_using */ - 259, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 202, /* (116) dbnm ::= */ - 202, /* (117) dbnm ::= DOT nm */ - 240, /* (118) fullname ::= nm */ - 240, /* (119) fullname ::= nm DOT nm */ - 265, /* (120) xfullname ::= nm */ - 265, /* (121) xfullname ::= nm DOT nm */ - 265, /* (122) xfullname ::= nm DOT nm AS nm */ - 265, /* (123) xfullname ::= nm AS nm */ - 261, /* (124) joinop ::= COMMA|JOIN */ - 261, /* (125) joinop ::= JOIN_KW JOIN */ - 261, /* (126) joinop ::= JOIN_KW nm JOIN */ - 261, /* (127) joinop ::= JOIN_KW nm nm JOIN */ - 262, /* (128) on_using ::= ON expr */ - 262, /* (129) on_using ::= USING LP idlist RP */ - 262, /* (130) on_using ::= */ - 267, /* (131) indexed_opt ::= */ - 263, /* (132) indexed_by ::= INDEXED BY nm */ - 263, /* (133) indexed_by ::= NOT INDEXED */ - 251, /* (134) orderby_opt ::= */ - 251, /* (135) orderby_opt ::= ORDER BY sortlist */ - 233, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */ - 233, /* (137) sortlist ::= expr sortorder nulls */ - 221, /* (138) sortorder ::= ASC */ - 221, /* (139) sortorder ::= DESC */ - 221, /* (140) sortorder ::= */ - 268, /* (141) nulls ::= NULLS FIRST */ - 268, /* (142) nulls ::= NULLS LAST */ - 268, /* (143) nulls ::= */ - 249, /* (144) groupby_opt ::= */ - 249, /* (145) groupby_opt ::= GROUP BY nexprlist */ - 250, /* (146) having_opt ::= */ - 250, /* (147) having_opt ::= HAVING expr */ - 252, /* (148) limit_opt ::= */ - 252, /* (149) limit_opt ::= LIMIT expr */ - 252, /* (150) limit_opt ::= LIMIT expr OFFSET expr */ - 252, /* (151) limit_opt ::= LIMIT expr COMMA expr */ - 192, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 248, /* (153) where_opt ::= */ - 248, /* (154) where_opt ::= WHERE expr */ - 270, /* (155) where_opt_ret ::= */ - 270, /* (156) where_opt_ret ::= WHERE expr */ - 270, /* (157) where_opt_ret ::= RETURNING selcollist */ - 270, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */ - 192, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - 271, /* (160) setlist ::= setlist COMMA nm EQ expr */ - 271, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */ - 271, /* (162) setlist ::= nm EQ expr */ - 271, /* (163) setlist ::= LP idlist RP EQ expr */ - 192, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - 192, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 274, /* (166) upsert ::= */ - 274, /* (167) upsert ::= RETURNING selcollist */ - 274, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - 274, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - 274, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */ - 274, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - 275, /* (172) returning ::= RETURNING selcollist */ - 272, /* (173) insert_cmd ::= INSERT orconf */ - 272, /* (174) insert_cmd ::= REPLACE */ - 273, /* (175) idlist_opt ::= */ - 273, /* (176) idlist_opt ::= LP idlist RP */ - 266, /* (177) idlist ::= idlist COMMA nm */ - 266, /* (178) idlist ::= nm */ - 219, /* (179) expr ::= LP expr RP */ - 219, /* (180) expr ::= ID|INDEXED|JOIN_KW */ - 219, /* (181) expr ::= nm DOT nm */ - 219, /* (182) expr ::= nm DOT nm DOT nm */ - 218, /* (183) term ::= NULL|FLOAT|BLOB */ - 218, /* (184) term ::= STRING */ - 218, /* (185) term ::= INTEGER */ - 219, /* (186) expr ::= VARIABLE */ - 219, /* (187) expr ::= expr COLLATE ID|STRING */ - 219, /* (188) expr ::= CAST LP expr AS typetoken RP */ - 219, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ - 219, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ - 219, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ - 219, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ - 219, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ - 219, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ - 218, /* (195) term ::= CTIME_KW */ - 219, /* (196) expr ::= LP nexprlist COMMA expr RP */ - 219, /* (197) expr ::= expr AND expr */ - 219, /* (198) expr ::= expr OR expr */ - 219, /* (199) expr ::= expr LT|GT|GE|LE expr */ - 219, /* (200) expr ::= expr EQ|NE expr */ - 219, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - 219, /* (202) expr ::= expr PLUS|MINUS expr */ - 219, /* (203) expr ::= expr STAR|SLASH|REM expr */ - 219, /* (204) expr ::= expr CONCAT expr */ - 277, /* (205) likeop ::= NOT LIKE_KW|MATCH */ - 219, /* (206) expr ::= expr likeop expr */ - 219, /* (207) expr ::= expr likeop expr ESCAPE expr */ - 219, /* (208) expr ::= expr ISNULL|NOTNULL */ - 219, /* (209) expr ::= expr NOT NULL */ - 219, /* (210) expr ::= expr IS expr */ - 219, /* (211) expr ::= expr IS NOT expr */ - 219, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */ - 219, /* (213) expr ::= expr IS DISTINCT FROM expr */ - 219, /* (214) expr ::= NOT expr */ - 219, /* (215) expr ::= BITNOT expr */ - 219, /* (216) expr ::= PLUS|MINUS expr */ - 219, /* (217) expr ::= expr PTR expr */ - 278, /* (218) between_op ::= BETWEEN */ - 278, /* (219) between_op ::= NOT BETWEEN */ - 219, /* (220) expr ::= expr between_op expr AND expr */ - 279, /* (221) in_op ::= IN */ - 279, /* (222) in_op ::= NOT IN */ - 219, /* (223) expr ::= expr in_op LP exprlist RP */ - 219, /* (224) expr ::= LP select RP */ - 219, /* (225) expr ::= expr in_op LP select RP */ - 219, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */ - 219, /* (227) expr ::= EXISTS LP select RP */ - 219, /* (228) expr ::= CASE case_operand case_exprlist case_else END */ - 282, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - 282, /* (230) case_exprlist ::= WHEN expr THEN expr */ - 283, /* (231) case_else ::= ELSE expr */ - 283, /* (232) case_else ::= */ - 281, /* (233) case_operand ::= */ - 264, /* (234) exprlist ::= */ - 255, /* (235) nexprlist ::= nexprlist COMMA expr */ - 255, /* (236) nexprlist ::= expr */ - 280, /* (237) paren_exprlist ::= */ - 280, /* (238) paren_exprlist ::= LP exprlist RP */ - 192, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - 284, /* (240) uniqueflag ::= UNIQUE */ - 284, /* (241) uniqueflag ::= */ - 223, /* (242) eidlist_opt ::= */ - 223, /* (243) eidlist_opt ::= LP eidlist RP */ - 234, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */ - 234, /* (245) eidlist ::= nm collate sortorder */ - 285, /* (246) collate ::= */ - 285, /* (247) collate ::= COLLATE ID|STRING */ - 192, /* (248) cmd ::= DROP INDEX ifexists fullname */ - 192, /* (249) cmd ::= VACUUM vinto */ - 192, /* (250) cmd ::= VACUUM nm vinto */ - 286, /* (251) vinto ::= INTO expr */ - 286, /* (252) vinto ::= */ - 192, /* (253) cmd ::= PRAGMA nm dbnm */ - 192, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */ - 192, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - 192, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */ - 192, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - 213, /* (258) plus_num ::= PLUS INTEGER|FLOAT */ - 214, /* (259) minus_num ::= MINUS INTEGER|FLOAT */ - 192, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - 288, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - 290, /* (262) trigger_time ::= BEFORE|AFTER */ - 290, /* (263) trigger_time ::= INSTEAD OF */ - 290, /* (264) trigger_time ::= */ - 291, /* (265) trigger_event ::= DELETE|INSERT */ - 291, /* (266) trigger_event ::= UPDATE */ - 291, /* (267) trigger_event ::= UPDATE OF idlist */ - 293, /* (268) when_clause ::= */ - 293, /* (269) when_clause ::= WHEN expr */ - 289, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - 289, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - 295, /* (272) trnm ::= nm DOT nm */ - 296, /* (273) tridxby ::= INDEXED BY nm */ - 296, /* (274) tridxby ::= NOT INDEXED */ - 294, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - 294, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - 294, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - 294, /* (278) trigger_cmd ::= scanpt select scanpt */ - 219, /* (279) expr ::= RAISE LP IGNORE RP */ - 219, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ - 238, /* (281) raisetype ::= ROLLBACK */ - 238, /* (282) raisetype ::= ABORT */ - 238, /* (283) raisetype ::= FAIL */ - 192, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ - 192, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 192, /* (286) cmd ::= DETACH database_kw_opt expr */ - 298, /* (287) key_opt ::= */ - 298, /* (288) key_opt ::= KEY expr */ - 192, /* (289) cmd ::= REINDEX */ - 192, /* (290) cmd ::= REINDEX nm dbnm */ - 192, /* (291) cmd ::= ANALYZE */ - 192, /* (292) cmd ::= ANALYZE nm dbnm */ - 192, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 192, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - 192, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 299, /* (296) add_column_fullname ::= fullname */ - 192, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 192, /* (298) cmd ::= create_vtab */ - 192, /* (299) cmd ::= create_vtab LP vtabarglist RP */ - 301, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 303, /* (301) vtabarg ::= */ - 304, /* (302) vtabargtoken ::= ANY */ - 304, /* (303) vtabargtoken ::= lp anylist RP */ - 305, /* (304) lp ::= LP */ - 269, /* (305) with ::= WITH wqlist */ - 269, /* (306) with ::= WITH RECURSIVE wqlist */ - 308, /* (307) wqas ::= AS */ - 308, /* (308) wqas ::= AS MATERIALIZED */ - 308, /* (309) wqas ::= AS NOT MATERIALIZED */ - 307, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ - 309, /* (311) withnm ::= nm */ - 243, /* (312) wqlist ::= wqitem */ - 243, /* (313) wqlist ::= wqlist COMMA wqitem */ - 310, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 311, /* (315) windowdefn ::= nm AS LP window RP */ - 312, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 312, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 312, /* (318) window ::= ORDER BY sortlist frame_opt */ - 312, /* (319) window ::= nm ORDER BY sortlist frame_opt */ - 312, /* (320) window ::= nm frame_opt */ - 313, /* (321) frame_opt ::= */ - 313, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 313, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 317, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ - 319, /* (325) frame_bound_s ::= frame_bound */ - 319, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ - 320, /* (327) frame_bound_e ::= frame_bound */ - 320, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 318, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ - 318, /* (330) frame_bound ::= CURRENT ROW */ - 321, /* (331) frame_exclude_opt ::= */ - 321, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 322, /* (333) frame_exclude ::= NO OTHERS */ - 322, /* (334) frame_exclude ::= CURRENT ROW */ - 322, /* (335) frame_exclude ::= GROUP|TIES */ - 253, /* (336) window_clause ::= WINDOW windowdefn_list */ - 276, /* (337) filter_over ::= filter_clause over_clause */ - 276, /* (338) filter_over ::= over_clause */ - 276, /* (339) filter_over ::= filter_clause */ - 316, /* (340) over_clause ::= OVER LP window RP */ - 316, /* (341) over_clause ::= OVER nm */ - 315, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ - 218, /* (343) term ::= QNUMBER */ - 187, /* (344) input ::= cmdlist */ - 188, /* (345) cmdlist ::= cmdlist ecmd */ - 188, /* (346) cmdlist ::= ecmd */ - 189, /* (347) ecmd ::= SEMI */ - 189, /* (348) ecmd ::= cmdx SEMI */ - 189, /* (349) ecmd ::= explain cmdx SEMI */ - 194, /* (350) trans_opt ::= */ - 194, /* (351) trans_opt ::= TRANSACTION */ - 194, /* (352) trans_opt ::= TRANSACTION nm */ - 196, /* (353) savepoint_opt ::= SAVEPOINT */ - 196, /* (354) savepoint_opt ::= */ - 192, /* (355) cmd ::= create_table create_table_args */ - 205, /* (356) table_option_set ::= table_option */ - 203, /* (357) columnlist ::= columnlist COMMA columnname carglist */ - 203, /* (358) columnlist ::= columnname carglist */ - 195, /* (359) nm ::= ID|INDEXED|JOIN_KW */ - 195, /* (360) nm ::= STRING */ - 210, /* (361) typetoken ::= typename */ - 211, /* (362) typename ::= ID|STRING */ - 212, /* (363) signed ::= plus_num */ - 212, /* (364) signed ::= minus_num */ - 209, /* (365) carglist ::= carglist ccons */ - 209, /* (366) carglist ::= */ - 217, /* (367) ccons ::= NULL onconf */ - 217, /* (368) ccons ::= GENERATED ALWAYS AS generated */ - 217, /* (369) ccons ::= AS generated */ - 204, /* (370) conslist_opt ::= COMMA conslist */ - 230, /* (371) conslist ::= conslist tconscomma tcons */ - 230, /* (372) conslist ::= tcons */ - 231, /* (373) tconscomma ::= */ - 235, /* (374) defer_subclause_opt ::= defer_subclause */ - 237, /* (375) resolvetype ::= raisetype */ - 241, /* (376) selectnowith ::= oneselect */ - 242, /* (377) oneselect ::= values */ - 257, /* (378) sclp ::= selcollist COMMA */ - 258, /* (379) as ::= ID|STRING */ - 267, /* (380) indexed_opt ::= indexed_by */ - 275, /* (381) returning ::= */ - 219, /* (382) expr ::= term */ - 277, /* (383) likeop ::= LIKE_KW|MATCH */ - 281, /* (384) case_operand ::= expr */ - 264, /* (385) exprlist ::= nexprlist */ - 287, /* (386) nmnum ::= plus_num */ - 287, /* (387) nmnum ::= nm */ - 287, /* (388) nmnum ::= ON */ - 287, /* (389) nmnum ::= DELETE */ - 287, /* (390) nmnum ::= DEFAULT */ - 213, /* (391) plus_num ::= INTEGER|FLOAT */ - 292, /* (392) foreach_clause ::= */ - 292, /* (393) foreach_clause ::= FOR EACH ROW */ - 295, /* (394) trnm ::= nm */ - 296, /* (395) tridxby ::= */ - 297, /* (396) database_kw_opt ::= DATABASE */ - 297, /* (397) database_kw_opt ::= */ - 300, /* (398) kwcolumn_opt ::= */ - 300, /* (399) kwcolumn_opt ::= COLUMNKW */ - 302, /* (400) vtabarglist ::= vtabarg */ - 302, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ - 303, /* (402) vtabarg ::= vtabarg vtabargtoken */ - 306, /* (403) anylist ::= */ - 306, /* (404) anylist ::= anylist LP anylist RP */ - 306, /* (405) anylist ::= anylist ANY */ - 269, /* (406) with ::= */ - 310, /* (407) windowdefn_list ::= windowdefn */ - 312, /* (408) window ::= frame_opt */ -}; - -/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number -** of symbols on the right-hand side of that rule. */ -static const signed char yyRuleInfoNRhs[] = { - -1, /* (0) explain ::= EXPLAIN */ - -3, /* (1) explain ::= EXPLAIN QUERY PLAN */ - -1, /* (2) cmdx ::= cmd */ - -3, /* (3) cmd ::= BEGIN transtype trans_opt */ - 0, /* (4) transtype ::= */ - -1, /* (5) transtype ::= DEFERRED */ - -1, /* (6) transtype ::= IMMEDIATE */ - -1, /* (7) transtype ::= EXCLUSIVE */ - -2, /* (8) cmd ::= COMMIT|END trans_opt */ - -2, /* (9) cmd ::= ROLLBACK trans_opt */ - -2, /* (10) cmd ::= SAVEPOINT nm */ - -3, /* (11) cmd ::= RELEASE savepoint_opt nm */ - -5, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - -6, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - -1, /* (14) createkw ::= CREATE */ - 0, /* (15) ifnotexists ::= */ - -3, /* (16) ifnotexists ::= IF NOT EXISTS */ - -1, /* (17) temp ::= TEMP */ - 0, /* (18) temp ::= */ - -5, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ - -2, /* (20) create_table_args ::= AS select */ - 0, /* (21) table_option_set ::= */ - -3, /* (22) table_option_set ::= table_option_set COMMA table_option */ - -2, /* (23) table_option ::= WITHOUT nm */ - -1, /* (24) table_option ::= nm */ - -2, /* (25) columnname ::= nm typetoken */ - 0, /* (26) typetoken ::= */ - -4, /* (27) typetoken ::= typename LP signed RP */ - -6, /* (28) typetoken ::= typename LP signed COMMA signed RP */ - -2, /* (29) typename ::= typename ID|STRING */ - 0, /* (30) scanpt ::= */ - 0, /* (31) scantok ::= */ - -2, /* (32) ccons ::= CONSTRAINT nm */ - -3, /* (33) ccons ::= DEFAULT scantok term */ - -4, /* (34) ccons ::= DEFAULT LP expr RP */ - -4, /* (35) ccons ::= DEFAULT PLUS scantok term */ - -4, /* (36) ccons ::= DEFAULT MINUS scantok term */ - -3, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ - -3, /* (38) ccons ::= NOT NULL onconf */ - -5, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - -2, /* (40) ccons ::= UNIQUE onconf */ - -4, /* (41) ccons ::= CHECK LP expr RP */ - -4, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ - -1, /* (43) ccons ::= defer_subclause */ - -2, /* (44) ccons ::= COLLATE ID|STRING */ - -3, /* (45) generated ::= LP expr RP */ - -4, /* (46) generated ::= LP expr RP ID */ - 0, /* (47) autoinc ::= */ - -1, /* (48) autoinc ::= AUTOINCR */ - 0, /* (49) refargs ::= */ - -2, /* (50) refargs ::= refargs refarg */ - -2, /* (51) refarg ::= MATCH nm */ - -3, /* (52) refarg ::= ON INSERT refact */ - -3, /* (53) refarg ::= ON DELETE refact */ - -3, /* (54) refarg ::= ON UPDATE refact */ - -2, /* (55) refact ::= SET NULL */ - -2, /* (56) refact ::= SET DEFAULT */ - -1, /* (57) refact ::= CASCADE */ - -1, /* (58) refact ::= RESTRICT */ - -2, /* (59) refact ::= NO ACTION */ - -3, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - -2, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 0, /* (62) init_deferred_pred_opt ::= */ - -2, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - -2, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 0, /* (65) conslist_opt ::= */ - -1, /* (66) tconscomma ::= COMMA */ - -2, /* (67) tcons ::= CONSTRAINT nm */ - -7, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - -5, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ - -5, /* (70) tcons ::= CHECK LP expr RP onconf */ - -10, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 0, /* (72) defer_subclause_opt ::= */ - 0, /* (73) onconf ::= */ - -3, /* (74) onconf ::= ON CONFLICT resolvetype */ - 0, /* (75) orconf ::= */ - -2, /* (76) orconf ::= OR resolvetype */ - -1, /* (77) resolvetype ::= IGNORE */ - -1, /* (78) resolvetype ::= REPLACE */ - -4, /* (79) cmd ::= DROP TABLE ifexists fullname */ - -2, /* (80) ifexists ::= IF EXISTS */ - 0, /* (81) ifexists ::= */ - -9, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - -4, /* (83) cmd ::= DROP VIEW ifexists fullname */ - -1, /* (84) cmd ::= select */ - -3, /* (85) select ::= WITH wqlist selectnowith */ - -4, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ - -1, /* (87) select ::= selectnowith */ - -3, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ - -1, /* (89) multiselect_op ::= UNION */ - -2, /* (90) multiselect_op ::= UNION ALL */ - -1, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ - -9, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - -10, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - -4, /* (94) values ::= VALUES LP nexprlist RP */ - -1, /* (95) oneselect ::= mvalues */ - -5, /* (96) mvalues ::= values COMMA LP nexprlist RP */ - -5, /* (97) mvalues ::= mvalues COMMA LP nexprlist RP */ - -1, /* (98) distinct ::= DISTINCT */ - -1, /* (99) distinct ::= ALL */ - 0, /* (100) distinct ::= */ - 0, /* (101) sclp ::= */ - -5, /* (102) selcollist ::= sclp scanpt expr scanpt as */ - -3, /* (103) selcollist ::= sclp scanpt STAR */ - -5, /* (104) selcollist ::= sclp scanpt nm DOT STAR */ - -2, /* (105) as ::= AS nm */ - 0, /* (106) as ::= */ - 0, /* (107) from ::= */ - -2, /* (108) from ::= FROM seltablist */ - -2, /* (109) stl_prefix ::= seltablist joinop */ - 0, /* (110) stl_prefix ::= */ - -5, /* (111) seltablist ::= stl_prefix nm dbnm as on_using */ - -6, /* (112) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - -8, /* (113) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - -6, /* (114) seltablist ::= stl_prefix LP select RP as on_using */ - -6, /* (115) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 0, /* (116) dbnm ::= */ - -2, /* (117) dbnm ::= DOT nm */ - -1, /* (118) fullname ::= nm */ - -3, /* (119) fullname ::= nm DOT nm */ - -1, /* (120) xfullname ::= nm */ - -3, /* (121) xfullname ::= nm DOT nm */ - -5, /* (122) xfullname ::= nm DOT nm AS nm */ - -3, /* (123) xfullname ::= nm AS nm */ - -1, /* (124) joinop ::= COMMA|JOIN */ - -2, /* (125) joinop ::= JOIN_KW JOIN */ - -3, /* (126) joinop ::= JOIN_KW nm JOIN */ - -4, /* (127) joinop ::= JOIN_KW nm nm JOIN */ - -2, /* (128) on_using ::= ON expr */ - -4, /* (129) on_using ::= USING LP idlist RP */ - 0, /* (130) on_using ::= */ - 0, /* (131) indexed_opt ::= */ - -3, /* (132) indexed_by ::= INDEXED BY nm */ - -2, /* (133) indexed_by ::= NOT INDEXED */ - 0, /* (134) orderby_opt ::= */ - -3, /* (135) orderby_opt ::= ORDER BY sortlist */ - -5, /* (136) sortlist ::= sortlist COMMA expr sortorder nulls */ - -3, /* (137) sortlist ::= expr sortorder nulls */ - -1, /* (138) sortorder ::= ASC */ - -1, /* (139) sortorder ::= DESC */ - 0, /* (140) sortorder ::= */ - -2, /* (141) nulls ::= NULLS FIRST */ - -2, /* (142) nulls ::= NULLS LAST */ - 0, /* (143) nulls ::= */ - 0, /* (144) groupby_opt ::= */ - -3, /* (145) groupby_opt ::= GROUP BY nexprlist */ - 0, /* (146) having_opt ::= */ - -2, /* (147) having_opt ::= HAVING expr */ - 0, /* (148) limit_opt ::= */ - -2, /* (149) limit_opt ::= LIMIT expr */ - -4, /* (150) limit_opt ::= LIMIT expr OFFSET expr */ - -4, /* (151) limit_opt ::= LIMIT expr COMMA expr */ - -6, /* (152) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 0, /* (153) where_opt ::= */ - -2, /* (154) where_opt ::= WHERE expr */ - 0, /* (155) where_opt_ret ::= */ - -2, /* (156) where_opt_ret ::= WHERE expr */ - -2, /* (157) where_opt_ret ::= RETURNING selcollist */ - -4, /* (158) where_opt_ret ::= WHERE expr RETURNING selcollist */ - -9, /* (159) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - -5, /* (160) setlist ::= setlist COMMA nm EQ expr */ - -7, /* (161) setlist ::= setlist COMMA LP idlist RP EQ expr */ - -3, /* (162) setlist ::= nm EQ expr */ - -5, /* (163) setlist ::= LP idlist RP EQ expr */ - -7, /* (164) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - -8, /* (165) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 0, /* (166) upsert ::= */ - -2, /* (167) upsert ::= RETURNING selcollist */ - -12, /* (168) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - -9, /* (169) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - -5, /* (170) upsert ::= ON CONFLICT DO NOTHING returning */ - -8, /* (171) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - -2, /* (172) returning ::= RETURNING selcollist */ - -2, /* (173) insert_cmd ::= INSERT orconf */ - -1, /* (174) insert_cmd ::= REPLACE */ - 0, /* (175) idlist_opt ::= */ - -3, /* (176) idlist_opt ::= LP idlist RP */ - -3, /* (177) idlist ::= idlist COMMA nm */ - -1, /* (178) idlist ::= nm */ - -3, /* (179) expr ::= LP expr RP */ - -1, /* (180) expr ::= ID|INDEXED|JOIN_KW */ - -3, /* (181) expr ::= nm DOT nm */ - -5, /* (182) expr ::= nm DOT nm DOT nm */ - -1, /* (183) term ::= NULL|FLOAT|BLOB */ - -1, /* (184) term ::= STRING */ - -1, /* (185) term ::= INTEGER */ - -1, /* (186) expr ::= VARIABLE */ - -3, /* (187) expr ::= expr COLLATE ID|STRING */ - -6, /* (188) expr ::= CAST LP expr AS typetoken RP */ - -5, /* (189) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ - -8, /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ - -4, /* (191) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ - -6, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ - -9, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ - -5, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ - -1, /* (195) term ::= CTIME_KW */ - -5, /* (196) expr ::= LP nexprlist COMMA expr RP */ - -3, /* (197) expr ::= expr AND expr */ - -3, /* (198) expr ::= expr OR expr */ - -3, /* (199) expr ::= expr LT|GT|GE|LE expr */ - -3, /* (200) expr ::= expr EQ|NE expr */ - -3, /* (201) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - -3, /* (202) expr ::= expr PLUS|MINUS expr */ - -3, /* (203) expr ::= expr STAR|SLASH|REM expr */ - -3, /* (204) expr ::= expr CONCAT expr */ - -2, /* (205) likeop ::= NOT LIKE_KW|MATCH */ - -3, /* (206) expr ::= expr likeop expr */ - -5, /* (207) expr ::= expr likeop expr ESCAPE expr */ - -2, /* (208) expr ::= expr ISNULL|NOTNULL */ - -3, /* (209) expr ::= expr NOT NULL */ - -3, /* (210) expr ::= expr IS expr */ - -4, /* (211) expr ::= expr IS NOT expr */ - -6, /* (212) expr ::= expr IS NOT DISTINCT FROM expr */ - -5, /* (213) expr ::= expr IS DISTINCT FROM expr */ - -2, /* (214) expr ::= NOT expr */ - -2, /* (215) expr ::= BITNOT expr */ - -2, /* (216) expr ::= PLUS|MINUS expr */ - -3, /* (217) expr ::= expr PTR expr */ - -1, /* (218) between_op ::= BETWEEN */ - -2, /* (219) between_op ::= NOT BETWEEN */ - -5, /* (220) expr ::= expr between_op expr AND expr */ - -1, /* (221) in_op ::= IN */ - -2, /* (222) in_op ::= NOT IN */ - -5, /* (223) expr ::= expr in_op LP exprlist RP */ - -3, /* (224) expr ::= LP select RP */ - -5, /* (225) expr ::= expr in_op LP select RP */ - -5, /* (226) expr ::= expr in_op nm dbnm paren_exprlist */ - -4, /* (227) expr ::= EXISTS LP select RP */ - -5, /* (228) expr ::= CASE case_operand case_exprlist case_else END */ - -5, /* (229) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - -4, /* (230) case_exprlist ::= WHEN expr THEN expr */ - -2, /* (231) case_else ::= ELSE expr */ - 0, /* (232) case_else ::= */ - 0, /* (233) case_operand ::= */ - 0, /* (234) exprlist ::= */ - -3, /* (235) nexprlist ::= nexprlist COMMA expr */ - -1, /* (236) nexprlist ::= expr */ - 0, /* (237) paren_exprlist ::= */ - -3, /* (238) paren_exprlist ::= LP exprlist RP */ - -12, /* (239) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - -1, /* (240) uniqueflag ::= UNIQUE */ - 0, /* (241) uniqueflag ::= */ - 0, /* (242) eidlist_opt ::= */ - -3, /* (243) eidlist_opt ::= LP eidlist RP */ - -5, /* (244) eidlist ::= eidlist COMMA nm collate sortorder */ - -3, /* (245) eidlist ::= nm collate sortorder */ - 0, /* (246) collate ::= */ - -2, /* (247) collate ::= COLLATE ID|STRING */ - -4, /* (248) cmd ::= DROP INDEX ifexists fullname */ - -2, /* (249) cmd ::= VACUUM vinto */ - -3, /* (250) cmd ::= VACUUM nm vinto */ - -2, /* (251) vinto ::= INTO expr */ - 0, /* (252) vinto ::= */ - -3, /* (253) cmd ::= PRAGMA nm dbnm */ - -5, /* (254) cmd ::= PRAGMA nm dbnm EQ nmnum */ - -6, /* (255) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - -5, /* (256) cmd ::= PRAGMA nm dbnm EQ minus_num */ - -6, /* (257) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - -2, /* (258) plus_num ::= PLUS INTEGER|FLOAT */ - -2, /* (259) minus_num ::= MINUS INTEGER|FLOAT */ - -5, /* (260) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - -11, /* (261) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - -1, /* (262) trigger_time ::= BEFORE|AFTER */ - -2, /* (263) trigger_time ::= INSTEAD OF */ - 0, /* (264) trigger_time ::= */ - -1, /* (265) trigger_event ::= DELETE|INSERT */ - -1, /* (266) trigger_event ::= UPDATE */ - -3, /* (267) trigger_event ::= UPDATE OF idlist */ - 0, /* (268) when_clause ::= */ - -2, /* (269) when_clause ::= WHEN expr */ - -3, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - -2, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (272) trnm ::= nm DOT nm */ - -3, /* (273) tridxby ::= INDEXED BY nm */ - -2, /* (274) tridxby ::= NOT INDEXED */ - -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - -3, /* (278) trigger_cmd ::= scanpt select scanpt */ - -4, /* (279) expr ::= RAISE LP IGNORE RP */ - -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ - -1, /* (281) raisetype ::= ROLLBACK */ - -1, /* (282) raisetype ::= ABORT */ - -1, /* (283) raisetype ::= FAIL */ - -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (286) cmd ::= DETACH database_kw_opt expr */ - 0, /* (287) key_opt ::= */ - -2, /* (288) key_opt ::= KEY expr */ - -1, /* (289) cmd ::= REINDEX */ - -3, /* (290) cmd ::= REINDEX nm dbnm */ - -1, /* (291) cmd ::= ANALYZE */ - -3, /* (292) cmd ::= ANALYZE nm dbnm */ - -6, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -7, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - -6, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -1, /* (296) add_column_fullname ::= fullname */ - -8, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -1, /* (298) cmd ::= create_vtab */ - -4, /* (299) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (301) vtabarg ::= */ - -1, /* (302) vtabargtoken ::= ANY */ - -3, /* (303) vtabargtoken ::= lp anylist RP */ - -1, /* (304) lp ::= LP */ - -2, /* (305) with ::= WITH wqlist */ - -3, /* (306) with ::= WITH RECURSIVE wqlist */ - -1, /* (307) wqas ::= AS */ - -2, /* (308) wqas ::= AS MATERIALIZED */ - -3, /* (309) wqas ::= AS NOT MATERIALIZED */ - -6, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ - -1, /* (311) withnm ::= nm */ - -1, /* (312) wqlist ::= wqitem */ - -3, /* (313) wqlist ::= wqlist COMMA wqitem */ - -3, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (315) windowdefn ::= nm AS LP window RP */ - -5, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (318) window ::= ORDER BY sortlist frame_opt */ - -5, /* (319) window ::= nm ORDER BY sortlist frame_opt */ - -2, /* (320) window ::= nm frame_opt */ - 0, /* (321) frame_opt ::= */ - -3, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (325) frame_bound_s ::= frame_bound */ - -2, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (327) frame_bound_e ::= frame_bound */ - -2, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (330) frame_bound ::= CURRENT ROW */ - 0, /* (331) frame_exclude_opt ::= */ - -2, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (333) frame_exclude ::= NO OTHERS */ - -2, /* (334) frame_exclude ::= CURRENT ROW */ - -1, /* (335) frame_exclude ::= GROUP|TIES */ - -2, /* (336) window_clause ::= WINDOW windowdefn_list */ - -2, /* (337) filter_over ::= filter_clause over_clause */ - -1, /* (338) filter_over ::= over_clause */ - -1, /* (339) filter_over ::= filter_clause */ - -4, /* (340) over_clause ::= OVER LP window RP */ - -2, /* (341) over_clause ::= OVER nm */ - -5, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (343) term ::= QNUMBER */ - -1, /* (344) input ::= cmdlist */ - -2, /* (345) cmdlist ::= cmdlist ecmd */ - -1, /* (346) cmdlist ::= ecmd */ - -1, /* (347) ecmd ::= SEMI */ - -2, /* (348) ecmd ::= cmdx SEMI */ - -3, /* (349) ecmd ::= explain cmdx SEMI */ - 0, /* (350) trans_opt ::= */ - -1, /* (351) trans_opt ::= TRANSACTION */ - -2, /* (352) trans_opt ::= TRANSACTION nm */ - -1, /* (353) savepoint_opt ::= SAVEPOINT */ - 0, /* (354) savepoint_opt ::= */ - -2, /* (355) cmd ::= create_table create_table_args */ - -1, /* (356) table_option_set ::= table_option */ - -4, /* (357) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (358) columnlist ::= columnname carglist */ - -1, /* (359) nm ::= ID|INDEXED|JOIN_KW */ - -1, /* (360) nm ::= STRING */ - -1, /* (361) typetoken ::= typename */ - -1, /* (362) typename ::= ID|STRING */ - -1, /* (363) signed ::= plus_num */ - -1, /* (364) signed ::= minus_num */ - -2, /* (365) carglist ::= carglist ccons */ - 0, /* (366) carglist ::= */ - -2, /* (367) ccons ::= NULL onconf */ - -4, /* (368) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (369) ccons ::= AS generated */ - -2, /* (370) conslist_opt ::= COMMA conslist */ - -3, /* (371) conslist ::= conslist tconscomma tcons */ - -1, /* (372) conslist ::= tcons */ - 0, /* (373) tconscomma ::= */ - -1, /* (374) defer_subclause_opt ::= defer_subclause */ - -1, /* (375) resolvetype ::= raisetype */ - -1, /* (376) selectnowith ::= oneselect */ - -1, /* (377) oneselect ::= values */ - -2, /* (378) sclp ::= selcollist COMMA */ - -1, /* (379) as ::= ID|STRING */ - -1, /* (380) indexed_opt ::= indexed_by */ - 0, /* (381) returning ::= */ - -1, /* (382) expr ::= term */ - -1, /* (383) likeop ::= LIKE_KW|MATCH */ - -1, /* (384) case_operand ::= expr */ - -1, /* (385) exprlist ::= nexprlist */ - -1, /* (386) nmnum ::= plus_num */ - -1, /* (387) nmnum ::= nm */ - -1, /* (388) nmnum ::= ON */ - -1, /* (389) nmnum ::= DELETE */ - -1, /* (390) nmnum ::= DEFAULT */ - -1, /* (391) plus_num ::= INTEGER|FLOAT */ - 0, /* (392) foreach_clause ::= */ - -3, /* (393) foreach_clause ::= FOR EACH ROW */ - -1, /* (394) trnm ::= nm */ - 0, /* (395) tridxby ::= */ - -1, /* (396) database_kw_opt ::= DATABASE */ - 0, /* (397) database_kw_opt ::= */ - 0, /* (398) kwcolumn_opt ::= */ - -1, /* (399) kwcolumn_opt ::= COLUMNKW */ - -1, /* (400) vtabarglist ::= vtabarg */ - -3, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (402) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (403) anylist ::= */ - -4, /* (404) anylist ::= anylist LP anylist RP */ - -2, /* (405) anylist ::= anylist ANY */ - 0, /* (406) with ::= */ - -1, /* (407) windowdefn_list ::= windowdefn */ - -1, /* (408) window ::= frame_opt */ + yyTraceShift(yypParser, yyNewState); +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ +} yyRuleInfo[] = { + { 147, -1 }, + { 147, -3 }, + { 148, -1 }, + { 149, -3 }, + { 150, 0 }, + { 150, -1 }, + { 150, -1 }, + { 150, -1 }, + { 149, -2 }, + { 149, -2 }, + { 149, -2 }, + { 149, -3 }, + { 149, -5 }, + { 154, -6 }, + { 156, -1 }, + { 158, 0 }, + { 158, -3 }, + { 157, -1 }, + { 157, 0 }, + { 155, -5 }, + { 155, -2 }, + { 162, 0 }, + { 162, -2 }, + { 164, -2 }, + { 166, 0 }, + { 166, -4 }, + { 166, -6 }, + { 167, -2 }, + { 171, -2 }, + { 171, -2 }, + { 171, -4 }, + { 171, -3 }, + { 171, -3 }, + { 171, -2 }, + { 171, -3 }, + { 171, -5 }, + { 171, -2 }, + { 171, -4 }, + { 171, -4 }, + { 171, -1 }, + { 171, -2 }, + { 176, 0 }, + { 176, -1 }, + { 178, 0 }, + { 178, -2 }, + { 180, -2 }, + { 180, -3 }, + { 180, -3 }, + { 180, -3 }, + { 181, -2 }, + { 181, -2 }, + { 181, -1 }, + { 181, -1 }, + { 181, -2 }, + { 179, -3 }, + { 179, -2 }, + { 182, 0 }, + { 182, -2 }, + { 182, -2 }, + { 161, 0 }, + { 184, -1 }, + { 185, -2 }, + { 185, -7 }, + { 185, -5 }, + { 185, -5 }, + { 185, -10 }, + { 188, 0 }, + { 174, 0 }, + { 174, -3 }, + { 189, 0 }, + { 189, -2 }, + { 190, -1 }, + { 190, -1 }, + { 149, -4 }, + { 192, -2 }, + { 192, 0 }, + { 149, -9 }, + { 149, -4 }, + { 149, -1 }, + { 163, -2 }, + { 194, -3 }, + { 197, -1 }, + { 197, -2 }, + { 197, -1 }, + { 195, -9 }, + { 206, -4 }, + { 206, -5 }, + { 198, -1 }, + { 198, -1 }, + { 198, 0 }, + { 209, 0 }, + { 199, -3 }, + { 199, -2 }, + { 199, -4 }, + { 210, -2 }, + { 210, 0 }, + { 200, 0 }, + { 200, -2 }, + { 212, -2 }, + { 212, 0 }, + { 211, -7 }, + { 211, -9 }, + { 211, -7 }, + { 211, -7 }, + { 159, 0 }, + { 159, -2 }, + { 193, -2 }, + { 213, -1 }, + { 213, -2 }, + { 213, -3 }, + { 213, -4 }, + { 215, -2 }, + { 215, 0 }, + { 214, 0 }, + { 214, -3 }, + { 214, -2 }, + { 216, -4 }, + { 216, 0 }, + { 204, 0 }, + { 204, -3 }, + { 186, -4 }, + { 186, -2 }, + { 175, -1 }, + { 175, -1 }, + { 175, 0 }, + { 202, 0 }, + { 202, -3 }, + { 203, 0 }, + { 203, -2 }, + { 205, 0 }, + { 205, -2 }, + { 205, -4 }, + { 205, -4 }, + { 149, -6 }, + { 201, 0 }, + { 201, -2 }, + { 149, -8 }, + { 218, -5 }, + { 218, -7 }, + { 218, -3 }, + { 218, -5 }, + { 149, -6 }, + { 149, -7 }, + { 219, -2 }, + { 219, -1 }, + { 220, 0 }, + { 220, -3 }, + { 217, -3 }, + { 217, -1 }, + { 173, -3 }, + { 173, -1 }, + { 173, -1 }, + { 173, -3 }, + { 173, -5 }, + { 172, -1 }, + { 172, -1 }, + { 172, -1 }, + { 173, -1 }, + { 173, -3 }, + { 173, -6 }, + { 173, -5 }, + { 173, -4 }, + { 172, -1 }, + { 173, -5 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 221, -2 }, + { 173, -3 }, + { 173, -5 }, + { 173, -2 }, + { 173, -3 }, + { 173, -3 }, + { 173, -4 }, + { 173, -2 }, + { 173, -2 }, + { 173, -2 }, + { 173, -2 }, + { 222, -1 }, + { 222, -2 }, + { 173, -5 }, + { 223, -1 }, + { 223, -2 }, + { 173, -5 }, + { 173, -3 }, + { 173, -5 }, + { 173, -5 }, + { 173, -4 }, + { 173, -5 }, + { 226, -5 }, + { 226, -4 }, + { 227, -2 }, + { 227, 0 }, + { 225, -1 }, + { 225, 0 }, + { 208, 0 }, + { 207, -3 }, + { 207, -1 }, + { 224, 0 }, + { 224, -3 }, + { 149, -12 }, + { 228, -1 }, + { 228, 0 }, + { 177, 0 }, + { 177, -3 }, + { 187, -5 }, + { 187, -3 }, + { 229, 0 }, + { 229, -2 }, + { 149, -4 }, + { 149, -1 }, + { 149, -2 }, + { 149, -3 }, + { 149, -5 }, + { 149, -6 }, + { 149, -5 }, + { 149, -6 }, + { 169, -2 }, + { 170, -2 }, + { 149, -5 }, + { 231, -11 }, + { 233, -1 }, + { 233, -2 }, + { 233, 0 }, + { 234, -1 }, + { 234, -1 }, + { 234, -3 }, + { 236, 0 }, + { 236, -2 }, + { 232, -3 }, + { 232, -2 }, + { 238, -3 }, + { 239, -3 }, + { 239, -2 }, + { 237, -7 }, + { 237, -5 }, + { 237, -5 }, + { 237, -1 }, + { 173, -4 }, + { 173, -6 }, + { 191, -1 }, + { 191, -1 }, + { 191, -1 }, + { 149, -4 }, + { 149, -6 }, + { 149, -3 }, + { 241, 0 }, + { 241, -2 }, + { 149, -1 }, + { 149, -3 }, + { 149, -1 }, + { 149, -3 }, + { 149, -6 }, + { 149, -7 }, + { 242, -1 }, + { 149, -1 }, + { 149, -4 }, + { 244, -8 }, + { 246, 0 }, + { 247, -1 }, + { 247, -3 }, + { 248, -1 }, + { 196, 0 }, + { 196, -2 }, + { 196, -3 }, + { 250, -6 }, + { 250, -8 }, + { 144, -1 }, + { 145, -2 }, + { 145, -1 }, + { 146, -1 }, + { 146, -3 }, + { 147, 0 }, + { 151, 0 }, + { 151, -1 }, + { 151, -2 }, + { 153, -1 }, + { 153, 0 }, + { 149, -2 }, + { 160, -4 }, + { 160, -2 }, + { 152, -1 }, + { 152, -1 }, + { 152, -1 }, + { 166, -1 }, + { 167, -1 }, + { 168, -1 }, + { 168, -1 }, + { 165, -2 }, + { 165, 0 }, + { 171, -2 }, + { 161, -2 }, + { 183, -3 }, + { 183, -1 }, + { 184, 0 }, + { 188, -1 }, + { 190, -1 }, + { 194, -1 }, + { 195, -1 }, + { 209, -2 }, + { 210, -1 }, + { 173, -1 }, + { 221, -1 }, + { 208, -1 }, + { 230, -1 }, + { 230, -1 }, + { 230, -1 }, + { 230, -1 }, + { 230, -1 }, + { 169, -1 }, + { 235, 0 }, + { 235, -3 }, + { 238, -1 }, + { 239, 0 }, + { 240, -1 }, + { 240, 0 }, + { 243, 0 }, + { 243, -1 }, + { 245, -1 }, + { 245, -3 }, + { 246, -2 }, + { 249, 0 }, + { 249, -4 }, + { 249, -2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. -** -** The yyLookahead and yyLookaheadToken parameters provide reduce actions -** access to the lookahead token (if any). The yyLookahead will be YYNOCODE -** if the lookahead token has already been consumed. As this procedure is -** only called from one place, optimizing compilers will in-line it, which -** means that the extra parameters have no performance impact. */ -static YYACTIONTYPE yy_reduce( +static void yy_reduce( yyParser *yypParser, /* The parser */ - unsigned int yyruleno, /* Number of the rule by which to reduce */ - int yyLookahead, /* Lookahead token, or YYNOCODE if none */ - sqlite3ParserTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ - sqlite3ParserCTX_PDECL /* %extra_context */ + unsigned int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ - YYACTIONTYPE yyact; /* The next action */ + int yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ - sqlite3ParserARG_FETCH - (void)yyLookahead; - (void)yyLookaheadToken; + sqlite3ParserARG_FETCH; yymsp = yypParser->yytos; +#ifndef NDEBUG + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + yysize = yyRuleInfo[yyruleno].nrhs; + fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, + yyRuleName[yyruleno], yymsp[yysize].stateno); + } +#endif /* NDEBUG */ + + /* Check that the stack is large enough to grow by a single entry + ** if the RHS of the rule is empty. This ensures that there is room + ** enough on the stack to push the LHS value */ + if( yyRuleInfo[yyruleno].nrhs==0 ){ +#ifdef YYTRACKMAXSTACKDEPTH + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); + } +#endif +#if YYSTACKDEPTH>0 + if( yypParser->yytos>=yypParser->yystackEnd ){ + yyStackOverflow(yypParser); + return; + } +#else + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ + if( yyGrowStack(yypParser) ){ + yyStackOverflow(yypParser); + return; + } + yymsp = yypParser->yytos; + } +#endif + } switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: @@ -177854,29 +138720,28 @@ ** break; */ /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* explain ::= EXPLAIN */ -{ if( pParse->pReprepare==0 ) pParse->explain = 1; } +{ pParse->explain = 1; } break; case 1: /* explain ::= EXPLAIN QUERY PLAN */ -{ if( pParse->pReprepare==0 ) pParse->explain = 2; } +{ pParse->explain = 2; } break; case 2: /* cmdx ::= cmd */ { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy194);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy502 = TK_DEFERRED;} +{yymsp[1].minor.yy194 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324); -{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/} +{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); {sqlite3EndTransaction(pParse,yymsp[-1].major);} break; @@ -177895,1559 +138760,1221 @@ sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0); } break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194); } break; case 14: /* createkw ::= CREATE */ {disableLookaside(pParse);} break; case 15: /* ifnotexists ::= */ case 18: /* temp ::= */ yytestcase(yyruleno==18); - case 47: /* autoinc ::= */ yytestcase(yyruleno==47); - case 62: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==62); - case 72: /* defer_subclause_opt ::= */ yytestcase(yyruleno==72); - case 81: /* ifexists ::= */ yytestcase(yyruleno==81); - case 100: /* distinct ::= */ yytestcase(yyruleno==100); - case 246: /* collate ::= */ yytestcase(yyruleno==246); -{yymsp[1].minor.yy502 = 0;} - break; - case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy502 = 1;} - break; - case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy502 = pParse->db->init.busy==0;} - break; - case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ -{ - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy9,0); -} - break; - case 20: /* create_table_args ::= AS select */ -{ - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy637); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); -} - break; - case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy9 = 0;} - break; - case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy9 = yymsp[-2].minor.yy9|yymsp[0].minor.yy9;} - yymsp[-2].minor.yy9 = yylhsminor.yy9; - break; - case 23: /* table_option ::= WITHOUT nm */ -{ - if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy9 = TF_WithoutRowid | TF_NoVisibleRowid; - }else{ - yymsp[-1].minor.yy9 = 0; - sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); - } -} - break; - case 24: /* table_option ::= nm */ -{ - if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy9 = TF_Strict; - }else{ - yylhsminor.yy9 = 0; - sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); - } -} - yymsp[0].minor.yy9 = yylhsminor.yy9; - break; - case 25: /* columnname ::= nm typetoken */ -{sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} - break; - case 26: /* typetoken ::= */ - case 65: /* conslist_opt ::= */ yytestcase(yyruleno==65); - case 106: /* as ::= */ yytestcase(yyruleno==106); -{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} - break; - case 27: /* typetoken ::= typename LP signed RP */ -{ - yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z); -} - break; - case 28: /* typetoken ::= typename LP signed COMMA signed RP */ + case 21: /* table_options ::= */ yytestcase(yyruleno==21); + case 41: /* autoinc ::= */ yytestcase(yyruleno==41); + case 56: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==56); + case 66: /* defer_subclause_opt ::= */ yytestcase(yyruleno==66); + case 75: /* ifexists ::= */ yytestcase(yyruleno==75); + case 89: /* distinct ::= */ yytestcase(yyruleno==89); + case 212: /* collate ::= */ yytestcase(yyruleno==212); +{yymsp[1].minor.yy194 = 0;} + break; + case 16: /* ifnotexists ::= IF NOT EXISTS */ +{yymsp[-2].minor.yy194 = 1;} + break; + case 17: /* temp ::= TEMP */ + case 42: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==42); +{yymsp[0].minor.yy194 = 1;} + break; + case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ +{ + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy194,0); +} + break; + case 20: /* create_table_args ::= AS select */ +{ + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy243); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); +} + break; + case 22: /* table_options ::= WITHOUT nm */ +{ + if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ + yymsp[-1].minor.yy194 = TF_WithoutRowid | TF_NoVisibleRowid; + }else{ + yymsp[-1].minor.yy194 = 0; + sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); + } +} + break; + case 23: /* columnname ::= nm typetoken */ +{sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} + break; + case 24: /* typetoken ::= */ + case 59: /* conslist_opt ::= */ yytestcase(yyruleno==59); + case 95: /* as ::= */ yytestcase(yyruleno==95); +{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} + break; + case 25: /* typetoken ::= typename LP signed RP */ +{ + yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z); +} + break; + case 26: /* typetoken ::= typename LP signed COMMA signed RP */ { yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z); } break; - case 29: /* typename ::= typename ID|STRING */ + case 27: /* typename ::= typename ID|STRING */ {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} break; - case 30: /* scanpt ::= */ -{ - assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy342 = yyLookaheadToken.z; -} - break; - case 31: /* scantok ::= */ -{ - assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy0 = yyLookaheadToken; -} - break; - case 32: /* ccons ::= CONSTRAINT nm */ - case 67: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==67); + case 28: /* ccons ::= CONSTRAINT nm */ + case 61: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==61); {pParse->constraintName = yymsp[0].minor.yy0;} break; - case 33: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} - break; - case 34: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} - break; - case 35: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} - break; - case 36: /* ccons ::= DEFAULT MINUS scantok term */ -{ - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy590, 0); - sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); -} - break; - case 37: /* ccons ::= DEFAULT scantok ID|INDEXED */ -{ - Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0); - if( p ){ - sqlite3ExprIdToTrueFalse(p); - testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); - } - sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); -} - break; - case 38: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);} - break; - case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);} - break; - case 40: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0, + case 29: /* ccons ::= DEFAULT term */ + case 31: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==31); +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);} + break; + case 30: /* ccons ::= DEFAULT LP expr RP */ +{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);} + break; + case 32: /* ccons ::= DEFAULT MINUS term */ +{ + ExprSpan v; + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0); + v.zStart = yymsp[-1].minor.yy0.z; + v.zEnd = yymsp[0].minor.yy190.zEnd; + sqlite3AddDefaultValue(pParse,&v); +} + break; + case 33: /* ccons ::= DEFAULT ID|INDEXED */ +{ + ExprSpan v; + spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0); + sqlite3AddDefaultValue(pParse,&v); +} + break; + case 34: /* ccons ::= NOT NULL onconf */ +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);} + break; + case 35: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);} + break; + case 36: /* ccons ::= UNIQUE onconf */ +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy194,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 41: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} - break; - case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy502);} - break; - case 43: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);} - break; - case 44: /* ccons ::= COLLATE ID|STRING */ + case 37: /* ccons ::= CHECK LP expr RP */ +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);} + break; + case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */ +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);} + break; + case 39: /* ccons ::= defer_subclause */ +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);} + break; + case 40: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; - case 45: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy590,0);} - break; - case 46: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy590,&yymsp[0].minor.yy0);} - break; - case 48: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy502 = 1;} - break; - case 49: /* refargs ::= */ -{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */} - break; - case 50: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy481.mask) | yymsp[0].minor.yy481.value; } - break; - case 51: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy481.value = 0; yymsp[-1].minor.yy481.mask = 0x000000; } - break; - case 52: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy481.value = 0; yymsp[-2].minor.yy481.mask = 0x000000; } - break; - case 53: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy481.mask = 0x0000ff; } - break; - case 54: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy481.mask = 0x00ff00; } - break; - case 55: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */} - break; - case 56: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */} - break; - case 57: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */} - break; - case 58: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */} - break; - case 59: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */} - break; - case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy502 = 0;} - break; - case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76); - case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173); -{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;} - break; - case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ - case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80); - case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); - case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); - case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); -{yymsp[-1].minor.yy502 = 1;} - break; - case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy502 = 0;} - break; - case 66: /* tconscomma ::= COMMA */ + case 43: /* refargs ::= */ +{ yymsp[1].minor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */} + break; + case 44: /* refargs ::= refargs refarg */ +{ yymsp[-1].minor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; } + break; + case 45: /* refarg ::= MATCH nm */ +{ yymsp[-1].minor.yy497.value = 0; yymsp[-1].minor.yy497.mask = 0x000000; } + break; + case 46: /* refarg ::= ON INSERT refact */ +{ yymsp[-2].minor.yy497.value = 0; yymsp[-2].minor.yy497.mask = 0x000000; } + break; + case 47: /* refarg ::= ON DELETE refact */ +{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194; yymsp[-2].minor.yy497.mask = 0x0000ff; } + break; + case 48: /* refarg ::= ON UPDATE refact */ +{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194<<8; yymsp[-2].minor.yy497.mask = 0x00ff00; } + break; + case 49: /* refact ::= SET NULL */ +{ yymsp[-1].minor.yy194 = OE_SetNull; /* EV: R-33326-45252 */} + break; + case 50: /* refact ::= SET DEFAULT */ +{ yymsp[-1].minor.yy194 = OE_SetDflt; /* EV: R-33326-45252 */} + break; + case 51: /* refact ::= CASCADE */ +{ yymsp[0].minor.yy194 = OE_Cascade; /* EV: R-33326-45252 */} + break; + case 52: /* refact ::= RESTRICT */ +{ yymsp[0].minor.yy194 = OE_Restrict; /* EV: R-33326-45252 */} + break; + case 53: /* refact ::= NO ACTION */ +{ yymsp[-1].minor.yy194 = OE_None; /* EV: R-33326-45252 */} + break; + case 54: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ +{yymsp[-2].minor.yy194 = 0;} + break; + case 55: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 70: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==70); + case 143: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==143); +{yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} + break; + case 57: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ + case 74: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==74); + case 184: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==184); + case 187: /* in_op ::= NOT IN */ yytestcase(yyruleno==187); + case 213: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==213); +{yymsp[-1].minor.yy194 = 1;} + break; + case 58: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ +{yymsp[-1].minor.yy194 = 0;} + break; + case 60: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; - case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);} + case 62: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);} break; - case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy502,0,0,0,0, + case 63: /* tcons ::= UNIQUE LP sortlist RP onconf */ +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy148,yymsp[0].minor.yy194,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 70: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy590,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} - break; - case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ -{ - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy502); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502); -} - break; - case 73: /* onconf ::= */ - case 75: /* orconf ::= */ yytestcase(yyruleno==75); -{yymsp[1].minor.yy502 = OE_Default;} - break; - case 74: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;} - break; - case 77: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy502 = OE_Ignore;} - break; - case 78: /* resolvetype ::= REPLACE */ - case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174); -{yymsp[0].minor.yy502 = OE_Replace;} - break; - case 79: /* cmd ::= DROP TABLE ifexists fullname */ -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy563, 0, yymsp[-1].minor.yy502); -} - break; - case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ -{ - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy637, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502); -} - break; - case 83: /* cmd ::= DROP VIEW ifexists fullname */ -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy563, 1, yymsp[-1].minor.yy502); -} - break; - case 84: /* cmd ::= select */ -{ - SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0}; - if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0 - || sqlite3ReadSchema(pParse)==SQLITE_OK - ){ - sqlite3Select(pParse, yymsp[0].minor.yy637, &dest); - } - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); -} - break; - case 85: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} - break; - case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} - break; - case 87: /* select ::= selectnowith */ -{ - Select *p = yymsp[0].minor.yy637; + case 64: /* tcons ::= CHECK LP expr RP onconf */ +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);} + break; + case 65: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ +{ + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194); +} + break; + case 67: /* onconf ::= */ + case 69: /* orconf ::= */ yytestcase(yyruleno==69); +{yymsp[1].minor.yy194 = OE_Default;} + break; + case 68: /* onconf ::= ON CONFLICT resolvetype */ +{yymsp[-2].minor.yy194 = yymsp[0].minor.yy194;} + break; + case 71: /* resolvetype ::= IGNORE */ +{yymsp[0].minor.yy194 = OE_Ignore;} + break; + case 72: /* resolvetype ::= REPLACE */ + case 144: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==144); +{yymsp[0].minor.yy194 = OE_Replace;} + break; + case 73: /* cmd ::= DROP TABLE ifexists fullname */ +{ + sqlite3DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194); +} + break; + case 76: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ +{ + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[0].minor.yy243, yymsp[-7].minor.yy194, yymsp[-5].minor.yy194); +} + break; + case 77: /* cmd ::= DROP VIEW ifexists fullname */ +{ + sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194); +} + break; + case 78: /* cmd ::= select */ +{ + SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; + sqlite3Select(pParse, yymsp[0].minor.yy243, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); +} + break; + case 79: /* select ::= with selectnowith */ +{ + Select *p = yymsp[0].minor.yy243; if( p ){ + p->pWith = yymsp[-1].minor.yy285; parserDoubleLinkSelect(pParse, p); + }else{ + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy285); } + yymsp[-1].minor.yy243 = p; /*A-overwrites-W*/ } break; - case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ + case 80: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy637; - Select *pLhs = yymsp[-2].minor.yy637; + Select *pRhs = yymsp[0].minor.yy243; + Select *pLhs = yymsp[-2].minor.yy243; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; x.n = 0; parserDoubleLinkSelect(pParse, pRhs); - pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0); - pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); + pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); + pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy502; + pRhs->op = (u8)yymsp[-1].minor.yy194; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy194!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy637 = pRhs; -} - break; - case 89: /* multiselect_op ::= UNION */ - case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91); -{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/} - break; - case 90: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy502 = TK_ALL;} - break; - case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ -{ - yymsp[-8].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy563,yymsp[-4].minor.yy590,yymsp[-3].minor.yy402,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[-7].minor.yy502,yymsp[0].minor.yy590); -} - break; - case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ -{ - yymsp[-9].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy402,yymsp[-6].minor.yy563,yymsp[-5].minor.yy590,yymsp[-4].minor.yy402,yymsp[-3].minor.yy590,yymsp[-1].minor.yy402,yymsp[-8].minor.yy502,yymsp[0].minor.yy590); - if( yymsp[-9].minor.yy637 ){ - yymsp[-9].minor.yy637->pWinDefn = yymsp[-2].minor.yy483; - }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy483); - } -} - break; - case 94: /* values ::= VALUES LP nexprlist RP */ -{ - yymsp[-3].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0); -} - break; - case 95: /* oneselect ::= mvalues */ -{ - sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy637); -} - break; - case 96: /* mvalues ::= values COMMA LP nexprlist RP */ - case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97); -{ - yymsp[-4].minor.yy637 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy637, yymsp[-1].minor.yy402); -} - break; - case 98: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy502 = SF_Distinct;} - break; - case 99: /* distinct ::= ALL */ -{yymsp[0].minor.yy502 = SF_All;} - break; - case 101: /* sclp ::= */ - case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134); - case 144: /* groupby_opt ::= */ yytestcase(yyruleno==144); - case 234: /* exprlist ::= */ yytestcase(yyruleno==234); - case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237); - case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242); -{yymsp[1].minor.yy402 = 0;} - break; - case 102: /* selcollist ::= sclp scanpt expr scanpt as */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy342,yymsp[-1].minor.yy342); -} - break; - case 103: /* selcollist ::= sclp scanpt STAR */ + yymsp[-2].minor.yy243 = pRhs; +} + break; + case 81: /* multiselect_op ::= UNION */ + case 83: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==83); +{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-OP*/} + break; + case 82: /* multiselect_op ::= UNION ALL */ +{yymsp[-1].minor.yy194 = TK_ALL;} + break; + case 84: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ +{ +#if SELECTTRACE_ENABLED + Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ +#endif + yymsp[-8].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset); +#if SELECTTRACE_ENABLED + /* Populate the Select.zSelName[] string that is used to help with + ** query planner debugging, to differentiate between multiple Select + ** objects in a complex query. + ** + ** If the SELECT keyword is immediately followed by a C-style comment + ** then extract the first few alphanumeric characters from within that + ** comment to be the zSelName value. Otherwise, the label is #N where + ** is an integer that is incremented with each SELECT statement seen. + */ + if( yymsp[-8].minor.yy243!=0 ){ + const char *z = s.z+6; + int i; + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "#%d", + ++pParse->nSelect); + while( z[0]==' ' ) z++; + if( z[0]=='/' && z[1]=='*' ){ + z += 2; + while( z[0]==' ' ) z++; + for(i=0; sqlite3Isalnum(z[i]); i++){} + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "%.*s", i, z); + } + } +#endif /* SELECTRACE_ENABLED */ +} + break; + case 85: /* values ::= VALUES LP nexprlist RP */ +{ + yymsp[-3].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values,0,0); +} + break; + case 86: /* values ::= values COMMA LP exprlist RP */ +{ + Select *pRight, *pLeft = yymsp[-4].minor.yy243; + pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); + if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; + if( pRight ){ + pRight->op = TK_ALL; + pRight->pPrior = pLeft; + yymsp[-4].minor.yy243 = pRight; + }else{ + yymsp[-4].minor.yy243 = pLeft; + } +} + break; + case 87: /* distinct ::= DISTINCT */ +{yymsp[0].minor.yy194 = SF_Distinct;} + break; + case 88: /* distinct ::= ALL */ +{yymsp[0].minor.yy194 = SF_All;} + break; + case 90: /* sclp ::= */ + case 118: /* orderby_opt ::= */ yytestcase(yyruleno==118); + case 125: /* groupby_opt ::= */ yytestcase(yyruleno==125); + case 200: /* exprlist ::= */ yytestcase(yyruleno==200); + case 203: /* paren_exprlist ::= */ yytestcase(yyruleno==203); + case 208: /* eidlist_opt ::= */ yytestcase(yyruleno==208); +{yymsp[1].minor.yy148 = 0;} + break; + case 91: /* selcollist ::= sclp expr as */ +{ + yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy148, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy148,&yymsp[-1].minor.yy190); +} + break; + case 92: /* selcollist ::= sclp STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p); -} - break; - case 104: /* selcollist ::= sclp scanpt nm DOT STAR */ -{ - Expr *pRight, *pLeft, *pDot; - pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); - pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot); -} - break; - case 105: /* as ::= AS nm */ - case 117: /* dbnm ::= DOT nm */ yytestcase(yyruleno==117); - case 258: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==258); - case 259: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==259); + yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); +} + break; + case 93: /* selcollist ::= sclp nm DOT STAR */ +{ + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); + Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); + yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); +} + break; + case 94: /* as ::= AS nm */ + case 105: /* dbnm ::= DOT nm */ yytestcase(yyruleno==105); + case 222: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==222); + case 223: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==223); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; - case 107: /* from ::= */ - case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110); -{yymsp[1].minor.yy563 = 0;} - break; - case 108: /* from ::= FROM seltablist */ -{ - yymsp[-1].minor.yy563 = yymsp[0].minor.yy563; - sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy563); -} - break; - case 109: /* stl_prefix ::= seltablist joinop */ -{ - if( ALWAYS(yymsp[-1].minor.yy563 && yymsp[-1].minor.yy563->nSrc>0) ) yymsp[-1].minor.yy563->a[yymsp[-1].minor.yy563->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502; -} - break; - case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */ -{ - yymsp[-4].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy563,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); -} - break; - case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ -{ - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy421); - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-1].minor.yy0); -} - break; - case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ -{ - yymsp[-7].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy563,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); - sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy563, yymsp[-3].minor.yy402); -} - break; - case 114: /* seltablist ::= stl_prefix LP select RP as on_using */ -{ - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy637,&yymsp[0].minor.yy421); - } - break; - case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ -{ - if( yymsp[-5].minor.yy563==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy421.pOn==0 && yymsp[0].minor.yy421.pUsing==0 ){ - yymsp[-5].minor.yy563 = yymsp[-3].minor.yy563; - }else if( ALWAYS(yymsp[-3].minor.yy563!=0) && yymsp[-3].minor.yy563->nSrc==1 ){ - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); - if( yymsp[-5].minor.yy563 ){ - SrcItem *pNew = &yymsp[-5].minor.yy563->a[yymsp[-5].minor.yy563->nSrc-1]; - SrcItem *pOld = yymsp[-3].minor.yy563->a; - assert( pOld->fg.fixedSchema==0 ); + case 96: /* from ::= */ +{yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} + break; + case 97: /* from ::= FROM seltablist */ +{ + yymsp[-1].minor.yy185 = yymsp[0].minor.yy185; + sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy185); +} + break; + case 98: /* stl_prefix ::= seltablist joinop */ +{ + if( ALWAYS(yymsp[-1].minor.yy185 && yymsp[-1].minor.yy185->nSrc>0) ) yymsp[-1].minor.yy185->a[yymsp[-1].minor.yy185->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy194; +} + break; + case 99: /* stl_prefix ::= */ +{yymsp[1].minor.yy185 = 0;} + break; + case 100: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ +{ + yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy185, &yymsp[-2].minor.yy0); +} + break; + case 101: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ +{ + yymsp[-8].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy185,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy185, yymsp[-4].minor.yy148); +} + break; + case 102: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ +{ + yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + } + break; + case 103: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ +{ + if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){ + yymsp[-6].minor.yy185 = yymsp[-4].minor.yy185; + }else if( yymsp[-4].minor.yy185->nSrc==1 ){ + yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); + if( yymsp[-6].minor.yy185 ){ + struct SrcList_item *pNew = &yymsp[-6].minor.yy185->a[yymsp[-6].minor.yy185->nSrc-1]; + struct SrcList_item *pOld = yymsp[-4].minor.yy185->a; pNew->zName = pOld->zName; - assert( pOld->fg.fixedSchema==0 ); - if( pOld->fg.isSubquery ){ - pNew->fg.isSubquery = 1; - pNew->u4.pSubq = pOld->u4.pSubq; - pOld->u4.pSubq = 0; - pOld->fg.isSubquery = 0; - assert( pNew->u4.pSubq!=0 && pNew->u4.pSubq->pSelect!=0 ); - if( (pNew->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0 ){ - pNew->fg.isNestedFrom = 1; - } - }else{ - pNew->u4.zDatabase = pOld->u4.zDatabase; - pOld->u4.zDatabase = 0; - } - if( pOld->fg.isTabFunc ){ - pNew->u1.pFuncArg = pOld->u1.pFuncArg; - pOld->u1.pFuncArg = 0; - pOld->fg.isTabFunc = 0; - pNew->fg.isTabFunc = 1; - } - pOld->zName = 0; - } - sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy563); + pNew->zDatabase = pOld->zDatabase; + pNew->pSelect = pOld->pSelect; + pOld->zName = pOld->zDatabase = 0; + pOld->pSelect = 0; + } + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy185); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy563); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy563,0,0,0,0,SF_NestedFrom,0); - yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy421); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy185); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy185,0,0,0,0,SF_NestedFrom,0,0); + yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); } } break; - case 116: /* dbnm ::= */ - case 131: /* indexed_opt ::= */ yytestcase(yyruleno==131); + case 104: /* dbnm ::= */ + case 113: /* indexed_opt ::= */ yytestcase(yyruleno==113); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 118: /* fullname ::= nm */ -{ - yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); -} - yymsp[0].minor.yy563 = yylhsminor.yy563; - break; - case 119: /* fullname ::= nm DOT nm */ -{ - yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); -} - yymsp[-2].minor.yy563 = yylhsminor.yy563; - break; - case 120: /* xfullname ::= nm */ -{yymsp[0].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} - break; - case 121: /* xfullname ::= nm DOT nm */ -{yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} - break; - case 122: /* xfullname ::= nm DOT nm AS nm */ -{ - yymsp[-4].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ - if( yymsp[-4].minor.yy563 ) yymsp[-4].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); -} - break; - case 123: /* xfullname ::= nm AS nm */ -{ - yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ - if( yymsp[-2].minor.yy563 ) yymsp[-2].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); -} - break; - case 124: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy502 = JT_INNER; } - break; - case 125: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} - break; - case 126: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} - break; - case 127: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} - break; - case 128: /* on_using ::= ON expr */ -{yymsp[-1].minor.yy421.pOn = yymsp[0].minor.yy590; yymsp[-1].minor.yy421.pUsing = 0;} - break; - case 129: /* on_using ::= USING LP idlist RP */ -{yymsp[-3].minor.yy421.pOn = 0; yymsp[-3].minor.yy421.pUsing = yymsp[-1].minor.yy204;} - break; - case 130: /* on_using ::= */ -{yymsp[1].minor.yy421.pOn = 0; yymsp[1].minor.yy421.pUsing = 0;} - break; - case 132: /* indexed_by ::= INDEXED BY nm */ + case 106: /* fullname ::= nm dbnm */ +{yymsp[-1].minor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 107: /* joinop ::= COMMA|JOIN */ +{ yymsp[0].minor.yy194 = JT_INNER; } + break; + case 108: /* joinop ::= JOIN_KW JOIN */ +{yymsp[-1].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} + break; + case 109: /* joinop ::= JOIN_KW nm JOIN */ +{yymsp[-2].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} + break; + case 110: /* joinop ::= JOIN_KW nm nm JOIN */ +{yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} + break; + case 111: /* on_opt ::= ON expr */ + case 128: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==128); + case 135: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==135); + case 196: /* case_else ::= ELSE expr */ yytestcase(yyruleno==196); +{yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} + break; + case 112: /* on_opt ::= */ + case 127: /* having_opt ::= */ yytestcase(yyruleno==127); + case 134: /* where_opt ::= */ yytestcase(yyruleno==134); + case 197: /* case_else ::= */ yytestcase(yyruleno==197); + case 199: /* case_operand ::= */ yytestcase(yyruleno==199); +{yymsp[1].minor.yy72 = 0;} + break; + case 114: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 133: /* indexed_by ::= NOT INDEXED */ + case 115: /* indexed_opt ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 135: /* orderby_opt ::= ORDER BY sortlist */ - case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145); -{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;} - break; - case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); -} - break; - case 137: /* sortlist ::= expr sortorder nulls */ -{ - yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy590); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); -} - break; - case 138: /* sortorder ::= ASC */ -{yymsp[0].minor.yy502 = SQLITE_SO_ASC;} - break; - case 139: /* sortorder ::= DESC */ -{yymsp[0].minor.yy502 = SQLITE_SO_DESC;} - break; - case 140: /* sortorder ::= */ - case 143: /* nulls ::= */ yytestcase(yyruleno==143); -{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;} - break; - case 141: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy502 = SQLITE_SO_ASC;} - break; - case 142: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy502 = SQLITE_SO_DESC;} - break; - case 146: /* having_opt ::= */ - case 148: /* limit_opt ::= */ yytestcase(yyruleno==148); - case 153: /* where_opt ::= */ yytestcase(yyruleno==153); - case 155: /* where_opt_ret ::= */ yytestcase(yyruleno==155); - case 232: /* case_else ::= */ yytestcase(yyruleno==232); - case 233: /* case_operand ::= */ yytestcase(yyruleno==233); - case 252: /* vinto ::= */ yytestcase(yyruleno==252); -{yymsp[1].minor.yy590 = 0;} - break; - case 147: /* having_opt ::= HAVING expr */ - case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154); - case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156); - case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); - case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251); -{yymsp[-1].minor.yy590 = yymsp[0].minor.yy590;} - break; - case 149: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,0);} - break; - case 150: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} - break; - case 151: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,yymsp[-2].minor.yy590);} - break; - case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ -{ - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy563, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy563,yymsp[0].minor.yy590,0,0); -} - break; - case 157: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-1].minor.yy590 = 0;} - break; - case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-3].minor.yy590 = yymsp[-2].minor.yy590;} - break; - case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ -{ - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy402,"set list"); - if( yymsp[-1].minor.yy563 ){ - SrcList *pFromClause = yymsp[-1].minor.yy563; - if( pFromClause->nSrc>1 ){ - Select *pSubquery; - Token as; - pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0); - as.n = 0; - as.z = 0; - pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); - } - yymsp[-5].minor.yy563 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy563, pFromClause); - } - sqlite3Update(pParse,yymsp[-5].minor.yy563,yymsp[-2].minor.yy402,yymsp[0].minor.yy590,yymsp[-6].minor.yy502,0,0,0); -} - break; - case 160: /* setlist ::= setlist COMMA nm EQ expr */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy590); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1); -} - break; - case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ -{ - yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); -} - break; - case 162: /* setlist ::= nm EQ expr */ -{ - yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy590); - sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1); -} - yymsp[-2].minor.yy402 = yylhsminor.yy402; - break; - case 163: /* setlist ::= LP idlist RP EQ expr */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); -} - break; - case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ -{ - sqlite3Insert(pParse, yymsp[-3].minor.yy563, yymsp[-1].minor.yy637, yymsp[-2].minor.yy204, yymsp[-5].minor.yy502, yymsp[0].minor.yy403); -} - break; - case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ -{ - sqlite3Insert(pParse, yymsp[-4].minor.yy563, 0, yymsp[-3].minor.yy204, yymsp[-6].minor.yy502, 0); -} - break; - case 166: /* upsert ::= */ -{ yymsp[1].minor.yy403 = 0; } - break; - case 167: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy403 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy402); } - break; - case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy402,yymsp[-6].minor.yy590,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,yymsp[0].minor.yy403);} - break; - case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy402,yymsp[-3].minor.yy590,0,0,yymsp[0].minor.yy403); } - break; - case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } - break; - case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,0);} - break; - case 172: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy402);} - break; - case 175: /* idlist_opt ::= */ -{yymsp[1].minor.yy204 = 0;} - break; - case 176: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy204 = yymsp[-1].minor.yy204;} - break; - case 177: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy204 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy204,&yymsp[0].minor.yy0);} - break; - case 178: /* idlist ::= nm */ -{yymsp[0].minor.yy204 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} - break; - case 179: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy590 = yymsp[-1].minor.yy590;} - break; - case 180: /* expr ::= ID|INDEXED|JOIN_KW */ -{yymsp[0].minor.yy590=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} - break; - case 181: /* expr ::= nm DOT nm */ -{ - Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); - Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); - yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); -} - yymsp[-2].minor.yy590 = yylhsminor.yy590; - break; - case 182: /* expr ::= nm DOT nm DOT nm */ -{ - Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-4].minor.yy0); - Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); - Expr *temp3 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); + case 116: /* using_opt ::= USING LP idlist RP */ +{yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;} + break; + case 117: /* using_opt ::= */ + case 145: /* idlist_opt ::= */ yytestcase(yyruleno==145); +{yymsp[1].minor.yy254 = 0;} + break; + case 119: /* orderby_opt ::= ORDER BY sortlist */ + case 126: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==126); +{yymsp[-2].minor.yy148 = yymsp[0].minor.yy148;} + break; + case 120: /* sortlist ::= sortlist COMMA expr sortorder */ +{ + yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy190.pExpr); + sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy148,yymsp[0].minor.yy194); +} + break; + case 121: /* sortlist ::= expr sortorder */ +{ + yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy190.pExpr); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy148,yymsp[0].minor.yy194); +} + break; + case 122: /* sortorder ::= ASC */ +{yymsp[0].minor.yy194 = SQLITE_SO_ASC;} + break; + case 123: /* sortorder ::= DESC */ +{yymsp[0].minor.yy194 = SQLITE_SO_DESC;} + break; + case 124: /* sortorder ::= */ +{yymsp[1].minor.yy194 = SQLITE_SO_UNDEFINED;} + break; + case 129: /* limit_opt ::= */ +{yymsp[1].minor.yy354.pLimit = 0; yymsp[1].minor.yy354.pOffset = 0;} + break; + case 130: /* limit_opt ::= LIMIT expr */ +{yymsp[-1].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr; yymsp[-1].minor.yy354.pOffset = 0;} + break; + case 131: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yymsp[-3].minor.yy354.pLimit = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pOffset = yymsp[0].minor.yy190.pExpr;} + break; + case 132: /* limit_opt ::= LIMIT expr COMMA expr */ +{yymsp[-3].minor.yy354.pOffset = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr;} + break; + case 133: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ +{ + sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72); +} + break; + case 136: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ +{ + sqlite3WithPush(pParse, yymsp[-7].minor.yy285, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy148,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy194); +} + break; + case 137: /* setlist ::= setlist COMMA nm EQ expr */ +{ + yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, 1); +} + break; + case 138: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ +{ + yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); +} + break; + case 139: /* setlist ::= nm EQ expr */ +{ + yylhsminor.yy148 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr); + sqlite3ExprListSetName(pParse, yylhsminor.yy148, &yymsp[-2].minor.yy0, 1); +} + yymsp[-2].minor.yy148 = yylhsminor.yy148; + break; + case 140: /* setlist ::= LP idlist RP EQ expr */ +{ + yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); +} + break; + case 141: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ +{ + sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); + sqlite3Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194); +} + break; + case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ +{ + sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1); + sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194); +} + break; + case 146: /* idlist_opt ::= LP idlist RP */ +{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} + break; + case 147: /* idlist ::= idlist COMMA nm */ +{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} + break; + case 148: /* idlist ::= nm */ +{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} + break; + case 149: /* expr ::= LP expr RP */ +{spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} + break; + case 150: /* expr ::= ID|INDEXED */ + case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151); +{spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 152: /* expr ::= nm DOT nm */ +{ + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); + spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ + yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); +} + break; + case 153: /* expr ::= nm DOT nm DOT nm */ +{ + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, 0, temp1); - } - yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); -} - yymsp[-4].minor.yy590 = yylhsminor.yy590; - break; - case 183: /* term ::= NULL|FLOAT|BLOB */ - case 184: /* term ::= STRING */ yytestcase(yyruleno==184); -{yymsp[0].minor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} - break; - case 185: /* term ::= INTEGER */ -{ - yylhsminor.yy590 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); - if( yylhsminor.yy590 ) yylhsminor.yy590->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); -} - yymsp[0].minor.yy590 = yylhsminor.yy590; - break; - case 186: /* expr ::= VARIABLE */ + spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); +} + break; + case 154: /* term ::= NULL|FLOAT|BLOB */ + case 155: /* term ::= STRING */ yytestcase(yyruleno==155); +{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 156: /* term ::= INTEGER */ +{ + yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; + yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; +} + yymsp[0].minor.yy190 = yylhsminor.yy190; + break; + case 157: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy590 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy590, n); + spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers ** in the virtual machine. #N is the N-th register. */ Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ assert( t.n>=2 ); + spanSet(&yymsp[0].minor.yy190, &t, &t); if( pParse->nested==0 ){ - parserSyntaxError(pParse, &t); - yymsp[0].minor.yy590 = 0; - }else{ - yymsp[0].minor.yy590 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy590 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy590->iTable); - } - } -} - break; - case 187: /* expr ::= expr COLLATE ID|STRING */ -{ - yymsp[-2].minor.yy590 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy590, &yymsp[0].minor.yy0, 1); -} - break; - case 188: /* expr ::= CAST LP expr AS typetoken RP */ -{ - yymsp[-5].minor.yy590 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy590, yymsp[-3].minor.yy590, 0); -} - break; - case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502); -} - yymsp[-4].minor.yy590 = yylhsminor.yy590; - break; - case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy402, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy502); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-1].minor.yy402); -} - yymsp[-7].minor.yy590 = yylhsminor.yy590; - break; - case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); -} - yymsp[-3].minor.yy590 = yylhsminor.yy590; - break; - case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy402, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy502); - sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); -} - yymsp[-5].minor.yy590 = yylhsminor.yy590; - break; - case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy402, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy502); - sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-2].minor.yy402); -} - yymsp[-8].minor.yy590 = yylhsminor.yy590; - break; - case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); -} - yymsp[-4].minor.yy590 = yylhsminor.yy590; - break; - case 195: /* term ::= CTIME_KW */ -{ - yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); -} - yymsp[0].minor.yy590 = yylhsminor.yy590; - break; - case 196: /* expr ::= LP nexprlist COMMA expr RP */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy590 ){ - yymsp[-4].minor.yy590->x.pList = pList; - if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy590->flags |= pList->a[0].pExpr->flags & EP_Propagate; - } + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); + yymsp[0].minor.yy190.pExpr = 0; + }else{ + yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); + } + } +} + break; + case 158: /* expr ::= expr COLLATE ID|STRING */ +{ + yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; +} + break; + case 159: /* expr ::= CAST LP expr AS typetoken RP */ +{ + spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ + yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0); +} + break; + case 160: /* expr ::= ID|INDEXED LP distinct exprlist RP */ +{ + if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); + } + yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); + spanSet(&yylhsminor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy194==SF_Distinct && yylhsminor.yy190.pExpr ){ + yylhsminor.yy190.pExpr->flags |= EP_Distinct; + } +} + yymsp[-4].minor.yy190 = yylhsminor.yy190; + break; + case 161: /* expr ::= ID|INDEXED LP STAR RP */ +{ + yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); +} + yymsp[-3].minor.yy190 = yylhsminor.yy190; + break; + case 162: /* term ::= CTIME_KW */ +{ + yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); + spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); +} + yymsp[0].minor.yy190 = yylhsminor.yy190; + break; + case 163: /* expr ::= LP nexprlist COMMA expr RP */ +{ + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); + yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yylhsminor.yy190.pExpr ){ + yylhsminor.yy190.pExpr->x.pList = pList; + spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); }else{ sqlite3ExprListDelete(pParse->db, pList); } } - break; - case 197: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy590=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} - break; - case 198: /* expr ::= expr OR expr */ - case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199); - case 200: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==200); - case 201: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==201); - case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202); - case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203); - case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204); -{yymsp[-2].minor.yy590=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} - break; - case 205: /* likeop ::= NOT LIKE_KW|MATCH */ + yymsp[-4].minor.yy190 = yylhsminor.yy190; + break; + case 164: /* expr ::= expr AND expr */ + case 165: /* expr ::= expr OR expr */ yytestcase(yyruleno==165); + case 166: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==166); + case 167: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==167); + case 168: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==168); + case 169: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==169); + case 170: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==170); + case 171: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==171); +{spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} + break; + case 172: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 206: /* expr ::= expr likeop expr */ + case 173: /* expr ::= expr likeop expr */ { ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy590); - yymsp[-2].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy590, 0); - if( yymsp[-2].minor.yy590 ) yymsp[-2].minor.yy590->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); + yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); + exprNot(pParse, bNot, &yymsp[-2].minor.yy190); + yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; + if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 207: /* expr ::= expr likeop expr ESCAPE expr */ + case 174: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - if( yymsp[-4].minor.yy590 ) yymsp[-4].minor.yy590->flags |= EP_InfixFunc; -} - break; - case 208: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy590,0);} - break; - case 209: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy590,0);} - break; - case 210: /* expr ::= expr IS expr */ -{ - yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-2].minor.yy590, TK_ISNULL); -} - break; - case 211: /* expr ::= expr IS NOT expr */ -{ - yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-3].minor.yy590, TK_NOTNULL); -} - break; - case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */ -{ - yymsp[-5].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-5].minor.yy590, TK_ISNULL); -} - break; - case 213: /* expr ::= expr IS DISTINCT FROM expr */ -{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy590,yymsp[0].minor.yy590); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-4].minor.yy590, TK_NOTNULL); -} - break; - case 214: /* expr ::= NOT expr */ - case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); -{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy590, 0);/*A-overwrites-B*/} - break; - case 216: /* expr ::= PLUS|MINUS expr */ -{ - Expr *p = yymsp[0].minor.yy590; - u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS); - assert( TK_UPLUS>TK_PLUS ); - assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) ); - if( p && p->op==TK_UPLUS ){ - p->op = op; - yymsp[-1].minor.yy590 = p; - }else{ - yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, op, p, 0); - /*A-overwrites-B*/ - } -} - break; - case 217: /* expr ::= expr PTR expr */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy590); - pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy590); - yylhsminor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); -} - yymsp[-2].minor.yy590 = yylhsminor.yy590; - break; - case 218: /* between_op ::= BETWEEN */ - case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); -{yymsp[0].minor.yy502 = 0;} - break; - case 220: /* expr ::= expr between_op expr AND expr */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy590, 0); - if( yymsp[-4].minor.yy590 ){ - yymsp[-4].minor.yy590->x.pList = pList; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); + yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); + exprNot(pParse, bNot, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; + if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; +} + break; + case 175: /* expr ::= expr ISNULL|NOTNULL */ +{spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} + break; + case 176: /* expr ::= expr NOT NULL */ +{spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} + break; + case 177: /* expr ::= expr IS expr */ +{ + spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); +} + break; + case 178: /* expr ::= expr IS NOT expr */ +{ + spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); +} + break; + case 179: /* expr ::= NOT expr */ + case 180: /* expr ::= BITNOT expr */ yytestcase(yyruleno==180); +{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + break; + case 181: /* expr ::= MINUS expr */ +{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + break; + case 182: /* expr ::= PLUS expr */ +{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} + break; + case 183: /* between_op ::= BETWEEN */ + case 186: /* in_op ::= IN */ yytestcase(yyruleno==186); +{yymsp[0].minor.yy194 = 0;} + break; + case 185: /* expr ::= expr between_op expr AND expr */ +{ + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); + if( yymsp[-4].minor.yy190.pExpr ){ + yymsp[-4].minor.yy190.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); - } - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); + } + exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; } break; - case 223: /* expr ::= expr in_op LP exprlist RP */ + case 188: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy402==0 ){ + if( yymsp[-1].minor.yy148==0 ){ /* Expressions of the form ** ** expr1 IN () ** expr1 NOT IN () ** ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy590); - yymsp[-4].minor.yy590 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy502 ? "true" : "false"); - if( yymsp[-4].minor.yy590 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy590); - }else{ - Expr *pRHS = yymsp[-1].minor.yy402->a[0].pExpr; - if( yymsp[-1].minor.yy402->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy590->op!=TK_VECTOR ){ - yymsp[-1].minor.yy402->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); - pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy590, pRHS); - }else if( yymsp[-1].minor.yy402->nExpr==1 && pRHS->op==TK_SELECT ){ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pRHS->x.pSelect); - pRHS->x.pSelect = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); - }else{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - if( yymsp[-4].minor.yy590==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); - }else if( yymsp[-4].minor.yy590->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy590->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy402); - if( pSelectRHS ){ - parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelectRHS); - } - }else{ - yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy402; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); - } - } - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - } - } - break; - case 224: /* expr ::= LP select RP */ -{ - yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy590, yymsp[-1].minor.yy637); - } - break; - case 225: /* expr ::= expr in_op LP select RP */ -{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, yymsp[-1].minor.yy637); - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - } - break; - case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */ -{ - SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); - Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402); - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelect); - if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); - } - break; - case 227: /* expr ::= EXISTS LP select RP */ + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr); + yymsp[-4].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy194],1); + }else if( yymsp[-1].minor.yy148->nExpr==1 ){ + /* Expressions of the form: + ** + ** expr1 IN (?1) + ** expr1 NOT IN (?2) + ** + ** with exactly one value on the RHS can be simplified to something + ** like this: + ** + ** expr1 == ?1 + ** expr1 <> ?2 + ** + ** But, the RHS of the == or <> is marked with the EP_Generic flag + ** so that it may not contribute to the computation of comparison + ** affinity or the collating sequence to use for comparison. Otherwise, + ** the semantics would be subtly different from IN or NOT IN. + */ + Expr *pRHS = yymsp[-1].minor.yy148->a[0].pExpr; + yymsp[-1].minor.yy148->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); + /* pRHS cannot be NULL because a malloc error would have been detected + ** before now and control would have never reached this point */ + if( ALWAYS(pRHS) ){ + pRHS->flags &= ~EP_Collate; + pRHS->flags |= EP_Generic; + } + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS); + }else{ + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); + if( yymsp[-4].minor.yy190.pExpr ){ + yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); + }else{ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); + } + exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); + } + yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + } + break; + case 189: /* expr ::= LP select RP */ +{ + spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ + yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); + } + break; + case 190: /* expr ::= expr in_op LP select RP */ +{ + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); + exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + } + break; + case 191: /* expr ::= expr in_op nm dbnm paren_exprlist */ +{ + SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); + Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); + exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); + yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; + } + break; + case 192: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy637); - } - break; - case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ -{ - yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy590, 0); - if( yymsp[-4].minor.yy590 ){ - yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy590 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590) : yymsp[-2].minor.yy402; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); - }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); - } -} - break; - case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ -{ - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); - yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy590); -} - break; - case 230: /* case_exprlist ::= WHEN expr THEN expr */ -{ - yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); - yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy590); -} - break; - case 235: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy590);} - break; - case 236: /* nexprlist ::= expr */ -{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy590); /*A-overwrites-Y*/} - break; - case 238: /* paren_exprlist ::= LP exprlist RP */ - case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243); -{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;} - break; - case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ -{ - sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy502, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy590, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF); - if( IN_RENAME_OBJECT && pParse->pNewIndex ){ - sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); - } -} - break; - case 240: /* uniqueflag ::= UNIQUE */ - case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282); -{yymsp[0].minor.yy502 = OE_Abort;} - break; - case 241: /* uniqueflag ::= */ -{yymsp[1].minor.yy502 = OE_None;} - break; - case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */ -{ - yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); -} - break; - case 245: /* eidlist ::= nm collate sortorder */ -{ - yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/ -} - break; - case 248: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy563, yymsp[-1].minor.yy502);} - break; - case 249: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy590);} - break; - case 250: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy590);} - break; - case 253: /* cmd ::= PRAGMA nm dbnm */ + spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ + p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); + } + break; + case 193: /* expr ::= CASE case_operand case_exprlist case_else END */ +{ + spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); + if( yymsp[-4].minor.yy190.pExpr ){ + yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); + }else{ + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); + } +} + break; + case 194: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ +{ + yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); + yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); +} + break; + case 195: /* case_exprlist ::= WHEN expr THEN expr */ +{ + yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); + yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); +} + break; + case 198: /* case_operand ::= expr */ +{yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} + break; + case 201: /* nexprlist ::= nexprlist COMMA expr */ +{yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} + break; + case 202: /* nexprlist ::= expr */ +{yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} + break; + case 204: /* paren_exprlist ::= LP exprlist RP */ + case 209: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==209); +{yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} + break; + case 205: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ +{ + sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, + sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); +} + break; + case 206: /* uniqueflag ::= UNIQUE */ + case 246: /* raisetype ::= ABORT */ yytestcase(yyruleno==246); +{yymsp[0].minor.yy194 = OE_Abort;} + break; + case 207: /* uniqueflag ::= */ +{yymsp[1].minor.yy194 = OE_None;} + break; + case 210: /* eidlist ::= eidlist COMMA nm collate sortorder */ +{ + yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); +} + break; + case 211: /* eidlist ::= nm collate sortorder */ +{ + yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ +} + break; + case 214: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} + break; + case 215: /* cmd ::= VACUUM */ +{sqlite3Vacuum(pParse,0);} + break; + case 216: /* cmd ::= VACUUM nm */ +{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} + break; + case 217: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 254: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 218: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 255: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 219: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 256: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 220: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 257: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 221: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 260: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 224: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy319, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); } break; - case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 225: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 262: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ } - break; - case 263: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy502 = TK_INSTEAD;} - break; - case 264: /* trigger_time ::= */ -{ yymsp[1].minor.yy502 = TK_BEFORE; } - break; - case 265: /* trigger_event ::= DELETE|INSERT */ - case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266); -{yymsp[0].minor.yy28.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy28.b = 0;} - break; - case 267: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy28.a = TK_UPDATE; yymsp[-2].minor.yy28.b = yymsp[0].minor.yy204;} - break; - case 268: /* when_clause ::= */ - case 287: /* key_opt ::= */ yytestcase(yyruleno==287); -{ yymsp[1].minor.yy590 = 0; } - break; - case 269: /* when_clause ::= WHEN expr */ - case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288); -{ yymsp[-1].minor.yy590 = yymsp[0].minor.yy590; } - break; - case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ -{ - assert( yymsp[-2].minor.yy319!=0 ); - yymsp[-2].minor.yy319->pLast->pNext = yymsp[-1].minor.yy319; - yymsp[-2].minor.yy319->pLast = yymsp[-1].minor.yy319; -} - break; - case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */ -{ - assert( yymsp[-1].minor.yy319!=0 ); - yymsp[-1].minor.yy319->pLast = yymsp[-1].minor.yy319; -} - break; - case 272: /* trnm ::= nm DOT nm */ + case 226: /* trigger_time ::= BEFORE|AFTER */ +{ yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/ } + break; + case 227: /* trigger_time ::= INSTEAD OF */ +{ yymsp[-1].minor.yy194 = TK_INSTEAD;} + break; + case 228: /* trigger_time ::= */ +{ yymsp[1].minor.yy194 = TK_BEFORE; } + break; + case 229: /* trigger_event ::= DELETE|INSERT */ + case 230: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==230); +{yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} + break; + case 231: /* trigger_event ::= UPDATE OF idlist */ +{yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} + break; + case 232: /* when_clause ::= */ + case 251: /* key_opt ::= */ yytestcase(yyruleno==251); +{ yymsp[1].minor.yy72 = 0; } + break; + case 233: /* when_clause ::= WHEN expr */ + case 252: /* key_opt ::= KEY expr */ yytestcase(yyruleno==252); +{ yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } + break; + case 234: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ +{ + assert( yymsp[-2].minor.yy145!=0 ); + yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; + yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; +} + break; + case 235: /* trigger_cmd_list ::= trigger_cmd SEMI */ +{ + assert( yymsp[-1].minor.yy145!=0 ); + yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; +} + break; + case 236: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; - sqlite3ErrorMsg(pParse, + sqlite3ErrorMsg(pParse, "qualified table names are not allowed on INSERT, UPDATE, and DELETE " "statements within triggers"); } break; - case 273: /* tridxby ::= INDEXED BY nm */ + case 237: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 274: /* tridxby ::= NOT INDEXED */ + case 238: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy319 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy563, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590, yymsp[-7].minor.yy502, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy342);} - yymsp[-8].minor.yy319 = yylhsminor.yy319; - break; - case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ -{ - yylhsminor.yy319 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy204,yymsp[-2].minor.yy637,yymsp[-6].minor.yy502,yymsp[-1].minor.yy403,yymsp[-7].minor.yy342,yymsp[0].minor.yy342);/*yylhsminor.yy319-overwrites-yymsp[-6].minor.yy502*/ -} - yymsp[-7].minor.yy319 = yylhsminor.yy319; - break; - case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ -{yylhsminor.yy319 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy590, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy342);} - yymsp[-5].minor.yy319 = yylhsminor.yy319; - break; - case 278: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy319 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy637, yymsp[-2].minor.yy342, yymsp[0].minor.yy342); /*yylhsminor.yy319-overwrites-yymsp[-1].minor.yy637*/} - yymsp[-2].minor.yy319 = yylhsminor.yy319; - break; - case 279: /* expr ::= RAISE LP IGNORE RP */ -{ - yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy590 ){ - yymsp[-3].minor.yy590->affExpr = OE_Ignore; - } -} - break; - case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */ -{ - yymsp[-5].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy590, 0); - if( yymsp[-5].minor.yy590 ) { - yymsp[-5].minor.yy590->affExpr = (char)yymsp[-3].minor.yy502; - } -} - break; - case 281: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy502 = OE_Rollback;} - break; - case 283: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy502 = OE_Fail;} - break; - case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ -{ - sqlite3DropTrigger(pParse,yymsp[0].minor.yy563,yymsp[-1].minor.yy502); -} - break; - case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ -{ - sqlite3Attach(pParse, yymsp[-3].minor.yy590, yymsp[-1].minor.yy590, yymsp[0].minor.yy590); -} - break; - case 286: /* cmd ::= DETACH database_kw_opt expr */ -{ - sqlite3Detach(pParse, yymsp[0].minor.yy590); -} - break; - case 289: /* cmd ::= REINDEX */ + case 239: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ +{yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} + break; + case 240: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ +{yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} + break; + case 241: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ +{yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} + break; + case 242: /* trigger_cmd ::= select */ +{yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} + break; + case 243: /* expr ::= RAISE LP IGNORE RP */ +{ + spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ + yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy190.pExpr ){ + yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; + } +} + break; + case 244: /* expr ::= RAISE LP raisetype COMMA nm RP */ +{ + spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ + yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + if( yymsp[-5].minor.yy190.pExpr ) { + yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; + } +} + break; + case 245: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy194 = OE_Rollback;} + break; + case 247: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy194 = OE_Fail;} + break; + case 248: /* cmd ::= DROP TRIGGER ifexists fullname */ +{ + sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); +} + break; + case 249: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ +{ + sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); +} + break; + case 250: /* cmd ::= DETACH database_kw_opt expr */ +{ + sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); +} + break; + case 253: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 290: /* cmd ::= REINDEX nm dbnm */ + case 254: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 291: /* cmd ::= ANALYZE */ + case 255: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 292: /* cmd ::= ANALYZE nm dbnm */ + case 256: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 257: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy563,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); } break; - case 294: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 258: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ -{ - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy563, &yymsp[0].minor.yy0); -} - break; - case 296: /* add_column_fullname ::= fullname */ + case 259: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy563); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); } break; - case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ -{ - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy563, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); -} - break; - case 298: /* cmd ::= create_vtab */ + case 260: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 299: /* cmd ::= create_vtab LP vtabarglist RP */ + case 261: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 262: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); } break; - case 301: /* vtabarg ::= */ + case 263: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 302: /* vtabargtoken ::= ANY */ - case 303: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==303); - case 304: /* lp ::= LP */ yytestcase(yyruleno==304); + case 264: /* vtabargtoken ::= ANY */ + case 265: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==265); + case 266: /* lp ::= LP */ yytestcase(yyruleno==266); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 305: /* with ::= WITH wqlist */ - case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy125, 1); } - break; - case 307: /* wqas ::= AS */ -{yymsp[0].minor.yy444 = M10d_Any;} - break; - case 308: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy444 = M10d_Yes;} - break; - case 309: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy444 = M10d_No;} - break; - case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ -{ - yymsp[-5].minor.yy361 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy637, yymsp[-3].minor.yy444); /*A-overwrites-X*/ -} - break; - case 311: /* withnm ::= nm */ -{pParse->bHasWith = 1;} - break; - case 312: /* wqlist ::= wqitem */ -{ - yymsp[0].minor.yy125 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy361); /*A-overwrites-X*/ -} - break; - case 313: /* wqlist ::= wqlist COMMA wqitem */ -{ - yymsp[-2].minor.yy125 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy125, yymsp[0].minor.yy361); -} - break; - case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ -{ - assert( yymsp[0].minor.yy483!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy483); - yymsp[0].minor.yy483->pNextWin = yymsp[-2].minor.yy483; - yylhsminor.yy483 = yymsp[0].minor.yy483; -} - yymsp[-2].minor.yy483 = yylhsminor.yy483; - break; - case 315: /* windowdefn ::= nm AS LP window RP */ -{ - if( ALWAYS(yymsp[-1].minor.yy483) ){ - yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); - } - yylhsminor.yy483 = yymsp[-1].minor.yy483; -} - yymsp[-4].minor.yy483 = yylhsminor.yy483; - break; - case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ -{ - yymsp[-4].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, 0); -} - break; - case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, &yymsp[-5].minor.yy0); -} - yymsp[-5].minor.yy483 = yylhsminor.yy483; - break; - case 318: /* window ::= ORDER BY sortlist frame_opt */ -{ - yymsp[-3].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, 0); -} - break; - case 319: /* window ::= nm ORDER BY sortlist frame_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0); -} - yymsp[-4].minor.yy483 = yylhsminor.yy483; - break; - case 320: /* window ::= nm frame_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, 0, &yymsp[-1].minor.yy0); -} - yymsp[-1].minor.yy483 = yylhsminor.yy483; - break; - case 321: /* frame_opt ::= */ -{ - yymsp[1].minor.yy483 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); -} - break; - case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy502, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy444); -} - yymsp[-2].minor.yy483 = yylhsminor.yy483; - break; - case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ -{ - yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy502, yymsp[-3].minor.yy205.eType, yymsp[-3].minor.yy205.pExpr, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, yymsp[0].minor.yy444); -} - yymsp[-5].minor.yy483 = yylhsminor.yy483; - break; - case 325: /* frame_bound_s ::= frame_bound */ - case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327); -{yylhsminor.yy205 = yymsp[0].minor.yy205;} - yymsp[0].minor.yy205 = yylhsminor.yy205; - break; - case 326: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 328: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==328); - case 330: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==330); -{yylhsminor.yy205.eType = yymsp[-1].major; yylhsminor.yy205.pExpr = 0;} - yymsp[-1].minor.yy205 = yylhsminor.yy205; - break; - case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy205.eType = yymsp[0].major; yylhsminor.yy205.pExpr = yymsp[-1].minor.yy590;} - yymsp[-1].minor.yy205 = yylhsminor.yy205; - break; - case 331: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy444 = 0;} - break; - case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy444 = yymsp[0].minor.yy444;} - break; - case 333: /* frame_exclude ::= NO OTHERS */ - case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334); -{yymsp[-1].minor.yy444 = yymsp[-1].major; /*A-overwrites-X*/} - break; - case 335: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy444 = yymsp[0].major; /*A-overwrites-X*/} - break; - case 336: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; } - break; - case 337: /* filter_over ::= filter_clause over_clause */ -{ - if( yymsp[0].minor.yy483 ){ - yymsp[0].minor.yy483->pFilter = yymsp[-1].minor.yy590; - }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); - } - yylhsminor.yy483 = yymsp[0].minor.yy483; -} - yymsp[-1].minor.yy483 = yylhsminor.yy483; - break; - case 338: /* filter_over ::= over_clause */ -{ - yylhsminor.yy483 = yymsp[0].minor.yy483; -} - yymsp[0].minor.yy483 = yylhsminor.yy483; - break; - case 339: /* filter_over ::= filter_clause */ -{ - yylhsminor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy483 ){ - yylhsminor.yy483->eFrmType = TK_FILTER; - yylhsminor.yy483->pFilter = yymsp[0].minor.yy590; - }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy590); - } -} - yymsp[0].minor.yy483 = yylhsminor.yy483; - break; - case 340: /* over_clause ::= OVER LP window RP */ -{ - yymsp[-3].minor.yy483 = yymsp[-1].minor.yy483; - assert( yymsp[-3].minor.yy483!=0 ); -} - break; - case 341: /* over_clause ::= OVER nm */ -{ - yymsp[-1].minor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy483 ){ - yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); - } -} - break; - case 342: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy590 = yymsp[-1].minor.yy590; } - break; - case 343: /* term ::= QNUMBER */ -{ - yylhsminor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); - sqlite3DequoteNumber(pParse, yylhsminor.yy590); -} - yymsp[0].minor.yy590 = yylhsminor.yy590; + case 267: /* with ::= */ +{yymsp[1].minor.yy285 = 0;} + break; + case 268: /* with ::= WITH wqlist */ +{ yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } + break; + case 269: /* with ::= WITH RECURSIVE wqlist */ +{ yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } + break; + case 270: /* wqlist ::= nm eidlist_opt AS LP select RP */ +{ + yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ +} + break; + case 271: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ +{ + yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); +} break; default: - /* (344) input ::= cmdlist */ yytestcase(yyruleno==344); - /* (345) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==345); - /* (346) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=346); - /* (347) ecmd ::= SEMI */ yytestcase(yyruleno==347); - /* (348) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==348); - /* (349) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=349); - /* (350) trans_opt ::= */ yytestcase(yyruleno==350); - /* (351) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==351); - /* (352) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==352); - /* (353) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==353); - /* (354) savepoint_opt ::= */ yytestcase(yyruleno==354); - /* (355) cmd ::= create_table create_table_args */ yytestcase(yyruleno==355); - /* (356) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=356); - /* (357) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==357); - /* (358) columnlist ::= columnname carglist */ yytestcase(yyruleno==358); - /* (359) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==359); - /* (360) nm ::= STRING */ yytestcase(yyruleno==360); - /* (361) typetoken ::= typename */ yytestcase(yyruleno==361); - /* (362) typename ::= ID|STRING */ yytestcase(yyruleno==362); - /* (363) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=363); - /* (364) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=364); - /* (365) carglist ::= carglist ccons */ yytestcase(yyruleno==365); - /* (366) carglist ::= */ yytestcase(yyruleno==366); - /* (367) ccons ::= NULL onconf */ yytestcase(yyruleno==367); - /* (368) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==368); - /* (369) ccons ::= AS generated */ yytestcase(yyruleno==369); - /* (370) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==370); - /* (371) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==371); - /* (372) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=372); - /* (373) tconscomma ::= */ yytestcase(yyruleno==373); - /* (374) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=374); - /* (375) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=375); - /* (376) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=376); - /* (377) oneselect ::= values */ yytestcase(yyruleno==377); - /* (378) sclp ::= selcollist COMMA */ yytestcase(yyruleno==378); - /* (379) as ::= ID|STRING */ yytestcase(yyruleno==379); - /* (380) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=380); - /* (381) returning ::= */ yytestcase(yyruleno==381); - /* (382) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=382); - /* (383) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==383); - /* (384) case_operand ::= expr */ yytestcase(yyruleno==384); - /* (385) exprlist ::= nexprlist */ yytestcase(yyruleno==385); - /* (386) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=386); - /* (387) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=387); - /* (388) nmnum ::= ON */ yytestcase(yyruleno==388); - /* (389) nmnum ::= DELETE */ yytestcase(yyruleno==389); - /* (390) nmnum ::= DEFAULT */ yytestcase(yyruleno==390); - /* (391) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==391); - /* (392) foreach_clause ::= */ yytestcase(yyruleno==392); - /* (393) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==393); - /* (394) trnm ::= nm */ yytestcase(yyruleno==394); - /* (395) tridxby ::= */ yytestcase(yyruleno==395); - /* (396) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==396); - /* (397) database_kw_opt ::= */ yytestcase(yyruleno==397); - /* (398) kwcolumn_opt ::= */ yytestcase(yyruleno==398); - /* (399) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==399); - /* (400) vtabarglist ::= vtabarg */ yytestcase(yyruleno==400); - /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==401); - /* (402) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==402); - /* (403) anylist ::= */ yytestcase(yyruleno==403); - /* (404) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==404); - /* (405) anylist ::= anylist ANY */ yytestcase(yyruleno==405); - /* (406) with ::= */ yytestcase(yyruleno==406); - /* (407) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=407); - /* (408) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=408); + /* (272) input ::= cmdlist */ yytestcase(yyruleno==272); + /* (273) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==273); + /* (274) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=274); + /* (275) ecmd ::= SEMI */ yytestcase(yyruleno==275); + /* (276) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==276); + /* (277) explain ::= */ yytestcase(yyruleno==277); + /* (278) trans_opt ::= */ yytestcase(yyruleno==278); + /* (279) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==279); + /* (280) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==280); + /* (281) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==281); + /* (282) savepoint_opt ::= */ yytestcase(yyruleno==282); + /* (283) cmd ::= create_table create_table_args */ yytestcase(yyruleno==283); + /* (284) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==284); + /* (285) columnlist ::= columnname carglist */ yytestcase(yyruleno==285); + /* (286) nm ::= ID|INDEXED */ yytestcase(yyruleno==286); + /* (287) nm ::= STRING */ yytestcase(yyruleno==287); + /* (288) nm ::= JOIN_KW */ yytestcase(yyruleno==288); + /* (289) typetoken ::= typename */ yytestcase(yyruleno==289); + /* (290) typename ::= ID|STRING */ yytestcase(yyruleno==290); + /* (291) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=291); + /* (292) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=292); + /* (293) carglist ::= carglist ccons */ yytestcase(yyruleno==293); + /* (294) carglist ::= */ yytestcase(yyruleno==294); + /* (295) ccons ::= NULL onconf */ yytestcase(yyruleno==295); + /* (296) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==296); + /* (297) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==297); + /* (298) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=298); + /* (299) tconscomma ::= */ yytestcase(yyruleno==299); + /* (300) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=300); + /* (301) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=301); + /* (302) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=302); + /* (303) oneselect ::= values */ yytestcase(yyruleno==303); + /* (304) sclp ::= selcollist COMMA */ yytestcase(yyruleno==304); + /* (305) as ::= ID|STRING */ yytestcase(yyruleno==305); + /* (306) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=306); + /* (307) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==307); + /* (308) exprlist ::= nexprlist */ yytestcase(yyruleno==308); + /* (309) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=309); + /* (310) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=310); + /* (311) nmnum ::= ON */ yytestcase(yyruleno==311); + /* (312) nmnum ::= DELETE */ yytestcase(yyruleno==312); + /* (313) nmnum ::= DEFAULT */ yytestcase(yyruleno==313); + /* (314) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==314); + /* (315) foreach_clause ::= */ yytestcase(yyruleno==315); + /* (316) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==316); + /* (317) trnm ::= nm */ yytestcase(yyruleno==317); + /* (318) tridxby ::= */ yytestcase(yyruleno==318); + /* (319) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==319); + /* (320) database_kw_opt ::= */ yytestcase(yyruleno==320); + /* (321) kwcolumn_opt ::= */ yytestcase(yyruleno==321); + /* (322) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==322); + /* (323) vtabarglist ::= vtabarg */ yytestcase(yyruleno==323); + /* (324) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==324); + /* (325) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==325); + /* (326) anylist ::= */ yytestcase(yyruleno==326); + /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); + /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); break; /********** End reduce actions ************************************************/ }; - assert( yyrulenoYY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) ); /* It is not possible for a REDUCE to be followed by an error */ assert( yyact!=YY_ERROR_ACTION ); - yymsp += yysize+1; - yypParser->yytos = yymsp; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact, "... then shift"); - return yyact; + if( yyact==YY_ACCEPT_ACTION ){ + yypParser->yytos += yysize; + yy_accept(yypParser); + }else{ + yymsp += yysize+1; + yypParser->yytos = yymsp; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yyTraceShift(yypParser, yyact); + } } /* ** The following code executes when the parse fails */ #ifndef YYNOERRORRECOVERY static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH + sqlite3ParserARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); } #endif @@ -179454,12 +139981,11 @@ while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3ParserCTX_STORE + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* YYNOERRORRECOVERY */ /* ** The following code executes when a syntax error first occurs. @@ -179467,34 +139993,28 @@ static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ ){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH + sqlite3ParserARG_FETCH; #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ - if( TOKEN.z[0] ){ - parserSyntaxError(pParse, &TOKEN); - }else{ - sqlite3ErrorMsg(pParse, "incomplete input"); - } + assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); /************ End %syntax_error code ******************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3ParserCTX_STORE + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following is executed when the parser accepts */ static void yy_accept( yyParser *yypParser /* The parser */ ){ - sqlite3ParserARG_FETCH - sqlite3ParserCTX_FETCH + sqlite3ParserARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); } #endif @@ -179504,12 +140024,11 @@ assert( yypParser->yytos==yypParser->yystack ); /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ /*********** End %parse_accept code *******************************************/ - sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3ParserCTX_STORE + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* The main parser program. ** The first argument is a pointer to a structure obtained from ** "sqlite3ParserAlloc" which describes the current state of the parser. @@ -179534,92 +140053,42 @@ int yymajor, /* The major token code number */ sqlite3ParserTOKENTYPE yyminor /* The value for the token */ sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; - YYACTIONTYPE yyact; /* The parser action. */ + unsigned int yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif - yyParser *yypParser = (yyParser*)yyp; /* The parser */ - sqlite3ParserCTX_FETCH - sqlite3ParserARG_STORE + yyParser *yypParser; /* The parser */ + yypParser = (yyParser*)yyp; assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif - - yyact = yypParser->yytos->stateno; -#ifndef NDEBUG - if( yyTraceFILE ){ - if( yyact < YY_MIN_REDUCE ){ - fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact); - }else{ - fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); - } - } -#endif - - while(1){ /* Exit by "break" */ - assert( yypParser->yytos>=yypParser->yystack ); - assert( yyact==yypParser->yytos->stateno ); - yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); - if( yyact >= YY_MIN_REDUCE ){ - unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */ -#ifndef NDEBUG - assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ); - if( yyTraceFILE ){ - int yysize = yyRuleInfoNRhs[yyruleno]; - if( yysize ){ - fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", - yyTracePrompt, - yyruleno, yyRuleName[yyruleno], - yyrulenoyytos[yysize].stateno); - }else{ - fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n", - yyTracePrompt, yyruleno, yyRuleName[yyruleno], - yyrulenoyytos - yypParser->yystack)>yypParser->yyhwm ){ - yypParser->yyhwm++; - assert( yypParser->yyhwm == - (int)(yypParser->yytos - yypParser->yystack)); - } -#endif - if( yypParser->yytos>=yypParser->yystackEnd ){ - if( yyGrowStack(yypParser) ){ - yyStackOverflow(yypParser); - break; - } - } - } - yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor sqlite3ParserCTX_PARAM); - }else if( yyact <= YY_MAX_SHIFTREDUCE ){ - yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); + sqlite3ParserARG_STORE; + +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + } +#endif + + do{ + yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); + if( yyact <= YY_MAX_SHIFTREDUCE ){ + yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif - break; - }else if( yyact==YY_ACCEPT_ACTION ){ - yypParser->yytos--; - yy_accept(yypParser); - return; + yymajor = YYNOCODE; + }else if( yyact <= YY_MAX_REDUCE ){ + yy_reduce(yypParser,yyact-YY_MIN_REDUCE); }else{ assert( yyact == YY_ERROR_ACTION ); yyminorunion.yy0 = yyminor; #ifdef YYERRORSYMBOL int yymx; @@ -179630,11 +140099,11 @@ } #endif #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". + ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** ** * Call the %syntax_error function. ** @@ -179661,17 +140130,19 @@ } #endif yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yymajor = YYNOCODE; }else{ - while( yypParser->yytos > yypParser->yystack ){ - yyact = yy_find_reduce_action(yypParser->yytos->stateno, - YYERRORSYMBOL); - if( yyact<=YY_MAX_SHIFTREDUCE ) break; + while( yypParser->yytos >= yypParser->yystack + && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yypParser->yytos->stateno, + YYERRORSYMBOL)) >= YY_MIN_REDUCE + ){ yy_pop_parser_stack(yypParser); } - if( yypParser->yytos <= yypParser->yystack || yymajor==0 ){ + if( yypParser->yytos < yypParser->yystack || yymajor==0 ){ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_parse_failed(yypParser); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif @@ -179680,12 +140151,10 @@ yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); } } yypParser->yyerrcnt = 3; yyerrorhit = 1; - if( yymajor==YYNOCODE ) break; - yyact = yypParser->yytos->stateno; #elif defined(YYNOERRORRECOVERY) /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax ** error routine and continue going as if nothing had happened. ** @@ -179692,11 +140161,12 @@ ** Applications can set this macro (for example inside %include) if ** they intend to abandon the parse upon the first syntax error seen. */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - break; + yymajor = YYNOCODE; + #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** ** * Report an error message, and throw away the input token. ** @@ -179714,14 +140184,14 @@ yy_parse_failed(yypParser); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif } - break; + yymajor = YYNOCODE; #endif } - } + }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ yyStackEntry *i; char cDiv = '['; fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); @@ -179733,24 +140203,10 @@ } #endif return; } -/* -** Return the fallback token corresponding to canonical token iToken, or -** 0 if iToken has no fallback. -*/ -SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){ -#ifdef YYFALLBACK - assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); - return yyFallback[iToken]; -#else - (void)iToken; - return 0; -#endif -} - /************** End of parse.c ***********************************************/ /************** Begin file tokenize.c ****************************************/ /* ** 2001 September 15 ** @@ -179778,12 +140234,12 @@ ** The lookup table is much faster. To maximize speed, and to ensure that ** a lookup table is used, all of the classes need to be small integers and ** all of them need to be used within the switch. */ #define CC_X 0 /* The letter 'x', or start of BLOB literal */ -#define CC_KYWD0 1 /* First letter of a keyword */ -#define CC_KYWD 2 /* Alphabetics or '_'. Usable in a keyword */ +#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */ +#define CC_ID 2 /* unicode characters usable in IDs */ #define CC_DIGIT 3 /* Digits */ #define CC_DOLLAR 4 /* '$' */ #define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */ #define CC_VARNUM 6 /* '?'. Numeric SQL variables */ #define CC_SPACE 7 /* Space characters */ @@ -179804,62 +140260,59 @@ #define CC_PERCENT 22 /* '%' */ #define CC_COMMA 23 /* ',' */ #define CC_AND 24 /* '&' */ #define CC_TILDA 25 /* '~' */ #define CC_DOT 26 /* '.' */ -#define CC_ID 27 /* unicode characters usable in IDs */ -#define CC_ILLEGAL 28 /* Illegal character */ -#define CC_NUL 29 /* 0x00 */ -#define CC_BOM 30 /* First byte of UTF8 BOM: 0xEF 0xBB 0xBF */ +#define CC_ILLEGAL 27 /* Illegal character */ static const unsigned char aiClass[] = { #ifdef SQLITE_ASCII /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ -/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28, -/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, /* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2, +/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, /* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28, -/* 8x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* 9x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* Ax */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* Cx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* Dx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* Ex */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30, -/* Fx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27 +/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, +/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 #endif #ifdef SQLITE_EBCDIC /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ -/* 0x */ 29, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 7, 7, 28, 28, -/* 1x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -/* 2x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -/* 3x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -/* 4x */ 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10, -/* 5x */ 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15, 4, 21, 18, 19, 28, -/* 6x */ 11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22, 2, 13, 6, -/* 7x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 8, 5, 5, 5, 8, 14, 8, -/* 8x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28, -/* 9x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28, -/* Ax */ 28, 25, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28, -/* Bx */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, 28, -/* Cx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28, -/* Dx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28, -/* Ex */ 28, 28, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28, -/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 28, 28, 28, 28, 28, 28, +/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10, +/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, +/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6, +/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, +/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, +/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, +/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, +/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, +/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, #endif }; /* ** The charMap() macro maps alphabetic characters (only) into their ** lower-case ASCII equivalent. On ASCII machines, this is just ** an upper-to-lower case map. On EBCDIC machines we also need ** to adjust the encoding. The mapping is only valid for alphabetics -** which are the only characters for which this feature is used. +** which are the only characters for which this feature is used. ** ** Used by keywordhash.h */ #ifdef SQLITE_ASCII # define charMap(X) sqlite3UpperToLower[(unsigned char)X] @@ -179887,11 +140340,11 @@ }; #endif /* ** The sqlite3KeywordCode function looks up an identifier to determine if -** it is a keyword. If it is a keyword, the token code of that keyword is +** it is a keyword. If it is a keyword, the token code of that keyword is ** returned. If the input is not a keyword, TK_ID is returned. ** ** The implementation of this routine was generated by a program, ** mkkeywordhash.c, located in the tool subdirectory of the distribution. ** The output of the mkkeywordhash.c program is written into a file @@ -179911,479 +140364,293 @@ ** might be implemented more directly using a hand-written hash table. ** But by using this automatically generated code, the size of the code ** is substantially reduced. This is important for embedded applications ** on platforms with limited memory. */ -/* Hash score: 231 */ -/* zKWText[] encodes 1007 bytes of keyword text in 667 bytes */ +/* Hash score: 182 */ +/* zKWText[] encodes 834 bytes of keyword text in 554 bytes */ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ -/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT */ -/* IESNOTNULLIKEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTS */ -/* CONSTRAINTOFFSETRIGGERANGENERATEDETACHAVINGLOBEGINNEREFERENCES */ -/* UNIQUERYWITHOUTERELEASEATTACHBETWEENOTHINGROUPSCASCADEFAULT */ -/* CASECOLLATECREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZE */ -/* PRAGMATERIALIZEDEFERREDISTINCTUPDATEVALUESVIRTUALWAYSWHENWHERE */ -/* CURSIVEABORTAFTERENAMEANDROPARTITIONAUTOINCREMENTCASTCOLUMN */ -/* COMMITCONFLICTCROSSCURRENT_TIMESTAMPRECEDINGFAILASTFILTER */ -/* EPLACEFIRSTFOLLOWINGFROMFULLIMITIFORDERESTRICTOTHERSOVER */ -/* ETURNINGRIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBY */ -/* INITIALLYPRIMARY */ -static const char zKWText[666] = { +/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ +/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ +/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */ +/* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ +/* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */ +/* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */ +/* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */ +/* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */ +/* VACUUMVIEWINITIALLY */ +static const char zKWText[553] = { 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F', - 'E','R','R','A','B','L','E','L','S','E','X','C','L','U','D','E','L','E', - 'T','E','M','P','O','R','A','R','Y','I','S','N','U','L','L','S','A','V', - 'E','P','O','I','N','T','E','R','S','E','C','T','I','E','S','N','O','T', - 'N','U','L','L','I','K','E','X','C','E','P','T','R','A','N','S','A','C', - 'T','I','O','N','A','T','U','R','A','L','T','E','R','A','I','S','E','X', - 'C','L','U','S','I','V','E','X','I','S','T','S','C','O','N','S','T','R', - 'A','I','N','T','O','F','F','S','E','T','R','I','G','G','E','R','A','N', - 'G','E','N','E','R','A','T','E','D','E','T','A','C','H','A','V','I','N', - 'G','L','O','B','E','G','I','N','N','E','R','E','F','E','R','E','N','C', - 'E','S','U','N','I','Q','U','E','R','Y','W','I','T','H','O','U','T','E', - 'R','E','L','E','A','S','E','A','T','T','A','C','H','B','E','T','W','E', - 'E','N','O','T','H','I','N','G','R','O','U','P','S','C','A','S','C','A', - 'D','E','F','A','U','L','T','C','A','S','E','C','O','L','L','A','T','E', - 'C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E', - 'I','M','M','E','D','I','A','T','E','J','O','I','N','S','E','R','T','M', - 'A','T','C','H','P','L','A','N','A','L','Y','Z','E','P','R','A','G','M', - 'A','T','E','R','I','A','L','I','Z','E','D','E','F','E','R','R','E','D', - 'I','S','T','I','N','C','T','U','P','D','A','T','E','V','A','L','U','E', - 'S','V','I','R','T','U','A','L','W','A','Y','S','W','H','E','N','W','H', - 'E','R','E','C','U','R','S','I','V','E','A','B','O','R','T','A','F','T', - 'E','R','E','N','A','M','E','A','N','D','R','O','P','A','R','T','I','T', - 'I','O','N','A','U','T','O','I','N','C','R','E','M','E','N','T','C','A', - 'S','T','C','O','L','U','M','N','C','O','M','M','I','T','C','O','N','F', - 'L','I','C','T','C','R','O','S','S','C','U','R','R','E','N','T','_','T', - 'I','M','E','S','T','A','M','P','R','E','C','E','D','I','N','G','F','A', - 'I','L','A','S','T','F','I','L','T','E','R','E','P','L','A','C','E','F', - 'I','R','S','T','F','O','L','L','O','W','I','N','G','F','R','O','M','F', - 'U','L','L','I','M','I','T','I','F','O','R','D','E','R','E','S','T','R', - 'I','C','T','O','T','H','E','R','S','O','V','E','R','E','T','U','R','N', - 'I','N','G','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O', - 'W','S','U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S', - 'I','N','G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W', - 'B','Y','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y', + 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N', + 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I', + 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E', + 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E', + 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T', + 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', + 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', + 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', + 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E', + 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A', + 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A', + 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A', + 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J', + 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L', + 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E', + 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H', + 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E', + 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E', + 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M', + 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R', + 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A', + 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', + 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O', + 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T', + 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R', + 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M', + 'V','I','E','W','I','N','I','T','I','A','L','L','Y', }; /* aKWHash[i] is the hash value for the i-th keyword */ static const unsigned char aKWHash[127] = { - 84, 92, 134, 82, 105, 29, 0, 0, 94, 0, 85, 72, 0, - 53, 35, 86, 15, 0, 42, 97, 54, 89, 135, 19, 0, 0, - 140, 0, 40, 129, 0, 22, 107, 0, 9, 0, 0, 123, 80, - 0, 78, 6, 0, 65, 103, 147, 0, 136, 115, 0, 0, 48, - 0, 90, 24, 0, 17, 0, 27, 70, 23, 26, 5, 60, 142, - 110, 122, 0, 73, 91, 71, 145, 61, 120, 74, 0, 49, 0, - 11, 41, 0, 113, 0, 0, 0, 109, 10, 111, 116, 125, 14, - 50, 124, 0, 100, 0, 18, 121, 144, 56, 130, 139, 88, 83, - 37, 30, 126, 0, 0, 108, 51, 131, 128, 0, 34, 0, 0, - 132, 0, 98, 38, 39, 0, 20, 45, 117, 93, + 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0, + 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0, + 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71, + 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44, + 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25, + 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0, + 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14, + 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113, + 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0, + 29, 0, 86, 63, 64, 0, 20, 61, 0, 56, }; /* aKWNext[] forms the hash collision chain. If aKWHash[i]==0 ** then the i-th keyword has no more hash collisions. Otherwise, ** the next keyword with the same hash is aKWHash[i]-1. */ -static const unsigned char aKWNext[148] = {0, - 0, 0, 0, 0, 4, 0, 43, 0, 0, 106, 114, 0, 0, - 0, 2, 0, 0, 143, 0, 0, 0, 13, 0, 0, 0, 0, - 141, 0, 0, 119, 52, 0, 0, 137, 12, 0, 0, 62, 0, - 138, 0, 133, 0, 0, 36, 0, 0, 28, 77, 0, 0, 0, - 0, 59, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 69, 0, 0, 0, 0, 0, 146, 3, 0, 58, 0, 1, - 75, 0, 0, 0, 31, 0, 0, 0, 0, 0, 127, 0, 104, - 0, 64, 66, 63, 0, 0, 0, 0, 0, 46, 0, 16, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 101, 0, - 112, 21, 7, 67, 0, 79, 96, 118, 0, 0, 68, 0, 0, - 99, 44, 0, 55, 0, 76, 0, 95, 32, 33, 57, 25, 0, - 102, 0, 0, 87, +static const unsigned char aKWNext[124] = { + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, + 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38, + 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0, + 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34, + 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8, + 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37, + 73, 83, 0, 35, 68, 0, 0, }; /* aKWLen[i] is the length (in bytes) of the i-th keyword */ -static const unsigned char aKWLen[148] = {0, +static const unsigned char aKWLen[124] = { 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, - 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 7, - 6, 9, 4, 2, 6, 5, 9, 9, 4, 7, 3, 2, 4, - 4, 6, 11, 6, 2, 7, 5, 5, 9, 6, 10, 4, 6, - 2, 3, 7, 5, 9, 6, 6, 4, 5, 5, 10, 6, 5, - 7, 4, 5, 7, 6, 7, 7, 6, 5, 7, 3, 7, 4, - 7, 6, 12, 9, 4, 6, 5, 4, 7, 6, 12, 8, 8, - 2, 6, 6, 7, 6, 4, 5, 9, 5, 5, 6, 3, 4, - 9, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 9, - 4, 4, 6, 7, 5, 9, 4, 4, 5, 2, 5, 8, 6, - 4, 9, 5, 8, 4, 3, 9, 5, 5, 6, 4, 6, 2, - 2, 9, 3, 7, + 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, + 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, + 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, + 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4, + 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, + 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, + 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, + 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8, + 3, 5, 5, 6, 4, 9, 3, }; /* aKWOffset[i] is the index into zKWText[] of the start of ** the text for the i-th keyword. */ -static const unsigned short int aKWOffset[148] = {0, +static const unsigned short int aKWOffset[124] = { 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, - 86, 90, 90, 94, 99, 101, 105, 111, 119, 123, 123, 123, 126, - 129, 132, 137, 142, 146, 147, 152, 156, 160, 168, 174, 181, 184, - 184, 187, 189, 195, 198, 206, 211, 216, 219, 222, 226, 236, 239, - 244, 244, 248, 252, 259, 265, 271, 277, 277, 283, 284, 288, 295, - 299, 306, 312, 324, 333, 335, 341, 346, 348, 355, 359, 370, 377, - 378, 385, 391, 397, 402, 408, 412, 415, 424, 429, 433, 439, 441, - 444, 453, 455, 457, 466, 470, 476, 482, 490, 495, 495, 495, 511, - 520, 523, 527, 532, 539, 544, 553, 557, 560, 565, 567, 571, 579, - 585, 588, 597, 602, 610, 610, 614, 623, 628, 633, 639, 642, 645, - 648, 650, 655, 659, + 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, + 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, + 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246, + 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318, + 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380, + 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459, + 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513, + 521, 524, 529, 534, 540, 544, 549, }; /* aKWCode[i] is the parser symbol code for the i-th keyword */ -static const unsigned char aKWCode[148] = {0, - TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, - TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, - TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, - TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, - TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, - TK_EXCLUDE, TK_DELETE, TK_TEMP, TK_TEMP, TK_OR, - TK_ISNULL, TK_NULLS, TK_SAVEPOINT, TK_INTERSECT, TK_TIES, - TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, - TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, - TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_CONSTRAINT, - TK_INTO, TK_OFFSET, TK_OF, TK_SET, TK_TRIGGER, - TK_RANGE, TK_GENERATED, TK_DETACH, TK_HAVING, TK_LIKE_KW, - TK_BEGIN, TK_JOIN_KW, TK_REFERENCES, TK_UNIQUE, TK_QUERY, - TK_WITHOUT, TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_ATTACH, - TK_BETWEEN, TK_NOTHING, TK_GROUPS, TK_GROUP, TK_CASCADE, - TK_ASC, TK_DEFAULT, TK_CASE, TK_COLLATE, TK_CREATE, - TK_CTIME_KW, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH, - TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_MATERIALIZED, TK_DEFERRED, - TK_DISTINCT, TK_IS, TK_UPDATE, TK_VALUES, TK_VIRTUAL, - TK_ALWAYS, TK_WHEN, TK_WHERE, TK_RECURSIVE, TK_ABORT, - TK_AFTER, TK_RENAME, TK_AND, TK_DROP, TK_PARTITION, - TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, - TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, - TK_CURRENT, TK_PRECEDING, TK_FAIL, TK_LAST, TK_FILTER, - TK_REPLACE, TK_FIRST, TK_FOLLOWING, TK_FROM, TK_JOIN_KW, - TK_LIMIT, TK_IF, TK_ORDER, TK_RESTRICT, TK_OTHERS, - TK_OVER, TK_RETURNING, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, - TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING, TK_VACUUM, - TK_VIEW, TK_WINDOW, TK_DO, TK_BY, TK_INITIALLY, - TK_ALL, TK_PRIMARY, -}; -/* Hash table decoded: -** 0: INSERT -** 1: IS -** 2: ROLLBACK TRIGGER -** 3: IMMEDIATE -** 4: PARTITION -** 5: TEMP -** 6: -** 7: -** 8: VALUES WITHOUT -** 9: -** 10: MATCH -** 11: NOTHING -** 12: -** 13: OF -** 14: TIES IGNORE -** 15: PLAN -** 16: INSTEAD INDEXED -** 17: -** 18: TRANSACTION RIGHT -** 19: WHEN -** 20: SET HAVING -** 21: MATERIALIZED IF -** 22: ROWS -** 23: SELECT -** 24: -** 25: -** 26: VACUUM SAVEPOINT -** 27: -** 28: LIKE UNION VIRTUAL REFERENCES -** 29: RESTRICT -** 30: -** 31: THEN REGEXP -** 32: TO -** 33: -** 34: BEFORE -** 35: -** 36: -** 37: FOLLOWING COLLATE CASCADE -** 38: CREATE -** 39: -** 40: CASE REINDEX -** 41: EACH -** 42: -** 43: QUERY -** 44: AND ADD -** 45: PRIMARY ANALYZE -** 46: -** 47: ROW ASC DETACH -** 48: CURRENT_TIME CURRENT_DATE -** 49: -** 50: -** 51: EXCLUSIVE TEMPORARY -** 52: -** 53: DEFERRED -** 54: DEFERRABLE -** 55: -** 56: DATABASE -** 57: -** 58: DELETE VIEW GENERATED -** 59: ATTACH -** 60: END -** 61: EXCLUDE -** 62: ESCAPE DESC -** 63: GLOB -** 64: WINDOW ELSE -** 65: COLUMN -** 66: FIRST -** 67: -** 68: GROUPS ALL -** 69: DISTINCT DROP KEY -** 70: BETWEEN -** 71: INITIALLY -** 72: BEGIN -** 73: FILTER CHECK ACTION -** 74: GROUP INDEX -** 75: -** 76: EXISTS DEFAULT -** 77: -** 78: FOR CURRENT_TIMESTAMP -** 79: EXCEPT -** 80: -** 81: CROSS -** 82: -** 83: -** 84: -** 85: CAST -** 86: FOREIGN AUTOINCREMENT -** 87: COMMIT -** 88: CURRENT AFTER ALTER -** 89: FULL FAIL CONFLICT -** 90: EXPLAIN -** 91: CONSTRAINT -** 92: FROM ALWAYS -** 93: -** 94: ABORT -** 95: -** 96: AS DO -** 97: REPLACE WITH RELEASE -** 98: BY RENAME -** 99: RANGE RAISE -** 100: OTHERS -** 101: USING NULLS -** 102: PRAGMA -** 103: JOIN ISNULL OFFSET -** 104: NOT -** 105: OR LAST LEFT -** 106: LIMIT -** 107: -** 108: -** 109: IN -** 110: INTO -** 111: OVER RECURSIVE -** 112: ORDER OUTER -** 113: -** 114: INTERSECT UNBOUNDED -** 115: -** 116: -** 117: RETURNING ON -** 118: -** 119: WHERE -** 120: NO INNER -** 121: NULL -** 122: -** 123: TABLE -** 124: NATURAL NOTNULL -** 125: PRECEDING -** 126: UPDATE UNIQUE -*/ +static const unsigned char aKWCode[124] = { + TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, + TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, + TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, + TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, + TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, + TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, + TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, + TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, + TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, + TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, + TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, + TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, + TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, + TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, + TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, + TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, + TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, + TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, + TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, + TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, + TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, + TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, + TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, + TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, + TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, +}; /* Check to see if z[0..n-1] is a keyword. If it is, write the ** parser symbol code for that keyword into *pType. Always ** return the integer n (the length of the token). */ static int keywordCode(const char *z, int n, int *pType){ int i, j; const char *zKW; - assert( n>=2 ); - i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; - for(i=(int)aKWHash[i]; i>0; i=aKWNext[i]){ - if( aKWLen[i]!=n ) continue; - zKW = &zKWText[aKWOffset[i]]; + if( n>=2 ){ + i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; + for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){ + if( aKWLen[i]!=n ) continue; + j = 0; + zKW = &zKWText[aKWOffset[i]]; #ifdef SQLITE_ASCII - if( (z[0]&~0x20)!=zKW[0] ) continue; - if( (z[1]&~0x20)!=zKW[1] ) continue; - j = 2; - while( j=2 ) keywordCode((char*)z, n, &id); + keywordCode((char*)z, n, &id); return id; } -#define SQLITE_N_KEYWORD 147 -SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){ - if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR; - i++; - *pzName = zKWText + aKWOffset[i]; - *pnName = aKWLen[i]; - return SQLITE_OK; -} -SQLITE_API int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; } -SQLITE_API int sqlite3_keyword_check(const char *zName, int nName){ - return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName); -} +#define SQLITE_N_KEYWORD 124 /************** End of keywordhash.h *****************************************/ /************** Continuing where we left off in tokenize.c *******************/ @@ -180390,18 +140657,18 @@ /* ** If X is a character that can be used in an identifier then ** IdChar(X) will be true. Otherwise it is false. ** ** For ASCII, any character with the high-order bit set is -** allowed in an identifier. For 7-bit characters, +** allowed in an identifier. For 7-bit characters, ** sqlite3IsIdChar[X] must be 1. ** ** For EBCDIC, the rules are more complex but have the same ** end result. ** ** Ticket #1066. the SQL standard does not allow '$' in the -** middle of identifiers. But many SQL implementations do. +** middle of identifiers. But many SQL implementations do. ** SQLite will allow '$' in identifiers for compatibility. ** But the feature is undocumented. */ #ifdef SQLITE_ASCII #define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) @@ -180423,92 +140690,18 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */ }; #define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) #endif -/* Make the IdChar function accessible from ctime.c and alter.c */ +/* Make the IdChar function accessible from ctime.c */ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** Return the id of the next token in string (*pz). Before returning, set -** (*pz) to point to the byte following the parsed token. -*/ -static int getToken(const unsigned char **pz){ - const unsigned char *z = *pz; - int t; /* Token type to return */ - do { - z += sqlite3GetToken(z, &t); - }while( t==TK_SPACE ); - if( t==TK_ID - || t==TK_STRING - || t==TK_JOIN_KW - || t==TK_WINDOW - || t==TK_OVER - || sqlite3ParserFallback(t)==TK_ID - ){ - t = TK_ID; - } - *pz = z; - return t; -} - -/* -** The following three functions are called immediately after the tokenizer -** reads the keywords WINDOW, OVER and FILTER, respectively, to determine -** whether the token should be treated as a keyword or an SQL identifier. -** This cannot be handled by the usual lemon %fallback method, due to -** the ambiguity in some constructions. e.g. -** -** SELECT sum(x) OVER ... -** -** In the above, "OVER" might be a keyword, or it might be an alias for the -** sum(x) expression. If a "%fallback ID OVER" directive were added to -** grammar, then SQLite would always treat "OVER" as an alias, making it -** impossible to call a window-function without a FILTER clause. -** -** WINDOW is treated as a keyword if: -** -** * the following token is an identifier, or a keyword that can fallback -** to being an identifier, and -** * the token after than one is TK_AS. -** -** OVER is a keyword if: -** -** * the previous token was TK_RP, and -** * the next token is either TK_LP or an identifier. -** -** FILTER is a keyword if: -** -** * the previous token was TK_RP, and -** * the next token is TK_LP. -*/ -static int analyzeWindowKeyword(const unsigned char *z){ - int t; - t = getToken(&z); - if( t!=TK_ID ) return TK_ID; - t = getToken(&z); - if( t!=TK_AS ) return TK_ID; - return TK_WINDOW; -} -static int analyzeOverKeyword(const unsigned char *z, int lastToken){ - if( lastToken==TK_RP ){ - int t = getToken(&z); - if( t==TK_LP || t==TK_ID ) return TK_OVER; - } - return TK_ID; -} -static int analyzeFilterKeyword(const unsigned char *z, int lastToken){ - if( lastToken==TK_RP && getToken(&z)==TK_LP ){ - return TK_FILTER; - } - return TK_ID; -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - -/* -** Return the length (in bytes) of the token that begins at z[0]. +#endif + + +/* +** Return the length (in bytes) of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ int i, c; switch( aiClass[*z] ){ /* Switch on the character-class of the first byte @@ -180525,15 +140718,12 @@ return i; } case CC_MINUS: { if( z[1]=='-' ){ for(i=2; (c=z[i])!=0 && c!='\n'; i++){} - *tokenType = TK_COMMENT; + *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ return i; - }else if( z[1]=='>' ){ - *tokenType = TK_PTR; - return 2 + (z[2]=='>'); } *tokenType = TK_MINUS; return 1; } case CC_LP: { @@ -180561,11 +140751,11 @@ *tokenType = TK_SLASH; return 1; } for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} if( c ) i++; - *tokenType = TK_COMMENT; + *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ return i; } case CC_PERCENT: { *tokenType = TK_REM; return 1; @@ -180664,72 +140854,40 @@ *tokenType = TK_DOT; return 1; } /* If the next character is a digit, this is a floating point ** number that begins with ".". Fall thru into the next case */ - /* no break */ deliberate_fall_through } case CC_DIGIT: { testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); - testcase( z[0]=='9' ); testcase( z[0]=='.' ); + testcase( z[0]=='9' ); *tokenType = TK_INTEGER; #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ - for(i=3; 1; i++){ - if( sqlite3Isxdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } - }else + for(i=3; sqlite3Isxdigit(z[i]); i++){} + return i; + } #endif - { - for(i=0; 1; i++){ - if( sqlite3Isdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } + for(i=0; sqlite3Isdigit(z[i]); i++){} #ifndef SQLITE_OMIT_FLOATING_POINT - if( z[i]=='.' ){ - if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; - for(i++; 1; i++){ - if( sqlite3Isdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } - } - if( (z[i]=='e' || z[i]=='E') && - ( sqlite3Isdigit(z[i+1]) - || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) - ) - ){ - if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; - for(i+=2; 1; i++){ - if( sqlite3Isdigit(z[i])==0 ){ - if( z[i]==SQLITE_DIGIT_SEPARATOR ){ - *tokenType = TK_QNUMBER; - }else{ - break; - } - } - } - } + if( z[i]=='.' ){ + i++; + while( sqlite3Isdigit(z[i]) ){ i++; } + *tokenType = TK_FLOAT; + } + if( (z[i]=='e' || z[i]=='E') && + ( sqlite3Isdigit(z[i+1]) + || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) + ) + ){ + i += 2; + while( sqlite3Isdigit(z[i]) ){ i++; } + *tokenType = TK_FLOAT; + } #endif - } while( IdChar(z[i]) ){ *tokenType = TK_ILLEGAL; i++; } return i; @@ -180772,13 +140930,12 @@ } } if( n==0 ) *tokenType = TK_ILLEGAL; return i; } - case CC_KYWD0: { - if( aiClass[z[1]]>CC_KYWD ){ i = 1; break; } - for(i=2; aiClass[z[i]]<=CC_KYWD; i++){} + case CC_KYWD: { + for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} if( IdChar(z[i]) ){ /* This token started out using characters that can appear in keywords, ** but z[i] is a character not allowed within keywords, so this must ** be an identifier instead */ i++; @@ -180801,29 +140958,15 @@ return i; } #endif /* If it is not a BLOB literal, then it must be an ID, since no ** SQL keywords start with the letter 'x'. Fall through */ - /* no break */ deliberate_fall_through } - case CC_KYWD: case CC_ID: { i = 1; break; } - case CC_BOM: { - if( z[1]==0xbb && z[2]==0xbf ){ - *tokenType = TK_SPACE; - return 3; - } - i = 1; - break; - } - case CC_NUL: { - *tokenType = TK_ILLEGAL; - return 0; - } default: { *tokenType = TK_ILLEGAL; return 1; } } @@ -180831,128 +140974,93 @@ *tokenType = TK_ID; return i; } /* -** Run the parser on the given SQL string. +** Run the parser on the given SQL string. The parser structure is +** passed in. An SQLITE_ status code is returned. If an error occurs +** then an and attempt is made to write an error message into +** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that +** error message. */ -SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ +SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ - Parse *pParentParse = 0; /* Outer parse context, if any */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ #endif - VVA_ONLY( u8 startedWithOom = db->mallocFailed ); assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); + db->u1.isInterrupted = 0; } pParse->rc = SQLITE_OK; pParse->zTail = zSql; -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_ParserTrace ){ - printf("parser: [[[%s]]]\n", zSql); - sqlite3ParserTrace(stdout, "parser: "); - }else{ - sqlite3ParserTrace(0, 0); - } -#endif + assert( pzErrMsg!=0 ); + /* sqlite3ParserTrace(stdout, "parser: "); */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK pEngine = &sEngine; - sqlite3ParserInit(pEngine, pParse); + sqlite3ParserInit(pEngine); #else - pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse); + pEngine = sqlite3ParserAlloc(sqlite3Malloc); if( pEngine==0 ){ sqlite3OomFault(db); return SQLITE_NOMEM_BKPT; } #endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->pVList==0 ); - pParentParse = db->pParse; - db->pParse = pParse; while( 1 ){ - n = sqlite3GetToken((u8*)zSql, &tokenType); - mxSqlLen -= n; - if( mxSqlLen<0 ){ - pParse->rc = SQLITE_TOOBIG; - pParse->nErr++; - break; - } -#ifndef SQLITE_OMIT_WINDOWFUNC - if( tokenType>=TK_WINDOW ){ - assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER - || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW - || tokenType==TK_QNUMBER || tokenType==TK_COMMENT - ); -#else + if( zSql[0]!=0 ){ + n = sqlite3GetToken((u8*)zSql, &tokenType); + mxSqlLen -= n; + if( mxSqlLen<0 ){ + pParse->rc = SQLITE_TOOBIG; + break; + } + }else{ + /* Upon reaching the end of input, call the parser two more times + ** with tokens TK_SEMI and 0, in that order. */ + if( lastTokenParsed==TK_SEMI ){ + tokenType = 0; + }else if( lastTokenParsed==0 ){ + break; + }else{ + tokenType = TK_SEMI; + } + zSql -= n; + } if( tokenType>=TK_SPACE ){ - assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL - || tokenType==TK_QNUMBER || tokenType==TK_COMMENT - ); -#endif /* SQLITE_OMIT_WINDOWFUNC */ - if( AtomicLoad(&db->u1.isInterrupted) ){ + assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); + if( db->u1.isInterrupted ){ pParse->rc = SQLITE_INTERRUPT; - pParse->nErr++; - break; - } - if( tokenType==TK_SPACE ){ - zSql += n; - continue; - } - if( zSql[0]==0 ){ - /* Upon reaching the end of input, call the parser two more times - ** with tokens TK_SEMI and 0, in that order. */ - if( lastTokenParsed==TK_SEMI ){ - tokenType = 0; - }else if( lastTokenParsed==0 ){ - break; - }else{ - tokenType = TK_SEMI; - } - n = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - }else if( tokenType==TK_WINDOW ){ - assert( n==6 ); - tokenType = analyzeWindowKeyword((const u8*)&zSql[6]); - }else if( tokenType==TK_OVER ){ - assert( n==4 ); - tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); - }else if( tokenType==TK_FILTER ){ - assert( n==6 ); - tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); -#endif /* SQLITE_OMIT_WINDOWFUNC */ - }else if( tokenType==TK_COMMENT && (db->flags & SQLITE_Comments)!=0 ){ - zSql += n; - continue; - }else if( tokenType!=TK_QNUMBER ){ - Token x; - x.z = zSql; - x.n = n; - sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); - break; - } - } - pParse->sLastToken.z = zSql; - pParse->sLastToken.n = n; - sqlite3Parser(pEngine, tokenType, pParse->sLastToken); - lastTokenParsed = tokenType; - zSql += n; - assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom ); - if( pParse->rc!=SQLITE_OK ) break; + break; + } + if( tokenType==TK_ILLEGAL ){ + sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); + break; + } + zSql += n; + }else{ + pParse->sLastToken.z = zSql; + pParse->sLastToken.n = n; + sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); + lastTokenParsed = tokenType; + zSql += n; + if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; + } } assert( nErr==0 ); + pParse->zTail = zSql; #ifdef YYTRACKMAXSTACKDEPTH sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); @@ -180964,176 +141072,60 @@ sqlite3ParserFree(pEngine, sqlite3_free); #endif if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM_BKPT; } - if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){ - if( pParse->zErrMsg==0 ){ - pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); - } - if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){ - sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail); - } + if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ + pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); + } + assert( pzErrMsg!=0 ); + if( pParse->zErrMsg ){ + *pzErrMsg = pParse->zErrMsg; + sqlite3_log(pParse->rc, "%s", *pzErrMsg); + pParse->zErrMsg = 0; nErr++; } - pParse->zTail = zSql; + if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ + sqlite3VdbeDelete(pParse->pVdbe); + pParse->pVdbe = 0; + } +#ifndef SQLITE_OMIT_SHARED_CACHE + if( pParse->nested==0 ){ + sqlite3DbFree(db, pParse->aTableLock); + pParse->aTableLock = 0; + pParse->nTableLock = 0; + } +#endif #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_free(pParse->apVtabLock); #endif - if( pParse->pNewTable && !IN_SPECIAL_PARSE ){ - /* If the pParse->declareVtab flag is set, do not delete any table + if( !IN_DECLARE_VTAB ){ + /* If the pParse->declareVtab flag is set, do not delete any table ** structure built up in pParse->pNewTable. The calling code (see vtab.c) ** will take responsibility for freeing the Table structure. */ sqlite3DeleteTable(db, pParse->pNewTable); } - if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){ - sqlite3DeleteTrigger(db, pParse->pNewTrigger); + + if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree); + sqlite3DeleteTrigger(db, pParse->pNewTrigger); + sqlite3DbFree(db, pParse->pVList); + while( pParse->pAinc ){ + AutoincInfo *p = pParse->pAinc; + pParse->pAinc = p->pNext; + sqlite3DbFreeNN(db, p); } - if( pParse->pVList ) sqlite3DbNNFreeNN(db, pParse->pVList); - db->pParse = pParentParse; + while( pParse->pZombieTab ){ + Table *p = pParse->pZombieTab; + pParse->pZombieTab = p->pNextZombie; + sqlite3DeleteTable(db, p); + } assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } - -#ifdef SQLITE_ENABLE_NORMALIZE -/* -** Insert a single space character into pStr if the current string -** ends with an identifier -*/ -static void addSpaceSeparator(sqlite3_str *pStr){ - if( pStr->nChar && sqlite3IsIdChar(pStr->zText[pStr->nChar-1]) ){ - sqlite3_str_append(pStr, " ", 1); - } -} - -/* -** Compute a normalization of the SQL given by zSql[0..nSql-1]. Return -** the normalization in space obtained from sqlite3DbMalloc(). Or return -** NULL if anything goes wrong or if zSql is NULL. -*/ -SQLITE_PRIVATE char *sqlite3Normalize( - Vdbe *pVdbe, /* VM being reprepared */ - const char *zSql /* The original SQL string */ -){ - sqlite3 *db; /* The database connection */ - int i; /* Next unread byte of zSql[] */ - int n; /* length of current token */ - int tokenType; /* type of current token */ - int prevType = 0; /* Previous non-whitespace token */ - int nParen; /* Number of nested levels of parentheses */ - int iStartIN; /* Start of RHS of IN operator in z[] */ - int nParenAtIN; /* Value of nParent at start of RHS of IN operator */ - u32 j; /* Bytes of normalized SQL generated so far */ - sqlite3_str *pStr; /* The normalized SQL string under construction */ - - db = sqlite3VdbeDb(pVdbe); - tokenType = -1; - nParen = iStartIN = nParenAtIN = 0; - pStr = sqlite3_str_new(db); - assert( pStr!=0 ); /* sqlite3_str_new() never returns NULL */ - for(i=0; zSql[i] && pStr->accError==0; i+=n){ - if( tokenType!=TK_SPACE ){ - prevType = tokenType; - } - n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType); - if( NEVER(n<=0) ) break; - switch( tokenType ){ - case TK_COMMENT: - case TK_SPACE: { - break; - } - case TK_NULL: { - if( prevType==TK_IS || prevType==TK_NOT ){ - sqlite3_str_append(pStr, " NULL", 5); - break; - } - /* Fall through */ - } - case TK_STRING: - case TK_INTEGER: - case TK_FLOAT: - case TK_VARIABLE: - case TK_BLOB: { - sqlite3_str_append(pStr, "?", 1); - break; - } - case TK_LP: { - nParen++; - if( prevType==TK_IN ){ - iStartIN = pStr->nChar; - nParenAtIN = nParen; - } - sqlite3_str_append(pStr, "(", 1); - break; - } - case TK_RP: { - if( iStartIN>0 && nParen==nParenAtIN ){ - assert( pStr->nChar>=(u32)iStartIN ); - pStr->nChar = iStartIN+1; - sqlite3_str_append(pStr, "?,?,?", 5); - iStartIN = 0; - } - nParen--; - sqlite3_str_append(pStr, ")", 1); - break; - } - case TK_ID: { - iStartIN = 0; - j = pStr->nChar; - if( sqlite3Isquote(zSql[i]) ){ - char *zId = sqlite3DbStrNDup(db, zSql+i, n); - int nId; - int eType = 0; - if( zId==0 ) break; - sqlite3Dequote(zId); - if( zSql[i]=='"' && sqlite3VdbeUsesDoubleQuotedString(pVdbe, zId) ){ - sqlite3_str_append(pStr, "?", 1); - sqlite3DbFree(db, zId); - break; - } - nId = sqlite3Strlen30(zId); - if( sqlite3GetToken((u8*)zId, &eType)==nId && eType==TK_ID ){ - addSpaceSeparator(pStr); - sqlite3_str_append(pStr, zId, nId); - }else{ - sqlite3_str_appendf(pStr, "\"%w\"", zId); - } - sqlite3DbFree(db, zId); - }else{ - addSpaceSeparator(pStr); - sqlite3_str_append(pStr, zSql+i, n); - } - while( jnChar ){ - pStr->zText[j] = sqlite3Tolower(pStr->zText[j]); - j++; - } - break; - } - case TK_SELECT: { - iStartIN = 0; - /* fall through */ - } - default: { - if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr); - j = pStr->nChar; - sqlite3_str_append(pStr, zSql+i, n); - while( jnChar ){ - pStr->zText[j] = sqlite3Toupper(pStr->zText[j]); - j++; - } - break; - } - } - } - if( tokenType!=TK_SEMI ) sqlite3_str_append(pStr, ";", 1); - return sqlite3_str_finish(pStr); -} -#endif /* SQLITE_ENABLE_NORMALIZE */ - /************** End of tokenize.c ********************************************/ /************** Begin file complete.c ****************************************/ /* ** 2001 September 15 ** @@ -181200,11 +141192,11 @@ ** in any other state. ** ** (2) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** -** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of +** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (4) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceded by EXPLAIN and/or followed by ** TEMP or TEMPORARY @@ -181496,14 +141488,10 @@ ** This header file is used by programs that want to link against the ** RTREE library. All it does is declare the sqlite3RtreeInit() interface. */ /* #include "sqlite3.h" */ -#ifdef SQLITE_OMIT_VIRTUALTABLE -# undef SQLITE_ENABLE_RTREE -#endif - #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); @@ -181513,11 +141501,11 @@ #endif /* __cplusplus */ /************** End of rtree.h ***********************************************/ /************** Continuing where we left off in main.c ***********************/ #endif -#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) +#ifdef SQLITE_ENABLE_ICU /************** Include sqliteicu.h in the middle of main.c ******************/ /************** Begin file sqliteicu.h ***************************************/ /* ** 2008 May 26 ** @@ -181542,96 +141530,42 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); #if 0 } /* extern "C" */ #endif /* __cplusplus */ + /************** End of sqliteicu.h *******************************************/ /************** Continuing where we left off in main.c ***********************/ #endif - -/* -** This is an extension initializer that is a no-op and always -** succeeds, except that it fails if the fault-simulation is set -** to 500. -*/ -static int sqlite3TestExtInit(sqlite3 *db){ - (void)db; - return sqlite3FaultSim(500); -} - - -/* -** Forward declarations of external module initializer functions -** for modules that need them. -*/ -#ifdef SQLITE_ENABLE_FTS5 -SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); +#ifdef SQLITE_ENABLE_JSON1 +SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*); #endif #ifdef SQLITE_ENABLE_STMTVTAB SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*); #endif -#ifdef SQLITE_EXTRA_AUTOEXT -int SQLITE_EXTRA_AUTOEXT(sqlite3*); -#endif -/* -** An array of pointers to extension initializer functions for -** built-in extensions. -*/ -static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { -#ifdef SQLITE_ENABLE_FTS3 - sqlite3Fts3Init, -#endif #ifdef SQLITE_ENABLE_FTS5 - sqlite3Fts5Init, -#endif -#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) - sqlite3IcuInit, -#endif -#ifdef SQLITE_ENABLE_RTREE - sqlite3RtreeInit, -#endif -#ifdef SQLITE_ENABLE_DBPAGE_VTAB - sqlite3DbpageRegister, -#endif -#ifdef SQLITE_ENABLE_DBSTAT_VTAB - sqlite3DbstatRegister, -#endif - sqlite3TestExtInit, -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) - sqlite3JsonTableFunctions, -#endif -#ifdef SQLITE_ENABLE_STMTVTAB - sqlite3StmtVtabInit, -#endif -#ifdef SQLITE_ENABLE_BYTECODE_VTAB - sqlite3VdbeBytecodeVtabInit, -#endif -#ifdef SQLITE_EXTRA_AUTOEXT - SQLITE_EXTRA_AUTOEXT, -#endif -}; +SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); +#endif #ifndef SQLITE_AMALGAMATION /* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant -** contains the text of SQLITE_VERSION macro. +** contains the text of SQLITE_VERSION macro. */ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; #endif /* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns -** a pointer to the to the sqlite3_version[] string constant. +** a pointer to the to the sqlite3_version[] string constant. */ SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } -/* IMPLEMENTATION-OF: R-25063-23286 The sqlite3_sourceid() function returns a +/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a ** pointer to a string constant whose value is the same as the -** 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. +** SQLITE_SOURCE_ID C preprocessor macro. */ -/* SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } */ +SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function ** returns an integer equal to SQLITE_VERSION_NUMBER. */ SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } @@ -181681,17 +141615,17 @@ ** See also the "PRAGMA data_store_directory" SQL command. */ SQLITE_API char *sqlite3_data_directory = 0; /* -** Initialize SQLite. +** Initialize SQLite. ** ** This routine must be called to initialize the memory allocation, ** VFS, and mutex subsystems prior to doing any serious work with ** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT ** this routine will be called automatically by key routines such as -** sqlite3_open(). +** sqlite3_open(). ** ** This routine is a no-op except on its very first call for the process, ** or for the first call after a call to sqlite3_shutdown. ** ** The first thread to call this routine runs the initialization to @@ -181712,11 +141646,11 @@ ** ** * Recursive calls to this routine from thread X return immediately ** without blocking. */ SQLITE_API int sqlite3_initialize(void){ - MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */ + MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ int rc; /* Result code */ #ifdef SQLITE_EXTRA_INIT int bRunExtraInit = 0; /* Extra initialization needed */ #endif @@ -181735,16 +141669,13 @@ /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end ** of this routine. */ - if( sqlite3GlobalConfig.isInit ){ - sqlite3MemoryBarrier(); - return SQLITE_OK; - } + if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; - /* Make sure the mutex subsystem is initialized. If unable to + /* Make sure the mutex subsystem is initialized. If unable to ** initialize the mutex subsystem, return early with the error. ** If the system is so sick that we are unable to allocate a mutex, ** there is not much SQLite is going to be able to do. ** ** The mutex subsystem must take care of serializing its own @@ -181752,17 +141683,17 @@ */ rc = sqlite3MutexInit(); if( rc ) return rc; /* Initialize the malloc() system and the recursive pInitMutex mutex. - ** This operation is protected by the STATIC_MAIN mutex. Note that + ** This operation is protected by the STATIC_MASTER mutex. Note that ** MutexAlloc() is called for a static mutex prior to initializing the ** malloc subsystem - this implies that the allocation of a static ** mutex must not require support from the malloc subsystem. */ - MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(pMainMtx); + MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + sqlite3_mutex_enter(pMaster); sqlite3GlobalConfig.isMutexInit = 1; if( !sqlite3GlobalConfig.isMallocInit ){ rc = sqlite3MallocInit(); } if( rc==SQLITE_OK ){ @@ -181776,11 +141707,11 @@ } } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.nRefInitMutex++; } - sqlite3_mutex_leave(pMainMtx); + sqlite3_mutex_leave(pMaster); /* If rc is not SQLITE_OK at this point, then either the malloc ** subsystem could not be initialized or the system failed to allocate ** the pInitMutex mutex. Return an error in either case. */ if( rc!=SQLITE_OK ){ @@ -181816,19 +141747,13 @@ } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.isPCacheInit = 1; rc = sqlite3OsInit(); } -#ifndef SQLITE_OMIT_DESERIALIZE - if( rc==SQLITE_OK ){ - rc = sqlite3MemdbInit(); - } -#endif - if( rc==SQLITE_OK ){ - sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, - sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); - sqlite3MemoryBarrier(); + if( rc==SQLITE_OK ){ + sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, + sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); sqlite3GlobalConfig.isInit = 1; #ifdef SQLITE_EXTRA_INIT bRunExtraInit = 1; #endif } @@ -181837,28 +141762,28 @@ sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex); /* Go back under the static mutex and clean up the recursive ** mutex to prevent a resource leak. */ - sqlite3_mutex_enter(pMainMtx); + sqlite3_mutex_enter(pMaster); sqlite3GlobalConfig.nRefInitMutex--; if( sqlite3GlobalConfig.nRefInitMutex<=0 ){ assert( sqlite3GlobalConfig.nRefInitMutex==0 ); sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex); sqlite3GlobalConfig.pInitMutex = 0; } - sqlite3_mutex_leave(pMainMtx); + sqlite3_mutex_leave(pMaster); /* The following is just a sanity check to make sure SQLite has ** been compiled correctly. It is important to run this code, but ** we don't want to run it too often and soak up CPU cycles for no ** reason. So we run it once during initialization. */ #ifndef NDEBUG #ifndef SQLITE_OMIT_FLOATING_POINT /* This section of code's only "output" is via assert() statements. */ - if( rc==SQLITE_OK ){ + if ( rc==SQLITE_OK ){ u64 x = (((u64)1)<<63)-1; double y; assert(sizeof(x)==8); assert(sizeof(x)==sizeof(y)); memcpy(&y, &x, 8); @@ -181874,10 +141799,11 @@ if( bRunExtraInit ){ int SQLITE_EXTRA_INIT(const char*); rc = SQLITE_EXTRA_INIT(0); } #endif + return rc; } /* ** Undo the effects of sqlite3_initialize(). Must not be called while @@ -181943,25 +141869,13 @@ */ SQLITE_API int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; - /* sqlite3_config() normally returns SQLITE_MISUSE if it is invoked while - ** the SQLite library is in use. Except, a few selected opcodes - ** are allowed. - */ - if( sqlite3GlobalConfig.isInit ){ - static const u64 mAnytimeConfigOption = 0 - | MASKBIT64( SQLITE_CONFIG_LOG ) - | MASKBIT64( SQLITE_CONFIG_PCACHE_HDRSZ ) - ; - if( op<0 || op>63 || (MASKBIT64(op) & mAnytimeConfigOption)==0 ){ - return SQLITE_MISUSE_BKPT; - } - testcase( op==SQLITE_CONFIG_LOG ); - testcase( op==SQLITE_CONFIG_PCACHE_HDRSZ ); - } + /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while + ** the SQLite library is in use. */ + if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; va_start(ap, op); switch( op ){ /* Mutex configuration options are only available in a threadsafe @@ -182026,19 +141940,24 @@ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } case SQLITE_CONFIG_MEMSTATUS: { - assert( !sqlite3GlobalConfig.isInit ); /* Cannot change at runtime */ /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes ** single argument of type int, interpreted as a boolean, which enables ** or disables the collection of memory allocation statistics. */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } - case SQLITE_CONFIG_SMALL_MALLOC: { - sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int); + case SQLITE_CONFIG_SCRATCH: { + /* EVIDENCE-OF: R-08404-60887 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). */ + sqlite3GlobalConfig.pScratch = va_arg(ap, void*); + sqlite3GlobalConfig.szScratch = va_arg(ap, int); + sqlite3GlobalConfig.nScratch = va_arg(ap, int); break; } case SQLITE_CONFIG_PAGECACHE: { /* EVIDENCE-OF: R-18761-36601 There are three arguments to ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem), @@ -182052,11 +141971,11 @@ case SQLITE_CONFIG_PCACHE_HDRSZ: { /* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes ** a single parameter which is a pointer to an integer and writes into ** that integer the number of extra bytes per page required for each page ** in SQLITE_CONFIG_PAGECACHE. */ - *va_arg(ap, int*) = + *va_arg(ap, int*) = sqlite3HeaderSizeBtree() + sqlite3HeaderSizePcache() + sqlite3HeaderSizePcache1(); break; } @@ -182139,11 +142058,11 @@ case SQLITE_CONFIG_LOOKASIDE: { sqlite3GlobalConfig.szLookaside = va_arg(ap, int); sqlite3GlobalConfig.nLookaside = va_arg(ap, int); break; } - + /* Record a pointer to the logger function and its first argument. ** The default is NULL. Logging is disabled if the function pointer is ** NULL. */ case SQLITE_CONFIG_LOG: { @@ -182150,14 +142069,12 @@ /* MSVC is picky about pulling func ptrs from va lists. ** http://support.microsoft.com/kb/47961 ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); */ typedef void(*LOGFUNC_t)(void*,int,const char*); - LOGFUNC_t xLog = va_arg(ap, LOGFUNC_t); - void *pLogArg = va_arg(ap, void*); - AtomicStore(&sqlite3GlobalConfig.xLog, xLog); - AtomicStore(&sqlite3GlobalConfig.pLogArg, pLogArg); + sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); + sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); break; } /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames ** can be changed at start-time using the @@ -182167,12 +142084,11 @@ case SQLITE_CONFIG_URI: { /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single ** argument of type int. If non-zero, then URI handling is globally ** enabled. If the parameter is zero, then URI handling is globally ** disabled. */ - int bOpenUri = va_arg(ap, int); - AtomicStore(&sqlite3GlobalConfig.bOpenUri, bOpenUri); + sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN @@ -182235,40 +142151,10 @@ case SQLITE_CONFIG_STMTJRNL_SPILL: { sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int); break; } -#ifdef SQLITE_ENABLE_SORTER_REFERENCES - case SQLITE_CONFIG_SORTERREF_SIZE: { - int iVal = va_arg(ap, int); - if( iVal<0 ){ - iVal = SQLITE_DEFAULT_SORTERREF_SIZE; - } - sqlite3GlobalConfig.szSorterRef = (u32)iVal; - break; - } -#endif /* SQLITE_ENABLE_SORTER_REFERENCES */ - -#ifndef SQLITE_OMIT_DESERIALIZE - case SQLITE_CONFIG_MEMDB_MAXSIZE: { - sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64); - break; - } -#endif /* SQLITE_OMIT_DESERIALIZE */ - - case SQLITE_CONFIG_ROWID_IN_VIEW: { - int *pVal = va_arg(ap,int*); -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid; - if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0; - *pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0); -#else - *pVal = 0; -#endif - break; - } - default: { rc = SQLITE_ERROR; break; } } @@ -182276,11 +142162,11 @@ return rc; } /* ** Set up the lookaside buffers for a database connection. -** Return SQLITE_OK on success. +** Return SQLITE_OK on success. ** If lookaside is already active, return SQLITE_BUSY. ** ** The sz parameter is the number of bytes in each lookaside slot. ** The cnt parameter is the number of slots. If pStart is NULL the ** space for the lookaside memory is obtained from sqlite3_malloc(). @@ -182288,19 +142174,15 @@ ** the lookaside memory. */ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ #ifndef SQLITE_OMIT_LOOKASIDE void *pStart; - sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt; - int nBig; /* Number of full-size slots */ - int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */ - - if( sqlite3LookasideUsed(db,0)>0 ){ + if( db->lookaside.nOut ){ return SQLITE_BUSY; } /* Free any existing lookaside buffer for this handle before - ** allocating a new one so we don't have to have space for + ** allocating a new one so we don't have to have space for ** both at the same time. */ if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } @@ -182313,76 +142195,38 @@ if( sz==0 || cnt==0 ){ sz = 0; pStart = 0; }else if( pBuf==0 ){ sqlite3BeginBenignMalloc(); - pStart = sqlite3Malloc( szAlloc ); /* IMP: R-61949-35727 */ + pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ sqlite3EndBenignMalloc(); - if( pStart ) szAlloc = sqlite3MallocSize(pStart); + if( pStart ) cnt = sqlite3MallocSize(pStart)/sz; }else{ pStart = pBuf; } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - if( sz>=LOOKASIDE_SMALL*3 ){ - nBig = szAlloc/(3*LOOKASIDE_SMALL+sz); - nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL; - }else if( sz>=LOOKASIDE_SMALL*2 ){ - nBig = szAlloc/(LOOKASIDE_SMALL+sz); - nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL; - }else -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - if( sz>0 ){ - nBig = szAlloc/sz; - nSm = 0; - }else{ - nBig = nSm = 0; - } db->lookaside.pStart = pStart; - db->lookaside.pInit = 0; db->lookaside.pFree = 0; db->lookaside.sz = (u16)sz; - db->lookaside.szTrue = (u16)sz; if( pStart ){ int i; LookasideSlot *p; assert( sz > (int)sizeof(LookasideSlot*) ); p = (LookasideSlot*)pStart; - for(i=0; ipNext = db->lookaside.pInit; - db->lookaside.pInit = p; + for(i=cnt-1; i>=0; i--){ + p->pNext = db->lookaside.pFree; + db->lookaside.pFree = p; p = (LookasideSlot*)&((u8*)p)[sz]; } -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - db->lookaside.pSmallInit = 0; - db->lookaside.pSmallFree = 0; - db->lookaside.pMiddle = p; - for(i=0; ipNext = db->lookaside.pSmallInit; - db->lookaside.pSmallInit = p; - p = (LookasideSlot*)&((u8*)p)[LOOKASIDE_SMALL]; - } -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - assert( ((uptr)p)<=szAlloc + (uptr)pStart ); db->lookaside.pEnd = p; db->lookaside.bDisable = 0; db->lookaside.bMalloced = pBuf==0 ?1:0; - db->lookaside.nSlot = nBig+nSm; }else{ - db->lookaside.pStart = 0; -#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - db->lookaside.pSmallInit = 0; - db->lookaside.pSmallFree = 0; - db->lookaside.pMiddle = 0; -#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ - db->lookaside.pEnd = 0; + db->lookaside.pStart = db; + db->lookaside.pEnd = db; db->lookaside.bDisable = 1; - db->lookaside.sz = 0; db->lookaside.bMalloced = 0; - db->lookaside.nSlot = 0; } - db->lookaside.pTrueEnd = db->lookaside.pEnd; - assert( sqlite3LookasideUsed(db,0)==0 ); #endif /* SQLITE_OMIT_LOOKASIDE */ return SQLITE_OK; } /* @@ -182436,11 +142280,11 @@ #endif sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){ + if( pBt && sqlite3BtreeIsInTrans(pBt) ){ Pager *pPager = sqlite3BtreePager(pBt); rc = sqlite3PagerFlush(pPager); if( rc==SQLITE_BUSY ){ bSeenBusy = 1; rc = SQLITE_OK; @@ -182456,15 +142300,10 @@ ** Configuration settings for an individual database connection */ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); va_start(ap, op); switch( op ){ case SQLITE_DBCONFIG_MAINDBNAME: { /* IMP: R-06824-28531 */ /* IMP: R-36257-52125 */ @@ -182480,49 +142319,33 @@ break; } default: { static const struct { int op; /* The opcode */ - u64 mask; /* Mask of the bit in sqlite3.flags to set/clear */ + u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */ } aFlagOp[] = { { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, - { SQLITE_DBCONFIG_ENABLE_VIEW, SQLITE_EnableView }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, - { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, - { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, - { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, - { SQLITE_DBCONFIG_WRITABLE_SCHEMA, SQLITE_WriteSchema| - SQLITE_NoSchemaError }, - { SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter }, - { SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL }, - { SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML }, - { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, SQLITE_LegacyFileFmt }, - { SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema }, - { SQLITE_DBCONFIG_STMT_SCANSTATUS, SQLITE_StmtScanStatus }, - { SQLITE_DBCONFIG_REVERSE_SCANORDER, SQLITE_ReverseOrder }, - { SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE, SQLITE_AttachCreate }, - { SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE, SQLITE_AttachWrite }, - { SQLITE_DBCONFIG_ENABLE_COMMENTS, SQLITE_Comments }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ for(i=0; iflags; + int oldFlags = db->flags; if( onoff>0 ){ db->flags |= aFlagOp[i].mask; }else if( onoff==0 ){ - db->flags &= ~(u64)aFlagOp[i].mask; + db->flags &= ~aFlagOp[i].mask; } if( oldFlags!=db->flags ){ - sqlite3ExpirePreparedStatements(db, 0); + sqlite3ExpirePreparedStatements(db); } if( pRes ){ *pRes = (db->flags & aFlagOp[i].mask)!=0; } rc = SQLITE_OK; @@ -182531,63 +142354,60 @@ } break; } } va_end(ap); - sqlite3_mutex_leave(db->mutex); return rc; } + +/* +** Return true if the buffer z[0..n-1] contains all spaces. +*/ +static int allSpaces(const char *z, int n){ + while( n>0 && z[n-1]==' ' ){ n--; } + return n==0; +} + /* ** This is the default collating function named "BINARY" which is always ** available. +** +** If the padFlag argument is not NULL then space padding at the end +** of strings is ignored. This implements the RTRIM collation. */ static int binCollFunc( - void *NotUsed, + void *padFlag, int nKey1, const void *pKey1, int nKey2, const void *pKey2 ){ int rc, n; - UNUSED_PARAMETER(NotUsed); n = nKey1xCmp!=binCollFunc || strcmp(p->zName,"BINARY")==0 ); - return p==0 || p->xCmp==binCollFunc; -} - -/* -** Another built-in collating sequence: NOCASE. +** Another built-in collating sequence: NOCASE. ** ** This collating sequence is intended to be used for "case independent ** comparison". SQLite's knowledge of upper and lower case equivalents ** extends only to the 26 characters used in the English language. ** @@ -182636,37 +142456,31 @@ } /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ -SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){ +SQLITE_API int sqlite3_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif return db->nChange; } -SQLITE_API int sqlite3_changes(sqlite3 *db){ - return (int)sqlite3_changes64(db); -} /* ** Return the number of changes since the database handle was opened. */ -SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return db->nTotalChange; -} SQLITE_API int sqlite3_total_changes(sqlite3 *db){ - return (int)sqlite3_total_changes64(db); +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + return db->nTotalChange; } /* ** Close all open savepoints. This function only manipulates fields of the ** database handle object, it does not close any savepoints that may be open @@ -182688,13 +142502,11 @@ ** if this is not the last copy of the function, do not invoke it. Multiple ** copies of a single function are created when create_function() is called ** with SQLITE_ANY as the encoding. */ static void functionDestroy(sqlite3 *db, FuncDef *p){ - FuncDestructor *pDestructor; - assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 ); - pDestructor = p->u.pDestructor; + FuncDestructor *pDestructor = p->u.pDestructor; if( pDestructor ){ pDestructor->nRef--; if( pDestructor->nRef==0 ){ pDestructor->xDestroy(pDestructor->pUserData); sqlite3DbFree(db, pDestructor); @@ -182711,11 +142523,11 @@ int i; HashElem *p; sqlite3BtreeEnterAll(db); for(i=0; inDb; i++){ Schema *pSchema = db->aDb[i].pSchema; - if( pSchema ){ + if( db->aDb[i].pSchema ){ for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ Table *pTab = (Table *)sqliteHashData(p); if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); } } @@ -182733,11 +142545,11 @@ #endif } /* ** Return TRUE if database connection db has unfinalized prepared -** statements or unfinished sqlite3_backup objects. +** statements or unfinished sqlite3_backup objects. */ static int connectionIsBusy(sqlite3 *db){ int j; assert( sqlite3_mutex_held(db->mutex) ); if( db->pVdbe ) return 1; @@ -182760,11 +142572,11 @@ if( !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); if( db->mTrace & SQLITE_TRACE_CLOSE ){ - db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0); + db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0); } /* Force xDisconnect calls on all virtual tables */ disconnectAllVtab(db); @@ -182792,59 +142604,21 @@ /* Closing the handle. Fourth parameter is passed the value 2. */ sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2); } #endif - while( db->pDbData ){ - DbClientData *p = db->pDbData; - db->pDbData = p->pNext; - assert( p->pData!=0 ); - if( p->xDestructor ) p->xDestructor(p->pData); - sqlite3_free(p); - } - /* Convert the connection into a zombie and then close it. */ - db->eOpenState = SQLITE_STATE_ZOMBIE; + db->magic = SQLITE_MAGIC_ZOMBIE; sqlite3LeaveMutexAndCloseZombie(db); return SQLITE_OK; } -/* -** Return the transaction state for a single databse, or the maximum -** transaction state over all attached databases if zSchema is null. -*/ -SQLITE_API int sqlite3_txn_state(sqlite3 *db, const char *zSchema){ - int iDb, nDb; - int iTxn = -1; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return -1; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( zSchema ){ - nDb = iDb = sqlite3FindDbName(db, zSchema); - if( iDb<0 ) nDb--; - }else{ - iDb = 0; - nDb = db->nDb-1; - } - for(; iDb<=nDb; iDb++){ - Btree *pBt = db->aDb[iDb].pBt; - int x = pBt!=0 ? sqlite3BtreeTxnState(pBt) : SQLITE_TXN_NONE; - if( x>iTxn ) iTxn = x; - } - sqlite3_mutex_leave(db->mutex); - return iTxn; -} - /* ** Two variations on the public interface for closing a database ** connection. The sqlite3_close() version returns SQLITE_BUSY and -** leaves the connection open if there are unfinalized prepared +** leaves the connection option if there are unfinalized prepared ** statements or unfinished sqlite3_backups. The sqlite3_close_v2() ** version forces the connection to become a zombie if there are ** unclosed resources, and arranges for deallocation when the last ** prepare statement or sqlite3_backup closes. */ @@ -182866,11 +142640,11 @@ /* If there are outstanding sqlite3_stmt or sqlite3_backup objects ** or if the connection has not yet been closed by sqlite3_close_v2(), ** then just leave the mutex and return. */ - if( db->eOpenState!=SQLITE_STATE_ZOMBIE || connectionIsBusy(db) ){ + if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){ sqlite3_mutex_leave(db->mutex); return; } /* If we reach this point, it means that the database connection has @@ -182938,36 +142712,40 @@ } sqlite3HashClear(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ Module *pMod = (Module *)sqliteHashData(i); + if( pMod->xDestroy ){ + pMod->xDestroy(pMod->pAux); + } sqlite3VtabEponymousTableClear(db, pMod); - sqlite3VtabModuleUnref(db, pMod); + sqlite3DbFree(db, pMod); } sqlite3HashClear(&db->aModule); #endif sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */ sqlite3ValueFree(db->pErr); sqlite3CloseExtensions(db); +#if SQLITE_USER_AUTHENTICATION + sqlite3_free(db->auth.zAuthUser); + sqlite3_free(db->auth.zAuthPW); +#endif - db->eOpenState = SQLITE_STATE_ERROR; + db->magic = SQLITE_MAGIC_ERROR; /* The temp-database schema is allocated differently from the other schema ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). ** So it needs to be freed here. Todo: Why not roll the temp schema into - ** the same sqliteMalloc() as the one that allocates the database + ** the same sqliteMalloc() as the one that allocates the database ** structure? */ sqlite3DbFree(db, db->aDb[1].pSchema); - if( db->xAutovacDestr ){ - db->xAutovacDestr(db->pAutovacPagesArg); - } sqlite3_mutex_leave(db->mutex); - db->eOpenState = SQLITE_STATE_CLOSED; + db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); - assert( sqlite3LookasideUsed(db,0)==0 ); + assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */ if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } sqlite3_free(db); } @@ -182984,41 +142762,41 @@ int inTrans = 0; int schemaChange; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); - /* Obtain all b-tree mutexes before making any calls to BtreeRollback(). + /* Obtain all b-tree mutexes before making any calls to BtreeRollback(). ** This is important in case the transaction being rolled back has ** modified the database schema. If the b-tree mutexes are not taken ** here, then another shared-cache connection might sneak in between ** the database rollback and schema reset, which can cause false ** corruption reports in some cases. */ sqlite3BtreeEnterAll(db); - schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0; + schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0; for(i=0; inDb; i++){ Btree *p = db->aDb[i].pBt; if( p ){ - if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){ + if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } sqlite3BtreeRollback(p, tripCode, !schemaChange); } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); - if( schemaChange ){ - sqlite3ExpirePreparedStatements(db, 0); + if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ + sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } sqlite3BtreeLeaveAll(db); /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; db->nDeferredImmCons = 0; - db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly); + db->flags &= ~SQLITE_DeferFKs; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); } @@ -183034,11 +142812,10 @@ int i, origRc = rc; for(i=0; i<2 && zName==0; i++, rc &= 0xff){ switch( rc ){ case SQLITE_OK: zName = "SQLITE_OK"; break; case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; - case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; case SQLITE_PERM: zName = "SQLITE_PERM"; break; case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; @@ -183047,14 +142824,13 @@ case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; - case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break; + case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; - case SQLITE_READONLY_DIRECTORY: zName = "SQLITE_READONLY_DIRECTORY";break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; @@ -183088,11 +142864,10 @@ case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break; case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break; case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break; case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break; - case SQLITE_CANTOPEN_SYMLINK: zName = "SQLITE_CANTOPEN_SYMLINK"; break; case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; @@ -183120,11 +142895,10 @@ case SQLITE_ROW: zName = "SQLITE_ROW"; break; case SQLITE_NOTICE: zName = "SQLITE_NOTICE"; break; case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break; case SQLITE_NOTICE_RECOVER_ROLLBACK: zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break; - case SQLITE_NOTICE_RBU: zName = "SQLITE_NOTICE_RBU"; break; case SQLITE_WARNING: zName = "SQLITE_WARNING"; break; case SQLITE_WARNING_AUTOINDEX: zName = "SQLITE_WARNING_AUTOINDEX"; break; case SQLITE_DONE: zName = "SQLITE_DONE"; break; } } @@ -183172,27 +142946,17 @@ #endif /* SQLITE_AUTH */ "authorization denied", /* SQLITE_FORMAT */ 0, /* SQLITE_RANGE */ "column index out of range", /* SQLITE_NOTADB */ "file is not a database", - /* SQLITE_NOTICE */ "notification message", - /* SQLITE_WARNING */ "warning message", }; const char *zErr = "unknown error"; switch( rc ){ case SQLITE_ABORT_ROLLBACK: { zErr = "abort due to ROLLBACK"; break; } - case SQLITE_ROW: { - zErr = "another row available"; - break; - } - case SQLITE_DONE: { - zErr = "no more rows available"; - break; - } default: { rc &= 0xff; if( ALWAYS(rc>=0) && rcbusyTimeout; + int timeout = db->busyTimeout; int delay, prior; assert( count>=0 ); if( count < NDELAY ){ delay = delays[count]; @@ -183233,22 +142992,20 @@ prior = totals[count]; }else{ delay = delays[NDELAY-1]; prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); } - if( prior + delay > tmout ){ - delay = tmout - prior; + if( prior + delay > timeout ){ + delay = timeout - prior; if( delay<=0 ) return 0; } sqlite3OsSleep(db->pVfs, delay*1000); return 1; #else - /* This case for unix systems that lack usleep() support. Sleeping - ** must be done in increments of whole seconds */ sqlite3 *db = (sqlite3 *)ptr; - int tmout = ((sqlite3 *)ptr)->busyTimeout; - if( (count+1)*1000 > tmout ){ + int timeout = ((sqlite3 *)ptr)->busyTimeout; + if( (count+1)*1000 > timeout ){ return 0; } sqlite3OsSleep(db->pVfs, 1000000); return 1; #endif @@ -183255,26 +143012,24 @@ } /* ** Invoke the given busy handler. ** -** This routine is called when an operation failed to acquire a -** lock on VFS file pFile. -** +** This routine is called when an operation failed with a lock. ** If this routine returns non-zero, the lock is retried. If it ** returns 0, the operation aborts with an SQLITE_BUSY error. */ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ int rc; - if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; - rc = p->xBusyHandler(p->pBusyArg, p->nBusy); + if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; + rc = p->xFunc(p->pArg, p->nBusy); if( rc==0 ){ p->nBusy = -1; }else{ p->nBusy++; } - return rc; + return rc; } /* ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. @@ -183286,12 +143041,12 @@ ){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); - db->busyHandler.xBusyHandler = xBusy; - db->busyHandler.pBusyArg = pArg; + db->busyHandler.xFunc = xBusy; + db->busyHandler.pArg = pArg; db->busyHandler.nBusy = 0; db->busyTimeout = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -183301,13 +143056,13 @@ ** This routine sets the progress callback for an Sqlite database to the ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ SQLITE_API void sqlite3_progress_handler( - sqlite3 *db, + sqlite3 *db, int nOps, - int (*xProgress)(void*), + int (*xProgress)(void*), void *pArg ){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; @@ -183336,12 +143091,11 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms>0 ){ - sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, - (void*)db); + sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); db->busyTimeout = ms; }else{ sqlite3_busy_handler(db, 0, 0); } return SQLITE_OK; @@ -183350,41 +143104,24 @@ /* ** Cause any pending operation to stop at its earliest opportunity. */ SQLITE_API void sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) - && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) - ){ + if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){ (void)SQLITE_MISUSE_BKPT; return; } #endif - AtomicStore(&db->u1.isInterrupted, 1); -} - -/* -** Return true or false depending on whether or not an interrupt is -** pending on connection db. -*/ -SQLITE_API int sqlite3_is_interrupted(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) - && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) - ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - return AtomicLoad(&db->u1.isInterrupted)!=0; -} + db->u1.isInterrupted = 1; +} + /* ** This function is exactly the same as sqlite3_create_function(), except ** that it is designed to be called by internal code. The difference is ** that if a malloc() fails in sqlite3_create_function(), an error code -** is returned and the mallocFailed flag cleared. +** is returned and the mallocFailed flag cleared. */ SQLITE_PRIVATE int sqlite3CreateFunc( sqlite3 *db, const char *zFunctionName, int nArg, @@ -183391,101 +143128,72 @@ int enc, void *pUserData, void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value **), FuncDestructor *pDestructor ){ FuncDef *p; + int nName; int extraFlags; assert( sqlite3_mutex_held(db->mutex) ); - assert( xValue==0 || xSFunc==0 ); - if( zFunctionName==0 /* Must have a valid name */ - || (xSFunc!=0 && xFinal!=0) /* Not both xSFunc and xFinal */ - || ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */ - || ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */ - || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) - || (255SQLITE_MAX_FUNCTION_ARG) || + (255<(nName = sqlite3Strlen30( zFunctionName))) ){ return SQLITE_MISUSE_BKPT; } assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); - assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); - extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY| - SQLITE_SUBTYPE|SQLITE_INNOCUOUS| - SQLITE_RESULT_SUBTYPE|SQLITE_SELFORDER1); + extraFlags = enc & SQLITE_DETERMINISTIC; enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); - - /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But - ** the meaning is inverted. So flip the bit. */ - assert( SQLITE_FUNC_UNSAFE==SQLITE_INNOCUOUS ); - extraFlags ^= SQLITE_FUNC_UNSAFE; /* tag-20230109-1 */ - - + #ifndef SQLITE_OMIT_UTF16 /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. ** ** If SQLITE_ANY is specified, add three versions of the function ** to the hash table. */ - switch( enc ){ - case SQLITE_UTF16: - enc = SQLITE_UTF16NATIVE; - break; - case SQLITE_ANY: { - int rc; - rc = sqlite3CreateFunc(db, zFunctionName, nArg, - (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE, /* tag-20230109-1 */ - pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); - if( rc==SQLITE_OK ){ - rc = sqlite3CreateFunc(db, zFunctionName, nArg, - (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE, /* tag-20230109-1*/ - pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); - } - if( rc!=SQLITE_OK ){ - return rc; - } - enc = SQLITE_UTF16BE; - break; - } - case SQLITE_UTF8: - case SQLITE_UTF16LE: - case SQLITE_UTF16BE: - break; - default: - enc = SQLITE_UTF8; - break; + if( enc==SQLITE_UTF16 ){ + enc = SQLITE_UTF16NATIVE; + }else if( enc==SQLITE_ANY ){ + int rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, + pUserData, xSFunc, xStep, xFinal, pDestructor); + if( rc==SQLITE_OK ){ + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, + pUserData, xSFunc, xStep, xFinal, pDestructor); + } + if( rc!=SQLITE_OK ){ + return rc; + } + enc = SQLITE_UTF16BE; } #else enc = SQLITE_UTF8; #endif - + /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE_BUSY. If a function ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0); - if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==(u32)enc && p->nArg==nArg ){ + if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to delete/modify user-function due to active statements"); assert( !db->mallocFailed ); return SQLITE_BUSY; }else{ - sqlite3ExpirePreparedStatements(db, 0); + sqlite3ExpirePreparedStatements(db); } - }else if( xSFunc==0 && xFinal==0 ){ - /* Trying to delete a function that does not exist. This is a no-op. - ** https://sqlite.org/forum/forumpost/726219164b */ - return SQLITE_OK; } p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1); assert(p || db->mallocFailed); if( !p ){ @@ -183500,75 +143208,17 @@ pDestructor->nRef++; } p->u.pDestructor = pDestructor; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; testcase( p->funcFlags & SQLITE_DETERMINISTIC ); - testcase( p->funcFlags & SQLITE_DIRECTONLY ); p->xSFunc = xSFunc ? xSFunc : xStep; p->xFinalize = xFinal; - p->xValue = xValue; - p->xInverse = xInverse; p->pUserData = pUserData; p->nArg = (u16)nArg; return SQLITE_OK; } -/* -** Worker function used by utf-8 APIs that create new functions: -** -** sqlite3_create_function() -** sqlite3_create_function_v2() -** sqlite3_create_window_function() -*/ -static int createFunctionApi( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*) -){ - int rc = SQLITE_ERROR; - FuncDestructor *pArg = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( xDestroy ){ - pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor)); - if( !pArg ){ - sqlite3OomFault(db); - xDestroy(p); - goto out; - } - pArg->nRef = 0; - pArg->xDestroy = xDestroy; - pArg->pUserData = p; - } - rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, - xSFunc, xStep, xFinal, xValue, xInverse, pArg - ); - if( pArg && pArg->nRef==0 ){ - assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) ); - xDestroy(p); - sqlite3_free(pArg); - } - - out: - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - /* ** Create new user functions. */ SQLITE_API int sqlite3_create_function( sqlite3 *db, @@ -183578,13 +143228,14 @@ void *p, void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*) ){ - return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, - xFinal, 0, 0, 0); + return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xSFunc, xStep, + xFinal, 0); } + SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunc, int nArg, int enc, @@ -183592,27 +143243,39 @@ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*), void (*xDestroy)(void *) ){ - return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, - xFinal, 0, 0, xDestroy); -} -SQLITE_API int sqlite3_create_window_function( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value **), - void (*xDestroy)(void *) -){ - return createFunctionApi(db, zFunc, nArg, enc, p, 0, xStep, - xFinal, xValue, xInverse, xDestroy); + int rc = SQLITE_ERROR; + FuncDestructor *pArg = 0; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE_BKPT; + } +#endif + sqlite3_mutex_enter(db->mutex); + if( xDestroy ){ + pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); + if( !pArg ){ + xDestroy(p); + goto out; + } + pArg->xDestroy = xDestroy; + pArg->pUserData = p; + } + rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, pArg); + if( pArg && pArg->nRef==0 ){ + assert( rc!=SQLITE_OK ); + xDestroy(p); + sqlite3DbFree(db, pArg); + } + + out: + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } #ifndef SQLITE_OMIT_UTF16 SQLITE_API int sqlite3_create_function16( sqlite3 *db, @@ -183631,47 +143294,25 @@ if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); - rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0,0,0); + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0); sqlite3DbFree(db, zFunc8); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } #endif -/* -** The following is the implementation of an SQL function that always -** fails with an error message stating that the function is used in the -** wrong context. The sqlite3_overload_function() API might construct -** SQL function that use this routine so that the functions will exist -** for name resolution but are actually overloaded by the xFindFunction -** method of virtual tables. -*/ -static void sqlite3InvalidFunction( - sqlite3_context *context, /* The function calling context */ - int NotUsed, /* Number of arguments to the function */ - sqlite3_value **NotUsed2 /* Value of each argument */ -){ - const char *zName = (const char*)sqlite3_user_data(context); - char *zErr; - UNUSED_PARAMETER2(NotUsed, NotUsed2); - zErr = sqlite3_mprintf( - "unable to use function %s in the requested context", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); -} - /* ** Declare that a function has been overloaded by a virtual table. ** ** If the function already exists as a regular global function, then ** this routine is a no-op. If the function does not exist, then create -** a new one that always throws a run-time error. +** a new one that always throws a run-time error. ** ** When virtual tables intend to provide an overloaded function, they ** should call this routine to make sure the global function exists. ** A global function must exist in order for name resolution to work ** properly. @@ -183679,32 +143320,31 @@ SQLITE_API int sqlite3_overload_function( sqlite3 *db, const char *zName, int nArg ){ - int rc; - char *zCopy; + int rc = SQLITE_OK; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); - rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0; + if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){ + rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, + 0, sqlite3InvalidFunction, 0, 0, 0); + } + rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); - if( rc ) return SQLITE_OK; - zCopy = sqlite3_mprintf("%s", zName); - if( zCopy==0 ) return SQLITE_NOMEM; - return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8, - zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free); + return rc; } #ifndef SQLITE_OMIT_TRACE /* ** Register a trace function. The pArg from the previously registered trace -** is returned. +** is returned. ** ** A NULL trace function means that no tracing is executes. A non-NULL ** trace is a pointer to a function that is invoked at the start of each ** SQL statement. */ @@ -183719,11 +143359,11 @@ } #endif sqlite3_mutex_enter(db->mutex); pOld = db->pTraceArg; db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0; - db->trace.xLegacy = xTrace; + db->xTrace = (int(*)(u32,void*,void*,void*))xTrace; db->pTraceArg = pArg; sqlite3_mutex_leave(db->mutex); return pOld; } #endif /* SQLITE_OMIT_DEPRECATED */ @@ -183743,20 +143383,20 @@ #endif sqlite3_mutex_enter(db->mutex); if( mTrace==0 ) xTrace = 0; if( xTrace==0 ) mTrace = 0; db->mTrace = mTrace; - db->trace.xV2 = xTrace; + db->xTrace = xTrace; db->pTraceArg = pArg; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } #ifndef SQLITE_OMIT_DEPRECATED /* -** Register a profile function. The pArg from the previously registered -** profile function is returned. +** Register a profile function. The pArg from the previously registered +** profile function is returned. ** ** A NULL profile function means that no profiling is executes. A non-NULL ** profile is a pointer to a function that is invoked at the conclusion of ** each SQL statement that is run. */ @@ -183775,12 +143415,10 @@ #endif sqlite3_mutex_enter(db->mutex); pOld = db->pProfileArg; db->xProfile = xProfile; db->pProfileArg = pArg; - db->mTrace &= SQLITE_TRACE_NONLEGACY_MASK; - if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE; sqlite3_mutex_leave(db->mutex); return pOld; } #endif /* SQLITE_OMIT_DEPRECATED */ #endif /* SQLITE_OMIT_TRACE */ @@ -183871,60 +143509,26 @@ void(*xCallback)( /* Callback function */ void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), void *pArg /* First callback argument */ ){ void *pRet; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( db==0 ){ - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pRet = db->pPreUpdateArg; db->xPreUpdateCallback = xCallback; db->pPreUpdateArg = pArg; sqlite3_mutex_leave(db->mutex); return pRet; } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ - -/* -** Register a function to be invoked prior to each autovacuum that -** determines the number of pages to vacuum. -*/ -SQLITE_API int sqlite3_autovacuum_pages( - sqlite3 *db, /* Attach the hook to this database */ - unsigned int (*xCallback)(void*,const char*,u32,u32,u32), - void *pArg, /* Argument to the function */ - void (*xDestructor)(void*) /* Destructor for pArg */ -){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - if( xDestructor ) xDestructor(pArg); - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( db->xAutovacDestr ){ - db->xAutovacDestr(db->pAutovacPagesArg); - } - db->xAutovacPages = xCallback; - db->pAutovacPagesArg = pArg; - db->xAutovacDestr = xDestructor; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). ** Invoke sqlite3_wal_checkpoint if the number of frames in the log file ** is greater than sqlite3.pWalArg cast to an integer (the value configured by ** wal_autocheckpoint()). -*/ +*/ SQLITE_PRIVATE int sqlite3WalDefaultHook( void *pClientData, /* Argument */ sqlite3 *db, /* Connection */ const char *zDb, /* Database */ int nFrame /* Size of WAL */ @@ -184006,11 +143610,11 @@ ){ #ifdef SQLITE_OMIT_WAL return SQLITE_OK; #else int rc; /* Return code */ - int iDb; /* Schema to checkpoint */ + int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif @@ -184023,18 +143627,16 @@ assert( SQLITE_CHECKPOINT_RESTART==2 ); assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint ** mode: */ - return SQLITE_MISUSE_BKPT; + return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); if( zDb && zDb[0] ){ iDb = sqlite3FindDbName(db, zDb); - }else{ - iDb = SQLITE_MAX_DB; /* This means process all schemas */ } if( iDb<0 ){ rc = SQLITE_ERROR; sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); }else{ @@ -184045,11 +143647,11 @@ rc = sqlite3ApiExit(db, rc); /* If there are no active statements, clear the interrupt flag at this ** point. */ if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); + db->u1.isInterrupted = 0; } sqlite3_mutex_leave(db->mutex); return rc; #endif @@ -184056,11 +143658,11 @@ } /* ** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points -** to contains a zero-length string, all attached databases are +** to contains a zero-length string, all attached databases are ** checkpointed. */ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ @@ -184070,39 +143672,36 @@ #ifndef SQLITE_OMIT_WAL /* ** Run a checkpoint on database iDb. This is a no-op if database iDb is ** not currently open in WAL mode. ** -** If a transaction is open on the database being checkpointed, this -** function returns SQLITE_LOCKED and a checkpoint is not attempted. If -** an error occurs while running the checkpoint, an SQLite error code is +** If a transaction is open on the database being checkpointed, this +** function returns SQLITE_LOCKED and a checkpoint is not attempted. If +** an error occurs while running the checkpoint, an SQLite error code is ** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK. ** ** The mutex on database handle db should be held by the caller. The mutex ** associated with the specific b-tree being checkpointed is taken by ** this function while the checkpoint is running. ** -** If iDb is passed SQLITE_MAX_DB then all attached databases are +** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are ** checkpointed. If an error is encountered it is returned immediately - ** no attempt is made to checkpoint any remaining databases. ** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART -** or TRUNCATE. +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. */ SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ int rc = SQLITE_OK; /* Return code */ int i; /* Used to iterate through attached dbs */ int bBusy = 0; /* True if SQLITE_BUSY has been encountered */ assert( sqlite3_mutex_held(db->mutex) ); assert( !pnLog || *pnLog==-1 ); assert( !pnCkpt || *pnCkpt==-1 ); - testcase( iDb==SQLITE_MAX_ATTACHED ); /* See forum post a006d86f72 */ - testcase( iDb==SQLITE_MAX_DB ); for(i=0; inDb && rc==SQLITE_OK; i++){ - if( i==iDb || iDb==SQLITE_MAX_DB ){ + if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){ rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt); pnLog = 0; pnCkpt = 0; if( rc==SQLITE_BUSY ){ bBusy = 1; @@ -184166,33 +143765,20 @@ sqlite3_mutex_enter(db->mutex); if( db->mallocFailed ){ z = sqlite3ErrStr(SQLITE_NOMEM_BKPT); }else{ testcase( db->pErr==0 ); - z = db->errCode ? (char*)sqlite3_value_text(db->pErr) : 0; + z = (char*)sqlite3_value_text(db->pErr); assert( !db->mallocFailed ); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } } sqlite3_mutex_leave(db->mutex); return z; } -/* -** Return the byte offset of the most recent error -*/ -SQLITE_API int sqlite3_error_offset(sqlite3 *db){ - int iOffset = -1; - if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){ - sqlite3_mutex_enter(db->mutex); - iOffset = db->errByteOffset; - sqlite3_mutex_leave(db->mutex); - } - return iOffset; -} - #ifndef SQLITE_OMIT_UTF16 /* ** Return UTF-16 encoded English language explanation of the most recent ** error. */ @@ -184256,11 +143842,11 @@ } return db->errCode; } SQLITE_API int sqlite3_system_errno(sqlite3 *db){ return db ? db->iSysErrno : 0; -} +} /* ** Return a string that describes the kind of error specified in the ** argument. For now, this simply calls the internal sqlite3ErrStr() ** function. @@ -184273,19 +143859,19 @@ ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. */ static int createCollation( sqlite3* db, - const char *zName, + const char *zName, u8 enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDel)(void*) ){ CollSeq *pColl; int enc2; - + assert( sqlite3_mutex_held(db->mutex) ); /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. @@ -184298,29 +143884,29 @@ } if( enc2SQLITE_UTF16BE ){ return SQLITE_MISUSE_BKPT; } - /* Check if this call is removing or replacing an existing collation + /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ if( db->nVdbeActive ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } - sqlite3ExpirePreparedStatements(db, 0); + sqlite3ExpirePreparedStatements(db); /* If collation sequence pColl was created directly by a call to ** sqlite3_create_collation, and not generated by synthCollSeq(), ** then any copies made by synthCollSeq() need to be invalidated. ** Also, collation destructor - CollSeq.xDel() - function may need ** to be called. - */ + */ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName); int j; for(j=0; j<3; j++){ CollSeq *p = &aColl[j]; @@ -184381,12 +143967,12 @@ # error SQLITE_MAX_COMPOUND_SELECT must be at least 2 #endif #if SQLITE_MAX_VDBE_OP<40 # error SQLITE_MAX_VDBE_OP must be at least 40 #endif -#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>32767 -# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 32767 +#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127 +# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127 #endif #if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125 # error SQLITE_MAX_ATTACHED must be between 0 and 125 #endif #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 @@ -184449,12 +144035,10 @@ } oldLimit = db->aLimit[limitId]; if( newLimit>=0 ){ /* IMP: R-52476-28732 */ if( newLimit>aHardLimit[limitId] ){ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ - }else if( newLimitaLimit[limitId] = newLimit; } return oldLimit; /* IMP: R-53341-35419 */ } @@ -184467,31 +144051,29 @@ ** The first argument to this function is the name of the VFS to use (or ** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx" ** query parameter. The second argument contains the URI (or non-URI filename) ** itself. When this function is called the *pFlags variable should contain ** the default flags to open the database handle with. The value stored in -** *pFlags may be updated before returning if the URI filename contains +** *pFlags may be updated before returning if the URI filename contains ** "cache=xxx" or "mode=xxx" query parameters. ** ** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to ** the VFS that should be used to open the database file. *pzFile is set to -** point to a buffer containing the name of the file to open. The value -** stored in *pzFile is a database name acceptable to sqlite3_uri_parameter() -** and is in the same format as names created using sqlite3_create_filename(). -** The caller must invoke sqlite3_free_filename() (not sqlite3_free()!) on -** the value returned in *pzFile to avoid a memory leak. +** point to a buffer containing the name of the file to open. It is the +** responsibility of the caller to eventually call sqlite3_free() to release +** this buffer. ** ** If an error occurs, then an SQLite error code is returned and *pzErrMsg -** may be set to point to a buffer containing an English language error +** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to eventually release ** this buffer by calling sqlite3_free(). */ SQLITE_PRIVATE int sqlite3ParseUri( const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */ const char *zUri, /* Nul-terminated URI to parse */ unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */ - sqlite3_vfs **ppVfs, /* OUT: VFS to use */ + sqlite3_vfs **ppVfs, /* OUT: VFS to use */ char **pzFile, /* OUT: Filename component of URI */ char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */ ){ int rc = SQLITE_OK; unsigned int flags = *pFlags; @@ -184500,39 +144082,36 @@ char c; int nUri = sqlite3Strlen30(zUri); assert( *pzErrMsg==0 ); - if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ - || AtomicLoad(&sqlite3GlobalConfig.bOpenUri)) /* IMP: R-51689-46548 */ - && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ + if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ + || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */ + && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ ){ char *zOpt; int eState; /* Parser state when parsing URI */ int iIn; /* Input character index */ int iOut = 0; /* Output character index */ - u64 nByte = nUri+8; /* Bytes of space to allocate */ + u64 nByte = nUri+2; /* Bytes of space to allocate */ - /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen + /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen ** method that there may be extra parameters following the file-name. */ flags |= SQLITE_OPEN_URI; for(iIn=0; iIn=0 && octet<256 ); @@ -184575,11 +144154,11 @@ #ifndef SQLITE_ENABLE_URI_00_ERROR /* This branch is taken when "%00" appears within the URI. In this ** case we ignore all text in the remainder of the path, name or ** value currently being parsed. So ignore the current character ** and skip to the next "?", "=" or "&", as appropriate. */ - while( (c = zUri[iIn])!=0 && c!='#' + while( (c = zUri[iIn])!=0 && c!='#' && (eState!=0 || c!='?') && (eState!=1 || (c!='=' && c!='&')) && (eState!=2 || c!='&') ){ iIn++; @@ -184610,13 +144189,14 @@ eState = 1; } zFile[iOut++] = c; } if( eState==1 ) zFile[iOut++] = '\0'; - memset(zFile+iOut, 0, 4); /* end-of-options + empty journal filenames */ + zFile[iOut++] = '\0'; + zFile[iOut++] = '\0'; - /* Check if there were any options specified that should be interpreted + /* Check if there were any options specified that should be interpreted ** here. Options that are interpreted here include "vfs" and those that ** correspond to flags that may be passed to the sqlite3_open_v2() ** method. */ zOpt = &zFile[sqlite3Strlen30(zFile)+1]; while( zOpt[0] ){ @@ -184648,11 +144228,11 @@ zModeType = "cache"; } if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){ static struct OpenMode aOpenMode[] = { { "ro", SQLITE_OPEN_READONLY }, - { "rw", SQLITE_OPEN_READWRITE }, + { "rw", SQLITE_OPEN_READWRITE }, { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE }, { "memory", SQLITE_OPEN_MEMORY }, { 0, 0 } }; @@ -184690,18 +144270,17 @@ zOpt = &zVal[nVal+1]; } }else{ - zFile = sqlite3_malloc64(nUri+8); + zFile = sqlite3_malloc64(nUri+2); if( !zFile ) return SQLITE_NOMEM_BKPT; - memset(zFile, 0, 4); - zFile += 4; if( nUri ){ memcpy(zFile, zUri, nUri); } - memset(zFile+nUri, 0, 4); + zFile[nUri] = '\0'; + zFile[nUri+1] = '\0'; flags &= ~SQLITE_OPEN_URI; } *ppVfs = sqlite3_vfs_find(zVfs); if( *ppVfs==0 ){ @@ -184708,38 +144287,22 @@ *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs); rc = SQLITE_ERROR; } parse_uri_out: if( rc!=SQLITE_OK ){ - sqlite3_free_filename(zFile); + sqlite3_free(zFile); zFile = 0; } *pFlags = flags; *pzFile = zFile; return rc; } - -/* -** This routine does the core work of extracting URI parameters from a -** database filename for the sqlite3_uri_parameter() interface. -*/ -static const char *uriParameter(const char *zFilename, const char *zParam){ - zFilename += sqlite3Strlen30(zFilename) + 1; - while( ALWAYS(zFilename!=0) && zFilename[0] ){ - int x = strcmp(zFilename, zParam); - zFilename += sqlite3Strlen30(zFilename) + 1; - if( x==0 ) return zFilename; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return 0; -} - /* ** This routine does the work of opening a database on behalf of -** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" +** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" ** is UTF-8 encoded. */ static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ sqlite3 **ppDb, /* OUT: Returned database handle */ @@ -184749,11 +144312,10 @@ sqlite3 *db; /* Store allocated handle here */ int rc; /* Return code */ int isThreadsafe; /* True for threadsafe connections */ char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */ char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */ - int i; /* Loop counter */ #ifdef SQLITE_ENABLE_API_ARMOR if( ppDb==0 ) return SQLITE_MISUSE_BKPT; #endif *ppDb = 0; @@ -184769,11 +144331,10 @@ }else if( flags & SQLITE_OPEN_FULLMUTEX ){ isThreadsafe = 1; }else{ isThreadsafe = sqlite3GlobalConfig.bFullMutex; } - if( flags & SQLITE_OPEN_PRIVATECACHE ){ flags &= ~SQLITE_OPEN_SHAREDCACHE; }else if( sqlite3GlobalConfig.sharedCacheEnabled ){ flags |= SQLITE_OPEN_SHAREDCACHE; } @@ -184782,104 +144343,53 @@ ** ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were ** dealt with in the previous code block. Besides these, the only ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, - ** SQLITE_OPEN_PRIVATECACHE, SQLITE_OPEN_EXRESCODE, and some reserved - ** bits. Silently mask off all other flags. + ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask + ** off all other flags. */ flags &= ~( SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MAIN_DB | - SQLITE_OPEN_TEMP_DB | - SQLITE_OPEN_TRANSIENT_DB | - SQLITE_OPEN_MAIN_JOURNAL | - SQLITE_OPEN_TEMP_JOURNAL | - SQLITE_OPEN_SUBJOURNAL | - SQLITE_OPEN_SUPER_JOURNAL | + SQLITE_OPEN_TEMP_DB | + SQLITE_OPEN_TRANSIENT_DB | + SQLITE_OPEN_MAIN_JOURNAL | + SQLITE_OPEN_TEMP_JOURNAL | + SQLITE_OPEN_SUBJOURNAL | + SQLITE_OPEN_MASTER_JOURNAL | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_WAL ); /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; - if( isThreadsafe -#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS - || sqlite3GlobalConfig.bCoreMutex -#endif - ){ + if( isThreadsafe ){ db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ sqlite3_free(db); db = 0; goto opendb_out; } - if( isThreadsafe==0 ){ - sqlite3MutexWarnOnContention(db->mutex); - } } sqlite3_mutex_enter(db->mutex); - db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff; + db->errMask = 0xff; db->nDb = 2; - db->eOpenState = SQLITE_STATE_BUSY; + db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; - db->lookaside.bDisable = 1; - db->lookaside.sz = 0; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS; db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; - db->init.azInit = sqlite3StdType; /* Any array of string ptrs will do */ -#ifdef SQLITE_ENABLE_SORTER_MMAP - /* Beginning with version 3.37.0, using the VFS xFetch() API to memory-map - ** the temporary files used to do external sorts (see code in vdbesort.c) - ** is disabled. It can still be used either by defining - ** SQLITE_ENABLE_SORTER_MMAP at compile time or by using the - ** SQLITE_TESTCTRL_SORTER_MMAP test-control at runtime. */ db->nMaxSorterMmap = 0x7FFFFFFF; -#endif - db->flags |= SQLITE_ShortColNames - | SQLITE_EnableTrigger - | SQLITE_EnableView - | SQLITE_CacheSpill - | SQLITE_AttachCreate - | SQLITE_AttachWrite - | SQLITE_Comments -#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0 - | SQLITE_TrustedSchema -#endif -/* The SQLITE_DQS compile-time option determines the default settings -** for SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML. -** -** SQLITE_DQS SQLITE_DBCONFIG_DQS_DDL SQLITE_DBCONFIG_DQS_DML -** ---------- ----------------------- ----------------------- -** undefined on on -** 3 on on -** 2 on off -** 1 off on -** 0 off off -** -** Legacy behavior is 3 (double-quoted string literals are allowed anywhere) -** and so that is the default. But developers are encouraged to use -** -DSQLITE_DQS=0 (best) or -DSQLITE_DQS=1 (second choice) if possible. -*/ -#if !defined(SQLITE_DQS) -# define SQLITE_DQS 3 -#endif -#if (SQLITE_DQS&1)==1 - | SQLITE_DqsDML -#endif -#if (SQLITE_DQS&2)==2 - | SQLITE_DqsDDL -#endif - + db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill #if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX | SQLITE_AutoIndex #endif #if SQLITE_DEFAULT_CKPTFULLFSYNC | SQLITE_CkptFullFSync @@ -184906,19 +144416,10 @@ | SQLITE_Fts3Tokenizer #endif #if defined(SQLITE_ENABLE_QPSG) | SQLITE_EnableQPSG #endif -#if defined(SQLITE_DEFAULT_DEFENSIVE) - | SQLITE_Defensive -#endif -#if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE) - | SQLITE_LegacyAlter -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) - | SQLITE_StmtScanStatus -#endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3HashInit(&db->aModule); #endif @@ -184932,31 +144433,23 @@ */ createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0); createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0); createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0); createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); - createCollation(db, "RTRIM", SQLITE_UTF8, 0, rtrimCollFunc, 0); + createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); if( db->mallocFailed ){ goto opendb_out; } - -#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) - /* Process magic filenames ":localStorage:" and ":sessionStorage:" */ - if( zFilename && zFilename[0]==':' ){ - if( strcmp(zFilename, ":localStorage:")==0 ){ - zFilename = "file:local?vfs=kvvfs"; - flags |= SQLITE_OPEN_URI; - }else if( strcmp(zFilename, ":sessionStorage:")==0 ){ - zFilename = "file:session?vfs=kvvfs"; - flags |= SQLITE_OPEN_URI; - } - } -#endif /* SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) */ + /* EVIDENCE-OF: R-08308-17224 The default collating function for all + ** strings is BINARY. + */ + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0); + assert( db->pDfltColl!=0 ); /* Parse the filename/URI argument ** - ** Only allow sensible combinations of bits in the flags argument. + ** Only allow sensible combinations of bits in the flags argument. ** Throw an error if any non-sense combination is used. If we ** do not block illegal combinations here, it could trigger ** assert() statements in deeper layers. Sensible combinations ** are: ** @@ -184970,27 +144463,20 @@ assert( SQLITE_OPEN_CREATE == 0x04 ); testcase( (1<<(flags&7))==0x02 ); /* READONLY */ testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ if( ((1<<(flags&7)) & 0x46)==0 ){ - rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */ + rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */ }else{ - if( zFilename==0 ) zFilename = ":memory:"; rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); } if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; } - assert( db->pVfs!=0 ); -#if SQLITE_OS_KV || defined(SQLITE_OS_KV_OPTIONAL) - if( sqlite3_stricmp(db->pVfs->zName, "kvvfs")==0 ){ - db->temp_store = 2; - } -#endif /* Open the backend database driver */ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, flags | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ @@ -185000,25 +144486,23 @@ sqlite3Error(db, rc); goto opendb_out; } sqlite3BtreeEnter(db->aDb[0].pBt); db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); - if( !db->mallocFailed ){ - sqlite3SetTextEncoding(db, SCHEMA_ENC(db)); - } + if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); sqlite3BtreeLeave(db->aDb[0].pBt); db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); /* The default safety_level for the main database is FULL; for the temp - ** database it is OFF. This matches the pager layer defaults. + ** database it is OFF. This matches the pager layer defaults. */ db->aDb[0].zDbSName = "main"; db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; db->aDb[1].zDbSName = "temp"; db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; - db->eOpenState = SQLITE_STATE_OPEN; + db->magic = SQLITE_MAGIC_OPEN; if( db->mallocFailed ){ goto opendb_out; } /* Register all built-in functions, but do not attempt to read the @@ -185027,15 +144511,18 @@ */ sqlite3Error(db, SQLITE_OK); sqlite3RegisterPerConnectionBuiltinFunctions(db); rc = sqlite3_errcode(db); - - /* Load compiled-in extensions */ - for(i=0; rc==SQLITE_OK && imallocFailed && rc==SQLITE_OK ){ + rc = sqlite3Fts5Init(db); } +#endif /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ if( rc==SQLITE_OK ){ @@ -185044,15 +144531,58 @@ if( rc!=SQLITE_OK ){ goto opendb_out; } } -#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS - /* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time - ** option gives access to internal functions by default. - ** Testing use only!!! */ - db->mDbFlags |= DBFLAG_InternalFunc; +#ifdef SQLITE_ENABLE_FTS1 + if( !db->mallocFailed ){ + extern int sqlite3Fts1Init(sqlite3*); + rc = sqlite3Fts1Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS2 + if( !db->mallocFailed && rc==SQLITE_OK ){ + extern int sqlite3Fts2Init(sqlite3*); + rc = sqlite3Fts2Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */ + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3Fts3Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_ICU + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3IcuInit(db); + } +#endif + +#ifdef SQLITE_ENABLE_RTREE + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3RtreeInit(db); + } +#endif + +#ifdef SQLITE_ENABLE_DBSTAT_VTAB + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3DbstatRegister(db); + } +#endif + +#ifdef SQLITE_ENABLE_JSON1 + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3Json1Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_STMTVTAB + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3StmtVtabInit(db); + } #endif /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. @@ -185076,36 +144606,52 @@ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); sqlite3_mutex_leave(db->mutex); } rc = sqlite3_errcode(db); - assert( db!=0 || (rc&0xff)==SQLITE_NOMEM ); - if( (rc&0xff)==SQLITE_NOMEM ){ + assert( db!=0 || rc==SQLITE_NOMEM ); + if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ - db->eOpenState = SQLITE_STATE_SICK; + db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ /* Opening a db handle. Fourth parameter is passed 0. */ void *pArg = sqlite3GlobalConfig.pSqllogArg; sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif - sqlite3_free_filename(zOpen); - return rc; +#if defined(SQLITE_HAS_CODEC) + if( rc==SQLITE_OK ){ + const char *zKey; + if( (zKey = sqlite3_uri_parameter(zOpen, "hexkey"))!=0 && zKey[0] ){ + u8 iByte; + int i; + char zDecoded[40]; + for(i=0, iByte=0; ipCollNeededArg = pCollNeededArg; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } #endif /* SQLITE_OMIT_UTF16 */ - -/* -** Find existing client data. -*/ -SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){ - DbClientData *p; - sqlite3_mutex_enter(db->mutex); - for(p=db->pDbData; p; p=p->pNext){ - if( strcmp(p->zName, zName)==0 ){ - void *pResult = p->pData; - sqlite3_mutex_leave(db->mutex); - return pResult; - } - } - sqlite3_mutex_leave(db->mutex); - return 0; -} - -/* -** Add new client data to a database connection. -*/ -SQLITE_API int sqlite3_set_clientdata( - sqlite3 *db, /* Attach client data to this connection */ - const char *zName, /* Name of the client data */ - void *pData, /* The client data itself */ - void (*xDestructor)(void*) /* Destructor */ -){ - DbClientData *p, **pp; - sqlite3_mutex_enter(db->mutex); - pp = &db->pDbData; - for(p=db->pDbData; p && strcmp(p->zName,zName); p=p->pNext){ - pp = &p->pNext; - } - if( p ){ - assert( p->pData!=0 ); - if( p->xDestructor ) p->xDestructor(p->pData); - if( pData==0 ){ - *pp = p->pNext; - sqlite3_free(p); - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; - } - }else if( pData==0 ){ - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; - }else{ - size_t n = strlen(zName); - p = sqlite3_malloc64( sizeof(DbClientData)+n+1 ); - if( p==0 ){ - if( xDestructor ) xDestructor(pData); - sqlite3_mutex_leave(db->mutex); - return SQLITE_NOMEM; - } - memcpy(p->zName, zName, n+1); - p->pNext = db->pDbData; - db->pDbData = p; - } - p->pData = pData; - p->xDestructor = xDestructor; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - #ifndef SQLITE_OMIT_DEPRECATED /* ** This function is now an anachronism. It used to be used to recover from a ** malloc() failure, but SQLite now does this automatically. @@ -185364,43 +144847,41 @@ ** to detect when version error conditions occurs. ** ** 2. Invoke sqlite3_log() to provide the source code location where ** a low-level error is first detected. */ -SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType){ +static int reportError(int iErr, int lineno, const char *zType){ sqlite3_log(iErr, "%s at line %d of [%.10s]", zType, lineno, 20+sqlite3_sourceid()); return iErr; } SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); + return reportError(SQLITE_CORRUPT, lineno, "database corruption"); } SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse"); + return reportError(SQLITE_MISUSE, lineno, "misuse"); } SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file"); + return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); } -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO) +#ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ char zMsg[100]; sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); + return reportError(SQLITE_CORRUPT, lineno, zMsg); } -#endif -#ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3NomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM"); + return reportError(SQLITE_NOMEM, lineno, "OOM"); } SQLITE_PRIVATE int sqlite3IoerrnomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); + return reportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); } #endif #ifndef SQLITE_OMIT_DEPRECATED /* @@ -185455,22 +144936,22 @@ goto error_out; } /* Locate the table in question */ pTab = sqlite3FindTable(db, zTableName, zDbName); - if( !pTab || IsView(pTab) ){ + if( !pTab || pTab->pSelect ){ pTab = 0; goto error_out; } /* Find the column for which info is requested */ if( zColumnName==0 ){ - /* Query for existence of table only */ + /* Query for existance of table only */ }else{ for(iCol=0; iColnCol; iCol++){ pCol = &pTab->aCol[iCol]; - if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){ + if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ break; } } if( iCol==pTab->nCol ){ if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ @@ -185484,20 +144965,20 @@ } /* The following block stores the meta information that will be returned ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey ** and autoinc. At this point there are two possibilities: + ** + ** 1. The specified column name was rowid", "oid" or "_rowid_" + ** and there is no explicitly declared IPK column. ** - ** 1. The specified column name was rowid", "oid" or "_rowid_" - ** and there is no explicitly declared IPK column. - ** - ** 2. The table is not a view and the column name identified an + ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. - */ + */ if( pCol ){ zDataType = sqlite3ColumnType(pCol,0); - zCollSeq = sqlite3ColumnColl(pCol); + zCollSeq = pCol->zColl; notnull = pCol->notNull!=0; primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0; }else{ zDataType = "INTEGER"; @@ -185540,14 +145021,14 @@ sqlite3_vfs *pVfs; int rc; pVfs = sqlite3_vfs_find(0); if( pVfs==0 ) return 0; - /* This function works in milliseconds, but the underlying OsSleep() + /* This function works in milliseconds, but the underlying OsSleep() ** API uses microseconds. Hence the 1000's. */ - rc = (sqlite3OsSleep(pVfs, ms<0 ? 0 : 1000*ms)/1000); + rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); return rc; } /* ** Enable or disable the extended result codes. @@ -185589,27 +145070,14 @@ *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_DATA_VERSION ){ - *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_RESERVE_BYTES ){ - int iNew = *(int*)pArg; - *(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree); - if( iNew>=0 && iNew<=255 ){ - sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0); - } - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_RESET_CACHE ){ - sqlite3BtreeClearCache(pBtree); - rc = SQLITE_OK; - }else{ - int nSave = db->busyHandler.nBusy; + }else if( fd->pMethods ){ rc = sqlite3OsFileControl(fd, op, pArg); - db->busyHandler.nBusy = nSave; + }else{ + rc = SQLITE_NOTFOUND; } sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); return rc; @@ -185643,62 +145111,17 @@ case SQLITE_TESTCTRL_PRNG_RESTORE: { sqlite3PrngRestoreState(); break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db); - ** - ** Control the seed for the pseudo-random number generator (PRNG) that - ** is built into SQLite. Cases: - ** - ** x!=0 && db!=0 Seed the PRNG to the current value of the - ** schema cookie in the main database for db, or - ** x if the schema cookie is zero. This case - ** is convenient to use with database fuzzers - ** as it allows the fuzzer some control over the - ** the PRNG seed. - ** - ** x!=0 && db==0 Seed the PRNG to the value of x. - ** - ** x==0 && db==0 Revert to default behavior of using the - ** xRandomness method on the primary VFS. - ** - ** This test-control also resets the PRNG so that the new seed will - ** be used for the next call to sqlite3_randomness(). - */ -#ifndef SQLITE_OMIT_WSD - case SQLITE_TESTCTRL_PRNG_SEED: { - int x = va_arg(ap, int); - int y; - sqlite3 *db = va_arg(ap, sqlite3*); - assert( db==0 || db->aDb[0].pSchema!=0 ); - if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; } - sqlite3Config.iPrngSeed = x; - sqlite3_randomness(0,0); - break; - } -#endif - - /* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b); - ** - ** If b is true, then activate the SQLITE_FkNoAction setting. If b is - ** false then clearn that setting. If the SQLITE_FkNoAction setting is - ** abled, all foreign key ON DELETE and ON UPDATE actions behave as if - ** they were NO ACTION, regardless of how they are defined. - ** - ** NB: One must usually run "PRAGMA writable_schema=RESET" after - ** using this test-control, before it will take full effect. failing - ** to reset the schema can result in some unexpected behavior. - */ - case SQLITE_TESTCTRL_FK_NO_ACTION: { - sqlite3 *db = va_arg(ap, sqlite3*); - int b = va_arg(ap, int); - if( b ){ - db->flags |= SQLITE_FkNoAction; - }else{ - db->flags &= ~SQLITE_FkNoAction; - } + /* + ** Reset the PRNG back to its uninitialized state. The next call + ** to sqlite3_randomness() will reseed the PRNG using a single call + ** to the xRandomness method of the default VFS. + */ + case SQLITE_TESTCTRL_PRNG_RESET: { + sqlite3_randomness(0,0); break; } /* ** sqlite3_test_control(BITVEC_TEST, size, program) @@ -185725,28 +145148,24 @@ ** is called immediately after installing the new callback and the return ** value from sqlite3FaultSim(0) becomes the return from ** sqlite3_test_control(). */ case SQLITE_TESTCTRL_FAULT_INSTALL: { - /* A bug in MSVC prevents it from understanding pointers to functions - ** types in the second argument to va_arg(). Work around the problem - ** using a typedef. - ** http://support.microsoft.com/kb/47961 <-- dead hyperlink - ** Search at http://web.archive.org/ to find the 2015-03-16 archive - ** of the link above to see the original text. + /* MSVC is picky about pulling func ptrs from va lists. + ** http://support.microsoft.com/kb/47961 ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int)); */ - typedef int(*sqlite3FaultFuncType)(int); - sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType); + typedef int(*TESTCALLBACKFUNC_t)(int); + sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t); rc = sqlite3FaultSim(0); break; } /* ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd) ** - ** Register hooks to call to indicate which malloc() failures + ** Register hooks to call to indicate which malloc() failures ** are benign. */ case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: { typedef void (*void_function)(void); void_function xBenignBegin; @@ -185793,33 +145212,10 @@ */ case SQLITE_TESTCTRL_ASSERT: { volatile int x = 0; assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); rc = x; -#if defined(SQLITE_DEBUG) - /* Invoke these debugging routines so that the compiler does not - ** issue "defined but not used" warnings. */ - if( x==9999 ){ - sqlite3ShowExpr(0); - sqlite3ShowExprList(0); - sqlite3ShowIdList(0); - sqlite3ShowSrcList(0); - sqlite3ShowWith(0); - sqlite3ShowUpsert(0); -#ifndef SQLITE_OMIT_TRIGGER - sqlite3ShowTriggerStep(0); - sqlite3ShowTriggerStepList(0); - sqlite3ShowTrigger(0); - sqlite3ShowTriggerList(0); -#endif -#ifndef SQLITE_OMIT_WINDOWFUNC - sqlite3ShowWindow(0); - sqlite3ShowWinFunc(0); -#endif - sqlite3ShowSelect(0); - } -#endif break; } /* @@ -185826,11 +145222,11 @@ ** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X) ** ** This action provides a run-time test to see how the ALWAYS and ** NEVER macros were defined at compile-time. ** - ** The return value is ALWAYS(X) if X is true, or 0 if X is false. + ** The return value is ALWAYS(X). ** ** The recommended test is X==2. If the return value is 2, that means ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the ** default setting. If the return value is 1, then ALWAYS() is either ** hard-coded to true or else it asserts if its argument is false. @@ -185849,11 +145245,11 @@ ** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0. ** } */ case SQLITE_TESTCTRL_ALWAYS: { int x = va_arg(ap,int); - rc = x ? ALWAYS(x) : 0; + rc = ALWAYS(x); break; } /* ** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER); @@ -185863,108 +145259,103 @@ ** ** 1 big-endian, determined at run-time ** 10 little-endian, determined at run-time ** 432101 big-endian, determined at compile-time ** 123410 little-endian, determined at compile-time - */ + */ case SQLITE_TESTCTRL_BYTEORDER: { rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN; break; } + + /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N) + ** + ** Set the nReserve size to N for the main database on the database + ** connection db. + */ + case SQLITE_TESTCTRL_RESERVE: { + sqlite3 *db = va_arg(ap, sqlite3*); + int x = va_arg(ap,int); + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0); + sqlite3_mutex_leave(db->mutex); + break; + } /* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N) ** - ** Enable or disable various optimizations for testing purposes. The + ** Enable or disable various optimizations for testing purposes. The ** argument N is a bitmask of optimizations to be disabled. For normal ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); - db->dbOptFlags = va_arg(ap, u32); + db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, sqlite3 *db, int *N) +#ifdef SQLITE_N_KEYWORD + /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) + ** + ** If zWord is a keyword recognized by the parser, then return the + ** number of keywords. Or if zWord is not a keyword, return 0. + ** + ** This test feature is only available in the amalgamation since + ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite + ** is built using separate source files. + */ + case SQLITE_TESTCTRL_ISKEYWORD: { + const char *zWord = va_arg(ap, const char*); + int n = sqlite3Strlen30(zWord); + rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; + break; + } +#endif + + /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); ** - ** Write the current optimization settings into *N. A zero bit means that - ** the optimization is on, and a 1 bit means that the optimization is off. + ** Pass pFree into sqlite3ScratchFree(). + ** If sz>0 then allocate a scratch buffer into pNew. */ - case SQLITE_TESTCTRL_GETOPT: { - sqlite3 *db = va_arg(ap, sqlite3*); - int *pN = va_arg(ap, int*); - *pN = db->dbOptFlags; - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt); - ** - ** If parameter onoff is 1, subsequent calls to localtime() fail. - ** If 2, then invoke xAlt() instead of localtime(). If 0, normal - ** processing. - ** - ** xAlt arguments are void pointers, but they really want to be: - ** - ** int xAlt(const time_t*, struct tm*); - ** - ** xAlt should write results in to struct tm object of its 2nd argument - ** and return zero on success, or return non-zero on failure. + case SQLITE_TESTCTRL_SCRATCHMALLOC: { + void *pFree, **ppNew; + int sz; + sz = va_arg(ap, int); + ppNew = va_arg(ap, void**); + pFree = va_arg(ap, void*); + if( sz ) *ppNew = sqlite3ScratchMalloc(sz); + sqlite3ScratchFree(pFree); + break; + } + + /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); + ** + ** If parameter onoff is non-zero, configure the wrappers so that all + ** subsequent calls to localtime() and variants fail. If onoff is zero, + ** undo this setting. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); - if( sqlite3GlobalConfig.bLocaltimeFault==2 ){ - typedef int(*sqlite3LocaltimeType)(const void*,void*); - sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType); - }else{ - sqlite3GlobalConfig.xAltLocaltime = 0; - } - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*); - ** - ** Toggle the ability to use internal functions on or off for - ** the database connection given in the argument. - */ - case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { - sqlite3 *db = va_arg(ap, sqlite3*); - db->mDbFlags ^= DBFLAG_InternalFunc; break; } /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); ** ** Set or clear a flag that indicates that the database file is always well- ** formed and never corrupt. This flag is clear by default, indicating that ** database files might have arbitrary corruption. Setting the flag during ** testing causes certain assert() statements in the code to be activated - ** that demonstrate invariants on well-formed database files. + ** that demonstrat invariants on well-formed database files. */ case SQLITE_TESTCTRL_NEVER_CORRUPT: { sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int); break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int); - ** - ** Set or clear a flag that causes SQLite to verify that type, name, - ** and tbl_name fields of the sqlite_schema table. This is normally - ** on, but it is sometimes useful to turn it off for testing. - ** - ** 2020-07-22: Disabling EXTRA_SCHEMA_CHECKS also disables the - ** verification of rootpage numbers when parsing the schema. This - ** is useful to make it easier to reach strange internal error states - ** during testing. The EXTRA_SCHEMA_CHECKS setting is always enabled - ** in production. - */ - case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: { - sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int); - break; - } - /* Set the threshold at which OP_Once counters reset back to zero. ** By default this is 0x7ffffffe (over 2 billion), but that value is ** too big to test in a reasonable amount of time, so this control is ** provided to set a small and easily reachable reset value. */ @@ -185973,17 +145364,16 @@ break; } /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); ** - ** Set the VDBE coverage callback function to xCallback with context + ** Set the VDBE coverage callback function to xCallback with context ** pointer ptr. */ case SQLITE_TESTCTRL_VDBE_COVERAGE: { #ifdef SQLITE_VDBE_COVERAGE - typedef void (*branch_callback)(void*,unsigned int, - unsigned char,unsigned char); + typedef void (*branch_callback)(void*,int,u8,u8); sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback); sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*); #endif break; } @@ -186021,253 +145411,29 @@ ** the schema to be reparsed the next time it is needed. This has the ** effect of erasing all imposter tables. */ case SQLITE_TESTCTRL_IMPOSTER: { sqlite3 *db = va_arg(ap, sqlite3*); - int iDb; sqlite3_mutex_enter(db->mutex); - iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); - if( iDb>=0 ){ - db->init.iDb = iDb; - db->init.busy = db->init.imposterTable = va_arg(ap,int); - db->init.newTnum = va_arg(ap,int); - if( db->init.busy==0 && db->init.newTnum>0 ){ - sqlite3ResetAllSchemasOfConnection(db); - } + db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); + db->init.busy = db->init.imposterTable = va_arg(ap,int); + db->init.newTnum = va_arg(ap,int); + if( db->init.busy==0 && db->init.newTnum>0 ){ + sqlite3ResetAllSchemasOfConnection(db); } sqlite3_mutex_leave(db->mutex); - break; - } - -#if defined(YYCOVERAGE) - /* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out) - ** - ** This test control (only available when SQLite is compiled with - ** -DYYCOVERAGE) writes a report onto "out" that shows all - ** state/lookahead combinations in the parser state machine - ** which are never exercised. If any state is missed, make the - ** return code SQLITE_ERROR. - */ - case SQLITE_TESTCTRL_PARSER_COVERAGE: { - FILE *out = va_arg(ap, FILE*); - if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR; - break; - } -#endif /* defined(YYCOVERAGE) */ - - /* sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, sqlite3_context*); - ** - ** This test-control causes the most recent sqlite3_result_int64() value - ** to be interpreted as a MEM_IntReal instead of as an MEM_Int. Normally, - ** MEM_IntReal values only arise during an INSERT operation of integer - ** values into a REAL column, so they can be challenging to test. This - ** test-control enables us to write an intreal() SQL function that can - ** inject an intreal() value at arbitrary places in an SQL statement, - ** for testing purposes. - */ - case SQLITE_TESTCTRL_RESULT_INTREAL: { - sqlite3_context *pCtx = va_arg(ap, sqlite3_context*); - sqlite3ResultIntReal(pCtx); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT, - ** sqlite3 *db, // Database connection - ** u64 *pnSeek // Write seek count here - ** ); - ** - ** This test-control queries the seek-counter on the "main" database - ** file. The seek-counter is written into *pnSeek and is then reset. - ** The seek-count is only available if compiled with SQLITE_DEBUG. - */ - case SQLITE_TESTCTRL_SEEK_COUNT: { - sqlite3 *db = va_arg(ap, sqlite3*); - u64 *pn = va_arg(ap, sqlite3_uint64*); - *pn = sqlite3BtreeSeekCount(db->aDb->pBt); - (void)db; /* Silence harmless unused variable warning */ - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr) - ** - ** "ptr" is a pointer to a u32. - ** - ** op==0 Store the current sqlite3TreeTrace in *ptr - ** op==1 Set sqlite3TreeTrace to the value *ptr - ** op==2 Store the current sqlite3WhereTrace in *ptr - ** op==3 Set sqlite3WhereTrace to the value *ptr - */ - case SQLITE_TESTCTRL_TRACEFLAGS: { - int opTrace = va_arg(ap, int); - u32 *ptr = va_arg(ap, u32*); - switch( opTrace ){ - case 0: *ptr = sqlite3TreeTrace; break; - case 1: sqlite3TreeTrace = *ptr; break; - case 2: *ptr = sqlite3WhereTrace; break; - case 3: sqlite3WhereTrace = *ptr; break; - } - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST, - ** double fIn, // Input value - ** int *pLogEst, // sqlite3LogEstFromDouble(fIn) - ** u64 *pInt, // sqlite3LogEstToInt(*pLogEst) - ** int *pLogEst2 // sqlite3LogEst(*pInt) - ** ); - ** - ** Test access for the LogEst conversion routines. - */ - case SQLITE_TESTCTRL_LOGEST: { - double rIn = va_arg(ap, double); - LogEst rLogEst = sqlite3LogEstFromDouble(rIn); - int *pI1 = va_arg(ap,int*); - u64 *pU64 = va_arg(ap,u64*); - int *pI2 = va_arg(ap,int*); - *pI1 = rLogEst; - *pU64 = sqlite3LogEstToInt(rLogEst); - *pI2 = sqlite3LogEst(*pU64); - break; - } - -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) - /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) - ** - ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value - ** of the id-th tuning parameter to *piValue. If "id" is between -1 - ** and -SQLITE_NTUNE, then write the current value of the (-id)-th - ** tuning parameter into *piValue. - ** - ** Tuning parameters are for use during transient development builds, - ** to help find the best values for constants in the query planner. - ** Access tuning parameters using the Tuning(ID) macro. Set the - ** parameters in the CLI using ".testctrl tune ID VALUE". - ** - ** Transient use only. Tuning parameters should not be used in - ** checked-in code. - */ - case SQLITE_TESTCTRL_TUNE: { - int id = va_arg(ap, int); - int *piValue = va_arg(ap, int*); - if( id>0 && id<=SQLITE_NTUNE ){ - Tuning(id) = *piValue; - }else if( id<0 && id>=-SQLITE_NTUNE ){ - *piValue = Tuning(-id); - }else{ - rc = SQLITE_NOTFOUND; - } - break; - } -#endif - - /* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff); - ** - ** Activate or deactivate validation of JSONB that is generated from - ** text. Off by default, as the validation is slow. Validation is - ** only available if compiled using SQLITE_DEBUG. - ** - ** If onOff is initially 1, then turn it on. If onOff is initially - ** off, turn it off. If onOff is initially -1, then change onOff - ** to be the current setting. - */ - case SQLITE_TESTCTRL_JSON_SELFCHECK: { -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) - int *pOnOff = va_arg(ap, int*); - if( *pOnOff<0 ){ - *pOnOff = sqlite3Config.bJsonSelfcheck; - }else{ - sqlite3Config.bJsonSelfcheck = (u8)((*pOnOff)&0xff); - } -#endif break; } } va_end(ap); #endif /* SQLITE_UNTESTABLE */ return rc; } - -/* -** The Pager stores the Database filename, Journal filename, and WAL filename -** consecutively in memory, in that order. The database filename is prefixed -** by four zero bytes. Locate the start of the database filename by searching -** backwards for the first byte following four consecutive zero bytes. -** -** This only works if the filename passed in was obtained from the Pager. -*/ -static const char *databaseName(const char *zName){ - while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){ - zName--; - } - return zName; -} - -/* -** Append text z[] to the end of p[]. Return a pointer to the first -** character after then zero terminator on the new text in p[]. -*/ -static char *appendText(char *p, const char *z){ - size_t n = strlen(z); - memcpy(p, z, n+1); - return p+n+1; -} - -/* -** Allocate memory to hold names for a database, journal file, WAL file, -** and query parameters. The pointer returned is valid for use by -** sqlite3_filename_database() and sqlite3_uri_parameter() and related -** functions. -** -** Memory layout must be compatible with that generated by the pager -** and expected by sqlite3_uri_parameter() and databaseName(). -*/ -SQLITE_API const char *sqlite3_create_filename( - const char *zDatabase, - const char *zJournal, - const char *zWal, - int nParam, - const char **azParam -){ - sqlite3_int64 nByte; - int i; - char *pResult, *p; - nByte = strlen(zDatabase) + strlen(zJournal) + strlen(zWal) + 10; - for(i=0; i0 ){ - zFilename += sqlite3Strlen30(zFilename) + 1; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return zFilename[0] ? zFilename : 0; + zFilename += sqlite3Strlen30(zFilename) + 1; + while( zFilename[0] ){ + int x = strcmp(zFilename, zParam); + zFilename += sqlite3Strlen30(zFilename) + 1; + if( x==0 ) return zFilename; + zFilename += sqlite3Strlen30(zFilename) + 1; + } + return 0; } /* ** Return a boolean value for a query parameter. */ @@ -186311,76 +145469,24 @@ const char *zParam, /* URI parameter sought */ sqlite3_int64 bDflt /* return if parameter is missing */ ){ const char *z = sqlite3_uri_parameter(zFilename, zParam); sqlite3_int64 v; - if( z && sqlite3DecOrHexToI64(z, &v)==0 ){ + if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){ bDflt = v; } return bDflt; } -/* -** Translate a filename that was handed to a VFS routine into the corresponding -** database, journal, or WAL file. -** -** It is an error to pass this routine a filename string that was not -** passed into the VFS from the SQLite core. Doing so is similar to -** passing free() a pointer that was not obtained from malloc() - it is -** an error that we cannot easily detect but that will likely cause memory -** corruption. -*/ -SQLITE_API const char *sqlite3_filename_database(const char *zFilename){ - if( zFilename==0 ) return 0; - return databaseName(zFilename); -} -SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){ - if( zFilename==0 ) return 0; - zFilename = databaseName(zFilename); - zFilename += sqlite3Strlen30(zFilename) + 1; - while( ALWAYS(zFilename) && zFilename[0] ){ - zFilename += sqlite3Strlen30(zFilename) + 1; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return zFilename + 1; -} -SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){ -#ifdef SQLITE_OMIT_WAL - return 0; -#else - zFilename = sqlite3_filename_journal(zFilename); - if( zFilename ) zFilename += sqlite3Strlen30(zFilename) + 1; - return zFilename; -#endif -} - /* ** Return the Btree pointer identified by zDbName. Return NULL if not found. */ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; return iDb<0 ? 0 : db->aDb[iDb].pBt; } -/* -** Return the name of the N-th database schema. Return NULL if N is out -** of range. -*/ -SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - if( N<0 || N>=db->nDb ){ - return 0; - }else{ - return db->aDb[N].zDbSName; - } -} - /* ** Return the filename of the database associated with a database ** connection. */ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ @@ -186411,15 +145517,15 @@ return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; } #ifdef SQLITE_ENABLE_SNAPSHOT /* -** Obtain a snapshot handle for the snapshot of database zDb currently +** Obtain a snapshot handle for the snapshot of database zDb currently ** being read by handle db. */ SQLITE_API int sqlite3_snapshot_get( - sqlite3 *db, + sqlite3 *db, const char *zDb, sqlite3_snapshot **ppSnapshot ){ int rc = SQLITE_ERROR; #ifndef SQLITE_OMIT_WAL @@ -186433,16 +145539,12 @@ if( db->autoCommit==0 ){ int iDb = sqlite3FindDbName(db, zDb); if( iDb==0 || iDb>1 ){ Btree *pBt = db->aDb[iDb].pBt; - if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){ - Pager *pPager = sqlite3BtreePager(pBt); - i64 dummy = 0; - sqlite3PagerSnapshotOpen(pPager, (sqlite3_snapshot*)&dummy); - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - sqlite3PagerSnapshotOpen(pPager, 0); + if( 0==sqlite3BtreeIsInTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); } } } @@ -186452,15 +145554,15 @@ #endif /* SQLITE_OMIT_WAL */ return rc; } /* -** Open a read-transaction on the snapshot identified by pSnapshot. +** Open a read-transaction on the snapshot idendified by pSnapshot. */ SQLITE_API int sqlite3_snapshot_open( - sqlite3 *db, - const char *zDb, + sqlite3 *db, + const char *zDb, sqlite3_snapshot *pSnapshot ){ int rc = SQLITE_ERROR; #ifndef SQLITE_OMIT_WAL @@ -186473,33 +145575,15 @@ if( db->autoCommit==0 ){ int iDb; iDb = sqlite3FindDbName(db, zDb); if( iDb==0 || iDb>1 ){ Btree *pBt = db->aDb[iDb].pBt; - if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ){ - Pager *pPager = sqlite3BtreePager(pBt); - int bUnlock = 0; - if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_NONE ){ - if( db->nVdbeActive==0 ){ - rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot); - if( rc==SQLITE_OK ){ - bUnlock = 1; - rc = sqlite3BtreeCommit(pBt); - } - } - }else{ - rc = SQLITE_OK; - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot); - } - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - sqlite3PagerSnapshotOpen(pPager, 0); - } - if( bUnlock ){ - sqlite3PagerSnapshotUnlock(pPager); + if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ + rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); + sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); } } } } @@ -186512,12 +145596,12 @@ ** Recover as many snapshots as possible from the wal file associated with ** schema zDb of database db. */ SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ int rc = SQLITE_ERROR; -#ifndef SQLITE_OMIT_WAL int iDb; +#ifndef SQLITE_OMIT_WAL #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -186525,12 +145609,12 @@ sqlite3_mutex_enter(db->mutex); iDb = sqlite3FindDbName(db, zDb); if( iDb==0 || iDb>1 ){ Btree *pBt = db->aDb[iDb].pBt; - if( SQLITE_TXN_NONE==sqlite3BtreeTxnState(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); sqlite3BtreeCommit(pBt); } } @@ -186558,12 +145642,12 @@ */ SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ int i, n; int nOpt; const char **azCompileOpt; - -#ifdef SQLITE_ENABLE_API_ARMOR + +#if SQLITE_ENABLE_API_ARMOR if( zOptName==0 ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif @@ -186571,11 +145655,11 @@ azCompileOpt = sqlite3CompileOptions(&nOpt); if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; n = sqlite3Strlen30(zOptName); - /* Since nOpt is normally in single digits, a linear search is + /* Since nOpt is normally in single digits, a linear search is ** adequate. No need for a binary search. */ for(i=0; ixUnlockNotify!=db->xUnlockNotify; + pp=&sqlite3BlockedList; + *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify; pp=&(*pp)->pNextBlocked ); db->pNextBlocked = *pp; *pp = db; } /* -** Obtain the STATIC_MAIN mutex. +** Obtain the STATIC_MASTER mutex. */ static void enterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); checkListProperties(0); } /* -** Release the STATIC_MAIN mutex. +** Release the STATIC_MASTER mutex. */ static void leaveMutex(void){ assertMutexHeld(); checkListProperties(0); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } /* ** Register an unlock-notify callback. ** @@ -186754,13 +145838,10 @@ void (*xNotify)(void **, int), void *pArg ){ int rc = SQLITE_OK; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); enterMutex(); if( xNotify==0 ){ removeFromBlockedList(db); @@ -186767,13 +145848,13 @@ db->pBlockingConnection = 0; db->pUnlockConnection = 0; db->xUnlockNotify = 0; db->pUnlockArg = 0; }else if( 0==db->pBlockingConnection ){ - /* The blocking transaction has been concluded. Or there never was a + /* The blocking transaction has been concluded. Or there never was a ** blocking transaction. In either case, invoke the notify callback - ** immediately. + ** immediately. */ xNotify(&pArg, 1); }else{ sqlite3 *p; @@ -186795,11 +145876,11 @@ sqlite3_mutex_leave(db->mutex); return rc; } /* -** This function is called while stepping or preparing a statement +** This function is called while stepping or preparing a statement ** associated with connection db. The operation will return SQLITE_LOCKED ** to the user because it requires a lock that will not be available ** until connection pBlocker concludes its current transaction. */ SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){ @@ -186811,11 +145892,11 @@ leaveMutex(); } /* ** This function is called when -** the transaction opened by database db has just finished. Locks held +** the transaction opened by database db has just finished. Locks held ** by database connection db have been released. ** ** This function loops through each entry in the blocked connections ** list and does the following: ** @@ -186837,11 +145918,11 @@ void **aArg; /* Arguments to the unlock callback */ void **aDyn = 0; /* Dynamically allocated space for aArg[] */ void *aStatic[16]; /* Starter space for aArg[]. No malloc required */ aArg = aStatic; - enterMutex(); /* Enter STATIC_MAIN mutex */ + enterMutex(); /* Enter STATIC_MASTER mutex */ /* This loop runs once for each entry in the blocked-connections list. */ for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){ sqlite3 *p = *pp; @@ -186871,29 +145952,29 @@ sqlite3_free(aDyn); aDyn = aArg = pNew; }else{ /* This occurs when the array of context pointers that need to ** be passed to the unlock-notify callback is larger than the - ** aStatic[] array allocated on the stack and the attempt to + ** aStatic[] array allocated on the stack and the attempt to ** allocate a larger array from the heap has failed. ** ** This is a difficult situation to handle. Returning an error ** code to the caller is insufficient, as even if an error code ** is returned the transaction on connection db will still be ** closed and the unlock-notify callbacks on blocked connections ** will go unissued. This might cause the application to wait - ** indefinitely for an unlock-notify callback that will never + ** indefinitely for an unlock-notify callback that will never ** arrive. ** ** Instead, invoke the unlock-notify callback with the context ** array already accumulated. We can then clear the array and - ** begin accumulating any further context pointers without + ** begin accumulating any further context pointers without ** requiring any dynamic allocation. This is sub-optimal because ** it means that instead of one callback with a large array of ** context pointers the application will receive two or more ** callbacks with smaller arrays of context pointers, which will - ** reduce the applications ability to prioritize multiple + ** reduce the applications ability to prioritize multiple ** connections. But it is the best that can be done under the ** circumstances. */ xUnlockNotify(aArg, nArg); nArg = 0; @@ -186920,15 +146001,15 @@ if( nArg!=0 ){ xUnlockNotify(aArg, nArg); } sqlite3_free(aDyn); - leaveMutex(); /* Leave STATIC_MAIN mutex */ + leaveMutex(); /* Leave STATIC_MASTER mutex */ } /* -** This is called when the database connection passed as an argument is +** This is called when the database connection passed as an argument is ** being closed. The connection is removed from the blocked list. */ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ sqlite3ConnectionUnlocked(db); enterMutex(); @@ -187001,11 +146082,11 @@ ** **** Document lists **** ** A doclist (document list) holds a docid-sorted list of hits for a ** given term. Doclists hold docids and associated token positions. ** A docid is the unique integer identifier for a single document. -** A position is the index of a word within the document. The first +** A position is the index of a word within the document. The first ** word of the document has a position of 0. ** ** FTS3 used to optionally store character offsets using a compile-time ** option. But that functionality is no longer supported. ** @@ -187026,11 +146107,11 @@ ** varint POS_END; (marks end of positions for this document. ** } ** ** Here, array { X } means zero or more occurrences of X, adjacent in ** memory. A "position" is an index of a token in the token stream -** generated by the tokenizer. Note that POS_END and POS_COLUMN occur +** generated by the tokenizer. Note that POS_END and POS_COLUMN occur ** in the same logical place as the position element, and act as sentinals ** ending a position list array. POS_END is 0. POS_COLUMN is 1. ** The positions numbers are not stored literally but rather as two more ** than the difference from the prior position, or the just the position plus ** 2 for the first position. Example: @@ -187050,11 +146131,11 @@ ** a single docid. A "column-list" is the set of positions for a single ** column. Hence, a position-list consists of one or more column-lists, ** a document record consists of a docid followed by a position-list and ** a doclist consists of one or more document records. ** -** A bare doclist omits the position information, becoming an +** A bare doclist omits the position information, becoming an ** array of varint-encoded docids. ** **** Segment leaf nodes **** ** Segment leaf nodes store terms and doclists, ordered by term. Leaf ** nodes are written using LeafWriter, and read using LeafReader (to @@ -187246,11 +146327,11 @@ ** */ #ifndef _FTSINT_H #define _FTSINT_H -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif /* FTS3/FTS4 require virtual tables */ #ifdef SQLITE_OMIT_VIRTUALTABLE @@ -187269,11 +146350,11 @@ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE -/* # include "sqlite3ext.h" */ +/* # include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT3 #endif /* #include "sqlite3.h" */ /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ @@ -187313,11 +146394,11 @@ ** functions that make up an implementation. ** ** When an fts3 table is created, it passes any arguments passed to ** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the ** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an +** implementation. The xCreate() function in turn returns an ** sqlite3_tokenizer structure representing the specific tokenizer to ** be used for the fts3 table (customized by the tokenizer clause arguments). ** ** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() ** method is called. It returns an sqlite3_tokenizer_cursor object @@ -187345,11 +146426,11 @@ ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) ** ** then argc is set to 2, and the argv[] array contains pointers ** to the strings "arg1" and "arg2". ** - ** This method should return either SQLITE_OK (0), or an SQLite error + ** This method should return either SQLITE_OK (0), or an SQLite error ** code. If SQLITE_OK is returned, then *ppTokenizer should be set ** to point at the newly created tokenizer structure. The generic ** sqlite3_tokenizer.pModule variable should not be initialized by ** this callback. The caller will do so. */ @@ -187366,20 +146447,20 @@ int (*xDestroy)(sqlite3_tokenizer *pTokenizer); /* ** Create a tokenizer cursor to tokenize an input buffer. The caller ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). + ** until the cursor is closed (using the xClose() method). */ int (*xOpen)( sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ const char *pInput, int nBytes, /* Input buffer */ sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ ); /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this + ** Destroy an existing tokenizer cursor. The fts3 module calls this ** method exactly once for each successful call to xOpen(). */ int (*xClose)(sqlite3_tokenizer_cursor *pCursor); /* @@ -187386,11 +146467,11 @@ ** Retrieve the next token from the tokenizer cursor pCursor. This ** method should either return SQLITE_OK and set the values of the ** "OUT" variables identified below, or SQLITE_DONE to indicate that ** the end of the buffer has been reached, or an SQLite error code. ** - ** *ppToken should be set to point at a buffer containing the + ** *ppToken should be set to point at a buffer containing the ** normalized version of the token (i.e. after any case-folding and/or ** stemming has been performed). *pnBytes should be set to the length ** of this buffer in bytes. The input text that generated the token is ** identified by the byte offsets returned in *piStartOffset and ** *piEndOffset. *piStartOffset should be set to the index of the first @@ -187398,11 +146479,11 @@ ** to the index of the first byte just past the end of the token in ** the input buffer. ** ** The buffer *ppToken is set to point at is managed by the tokenizer ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). + ** to xNext() or xClose(). */ /* TODO(shess) current implementation requires pInput to be ** nul-terminated. This should either be fixed, or pInput/nBytes ** should be converted to zInput. */ @@ -187416,11 +146497,11 @@ /*********************************************************************** ** Methods below this point are only available if iVersion>=1. */ - /* + /* ** Configure the language id of a tokenizer cursor. */ int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); }; @@ -187485,11 +146566,11 @@ int count; /* Number of entries with this hash */ Fts3HashElem *chain; /* Pointer to first entry with this hash */ } *ht; }; -/* Each element in the hash table is an instance of the following +/* Each element in the hash table is an instance of the following ** structure. All elements are stored on a single doubly-linked list. ** ** Again, this structure is intended to be opaque, but it can't really ** be opaque because it is used by macros. */ @@ -187504,14 +146585,14 @@ ** ** FTS3_HASH_STRING pKey points to a string that is nKey bytes long ** (including the null-terminator, if any). Case ** is respected in comparisons. ** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. +** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. ** memcmp() is used to compare keys. ** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. +** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. */ #define FTS3_HASH_STRING 1 #define FTS3_HASH_BINARY 2 /* @@ -187560,11 +146641,11 @@ /************** End of fts3_hash.h *******************************************/ /************** Continuing where we left off in fts3Int.h ********************/ /* ** This constant determines the maximum depth of an FTS expression tree -** that the library will create and use. FTS uses recursion to perform +** that the library will create and use. FTS uses recursion to perform ** various operations on the query tree, so the disadvantage of a large ** limit is that it may allow very large queries to use large amounts ** of stack space (perhaps causing a stack overflow). */ #ifndef SQLITE_FTS3_MAX_EXPR_DEPTH @@ -187578,15 +146659,15 @@ ** segment of level N+1. */ #define FTS3_MERGE_COUNT 16 /* -** This is the maximum amount of data (in bytes) to store in the +** This is the maximum amount of data (in bytes) to store in the ** Fts3Table.pendingTerms hash table. Normally, the hash table is ** populated as documents are inserted/updated/deleted in a transaction ** and used to create a new segment when the transaction is committed. -** However if this limit is reached midway through a transaction, a new +** However if this limit is reached midway through a transaction, a new ** segment is created and the hash table cleared immediately. */ #define FTS3_MAX_PENDING_DATA (1*1024*1024) /* @@ -187608,25 +146689,23 @@ ** Maximum length of a varint encoded integer. The varint format is different ** from that used by SQLite, so the maximum length is 10, not 9. */ #define FTS3_VARINT_MAX 10 -#define FTS3_BUFFER_PADDING 8 - /* ** FTS4 virtual tables may maintain multiple indexes - one index of all terms ** in the document set and zero or more prefix indexes. All indexes are stored -** as one or more b+-trees in the %_segments and %_segdir tables. +** as one or more b+-trees in the %_segments and %_segdir tables. ** ** It is possible to determine which index a b+-tree belongs to based on the ** value stored in the "%_segdir.level" column. Given this value L, the index ** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with ** level values between 0 and 1023 (inclusive) belong to index 0, all levels ** between 1024 and 2047 to index 1, and so on. ** -** It is considered impossible for an index to use more than 1024 levels. In -** theory though this may happen, but only after at least +** It is considered impossible for an index to use more than 1024 levels. In +** theory though this may happen, but only after at least ** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables. */ #define FTS3_SEGDIR_MAXLEVEL 1024 #define FTS3_SEGDIR_MAXLEVEL_STR "1024" @@ -187640,46 +146719,33 @@ /* ** Terminator values for position-lists and column-lists. */ #define POS_COLUMN (1) /* Column-list terminator */ -#define POS_END (0) /* Position-list terminator */ - -/* -** The assert_fts3_nc() macro is similar to the assert() macro, except that it -** is used for assert() conditions that are true only if it can be -** guranteed that the database is not corrupt. -*/ -#ifdef SQLITE_DEBUG -SQLITE_API extern int sqlite3_fts3_may_be_corrupt; -# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x)) -#else -# define assert_fts3_nc(x) assert(x) -#endif +#define POS_END (0) /* Position-list terminator */ /* ** This section provides definitions to allow the -** FTS3 extension to be compiled outside of the +** FTS3 extension to be compiled outside of the ** amalgamation. */ #ifndef SQLITE_AMALGAMATION /* ** Macros indicating that conditional expressions are always true or ** false. */ -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) -# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 -#endif -#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) -# define ALWAYS(X) (1) -# define NEVER(X) (0) -#elif !defined(NDEBUG) -# define ALWAYS(X) ((X)?1:(assert(0),0)) -# define NEVER(X) ((X)?(assert(0),1):0) +#ifdef SQLITE_COVERAGE_TEST +# define ALWAYS(x) (1) +# define NEVER(X) (0) +#elif defined(SQLITE_DEBUG) +# define ALWAYS(x) sqlite3Fts3Always((x)!=0) +# define NEVER(x) sqlite3Fts3Never((x)!=0) +SQLITE_PRIVATE int sqlite3Fts3Always(int b); +SQLITE_PRIVATE int sqlite3Fts3Never(int b); #else -# define ALWAYS(X) (X) -# define NEVER(X) (X) +# define ALWAYS(x) (x) +# define NEVER(x) (x) #endif /* ** Internal types used by SQLite. */ @@ -187695,11 +146761,11 @@ #define UNUSED_PARAMETER(x) (void)(x) /* ** Activate assert() only if SQLITE_TEST is enabled. */ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif /* ** The TESTONLY macro is used to enclose variable declarations or @@ -187710,15 +146776,10 @@ # define TESTONLY(X) X #else # define TESTONLY(X) #endif -#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) -#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) - -#define deliberate_fall_through - #endif /* SQLITE_AMALGAMATION */ #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3Fts3Corrupt(void); # define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt() @@ -187758,14 +146819,13 @@ sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ char *zContentTbl; /* content=xxx option, or NULL */ char *zLanguageid; /* languageid=xxx option, or NULL */ int nAutoincrmerge; /* Value configured by 'automerge' */ u32 nLeafAdd; /* Number of leaf blocks added this trans */ - int bLock; /* Used to prevent recursive content= tbls */ - /* Precompiled statements used by the implementation. Each of these - ** statements is run and reset within a single virtual table API call. + /* Precompiled statements used by the implementation. Each of these + ** statements is run and reset within a single virtual table API call. */ sqlite3_stmt *aStmt[40]; sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */ char *zReadExprlist; @@ -187778,27 +146838,26 @@ u8 bDescIdx; /* True if doclists are in reverse order */ u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ int nPgsz; /* Page size for host database */ char *zSegmentsTbl; /* Name of %_segments table */ sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ - int iSavepoint; - /* - ** The following array of hash tables is used to buffer pending index + /* + ** The following array of hash tables is used to buffer pending index ** updates during transactions. All pending updates buffered at any one ** time must share a common language-id (see the FTS4 langid= feature). ** The current language id is stored in variable iPrevLangid. ** ** A single FTS4 table may have multiple full-text indexes. For each index ** there is an entry in the aIndex[] array. Index 0 is an index of all the ** terms that appear in the document set. Each subsequent index in aIndex[] ** is an index of prefixes of a specific length. ** - ** Variable nPendingData contains an estimate the memory consumed by the + ** Variable nPendingData contains an estimate the memory consumed by the ** pending data structures, including hash table overhead, but not including ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash - ** tables are flushed to disk. Variable iPrevDocid is the docid of the most + ** tables are flushed to disk. Variable iPrevDocid is the docid of the most ** recently inserted record. */ int nIndex; /* Size of aIndex[] */ struct Fts3Index { int nPrefix; /* Prefix length (0 for main terms index) */ @@ -187818,27 +146877,17 @@ */ int inTransaction; /* True after xBegin but before xCommit/xRollback */ int mxSavepoint; /* Largest valid xSavepoint integer */ #endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +#ifdef SQLITE_TEST /* True to disable the incremental doclist optimization. This is controled ** by special insert command 'test-no-incr-doclist'. */ int bNoIncrDoclist; - - /* Number of segments in a level */ - int nMergeCount; #endif }; -/* Macro to find the number of segments to merge */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) -# define MergeCount(P) ((P)->nMergeCount) -#else -# define MergeCount(P) FTS3_MERGE_COUNT -#endif - /* ** When the core wants to read from the virtual table, it creates a ** virtual table cursor (an instance of the following structure) using ** the xOpen method. Cursors are destroyed using the xClose method. */ @@ -187877,14 +146926,14 @@ ** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index ** of the column to be searched. For example, in ** ** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d); ** SELECT docid FROM ex1 WHERE b MATCH 'one two three'; -** +** ** Because the LHS of the MATCH operator is 2nd column "b", ** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a, -** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" +** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" ** indicating that all columns should be searched, ** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. */ #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ @@ -187939,25 +146988,25 @@ /* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an ** OR condition. */ char *pOrPoslist; i64 iOrDocid; - /* Variables below this point are populated by fts3_expr.c when parsing - ** a MATCH expression. Everything above is part of the evaluation phase. + /* Variables below this point are populated by fts3_expr.c when parsing + ** a MATCH expression. Everything above is part of the evaluation phase. */ int nToken; /* Number of tokens in the phrase */ int iColumn; /* Index of column this phrase must match */ Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */ }; /* ** A tree of these objects forms the RHS of a MATCH operator. ** -** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist -** points to a malloced buffer, size nDoclist bytes, containing the results -** of this phrase query in FTS3 doclist format. As usual, the initial -** "Length" field found in doclists stored on disk is omitted from this +** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist +** points to a malloced buffer, size nDoclist bytes, containing the results +** of this phrase query in FTS3 doclist format. As usual, the initial +** "Length" field found in doclists stored on disk is omitted from this ** buffer. ** ** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global ** matchinfo data. If it is not NULL, it points to an array of size nCol*3, ** where nCol is the number of columns in the queried FTS table. The array @@ -187965,11 +147014,11 @@ ** ** aMI[iCol*3 + 0] = Undefined ** aMI[iCol*3 + 1] = Number of occurrences ** aMI[iCol*3 + 2] = Number of rows containing at least one instance ** -** The aMI array is allocated using sqlite3_malloc(). It should be freed +** The aMI array is allocated using sqlite3_malloc(). It should be freed ** when the expression node is. */ struct Fts3Expr { int eType; /* One of the FTSQUERY_XXX values defined below */ int nNear; /* Valid if eType==FTSQUERY_NEAR */ @@ -187989,11 +147038,11 @@ u32 *aMI; /* See above */ }; /* ** Candidate values for Fts3Query.eType. Note that the order of the first -** four values is in order of precedence when parsing expressions. For +** four values is in order of precedence when parsing expressions. For ** example, the following: ** ** "a OR b AND c NOT d NEAR e" ** ** is equivalent to: @@ -188046,11 +147095,11 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, +SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, int, int, int, const char *, int, int, int, Fts3MultiSegReader *); /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 @@ -188072,11 +147121,11 @@ Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */ int nSegment; /* Size of apSegment array */ int nAdvance; /* How many seg-readers to advance */ Fts3SegFilter *pFilter; /* Pointer to filter object */ char *aBuffer; /* Buffer to merge doclists in */ - i64 nBuffer; /* Allocated size of aBuffer[] in bytes */ + int nBuffer; /* Allocated size of aBuffer[] in bytes */ int iColFilter; /* If >=0, filter for this column */ int bRestart; /* Used by fts3.c only. */ @@ -188098,26 +147147,23 @@ /* fts3.c */ SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); -SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *); -SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*); SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*); SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc); -SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut); /* fts3_tokenizer.c */ SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); -SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, +SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, sqlite3_tokenizer **, char ** ); SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char); /* fts3_snippet.c */ @@ -188132,14 +147178,13 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, char **, int, int, int, const char *, int, Fts3Expr **, char ** ); SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); #ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); +SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); #endif -SQLITE_PRIVATE void *sqlite3Fts3MallocZero(i64 nByte); SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, sqlite3_tokenizer_cursor ** ); @@ -188150,28 +147195,24 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart( Fts3Table*, Fts3MultiSegReader*, int, const char*, int); SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); -SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); +SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); /* fts3_tokenize_vtab.c */ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*)); +SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); /* fts3_unicode2.c (functions generated by parsing unicode text files) */ #ifndef SQLITE_DISABLE_FTS3_UNICODE SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); #endif -SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*); - -SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk); - #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ #endif /* _FTSINT_H */ /************** End of fts3Int.h *********************************************/ /************** Continuing where we left off in fts3.c ***********************/ @@ -188187,37 +147228,28 @@ /* #include */ /* #include */ /* #include */ /* #include "fts3.h" */ -#ifndef SQLITE_CORE +#ifndef SQLITE_CORE /* # include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #endif -typedef struct Fts3HashWrapper Fts3HashWrapper; -struct Fts3HashWrapper { - Fts3Hash hash; /* Hash table */ - int nRef; /* Number of pointers to this object */ -}; - static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); -/* -** This variable is set to false when running tests for which the on disk -** structures should not be corrupt. Otherwise, true. If it is false, extra -** assert() conditions in the fts3 code are activated - conditions that are -** only true if it is guaranteed that the fts3 database is not corrupt. -*/ -#ifdef SQLITE_DEBUG -SQLITE_API int sqlite3_fts3_may_be_corrupt = 1; +#ifndef SQLITE_AMALGAMATION +# if defined(SQLITE_DEBUG) +SQLITE_PRIVATE int sqlite3Fts3Always(int b) { assert( b ); return b; } +SQLITE_PRIVATE int sqlite3Fts3Never(int b) { assert( !b ); return b; } +# endif #endif -/* +/* ** Write a 64-bit variable-length integer to memory starting at p[0]. ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. ** The number of bytes written is returned. */ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ @@ -188231,17 +147263,22 @@ assert( q - (unsigned char *)p <= FTS3_VARINT_MAX ); return (int) (q - (unsigned char *)p); } #define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \ - v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \ + v = (v & mask1) | ( (*ptr++) << shift ); \ if( (v & mask2)==0 ){ var = v; return ret; } #define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \ v = (*ptr++); \ if( (v & mask2)==0 ){ var = v; return ret; } -SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){ +/* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read, or 0 on error. +** The value is stored in *v. +*/ +SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ const unsigned char *p = (const unsigned char*)pBuf; const unsigned char *pStart = p; u32 a; u64 b; int shift; @@ -188260,64 +147297,28 @@ *v = b; return (int)(p - pStart); } /* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ - return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v); -} - -/* -** Read a 64-bit variable-length integer from memory starting at p[0] and -** not extending past pEnd[-1]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded( - const char *pBuf, - const char *pEnd, - sqlite_int64 *v -){ - const unsigned char *p = (const unsigned char*)pBuf; - const unsigned char *pStart = p; - const unsigned char *pX = (const unsigned char*)pEnd; - u64 b = 0; - int shift; - for(shift=0; shift<=63; shift+=7){ - u64 c = p=0 ); return 5; } @@ -188354,11 +147355,11 @@ if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ int iIn = 1; /* Index of next byte to read from input */ int iOut = 0; /* Index of next byte to write to output */ /* If the first byte was a '[', then the close-quote character is a ']' */ - if( quote=='[' ) quote = ']'; + if( quote=='[' ) quote = ']'; while( z[iIn] ){ if( z[iIn]==quote ){ if( z[iIn+1]!=quote ) break; z[iOut++] = quote; @@ -188390,18 +147391,18 @@ ** ** Argument pStart points to the first byte of the doclist that the ** varint is part of. */ static void fts3GetReverseVarint( - char **pp, - char *pStart, + char **pp, + char *pStart, sqlite3_int64 *pVal ){ sqlite3_int64 iVal; char *p; - /* Pointer p now points at the first byte past the varint we are + /* Pointer p now points at the first byte past the varint we are ** interested in. So, unless the doclist is corrupt, the 0x80 bit is ** clear on character p[-1]. */ for(p = (*pp)-2; p>=pStart && *p&0x80; p--); p++; *pp = p; @@ -188484,22 +147485,17 @@ int rc = SQLITE_OK; /* Return code */ const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */ sqlite3 *db = p->db; /* Database handle */ /* Drop the shadow tables */ - fts3DbExec(&rc, db, - "DROP TABLE IF EXISTS %Q.'%q_segments';" - "DROP TABLE IF EXISTS %Q.'%q_segdir';" - "DROP TABLE IF EXISTS %Q.'%q_docsize';" - "DROP TABLE IF EXISTS %Q.'%q_stat';" - "%s DROP TABLE IF EXISTS %Q.'%q_content';", - zDb, p->zName, - zDb, p->zName, - zDb, p->zName, - zDb, p->zName, - (p->zContentTbl ? "--" : ""), zDb,p->zName - ); + if( p->zContentTbl==0 ){ + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName); + } + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName); + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName); + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName); + fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName); /* If everything has worked, invoke fts3DisconnectMethod() to free the ** memory associated with the Fts3Table structure and return SQLITE_OK. ** Otherwise, return an SQLite error code. */ @@ -188510,11 +147506,11 @@ /* ** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table ** passed as the first argument. This is done as part of the xConnect() ** and xCreate() methods. ** -** If *pRc is non-zero when this function is called, it is a no-op. +** If *pRc is non-zero when this function is called, it is a no-op. ** Otherwise, if an error occurs, an SQLite error code is stored in *pRc ** before returning. */ static void fts3DeclareVtab(int *pRc, Fts3Table *p){ if( *pRc==SQLITE_OK ){ @@ -188524,21 +147520,20 @@ char *zCols; /* List of user defined columns */ const char *zLanguageid; zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - sqlite3_vtab_config(p->db, SQLITE_VTAB_INNOCUOUS); /* Create a list of user columns for the virtual table */ zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); for(i=1; zCols && inColumn; i++){ zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); } /* Create the whole "CREATE TABLE" statement to pass to SQLite */ zSql = sqlite3_mprintf( - "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", + "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", zCols, p->zName, zLanguageid ); if( !zCols || !zSql ){ rc = SQLITE_NOMEM; }else{ @@ -188553,11 +147548,11 @@ /* ** Create the %_stat table if it does not already exist. */ SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){ - fts3DbExec(pRc, p->db, + fts3DbExec(pRc, p->db, "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'" "(id INTEGER PRIMARY KEY, value BLOB);", p->zDb, p->zName ); if( (*pRc)==SQLITE_OK ) p->bHasStat = 1; @@ -188589,25 +147584,25 @@ } if( zLanguageid && zContentCols ){ zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); } if( zContentCols==0 ) rc = SQLITE_NOMEM; - + /* Create the content table */ - fts3DbExec(&rc, db, + fts3DbExec(&rc, db, "CREATE TABLE %Q.'%q_content'(%s)", p->zDb, p->zName, zContentCols ); sqlite3_free(zContentCols); } /* Create other tables */ - fts3DbExec(&rc, db, + fts3DbExec(&rc, db, "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", p->zDb, p->zName ); - fts3DbExec(&rc, db, + fts3DbExec(&rc, db, "CREATE TABLE %Q.'%q_segdir'(" "level INTEGER," "idx INTEGER," "start_block INTEGER," "leaves_end_block INTEGER," @@ -188616,11 +147611,11 @@ "PRIMARY KEY(level, idx)" ");", p->zDb, p->zName ); if( p->bHasDocsize ){ - fts3DbExec(&rc, db, + fts3DbExec(&rc, db, "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", p->zDb, p->zName ); } assert( p->bHasStat==p->bFts4 ); @@ -188631,20 +147626,20 @@ } /* ** Store the current database page-size in bytes in p->nPgsz. ** -** If *pRc is non-zero when this function is called, it is a no-op. +** If *pRc is non-zero when this function is called, it is a no-op. ** Otherwise, if an error occurs, an SQLite error code is stored in *pRc ** before returning. */ static void fts3DatabasePageSize(int *pRc, Fts3Table *p){ if( *pRc==SQLITE_OK ){ int rc; /* Return code */ char *zSql; /* SQL text "PRAGMA %Q.page_size" */ sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */ - + zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb); if( !zSql ){ rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); @@ -188666,15 +147661,15 @@ /* ** "Special" FTS4 arguments are column specifications of the following form: ** ** = ** -** There may not be whitespace surrounding the "=" character. The +** There may not be whitespace surrounding the "=" character. The ** term may be quoted, but the may not. */ static int fts3IsSpecialColumn( - const char *z, + const char *z, int *pnKey, char **pzValue ){ char *zValue; const char *zCsr = z; @@ -188728,14 +147723,14 @@ ** The pointer returned points to memory obtained from sqlite3_malloc(). It ** is the callers responsibility to call sqlite3_free() to release this ** memory. */ static char *fts3QuoteId(char const *zInput){ - sqlite3_int64 nRet; + int nRet; char *zRet; nRet = 2 + (int)strlen(zInput)*2 + 1; - zRet = sqlite3_malloc64(nRet); + zRet = sqlite3_malloc(nRet); if( zRet ){ int i; char *z = zRet; *(z++) = '"'; for(i=0; zInput[i]; i++){ @@ -188747,11 +147742,11 @@ } return zRet; } /* -** Return a list of comma separated SQL expressions and a FROM clause that +** Return a list of comma separated SQL expressions and a FROM clause that ** could be used in a SELECT statement such as the following: ** ** SELECT FROM %_content AS x ... ** ** to return the docid, followed by each column of text data in order @@ -188798,11 +147793,11 @@ } if( p->zLanguageid ){ fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); } } - fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", + fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", p->zDb, (p->zContentTbl ? p->zContentTbl : p->zName), (p->zContentTbl ? "" : "_content") ); return zRet; @@ -188813,11 +147808,11 @@ ** of columns in the %_content table (one for the docid plus one for each ** user-defined text column). ** ** If argument zFunc is not NULL, then all but the first question mark ** is preceded by zFunc and an open bracket, and followed by a closed -** bracket. For example, if zFunc is "zip" and the FTS3 table has three +** bracket. For example, if zFunc is "zip" and the FTS3 table has three ** user-defined text columns, the following string is returned: ** ** "?, zip(?), zip(?), zip(?)" ** ** The pointer returned points to a buffer allocated by sqlite3_malloc(). It @@ -188848,52 +147843,38 @@ } sqlite3_free(zFree); return zRet; } -/* -** Buffer z contains a positive integer value encoded as utf-8 text. -** Decode this value and store it in *pnOut, returning the number of bytes -** consumed. If an overflow error occurs return a negative value. -*/ -SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut){ - u64 iVal = 0; - int i; - for(i=0; z[i]>='0' && z[i]<='9'; i++){ - iVal = iVal*10 + (z[i] - '0'); - if( iVal>0x7FFFFFFF ) return -1; - } - *pnOut = (int)iVal; - return i; -} - /* ** This function interprets the string at (*pp) as a non-negative integer -** value. It reads the integer and sets *pnOut to the value read, then +** value. It reads the integer and sets *pnOut to the value read, then ** sets *pp to point to the byte immediately following the last byte of ** the integer value. ** -** Only decimal digits ('0'..'9') may be part of an integer value. +** Only decimal digits ('0'..'9') may be part of an integer value. ** ** If *pp does not being with a decimal digit SQLITE_ERROR is returned and ** the output value undefined. Otherwise SQLITE_OK is returned. ** ** This function is used when parsing the "prefix=" FTS4 parameter. */ static int fts3GobbleInt(const char **pp, int *pnOut){ const int MAX_NPREFIX = 10000000; + const char *p; /* Iterator pointer */ int nInt = 0; /* Output value */ - int nByte; - nByte = sqlite3Fts3ReadInt(*pp, &nInt); - if( nInt>MAX_NPREFIX ){ - nInt = 0; - } - if( nByte==0 ){ - return SQLITE_ERROR; - } + + for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ + nInt = nInt * 10 + (p[0] - '0'); + if( nInt>MAX_NPREFIX ){ + nInt = 0; + break; + } + } + if( p==*pp ) return SQLITE_ERROR; *pnOut = nInt; - *pp += nByte; + *pp = p; return SQLITE_OK; } /* ** This function is called to allocate an array of Fts3Index structures @@ -188926,11 +147907,11 @@ for(p=zParam; *p; p++){ if( *p==',' ) nIndex++; } } - aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex); + aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); *apIndex = aIndex; if( !aIndex ){ return SQLITE_NOMEM; } @@ -188989,11 +147970,11 @@ int *pnCol, /* OUT: Size of array *pazCol */ int *pnStr, /* OUT: Bytes of string content */ char **pzErr /* OUT: error message */ ){ int rc = SQLITE_OK; /* Return code */ - char *zSql; /* "SELECT *" statement on zTbl */ + char *zSql; /* "SELECT *" statement on zTbl */ sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); if( !zSql ){ rc = SQLITE_NOMEM; @@ -189005,25 +147986,25 @@ } sqlite3_free(zSql); if( rc==SQLITE_OK ){ const char **azCol; /* Output array */ - sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */ + int nStr = 0; /* Size of all column names (incl. 0x00) */ int nCol; /* Number of table columns */ int i; /* Used to iterate through columns */ /* Loop through the returned columns. Set nStr to the number of bytes of ** space required to store a copy of each column name, including the ** nul-terminator byte. */ nCol = sqlite3_column_count(pStmt); for(i=0; ihash; + Fts3Hash *pHash = (Fts3Hash *)pAux; Fts3Table *p = 0; /* Pointer to allocated vtab */ int rc = SQLITE_OK; /* Return code */ int i; /* Iterator variable */ - sqlite3_int64 nByte; /* Size of allocation used for *p */ + int nByte; /* Size of allocation used for *p */ int iCol; /* Column index */ int nString = 0; /* Bytes required to hold all column names */ int nCol = 0; /* Number of columns in the FTS table */ char *zCsr; /* Space for holding column names */ int nDb; /* Bytes required to hold database name */ @@ -189101,14 +148082,14 @@ nDb = (int)strlen(argv[1]) + 1; nName = (int)strlen(argv[2]) + 1; nByte = sizeof(const char *) * (argc-2); - aCol = (const char **)sqlite3_malloc64(nByte); + aCol = (const char **)sqlite3_malloc(nByte); if( aCol ){ memset((void*)aCol, 0, nByte); - azNotindexed = (char **)sqlite3_malloc64(nByte); + azNotindexed = (char **)sqlite3_malloc(nByte); } if( azNotindexed ){ memset(azNotindexed, 0, nByte); } if( !aCol || !azNotindexed ){ @@ -189131,13 +148112,13 @@ char const *z = argv[i]; int nKey; char *zVal; /* Check if this is a tokenizer specification */ - if( !pTokenizer + if( !pTokenizer && strlen(z)>8 - && 0==sqlite3_strnicmp(z, "tokenize", 8) + && 0==sqlite3_strnicmp(z, "tokenize", 8) && 0==sqlite3Fts3IsIdChar(z[8]) ){ rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr); } @@ -189193,12 +148174,12 @@ zUncompress = zVal; zVal = 0; break; case 4: /* ORDER */ - if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) - && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) + if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) + && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) ){ sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); rc = SQLITE_ERROR; } bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); @@ -189245,21 +148226,21 @@ ** ** 2. If no column names were specified as part of the CREATE VIRTUAL ** TABLE statement, use all columns from the content table. */ if( rc==SQLITE_OK && zContent ){ - sqlite3_free(zCompress); - sqlite3_free(zUncompress); + sqlite3_free(zCompress); + sqlite3_free(zUncompress); zCompress = 0; zUncompress = 0; if( nCol==0 ){ - sqlite3_free((void*)aCol); + sqlite3_free((void*)aCol); aCol = 0; rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); /* If a languageid= option was specified, remove the language id - ** column from the aCol[] array. */ + ** column from the aCol[] array. */ if( rc==SQLITE_OK && zLanguageid ){ int j; for(j=0; j0 ){ memcpy(zCsr, z, n); } @@ -189361,11 +148342,11 @@ for(iCol=0; iColazColumn[iCol]); for(i=0; iazColumn[iCol], zNot, n) + && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){ p->abNotindexed[iCol] = 1; sqlite3_free(zNot); azNotindexed[i] = 0; } @@ -189385,11 +148366,11 @@ } p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); if( rc!=SQLITE_OK ) goto fts3_init_out; - /* If this is an xCreate call, create the underlying tables in the + /* If this is an xCreate call, create the underlying tables in the ** database. TODO: For xConnect(), it could verify that said tables exist. */ if( isCreate ){ rc = fts3CreateTables(p); } @@ -189404,14 +148385,10 @@ /* Figure out the page-size for the database. This is required in order to ** estimate the cost of loading large doclists from the database. */ fts3DatabasePageSize(&rc, p); p->nNodeSize = p->nPgsz-35; -#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST) - p->nMergeCount = FTS3_MERGE_COUNT; -#endif - /* Declare the table schema to SQLite. */ fts3DeclareVtab(&rc, p); fts3_init_out: sqlite3_free(zPrefix); @@ -189485,15 +148462,15 @@ pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; } #endif } -/* +/* ** Implementation of the xBestIndex method for FTS3 tables. There ** are three possible strategies, in order of preference: ** -** 1. Direct lookup by rowid or docid. +** 1. Direct lookup by rowid or docid. ** 2. Full-text search using a MATCH operator on a non-docid column. ** 3. Linear scan of %_content table. */ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts3Table *p = (Fts3Table *)pVTab; @@ -189503,16 +148480,12 @@ int iLangidCons = -1; /* Index of langid=x constraint, if present */ int iDocidGe = -1; /* Index of docid>=x constraint, if present */ int iDocidLe = -1; /* Index of docid<=x constraint, if present */ int iIdx; - if( p->bLock ){ - return SQLITE_ERROR; - } - /* By default use a full table scan. This is an expensive option, - ** so search through the constraints to see if a more efficient + ** so search through the constraints to see if a more efficient ** strategy is possible. */ pInfo->idxNum = FTS3_FULLSCAN_SEARCH; pInfo->estimatedCost = 5000000; for(i=0; inConstraint; i++){ @@ -189544,25 +148517,25 @@ /* A MATCH constraint. Use a full-text search. ** ** If there is more than one MATCH constraint available, use the first ** one encountered. If there is both a MATCH constraint and a direct - ** rowid/docid lookup, prefer the MATCH strategy. This is done even + ** rowid/docid lookup, prefer the MATCH strategy. This is done even ** though the rowid/docid lookup is faster than a MATCH query, selecting - ** it would lead to an "unable to use function MATCH in the requested + ** it would lead to an "unable to use function MATCH in the requested ** context" error. */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH + if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn ){ pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; pInfo->estimatedCost = 2.0; iCons = i; } /* Equality constraint on the langid column */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ + if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && pCons->iColumn==p->nColumn + 2 ){ iLangidCons = i; } @@ -189586,26 +148559,26 @@ iIdx = 1; if( iCons>=0 ){ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; pInfo->aConstraintUsage[iCons].omit = 1; - } + } if( iLangidCons>=0 ){ pInfo->idxNum |= FTS3_HAVE_LANGID; pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; - } + } if( iDocidGe>=0 ){ pInfo->idxNum |= FTS3_HAVE_DOCID_GE; pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++; - } + } if( iDocidLe>=0 ){ pInfo->idxNum |= FTS3_HAVE_DOCID_LE; pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++; - } + } /* Regardless of the strategy selected, FTS can deliver rows in rowid (or - ** docid) order. Both ascending and descending are possible. + ** docid) order. Both ascending and descending are possible. */ if( pInfo->nOrderBy==1 ){ struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0]; if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){ if( pOrder->desc ){ @@ -189628,11 +148601,11 @@ sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ UNUSED_PARAMETER(pVTab); /* Allocate a buffer large enough for an Fts3Cursor structure. If the - ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, + ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, ** if the allocation fails, return SQLITE_NOMEM. */ *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor)); if( !pCsr ){ return SQLITE_NOMEM; @@ -189705,15 +148678,11 @@ pCsr->pStmt = p->pSeekStmt; p->pSeekStmt = 0; }else{ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); if( !zSql ) return SQLITE_NOMEM; - p->bLock++; - rc = sqlite3_prepare_v3( - p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 - ); - p->bLock--; + rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0); sqlite3_free(zSql); } if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; } return rc; @@ -189720,26 +148689,22 @@ } /* ** Position the pCsr->pStmt statement so that it is on the row ** of the %_content table that contains the last match. Return -** SQLITE_OK on success. +** SQLITE_OK on success. */ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ int rc = SQLITE_OK; if( pCsr->isRequireSeek ){ rc = fts3CursorSeekStmt(pCsr); if( rc==SQLITE_OK ){ - Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab; - pTab->bLock++; sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); pCsr->isRequireSeek = 0; if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ - pTab->bLock--; return SQLITE_OK; }else{ - pTab->bLock--; rc = sqlite3_reset(pCsr->pStmt); if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ /* If no row was found and no error has occurred, then the %_content ** table is missing a row that is present in the full-text index. ** The data structures are corrupt. */ @@ -189756,11 +148721,11 @@ return rc; } /* ** This function is used to process a single interior node when searching -** a b-tree for a term or term prefix. The node data is passed to this +** a b-tree for a term or term prefix. The node data is passed to this ** function via the zNode/nNode parameters. The term to search for is ** passed in zTerm/nTerm. ** ** If piFirst is not NULL, then this function sets *piFirst to the blockid ** of the child node that heads the sub-tree that may contain the term. @@ -189781,18 +148746,17 @@ ){ int rc = SQLITE_OK; /* Return code */ const char *zCsr = zNode; /* Cursor to iterate through node */ const char *zEnd = &zCsr[nNode];/* End of interior node buffer */ char *zBuffer = 0; /* Buffer to load terms into */ - i64 nAlloc = 0; /* Size of allocated buffer */ + int nAlloc = 0; /* Size of allocated buffer */ int isFirstTerm = 1; /* True when processing first term on page */ - u64 iChild; /* Block id of child node to descend to */ - int nBuffer = 0; /* Total term size */ + sqlite3_int64 iChild; /* Block id of child node to descend to */ - /* Skip over the 'height' varint that occurs at the start of every + /* Skip over the 'height' varint that occurs at the start of every ** interior node. Then load the blockid of the left-child of the b-tree - ** node into variable iChild. + ** node into variable iChild. ** ** Even if the data structure on disk is corrupted, this (reading two ** varints from the buffer) does not risk an overread. If zNode is a ** root node, then the buffer comes from a SELECT statement. SQLite does ** not make this guarantee explicitly, but in practice there are always @@ -189799,42 +148763,39 @@ ** either more than 20 bytes of allocated space following the nNode bytes of ** contents, or two zero bytes. Or, if the node is read from the %_segments ** table, then there are always 20 bytes of zeroed padding following the ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details). */ - zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild); - zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild); + zCsr += sqlite3Fts3GetVarint(zCsr, &iChild); + zCsr += sqlite3Fts3GetVarint(zCsr, &iChild); if( zCsr>zEnd ){ return FTS_CORRUPT_VTAB; } - + while( zCsrnBuffer ){ - rc = FTS_CORRUPT_VTAB; - goto finish_scan; - } } isFirstTerm = 0; zCsr += fts3GetVarint32(zCsr, &nSuffix); - + assert( nPrefix>=0 && nSuffix>=0 ); - if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){ + if( &zCsr[nSuffix]>zEnd ){ rc = FTS_CORRUPT_VTAB; goto finish_scan; } - if( (i64)nPrefix+nSuffix>nAlloc ){ + if( nPrefix+nSuffix>nAlloc ){ char *zNew; - nAlloc = ((i64)nPrefix+nSuffix) * 2; - zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc); + nAlloc = (nPrefix+nSuffix) * 2; + zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); if( !zNew ){ rc = SQLITE_NOMEM; goto finish_scan; } zBuffer = zNew; @@ -189844,33 +148805,33 @@ nBuffer = nPrefix + nSuffix; zCsr += nSuffix; /* Compare the term we are searching for with the term just loaded from ** the interior node. If the specified term is greater than or equal - ** to the term from the interior node, then all terms on the sub-tree - ** headed by node iChild are smaller than zTerm. No need to search + ** to the term from the interior node, then all terms on the sub-tree + ** headed by node iChild are smaller than zTerm. No need to search ** iChild. ** ** If the interior node term is larger than the specified term, then ** the tree headed by iChild may contain the specified term. */ cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer)); if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){ - *piFirst = (i64)iChild; + *piFirst = iChild; piFirst = 0; } if( piLast && cmp<0 ){ - *piLast = (i64)iChild; + *piLast = iChild; piLast = 0; } iChild++; }; - if( piFirst ) *piFirst = (i64)iChild; - if( piLast ) *piLast = (i64)iChild; + if( piFirst ) *piFirst = iChild; + if( piLast ) *piLast = iChild; finish_scan: sqlite3_free(zBuffer); return rc; } @@ -189881,24 +148842,24 @@ ** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes) ** contains a term. This function searches the sub-tree headed by the zNode ** node for the range of leaf nodes that may contain the specified term ** or terms for which the specified term is a prefix. ** -** If piLeaf is not NULL, then *piLeaf is set to the blockid of the +** If piLeaf is not NULL, then *piLeaf is set to the blockid of the ** left-most leaf node in the tree that may contain the specified term. ** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the ** right-most leaf node that may contain a term for which the specified ** term is a prefix. ** -** It is possible that the range of returned leaf nodes does not contain -** the specified term or any terms for which it is a prefix. However, if the +** It is possible that the range of returned leaf nodes does not contain +** the specified term or any terms for which it is a prefix. However, if the ** segment does contain any such terms, they are stored within the identified ** range. Because this function only inspects interior segment nodes (and ** never loads leaf nodes into memory), it is not possible to be sure. ** ** If an error occurs, an error code other than SQLITE_OK is returned. -*/ +*/ static int fts3SelectLeaf( Fts3Table *p, /* Virtual table handle */ const char *zTerm, /* Term to select leaves for */ int nTerm, /* Size of term zTerm in bytes */ const char *zNode, /* Buffer containing segment interior node */ @@ -189911,11 +148872,11 @@ assert( piLeaf || piLeaf2 ); fts3GetVarint32(zNode, &iHeight); rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); - assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); + assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); if( rc==SQLITE_OK && iHeight>1 ){ char *zBlob = 0; /* Blob read from %_segments table */ int nBlob = 0; /* Size of zBlob in bytes */ @@ -189931,44 +148892,38 @@ if( rc==SQLITE_OK ){ rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0); } if( rc==SQLITE_OK ){ - int iNewHeight = 0; - fts3GetVarint32(zBlob, &iNewHeight); - if( iNewHeight>=iHeight ){ - rc = FTS_CORRUPT_VTAB; - }else{ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2); - } + rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2); } sqlite3_free(zBlob); } return rc; } /* -** This function is used to create delta-encoded serialized lists of FTS3 +** This function is used to create delta-encoded serialized lists of FTS3 ** varints. Each call to this function appends a single varint to a list. */ static void fts3PutDeltaVarint( char **pp, /* IN/OUT: Output pointer */ sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ sqlite3_int64 iVal /* Write this value to the list */ ){ - assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); + assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); *piPrev = iVal; } /* -** When this function is called, *ppPoslist is assumed to point to the +** When this function is called, *ppPoslist is assumed to point to the ** start of a position-list. After it returns, *ppPoslist points to the ** first byte after the position-list. ** -** A position list is list of positions (delta encoded) and columns for +** A position list is list of positions (delta encoded) and columns for ** a single document record of a doclist. So, in other words, this ** routine advances *ppPoslist so that it points to the next docid in ** the doclist, or to the first byte past the end of the doclist. ** ** If pp is not NULL, then the contents of the position list are copied @@ -189977,16 +148932,16 @@ */ static void fts3PoslistCopy(char **pp, char **ppPoslist){ char *pEnd = *ppPoslist; char c = 0; - /* The end of a position list is marked by a zero encoded as an FTS3 + /* The end of a position list is marked by a zero encoded as an FTS3 ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by ** a byte with the 0x80 bit set, then it is not a varint 0, but the tail ** of some other, multi-byte, value. ** - ** The following while-loop moves pEnd to point to the first byte that is not + ** The following while-loop moves pEnd to point to the first byte that is not ** immediately preceded by a byte with the 0x80 bit set. Then increments ** pEnd once more so that it points to the byte immediately following the ** last byte in the position-list. */ while( *pEnd | c ){ @@ -190004,11 +148959,11 @@ } *ppPoslist = pEnd; } /* -** When this function is called, *ppPoslist is assumed to point to the +** When this function is called, *ppPoslist is assumed to point to the ** start of a column-list. After it returns, *ppPoslist points to the ** to the terminator (POS_COLUMN or POS_END) byte of the column-list. ** ** A column-list is list of delta-encoded positions for a single column ** within a single document within a doclist. @@ -190042,24 +148997,23 @@ } *ppPoslist = pEnd; } /* -** Value used to signify the end of an position-list. This must be -** as large or larger than any value that might appear on the -** position-list, even a position list that has been corrupted. +** Value used to signify the end of an position-list. This is safe because +** it is not possible to have a document with 2^31 terms. */ -#define POSITION_LIST_END LARGEST_INT64 +#define POSITION_LIST_END 0x7fffffff /* ** This function is used to help parse position-lists. When this function is ** called, *pp may point to the start of the next varint in the position-list ** being parsed, or it may point to 1 byte past the end of the position-list ** (in which case **pp will be a terminator bytes POS_END (0) or ** (1)). ** -** If *pp points past the end of the current position-list, set *pi to +** If *pp points past the end of the current position-list, set *pi to ** POSITION_LIST_END and return. Otherwise, read the next varint from *pp, ** increment the current value of *pi by the value read, and set *pp to ** point to the next value before returning. ** ** Before calling this routine *pi must be initialized to the value of @@ -190071,13 +149025,11 @@ static void fts3ReadNextPos( char **pp, /* IN/OUT: Pointer into position-list buffer */ sqlite3_int64 *pi /* IN/OUT: Value read from position-list */ ){ if( (**pp)&0xFE ){ - int iVal; - *pp += fts3GetVarint32((*pp), &iVal); - *pi += iVal; + fts3GetDeltaVarint(pp, pi); *pi -= 2; }else{ *pi = POSITION_LIST_END; } } @@ -190085,11 +149037,11 @@ /* ** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by ** the value of iCol encoded as a varint to *pp. This will start a new ** column list. ** -** Set *pp to point to the byte just after the last byte written before +** Set *pp to point to the byte just after the last byte written before ** returning (do not modify it if iCol==0). Return the total number of bytes ** written (0 if iCol==0). */ static int fts3PutColNumber(char **pp, int iCol){ int n = 0; /* Number of bytes written */ @@ -190107,11 +149059,11 @@ ** into *pp contains all positions of both *pp1 and *pp2 in sorted ** order and with any duplicates removed. All pointers are ** updated appropriately. The caller is responsible for insuring ** that there is enough space in *pp to hold the complete output. */ -static int fts3PoslistMerge( +static void fts3PoslistMerge( char **pp, /* Output buffer */ char **pp1, /* Left input list */ char **pp2 /* Right input list */ ){ char *p = *pp; @@ -190120,22 +149072,16 @@ while( *p1 || *p2 ){ int iCol1; /* The current column index in pp1 */ int iCol2; /* The current column index in pp2 */ - if( *p1==POS_COLUMN ){ - fts3GetVarint32(&p1[1], &iCol1); - if( iCol1==0 ) return FTS_CORRUPT_VTAB; - } - else if( *p1==POS_END ) iCol1 = 0x7fffffff; + if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1); + else if( *p1==POS_END ) iCol1 = POSITION_LIST_END; else iCol1 = 0; - if( *p2==POS_COLUMN ){ - fts3GetVarint32(&p2[1], &iCol2); - if( iCol2==0 ) return FTS_CORRUPT_VTAB; - } - else if( *p2==POS_END ) iCol2 = 0x7fffffff; + if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2); + else if( *p2==POS_END ) iCol2 = POSITION_LIST_END; else iCol2 = 0; if( iCol1==iCol2 ){ sqlite3_int64 i1 = 0; /* Last position from pp1 */ sqlite3_int64 i2 = 0; /* Last position from pp2 */ @@ -190144,24 +149090,21 @@ p1 += n; p2 += n; /* At this point, both p1 and p2 point to the start of column-lists ** for the same column (the column with index iCol1 and iCol2). - ** A column-list is a list of non-negative delta-encoded varints, each + ** A column-list is a list of non-negative delta-encoded varints, each ** incremented by 2 before being stored. Each list is terminated by a ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists ** and writes the results to buffer p. p is left pointing to the byte ** after the list written. No terminator (POS_END or POS_COLUMN) is ** written to the output. */ fts3GetDeltaVarint(&p1, &i1); fts3GetDeltaVarint(&p2, &i2); - if( i1<2 || i2<2 ){ - break; - } do { - fts3PutDeltaVarint(&p, &iPrev, (i1pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e. ** when the *pp1 token appears before the *pp2 token, but not more than nToken ** slots before it. ** @@ -190224,23 +149166,18 @@ int iCol2 = 0; /* Never set both isSaveLeft and isExact for the same invocation. */ assert( isSaveLeft==0 || isExact==0 ); - assert_fts3_nc( p!=0 && *p1!=0 && *p2!=0 ); - if( *p1==POS_COLUMN ){ + assert( p!=0 && *p1!=0 && *p2!=0 ); + if( *p1==POS_COLUMN ){ p1++; p1 += fts3GetVarint32(p1, &iCol1); - /* iCol1==0 indicates corruption. Column 0 does not have a POS_COLUMN - ** entry, so this is actually end-of-doclist. */ - if( iCol1==0 ) return 0; } - if( *p2==POS_COLUMN ){ + if( *p2==POS_COLUMN ){ p2++; p2 += fts3GetVarint32(p2, &iCol2); - /* As above, iCol2==0 indicates corruption. */ - if( iCol2==0 ) return 0; } while( 1 ){ if( iCol1==iCol2 ){ char *pSave = p; @@ -190251,17 +149188,18 @@ if( iCol1 ){ *p++ = POS_COLUMN; p += sqlite3Fts3PutVarint(p, iCol1); } + assert( *p1!=POS_END && *p1!=POS_COLUMN ); + assert( *p2!=POS_END && *p2!=POS_COLUMN ); fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - if( iPos1<0 || iPos2<0 ) break; while( 1 ){ - if( iPos2==iPos1+nToken - || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken) + if( iPos2==iPos1+nToken + || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken) ){ sqlite3_int64 iSave; iSave = isSaveLeft ? iPos1 : iPos2; fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; pSave = 0; @@ -190292,12 +149230,12 @@ p2 += fts3GetVarint32(p2, &iCol2); } /* Advance pointer p1 or p2 (whichever corresponds to the smaller of ** iCol1 and iCol2) so that it points to either the 0x00 that marks the - ** end of the position list, or the 0x01 that precedes the next - ** column-number in the position list. + ** end of the position list, or the 0x01 that precedes the next + ** column-number in the position list. */ else if( iCol1=pEnd ){ *pp = 0; }else{ - u64 iVal; - *pp += sqlite3Fts3GetVarintU(*pp, &iVal); + sqlite3_int64 iVal; + *pp += sqlite3Fts3GetVarint(*pp, &iVal); if( bDescIdx ){ - *pVal = (i64)((u64)*pVal - iVal); + *pVal -= iVal; }else{ - *pVal = (i64)((u64)*pVal + iVal); + *pVal += iVal; } } } /* @@ -190418,13 +149356,13 @@ ** This function is used to write a single varint to a buffer. The varint ** is written to *pp. Before returning, *pp is set to point 1 byte past the ** end of the value written. ** ** If *pbFirst is zero when this function is called, the value written to -** the buffer is that of parameter iVal. +** the buffer is that of parameter iVal. ** -** If *pbFirst is non-zero when this function is called, then the value +** If *pbFirst is non-zero when this function is called, then the value ** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal) ** (if bDescIdx is non-zero). ** ** Before returning, this function always sets *pbFirst to 1 and *piPrev ** to the value of parameter iVal. @@ -190434,41 +149372,38 @@ int bDescIdx, /* True for descending docids */ sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ int *pbFirst, /* IN/OUT: True after first int written */ sqlite3_int64 iVal /* Write this value to the list */ ){ - sqlite3_uint64 iWrite; + sqlite3_int64 iWrite; if( bDescIdx==0 || *pbFirst==0 ){ - assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev ); - iWrite = (u64)iVal - (u64)*piPrev; + iWrite = iVal - *piPrev; }else{ - assert_fts3_nc( *piPrev>=iVal ); - iWrite = (u64)*piPrev - (u64)iVal; + iWrite = *piPrev - iVal; } assert( *pbFirst || *piPrev==0 ); - assert_fts3_nc( *pbFirst==0 || iWrite>0 ); + assert( *pbFirst==0 || iWrite>0 ); *pp += sqlite3Fts3PutVarint(*pp, iWrite); *piPrev = iVal; *pbFirst = 1; } /* ** This macro is used by various functions that merge doclists. The two ** arguments are 64-bit docid values. If the value of the stack variable -** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). +** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). ** Otherwise, (i2-i1). ** ** Using this makes it easier to write code that can merge doclists that are ** sorted in either ascending or descending order. */ -/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */ -#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1))) +#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2)) /* ** This function does an "OR" merge of two doclists (output contains all -** positions contained in either argument doclist). If the docids in the +** positions contained in either argument doclist). If the docids in the ** input doclists are sorted in ascending order, parameter bDescDoclist ** should be false. If they are sorted in ascending order, it should be ** passed a non-zero value. ** ** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer @@ -190482,11 +149417,10 @@ int bDescDoclist, /* True if arguments are desc */ char *a1, int n1, /* First doclist */ char *a2, int n2, /* Second doclist */ char **paOut, int *pnOut /* OUT: Malloc'd doclist */ ){ - int rc = SQLITE_OK; sqlite3_int64 i1 = 0; sqlite3_int64 i2 = 0; sqlite3_int64 iPrev = 0; char *pEnd1 = &a1[n1]; char *pEnd2 = &a2[n2]; @@ -190504,16 +149438,16 @@ ** then the first docid in each list is simply encoded as a varint. For ** each subsequent docid, the varint stored is the difference between the ** current and previous docid (a positive number - since the list is in ** ascending order). ** - ** The first docid written to the output is therefore encoded using the + ** The first docid written to the output is therefore encoded using the ** same number of bytes as it is in whichever of the input lists it is - ** read from. And each subsequent docid read from the same input list + ** read from. And each subsequent docid read from the same input list ** consumes either the same or less bytes as it did in the input (since ** the difference between it and the previous value in the output must - ** be a positive value less than or equal to the delta value read from + ** be a positive value less than or equal to the delta value read from ** the input list). The same argument applies to all but the first docid ** read from the 'other' list. And to the contents of all position lists ** that will be copied and merged from the input to the output. ** ** However, if the first docid copied to the output is a negative number, @@ -190521,16 +149455,16 @@ ** be larger in the output than it was in the input (since the delta value ** may be a larger positive integer than the actual docid). ** ** The space required to store the output is therefore the sum of the ** sizes of the two inputs, plus enough space for exactly one of the input - ** docids to grow. + ** docids to grow. ** - ** A symetric argument may be made if the doclists are in descending + ** A symetric argument may be made if the doclists are in descending ** order. */ - aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING); + aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1); if( !aOut ) return SQLITE_NOMEM; p = aOut; fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); @@ -190537,12 +149471,11 @@ while( p1 || p2 ){ sqlite3_int64 iDiff = DOCID_CMP(i1, i2); if( p2 && p1 && iDiff==0 ){ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - rc = fts3PoslistMerge(&p, &p1, &p2); - if( rc ) break; + fts3PoslistMerge(&p, &p1, &p2); fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); }else if( !p2 || (p1 && iDiff<0) ){ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); fts3PoslistCopy(&p, &p1); @@ -190550,34 +149483,26 @@ }else{ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2); fts3PoslistCopy(&p, &p2); fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); } - - assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) ); } - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - p = aOut = 0; - }else{ - assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 ); - memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING); - } *paOut = aOut; *pnOut = (int)(p-aOut); - return rc; + assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 ); + return SQLITE_OK; } /* ** This function does a "phrase" merge of two doclists. In a phrase merge, ** the output contains a copy of each position from the right-hand input ** doclist for which there is a position in the left-hand input doclist ** exactly nDist tokens before it. ** ** If the docids in the input doclists are sorted in ascending order, -** parameter bDescDoclist should be false. If they are sorted in ascending +** parameter bDescDoclist should be false. If they are sorted in ascending ** order, it should be passed a non-zero value. ** ** The right-hand input doclist is overwritten by this function. */ static int fts3DoclistPhraseMerge( @@ -190598,11 +149523,11 @@ int bFirstOut = 0; char *aOut; assert( nDist>0 ); if( bDescDoclist ){ - aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX); + aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX); if( aOut==0 ) return SQLITE_NOMEM; }else{ aOut = aRight; } p = aOut; @@ -190719,11 +149644,11 @@ pTS->aaOutput[i] = 0; }else{ int nNew; char *aNew; - int rc = fts3DoclistOrMerge(p->bDescIdx, + int rc = fts3DoclistOrMerge(p->bDescIdx, pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew ); if( rc!=SQLITE_OK ){ sqlite3_free(aOut); return rc; @@ -190763,30 +149688,29 @@ char *aDoclist, /* Pointer to doclist */ int nDoclist /* Size of aDoclist in bytes */ ){ if( pTS->aaOutput[0]==0 ){ /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). + ** buffer using memcpy(). ** - ** Add FTS3_VARINT_MAX bytes of unused space to the end of the + ** Add FTS3_VARINT_MAX bytes of unused space to the end of the ** allocation. This is so as to ensure that the buffer is big enough ** to hold the current doclist AND'd with any other doclist. If the ** doclists are stored in order=ASC order, this padding would not be ** required (since the size of [doclistA AND doclistB] is always less ** than or equal to the size of [doclistA] in that case). But this is - ** not true for order=DESC. For example, a doclist containing (1, -1) + ** not true for order=DESC. For example, a doclist containing (1, -1) ** may be smaller than (-1), as in the first example the -1 may be stored ** as a single-byte delta, whereas in the second it must be stored as a ** FTS3_VARINT_MAX byte varint. ** ** Similar padding is added in the fts3DoclistOrMerge() function. */ - pTS->aaOutput[0] = sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1); + pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); pTS->anOutput[0] = nDoclist; if( pTS->aaOutput[0] ){ memcpy(pTS->aaOutput[0], aDoclist, nDoclist); - memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX); }else{ return SQLITE_NOMEM; } }else{ char *aMerge = aDoclist; @@ -190801,11 +149725,11 @@ break; }else{ char *aNew; int nNew; - int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge, + int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge, pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew ); if( rc!=SQLITE_OK ){ if( aMerge!=aDoclist ) sqlite3_free(aMerge); return rc; @@ -190812,11 +149736,11 @@ } if( aMerge!=aDoclist ) sqlite3_free(aMerge); sqlite3_free(pTS->aaOutput[iOut]); pTS->aaOutput[iOut] = 0; - + aMerge = aNew; nMerge = nNew; if( (iOut+1)==SizeofArray(pTS->aaOutput) ){ pTS->aaOutput[iOut] = aMerge; pTS->anOutput[iOut] = nMerge; @@ -190829,17 +149753,17 @@ /* ** Append SegReader object pNew to the end of the pCsr->apSegment[] array. */ static int fts3SegReaderCursorAppend( - Fts3MultiSegReader *pCsr, + Fts3MultiSegReader *pCsr, Fts3SegReader *pNew ){ if( (pCsr->nSegment%16)==0 ){ Fts3SegReader **apNew; - sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*); - apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte); + int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*); + apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte); if( !apNew ){ sqlite3Fts3SegReaderFree(pNew); return SQLITE_NOMEM; } pCsr->apSegment = apNew; @@ -190868,17 +149792,17 @@ ){ int rc = SQLITE_OK; /* Error code */ sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */ int rc2; /* Result of sqlite3_reset() */ - /* If iLevel is less than 0 and this is not a scan, include a seg-reader + /* If iLevel is less than 0 and this is not a scan, include a seg-reader ** for the pending-terms. If this is a scan, then this call must be being ** made by an fts4aux module, not an FTS table. In this case calling - ** Fts3SegReaderPending might segfault, as the data structures used by + ** Fts3SegReaderPending might segfault, as the data structures used by ** fts4aux are not completely populated. So it's easiest to filter these ** calls out here. */ - if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){ + if( iLevel<0 && p->aIndex ){ Fts3SegReader *pSeg = 0; rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg); if( rc==SQLITE_OK && pSeg ){ rc = fts3SegReaderCursorAppend(pCsr, pSeg); } @@ -190899,20 +149823,20 @@ int nRoot = sqlite3_column_bytes(pStmt, 4); char const *zRoot = sqlite3_column_blob(pStmt, 4); /* If zTerm is not NULL, and this segment is not stored entirely on its ** root node, the range of leaves scanned can be reduced. Do this. */ - if( iStartBlock && zTerm && zRoot ){ + if( iStartBlock && zTerm ){ sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0); rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi); if( rc!=SQLITE_OK ) goto finished; if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock; } - - rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, + + rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, (isPrefix==0 && isScan==0), - iStartBlock, iLeavesEndBlock, + iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg ); if( rc!=SQLITE_OK ) goto finished; rc = fts3SegReaderCursorAppend(pCsr, pSeg); } @@ -190924,11 +149848,11 @@ return rc; } /* -** Set up a cursor object for iterating through a full-text index or a +** Set up a cursor object for iterating through a full-text index or a ** single level therein. */ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( Fts3Table *p, /* FTS3 table handle */ int iLangid, /* Language-id to search */ @@ -190940,11 +149864,11 @@ int isScan, /* True to scan from zTerm to EOF */ Fts3MultiSegReader *pCsr /* Cursor object to populate */ ){ assert( iIndex>=0 && iIndexnIndex ); assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING + || iLevel==FTS3_SEGCURSOR_PENDING || iLevel>=0 ); assert( iLevelnIndex; i++){ if( p->aIndex[i].nPrefix==nTerm ){ bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr ); pSegcsr->bLookup = 1; } } for(i=1; bFound==0 && inIndex; i++){ if( p->aIndex[i].nPrefix==nTerm+1 ){ bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr ); if( rc==SQLITE_OK ){ rc = fts3SegReaderCursorAddZero( p, pCsr->iLangid, zTerm, nTerm, pSegcsr @@ -191027,11 +149951,11 @@ } } } if( bFound==0 ){ - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr ); pSegcsr->bLookup = !isPrefix; } } @@ -191075,11 +149999,11 @@ filter.zTerm = pTok->z; filter.nTerm = pTok->n; rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter); while( SQLITE_OK==rc - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) + && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) ){ rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist); } if( rc==SQLITE_OK ){ @@ -191104,11 +150028,11 @@ ** This function counts the total number of docids in the doclist stored ** in buffer aList[], size nList bytes. ** ** If the isPoslist argument is true, then it is assumed that the doclist ** contains a position-list following each docid. Otherwise, it is assumed -** that the doclist is simply a list of docids stored as delta encoded +** that the doclist is simply a list of docids stored as delta encoded ** varints. */ static int fts3DoclistCountDocids(char *aList, int nList){ int nDoc = 0; /* Return value */ if( aList ){ @@ -191137,27 +150061,36 @@ */ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){ int rc; Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){ - Fts3Table *pTab = (Fts3Table*)pCursor->pVtab; - pTab->bLock++; if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){ pCsr->isEof = 1; rc = sqlite3_reset(pCsr->pStmt); }else{ pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0); rc = SQLITE_OK; } - pTab->bLock--; }else{ rc = fts3EvalNext((Fts3Cursor *)pCursor); } assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); return rc; } +/* +** The following are copied from sqliteInt.h. +** +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#ifndef SQLITE_AMALGAMATION +# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +#endif + /* ** If the numeric type of argument pVal is "integer", then return it ** converted to a 64-bit signed integer. Otherwise, return a copy of ** the second parameter, iDefault. */ @@ -191207,14 +150140,10 @@ int iIdx; UNUSED_PARAMETER(idxStr); UNUSED_PARAMETER(nVal); - if( p->bLock ){ - return SQLITE_ERROR; - } - eSearch = (idxNum & 0x0000FFFF); assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); assert( p->pSegments==0 ); /* Collect arguments into local variables */ @@ -191250,11 +150179,11 @@ pCsr->iLangid = 0; if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid); assert( p->base.zErrMsg==0 ); rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, - p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, + p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, &p->base.zErrMsg ); if( rc!=SQLITE_OK ){ return rc; } @@ -191277,20 +150206,16 @@ "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, (pCsr->bDesc ? "DESC" : "ASC") ); }else{ - zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", + zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") ); } if( zSql ){ - p->bLock++; - rc = sqlite3_prepare_v3( - p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 - ); - p->bLock--; + rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0); sqlite3_free(zSql); }else{ rc = SQLITE_NOMEM; } }else if( eSearch==FTS3_DOCID_SEARCH ){ @@ -191302,12 +150227,12 @@ if( rc!=SQLITE_OK ) return rc; return fts3NextMethod(pCursor); } -/* -** This is the xEof method of the virtual table. SQLite calls this +/* +** This is the xEof method of the virtual table. SQLite calls this ** routine to find out if it has reached the end of a result set. */ static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ Fts3Cursor *pCsr = (Fts3Cursor*)pCursor; if( pCsr->isEof ){ @@ -191315,11 +150240,11 @@ pCsr->isEof = 1; } return pCsr->isEof; } -/* +/* ** This is the xRowid method. The SQLite core calls this routine to ** retrieve the rowid for the current row of the result set. fts3 ** exposes %_content.docid as the rowid for the virtual table. The ** rowid should be written to *pRowid. */ @@ -191327,11 +150252,11 @@ Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; *pRowid = pCsr->iPrevId; return SQLITE_OK; } -/* +/* ** This is the xColumn method, called by SQLite to request a value from ** the row that the supplied cursor currently points to. ** ** If: ** @@ -191353,11 +150278,11 @@ assert( iCol>=0 && iCol<=p->nColumn+2 ); switch( iCol-p->nColumn ){ case 0: /* The special 'table-name' column */ - sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0); + sqlite3_result_pointer(pCtx, pCsr); break; case 1: /* The docid column */ sqlite3_result_int64(pCtx, pCsr->iPrevId); @@ -191370,11 +150295,11 @@ }else if( p->zLanguageid==0 ){ sqlite3_result_int(pCtx, 0); break; }else{ iCol = p->nColumn; - /* no break */ deliberate_fall_through + /* fall-through */ } default: /* A user column. Or, if this is a full-table scan, possibly the ** language-id column. Seek the cursor. */ @@ -191387,12 +150312,12 @@ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); return rc; } -/* -** This function is the implementation of the xUpdate callback used by +/* +** This function is the implementation of the xUpdate callback used by ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be ** inserted, updated or deleted. */ static int fts3UpdateMethod( sqlite3_vtab *pVtab, /* Virtual table handle */ @@ -191423,22 +150348,22 @@ ** is only attempted if it will write at least 64 leaf blocks. Hence ** nMinMerge. ** ** Of course, updating the input segments also involves deleting a bunch ** of blocks from the segments table. But this is not considered overhead - ** as it would also be required by a crisis-merge that used the same input + ** as it would also be required by a crisis-merge that used the same input ** segments. */ const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ Fts3Table *p = (Fts3Table*)pVtab; int rc; i64 iLastRowid = sqlite3_last_insert_rowid(p->db); rc = sqlite3Fts3PendingTermsFlush(p); - if( rc==SQLITE_OK - && p->nLeafAdd>(nMinMerge/16) + if( rc==SQLITE_OK + && p->nLeafAdd>(nMinMerge/16) && p->nAutoincrmerge && p->nAutoincrmerge!=0xff ){ int mxLevel = 0; /* Maximum relative level value in db */ int A; /* Incr-merge parameter A */ @@ -191473,28 +150398,22 @@ } return rc; } /* -** Implementation of xBegin() method. +** Implementation of xBegin() method. */ static int fts3BeginMethod(sqlite3_vtab *pVtab){ Fts3Table *p = (Fts3Table*)pVtab; - int rc; UNUSED_PARAMETER(pVtab); assert( p->pSegments==0 ); assert( p->nPendingData==0 ); assert( p->inTransaction!=1 ); + TESTONLY( p->inTransaction = 1 ); + TESTONLY( p->mxSavepoint = -1; ); p->nLeafAdd = 0; - rc = fts3SetHasStat(p); -#ifdef SQLITE_DEBUG - if( rc==SQLITE_OK ){ - p->inTransaction = 1; - p->mxSavepoint = -1; - } -#endif - return rc; + return fts3SetHasStat(p); } /* ** Implementation of xCommit() method. This is a no-op. The contents of ** the pending-terms hash-table have already been flushed into the database @@ -191535,21 +150454,21 @@ char c = 0; /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ while( p>pStart && (c=*p--)==0 ); - /* Search backwards for a varint with value zero (the end of the previous + /* Search backwards for a varint with value zero (the end of the previous ** poslist). This is an 0x00 byte preceded by some byte that does not ** have the 0x80 bit set. */ - while( p>pStart && (*p & 0x80) | c ){ - c = *p--; + while( p>pStart && (*p & 0x80) | c ){ + c = *p--; } assert( p==pStart || c==0 ); /* At this point p points to that preceding byte without the 0x80 bit ** set. So to find the start of the poslist, skip forward 2 bytes then - ** over a varint. + ** over a varint. ** ** Normally. The other case is that p==pStart and the poslist to return ** is the first in the doclist. In this case do not skip forward 2 bytes. ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) ** is required for cases where the first byte of a doclist and the @@ -191566,11 +150485,11 @@ /* ** Helper function used by the implementation of the overloaded snippet(), ** offsets() and optimize() SQL functions. ** ** If the value passed as the third argument is a blob of size -** sizeof(Fts3Cursor*), then the blob contents are copied to the +** sizeof(Fts3Cursor*), then the blob contents are copied to the ** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error ** message is written to context pContext and SQLITE_ERROR returned. The ** string passed via zFunc is used as part of the error message. */ static int fts3FunctionArg( @@ -191578,11 +150497,11 @@ const char *zFunc, /* Function name */ sqlite3_value *pVal, /* argv[0] passed to function */ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ ){ int rc; - *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor"); + *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal); if( (*ppCsr)!=0 ){ rc = SQLITE_OK; }else{ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); sqlite3_result_error(pContext, zErr, -1); @@ -191611,25 +150530,21 @@ ** the non-overloaded version would have been called instead of this one). */ assert( nVal>=1 ); if( nVal>6 ){ - sqlite3_result_error(pContext, + sqlite3_result_error(pContext, "wrong number of arguments to function snippet()", -1); return; } if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; switch( nVal ){ case 6: nToken = sqlite3_value_int(apVal[5]); - /* no break */ deliberate_fall_through case 5: iCol = sqlite3_value_int(apVal[4]); - /* no break */ deliberate_fall_through case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); - /* no break */ deliberate_fall_through case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); - /* no break */ deliberate_fall_through case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); } if( !zEllipsis || !zEnd || !zStart ){ sqlite3_result_error_nomem(pContext); }else if( nToken==0 ){ @@ -191657,12 +150572,12 @@ if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ sqlite3Fts3Offsets(pContext, pCsr); } } -/* -** Implementation of the special optimize() function for FTS3. This +/* +** Implementation of the special optimize() function for FTS3. This ** function merges all segments in the database to a single segment. ** Example usage is: ** ** SELECT optimize(t) FROM t LIMIT 1; ** @@ -191767,24 +150682,22 @@ int rc; /* Return Code */ /* At this point it must be known if the %_stat table exists or not. ** So bHasStat may not be 2. */ rc = fts3SetHasStat(p); - + /* As it happens, the pending terms table is always empty here. This is - ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction - ** always opens a savepoint transaction. And the xSavepoint() method + ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction + ** always opens a savepoint transaction. And the xSavepoint() method ** flushes the pending terms table. But leave the (no-op) call to ** PendingTermsFlush() in in case that changes. */ assert( p->nPendingData==0 ); if( rc==SQLITE_OK ){ rc = sqlite3Fts3PendingTermsFlush(p); } - p->bIgnoreSavepoint = 1; - if( p->zContentTbl==0 ){ fts3DbExec(&rc, db, "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", p->zDb, p->zName, zName ); @@ -191808,12 +150721,10 @@ ); fts3DbExec(&rc, db, "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", p->zDb, p->zName, zName ); - - p->bIgnoreSavepoint = 0; return rc; } /* ** The xSavepoint() method. @@ -191820,32 +150731,16 @@ ** ** Flush the contents of the pending-terms table to disk. */ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ int rc = SQLITE_OK; - Fts3Table *pTab = (Fts3Table*)pVtab; - assert( pTab->inTransaction ); - assert( pTab->mxSavepoint<=iSavepoint ); - TESTONLY( pTab->mxSavepoint = iSavepoint ); - - if( pTab->bIgnoreSavepoint==0 ){ - if( fts3HashCount(&pTab->aIndex[0].hPending)>0 ){ - char *zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')", - pTab->zDb, pTab->zName, pTab->zName - ); - if( zSql ){ - pTab->bIgnoreSavepoint = 1; - rc = sqlite3_exec(pTab->db, zSql, 0, 0, 0); - pTab->bIgnoreSavepoint = 0; - sqlite3_free(zSql); - }else{ - rc = SQLITE_NOMEM; - } - } - if( rc==SQLITE_OK ){ - pTab->iSavepoint = iSavepoint+1; - } + UNUSED_PARAMETER(iSavepoint); + assert( ((Fts3Table *)pVtab)->inTransaction ); + assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint ); + TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); + if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ + rc = fts3SyncMethod(pVtab); } return rc; } /* @@ -191852,85 +150747,36 @@ ** The xRelease() method. ** ** This is a no-op. */ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *pTab = (Fts3Table*)pVtab; - assert( pTab->inTransaction ); - assert( pTab->mxSavepoint >= iSavepoint ); - TESTONLY( pTab->mxSavepoint = iSavepoint-1 ); - pTab->iSavepoint = iSavepoint; + TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); + UNUSED_PARAMETER(iSavepoint); + UNUSED_PARAMETER(pVtab); + assert( p->inTransaction ); + assert( p->mxSavepoint >= iSavepoint ); + TESTONLY( p->mxSavepoint = iSavepoint-1 ); return SQLITE_OK; } /* ** The xRollbackTo() method. ** ** Discard the contents of the pending terms table. */ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *pTab = (Fts3Table*)pVtab; + Fts3Table *p = (Fts3Table*)pVtab; UNUSED_PARAMETER(iSavepoint); - assert( pTab->inTransaction ); - TESTONLY( pTab->mxSavepoint = iSavepoint ); - if( (iSavepoint+1)<=pTab->iSavepoint ){ - sqlite3Fts3PendingTermsClear(pTab); - } + assert( p->inTransaction ); + assert( p->mxSavepoint >= iSavepoint ); + TESTONLY( p->mxSavepoint = iSavepoint ); + sqlite3Fts3PendingTermsClear(p); return SQLITE_OK; } - -/* -** Return true if zName is the extension on one of the shadow tables used -** by this module. -*/ -static int fts3ShadowName(const char *zName){ - static const char *azName[] = { - "content", "docsize", "segdir", "segments", "stat", - }; - unsigned int i; - for(i=0; ibFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc)); - if( *pzErr ) rc = SQLITE_OK; - }else if( rc==SQLITE_OK && bOk==0 ){ - *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", - p->bFts4 ? 4 : 3, zSchema, zTabname); - if( *pzErr==0 ) rc = SQLITE_NOMEM; - } - sqlite3Fts3SegmentsClose(p); - return rc; -} - - static const sqlite3_module fts3Module = { - /* iVersion */ 4, + /* iVersion */ 2, /* xCreate */ fts3CreateMethod, /* xConnect */ fts3ConnectMethod, /* xBestIndex */ fts3BestIndexMethod, /* xDisconnect */ fts3DisconnectMethod, /* xDestroy */ fts3DestroyMethod, @@ -191949,30 +150795,25 @@ /* xFindFunction */ fts3FindFunctionMethod, /* xRename */ fts3RenameMethod, /* xSavepoint */ fts3SavepointMethod, /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, - /* xShadowName */ fts3ShadowName, - /* xIntegrity */ fts3IntegrityMethod, }; /* ** This function is registered as the module destructor (called when an ** FTS3 enabled database connection is closed). It frees the memory ** allocated for the tokenizer hash table. */ static void hashDestroy(void *p){ - Fts3HashWrapper *pHash = (Fts3HashWrapper *)p; - pHash->nRef--; - if( pHash->nRef<=0 ){ - sqlite3Fts3HashClear(&pHash->hash); - sqlite3_free(pHash); - } + Fts3Hash *pHash = (Fts3Hash *)p; + sqlite3Fts3HashClear(pHash); + sqlite3_free(pHash); } /* -** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are +** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are ** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c ** respectively. The following three forward declarations are for functions ** declared in these files used to retrieve the respective implementations. ** ** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed @@ -191994,11 +150835,11 @@ ** SQLite. If fts3 is built as a dynamically loadable extension, this ** function is called by the sqlite3_extension_init() entry point. */ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ int rc = SQLITE_OK; - Fts3HashWrapper *pHash = 0; + Fts3Hash *pHash = 0; const sqlite3_tokenizer_module *pSimple = 0; const sqlite3_tokenizer_module *pPorter = 0; #ifndef SQLITE_DISABLE_FTS3_UNICODE const sqlite3_tokenizer_module *pUnicode = 0; #endif @@ -192022,92 +150863,88 @@ sqlite3Fts3SimpleTokenizerModule(&pSimple); sqlite3Fts3PorterTokenizerModule(&pPorter); /* Allocate and initialize the hash-table used to store tokenizers. */ - pHash = sqlite3_malloc(sizeof(Fts3HashWrapper)); + pHash = sqlite3_malloc(sizeof(Fts3Hash)); if( !pHash ){ rc = SQLITE_NOMEM; }else{ - sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1); - pHash->nRef = 0; + sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); } /* Load the built-in tokenizers into the hash table */ if( rc==SQLITE_OK ){ - if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple) - || sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter) + if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) + || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) #ifndef SQLITE_DISABLE_FTS3_UNICODE - || sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode) + || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) #endif #ifdef SQLITE_ENABLE_ICU - || (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu)) + || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) #endif ){ rc = SQLITE_NOMEM; } } #ifdef SQLITE_TEST if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash); + rc = sqlite3Fts3ExprInitTestInterface(db); } #endif - /* Create the virtual table wrapper around the hash-table and overload + /* Create the virtual table wrapper around the hash-table and overload ** the four scalar functions. If this is successful, register the ** module with sqlite. */ - if( SQLITE_OK==rc - && SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer")) + if( SQLITE_OK==rc + && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) ){ - pHash->nRef++; rc = sqlite3_create_module_v2( db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); if( rc==SQLITE_OK ){ - pHash->nRef++; rc = sqlite3_create_module_v2( - db, "fts4", &fts3Module, (void *)pHash, hashDestroy + db, "fts4", &fts3Module, (void *)pHash, 0 ); } if( rc==SQLITE_OK ){ - pHash->nRef++; - rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy); + rc = sqlite3Fts3InitTok(db, (void *)pHash); } return rc; } /* An error has occurred. Delete the hash table and return the error code. */ assert( rc!=SQLITE_OK ); if( pHash ){ - sqlite3Fts3HashClear(&pHash->hash); + sqlite3Fts3HashClear(pHash); sqlite3_free(pHash); } return rc; } /* ** Allocate an Fts3MultiSegReader for each token in the expression headed -** by pExpr. +** by pExpr. ** ** An Fts3SegReader object is a cursor that can seek or scan a range of ** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple ** Fts3SegReader objects internally to provide an interface to seek or scan ** within the union of all segments of a b-tree. Hence the name. ** ** If the allocated Fts3MultiSegReader just seeks to a single entry in a ** segment b-tree (if the term is not a prefix or it is a prefix for which ** there exists prefix b-tree of the right length) then it may be traversed -** and merged incrementally. Otherwise, it has to be merged into an in-memory +** and merged incrementally. Otherwise, it has to be merged into an in-memory ** doclist and then traversed. */ static void fts3EvalAllocateReaders( Fts3Cursor *pCsr, /* FTS cursor handle */ Fts3Expr *pExpr, /* Allocate readers for this expression */ @@ -192120,11 +150957,11 @@ int i; int nToken = pExpr->pPhrase->nToken; *pnToken += nToken; for(i=0; ipPhrase->aToken[i]; - int rc = fts3TermSegReaderCursor(pCsr, + int rc = fts3TermSegReaderCursor(pCsr, pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr ); if( rc!=SQLITE_OK ){ *pRc = rc; return; @@ -192238,11 +151075,10 @@ } return rc; } -#ifndef SQLITE_DISABLE_FTS4_DEFERRED /* ** This function is called on each phrase after the position lists for ** any deferred tokens have been loaded into memory. It updates the phrases ** current position list to include only those positions that are really ** instances of the phrase (after considering deferred tokens). If this @@ -192254,11 +151090,12 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ int iToken; /* Used to iterate through phrase tokens */ char *aPoslist = 0; /* Position list for deferred tokens */ int nPoslist = 0; /* Number of bytes in aPoslist */ int iPrev = -1; /* Token number of previous deferred token */ - char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0); + + assert( pPhrase->doclist.bFreeList==0 ); for(iToken=0; iTokennToken; iToken++){ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; Fts3DeferredToken *pDeferred = pToken->pDeferred; @@ -192268,11 +151105,10 @@ int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList); if( rc!=SQLITE_OK ) return rc; if( pList==0 ){ sqlite3_free(aPoslist); - sqlite3_free(aFree); pPhrase->doclist.pList = 0; pPhrase->doclist.nList = 0; return SQLITE_OK; }else if( aPoslist==0 ){ @@ -192289,11 +151125,10 @@ sqlite3_free(aPoslist); aPoslist = pList; nPoslist = (int)(aOut - aPoslist); if( nPoslist==0 ){ sqlite3_free(aPoslist); - sqlite3_free(aFree); pPhrase->doclist.pList = 0; pPhrase->doclist.nList = 0; return SQLITE_OK; } } @@ -192322,18 +151157,17 @@ p1 = pPhrase->doclist.pList; p2 = aPoslist; nDistance = iPrev - nMaxUndeferred; } - aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING); + aOut = (char *)sqlite3_malloc(nPoslist+8); if( !aOut ){ sqlite3_free(aPoslist); return SQLITE_NOMEM; } - + pPhrase->doclist.pList = aOut; - assert( p1 && p2 ); if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){ pPhrase->doclist.bFreeList = 1; pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList); }else{ sqlite3_free(aOut); @@ -192342,23 +151176,21 @@ } sqlite3_free(aPoslist); } } - if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree); return SQLITE_OK; } -#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ /* ** Maximum number of tokens a phrase may have to be considered for the ** incremental doclists strategy. */ #define MAX_INCR_PHRASE_TOKENS 4 /* -** This function is called for each Fts3Phrase in a full-text query +** This function is called for each Fts3Phrase in a full-text query ** expression to initialize the mechanism for returning rows. Once this ** function has been called successfully on an Fts3Phrase, it may be ** used with fts3EvalPhraseNext() to iterate through the matching docids. ** ** If parameter bOptOk is true, then the phrase may (or may not) use the @@ -192372,18 +151204,18 @@ int rc = SQLITE_OK; /* Error code */ int i; /* Determine if doclists may be loaded from disk incrementally. This is ** possible if the bOptOk argument is true, the FTS doclists will be - ** scanned in forward order, and the phrase consists of + ** scanned in forward order, and the phrase consists of ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" ** tokens or prefix tokens that cannot use a prefix-index. */ int bHaveIncr = 0; - int bIncrOk = (bOptOk - && pCsr->bDesc==pTab->bDescIdx + int bIncrOk = (bOptOk + && pCsr->bDesc==pTab->bDescIdx && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +#ifdef SQLITE_TEST && pTab->bNoIncrDoclist==0 #endif ); for(i=0; bIncrOk==1 && inToken; i++){ Fts3PhraseToken *pToken = &p->aToken[i]; @@ -192413,16 +151245,16 @@ assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr ); return rc; } /* -** This function is used to iterate backwards (from the end to start) +** This function is used to iterate backwards (from the end to start) ** through doclists. It is used by this module to iterate through phrase ** doclists in reverse and by the fts3_write.c module to iterate through ** pending-terms lists when writing to databases with "order=desc". ** -** The doclist may be sorted in ascending (parameter bDescIdx==0) or +** The doclist may be sorted in ascending (parameter bDescIdx==0) or ** descending (parameter bDescIdx==1) order of docid. Regardless, this ** function iterates from the end of the doclist to the beginning. */ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( int bDescIdx, /* True if the doclist is desc */ @@ -192435,11 +151267,11 @@ ){ char *p = *ppIter; assert( nDoclist>0 ); assert( *pbEof==0 ); - assert_fts3_nc( p || *piDocid==0 ); + assert( p || *piDocid==0 ); assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); if( p==0 ){ sqlite3_int64 iDocid = 0; char *pNext = 0; @@ -192490,19 +151322,19 @@ ){ char *p = *ppIter; assert( nDoclist>0 ); assert( *pbEof==0 ); - assert_fts3_nc( p || *piDocid==0 ); + assert( p || *piDocid==0 ); assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); if( p==0 ){ p = aDoclist; p += sqlite3Fts3GetVarint(p, piDocid); }else{ fts3PoslistCopy(0, &p); - while( p<&aDoclist[nDoclist] && *p==0 ) p++; + while( p<&aDoclist[nDoclist] && *p==0 ) p++; if( p>=&aDoclist[nDoclist] ){ *pbEof = 1; }else{ sqlite3_int64 iVar; p += sqlite3Fts3GetVarint(p, &iVar); @@ -192521,20 +151353,19 @@ Fts3Table *pTab, Fts3Doclist *pDL, u8 *pbEof ){ char *pIter; /* Used to iterate through aAll */ - char *pEnd; /* 1 byte past end of aAll */ - + char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */ + if( pDL->pNextDocid ){ pIter = pDL->pNextDocid; - assert( pDL->aAll!=0 || pIter==0 ); }else{ pIter = pDL->aAll; } - if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){ + if( pIter>=pEnd ){ /* We have already reached the end of this doclist. EOF. */ *pbEof = 1; }else{ sqlite3_int64 iDelta; pIter += sqlite3Fts3GetVarint(pIter, &iDelta); @@ -192571,16 +151402,16 @@ char *pList; int nList; }; /* -** Token pToken is an incrementally loaded token that is part of a +** Token pToken is an incrementally loaded token that is part of a ** multi-token phrase. Advance it to the next matching document in the ** database and populate output variable *p with the details of the new ** entry. Or, if the iterator has reached EOF, set *pbEof to true. ** -** If an error occurs, return an SQLite error code. Otherwise, return +** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. */ static int incrPhraseTokenNext( Fts3Table *pTab, /* Virtual table handle */ Fts3Phrase *pPhrase, /* Phrase to advance token of */ @@ -192617,22 +151448,22 @@ /* ** The phrase iterator passed as the second argument: ** -** * features at least one token that uses an incremental doclist, and +** * features at least one token that uses an incremental doclist, and ** ** * does not contain any deferred tokens. ** ** Advance it to the next matching documnent in the database and populate -** the Fts3Doclist.pList and nList fields. +** the Fts3Doclist.pList and nList fields. ** ** If there is no "next" entry and no error occurs, then *pbEof is set to ** 1 before returning. Otherwise, if no error occurs and the iterator is ** successfully advanced, *pbEof is set to 0. ** -** If an error occurs, return an SQLite error code. Otherwise, return +** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. */ static int fts3EvalIncrPhraseNext( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Phrase *p, /* Phrase object to advance to next docid */ @@ -192646,11 +151477,11 @@ /* This is only called if it is guaranteed that the phrase has at least ** one incremental token. In which case the bIncr flag is set. */ assert( p->bIncr==1 ); if( p->nToken==1 ){ - rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, + rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, &pDL->iDocid, &pDL->pList, &pDL->nList ); if( pDL->pList==0 ) bEof = 1; }else{ int bDescDoclist = pCsr->bDesc; @@ -192676,12 +151507,12 @@ assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) ); assert( rc!=SQLITE_OK || bMaxSet ); /* Keep advancing iterators until they all point to the same document */ for(i=0; inToken; i++){ - while( rc==SQLITE_OK && bEof==0 - && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0 + while( rc==SQLITE_OK && bEof==0 + && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0 ){ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); if( DOCID_CMP(a[i].iDocid, iMax)>0 ){ iMax = a[i].iDocid; i = 0; @@ -192691,14 +151522,13 @@ /* Check if the current entries really are a phrase match */ if( bEof==0 ){ int nList = 0; int nByte = a[p->nToken-1].nList; - char *aDoclist = sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING); + char *aDoclist = sqlite3_malloc(nByte+1); if( !aDoclist ) return SQLITE_NOMEM; memcpy(aDoclist, a[p->nToken-1].pList, nByte+1); - memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING); for(i=0; i<(p->nToken-1); i++){ if( a[i].bIgnore==0 ){ char *pL = a[i].pList; char *pR = aDoclist; @@ -192724,12 +151554,12 @@ *pbEof = bEof; return rc; } /* -** Attempt to move the phrase iterator to point to the next matching docid. -** If an error occurs, return an SQLite error code. Otherwise, return +** Attempt to move the phrase iterator to point to the next matching docid. +** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. ** ** If there is no "next" entry and no error occurs, then *pbEof is set to ** 1 before returning. Otherwise, if no error occurs and the iterator is ** successfully advanced, *pbEof is set to 0. @@ -192744,11 +151574,11 @@ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; if( p->bIncr ){ rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof); }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){ - sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, + sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof ); pDL->pList = pDL->pNextDocid; }else{ fts3EvalDlPhraseNext(pTab, pDL, pbEof); @@ -192804,11 +151634,11 @@ ** token in the FTS expression. ** ** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong ** to phrases that are connected only by AND and NEAR operators (not OR or ** NOT). When determining tokens to defer, each AND/NEAR cluster is considered -** separately. The root of a tokens AND/NEAR cluster is stored in +** separately. The root of a tokens AND/NEAR cluster is stored in ** Fts3TokenAndCost.pRoot. */ typedef struct Fts3TokenAndCost Fts3TokenAndCost; struct Fts3TokenAndCost { Fts3Phrase *pPhrase; /* The phrase the token belongs to */ @@ -192872,24 +151702,24 @@ /* ** Determine the average document (row) size in pages. If successful, ** write this value to *pnPage and return SQLITE_OK. Otherwise, return ** an SQLite error code. ** -** The average document size in pages is calculated by first calculating +** The average document size in pages is calculated by first calculating ** determining the average size in bytes, B. If B is less than the amount ** of data that will fit on a single leaf page of an intkey table in ** this database, then the average docsize is 1. Otherwise, it is 1 plus ** the number of overflow pages consumed by a record B bytes in size. */ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){ int rc = SQLITE_OK; if( pCsr->nRowAvg==0 ){ /* The average document size, which is required to calculate the cost - ** of each doclist, has not yet been determined. Read the required + ** of each doclist, has not yet been determined. Read the required ** data from the %_stat table to calculate it. ** - ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 + ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 ** varints, where nCol is the number of columns in the FTS3 table. ** The first varint is the number of documents currently stored in ** the table. The following nCol varints contain the total amount of ** data stored in all rows of each column of the table, from left ** to right. @@ -192902,39 +151732,38 @@ const char *a; rc = sqlite3Fts3SelectDoctotal(p, &pStmt); if( rc!=SQLITE_OK ) return rc; a = sqlite3_column_blob(pStmt, 0); - testcase( a==0 ); /* If %_stat.value set to X'' */ - if( a ){ - pEnd = &a[sqlite3_column_bytes(pStmt, 0)]; - a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc); - while( anDoc = nDoc; pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz); - assert( pCsr->nRowAvg>0 ); + assert( pCsr->nRowAvg>0 ); rc = sqlite3_reset(pStmt); } *pnPage = pCsr->nRowAvg; return rc; } /* -** This function is called to select the tokens (if any) that will be +** This function is called to select the tokens (if any) that will be ** deferred. The array aTC[] has already been populated when this is ** called. ** -** This function is called once for each AND/NEAR cluster in the +** This function is called once for each AND/NEAR cluster in the ** expression. Each invocation determines which tokens to defer within ** the cluster with root node pRoot. See comments above the definition ** of struct Fts3TokenAndCost for more details. ** ** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken() @@ -192980,12 +151809,12 @@ /* Obtain the average docsize (in pages). */ rc = fts3EvalAverageDocsize(pCsr, &nDocSize); assert( rc!=SQLITE_OK || nDocSize>0 ); - /* Iterate through all tokens in this AND/NEAR cluster, in ascending order - ** of the number of overflow pages that will be loaded by the pager layer + /* Iterate through all tokens in this AND/NEAR cluster, in ascending order + ** of the number of overflow pages that will be loaded by the pager layer ** to retrieve the entire doclist for the token from the full-text index. ** Load the doclists for tokens that are either: ** ** a. The cheapest token in the entire query (i.e. the one visited by the ** first iteration of this loop), or @@ -192992,11 +151821,11 @@ ** ** b. Part of a multi-token phrase. ** ** After each token doclist is loaded, merge it with the others from the ** same phrase and count the number of documents that the merged doclist - ** contains. Set variable "nMinEst" to the smallest number of documents in + ** contains. Set variable "nMinEst" to the smallest number of documents in ** any phrase doclist for which 1 or more token doclists have been loaded. ** Let nOther be the number of other phrases for which it is certain that ** one or more tokens will not be deferred. ** ** Then, for each token, defer it if loading the doclist would result in @@ -193008,30 +151837,30 @@ int iTC; /* Used to iterate through aTC[] array. */ Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */ /* Set pTC to point to the cheapest remaining token. */ for(iTC=0; iTCnOvfl) + if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot + && (!pTC || aTC[iTC].nOvflnOvfl) ){ pTC = &aTC[iTC]; } } assert( pTC ); if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){ /* The number of overflow pages to load for this (and therefore all - ** subsequent) tokens is greater than the estimated number of pages + ** subsequent) tokens is greater than the estimated number of pages ** that will be loaded if all subsequent tokens are deferred. */ Fts3PhraseToken *pToken = pTC->pToken; rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol); fts3SegReaderCursorFree(pToken->pSegcsr); pToken->pSegcsr = 0; }else{ /* Set nLoad4 to the value of (4^nOther) for the next iteration of the - ** for-loop. Except, limit the value to 2^24 to prevent it from + ** for-loop. Except, limit the value to 2^24 to prevent it from ** overflowing the 32-bit integer it is stored in. */ if( ii<12 ) nLoad4 = nLoad4*4; if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ /* Either this is the cheapest token in the entire query, or it is @@ -193085,19 +151914,20 @@ /* Determine which, if any, tokens in the expression should be deferred. */ #ifndef SQLITE_DISABLE_FTS4_DEFERRED if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){ Fts3TokenAndCost *aTC; - aTC = (Fts3TokenAndCost *)sqlite3_malloc64( + Fts3Expr **apOr; + aTC = (Fts3TokenAndCost *)sqlite3_malloc( sizeof(Fts3TokenAndCost) * nToken + sizeof(Fts3Expr *) * nOr * 2 ); + apOr = (Fts3Expr **)&aTC[nToken]; if( !aTC ){ rc = SQLITE_NOMEM; }else{ - Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken]; int ii; Fts3TokenAndCost *pTC = aTC; Fts3Expr **ppOr = apOr; fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc); @@ -193139,20 +151969,20 @@ ** ** abc NEAR/5 "def ghi" ** ** Parameter nNear is passed the NEAR distance of the expression (5 in ** the example above). When this function is called, *paPoslist points to -** the position list, and *pnToken is the number of phrase tokens in the +** the position list, and *pnToken is the number of phrase tokens in, the ** phrase on the other side of the NEAR operator to pPhrase. For example, ** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to ** the position list associated with phrase "abc". ** ** All positions in the pPhrase position list that are not sufficiently ** close to a position in the *paPoslist position list are removed. If this ** leaves 0 positions, zero is returned. Otherwise, non-zero. ** -** Before returning, *paPoslist is set to point to the position lsit +** Before returning, *paPoslist is set to point to the position lsit ** associated with pPhrase. And *pnToken is set to the number of tokens in ** pPhrase. */ static int fts3EvalNearTrim( int nNear, /* NEAR distance. As in "NEAR/nNear". */ @@ -193162,12 +151992,12 @@ Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */ ){ int nParam1 = nNear + pPhrase->nToken; int nParam2 = nNear + *pnToken; int nNew; - char *p2; - char *pOut; + char *p2; + char *pOut; int res; assert( pPhrase->doclist.pList ); p2 = pOut = pPhrase->doclist.pList; @@ -193174,16 +152004,14 @@ res = fts3PoslistNearMerge( &pOut, aTmp, nParam1, nParam2, paPoslist, &p2 ); if( res ){ nNew = (int)(pOut - pPhrase->doclist.pList) - 1; - assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 ); - if( nNew>=0 && nNew<=pPhrase->doclist.nList ){ - assert( pPhrase->doclist.pList[nNew]=='\0' ); - memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew); - pPhrase->doclist.nList = nNew; - } + assert( pPhrase->doclist.pList[nNew]=='\0' ); + assert( nNew<=pPhrase->doclist.nList && nNew>0 ); + memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew); + pPhrase->doclist.nList = nNew; *paPoslist = pPhrase->doclist.pList; *pnToken = pPhrase->nToken; } return res; @@ -193212,33 +152040,34 @@ ** It says above that this function advances the expression to the next ** matching row. This is usually true, but there are the following exceptions: ** ** 1. Deferred tokens are not taken into account. If a phrase consists ** entirely of deferred tokens, it is assumed to match every row in -** the db. In this case the position-list is not populated at all. +** the db. In this case the position-list is not populated at all. ** ** Or, if a phrase contains one or more deferred tokens and one or -** more non-deferred tokens, then the expression is advanced to the +** more non-deferred tokens, then the expression is advanced to the ** next possible match, considering only non-deferred tokens. In other ** words, if the phrase is "A B C", and "B" is deferred, the expression -** is advanced to the next row that contains an instance of "A * C", +** is advanced to the next row that contains an instance of "A * C", ** where "*" may match any single token. The position list in this case ** is populated as for "A * C" before returning. ** -** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is +** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is ** advanced to point to the next row that matches "x AND y". -** +** ** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is ** really a match, taking into account deferred tokens and NEAR operators. */ static void fts3EvalNextRow( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Expr *pExpr, /* Expr. to advance to next matching row */ int *pRc /* IN/OUT: Error code */ ){ - if( *pRc==SQLITE_OK && pExpr->bEof==0 ){ + if( *pRc==SQLITE_OK ){ int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ + assert( pExpr->bEof==0 ); pExpr->bStart = 1; switch( pExpr->eType ){ case FTSQUERY_NEAR: case FTSQUERY_AND: { @@ -193287,23 +152116,22 @@ while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ memset(pDl->pList, 0, pDl->nList); fts3EvalNextRow(pCsr, pLeft, pRc); } } - pRight->bEof = pLeft->bEof = 1; } } break; } - + case FTSQUERY_OR: { Fts3Expr *pLeft = pExpr->pLeft; Fts3Expr *pRight = pExpr->pRight; sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - assert_fts3_nc( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); - assert_fts3_nc( pRight->bStart || pLeft->iDocid==pRight->iDocid ); + assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); + assert( pRight->bStart || pLeft->iDocid==pRight->iDocid ); if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ fts3EvalNextRow(pCsr, pLeft, pRc); }else if( pLeft->bEof || iCmp>0 ){ fts3EvalNextRow(pCsr, pRight, pRc); @@ -193332,13 +152160,13 @@ assert( *pRc!=SQLITE_OK || pRight->bStart ); } fts3EvalNextRow(pCsr, pLeft, pRc); if( pLeft->bEof==0 ){ - while( !*pRc - && !pRight->bEof - && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 + while( !*pRc + && !pRight->bEof + && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 ){ fts3EvalNextRow(pCsr, pRight, pRc); } } pExpr->iDocid = pLeft->iDocid; @@ -193359,18 +152187,18 @@ /* ** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR ** cluster, then this function returns 1 immediately. ** -** Otherwise, it checks if the current row really does match the NEAR -** expression, using the data currently stored in the position lists -** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. +** Otherwise, it checks if the current row really does match the NEAR +** expression, using the data currently stored in the position lists +** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. ** ** If the current row is a match, the position list associated with each ** phrase in the NEAR expression is edited in place to contain only those ** phrase instances sufficiently close to their peers to satisfy all NEAR -** constraints. In this case it returns 1. If the NEAR expression does not +** constraints. In this case it returns 1. If the NEAR expression does not ** match the current row, 0 is returned. The position lists may or may not ** be edited if 0 is returned. */ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ int res = 1; @@ -193389,29 +152217,29 @@ ** | | ** +--NEAR--+ "y" ** | | ** "w" "x" ** - ** The right-hand child of a NEAR node is always a phrase. The + ** The right-hand child of a NEAR node is always a phrase. The ** left-hand child may be either a phrase or a NEAR node. There are ** no exceptions to this - it's the way the parser in fts3_expr.c works. */ - if( *pRc==SQLITE_OK - && pExpr->eType==FTSQUERY_NEAR + if( *pRc==SQLITE_OK + && pExpr->eType==FTSQUERY_NEAR && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) ){ - Fts3Expr *p; - sqlite3_int64 nTmp = 0; /* Bytes of temp space */ + Fts3Expr *p; + int nTmp = 0; /* Bytes of temp space */ char *aTmp; /* Temp space for PoslistNearMerge() */ /* Allocate temporary working space. */ for(p=pExpr; p->pLeft; p=p->pLeft){ assert( p->pRight->pPhrase->doclist.nList>0 ); nTmp += p->pRight->pPhrase->doclist.nList; } nTmp += p->pPhrase->doclist.nList; - aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX); + aTmp = sqlite3_malloc(nTmp*2); if( !aTmp ){ *pRc = SQLITE_NOMEM; res = 0; }else{ char *aPoslist = p->pPhrase->doclist.pList; @@ -193444,16 +152272,16 @@ } /* ** This function is a helper function for sqlite3Fts3EvalTestDeferred(). ** Assuming no error occurs or has occurred, It returns non-zero if the -** expression passed as the second argument matches the row that pCsr +** expression passed as the second argument matches the row that pCsr ** currently points to, or zero if it does not. ** ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** If an error occurs during execution of this function, *pRc is set to -** the appropriate SQLite error code. In this case the returned value is +** If an error occurs during execution of this function, *pRc is set to +** the appropriate SQLite error code. In this case the returned value is ** undefined. */ static int fts3EvalTestExpr( Fts3Cursor *pCsr, /* FTS cursor handle */ Fts3Expr *pExpr, /* Expr to test. May or may not be root. */ @@ -193468,14 +152296,14 @@ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) && fts3EvalNearTest(pExpr, pRc) ); - /* If the NEAR expression does not match any rows, zero the doclist for + /* If the NEAR expression does not match any rows, zero the doclist for ** all phrases involved in the NEAR. This is because the snippet(), - ** offsets() and matchinfo() functions are not supposed to recognize - ** any instances of phrases that are part of unmatched NEAR queries. + ** offsets() and matchinfo() functions are not supposed to recognize + ** any instances of phrases that are part of unmatched NEAR queries. ** For example if this expression: ** ** ... MATCH 'a OR (b NEAR c)' ** ** is matched against a row containing: @@ -193483,12 +152311,12 @@ ** 'a b d e' ** ** then any snippet() should ony highlight the "a" term, not the "b" ** (as "b" is part of a non-matching NEAR clause). */ - if( bHit==0 - && pExpr->eType==FTSQUERY_NEAR + if( bHit==0 + && pExpr->eType==FTSQUERY_NEAR && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) ){ Fts3Expr *p; for(p=pExpr; p->pPhrase==0; p=p->pLeft){ if( p->pRight->iDocid==pCsr->iPrevId ){ @@ -193516,27 +152344,25 @@ ); break; default: { #ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( pCsr->pDeferred && (pExpr->bDeferred || ( - pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList - ))){ + if( pCsr->pDeferred + && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred) + ){ Fts3Phrase *pPhrase = pExpr->pPhrase; + assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 ); if( pExpr->bDeferred ){ fts3EvalInvalidatePoslist(pPhrase); } *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase); bHit = (pPhrase->doclist.pList!=0); pExpr->iDocid = pCsr->iPrevId; }else #endif { - bHit = ( - pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId - && pExpr->pPhrase->doclist.nList>0 - ); + bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId); } break; } } } @@ -193574,11 +152400,11 @@ /* If there are one or more deferred tokens, load the current row into ** memory and scan it to determine the position list for each deferred ** token. Then, see if this row is really a match, considering deferred ** tokens and NEAR operators (neither of which were taken into account - ** earlier, by fts3EvalNextRow()). + ** earlier, by fts3EvalNextRow()). */ if( pCsr->pDeferred ){ rc = fts3CursorSeek(0, pCsr); if( rc==SQLITE_OK ){ rc = sqlite3Fts3CacheDeferredDoclists(pCsr); @@ -193629,11 +152455,11 @@ return rc; } /* ** Restart interation for expression pExpr so that the next call to -** fts3EvalNext() visits the first row. Do not allow incremental +** fts3EvalNext() visits the first row. Do not allow incremental ** loading or merging of phrase doclists for this iteration. ** ** If *pRc is other than SQLITE_OK when this function is called, it is ** a no-op. If an error occurs within this function, *pRc is set to an ** SQLite error code before returning. @@ -193672,25 +152498,26 @@ fts3EvalRestart(pCsr, pExpr->pRight, pRc); } } /* -** After allocating the Fts3Expr.aMI[] array for each phrase in the +** After allocating the Fts3Expr.aMI[] array for each phrase in the ** expression rooted at pExpr, the cursor iterates through all rows matched ** by pExpr, calling this function for each row. This function increments ** the values in Fts3Expr.aMI[] according to the position-list currently -** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase +** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase ** expression nodes. */ -static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){ +static void fts3EvalUpdateCounts(Fts3Expr *pExpr){ if( pExpr ){ Fts3Phrase *pPhrase = pExpr->pPhrase; if( pPhrase && pPhrase->doclist.pList ){ int iCol = 0; char *p = pPhrase->doclist.pList; - do{ + assert( *p ); + while( 1 ){ u8 c = 0; int iCnt = 0; while( 0xFE & (*p | c) ){ if( (c&0x80)==0 ) iCnt++; c = *p++ & 0x80; @@ -193702,32 +152529,16 @@ pExpr->aMI[iCol*3 + 1] += iCnt; pExpr->aMI[iCol*3 + 2] += (iCnt>0); if( *p==0x00 ) break; p++; p += fts3GetVarint32(p, &iCol); - }while( iColpLeft, nCol); - fts3EvalUpdateCounts(pExpr->pRight, nCol); - } -} - -/* -** This is an sqlite3Fts3ExprIterate() callback. If the Fts3Expr.aMI[] array -** has not yet been allocated, allocate and zero it. Otherwise, just zero -** it. -*/ -static int fts3AllocateMSI(Fts3Expr *pExpr, int iPhrase, void *pCtx){ - Fts3Table *pTab = (Fts3Table*)pCtx; - UNUSED_PARAMETER(iPhrase); - if( pExpr->aMI==0 ){ - pExpr->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32)); - if( pExpr->aMI==0 ) return SQLITE_NOMEM; - } - memset(pExpr->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); - return SQLITE_OK; + } + } + + fts3EvalUpdateCounts(pExpr->pLeft); + fts3EvalUpdateCounts(pExpr->pRight); + } } /* ** Expression pExpr must be of type FTSQUERY_PHRASE. ** @@ -193747,29 +152558,34 @@ assert( pExpr->eType==FTSQUERY_PHRASE ); if( pExpr->aMI==0 ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; Fts3Expr *pRoot; /* Root of NEAR expression */ + Fts3Expr *p; /* Iterator used for several purposes */ sqlite3_int64 iPrevId = pCsr->iPrevId; sqlite3_int64 iDocid; u8 bEof; /* Find the root of the NEAR expression */ pRoot = pExpr; - while( pRoot->pParent - && (pRoot->pParent->eType==FTSQUERY_NEAR || pRoot->bDeferred) - ){ + while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){ pRoot = pRoot->pParent; } iDocid = pRoot->iDocid; bEof = pRoot->bEof; assert( pRoot->bStart ); /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */ - rc = sqlite3Fts3ExprIterate(pRoot, fts3AllocateMSI, (void*)pTab); - if( rc!=SQLITE_OK ) return rc; + for(p=pRoot; p; p=p->pLeft){ + Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight); + assert( pE->aMI==0 ); + pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32)); + if( !pE->aMI ) return SQLITE_NOMEM; + memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); + } + fts3EvalRestart(pCsr, pRoot, &rc); while( pCsr->isEof==0 && rc==SQLITE_OK ){ do { @@ -193781,17 +152597,17 @@ fts3EvalNextRow(pCsr, pRoot, &rc); pCsr->isEof = pRoot->bEof; pCsr->isRequireSeek = 1; pCsr->isMatchinfoNeeded = 1; pCsr->iPrevId = pRoot->iDocid; - }while( pCsr->isEof==0 - && pRoot->eType==FTSQUERY_NEAR - && sqlite3Fts3EvalTestDeferred(pCsr, &rc) + }while( pCsr->isEof==0 + && pRoot->eType==FTSQUERY_NEAR + && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); if( rc==SQLITE_OK && pCsr->isEof==0 ){ - fts3EvalUpdateCounts(pRoot, pTab->nColumn); + fts3EvalUpdateCounts(pRoot); } } pCsr->isEof = 0; pCsr->iPrevId = iPrevId; @@ -193798,31 +152614,30 @@ if( bEof ){ pRoot->bEof = bEof; }else{ /* Caution: pRoot may iterate through docids in ascending or descending - ** order. For this reason, even though it seems more defensive, the + ** order. For this reason, even though it seems more defensive, the ** do loop can not be written: ** ** do {...} while( pRoot->iDocidbEof==0 ); - if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB; + assert( pRoot->bEof==0 ); }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); } } return rc; } /* -** This function is used by the matchinfo() module to query a phrase +** This function is used by the matchinfo() module to query a phrase ** expression node for the following information: ** -** 1. The total number of occurrences of the phrase in each column of +** 1. The total number of occurrences of the phrase in each column of ** the FTS table (considering all rows), and ** ** 2. For each column, the number of rows in the table for which the ** column contains at least one instance of the phrase. ** @@ -193832,16 +152647,16 @@ ** aiOut[iCol*3 + 1] = Number of occurrences ** aiOut[iCol*3 + 2] = Number of rows containing at least one instance ** ** Caveats: ** -** * If a phrase consists entirely of deferred tokens, then all output +** * If a phrase consists entirely of deferred tokens, then all output ** values are set to the number of documents in the table. In other -** words we assume that very common tokens occur exactly once in each +** words we assume that very common tokens occur exactly once in each ** column of each row of the table. ** -** * If a phrase contains some deferred tokens (and some non-deferred +** * If a phrase contains some deferred tokens (and some non-deferred ** tokens), count the potential occurrence identified by considering ** the non-deferred tokens instead of actual phrase occurrences. ** ** * If the phrase is part of a NEAR expression, then only phrase instances ** that meet the NEAR constraint are included in the counts. @@ -193875,18 +152690,18 @@ return rc; } /* ** The expression pExpr passed as the second argument to this function -** must be of type FTSQUERY_PHRASE. +** must be of type FTSQUERY_PHRASE. ** ** The returned value is either NULL or a pointer to a buffer containing ** a position-list indicating the occurrences of the phrase in column iCol -** of the current row. +** of the current row. ** -** More specifically, the returned buffer contains 1 varint for each -** occurrence of the phrase in the column, stored using the normal (delta+2) +** More specifically, the returned buffer contains 1 varint for each +** occurrence of the phrase in the column, stored using the normal (delta+2) ** compression and is terminated by either an 0x01 or 0x00 byte. For example, ** if the requested column contains "a b X c d X X" and the position-list ** for 'X' is requested, the buffer returned may contain: ** ** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00 @@ -193904,11 +152719,11 @@ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; char *pIter; int iThis; sqlite3_int64 iDocid; - /* If this phrase is applies specifically to some column other than + /* If this phrase is applies specifically to some column other than ** column iCol, return a NULL pointer. */ *ppOut = 0; assert( iCol>=0 && iColnColumn ); if( (pPhrase->iColumnnColumn && pPhrase->iColumn!=iCol) ){ return SQLITE_OK; @@ -193921,15 +152736,14 @@ int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ int bOr = 0; u8 bTreeEof = 0; Fts3Expr *p; /* Used to iterate from pExpr to root */ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ - Fts3Expr *pRun; /* Closest non-deferred ancestor of pNear */ int bMatch; - /* Check if this phrase descends from an OR expression node. If not, - ** return NULL. Otherwise, the entry that corresponds to docid + /* Check if this phrase descends from an OR expression node. If not, + ** return NULL. Otherwise, the entry that corresponds to docid ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the ** tree that the node is part of has been marked as EOF, but the node ** itself is not EOF, then it may point to an earlier entry. */ pNear = pExpr; for(p=pExpr->pParent; p; p=p->pParent){ @@ -193936,34 +152750,26 @@ if( p->eType==FTSQUERY_OR ) bOr = 1; if( p->eType==FTSQUERY_NEAR ) pNear = p; if( p->bEof ) bTreeEof = 1; } if( bOr==0 ) return SQLITE_OK; - pRun = pNear; - while( pRun->bDeferred ){ - assert( pRun->pParent ); - pRun = pRun->pParent; - } /* This is the descendent of an OR node. In this case we cannot use ** an incremental phrase. Load the entire doclist for the phrase ** into memory in this case. */ if( pPhrase->bIncr ){ - int bEofSave = pRun->bEof; - fts3EvalRestart(pCsr, pRun, &rc); - while( rc==SQLITE_OK && !pRun->bEof ){ - fts3EvalNextRow(pCsr, pRun, &rc); - if( bEofSave==0 && pRun->iDocid==iDocid ) break; + int bEofSave = pNear->bEof; + fts3EvalRestart(pCsr, pNear, &rc); + while( rc==SQLITE_OK && !pNear->bEof ){ + fts3EvalNextRow(pCsr, pNear, &rc); + if( bEofSave==0 && pNear->iDocid==iDocid ) break; } assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); - if( rc==SQLITE_OK && pRun->bEof!=bEofSave ){ - rc = FTS_CORRUPT_VTAB; - } } if( bTreeEof ){ - while( rc==SQLITE_OK && !pRun->bEof ){ - fts3EvalNextRow(pCsr, pRun, &rc); + while( rc==SQLITE_OK && !pNear->bEof ){ + fts3EvalNextRow(pCsr, pNear, &rc); } } if( rc!=SQLITE_OK ) return rc; bMatch = 1; @@ -193981,20 +152787,20 @@ if( pCsr->bDesc==bDescDoclist ){ bEof = !pPh->doclist.nAll || (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ sqlite3Fts3DoclistNext( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, + bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, &pIter, &iDocid, &bEof ); } }else{ bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ int dummy; sqlite3Fts3DoclistPrev( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, + bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, &pIter, &iDocid, &dummy, &bEof ); } } pPh->pOrPoslist = pIter; @@ -194058,19 +152864,19 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){ return SQLITE_CORRUPT_VTAB; } #endif -#if !defined(SQLITE_CORE) +#if !SQLITE_CORE /* ** Initialize API pointer table, if required. */ #ifdef _WIN32 __declspec(dllexport) #endif SQLITE_API int sqlite3_fts3_init( - sqlite3 *db, + sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3Fts3Init(db); @@ -194147,11 +152953,11 @@ ){ char const *zDb; /* Name of database (e.g. "main") */ char const *zFts3; /* Name of fts3 table */ int nDb; /* Result of strlen(zDb) */ int nFts3; /* Result of strlen(zFts3) */ - sqlite3_int64 nByte; /* Bytes of space to allocate here */ + int nByte; /* Bytes of space to allocate here */ int rc; /* value returned by declare_vtab() */ Fts3auxTable *p; /* Virtual table object to return */ UNUSED_PARAMETER(pUnused); @@ -194160,15 +152966,15 @@ ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table); ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table); */ if( argc!=4 && argc!=5 ) goto bad_args; - zDb = argv[1]; + zDb = argv[1]; nDb = (int)strlen(zDb); if( argc==5 ){ if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){ - zDb = argv[3]; + zDb = argv[3]; nDb = (int)strlen(zDb); zFts3 = argv[4]; }else{ goto bad_args; } @@ -194179,11 +152985,11 @@ rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA); if( rc!=SQLITE_OK ) return rc; nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; - p = (Fts3auxTable *)sqlite3_malloc64(nByte); + p = (Fts3auxTable *)sqlite3_malloc(nByte); if( !p ) return SQLITE_NOMEM; memset(p, 0, nByte); p->pFts3Tab = (Fts3Table *)&p[1]; p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1]; @@ -194228,11 +153034,11 @@ /* ** xBestIndex - Analyze a WHERE and ORDER BY clause. */ static int fts3auxBestIndexMethod( - sqlite3_vtab *pVTab, + sqlite3_vtab *pVTab, sqlite3_index_info *pInfo ){ int i; int iEq = -1; int iGe = -1; @@ -194241,18 +153047,18 @@ int iNext = 1; /* Next free argvIndex value */ UNUSED_PARAMETER(pVTab); /* This vtab delivers always results in "ORDER BY term ASC" order. */ - if( pInfo->nOrderBy==1 - && pInfo->aOrderBy[0].iColumn==0 + if( pInfo->nOrderBy==1 + && pInfo->aOrderBy[0].iColumn==0 && pInfo->aOrderBy[0].desc==0 ){ pInfo->orderByConsumed = 1; } - /* Search for equality and range constraints on the "term" column. + /* Search for equality and range constraints on the "term" column. ** And equality constraints on the hidden "languageid" column. */ for(i=0; inConstraint; i++){ if( pInfo->aConstraint[i].usable ){ int op = pInfo->aConstraint[i].op; int iCol = pInfo->aConstraint[i].iColumn; @@ -194329,15 +153135,15 @@ } static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){ if( nSize>pCsr->nStat ){ struct Fts3auxColstats *aNew; - aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat, + aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat, sizeof(struct Fts3auxColstats) * nSize ); if( aNew==0 ) return SQLITE_NOMEM; - memset(&aNew[pCsr->nStat], 0, + memset(&aNew[pCsr->nStat], 0, sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat) ); pCsr->aStat = aNew; pCsr->nStat = nSize; } @@ -194378,11 +153184,10 @@ } if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM; memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat); iCol = 0; - rc = SQLITE_OK; while( iaStat[iCol+1].nDoc++; eState = 2; break; } } pCsr->iCol = 0; + rc = SQLITE_OK; }else{ pCsr->isEof = 1; } return rc; } @@ -194491,11 +153293,10 @@ /* In case this cursor is being reused, close and zero it. */ testcase(pCsr->filter.zTerm); sqlite3Fts3SegReaderFinish(&pCsr->csr); sqlite3_free((void *)pCsr->filter.zTerm); sqlite3_free(pCsr->aStat); - sqlite3_free(pCsr->zStop); memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr); pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; @@ -194502,21 +153303,21 @@ if( iEq>=0 || iGe>=0 ){ const unsigned char *zStr = sqlite3_value_text(apVal[0]); assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) ); if( zStr ){ pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); + pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]); if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; - pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm); } } if( iLe>=0 ){ pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe])); + pCsr->nStop = sqlite3_value_bytes(apVal[iLe]); if( pCsr->zStop==0 ) return SQLITE_NOMEM; - pCsr->nStop = (int)strlen(pCsr->zStop); } - + if( iLangid>=0 ){ iLangVal = sqlite3_value_int(apVal[iLangid]); /* If the user specified a negative value for the languageid, use zero ** instead. This works, as the "languageid=?" constraint will also @@ -194625,13 +153426,11 @@ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ + 0 /* xRollbackTo */ }; int rc; /* Return code */ rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0); return rc; @@ -194652,37 +153451,37 @@ ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This module contains code that implements a parser for fts3 query strings -** (the right-hand argument to the MATCH operator). Because the supported +** (the right-hand argument to the MATCH operator). Because the supported ** syntax is relatively simple, the whole tokenizer/parser system is -** hand-coded. +** hand-coded. */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* -** By default, this module parses the legacy syntax that has been +** By default, this module parses the legacy syntax that has been ** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS ** is defined, then it uses the new syntax. The differences between ** the new and the old syntaxes are: ** ** a) The new syntax supports parenthesis. The old does not. ** ** b) The new syntax supports the AND and NOT operators. The old does not. ** -** c) The old syntax supports the "-" token qualifier. This is not +** c) The old syntax supports the "-" token qualifier. This is not ** supported by the new syntax (it is replaced by the NOT operator). ** ** d) When using the old syntax, the OR operator has a greater precedence ** than an implicit AND. When using the new, both implicity and explicit ** AND operators have a higher precedence than OR. ** ** If compiled with SQLITE_TEST defined, then this module exports the ** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable -** to zero causes the module to use the old syntax. If it is set to +** to zero causes the module to use the old syntax. If it is set to ** non-zero the new syntax is activated. This is so both syntaxes can ** be tested using a single build of testfixture. ** ** The following describes the syntax supported by the fts3 MATCH ** operator in a similar format to that used by the lemon parser @@ -194707,11 +153506,11 @@ */ #ifdef SQLITE_TEST SQLITE_API int sqlite3_fts3_enable_parentheses = 0; #else -# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS +# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS # define sqlite3_fts3_enable_parentheses 1 # else # define sqlite3_fts3_enable_parentheses 0 # endif #endif @@ -194725,11 +153524,11 @@ /* #include */ /* ** isNot: ** This variable is used by function getNextNode(). When getNextNode() is -** called, it sets ParseContext.isNot to true if the 'next node' is a +** called, it sets ParseContext.isNot to true if the 'next node' is a ** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the ** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to ** zero. */ typedef struct ParseContext ParseContext; @@ -194744,11 +153543,11 @@ sqlite3_context *pCtx; /* Write error message here */ int nNest; /* Number of nested brackets */ }; /* -** This function is equivalent to the standard isspace() function. +** This function is equivalent to the standard isspace() function. ** ** The standard isspace() can be awkward to use safely, because although it ** is defined to accept an argument of type int, its behavior when passed ** an integer that falls outside of the range of the unsigned char type ** is undefined (and sometimes, "undefined" means segfault). This wrapper @@ -194760,15 +153559,15 @@ return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; } /* ** Allocate nByte bytes of memory using sqlite3_malloc(). If successful, -** zero the memory before returning a pointer to it. If unsuccessful, +** zero the memory before returning a pointer to it. If unsuccessful, ** return NULL. */ -SQLITE_PRIVATE void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){ - void *pRet = sqlite3_malloc64(nByte); +static void *fts3MallocZero(int nByte){ + void *pRet = sqlite3_malloc(nByte); if( pRet ) memset(pRet, 0, nByte); return pRet; } SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer( @@ -194808,11 +153607,11 @@ ** Extract the next token from buffer z (length n) using the tokenizer ** and other information (column names etc.) in pParse. Create an Fts3Expr ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this ** single token and set *ppExpr to point to it. If the end of the buffer is ** reached before a token is found, set *ppExpr to zero. It is the -** responsibility of the caller to eventually deallocate the allocated +** responsibility of the caller to eventually deallocate the allocated ** Fts3Expr structure (if any) by passing it to sqlite3_free(). ** ** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation ** fails. */ @@ -194839,16 +153638,16 @@ *pnConsumed = i; rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; - sqlite3_int64 nByte; /* total space to allocate */ + int nByte; /* total space to allocate */ rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); if( rc==SQLITE_OK ){ nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; - pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte); + pRet = (Fts3Expr *)fts3MallocZero(nByte); if( !pRet ){ rc = SQLITE_NOMEM; }else{ pRet->eType = FTSQUERY_PHRASE; pRet->pPhrase = (Fts3Phrase *)&pRet[1]; @@ -194862,12 +153661,12 @@ pRet->pPhrase->aToken[0].isPrefix = 1; iEnd++; } while( 1 ){ - if( !sqlite3_fts3_enable_parentheses - && iStart>0 && z[iStart-1]=='-' + if( !sqlite3_fts3_enable_parentheses + && iStart>0 && z[iStart-1]=='-' ){ pParse->isNot = 1; iStart--; }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){ pRet->pPhrase->aToken[0].bFirst = 1; @@ -194883,22 +153682,22 @@ rc = SQLITE_OK; } pModule->xClose(pCursor); } - + *ppExpr = pRet; return rc; } /* ** Enlarge a memory allocation. If an out-of-memory allocation occurs, ** then free the old allocation. */ -static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){ - void *pRet = sqlite3_realloc64(pOrig, nNew); +static void *fts3ReallocOrFree(void *pOrig, int nNew){ + void *pRet = sqlite3_realloc(pOrig, nNew); if( !pRet ){ sqlite3_free(pOrig); } return pRet; } @@ -194905,11 +153704,11 @@ /* ** Buffer zInput, length nInput, contains the contents of a quoted string ** that appeared as part of an fts3 query expression. Neither quote character ** is included in the buffer. This function attempts to tokenize the entire -** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE +** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE ** containing the results. ** ** If successful, SQLITE_OK is returned and *ppExpr set to point at the ** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory ** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set @@ -194930,20 +153729,20 @@ const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase); int nToken = 0; /* The final Fts3Expr data structure, including the Fts3Phrase, - ** Fts3PhraseToken structures token buffers are all stored as a single + ** Fts3PhraseToken structures token buffers are all stored as a single ** allocation so that the expression can be freed with a single call to ** sqlite3_free(). Setting this up requires a two pass approach. ** ** The first pass, in the block below, uses a tokenizer cursor to iterate ** through the tokens in the expression. This pass uses fts3ReallocOrFree() ** to assemble data in two dynamic buffers: ** ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase - ** structure, followed by the array of Fts3PhraseToken + ** structure, followed by the array of Fts3PhraseToken ** structures. This pass only populates the Fts3PhraseToken array. ** ** Buffer zTemp: Contains copies of all tokens. ** ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, @@ -194960,15 +153759,14 @@ rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); if( rc==SQLITE_OK ){ Fts3PhraseToken *pToken; p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken)); + if( !p ) goto no_mem; + zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte); - if( !zTemp || !p ){ - rc = SQLITE_NOMEM; - goto getnextstring_out; - } + if( !zTemp ) goto no_mem; assert( nToken==ii ); pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii]; memset(pToken, 0, sizeof(Fts3PhraseToken)); @@ -194979,55 +153777,57 @@ pToken->isPrefix = (iEndbFirst = (iBegin>0 && zInput[iBegin-1]=='^'); nToken = ii+1; } } + + pModule->xClose(pCursor); + pCursor = 0; } if( rc==SQLITE_DONE ){ int jj; char *zBuf = 0; p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp); - if( !p ){ - rc = SQLITE_NOMEM; - goto getnextstring_out; - } + if( !p ) goto no_mem; memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p); p->eType = FTSQUERY_PHRASE; p->pPhrase = (Fts3Phrase *)&p[1]; p->pPhrase->iColumn = pParse->iDefaultCol; p->pPhrase->nToken = nToken; zBuf = (char *)&p->pPhrase->aToken[nToken]; - assert( nTemp==0 || zTemp ); if( zTemp ){ memcpy(zBuf, zTemp, nTemp); + sqlite3_free(zTemp); + }else{ + assert( nTemp==0 ); } for(jj=0; jjpPhrase->nToken; jj++){ p->pPhrase->aToken[jj].z = zBuf; zBuf += p->pPhrase->aToken[jj].n; } rc = SQLITE_OK; } - getnextstring_out: + *ppExpr = p; + return rc; +no_mem: + if( pCursor ){ pModule->xClose(pCursor); } sqlite3_free(zTemp); - if( rc!=SQLITE_OK ){ - sqlite3_free(p); - p = 0; - } - *ppExpr = p; - return rc; + sqlite3_free(p); + *ppExpr = 0; + return SQLITE_NOMEM; } /* -** The output variable *ppExpr is populated with an allocated Fts3Expr +** The output variable *ppExpr is populated with an allocated Fts3Expr ** structure, or set to 0 if the end of the input buffer is reached. ** ** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM ** if a malloc failure occurs, or SQLITE_ERROR if a parse error is encountered. ** If SQLITE_ERROR is returned, pContext is populated with an error message. @@ -195059,11 +153859,11 @@ int nInput = n; pParse->isNot = 0; /* Skip over any whitespace before checking for a keyword, an open or - ** close bracket, or a quoted string. + ** close bracket, or a quoted string. */ while( nInput>0 && fts3isspace(*zInput) ){ nInput--; zInput++; } @@ -195086,23 +153886,26 @@ /* If this is a "NEAR" keyword, check for an explicit nearness. */ if( pKey->eType==FTSQUERY_NEAR ){ assert( nKey==4 ); if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){ - nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear); + nNear = 0; + for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){ + nNear = nNear * 10 + (zInput[nKey] - '0'); + } } } /* At this point this is probably a keyword. But for that to be true, ** the next byte must contain either whitespace, an open or close - ** parenthesis, a quote character, or EOF. + ** parenthesis, a quote character, or EOF. */ cNext = zInput[nKey]; - if( fts3isspace(cNext) + if( fts3isspace(cNext) || cNext=='"' || cNext=='(' || cNext==')' || cNext==0 ){ - pRet = (Fts3Expr *)sqlite3Fts3MallocZero(sizeof(Fts3Expr)); + pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr)); if( !pRet ){ return SQLITE_NOMEM; } pRet->eType = pKey->eType; pRet->nNear = nNear; @@ -195133,16 +153936,12 @@ if( sqlite3_fts3_enable_parentheses ){ if( *zInput=='(' ){ int nConsumed = 0; pParse->nNest++; -#if !defined(SQLITE_MAX_EXPR_DEPTH) - if( pParse->nNest>1000 ) return SQLITE_ERROR; -#elif SQLITE_MAX_EXPR_DEPTH>0 - if( pParse->nNest>SQLITE_MAX_EXPR_DEPTH ) return SQLITE_ERROR; -#endif rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed); + if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; } *pnConsumed = (int)(zInput - z) + 1 + nConsumed; return rc; }else if( *zInput==')' ){ pParse->nNest--; *pnConsumed = (int)((zInput - z) + 1); @@ -195149,28 +153948,28 @@ *ppExpr = 0; return SQLITE_DONE; } } - /* If control flows to this point, this must be a regular token, or + /* If control flows to this point, this must be a regular token, or ** the end of the input. Read a regular token using the sqlite3_tokenizer ** interface. Before doing so, figure out if there is an explicit - ** column specifier for the token. + ** column specifier for the token. ** ** TODO: Strangely, it is not possible to associate a column specifier ** with a quoted phrase, only with a single token. Not sure if this was ** an implementation artifact or an intentional decision when fts3 was - ** first implemented. Whichever it was, this module duplicates the + ** first implemented. Whichever it was, this module duplicates the ** limitation. */ iCol = pParse->iDefaultCol; iColLen = 0; for(ii=0; iinCol; ii++){ const char *zStr = pParse->azCol[ii]; int nStr = (int)strlen(zStr); - if( nInput>nStr && zInput[nStr]==':' - && sqlite3_strnicmp(zStr, zInput, nStr)==0 + if( nInput>nStr && zInput[nStr]==':' + && sqlite3_strnicmp(zStr, zInput, nStr)==0 ){ iCol = ii; iColLen = (int)((zInput - z) + nStr + 1); break; } @@ -195211,11 +154010,11 @@ assert( p->eType==FTSQUERY_AND ); return 3; } /* -** Argument ppHead contains a pointer to the current head of a query +** Argument ppHead contains a pointer to the current head of a query ** expression tree being parsed. pPrev is the expression node most recently ** inserted into the tree. This function adds pNew, which is always a binary ** operator node, into the expression tree based on the relative precedence ** of pNew and the existing nodes of the tree. This may result in the head ** of the tree changing, in which case *ppHead is set to the new root node. @@ -195241,11 +154040,11 @@ pSplit->pParent = pNew; } /* ** Parse the fts3 query expression found in buffer z, length n. This function -** returns either when the end of the buffer is reached or an unmatched +** returns either when the end of the buffer is reached or an unmatched ** closing bracket - ')' - is encountered. ** ** If successful, SQLITE_OK is returned, *ppExpr is set to point to the ** parsed form of the expression and *pnConsumed is set to the number of ** bytes read from buffer z. Otherwise, *ppExpr is set to 0 and SQLITE_NOMEM @@ -195273,15 +154072,15 @@ assert( nByte>0 || (rc!=SQLITE_OK && p==0) ); if( rc==SQLITE_OK ){ if( p ){ int isPhrase; - if( !sqlite3_fts3_enable_parentheses - && p->eType==FTSQUERY_PHRASE && pParse->isNot + if( !sqlite3_fts3_enable_parentheses + && p->eType==FTSQUERY_PHRASE && pParse->isNot ){ /* Create an implicit NOT operator. */ - Fts3Expr *pNot = sqlite3Fts3MallocZero(sizeof(Fts3Expr)); + Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr)); if( !pNot ){ sqlite3Fts3ExprFree(p); rc = SQLITE_NOMEM; goto exprparse_out; } @@ -195311,11 +154110,11 @@ if( isPhrase && !isRequirePhrase ){ /* Insert an implicit AND operator. */ Fts3Expr *pAnd; assert( pRet && pPrev ); - pAnd = sqlite3Fts3MallocZero(sizeof(Fts3Expr)); + pAnd = fts3MallocZero(sizeof(Fts3Expr)); if( !pAnd ){ sqlite3Fts3ExprFree(p); rc = SQLITE_NOMEM; goto exprparse_out; } @@ -195395,17 +154194,17 @@ *ppExpr = pRet; return rc; } /* -** Return SQLITE_ERROR if the maximum depth of the expression tree passed +** Return SQLITE_ERROR if the maximum depth of the expression tree passed ** as the only argument is more than nMaxDepth. */ static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){ int rc = SQLITE_OK; if( p ){ - if( nMaxDepth<0 ){ + if( nMaxDepth<0 ){ rc = SQLITE_TOOBIG; }else{ rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1); if( rc==SQLITE_OK ){ rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1); @@ -195416,16 +154215,16 @@ } /* ** This function attempts to transform the expression tree at (*pp) to ** an equivalent but more balanced form. The tree is modified in place. -** If successful, SQLITE_OK is returned and (*pp) set to point to the -** new root expression node. +** If successful, SQLITE_OK is returned and (*pp) set to point to the +** new root expression node. ** ** nMaxDepth is the maximum allowable depth of the balanced sub-tree. ** -** Otherwise, if an error occurs, an SQLite error code is returned and +** Otherwise, if an error occurs, an SQLite error code is returned and ** expression (*pp) freed. */ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){ int rc = SQLITE_OK; /* Return code */ Fts3Expr *pRoot = *pp; /* Initial root node */ @@ -195437,11 +154236,11 @@ } if( rc==SQLITE_OK ){ if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ Fts3Expr **apLeaf; - apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth); + apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth); if( 0==apLeaf ){ rc = SQLITE_NOMEM; }else{ memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); } @@ -195536,11 +154335,11 @@ } } } pRoot = p; }else{ - /* An error occurred. Delete the contents of the apLeaf[] array + /* An error occurred. Delete the contents of the apLeaf[] array ** and pFree list. Everything else is cleaned up by the call to ** sqlite3Fts3ExprFree(pRoot) below. */ Fts3Expr *pDel; for(i=0; ipRight = pRight; pRight->pParent = pRoot; } } } - + if( rc!=SQLITE_OK ){ sqlite3Fts3ExprFree(pRoot); pRoot = 0; } *pp = pRoot; @@ -195592,13 +154391,13 @@ /* ** This function is similar to sqlite3Fts3ExprParse(), with the following ** differences: ** ** 1. It does not do expression rebalancing. -** 2. It does not check that the expression does not exceed the +** 2. It does not check that the expression does not exceed the ** maximum allowable depth. -** 3. Even if it fails, *ppExpr may still be set to point to an +** 3. Even if it fails, *ppExpr may still be set to point to an ** expression tree. It should be deleted using sqlite3Fts3ExprFree() ** in this case. */ static int fts3ExprParseUnbalanced( sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ @@ -195633,11 +154432,11 @@ /* Check for mismatched parenthesis */ if( rc==SQLITE_OK && sParse.nNest ){ rc = SQLITE_ERROR; } - + return rc; } /* ** Parameters z and n contain a pointer to and length of a buffer containing @@ -195652,11 +154451,11 @@ ** nul-terminated string and the length is determined using strlen(). ** ** The first parameter, pTokenizer, is passed the fts3 tokenizer module to ** use to normalize query tokens while parsing the expression. The azCol[] ** array, which is assumed to contain nCol entries, should contain the names -** of each column in the target fts3 table, in order from left to right. +** of each column in the target fts3 table, in order from left to right. ** Column names must be nul-terminated strings. ** ** The iDefaultCol parameter should be passed the index of the table column ** that appears on the left-hand-side of the MATCH operator (the default ** column to match against for tokens for which a column name is not explicitly @@ -195675,11 +154474,11 @@ char **pzErr /* OUT: Error message (sqlite3_malloc) */ ){ int rc = fts3ExprParseUnbalanced( pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr ); - + /* Rebalance the expression. And check that its depth does not exceed ** SQLITE_FTS3_MAX_EXPR_DEPTH. */ if( rc==SQLITE_OK && *ppExpr ){ rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH); if( rc==SQLITE_OK ){ @@ -195690,11 +154489,11 @@ if( rc!=SQLITE_OK ){ sqlite3Fts3ExprFree(*ppExpr); *ppExpr = 0; if( rc==SQLITE_TOOBIG ){ sqlite3Fts3ErrMsg(pzErr, - "FTS expression tree is too large (maximum depth %d)", + "FTS expression tree is too large (maximum depth %d)", SQLITE_FTS3_MAX_EXPR_DEPTH ); rc = SQLITE_ERROR; }else if( rc==SQLITE_ERROR ){ sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z); @@ -195748,19 +154547,47 @@ */ #ifdef SQLITE_TEST /* #include */ + +/* +** Function to query the hash-table of tokenizers (see README.tokenizers). +*/ +static int queryTestTokenizer( + sqlite3 *db, + const char *zName, + const sqlite3_tokenizer_module **pp +){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts3_tokenizer(?)"; + + *pp = 0; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ + memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); + } + } + + return sqlite3_finalize(pStmt); +} /* ** Return a pointer to a buffer containing a text representation of the ** expression passed as the first argument. The buffer is obtained from -** sqlite3_malloc(). It is the responsibility of the caller to use +** sqlite3_malloc(). It is the responsibility of the caller to use ** sqlite3_free() to release the memory. If an OOM condition is encountered, ** NULL is returned. ** -** If the second argument is not NULL, then its contents are prepended to +** If the second argument is not NULL, then its contents are prepended to ** the returned expression text and then freed using sqlite3_free(). */ static char *exprToString(Fts3Expr *pExpr, char *zBuf){ if( pExpr==0 ){ return sqlite3_mprintf(""); @@ -195770,11 +154597,11 @@ Fts3Phrase *pPhrase = pExpr->pPhrase; int i; zBuf = sqlite3_mprintf( "%zPHRASE %d 0", zBuf, pPhrase->iColumn); for(i=0; zBuf && inToken; i++){ - zBuf = sqlite3_mprintf("%z %.*s%s", zBuf, + zBuf = sqlite3_mprintf("%z %.*s%s", zBuf, pPhrase->aToken[i].n, pPhrase->aToken[i].z, (pPhrase->aToken[i].isPrefix?"+":"") ); } return zBuf; @@ -195803,11 +154630,11 @@ return zBuf; } /* -** This is the implementation of a scalar SQL function used to test the +** This is the implementation of a scalar SQL function used to test the ** expression parser. It should be called as follows: ** ** fts3_exprtest(, , , ...); ** ** The first argument, , is the name of the fts3 tokenizer used @@ -195816,61 +154643,65 @@ ** of a column of the fts3 table that the query expression may refer to. ** For example: ** ** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); */ -static void fts3ExprTestCommon( - int bRebalance, +static void fts3ExprTest( sqlite3_context *context, int argc, sqlite3_value **argv ){ + sqlite3_tokenizer_module const *pModule = 0; sqlite3_tokenizer *pTokenizer = 0; int rc; char **azCol = 0; const char *zExpr; int nExpr; int nCol; int ii; Fts3Expr *pExpr; char *zBuf = 0; - Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); - const char *zTokenizer = 0; - char *zErr = 0; + sqlite3 *db = sqlite3_context_db_handle(context); if( argc<3 ){ - sqlite3_result_error(context, + sqlite3_result_error(context, "Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1 ); return; } - zTokenizer = (const char*)sqlite3_value_text(argv[0]); - rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_error(context, zErr, -1); - } - sqlite3_free(zErr); - return; - } + rc = queryTestTokenizer(db, + (const char *)sqlite3_value_text(argv[0]), &pModule); + if( rc==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + goto exprtest_out; + }else if( !pModule ){ + sqlite3_result_error(context, "No such tokenizer module", -1); + goto exprtest_out; + } + + rc = pModule->xCreate(0, 0, &pTokenizer); + assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); + if( rc==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + goto exprtest_out; + } + pTokenizer->pModule = pModule; zExpr = (const char *)sqlite3_value_text(argv[1]); nExpr = sqlite3_value_bytes(argv[1]); nCol = argc-2; - azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *)); + azCol = (char **)sqlite3_malloc(nCol*sizeof(char *)); if( !azCol ){ sqlite3_result_error_nomem(context); goto exprtest_out; } for(ii=0; iipModule->xDestroy(pTokenizer); + if( pModule && pTokenizer ){ + rc = pModule->xDestroy(pTokenizer); } sqlite3_free(azCol); } -static void fts3ExprTest( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3ExprTestCommon(0, context, argc, argv); -} -static void fts3ExprTestRebalance( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3ExprTestCommon(1, context, argc, argv); -} - /* -** Register the query expression parser test function fts3_exprtest() -** with database connection db. +** Register the query expression parser test function fts3_exprtest() +** with database connection db. */ -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ +SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ int rc = sqlite3_create_function( - db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 + db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 ); if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", - -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 + rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", + -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 ); } return rc; } @@ -195971,12 +154787,12 @@ /* #include "fts3_hash.h" */ /* ** Malloc and Free functions */ -static void *fts3HashMalloc(sqlite3_int64 n){ - void *p = sqlite3_malloc64(n); +static void *fts3HashMalloc(int n){ + void *p = sqlite3_malloc(n); if( p ){ memset(p, 0, n); } return p; } @@ -195986,12 +154802,12 @@ /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** ** "pNew" is a pointer to the hash table that is to be initialized. -** keyClass is one of the constants -** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass +** keyClass is one of the constants +** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass ** determines what kind of key the hash table will use. "copyKey" is ** true if the hash table should make its own private copy of keys and ** false if it should just use the supplied pointer. */ SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){ @@ -196064,11 +154880,11 @@ } /* ** Return a pointer to the appropriate hash function given the key class. ** -** The C syntax in this function definition may be unfamilar to some +** The C syntax in this function definition may be unfamilar to some ** programmers, so we provide the following additional explanation: ** ** The name of the function is "ftsHashFunction". The function takes a ** single parameter "keyClass". The return value of ftsHashFunction() ** is a pointer to another function. Specifically, the return value @@ -196124,11 +154940,11 @@ pEntry->chain = pNew; } /* Resize the hash table so that it cantains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail +** "new_size" must be a power of 2. The hash table might fail ** to resize if sqliteMalloc() fails. ** ** Return non-zero if a memory allocation error occurs. */ static int fts3Rehash(Fts3Hash *pH, int new_size){ @@ -196169,11 +154985,11 @@ struct _fts3ht *pEntry = &pH->ht[h]; elem = pEntry->chain; count = pEntry->count; xCompare = ftsCompareFunction(pH->keyClass); while( count-- && elem ){ - if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ return elem; } elem = elem->next; } } @@ -196188,11 +155004,11 @@ Fts3HashElem* elem, /* The element to be removed from the pH */ int h /* Hash value for the element */ ){ struct _fts3ht *pEntry; if( elem->prev ){ - elem->prev->next = elem->next; + elem->prev->next = elem->next; }else{ pH->first = elem->next; } if( elem->next ){ elem->next->prev = elem->prev; @@ -196216,12 +155032,12 @@ fts3HashClear(pH); } } SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem( - const Fts3Hash *pH, - const void *pKey, + const Fts3Hash *pH, + const void *pKey, int nKey ){ int h; /* A hash on key */ int (*xHash)(const void*,int); /* The hash function */ @@ -196231,11 +155047,11 @@ h = (*xHash)(pKey,nKey); assert( (pH->htsize & (pH->htsize-1))==0 ); return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1)); } -/* +/* ** Attempt to locate an element of the hash table pH with a key ** that matches pKey,nKey. Return the data for this element if it is ** found, or NULL if there is no match. */ SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){ @@ -196405,11 +155221,11 @@ } /* ** Prepare to begin tokenizing a particular string. The input ** string to be tokenized is zInput[0..nInput-1]. A cursor -** used to incrementally tokenize this string is returned in +** used to incrementally tokenize this string is returned in ** *ppCursor. */ static int porterOpen( sqlite3_tokenizer *pTokenizer, /* The tokenizer */ const char *zInput, int nInput, /* String to be tokenized */ @@ -196458,11 +155274,11 @@ }; /* ** isConsonant() and isVowel() determine if their first character in ** the string they point to is a consonant or a vowel, according -** to Porter ruls. +** to Porter ruls. ** ** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. ** 'Y' is a consonant unless it follows another consonant, ** in which case it is a vowel. ** @@ -196578,15 +155394,15 @@ isConsonant(z+2); } /* ** If the word ends with zFrom and xCond() is true for the stem -** of the word that preceeds the zFrom ending, then change the +** of the word that preceeds the zFrom ending, then change the ** ending to zTo. ** ** The input word *pz and zFrom are both in reverse order. zTo -** is in normal order. +** is in normal order. ** ** Return TRUE if zFrom matches. Return FALSE if zFrom does not ** match. Not that TRUE is returned even if xCond() fails and ** no substitution occurs. */ @@ -196651,13 +155467,13 @@ ** Words that are longer than about 20 bytes are stemmed by retaining ** a few bytes from the beginning and the end of the word. If the ** word contains digits, 3 bytes are taken from the beginning and ** 3 bytes from the end. For long words without digits, 10 bytes ** are taken from each end. US-ASCII case folding still applies. -** -** If the input word contains not digits but does characters not -** in [a-zA-Z] then no stemming is attempted and this routine just +** +** If the input word contains not digits but does characters not +** in [a-zA-Z] then no stemming is attempted and this routine just ** copies the input into the input into the output with US-ASCII ** case folding. ** ** Stemming never increases the length of the word. So there is ** no chance of overflowing the zOut buffer. @@ -196698,15 +155514,15 @@ ){ z++; } } - /* Step 1b */ + /* Step 1b */ z2 = z; if( stem(&z, "dee", "ee", m_gt_0) ){ /* Do nothing. The work was all in the test */ - }else if( + }else if( (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) && z!=z2 ){ if( stem(&z, "ta", "ate", 0) || stem(&z, "lb", "ble", 0) || @@ -196741,11 +155557,11 @@ break; case 'g': stem(&z, "igol", "log", m_gt_0); break; case 'l': - if( !stem(&z, "ilb", "ble", m_gt_0) + if( !stem(&z, "ilb", "ble", m_gt_0) && !stem(&z, "illa", "al", m_gt_0) && !stem(&z, "iltne", "ent", m_gt_0) && !stem(&z, "ile", "e", m_gt_0) ){ stem(&z, "ilsuo", "ous", m_gt_0); @@ -196943,11 +155759,11 @@ if( c->iOffset>iStartOffset ){ int n = c->iOffset-iStartOffset; if( n>c->nAllocated ){ char *pNew; c->nAllocated = n+20; - pNew = sqlite3_realloc64(c->zToken, c->nAllocated); + pNew = sqlite3_realloc(c->zToken, c->nAllocated); if( !pNew ) return SQLITE_NOMEM; c->zToken = pNew; } porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); *pzToken = c->zToken; @@ -197029,11 +155845,11 @@ sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,-1,&isEnabled); return isEnabled; } /* -** Implementation of the SQL scalar function for accessing the underlying +** Implementation of the SQL scalar function for accessing the underlying ** hash table. This function may be called as follows: ** ** SELECT (); ** SELECT (, ); ** @@ -197066,11 +155882,11 @@ zName = sqlite3_value_text(argv[0]); nName = sqlite3_value_bytes(argv[0])+1; if( argc==2 ){ - if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[1]) ){ + if( fts3TokenizerEnabled(context) ){ void *pOld; int n = sqlite3_value_bytes(argv[1]); if( zName==0 || n!=sizeof(pPtr) ){ sqlite3_result_error(context, "argument type mismatch", -1); return; @@ -197093,13 +155909,11 @@ sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); return; } } - if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[0]) ){ - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); - } + sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); } SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){ static const char isFtsIdChar[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ @@ -197183,12 +155997,12 @@ }else{ char const **aArg = 0; int iArg = 0; z = &z[n+1]; while( zxCreate(iArg, aArg, ppTok); assert( rc!=SQLITE_OK || *ppTok ); if( rc!=SQLITE_OK ){ sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer"); }else{ - (*ppTok)->pModule = m; + (*ppTok)->pModule = m; } sqlite3_free((void *)aArg); } sqlite3_free(zCopy); @@ -197213,15 +156027,19 @@ } #ifdef SQLITE_TEST -#include "tclsqlite.h" +#if defined(INCLUDE_SQLITE_TCL_H) +# include "sqlite_tcl.h" +#else +# include "tcl.h" +#endif /* #include */ /* -** Implementation of a special SQL scalar function for testing tokenizers +** Implementation of a special SQL scalar function for testing tokenizers ** designed to be used in concert with the Tcl testing framework. This ** function must be called with two or more arguments: ** ** SELECT (, ..., ); ** @@ -197229,21 +156047,21 @@ ** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') ** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test'). ** ** The return value is a string that may be interpreted as a Tcl ** list. For each token in the , three elements are -** added to the returned list. The first is the token position, the +** added to the returned list. The first is the token position, the ** second is the token text (folded, stemmed, etc.) and the third is the -** substring of associated with the token. For example, +** substring of associated with the token. For example, ** using the built-in "simple" tokenizer: ** ** SELECT fts_tokenizer_test('simple', 'I don't see how'); ** ** will return the string: ** ** "{0 i I 1 dont don't 2 see see 3 how how}" -** +** */ static void testFunc( sqlite3_context *context, int argc, sqlite3_value **argv @@ -197334,12 +156152,12 @@ Tcl_DecrRefCount(pRet); } static int registerTokenizer( - sqlite3 *db, - char *zName, + sqlite3 *db, + char *zName, const sqlite3_tokenizer_module *p ){ int rc; sqlite3_stmt *pStmt; const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; @@ -197357,12 +156175,12 @@ } static int queryTokenizer( - sqlite3 *db, - char *zName, + sqlite3 *db, + char *zName, const sqlite3_tokenizer_module **pp ){ int rc; sqlite3_stmt *pStmt; const char zSql[] = "SELECT fts3_tokenizer(?)"; @@ -197373,13 +156191,11 @@ return rc; } sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB - && sqlite3_column_bytes(pStmt, 0)==sizeof(*pp) - ){ + if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); } } return sqlite3_finalize(pStmt); @@ -197443,32 +156259,32 @@ #endif /* ** Set up SQL objects in database db used to access the contents of ** the hash table pointed to by argument pHash. The hash table must -** been initialized to use string keys, and to take a private copy +** been initialized to use string keys, and to take a private copy ** of the key when a value is inserted. i.e. by a call similar to: ** ** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); ** ** This function adds a scalar function (see header comment above ** fts3TokenizerFunc() in this file for details) and, if ENABLE_TABLE is -** defined at compilation time, a temporary virtual table (see header -** comment above struct HashTableVtab) to the database schema. Both +** defined at compilation time, a temporary virtual table (see header +** comment above struct HashTableVtab) to the database schema. Both ** provide read/write access to the contents of *pHash. ** ** The third argument to this function, zName, is used as the name ** of both the scalar and, if created, the virtual table. */ SQLITE_PRIVATE int sqlite3Fts3InitHashTable( - sqlite3 *db, - Fts3Hash *pHash, + sqlite3 *db, + Fts3Hash *pHash, const char *zName ){ int rc = SQLITE_OK; void *p = (void *)pHash; - const int any = SQLITE_UTF8|SQLITE_DIRECTONLY; + const int any = SQLITE_ANY; #ifdef SQLITE_TEST char *zTest = 0; char *zTest2 = 0; void *pdb = (void *)db; @@ -197613,11 +156429,11 @@ } /* ** Prepare to begin tokenizing a particular string. The input ** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in +** used to incrementally tokenize this string is returned in ** *ppCursor. */ static int simpleOpen( sqlite3_tokenizer *pTokenizer, /* The tokenizer */ const char *pInput, int nBytes, /* String to be tokenized */ @@ -197691,11 +156507,11 @@ if( c->iOffset>iStartOffset ){ int i, n = c->iOffset-iStartOffset; if( n>c->nTokenAllocated ){ char *pNew; c->nTokenAllocated = n+20; - pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated); + pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); if( !pNew ) return SQLITE_NOMEM; c->pToken = pNew; } for(i=0; i ** -** The virtual table module tokenizes this , using the FTS3 -** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE +** The virtual table module tokenizes this , using the FTS3 +** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE ** statement and returns one row for each token in the result. With ** fields set as follows: ** ** input: Always set to a copy of ** token: A token from the input. @@ -197838,11 +156654,11 @@ return SQLITE_OK; } /* ** The second argument, argv[], is an array of pointers to nul-terminated -** strings. This function makes a copy of the array and strings into a +** strings. This function makes a copy of the array and strings into a ** single block of memory. It then dequotes any of the strings that appear ** to be quoted. ** ** If successful, output parameter *pazDequote is set to point at the ** array of dequoted strings and SQLITE_OK is returned. The caller is @@ -197865,11 +156681,11 @@ for(i=0; i1 ) azArg = (const char * const *)&azDequote[1]; + const char * const *azArg = (const char * const *)&azDequote[1]; rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok); } if( rc==SQLITE_OK ){ pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable)); @@ -197975,20 +156790,20 @@ /* ** xBestIndex - Analyze a WHERE and ORDER BY clause. */ static int fts3tokBestIndexMethod( - sqlite3_vtab *pVTab, + sqlite3_vtab *pVTab, sqlite3_index_info *pInfo ){ int i; UNUSED_PARAMETER(pVTab); for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable - && pInfo->aConstraint[i].iColumn==0 - && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ + if( pInfo->aConstraint[i].usable + && pInfo->aConstraint[i].iColumn==0 + && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ ){ pInfo->idxNum = 1; pInfo->aConstraintUsage[i].argvIndex = 1; pInfo->aConstraintUsage[i].omit = 1; pInfo->estimatedCost = 1; @@ -198090,15 +156905,15 @@ fts3tokResetCursor(pCsr); if( idxNum==1 ){ const char *zByte = (const char *)sqlite3_value_text(apVal[0]); int nByte = sqlite3_value_bytes(apVal[0]); - pCsr->zInput = sqlite3_malloc64(nByte+1); + pCsr->zInput = sqlite3_malloc(nByte+1); if( pCsr->zInput==0 ){ rc = SQLITE_NOMEM; }else{ - if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte); + memcpy(pCsr->zInput, zByte, nByte); pCsr->zInput[nByte] = 0; rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr); if( rc==SQLITE_OK ){ pCsr->pCsr->pTokenizer = pTab->pTok; } @@ -198163,11 +156978,11 @@ /* ** Register the fts3tok module with database connection db. Return SQLITE_OK ** if successful or an error code if sqlite3_create_module() fails. */ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){ +SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ static const sqlite3_module fts3tok_module = { 0, /* iVersion */ fts3tokConnectMethod, /* xCreate */ fts3tokConnectMethod, /* xConnect */ fts3tokBestIndexMethod, /* xBestIndex */ @@ -198187,19 +157002,15 @@ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ + 0 /* xRollbackTo */ }; int rc; /* Return code */ - rc = sqlite3_create_module_v2( - db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy - ); + rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); return rc; } #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ @@ -198218,27 +157029,27 @@ ****************************************************************************** ** ** This file is part of the SQLite FTS3 extension module. Specifically, ** this file contains code to insert, update and delete rows from FTS3 ** tables. It also contains code to merge FTS3 b-tree segments. Some -** of the sub-routines used to merge segments are also used by the query +** of the sub-routines used to merge segments are also used by the query ** code in fts3.c. */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ /* #include */ /* #include */ -/* #include */ + #define FTS_MAX_APPENDABLE_HEIGHT 16 /* ** When full-text index nodes are loaded from disk, the buffer that they -** are loaded into has the following number of bytes of padding at the end +** are loaded into has the following number of bytes of padding at the end ** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer ** of 920 bytes is allocated for it. ** ** This means that if we have a pointer into a buffer containing node data, ** it is always safe to read up to two varints from it without risking an @@ -198251,14 +157062,14 @@ ** memory incrementally instead of all at once. This can be a big performance ** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext() ** method before retrieving all query results (as may happen, for example, ** if a query has a LIMIT clause). ** -** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD +** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD ** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes. -** The code is written so that the hard lower-limit for each of these values -** is 1. Clearly such small values would be inefficient, but can be useful +** The code is written so that the hard lower-limit for each of these values +** is 1. Clearly such small values would be inefficient, but can be useful ** for testing purposes. ** ** If this module is built with SQLITE_TEST defined, these constants may ** be overridden at runtime for testing purposes. File fts3_test.c contains ** a Tcl interface to read and write the values. @@ -198267,25 +157078,25 @@ int test_fts3_node_chunksize = (4*1024); int test_fts3_node_chunk_threshold = (4*1024)*4; # define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize # define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold #else -# define FTS3_NODE_CHUNKSIZE (4*1024) +# define FTS3_NODE_CHUNKSIZE (4*1024) # define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4) #endif /* -** The values that may be meaningfully bound to the :1 parameter in +** The two values that may be meaningfully bound to the :1 parameter in ** statements SQL_REPLACE_STAT and SQL_SELECT_STAT. */ #define FTS_STAT_DOCTOTAL 0 #define FTS_STAT_INCRMERGEHINT 1 #define FTS_STAT_AUTOINCRMERGE 2 /* ** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic -** and incremental merge operation that takes place. This is used for +** and incremental merge operation that takes place. This is used for ** debugging FTS only, it should not usually be turned on in production ** systems. */ #ifdef FTS3_LOG_MERGES static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){ @@ -198367,11 +157178,11 @@ char *zTerm; /* Pointer to current term */ int nTermAlloc; /* Allocated size of zTerm buffer */ char *aDoclist; /* Pointer to doclist of current entry */ int nDoclist; /* Size of doclist in current entry */ - /* The following variables are used by fts3SegReaderNextDocid() to iterate + /* The following variables are used by fts3SegReaderNextDocid() to iterate ** through the current doclist (aDoclist/nDoclist). */ char *pOffsetList; int nOffsetList; /* For descending pending seg-readers only */ sqlite3_int64 iDocid; @@ -198412,15 +157223,15 @@ ** fts3NodeAddTerm() ** fts3NodeWrite() ** fts3NodeFree() ** ** When a b+tree is written to the database (either as a result of a merge -** or the pending-terms table being flushed), leaves are written into the +** or the pending-terms table being flushed), leaves are written into the ** database file as soon as they are completely populated. The interior of ** the tree is assembled in memory and written out only once all leaves have ** been populated and stored. This is Ok, as the b+-tree fanout is usually -** very large, meaning that the interior of the tree consumes relatively +** very large, meaning that the interior of the tree consumes relatively ** little memory. */ struct SegmentNode { SegmentNode *pParent; /* Parent node (or NULL for root node) */ SegmentNode *pRight; /* Pointer to right-sibling */ @@ -198437,11 +157248,11 @@ /* ** Valid values for the second argument to fts3SqlStmt(). */ #define SQL_DELETE_CONTENT 0 #define SQL_IS_EMPTY 1 -#define SQL_DELETE_ALL_CONTENT 2 +#define SQL_DELETE_ALL_CONTENT 2 #define SQL_DELETE_ALL_SEGMENTS 3 #define SQL_DELETE_ALL_SEGDIR 4 #define SQL_DELETE_ALL_DOCSIZE 5 #define SQL_DELETE_ALL_STAT 6 #define SQL_SELECT_CONTENT_BY_ROWID 7 @@ -198485,11 +157296,11 @@ ** for the statement identified by the second argument. If successful, ** *pp is set to the requested statement handle and SQLITE_OK returned. ** Otherwise, an SQLite error code is returned and *pp is set to 0. ** ** If argument apVal is not NULL, then it must point to an array with -** at least as many entries as the requested statement has bound +** at least as many entries as the requested statement has bound ** parameters. The values are bound to the statements parameters before ** returning. */ static int fts3SqlStmt( Fts3Table *p, /* Virtual table handle */ @@ -198509,11 +157320,11 @@ /* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", /* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", /* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", /* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", - /* Return segments in order from oldest to newest.*/ + /* Return segments in order from oldest to newest.*/ /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?" "ORDER BY level DESC, idx ASC", @@ -198540,19 +157351,17 @@ ** of the oldest level in the db that contains at least ? segments. Or, ** if no level in the FTS index contains more than ? segments, the statement ** returns zero rows. */ /* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' " " GROUP BY level HAVING cnt>=?" - " ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1", + " ORDER BY (level %% 1024) ASC LIMIT 1", /* Estimate the upper limit on the number of leaf nodes in a new segment -** created by merging the oldest :2 segments from absolute level :1. See +** created by merging the oldest :2 segments from absolute level :1. See ** function sqlite3Fts3Incrmerge() for details. */ /* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) " - " FROM (SELECT * FROM %Q.'%q_segdir' " - " WHERE level = ? ORDER BY idx ASC LIMIT ?" - " )", + " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?", /* SQL_DELETE_SEGDIR_ENTRY ** Delete the %_segdir entry on absolute level :1 with index :2. */ /* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", @@ -198560,11 +157369,11 @@ ** Modify the idx value for the segment with idx=:3 on absolute level :2 ** to :1. */ /* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?", /* SQL_SELECT_SEGDIR -** Read a single entry from the %_segdir table. The entry from absolute +** Read a single entry from the %_segdir table. The entry from absolute ** level :1 with index value :2. */ /* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root " "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", /* SQL_CHOMP_SEGDIR @@ -198584,11 +157393,11 @@ /* SQL_SELECT_MXLEVEL ** Return the largest relative level in the FTS index or indexes. */ /* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'", - /* Return segments in order from oldest to newest.*/ + /* Return segments in order from oldest to newest.*/ /* 37 */ "SELECT level, idx, end_block " "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? " "ORDER BY level DESC, idx ASC", /* Update statements used while promoting segments */ @@ -198600,27 +157409,26 @@ int rc = SQLITE_OK; sqlite3_stmt *pStmt; assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); assert( eStmt=0 ); - + pStmt = p->aStmt[eStmt]; if( !pStmt ){ - int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB; char *zSql; if( eStmt==SQL_CONTENT_INSERT ){ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ - f &= ~SQLITE_PREPARE_NO_VTAB; zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist); }else{ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); } if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL); + rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + &pStmt, NULL); sqlite3_free(zSql); assert( rc==SQLITE_OK || pStmt==0 ); p->aStmt[eStmt] = pStmt; } } @@ -198705,36 +157513,36 @@ sqlite3_value **apVal /* Parameters to bind */ ){ sqlite3_stmt *pStmt; int rc; if( *pRC ) return; - rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); + rc = fts3SqlStmt(p, eStmt, &pStmt, apVal); if( rc==SQLITE_OK ){ sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); } *pRC = rc; } /* -** This function ensures that the caller has obtained an exclusive -** shared-cache table-lock on the %_segdir table. This is required before +** This function ensures that the caller has obtained an exclusive +** shared-cache table-lock on the %_segdir table. This is required before ** writing data to the fts3 table. If this lock is not acquired first, then ** the caller may end up attempting to take this lock as part of committing -** a transaction, causing SQLite to return SQLITE_LOCKED or +** a transaction, causing SQLite to return SQLITE_LOCKED or ** LOCKED_SHAREDCACHEto a COMMIT command. ** -** It is best to avoid this because if FTS3 returns any error when -** committing a transaction, the whole transaction will be rolled back. -** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. -** It can still happen if the user locks the underlying tables directly +** It is best to avoid this because if FTS3 returns any error when +** committing a transaction, the whole transaction will be rolled back. +** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. +** It can still happen if the user locks the underlying tables directly ** instead of accessing them via FTS. */ static int fts3Writelock(Fts3Table *p){ int rc = SQLITE_OK; - + if( p->nPendingData==0 ){ sqlite3_stmt *pStmt; rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0); if( rc==SQLITE_OK ){ sqlite3_bind_null(pStmt, 1); @@ -198747,38 +157555,38 @@ } /* ** FTS maintains a separate indexes for each language-id (a 32-bit integer). ** Within each language id, a separate index is maintained to store the -** document terms, and each configured prefix size (configured the FTS +** document terms, and each configured prefix size (configured the FTS ** "prefix=" option). And each index consists of multiple levels ("relative ** levels"). ** ** All three of these values (the language id, the specific index and the ** level within the index) are encoded in 64-bit integer values stored ** in the %_segdir table on disk. This function is used to convert three ** separate component values into the single 64-bit integer value that ** can be used to query the %_segdir table. ** -** Specifically, each language-id/index combination is allocated 1024 +** Specifically, each language-id/index combination is allocated 1024 ** 64-bit integer level values ("absolute levels"). The main terms index ** for language-id 0 is allocate values 0-1023. The first prefix index ** (if any) for language-id 0 is allocated values 1024-2047. And so on. ** Language 1 indexes are allocated immediately following language 0. ** ** So, for a system with nPrefix prefix indexes configured, the block of -** absolute levels that corresponds to language-id iLangid and index +** absolute levels that corresponds to language-id iLangid and index ** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024). */ static sqlite3_int64 getAbsoluteLevel( Fts3Table *p, /* FTS3 table handle */ int iLangid, /* Language id */ int iIndex, /* Index in p->aIndex[] */ int iLevel /* Level of segments */ ){ sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */ - assert_fts3_nc( iLangid>=0 ); + assert( iLangid>=0 ); assert( p->nIndex>0 ); assert( iIndex>=0 && iIndexnIndex ); iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL; return iBase + iLevel; @@ -198785,11 +157593,11 @@ } /* ** Set *ppStmt to a statement handle that may be used to iterate through ** all rows in the %_segdir table, from oldest to newest. If successful, -** return SQLITE_OK. If an error occurs while preparing the statement, +** return SQLITE_OK. If an error occurs while preparing the statement, ** return an SQLite error code. ** ** There is only ever one instance of this SQL statement compiled for ** each FTS3 table. ** @@ -198816,20 +157624,20 @@ assert( iIndex>=0 && iIndexnIndex ); if( iLevel<0 ){ /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, + sqlite3_bind_int64(pStmt, 2, getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) ); } }else{ /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); } } *ppStmt = pStmt; return rc; @@ -198854,27 +157662,27 @@ ){ PendingList *p = *pp; /* Allocate or grow the PendingList as required. */ if( !p ){ - p = sqlite3_malloc64(sizeof(*p) + 100); + p = sqlite3_malloc(sizeof(*p) + 100); if( !p ){ return SQLITE_NOMEM; } p->nSpace = 100; p->aData = (char *)&p[1]; p->nData = 0; } else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){ - i64 nNew = p->nSpace * 2; - p = sqlite3_realloc64(p, sizeof(*p) + nNew); + int nNew = p->nSpace * 2; + p = sqlite3_realloc(p, sizeof(*p) + nNew); if( !p ){ sqlite3_free(*pp); *pp = 0; return SQLITE_NOMEM; } - p->nSpace = (int)nNew; + p->nSpace = nNew; p->aData = (char *)&p[1]; } /* Append the new serialized varint to the end of the list. */ p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i); @@ -198903,11 +157711,11 @@ int rc = SQLITE_OK; assert( !p || p->iLastDocid<=iDocid ); if( !p || p->iLastDocid!=iDocid ){ - u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0); + sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0); if( p ){ assert( p->nDatanSpace ); assert( p->aData[p->nData]==0 ); p->nData++; } @@ -198969,11 +157777,11 @@ if( pList ){ p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem)); } if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){ if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){ - /* Malloc failed while inserting the new entry. This can only + /* Malloc failed while inserting the new entry. This can only ** happen if there was no previous entry for this token. */ assert( 0==fts3HashFind(pHash, zToken, nToken) ); sqlite3_free(pList); rc = SQLITE_NOMEM; @@ -199015,11 +157823,11 @@ const char**,int*,int*,int*,int*); assert( pTokenizer && pModule ); /* If the user has inserted a NULL value, this function may be called with - ** zText==0. In this case, add zero token entries to the hash table and + ** zText==0. In this case, add zero token entries to the hash table and ** return early. */ if( zText==0 ){ *pnWord = 0; return SQLITE_OK; } @@ -199046,12 +157854,12 @@ /* Add the term to the terms index */ rc = fts3PendingTermsAddOne( p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken ); - - /* Add the term to each of the prefix indexes that it is not too + + /* Add the term to each of the prefix indexes that it is not too ** short for. */ for(i=1; rc==SQLITE_OK && inIndex; i++){ struct Fts3Index *pIndex = &p->aIndex[i]; if( nTokennPrefix ) continue; rc = fts3PendingTermsAddOne( @@ -199063,12 +157871,12 @@ pModule->xClose(pCsr); *pnWord += nWord; return (rc==SQLITE_DONE ? SQLITE_OK : rc); } -/* -** Calling this function indicates that subsequent calls to +/* +** Calling this function indicates that subsequent calls to ** fts3PendingTermsAdd() are to add term/position-list pairs for the ** contents of the document with docid iDocid. */ static int fts3PendingTermsDocid( Fts3Table *p, /* Full-text table handle */ @@ -199083,14 +157891,14 @@ ** forced-flush would provide better performance. I suspect that if ** we ordered the doclists by size and flushed the largest until the ** buffer was half empty, that would let the less frequent terms ** generate longer doclists. */ - if( iDocidiPrevDocid + if( iDocidiPrevDocid || (iDocid==p->iPrevDocid && p->bPrevDelete==0) || p->iPrevLangid!=iLangid - || p->nPendingData>p->nMaxPendingData + || p->nPendingData>p->nMaxPendingData ){ int rc = sqlite3Fts3PendingTermsFlush(p); if( rc!=SQLITE_OK ) return rc; } p->iPrevDocid = iDocid; @@ -199098,11 +157906,11 @@ p->bPrevDelete = bDelete; return SQLITE_OK; } /* -** Discard the contents of the pending-terms hash tables. +** Discard the contents of the pending-terms hash tables. */ SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){ int i; for(i=0; inIndex; i++){ Fts3HashElem *pElem; @@ -199123,13 +157931,13 @@ ** ** Argument apVal is the same as the similarly named argument passed to ** fts3InsertData(). Parameter iDocid is the docid of the new row. */ static int fts3InsertTerms( - Fts3Table *p, - int iLangid, - sqlite3_value **apVal, + Fts3Table *p, + int iLangid, + sqlite3_value **apVal, u32 *aSz ){ int i; /* Iterator variable */ for(i=2; inColumn+2; i++){ int iCol = i-2; @@ -199188,11 +157996,11 @@ ** defined columns in the FTS3 table, plus one for the docid field. */ rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); if( rc==SQLITE_OK && p->zLanguageid ){ rc = sqlite3_bind_int( - pContentInsert, p->nColumn+2, + pContentInsert, p->nColumn+2, sqlite3_value_int(apVal[p->nColumn+4]) ); } if( rc!=SQLITE_OK ) return rc; @@ -199215,12 +158023,12 @@ } rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); if( rc!=SQLITE_OK ) return rc; } - /* Execute the statement to insert the record. Set *piDocid to the - ** new docid value. + /* Execute the statement to insert the record. Set *piDocid to the + ** new docid value. */ sqlite3_step(pContentInsert); rc = sqlite3_reset(pContentInsert); *piDocid = sqlite3_last_insert_rowid(p->db); @@ -199266,11 +158074,11 @@ /* ** The first element in the apVal[] array is assumed to contain the docid ** (an integer) of a row about to be deleted. Remove all terms from the ** full-text index. */ -static void fts3DeleteTerms( +static void fts3DeleteTerms( int *pRC, /* Result code */ Fts3Table *p, /* The FTS table to delete from */ sqlite3_value *pRowid, /* The docid to be deleted */ u32 *aSz, /* Sizes of deleted document written here */ int *pbFound /* OUT: Set to true if row really does exist */ @@ -199313,30 +158121,30 @@ ** Forward declaration to account for the circular dependency between ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). */ static int fts3SegmentMerge(Fts3Table *, int, int, int); -/* +/* ** This function allocates a new level iLevel index in the segdir table. ** Usually, indexes are allocated within a level sequentially starting ** with 0, so the allocated index is one greater than the value returned ** by: ** ** SELECT max(idx) FROM %_segdir WHERE level = :iLevel ** ** However, if there are already FTS3_MERGE_COUNT indexes at the requested -** level, they are merged into a single level (iLevel+1) segment and the +** level, they are merged into a single level (iLevel+1) segment and the ** allocated index is 0. ** ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK ** returned. Otherwise, an SQLite error code is returned. */ static int fts3AllocateSegdirIdx( - Fts3Table *p, + Fts3Table *p, int iLangid, /* Language id */ int iIndex, /* Index for p->aIndex */ - int iLevel, + int iLevel, int *piIdx ){ int rc; /* Return Code */ sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ int iNext = 0; /* Result of query pNextIdx */ @@ -199360,11 +158168,11 @@ /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already ** full, merge all segments in level iLevel into a single iLevel+1 ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. */ - if( iNext>=MergeCount(p) ){ + if( iNext>=FTS3_MERGE_COUNT ){ fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); *piIdx = 0; }else{ *piIdx = iNext; @@ -199380,11 +158188,11 @@ ** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB) ** ** This function reads data from a single row of the %_segments table. The ** specific row is identified by the iBlockid parameter. If paBlob is not ** NULL, then a buffer is allocated using sqlite3_malloc() and populated -** with the contents of the blob stored in the "block" column of the +** with the contents of the blob stored in the "block" column of the ** identified table row is. Whether or not paBlob is NULL, *pnBlob is set ** to the size of the blob in bytes before returning. ** ** If an error occurs, or the table does not contain the specified row, ** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If @@ -199427,11 +158235,11 @@ if( rc==SQLITE_OK ){ int nByte = sqlite3_blob_bytes(p->pSegments); *pnBlob = nByte; if( paBlob ){ - char *aByte = sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING); + char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING); if( !aByte ){ rc = SQLITE_NOMEM; }else{ if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){ nByte = FTS3_NODE_CHUNKSIZE; @@ -199444,12 +158252,10 @@ aByte = 0; } } *paBlob = aByte; } - }else if( rc==SQLITE_ERROR ){ - rc = FTS_CORRUPT_VTAB; } return rc; } @@ -199459,18 +158265,18 @@ */ SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){ sqlite3_blob_close(p->pSegments); p->pSegments = 0; } - + static int fts3SegReaderIncrRead(Fts3SegReader *pReader){ int nRead; /* Number of bytes to read */ int rc; /* Return code */ nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE); rc = sqlite3_blob_read( - pReader->pBlob, + pReader->pBlob, &pReader->aNode[pReader->nPopulate], nRead, pReader->nPopulate ); @@ -199486,14 +158292,14 @@ return rc; } static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){ int rc = SQLITE_OK; - assert( !pReader->pBlob + assert( !pReader->pBlob || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode]) ); - while( pReader->pBlob && rc==SQLITE_OK + while( pReader->pBlob && rc==SQLITE_OK && (pFrom - pReader->aNode + nByte)>pReader->nPopulate ){ rc = fts3SegReaderIncrRead(pReader); } return rc; @@ -199515,11 +158321,11 @@ ** Move the iterator passed as the first argument to the next term in the ** segment. If successful, SQLITE_OK is returned. If there is no next term, ** SQLITE_DONE. Otherwise, an SQLite error code. */ static int fts3SegReaderNext( - Fts3Table *p, + Fts3Table *p, Fts3SegReader *pReader, int bIncr ){ int rc; /* Return code of various sub-routines */ char *pNext; /* Cursor variable */ @@ -199540,23 +158346,13 @@ pReader->aNode = 0; if( pElem ){ char *aCopy; PendingList *pList = (PendingList *)fts3HashData(pElem); int nCopy = pList->nData+1; - - int nTerm = fts3HashKeysize(pElem); - if( (nTerm+1)>pReader->nTermAlloc ){ - sqlite3_free(pReader->zTerm); - pReader->zTerm = (char*)sqlite3_malloc64(((i64)nTerm+1)*2); - if( !pReader->zTerm ) return SQLITE_NOMEM; - pReader->nTermAlloc = (nTerm+1)*2; - } - memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm); - pReader->zTerm[nTerm] = '\0'; - pReader->nTerm = nTerm; - - aCopy = (char*)sqlite3_malloc64(nCopy); + pReader->zTerm = (char *)fts3HashKey(pElem); + pReader->nTerm = fts3HashKeysize(pElem); + aCopy = (char*)sqlite3_malloc(nCopy); if( !aCopy ) return SQLITE_NOMEM; memcpy(aCopy, pList->aData, nCopy); pReader->nNode = pReader->nDoclist = nCopy; pReader->aNode = pReader->aDoclist = aCopy; pReader->ppNextElem++; @@ -199565,21 +158361,19 @@ return SQLITE_OK; } fts3SegReaderSetEof(pReader); - /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf + /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf ** blocks have already been traversed. */ -#ifdef CORRUPT_DB - assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB ); -#endif + assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock ); if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){ return SQLITE_OK; } rc = sqlite3Fts3ReadBlock( - p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, + p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, (bIncr ? &pReader->nPopulate : 0) ); if( rc!=SQLITE_OK ) return rc; assert( pReader->pBlob==0 ); if( bIncr && pReader->nPopulatenNode ){ @@ -199591,28 +158385,24 @@ assert( !fts3SegReaderIsPending(pReader) ); rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2); if( rc!=SQLITE_OK ) return rc; - - /* Because of the FTS3_NODE_PADDING bytes of padding, the following is + + /* Because of the FTS3_NODE_PADDING bytes of padding, the following is ** safe (no risk of overread) even if the node data is corrupted. */ pNext += fts3GetVarint32(pNext, &nPrefix); pNext += fts3GetVarint32(pNext, &nSuffix); - if( nSuffix<=0 - || (&pReader->aNode[pReader->nNode] - pNext)pReader->nTerm + if( nPrefix<0 || nSuffix<=0 + || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] ){ return FTS_CORRUPT_VTAB; } - /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are - ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer - ** overflow - hence the (i64) casts. */ - if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){ - i64 nNew = ((i64)nPrefix+nSuffix)*2; - char *zNew = sqlite3_realloc64(pReader->zTerm, nNew); + if( nPrefix+nSuffix>pReader->nTermAlloc ){ + int nNew = (nPrefix+nSuffix)*2; + char *zNew = sqlite3_realloc(pReader->zTerm, nNew); if( !zNew ){ return SQLITE_NOMEM; } pReader->zTerm = zNew; pReader->nTermAlloc = nNew; @@ -199627,16 +158417,15 @@ pNext += fts3GetVarint32(pNext, &pReader->nDoclist); pReader->aDoclist = pNext; pReader->pOffsetList = 0; /* Check that the doclist does not appear to extend past the end of the - ** b-tree node. And that the final byte of the doclist is 0x00. If either + ** b-tree node. And that the final byte of the doclist is 0x00. If either ** of these statements is untrue, then the data structure is corrupt. */ - if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode) + if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1]) - || pReader->nDoclist==0 ){ return FTS_CORRUPT_VTAB; } return SQLITE_OK; } @@ -199652,11 +158441,11 @@ if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ u8 bEof = 0; pReader->iDocid = 0; pReader->nOffsetList = 0; sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList, + pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList, &pReader->iDocid, &pReader->nOffsetList, &bEof ); }else{ rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX); if( rc==SQLITE_OK ){ @@ -199668,12 +158457,12 @@ } /* ** Advance the SegReader to point to the next docid in the doclist ** associated with the current term. -** -** If arguments ppOffsetList and pnOffsetList are not NULL, then +** +** If arguments ppOffsetList and pnOffsetList are not NULL, then ** *ppOffsetList is set to point to the first column-offset list ** in the doclist entry (i.e. immediately past the docid varint). ** *pnOffsetList is set to the length of the set of column-offset ** lists, not including the nul-terminator byte. For example: */ @@ -199712,26 +158501,26 @@ /* Pointer p currently points at the first byte of an offset list. The ** following block advances it to point one byte past the end of ** the same offset list. */ while( 1 ){ - + /* The following line of code (and the "p++" below the while() loop) is - ** normally all that is required to move pointer p to the desired + ** normally all that is required to move pointer p to the desired ** position. The exception is if this node is being loaded from disk ** incrementally and pointer "p" now points to the first byte past ** the populated part of pReader->aNode[]. */ while( *p | c ) c = *p++ & 0x80; assert( *p==0 ); - + if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break; rc = fts3SegReaderIncrRead(pReader); if( rc!=SQLITE_OK ) return rc; } p++; - + /* If required, populate the output variables with a pointer to and the ** size of the previous offset-list. */ if( ppOffsetList ){ *ppOffsetList = pReader->pOffsetList; @@ -199738,11 +158527,11 @@ *pnOffsetList = (int)(p - pReader->pOffsetList - 1); } /* List may have been edited in place by fts3EvalNearTrim() */ while( p=pEnd ){ pReader->pOffsetList = 0; }else{ rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX); if( rc==SQLITE_OK ){ - u64 iDelta; - pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta); + sqlite3_int64 iDelta; + pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta); if( pTab->bDescIdx ){ - pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta); + pReader->iDocid -= iDelta; }else{ - pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta); + pReader->iDocid += iDelta; } } } } - return rc; + return SQLITE_OK; } SQLITE_PRIVATE int sqlite3Fts3MsrOvfl( - Fts3Cursor *pCsr, + Fts3Cursor *pCsr, Fts3MultiSegReader *pMsr, int *pnOvfl ){ Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; int nOvfl = 0; @@ -199780,12 +158569,12 @@ assert( p->bFts4 ); assert( pgsz>0 ); for(ii=0; rc==SQLITE_OK && iinSegment; ii++){ Fts3SegReader *pReader = pMsr->apSegment[ii]; - if( !fts3SegReaderIsPending(pReader) - && !fts3SegReaderIsRootOnly(pReader) + if( !fts3SegReaderIsPending(pReader) + && !fts3SegReaderIsRootOnly(pReader) ){ sqlite3_int64 jj; for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){ int nBlob; rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0); @@ -199799,16 +158588,18 @@ *pnOvfl = nOvfl; return rc; } /* -** Free all allocations associated with the iterator passed as the +** Free all allocations associated with the iterator passed as the ** second argument. */ SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ if( pReader ){ - sqlite3_free(pReader->zTerm); + if( !fts3SegReaderIsPending(pReader) ){ + sqlite3_free(pReader->zTerm); + } if( !fts3SegReaderIsRootOnly(pReader) ){ sqlite3_free(pReader->aNode); } sqlite3_blob_close(pReader->pBlob); } @@ -199829,21 +158620,16 @@ Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ ){ Fts3SegReader *pReader; /* Newly allocated SegReader object */ int nExtra = 0; /* Bytes to allocate segment root node */ - assert( zRoot!=0 || nRoot==0 ); -#ifdef CORRUPT_DB - assert( zRoot!=0 || CORRUPT_DB ); -#endif - + assert( iStartLeaf<=iEndLeaf ); if( iStartLeaf==0 ){ - if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB; nExtra = nRoot + FTS3_NODE_PADDING; } - pReader = (Fts3SegReader *)sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra); + pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra); if( !pReader ){ return SQLITE_NOMEM; } memset(pReader, 0, sizeof(Fts3SegReader)); pReader->iIdx = iAge; @@ -199855,11 +158641,11 @@ if( nExtra ){ /* The entire segment is stored in the root node. */ pReader->aNode = (char *)&pReader[1]; pReader->rootOnly = 1; pReader->nNode = nRoot; - if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot); + memcpy(pReader->aNode, zRoot, nRoot); memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING); }else{ pReader->iCurrentBlock = iStartLeaf-1; } *ppReader = pReader; @@ -199931,11 +158717,11 @@ int nKey = fts3HashKeysize(pE); if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){ if( nElem==nAlloc ){ Fts3HashElem **aElem2; nAlloc += 16; - aElem2 = (Fts3HashElem **)sqlite3_realloc64( + aElem2 = (Fts3HashElem **)sqlite3_realloc( aElem, nAlloc*sizeof(Fts3HashElem *) ); if( !aElem2 ){ rc = SQLITE_NOMEM; nElem = 0; @@ -199956,11 +158742,11 @@ qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm); } }else{ /* The query is a simple term lookup that matches at most one term in - ** the index. All that is required is a straight hash-lookup. + ** the index. All that is required is a straight hash-lookup. ** ** Because the stack address of pE may be accessed via the aElem pointer ** below, the "Fts3HashElem *pE" must be declared so that it is valid ** within this entire function, not just this "else{...}" block. */ @@ -199970,13 +158756,12 @@ nElem = 1; } } if( nElem>0 ){ - sqlite3_int64 nByte; - nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); - pReader = (Fts3SegReader *)sqlite3_malloc64(nByte); + int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); + pReader = (Fts3SegReader *)sqlite3_malloc(nByte); if( !pReader ){ rc = SQLITE_NOMEM; }else{ memset(pReader, 0, nByte); pReader->iIdx = 0x7FFFFFFF; @@ -199991,11 +158776,11 @@ *ppReader = pReader; return rc; } /* -** Compare the entries pointed to by two Fts3SegReader structures. +** Compare the entries pointed to by two Fts3SegReader structures. ** Comparison is as follows: ** ** 1) EOF is greater than not EOF. ** ** 2) The current terms (if any) are compared using memcmp(). If one @@ -200020,11 +158805,11 @@ rc = (pLhs->aNode==0) - (pRhs->aNode==0); } if( rc==0 ){ rc = pRhs->iIdx - pLhs->iIdx; } - assert_fts3_nc( rc!=0 ); + assert( rc!=0 ); return rc; } /* ** A different comparison function for SegReader structures. In this @@ -200062,11 +158847,11 @@ return rc; } /* ** Compare the term that the Fts3SegReader object passed as the first argument -** points to with the term specified by arguments zTerm and nTerm. +** points to with the term specified by arguments zTerm and nTerm. ** ** If the pSeg iterator is already at EOF, return 0. Otherwise, return ** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are ** equal, or +ve if the pSeg term is greater than zTerm/nTerm. */ @@ -200123,11 +158908,11 @@ assert( xCmp(apSegment[i], apSegment[i+1])<0 ); } #endif } -/* +/* ** Insert a record into the %_segments table. */ static int fts3WriteSegment( Fts3Table *p, /* Virtual table handle */ sqlite3_int64 iBlock, /* Block id for new block */ @@ -200139,11 +158924,10 @@ if( rc==SQLITE_OK ){ sqlite3_bind_int64(pStmt, 1, iBlock); sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 2); } return rc; } /* @@ -200165,11 +158949,11 @@ } *pnMax = mxLevel; return rc; } -/* +/* ** Insert a record into the %_segdir table. */ static int fts3WriteSegdir( Fts3Table *p, /* Virtual table handle */ sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */ @@ -200196,18 +158980,17 @@ sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free); } sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 6); } return rc; } /* ** Return the size of the common prefix (if any) shared by zPrev and -** zNext, in bytes. For example, +** zNext, in bytes. For example, ** ** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3 ** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2 ** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0 */ @@ -200216,31 +158999,31 @@ int nPrev, /* Size of buffer zPrev in bytes */ const char *zNext, /* Buffer containing next term */ int nNext /* Size of buffer zNext in bytes */ ){ int n; - for(n=0; nnData; /* Current size of node in bytes */ int nReq = nData; /* Required space after adding zTerm */ @@ -200248,28 +159031,23 @@ int nSuffix; /* Suffix length */ nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); nSuffix = nTerm-nPrefix; - /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of - ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when - ** compared with BINARY collation. This indicates corruption. */ - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; - nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; if( nReq<=p->nNodeSize || !pTree->zTerm ){ if( nReq>p->nNodeSize ){ /* An unusual case: this is the first term to be added to the node ** and the static node buffer (p->nNodeSize bytes) is not large ** enough. Use a separately malloced buffer instead This wastes ** p->nNodeSize bytes, but since this scenario only comes about when - ** the database contain two terms that share a prefix of almost 2KB, - ** this is not expected to be a serious problem. + ** the database contain two terms that share a prefix of almost 2KB, + ** this is not expected to be a serious problem. */ assert( pTree->aData==(char *)&pTree[1] ); - pTree->aData = (char *)sqlite3_malloc64(nReq); + pTree->aData = (char *)sqlite3_malloc(nReq); if( !pTree->aData ){ return SQLITE_NOMEM; } } @@ -200283,11 +159061,11 @@ pTree->nData = nData + nSuffix; pTree->nEntry++; if( isCopyTerm ){ if( pTree->nMalloczMalloc, (i64)nTerm*2); + char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2); if( !zNew ){ return SQLITE_NOMEM; } pTree->nMalloc = nTerm*2; pTree->zMalloc = zNew; @@ -200306,14 +159084,14 @@ /* If control flows to here, it was not possible to append zTerm to the ** current node. Create a new node (a right-sibling of the current node). ** If this is the first node in the tree, the term is added to it. ** ** Otherwise, the term is not added to the new node, it is left empty for - ** now. Instead, the term is inserted into the parent of pTree. If pTree + ** now. Instead, the term is inserted into the parent of pTree. If pTree ** has no parent, one is created here. */ - pNew = (SegmentNode *)sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize); + pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); if( !pNew ){ return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SegmentNode)); pNew->nData = 1 + FTS3_VARINT_MAX; @@ -200331,11 +159109,11 @@ pNew->zMalloc = pTree->zMalloc; pNew->nMalloc = pTree->nMalloc; pTree->zMalloc = 0; }else{ pNew->pLeftmost = pNew; - rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm); + rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm); } *ppTree = pNew; return rc; } @@ -200342,12 +159120,12 @@ /* ** Helper function for fts3NodeWrite(). */ static int fts3TreeFinishNode( - SegmentNode *pTree, - int iHeight, + SegmentNode *pTree, + int iHeight, sqlite3_int64 iLeftChild ){ int nStart; assert( iHeight>=1 && iHeight<128 ); nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild); @@ -200356,19 +159134,19 @@ return nStart; } /* ** Write the buffer for the segment node pTree and all of its peers to the -** database. Then call this function recursively to write the parent of -** pTree and its peers to the database. +** database. Then call this function recursively to write the parent of +** pTree and its peers to the database. ** ** Except, if pTree is a root node, do not write it to the database. Instead, ** set output variables *paRoot and *pnRoot to contain the root node. ** ** If successful, SQLITE_OK is returned and output variable *piLast is ** set to the largest blockid written to the database (or zero if no -** blocks were written to the db). Otherwise, an SQLite error code is +** blocks were written to the db). Otherwise, an SQLite error code is ** returned. */ static int fts3NodeWrite( Fts3Table *p, /* Virtual table handle */ SegmentNode *pTree, /* SegmentNode handle */ @@ -200392,11 +159170,11 @@ sqlite3_int64 iNextFree = iFree; sqlite3_int64 iNextLeaf = iLeaf; for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){ int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf); int nWrite = pIter->nData - nStart; - + rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite); iNextFree++; iNextLeaf += (pIter->nEntry+1); } if( rc==SQLITE_OK ){ @@ -200438,35 +159216,35 @@ ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ static int fts3SegWriterAdd( Fts3Table *p, /* Virtual table handle */ - SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ + SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ int isCopyTerm, /* True if buffer zTerm must be copied */ const char *zTerm, /* Pointer to buffer containing term */ int nTerm, /* Size of term in bytes */ const char *aDoclist, /* Pointer to buffer containing doclist */ int nDoclist /* Size of doclist in bytes */ ){ int nPrefix; /* Size of term prefix in bytes */ int nSuffix; /* Size of term suffix in bytes */ - i64 nReq; /* Number of bytes required on leaf page */ + int nReq; /* Number of bytes required on leaf page */ int nData; SegmentWriter *pWriter = *ppWriter; if( !pWriter ){ int rc; sqlite3_stmt *pStmt; /* Allocate the SegmentWriter structure */ - pWriter = (SegmentWriter *)sqlite3_malloc64(sizeof(SegmentWriter)); + pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter)); if( !pWriter ) return SQLITE_NOMEM; memset(pWriter, 0, sizeof(SegmentWriter)); *ppWriter = pWriter; /* Allocate a buffer in which to accumulate data */ - pWriter->aData = (char *)sqlite3_malloc64(p->nNodeSize); + pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize); if( !pWriter->aData ) return SQLITE_NOMEM; pWriter->nSize = p->nNodeSize; /* Find the next free blockid in the %_segments table */ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); @@ -200481,15 +159259,10 @@ nData = pWriter->nData; nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm); nSuffix = nTerm-nPrefix; - /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of - ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when - ** compared with BINARY collation. This indicates corruption. */ - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; - /* Figure out how many bytes are required by this new entry */ nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */ sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ nSuffix + /* Term suffix */ sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ @@ -200497,11 +159270,10 @@ if( nData>0 && nData+nReq>p->nNodeSize ){ int rc; /* The current leaf node is full. Write it out to the database. */ - if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB; rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); if( rc!=SQLITE_OK ) return rc; p->nLeafAdd++; /* Add the current term to the interior node tree. The term added to @@ -200537,25 +159309,23 @@ /* If the buffer currently allocated is too small for this entry, realloc ** the buffer to make it large enough. */ if( nReq>pWriter->nSize ){ - char *aNew = sqlite3_realloc64(pWriter->aData, nReq); + char *aNew = sqlite3_realloc(pWriter->aData, nReq); if( !aNew ) return SQLITE_NOMEM; pWriter->aData = aNew; pWriter->nSize = nReq; } assert( nData+nReq<=pWriter->nSize ); /* Append the prefix-compressed term and doclist to the buffer. */ nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix); nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix); - assert( nSuffix>0 ); memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix); nData += nSuffix; nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist); - assert( nDoclist>0 ); memcpy(&pWriter->aData[nData], aDoclist, nDoclist); pWriter->nData = nData + nDoclist; /* Save the current term so that it can be used to prefix-compress the next. ** If the isCopyTerm parameter is true, then the buffer pointed to by @@ -200562,20 +159332,19 @@ ** zTerm is transient, so take a copy of the term data. Otherwise, just ** store a copy of the pointer. */ if( isCopyTerm ){ if( nTerm>pWriter->nMalloc ){ - char *zNew = sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2); + char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2); if( !zNew ){ return SQLITE_NOMEM; } pWriter->nMalloc = nTerm*2; pWriter->zMalloc = zNew; pWriter->zTerm = zNew; } assert( pWriter->zTerm==pWriter->zMalloc ); - assert( nTerm>0 ); memcpy(pWriter->zTerm, zTerm, nTerm); }else{ pWriter->zTerm = (char *)zTerm; } pWriter->nTerm = nTerm; @@ -200607,24 +159376,24 @@ if( rc==SQLITE_OK ){ rc = fts3NodeWrite(p, pWriter->pTree, 1, pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot); } if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, iLevel, iIdx, + rc = fts3WriteSegdir(p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot); } }else{ /* The entire tree fits on the root node. Write it to the segdir table. */ - rc = fts3WriteSegdir(p, iLevel, iIdx, + rc = fts3WriteSegdir(p, iLevel, iIdx, 0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData); } p->nLeafAdd++; return rc; } /* -** Release all memory held by the SegmentWriter object passed as the +** Release all memory held by the SegmentWriter object passed as the ** first argument. */ static void fts3SegWriterFree(SegmentWriter *pWriter){ if( pWriter ){ sqlite3_free(pWriter->aData); @@ -200670,13 +159439,13 @@ ** Segment levels are stored in the 'level' column of the %_segdir table. ** ** Return SQLITE_OK if successful, or an SQLite error code if not. */ static int fts3SegmentMaxLevel( - Fts3Table *p, + Fts3Table *p, int iLangid, - int iIndex, + int iIndex, sqlite3_int64 *pnMax ){ sqlite3_stmt *pStmt; int rc; assert( iIndex>=0 && iIndexnIndex ); @@ -200688,11 +159457,11 @@ ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). */ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, + sqlite3_bind_int64(pStmt, 2, getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) ); if( SQLITE_ROW==sqlite3_step(pStmt) ){ *pnMax = sqlite3_column_int64(pStmt, 0); } @@ -200717,12 +159486,12 @@ */ sqlite3_stmt *pStmt; int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; sqlite3_bind_int64(pStmt, 1, iAbsLevel+1); - sqlite3_bind_int64(pStmt, 2, - (((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL + sqlite3_bind_int64(pStmt, 2, + ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL ); *pbMax = 0; if( SQLITE_ROW==sqlite3_step(pStmt) ){ *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL; @@ -200755,13 +159524,13 @@ /* ** This function is used after merging multiple segments into a single large ** segment to delete the old, now redundant, segment b-trees. Specifically, ** it: -** -** 1) Deletes all %_segments entries for the segments associated with -** each of the SegReader objects in the array passed as the third +** +** 1) Deletes all %_segments entries for the segments associated with +** each of the SegReader objects in the array passed as the third ** argument, and ** ** 2) deletes all %_segdir entries with level iLevel, or all %_segdir ** entries regardless of level if (iLevel<0). ** @@ -200789,11 +159558,11 @@ assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL ); if( iLevel==FTS3_SEGCURSOR_ALL ){ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); if( rc==SQLITE_OK ){ sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pDelete, 2, + sqlite3_bind_int64(pDelete, 2, getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) ); } }else{ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); @@ -200811,11 +159580,11 @@ return rc; } /* -** When this function is called, buffer *ppList (size *pnList bytes) contains +** When this function is called, buffer *ppList (size *pnList bytes) contains ** a position list that may (or may not) feature multiple columns. This ** function adjusts the pointer *ppList and the length *pnList so that they ** identify the subset of the position list that corresponds to column iCol. ** ** If there are no entries in the input position list for column iCol, then @@ -200838,26 +159607,26 @@ assert( iCol>=0 ); while( 1 ){ char c = 0; while( p0){ + if( bZero && &pList[nList]!=pEnd ){ memset(&pList[nList], 0, pEnd - &pList[nList]); } *ppList = pList; *pnList = nList; } @@ -200870,24 +159639,21 @@ ** trying to resize the buffer, return SQLITE_NOMEM. */ static int fts3MsrBufferData( Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ char *pList, - i64 nList + int nList ){ - if( (nList+FTS3_NODE_PADDING)>pMsr->nBuffer ){ + if( nList>pMsr->nBuffer ){ char *pNew; - int nNew = nList*2 + FTS3_NODE_PADDING; - pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, nNew); + pMsr->nBuffer = nList*2; + pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer); if( !pNew ) return SQLITE_NOMEM; pMsr->aBuffer = pNew; - pMsr->nBuffer = nNew; } - assert( nList>0 ); memcpy(pMsr->aBuffer, pList, nList); - memset(&pMsr->aBuffer[nList], 0, FTS3_NODE_PADDING); return SQLITE_OK; } SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( Fts3Table *p, /* Virtual table handle */ @@ -200921,11 +159687,11 @@ int j; sqlite3_int64 iDocid = apSegment[0]->iDocid; rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); j = 1; - while( rc==SQLITE_OK + while( rc==SQLITE_OK && jpOffsetList && apSegment[j]->iDocid==iDocid ){ rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0); @@ -200933,11 +159699,11 @@ } if( rc!=SQLITE_OK ) return rc; fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1); + rc = fts3MsrBufferData(pMsr, pList, nList+1); if( rc!=SQLITE_OK ) return rc; assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); pList = pMsr->aBuffer; } @@ -200964,11 +159730,11 @@ int nTerm /* Length of zTerm in bytes */ ){ int i; int nSeg = pCsr->nSegment; - /* If the Fts3SegFilter defines a specific term (or term prefix) to search + /* If the Fts3SegFilter defines a specific term (or term prefix) to search ** for, then advance each segment iterator until it points to a term of ** equal or greater value than the specified term. This prevents many ** unnecessary merge/sort operations for the case where single segment ** b-tree leaf nodes contain more than one term. */ @@ -201048,11 +159814,11 @@ ** a state that if the next two calls are: ** ** sqlite3Fts3SegReaderStart() ** sqlite3Fts3SegReaderStep() ** -** then the entire doclist for the term is available in +** then the entire doclist for the term is available in ** MultiSegReader.aDoclist/nDoclist. */ SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){ int i; /* Used to iterate through segment-readers */ @@ -201067,23 +159833,10 @@ pCsr->apSegment[i]->pOffsetList = 0; pCsr->apSegment[i]->nOffsetList = 0; pCsr->apSegment[i]->iDocid = 0; } - return SQLITE_OK; -} - -static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){ - if( nReq>pCsr->nBuffer ){ - char *aNew; - pCsr->nBuffer = nReq*2; - aNew = sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer); - if( !aNew ){ - return SQLITE_NOMEM; - } - pCsr->aBuffer = aNew; - } return SQLITE_OK; } SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( @@ -201109,13 +159862,13 @@ if( pCsr->nSegment==0 ) return SQLITE_OK; do { int nMerge; int i; - + /* Advance the first pCsr->nAdvance entries in the apSegment[] array - ** forward. Then sort the list in order of current term again. + ** forward. Then sort the list in order of current term again. */ for(i=0; inAdvance; i++){ Fts3SegReader *pSeg = apSegment[i]; if( pSeg->bLookup ){ fts3SegReaderSetEof(pSeg); @@ -201133,44 +159886,43 @@ pCsr->nTerm = apSegment[0]->nTerm; pCsr->zTerm = apSegment[0]->zTerm; /* If this is a prefix-search, and if the term that apSegment[0] points - ** to does not share a suffix with pFilter->zTerm/nTerm, then all + ** to does not share a suffix with pFilter->zTerm/nTerm, then all ** required callbacks have been made. In this case exit early. ** ** Similarly, if this is a search for an exact match, and the first term ** of segment apSegment[0] is not a match, exit early. */ if( pFilter->zTerm && !isScan ){ - if( pCsr->nTermnTerm + if( pCsr->nTermnTerm || (!isPrefix && pCsr->nTerm>pFilter->nTerm) - || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm) + || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm) ){ break; } } nMerge = 1; - while( nMergeaNode - && apSegment[nMerge]->nTerm==pCsr->nTerm + && apSegment[nMerge]->nTerm==pCsr->nTerm && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm) ){ nMerge++; } assert( isIgnoreEmpty || (isRequirePos && !isColFilter) ); - if( nMerge==1 - && !isIgnoreEmpty - && !isFirst + if( nMerge==1 + && !isIgnoreEmpty + && !isFirst && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0) ){ pCsr->nDoclist = apSegment[0]->nDoclist; if( fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, - (i64)pCsr->nDoclist); + rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist); pCsr->aDoclist = pCsr->aBuffer; }else{ pCsr->aDoclist = apSegment[0]->aDoclist; } if( rc==SQLITE_OK ) rc = SQLITE_ROW; @@ -201206,31 +159958,36 @@ fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList); } if( !isIgnoreEmpty || nList>0 ){ - /* Calculate the 'docid' delta value to write into the merged + /* Calculate the 'docid' delta value to write into the merged ** doclist. */ sqlite3_int64 iDelta; if( p->bDescIdx && nDoclist>0 ){ - if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB; - iDelta = (i64)((u64)iPrev - (u64)iDocid); + iDelta = iPrev - iDocid; }else{ - if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB; - iDelta = (i64)((u64)iDocid - (u64)iPrev); + iDelta = iDocid - iPrev; } + assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) ); + assert( nDoclist>0 || iDelta==iDocid ); nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); - - rc = fts3GrowSegReaderBuffer(pCsr, - (i64)nByte+nDoclist+FTS3_NODE_PADDING); - if( rc ) return rc; + if( nDoclist+nByte>pCsr->nBuffer ){ + char *aNew; + pCsr->nBuffer = (nDoclist+nByte)*2; + aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer); + if( !aNew ){ + return SQLITE_NOMEM; + } + pCsr->aBuffer = aNew; + } if( isFirst ){ char *a = &pCsr->aBuffer[nDoclist]; int nWrite; - + nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a); if( nWrite ){ iPrev = iDocid; nDoclist += nWrite; } @@ -201246,13 +160003,10 @@ } fts3SegReaderSort(apSegment, nMerge, j, xCmp); } if( nDoclist>0 ){ - rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING); - if( rc ) return rc; - memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING); pCsr->aDoclist = pCsr->aBuffer; pCsr->nDoclist = nDoclist; rc = SQLITE_ROW; } } @@ -201279,44 +160033,44 @@ pCsr->aBuffer = 0; } } /* -** Decode the "end_block" field, selected by column iCol of the SELECT -** statement passed as the first argument. +** Decode the "end_block" field, selected by column iCol of the SELECT +** statement passed as the first argument. ** ** The "end_block" field may contain either an integer, or a text field -** containing the text representation of two non-negative integers separated -** by one or more space (0x20) characters. In the first case, set *piEndBlock -** to the integer value and *pnByte to zero before returning. In the second, +** containing the text representation of two non-negative integers separated +** by one or more space (0x20) characters. In the first case, set *piEndBlock +** to the integer value and *pnByte to zero before returning. In the second, ** set *piEndBlock to the first value and *pnByte to the second. */ static void fts3ReadEndBlockField( - sqlite3_stmt *pStmt, - int iCol, + sqlite3_stmt *pStmt, + int iCol, i64 *piEndBlock, i64 *pnByte ){ const unsigned char *zText = sqlite3_column_text(pStmt, iCol); if( zText ){ int i; int iMul = 1; - u64 iVal = 0; + i64 iVal = 0; for(i=0; zText[i]>='0' && zText[i]<='9'; i++){ iVal = iVal*10 + (zText[i] - '0'); } - *piEndBlock = (i64)iVal; + *piEndBlock = iVal; while( zText[i]==' ' ) i++; iVal = 0; if( zText[i]=='-' ){ i++; iMul = -1; } for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){ iVal = iVal*10 + (zText[i] - '0'); } - *pnByte = ((i64)iVal * (i64)iMul); + *pnByte = (iVal * (i64)iMul); } } /* @@ -201336,22 +160090,22 @@ if( rc==SQLITE_OK ){ int bOk = 0; i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1; i64 nLimit = (nByte*3)/2; - /* Loop through all entries in the %_segdir table corresponding to + /* Loop through all entries in the %_segdir table corresponding to ** segments in this index on levels greater than iAbsLevel. If there is - ** at least one such segment, and it is possible to determine that all - ** such segments are smaller than nLimit bytes in size, they will be + ** at least one such segment, and it is possible to determine that all + ** such segments are smaller than nLimit bytes in size, they will be ** promoted to level iAbsLevel. */ sqlite3_bind_int64(pRange, 1, iAbsLevel+1); sqlite3_bind_int64(pRange, 2, iLast); while( SQLITE_ROW==sqlite3_step(pRange) ){ i64 nSize = 0, dummy; fts3ReadEndBlockField(pRange, 2, &dummy, &nSize); if( nSize<=0 || nSize>nLimit ){ - /* If nSize==0, then the %_segdir.end_block field does not not + /* If nSize==0, then the %_segdir.end_block field does not not ** contain a size value. This happens if it was written by an ** old version of FTS. In this case it is not possible to determine ** the size of the segment, and so segment promotion does not ** take place. */ bOk = 0; @@ -201413,22 +160167,22 @@ return rc; } /* -** Merge all level iLevel segments in the database into a single +** Merge all level iLevel segments in the database into a single ** iLevel+1 segment. Or, if iLevel<0, merge all segments into a -** single segment with a level equal to the numerically largest level +** single segment with a level equal to the numerically largest level ** currently present in the database. ** ** If this function is called with iLevel<0, but there is only one -** segment in the database, SQLITE_DONE is returned immediately. -** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, +** segment in the database, SQLITE_DONE is returned immediately. +** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, ** an SQLite error code is returned. */ static int fts3SegmentMerge( - Fts3Table *p, + Fts3Table *p, int iLangid, /* Language id to merge */ int iIndex, /* Index in p->aIndex[] to merge */ int iLevel /* Level to merge */ ){ int rc; /* Return code */ @@ -201468,38 +160222,36 @@ bIgnoreEmpty = 1; }else{ /* This call is to merge all segments at level iLevel. find the next ** available segment index at level iLevel+1. The call to - ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to + ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to ** a single iLevel+2 segment if necessary. */ assert( FTS3_SEGCURSOR_PENDING==-1 ); iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel); } if( rc!=SQLITE_OK ) goto finished; assert( csr.nSegment>0 ); - assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); - assert_fts3_nc( - iNewLevel=getAbsoluteLevel(p, iLangid, iIndex, 0) ); + assert( iNewLevelnIndex; i++){ rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); if( rc==SQLITE_DONE ) rc = SQLITE_OK; } + sqlite3Fts3PendingTermsClear(p); /* Determine the auto-incr-merge setting if unknown. If enabled, ** estimate the number of leaf blocks of content to be written */ if( rc==SQLITE_OK && p->bHasStat @@ -201551,14 +160304,10 @@ p->nAutoincrmerge = 0; } rc = sqlite3_reset(pStmt); } } - - if( rc==SQLITE_OK ){ - sqlite3Fts3PendingTermsClear(p); - } return rc; } /* ** Encode N integers as varints into a blob. @@ -201583,20 +160332,18 @@ int N, /* The number of integers to decode */ u32 *a, /* Write the integer values */ const char *zBuf, /* The BLOB containing the varints */ int nBuf /* size of the BLOB */ ){ - int i = 0; - if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){ - int j; - for(i=j=0; iiPrevDocid. The sizes are encoded as @@ -201611,11 +160358,11 @@ int nBlob; /* Number of bytes in the BLOB */ sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ int rc; /* Result code from subfunctions */ if( *pRC ) return; - pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn ); + pBlob = sqlite3_malloc( 10*p->nColumn ); if( pBlob==0 ){ *pRC = SQLITE_NOMEM; return; } fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); @@ -201632,11 +160379,11 @@ } /* ** Record 0 of the %_stat table contains a blob consisting of N varints, ** where N is the number of user defined columns in the fts3 table plus -** two. If nCol is the number of user defined columns, then values of the +** two. If nCol is the number of user defined columns, then values of the ** varints are set as follows: ** ** Varint 0: Total number of rows in the table. ** ** Varint 1..nCol: For each column, the total number of tokens stored in @@ -201661,11 +160408,11 @@ int rc; /* Result code from subfunctions */ const int nStat = p->nColumn+2; if( *pRC ) return; - a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat ); + a = sqlite3_malloc( (sizeof(u32)+10)*nStat ); if( a==0 ){ *pRC = SQLITE_NOMEM; return; } pBlob = (char*)&a[nStat]; @@ -201712,27 +160459,23 @@ } sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); sqlite3_step(pStmt); *pRC = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 2); sqlite3_free(a); } /* -** Merge the entire database so that there is one segment for each +** Merge the entire database so that there is one segment for each ** iIndex/iLangid combination. */ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ int bSeenDone = 0; int rc; sqlite3_stmt *pAllLangid = 0; - rc = sqlite3Fts3PendingTermsFlush(p); - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); - } + rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); sqlite3_bind_int(pAllLangid, 2, p->nIndex); while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ @@ -201749,20 +160492,21 @@ rc2 = sqlite3_reset(pAllLangid); if( rc==SQLITE_OK ) rc = rc2; } sqlite3Fts3SegmentsClose(p); + sqlite3Fts3PendingTermsClear(p); return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; } /* ** This function is called when the user executes the following statement: ** ** INSERT INTO () VALUES('rebuild'); ** -** The entire FTS index is discarded and rebuilt. If the table is one +** The entire FTS index is discarded and rebuilt. If the table is one ** created using the content=xxx option, then the new index is based on ** the current contents of the xxx table. Otherwise, it is rebuilt based ** on the contents of the %_content table. */ static int fts3DoRebuild(Fts3Table *p){ @@ -201784,12 +160528,12 @@ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); } if( rc==SQLITE_OK ){ - sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3; - aSz = (u32 *)sqlite3_malloc64(nByte); + int nByte = sizeof(u32) * (p->nColumn+1)*3; + aSz = (u32 *)sqlite3_malloc(nByte); if( aSz==0 ){ rc = SQLITE_NOMEM; }else{ memset(aSz, 0, nByte); aSzIns = &aSz[p->nColumn+1]; @@ -201838,29 +160582,29 @@ return rc; } /* -** This function opens a cursor used to read the input data for an +** This function opens a cursor used to read the input data for an ** incremental merge operation. Specifically, it opens a cursor to scan -** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute +** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute ** level iAbsLevel. */ static int fts3IncrmergeCsr( Fts3Table *p, /* FTS3 table handle */ sqlite3_int64 iAbsLevel, /* Absolute level to open */ int nSeg, /* Number of segments to merge */ Fts3MultiSegReader *pCsr /* Cursor object to populate */ ){ int rc; /* Return Code */ - sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ - sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */ + sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ + int nByte; /* Bytes allocated at pCsr->apSegment[] */ /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ memset(pCsr, 0, sizeof(*pCsr)); nByte = sizeof(Fts3SegReader *) * nSeg; - pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte); + pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); if( pCsr->apSegment==0 ){ rc = SQLITE_NOMEM; }else{ memset(pCsr->apSegment, 0, nByte); @@ -201905,11 +160649,11 @@ int n; /* Number of valid bytes of data in a[] */ int nAlloc; /* Allocated size of a[] (nAlloc>=n) */ }; /* -** This structure is used to build up buffers containing segment b-tree +** This structure is used to build up buffers containing segment b-tree ** nodes (blocks). */ struct NodeWriter { sqlite3_int64 iBlock; /* Current block id */ Blob key; /* Last key written to the current block */ @@ -201962,11 +160706,11 @@ ** to reflect the new size of the pBlob->a[] buffer. */ static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ int nAlloc = nMin; - char *a = (char *)sqlite3_realloc64(pBlob->a, nAlloc); + char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc); if( a ){ pBlob->nAlloc = nAlloc; pBlob->a = a; }else{ *pRc = SQLITE_NOMEM; @@ -201974,16 +160718,16 @@ } } /* ** Attempt to advance the node-reader object passed as the first argument to -** the next entry on the node. +** the next entry on the node. ** -** Return an error code if an error occurs (SQLITE_NOMEM is possible). +** Return an error code if an error occurs (SQLITE_NOMEM is possible). ** Otherwise return SQLITE_OK. If there is no next entry on the node ** (e.g. because the current entry is the last) set NodeReader->aNode to -** NULL to indicate EOF. Otherwise, populate the NodeReader structure output +** NULL to indicate EOF. Otherwise, populate the NodeReader structure output ** variables for the new entry. */ static int nodeReaderNext(NodeReader *p){ int bFirst = (p->term.n==0); /* True for first term on the node */ int nPrefix = 0; /* Bytes to copy from previous term */ @@ -201999,30 +160743,25 @@ if( bFirst==0 ){ p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix); } p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); - if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){ - return FTS_CORRUPT_VTAB; - } blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); - if( rc==SQLITE_OK && ALWAYS(p->term.a!=0) ){ + if( rc==SQLITE_OK ){ memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix); p->term.n = nPrefix+nSuffix; p->iOff += nSuffix; if( p->iChild==0 ){ p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); - if( (p->nNode-p->iOff)nDoclist ){ - return FTS_CORRUPT_VTAB; - } p->aDoclist = &p->aNode[p->iOff]; p->iOff += p->nDoclist; } } } - assert_fts3_nc( p->iOff<=p->nNode ); + assert( p->iOff<=p->nNode ); + return rc; } /* ** Release all dynamic resources held by node-reader object *p. @@ -202032,28 +160771,28 @@ } /* ** Initialize a node-reader object to read the node in buffer aNode/nNode. ** -** If successful, SQLITE_OK is returned and the NodeReader object set to +** If successful, SQLITE_OK is returned and the NodeReader object set to ** point to the first entry on the node (if any). Otherwise, an SQLite ** error code is returned. */ static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){ memset(p, 0, sizeof(NodeReader)); p->aNode = aNode; p->nNode = nNode; /* Figure out if this is a leaf or an internal node. */ - if( aNode && aNode[0] ){ + if( p->aNode[0] ){ /* An internal node. */ p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild); }else{ p->iOff = 1; } - return aNode ? nodeReaderNext(p) : SQLITE_OK; + return nodeReaderNext(p); } /* ** This function is called while writing an FTS segment each time a leaf o ** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed @@ -202081,22 +160820,21 @@ int nPrefix; int nSuffix; int nSpace; /* Figure out how much space the key will consume if it is written to - ** the current node of layer iLayer. Due to the prefix compression, + ** the current node of layer iLayer. Due to the prefix compression, ** the space required changes depending on which node the key is to ** be added to. */ nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm); nSuffix = nTerm - nPrefix; - if(nSuffix<=0 ) return FTS_CORRUPT_VTAB; nSpace = sqlite3Fts3VarintLen(nPrefix); nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ + if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ /* If the current node of layer iLayer contains zero keys, or if adding - ** the key to it will not cause it to grow to larger than nNodeSize + ** the key to it will not cause it to grow to larger than nNodeSize ** bytes in size, write the key here. */ Blob *pBlk = &pNode->block; if( pBlk->n==0 ){ blobGrowBuffer(pBlk, p->nNodeSize, &rc); @@ -202111,12 +160849,10 @@ if( rc==SQLITE_OK ){ if( pNode->key.n ){ pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix); } pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix); - assert( nPrefix+nSuffix<=nTerm ); - assert( nPrefix>=0 ); memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix); pBlk->n += nSuffix; memcpy(pNode->key.a, zTerm, nTerm); pNode->key.n = nTerm; @@ -202150,16 +160886,16 @@ ** header must be written before this function is called. ** ** A node header is a single 0x00 byte for a leaf node, or a height varint ** followed by the left-hand-child varint for an internal node. ** -** The term to be appended is passed via arguments zTerm/nTerm. For a +** The term to be appended is passed via arguments zTerm/nTerm. For a ** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal ** node, both aDoclist and nDoclist must be passed 0. ** ** If the size of the value in blob pPrev is zero, then this is the first -** term written to the node. Otherwise, pPrev contains a copy of the +** term written to the node. Otherwise, pPrev contains a copy of the ** previous term. Before this function returns, it is updated to contain a ** copy of zTerm/nTerm. ** ** It is assumed that the buffer associated with pNode is already large ** enough to accommodate the new entry. The buffer associated with pPrev @@ -202172,30 +160908,27 @@ Blob *pNode, /* Current node image to append to */ Blob *pPrev, /* Buffer containing previous term written */ const char *zTerm, /* New term to write */ int nTerm, /* Size of zTerm in bytes */ const char *aDoclist, /* Doclist (or NULL) to write */ - int nDoclist /* Size of aDoclist in bytes */ + int nDoclist /* Size of aDoclist in bytes */ ){ int rc = SQLITE_OK; /* Return code */ int bFirst = (pPrev->n==0); /* True if this is the first term written */ int nPrefix; /* Size of term prefix in bytes */ int nSuffix; /* Size of term suffix in bytes */ /* Node must have already been started. There must be a doclist for a ** leaf node, and there must not be a doclist for an internal node. */ assert( pNode->n>0 ); - assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) ); + assert( (pNode->a[0]=='\0')==(aDoclist!=0) ); blobGrowBuffer(pPrev, nTerm, &rc); if( rc!=SQLITE_OK ) return rc; - assert( pPrev!=0 ); - assert( pPrev->a!=0 ); nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); nSuffix = nTerm - nPrefix; - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; memcpy(pPrev->a, zTerm, nTerm); pPrev->n = nTerm; if( bFirst==0 ){ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix); @@ -202237,28 +160970,23 @@ NodeWriter *pLeaf; /* Object used to write leaf nodes */ pLeaf = &pWriter->aNodeWriter[0]; nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); nSuffix = nTerm - nPrefix; - if(nSuffix<=0 ) return FTS_CORRUPT_VTAB; nSpace = sqlite3Fts3VarintLen(nPrefix); nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; /* If the current block is not empty, and if adding this term/doclist - ** to the current block would make it larger than Fts3Table.nNodeSize bytes, - ** and if there is still room for another leaf page, write this block out to - ** the database. */ - if( pLeaf->block.n>0 - && (pLeaf->block.n + nSpace)>p->nNodeSize - && pLeaf->iBlock < (pWriter->iStart + pWriter->nLeafEst) - ){ + ** to the current block would make it larger than Fts3Table.nNodeSize + ** bytes, write this block out to the database. */ + if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){ rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); pWriter->nWork++; - /* Add the current term to the parent node. The term added to the + /* Add the current term to the parent node. The term added to the ** parent must: ** ** a) be greater than the largest term on the leaf node just written ** to the database (still available in pLeaf->key), and ** @@ -202319,11 +161047,11 @@ int i; /* Used to iterate through non-root layers */ int iRoot; /* Index of root in pWriter->aNodeWriter */ NodeWriter *pRoot; /* NodeWriter for root node */ int rc = *pRc; /* Error code */ - /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment + /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment ** root node. If the segment fits entirely on a single leaf node, iRoot ** will be set to 0. If the root node is the parent of the leaves, iRoot ** will be 1. And so on. */ for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){ NodeWriter *pNode = &pWriter->aNodeWriter[iRoot]; @@ -202337,21 +161065,21 @@ /* Empty output segment. This is a no-op. */ if( iRoot<0 ) return; /* The entire output segment fits on a single node. Normally, this means ** the node would be stored as a blob in the "root" column of the %_segdir - ** table. However, this is not permitted in this case. The problem is that - ** space has already been reserved in the %_segments table, and so the - ** start_block and end_block fields of the %_segdir table must be populated. - ** And, by design or by accident, released versions of FTS cannot handle + ** table. However, this is not permitted in this case. The problem is that + ** space has already been reserved in the %_segments table, and so the + ** start_block and end_block fields of the %_segdir table must be populated. + ** And, by design or by accident, released versions of FTS cannot handle ** segments that fit entirely on the root node with start_block!=0. ** - ** Instead, create a synthetic root node that contains nothing but a + ** Instead, create a synthetic root node that contains nothing but a ** pointer to the single content node. So that the segment consists of a ** single leaf and a single interior (root) node. ** - ** Todo: Better might be to defer allocating space in the %_segments + ** Todo: Better might be to defer allocating space in the %_segments ** table until we are sure it is needed. */ if( iRoot==0 ){ Blob *pBlock = &pWriter->aNodeWriter[1].block; blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc); @@ -202375,11 +161103,11 @@ sqlite3_free(pNode->key.a); } /* Write the %_segdir record. */ if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, + rc = fts3WriteSegdir(p, pWriter->iAbsLevel+1, /* level */ pWriter->iIdx, /* idx */ pWriter->iStart, /* start_block */ pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */ pWriter->iEnd, /* end_block */ @@ -202406,27 +161134,23 @@ const char *zRhs, int nRhs /* RHS of comparison */ ){ int nCmp = MIN(nLhs, nRhs); int res; - if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){ - res = memcmp(zLhs, zRhs, nCmp); - }else{ - res = 0; - } + res = memcmp(zLhs, zRhs, nCmp); if( res==0 ) res = nLhs - nRhs; return res; } /* -** Query to see if the entry in the %_segments table with blockid iEnd is +** Query to see if the entry in the %_segments table with blockid iEnd is ** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before -** returning. Otherwise, set *pbRes to 0. +** returning. Otherwise, set *pbRes to 0. ** -** Or, if an error occurs while querying the database, return an SQLite +** Or, if an error occurs while querying the database, return an SQLite ** error code. The final value of *pbRes is undefined in this case. ** ** This is used to test if a segment is an "appendable" segment. If it ** is, then a NULL entry has been inserted into the %_segments table ** with blockid %_segdir.end_block. @@ -202440,27 +161164,27 @@ if( rc==SQLITE_OK ){ sqlite3_bind_int64(pCheck, 1, iEnd); if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; rc = sqlite3_reset(pCheck); } - + *pbRes = bRes; return rc; } /* ** This function is called when initializing an incremental-merge operation. -** It checks if the existing segment with index value iIdx at absolute level +** It checks if the existing segment with index value iIdx at absolute level ** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the ** merge-writer object *pWriter is initialized to write to it. ** ** An existing segment can be appended to by an incremental merge if: ** ** * It was initially created as an appendable segment (with all required ** space pre-allocated), and ** -** * The first key read from the input (arguments zKey and nKey) is +** * The first key read from the input (arguments zKey and nKey) is ** greater than the largest key currently stored in the potential ** output segment. */ static int fts3IncrmergeLoad( Fts3Table *p, /* Fts3 table handle */ @@ -202494,14 +161218,10 @@ pWriter->nLeafData = pWriter->nLeafData * -1; } pWriter->bNoLeafData = (pWriter->nLeafData==0); nRoot = sqlite3_column_bytes(pSelect, 4); aRoot = sqlite3_column_blob(pSelect, 4); - if( aRoot==0 ){ - sqlite3_reset(pSelect); - return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB; - } }else{ return sqlite3_reset(pSelect); } /* Check for the zero-length marker in the %_segments table */ @@ -202533,14 +161253,10 @@ /* It is possible to append to this segment. Set up the IncrmergeWriter ** object to do so. */ int i; int nHeight = (int)aRoot[0]; NodeWriter *pNode; - if( nHeight<1 || nHeight>=FTS_MAX_APPENDABLE_HEIGHT ){ - sqlite3_reset(pSelect); - return FTS_CORRUPT_VTAB; - } pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT; pWriter->iStart = iStart; pWriter->iEnd = iEnd; pWriter->iAbsLevel = iAbsLevel; @@ -202550,50 +161266,38 @@ pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; } pNode = &pWriter->aNodeWriter[nHeight]; pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight; - blobGrowBuffer(&pNode->block, - MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc - ); + blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc); if( rc==SQLITE_OK ){ memcpy(pNode->block.a, aRoot, nRoot); pNode->block.n = nRoot; - memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING); } for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ NodeReader reader; - memset(&reader, 0, sizeof(reader)); pNode = &pWriter->aNodeWriter[i]; - if( pNode->block.a){ - rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); - while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); - blobGrowBuffer(&pNode->key, reader.term.n, &rc); - if( rc==SQLITE_OK ){ - assert_fts3_nc( reader.term.n>0 || reader.aNode==0 ); - if( reader.term.n>0 ){ - memcpy(pNode->key.a, reader.term.a, reader.term.n); - } - pNode->key.n = reader.term.n; - if( i>0 ){ - char *aBlock = 0; - int nBlock = 0; - pNode = &pWriter->aNodeWriter[i-1]; - pNode->iBlock = reader.iChild; - rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0); - blobGrowBuffer(&pNode->block, - MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc - ); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aBlock, nBlock); - pNode->block.n = nBlock; - memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING); - } - sqlite3_free(aBlock); - } + rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); + while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); + blobGrowBuffer(&pNode->key, reader.term.n, &rc); + if( rc==SQLITE_OK ){ + memcpy(pNode->key.a, reader.term.a, reader.term.n); + pNode->key.n = reader.term.n; + if( i>0 ){ + char *aBlock = 0; + int nBlock = 0; + pNode = &pWriter->aNodeWriter[i-1]; + pNode->iBlock = reader.iChild; + rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0); + blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc); + if( rc==SQLITE_OK ){ + memcpy(pNode->block.a, aBlock, nBlock); + pNode->block.n = nBlock; + } + sqlite3_free(aBlock); } } nodeReaderRelease(&reader); } } @@ -202606,17 +161310,17 @@ } /* ** Determine the largest segment index value that exists within absolute ** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus -** one before returning SQLITE_OK. Or, if there are no segments at all +** one before returning SQLITE_OK. Or, if there are no segments at all ** within level iAbsLevel, set *piIdx to zero. ** ** If an error occurs, return an SQLite error code. The final value of ** *piIdx is undefined in this case. */ -static int fts3IncrmergeOutputIdx( +static int fts3IncrmergeOutputIdx( Fts3Table *p, /* FTS Table handle */ sqlite3_int64 iAbsLevel, /* Absolute index of input segments */ int *piIdx /* OUT: Next free index at iAbsLevel+1 */ ){ int rc; @@ -202631,11 +161335,11 @@ } return rc; } -/* +/* ** Allocate an appendable output segment on absolute level iAbsLevel+1 ** with idx value iIdx. ** ** In the %_segdir table, a segment is defined by the values in three ** columns: @@ -202645,23 +161349,23 @@ ** end_block ** ** When an appendable segment is allocated, it is estimated that the ** maximum number of leaf blocks that may be required is the sum of the ** number of leaf blocks consumed by the input segments, plus the number -** of input segments, multiplied by two. This value is stored in stack +** of input segments, multiplied by two. This value is stored in stack ** variable nLeafEst. ** ** A total of 16*nLeafEst blocks are allocated when an appendable segment ** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous ** array of leaf nodes starts at the first block allocated. The array ** of interior nodes that are parents of the leaf nodes start at block ** (start_block + (1 + end_block - start_block) / 16). And so on. ** -** In the actual code below, the value "16" is replaced with the +** In the actual code below, the value "16" is replaced with the ** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT. */ -static int fts3IncrmergeWriter( +static int fts3IncrmergeWriter( Fts3Table *p, /* Fts3 table handle */ sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ int iIdx, /* Index of new output segment */ Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */ IncrmergeWriter *pWriter /* Populate this object */ @@ -202695,11 +161399,11 @@ rc = sqlite3_reset(pFirstBlock); } if( rc!=SQLITE_OK ) return rc; /* Insert the marker in the %_segments table to make sure nobody tries - ** to steal the space just allocated. This is also used to identify + ** to steal the space just allocated. This is also used to identify ** appendable segments. */ rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); if( rc!=SQLITE_OK ) return rc; pWriter->iAbsLevel = iAbsLevel; @@ -202712,17 +161416,17 @@ } return SQLITE_OK; } /* -** Remove an entry from the %_segdir table. This involves running the +** Remove an entry from the %_segdir table. This involves running the ** following two statements: ** ** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx ** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx ** -** The DELETE statement removes the specific %_segdir level. The UPDATE +** The DELETE statement removes the specific %_segdir level. The UPDATE ** statement ensures that the remaining segments have contiguously allocated ** idx values. */ static int fts3RemoveSegdirEntry( Fts3Table *p, /* FTS3 table handle */ @@ -202766,11 +161470,11 @@ sqlite3_bind_int64(pSelect, 1, iAbsLevel); while( SQLITE_ROW==sqlite3_step(pSelect) ){ if( nIdx>=nAlloc ){ int *aNew; nAlloc += 16; - aNew = sqlite3_realloc64(aIdx, nAlloc*sizeof(int)); + aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int)); if( !aNew ){ rc = SQLITE_NOMEM; break; } aIdx = aNew; @@ -202832,23 +161536,20 @@ sqlite3_int64 *piBlock /* OUT: Block number in next layer down */ ){ NodeReader reader; /* Reader object */ Blob prev = {0, 0, 0}; /* Previous term written to new node */ int rc = SQLITE_OK; /* Return code */ - int bLeaf; /* True for a leaf node */ - - if( nNode<1 ) return FTS_CORRUPT_VTAB; - bLeaf = aNode[0]=='\0'; + int bLeaf = aNode[0]=='\0'; /* True for a leaf node */ /* Allocate required output space */ blobGrowBuffer(pNew, nNode, &rc); if( rc!=SQLITE_OK ) return rc; pNew->n = 0; /* Populate new node buffer */ - for(rc = nodeReaderInit(&reader, aNode, nNode); - rc==SQLITE_OK && reader.aNode; + for(rc = nodeReaderInit(&reader, aNode, nNode); + rc==SQLITE_OK && reader.aNode; rc = nodeReaderNext(&reader) ){ if( pNew->n==0 ){ int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm); if( res<0 || (bLeaf==0 && res==0) ) continue; @@ -202871,11 +161572,11 @@ sqlite3_free(prev.a); return rc; } /* -** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute +** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute ** level iAbsLevel. This may involve deleting entries from the %_segments ** table, and modifying existing entries in both the %_segments and %_segdir ** tables. ** ** SQLITE_OK is returned if the segment is updated successfully. Or an @@ -202946,11 +161647,10 @@ sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); sqlite3_bind_int64(pChomp, 3, iAbsLevel); sqlite3_bind_int(pChomp, 4, iIdx); sqlite3_step(pChomp); rc = sqlite3_reset(pChomp); - sqlite3_bind_null(pChomp, 2); } } sqlite3_free(root.a); sqlite3_free(block.a); @@ -202995,13 +161695,13 @@ if( rc==SQLITE_OK ){ rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx); } *pnRem = 0; }else{ - /* The incremental merge did not copy all the data from this + /* The incremental merge did not copy all the data from this ** segment to the upper level. The segment is modified in place - ** so that it contains no keys smaller than zTerm/nTerm. */ + ** so that it contains no keys smaller than zTerm/nTerm. */ const char *zTerm = pSeg->zTerm; int nTerm = pSeg->nTerm; rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm); nRem++; } @@ -203026,18 +161726,17 @@ if( rc==SQLITE_OK ){ sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT); sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 2); } return rc; } /* -** Load an incr-merge hint from the database. The incr-merge hint, if one +** Load an incr-merge hint from the database. The incr-merge hint, if one ** exists, is stored in the rowid==1 row of the %_stat table. ** ** If successful, populate blob *pHint with the value read from the %_stat ** table and return SQLITE_OK. Otherwise, if an error occurs, return an ** SQLite error code. @@ -203055,11 +161754,11 @@ const char *aHint = sqlite3_column_blob(pSelect, 0); int nHint = sqlite3_column_bytes(pSelect, 0); if( aHint ){ blobGrowBuffer(pHint, nHint, &rc); if( rc==SQLITE_OK ){ - if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint); + memcpy(pHint->a, aHint, nHint); pHint->n = nHint; } } } rc2 = sqlite3_reset(pSelect); @@ -203070,11 +161769,11 @@ } /* ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. ** Otherwise, append an entry to the hint stored in blob *pHint. Each entry -** consists of two varints, the absolute level number of the input segments +** consists of two varints, the absolute level number of the input segments ** and the number of input segments. ** ** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs, ** set *pRc to an SQLite error code before returning. */ @@ -203091,44 +161790,40 @@ } } /* ** Read the last entry (most recently pushed) from the hint blob *pHint -** and then remove the entry. Write the two values read to *piAbsLevel and +** and then remove the entry. Write the two values read to *piAbsLevel and ** *pnInput before returning. ** ** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does ** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB. */ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ const int nHint = pHint->n; int i; - i = pHint->n-1; - if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB; + i = pHint->n-2; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - if( i==0 ) return FTS_CORRUPT_VTAB; - i--; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); - assert( i<=nHint ); if( i!=nHint ) return FTS_CORRUPT_VTAB; return SQLITE_OK; } /* ** Attempt an incremental merge that writes nMerge leaf blocks. ** -** Incremental merges happen nMin segments at a time. The segments -** to be merged are the nMin oldest segments (the ones with the smallest -** values for the _segdir.idx field) in the highest level that contains -** at least nMin segments. Multiple merges might occur in an attempt to +** Incremental merges happen nMin segments at a time. The segments +** to be merged are the nMin oldest segments (the ones with the smallest +** values for the _segdir.idx field) in the highest level that contains +** at least nMin segments. Multiple merges might occur in an attempt to ** write the quota of nMerge leaf blocks. */ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ int rc; /* Return code */ int nRem = nMerge; /* Number of leaf pages yet to be written */ @@ -203140,11 +161835,11 @@ Blob hint = {0, 0, 0}; /* Hint read from %_stat table */ int bDirtyHint = 0; /* True if blob 'hint' has been modified */ /* Allocate space for the cursor, filter and writer objects */ const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); - pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc); + pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc); if( !pWriter ) return SQLITE_NOMEM; pFilter = (Fts3SegFilter *)&pWriter[1]; pCsr = (Fts3MultiSegReader *)&pFilter[1]; rc = fts3IncrmergeHintLoad(p, &hint); @@ -203155,11 +161850,11 @@ int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ /* Search the %_segdir table for the absolute level with the smallest ** relative level number that contains at least nMin segments, if any. ** If one is found, set iAbsLevel to the absolute level number and - ** nSeg to nMin. If no level with at least nMin segments can be found, + ** nSeg to nMin. If no level with at least nMin segments can be found, ** set nSeg to -1. */ rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0); sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin)); if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ @@ -203171,28 +161866,22 @@ } rc = sqlite3_reset(pFindLevel); /* If the hint read from the %_stat table is not empty, check if the ** last entry in it specifies a relative level smaller than or equal - ** to the level identified by the block above (if any). If so, this + ** to the level identified by the block above (if any). If so, this ** iteration of the loop will work on merging at the hinted level. */ if( rc==SQLITE_OK && hint.n ){ int nHint = hint.n; sqlite3_int64 iHintAbsLevel = 0; /* Hint level */ int nHintSeg = 0; /* Hint number of segments */ rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg); if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){ - /* Based on the scan in the block above, it is known that there - ** are no levels with a relative level smaller than that of - ** iAbsLevel with more than nSeg segments, or if nSeg is -1, - ** no levels with more than nMin segments. Use this to limit the - ** value of nHintSeg to avoid a large memory allocation in case the - ** merge-hint is corrupt*/ iAbsLevel = iHintAbsLevel; - nSeg = MIN(MAX(nMin,nSeg), nHintSeg); + nSeg = nHintSeg; bUseHint = 1; bDirtyHint = 1; }else{ /* This undoes the effect of the HintPop() above - so that no entry ** is removed from the hint blob. */ @@ -203201,23 +161890,17 @@ } /* If nSeg is less that zero, then there is no level with at least ** nMin segments and no hint in the %_stat table. No work to do. ** Exit early in this case. */ - if( nSeg<=0 ) break; - - assert( nMod<=0x7FFFFFFF ); - if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){ - rc = FTS_CORRUPT_VTAB; - break; - } - - /* Open a cursor to iterate through the contents of the oldest nSeg - ** indexes of absolute level iAbsLevel. If this cursor is opened using + if( nSeg<0 ) break; + + /* Open a cursor to iterate through the contents of the oldest nSeg + ** indexes of absolute level iAbsLevel. If this cursor is opened using ** the 'hint' parameters, it is possible that there are less than nSeg ** segments available in level iAbsLevel. In this case, no work is - ** done on iAbsLevel - fall through to the next iteration of the loop + ** done on iAbsLevel - fall through to the next iteration of the loop ** to start work on some other level. */ memset(pWriter, 0, nAlloc); pFilter->flags = FTS3_SEGMENT_REQUIRE_POS; if( rc==SQLITE_OK ){ @@ -203235,19 +161918,12 @@ if( rc==SQLITE_OK ){ rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr); } if( SQLITE_OK==rc && pCsr->nSegment==nSeg && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) + && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) ){ - int bEmpty = 0; - rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( rc==SQLITE_OK ){ - bEmpty = 1; - }else if( rc!=SQLITE_ROW ){ - sqlite3Fts3SegReaderFinish(pCsr); - break; - } if( bUseHint && iIdx>0 ){ const char *zKey = pCsr->zTerm; int nKey = pCsr->nTerm; rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); }else{ @@ -203254,17 +161930,15 @@ rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); } if( rc==SQLITE_OK && pWriter->nLeafEst ){ fts3LogMerge(nSeg, iAbsLevel); - if( bEmpty==0 ){ - do { - rc = fts3IncrmergeAppend(p, pWriter, pCsr); - if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; - }while( rc==SQLITE_ROW ); - } + do { + rc = fts3IncrmergeAppend(p, pWriter, pCsr); + if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); + if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; + }while( rc==SQLITE_ROW ); /* Update or delete the input segments */ if( rc==SQLITE_OK ){ nRem -= (1 + pWriter->nWork); rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg); @@ -203301,11 +161975,11 @@ ** Convert the text beginning at *pz into an integer and return ** its value. Advance *pz to point to the first character past ** the integer. ** ** This function used for parameters to merge= and incrmerge= -** commands. +** commands. */ static int fts3Getint(const char **pz){ const char *z = *pz; int i = 0; while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0'; @@ -203325,11 +161999,11 @@ static int fts3DoIncrmerge( Fts3Table *p, /* FTS3 table handle */ const char *zParam /* Nul-terminated string containing "A,B" */ ){ int rc; - int nMin = (MergeCount(p) / 2); + int nMin = (FTS3_MERGE_COUNT / 2); int nMerge = 0; const char *z = zParam; /* Read the first integer value */ nMerge = fts3Getint(&z); @@ -203370,11 +162044,11 @@ const char *zParam /* Nul-terminated string containing boolean */ ){ int rc = SQLITE_OK; sqlite3_stmt *pStmt = 0; p->nAutoincrmerge = fts3Getint(&zParam); - if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){ + if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){ p->nAutoincrmerge = 8; } if( !p->bHasStat ){ assert( p->bFts4==0 ); sqlite3Fts3CreateStatTable(&rc, p); @@ -203432,11 +162106,11 @@ Fts3SegFilter filter; Fts3MultiSegReader csr; int rc; u64 cksum = 0; - if( *pRc ) return 0; + assert( *pRc==SQLITE_OK ); memset(&filter, 0, sizeof(filter)); memset(&csr, 0, sizeof(csr)); filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; filter.flags |= FTS3_SEGMENT_SCAN; @@ -203453,29 +162127,25 @@ char *pCsr = csr.aDoclist; char *pEnd = &pCsr[csr.nDoclist]; i64 iDocid = 0; i64 iCol = 0; - u64 iPos = 0; + i64 iPos = 0; pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); while( pCsrbDescIdx ){ - iDocid = (i64)((u64)iDocid - iVal); - }else{ - iDocid = (i64)((u64)iDocid + iVal); - } + pCsr += sqlite3Fts3GetVarint(pCsr, &iVal); + iDocid += iVal; } }else{ iPos += (iVal - 2); cksum = cksum ^ fts3ChecksumEntry( csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid, @@ -203496,14 +162166,14 @@ ** Check if the contents of the FTS index match the current contents of the ** content table. If no error occurs and the contents do match, set *pbOk ** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk ** to false before returning. ** -** If an error occurs (e.g. an OOM or IO error), return an SQLite error +** If an error occurs (e.g. an OOM or IO error), return an SQLite error ** code. The final value of *pbOk is undefined in this case. */ -SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){ +static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ int rc = SQLITE_OK; /* Return code */ u64 cksum1 = 0; /* Checksum based on FTS index contents */ u64 cksum2 = 0; /* Checksum based on %_content contents */ sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */ @@ -203527,11 +162197,11 @@ /* This block calculates the checksum according to the %_content table */ if( rc==SQLITE_OK ){ sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; sqlite3_stmt *pStmt = 0; char *zSql; - + zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); if( !zSql ){ rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); @@ -203544,13 +162214,14 @@ int iCol; for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ if( p->abNotindexed[iCol]==0 ){ const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); + int nText = sqlite3_column_bytes(pStmt, iCol+1); sqlite3_tokenizer_cursor *pT = 0; - rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT); + rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ int nToken = 0; /* Number of bytes in token */ int iDum1 = 0, iDum2 = 0; /* Dummy variables */ int iPos = 0; /* Position of token in zText */ @@ -203577,34 +162248,29 @@ } sqlite3_finalize(pStmt); } - if( rc==SQLITE_CORRUPT_VTAB ){ - rc = SQLITE_OK; - *pbOk = 0; - }else{ - *pbOk = (rc==SQLITE_OK && cksum1==cksum2); - } + *pbOk = (cksum1==cksum2); return rc; } /* ** Run the integrity-check. If no error occurs and the current contents of ** the FTS index are correct, return SQLITE_OK. Or, if the contents of the ** FTS index are incorrect, return SQLITE_CORRUPT_VTAB. ** -** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite +** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite ** error code. ** ** The integrity-check works as follows. For each token and indexed token ** prefix in the document set, a 64-bit checksum is calculated (by code ** in fts3ChecksumEntry()) based on the following: ** ** + The index number (0 for the main index, 1 for the first prefix ** index etc.), -** + The token (or token prefix) text itself, +** + The token (or token prefix) text itself, ** + The language-id of the row it appears in, ** + The docid of the row it appears in, ** + The column it appears in, and ** + The tokens position within that column. ** @@ -203611,11 +162277,11 @@ ** The checksums for all entries in the index are XORed together to create ** a single checksum for the entire index. ** ** The integrity-check code calculates the same checksum in two ways: ** -** 1. By scanning the contents of the FTS index, and +** 1. By scanning the contents of the FTS index, and ** 2. By scanning and tokenizing the content table. ** ** If the two checksums are identical, the integrity-check is deemed to have ** passed. */ @@ -203622,25 +162288,25 @@ static int fts3DoIntegrityCheck( Fts3Table *p /* FTS3 table handle */ ){ int rc; int bOk = 0; - rc = sqlite3Fts3IntegrityCheck(p, &bOk); + rc = fts3IntegrityCheck(p, &bOk); if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; return rc; } /* ** Handle a 'special' INSERT of the form: ** ** "INSERT INTO tbl(tbl) VALUES()" ** -** Argument pVal contains the result of . Currently the only +** Argument pVal contains the result of . Currently the only ** meaningful value to insert is the text 'optimize'. */ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ - int rc = SQLITE_ERROR; /* Return Code */ + int rc; /* Return Code */ const char *zVal = (const char *)sqlite3_value_text(pVal); int nVal = sqlite3_value_bytes(pVal); if( !zVal ){ return SQLITE_NOMEM; @@ -203652,34 +162318,25 @@ rc = fts3DoIntegrityCheck(p); }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){ rc = fts3DoIncrmerge(p, &zVal[6]); }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){ rc = fts3DoAutoincrmerge(p, &zVal[10]); - }else if( nVal==5 && 0==sqlite3_strnicmp(zVal, "flush", 5) ){ - rc = sqlite3Fts3PendingTermsFlush(p); - } -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - else{ - int v; - if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ - v = atoi(&zVal[9]); - if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v; - rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ - v = atoi(&zVal[11]); - if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v; - rc = SQLITE_OK; - }else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){ - p->bNoIncrDoclist = atoi(&zVal[21]); - rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){ - v = atoi(&zVal[11]); - if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v; - rc = SQLITE_OK; - } - } -#endif +#ifdef SQLITE_TEST + }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ + p->nNodeSize = atoi(&zVal[9]); + rc = SQLITE_OK; + }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ + p->nMaxPendingData = atoi(&zVal[11]); + rc = SQLITE_OK; + }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){ + p->bNoIncrDoclist = atoi(&zVal[21]); + rc = SQLITE_OK; +#endif + }else{ + rc = SQLITE_ERROR; + } + return rc; } #ifndef SQLITE_DISABLE_FTS4_DEFERRED /* @@ -203693,11 +162350,11 @@ pDef->pList = 0; } } /* -** Free all entries in the pCsr->pDeffered list. Entries are added to +** Free all entries in the pCsr->pDeffered list. Entries are added to ** this list using sqlite3Fts3DeferToken(). */ SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){ Fts3DeferredToken *pDef; Fts3DeferredToken *pNext; @@ -203721,18 +162378,18 @@ int rc = SQLITE_OK; /* Return code */ if( pCsr->pDeferred ){ int i; /* Used to iterate through table columns */ sqlite3_int64 iDocid; /* Docid of the row pCsr points to */ Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */ - + Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; sqlite3_tokenizer *pT = p->pTokenizer; sqlite3_tokenizer_module const *pModule = pT->pModule; - + assert( pCsr->isRequireSeek==0 ); iDocid = sqlite3_column_int64(pCsr->pStmt, 0); - + for(i=0; inColumn && rc==SQLITE_OK; i++){ if( p->abNotindexed[i]==0 ){ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); sqlite3_tokenizer_cursor *pTC = 0; @@ -203769,12 +162426,12 @@ return rc; } SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList( - Fts3DeferredToken *p, - char **ppData, + Fts3DeferredToken *p, + char **ppData, int *pnData ){ char *pRet; int nSkip; sqlite3_int64 dummy; @@ -203784,17 +162441,17 @@ if( p->pList==0 ){ return SQLITE_OK; } - pRet = (char *)sqlite3_malloc64(p->pList->nData); + pRet = (char *)sqlite3_malloc(p->pList->nData); if( !pRet ) return SQLITE_NOMEM; nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy); *pnData = p->pList->nData - nSkip; *ppData = pRet; - + memcpy(pRet, &p->pList->aData[nSkip], *pnData); return SQLITE_OK; } /* @@ -203804,17 +162461,17 @@ Fts3Cursor *pCsr, /* Fts3 table cursor */ Fts3PhraseToken *pToken, /* Token to defer */ int iCol /* Column that token must appear in (or -1) */ ){ Fts3DeferredToken *pDeferred; - pDeferred = sqlite3_malloc64(sizeof(*pDeferred)); + pDeferred = sqlite3_malloc(sizeof(*pDeferred)); if( !pDeferred ){ return SQLITE_NOMEM; } memset(pDeferred, 0, sizeof(*pDeferred)); pDeferred->pToken = pToken; - pDeferred->pNext = pCsr->pDeferred; + pDeferred->pNext = pCsr->pDeferred; pDeferred->iCol = iCol; pCsr->pDeferred = pDeferred; assert( pToken->pDeferred==0 ); pToken->pDeferred = pDeferred; @@ -203827,12 +162484,12 @@ ** SQLite value pRowid contains the rowid of a row that may or may not be ** present in the FTS3 table. If it is, delete it and adjust the contents ** of subsiduary data structures accordingly. */ static int fts3DeleteByRowid( - Fts3Table *p, - sqlite3_value *pRowid, + Fts3Table *p, + sqlite3_value *pRowid, int *pnChng, /* IN/OUT: Decrement if row is deleted */ u32 *aSzDel ){ int rc = SQLITE_OK; /* Return code */ int bFound = 0; /* True if *pRowid really is in the table */ @@ -203866,27 +162523,28 @@ /* ** This function does the work for the xUpdate method of FTS3 virtual ** tables. The schema of the virtual table being: ** -** CREATE TABLE
                ( +** CREATE TABLE
                ( ** , -**
                HIDDEN, -** docid HIDDEN, +**
                HIDDEN, +** docid HIDDEN, ** HIDDEN ** ); ** -** +** */ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( sqlite3_vtab *pVtab, /* FTS3 vtab object */ int nArg, /* Size of argument array */ sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ + int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ u32 *aSzDel = 0; /* Sizes of deleted documents */ int nChng = 0; /* Net change in number of documents */ int bInsertDone = 0; @@ -203893,22 +162551,22 @@ /* At this point it must be known if the %_stat table exists or not. ** So bHasStat may not be 2. */ assert( p->bHasStat==0 || p->bHasStat==1 ); assert( p->pSegments==0 ); - assert( + assert( nArg==1 /* DELETE operations */ || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ ); /* Check for a "special" INSERT operation. One of the form: ** ** INSERT INTO xyz(xyz) VALUES('command'); */ - if( nArg>1 - && sqlite3_value_type(apVal[0])==SQLITE_NULL - && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL + if( nArg>1 + && sqlite3_value_type(apVal[0])==SQLITE_NULL + && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){ rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); goto update_out; } @@ -203916,11 +162574,11 @@ rc = SQLITE_CONSTRAINT; goto update_out; } /* Allocate space to hold the change in document sizes */ - aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2); + aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 ); if( aSzDel==0 ){ rc = SQLITE_NOMEM; goto update_out; } aSzIns = &aSzDel[p->nColumn+1]; @@ -203943,28 +162601,28 @@ sqlite3_value *pNewRowid = apVal[3+p->nColumn]; if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){ pNewRowid = apVal[1]; } - if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && ( + if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && ( sqlite3_value_type(apVal[0])==SQLITE_NULL || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid) )){ /* The new rowid is not NULL (in this case the rowid will be - ** automatically assigned and there is no chance of a conflict), and + ** automatically assigned and there is no chance of a conflict), and ** the statement is either an INSERT or an UPDATE that modifies the ** rowid column. So if the conflict mode is REPLACE, then delete any - ** existing row with rowid=pNewRowid. + ** existing row with rowid=pNewRowid. ** - ** Or, if the conflict mode is not REPLACE, insert the new record into + ** Or, if the conflict mode is not REPLACE, insert the new record into ** the %_content table. If we hit the duplicate rowid constraint (or any ** other error) while doing so, return immediately. ** ** This branch may also run if pNewRowid contains a value that cannot - ** be losslessly converted to an integer. In this case, the eventual + ** be losslessly converted to an integer. In this case, the eventual ** call to fts3InsertData() (either just below or further on in this - ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is + ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is ** invoked, it will delete zero rows (since no row will have ** docid=$pNewRowid if $pNewRowid is not an integer value). */ if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){ rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel); @@ -203980,22 +162638,23 @@ /* If this is a DELETE or UPDATE operation, remove the old record. */ if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); + isRemove = 1; } - + /* If this is an INSERT or UPDATE operation, insert the new record. */ if( nArg>1 && rc==SQLITE_OK ){ int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); if( bInsertDone==0 ){ rc = fts3InsertData(p, apVal, pRowid); if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ rc = FTS_CORRUPT_VTAB; } } - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); } if( rc==SQLITE_OK ){ assert( p->iPrevDocid==*pRowid ); rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); @@ -204014,14 +162673,14 @@ sqlite3_free(aSzDel); sqlite3Fts3SegmentsClose(p); return rc; } -/* +/* ** Flush any data in the pending-terms hash table to disk. If successful, -** merge all segments in the database (including the new segment, if -** there was any data to flush) into a single segment. +** merge all segments in the database (including the new segment, if +** there was any data to flush) into a single segment. */ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ int rc; rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); if( rc==SQLITE_OK ){ @@ -204059,14 +162718,10 @@ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ /* #include */ -#ifndef SQLITE_AMALGAMATION -typedef sqlite3_int64 i64; -#endif - /* ** Characters that may appear in the second argument to matchinfo(). */ #define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ #define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ @@ -204077,17 +162732,17 @@ #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ #define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ #define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */ /* -** The default value for the second argument to matchinfo(). +** The default value for the second argument to matchinfo(). */ #define FTS3_MATCHINFO_DEFAULT "pcx" /* -** Used as an sqlite3Fts3ExprIterate() context when loading phrase doclists to +** Used as an fts3ExprIterate() context when loading phrase doclists to ** Fts3Expr.aDoclist[]/nDoclist. */ typedef struct LoadDoclistCtx LoadDoclistCtx; struct LoadDoclistCtx { Fts3Cursor *pCsr; /* FTS3 Cursor */ @@ -204094,11 +162749,11 @@ int nPhrase; /* Number of phrases seen so far */ int nToken; /* Number of tokens seen so far */ }; /* -** The following types are used as part of the implementation of the +** The following types are used as part of the implementation of the ** fts3BestSnippet() routine. */ typedef struct SnippetIter SnippetIter; typedef struct SnippetPhrase SnippetPhrase; typedef struct SnippetFragment SnippetFragment; @@ -204113,13 +162768,13 @@ }; struct SnippetPhrase { int nToken; /* Number of tokens in phrase */ char *pList; /* Pointer to start of phrase position list */ - i64 iHead; /* Next value in position list */ + int iHead; /* Next value in position list */ char *pHead; /* Position list data following iHead */ - i64 iTail; /* Next value in trailing position list */ + int iTail; /* Next value in trailing position list */ char *pTail; /* Position list data following iTail */ }; struct SnippetFragment { int iCol; /* Column snippet is extracted from */ @@ -204127,11 +162782,11 @@ u64 covered; /* Mask of query phrases covered */ u64 hlmask; /* Mask of snippet terms to highlight */ }; /* -** This type is used as an sqlite3Fts3ExprIterate() context object while +** This type is used as an fts3ExprIterate() context object while ** accumulating the data returned by the matchinfo() function. */ typedef struct MatchInfo MatchInfo; struct MatchInfo { Fts3Cursor *pCursor; /* FTS3 Cursor */ @@ -204174,22 +162829,21 @@ */ /* ** Allocate a two-slot MatchinfoBuffer object. */ -static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){ +static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){ MatchinfoBuffer *pRet; - sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1) - + sizeof(MatchinfoBuffer); - sqlite3_int64 nStr = strlen(zMatchinfo); + int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer); + int nStr = (int)strlen(zMatchinfo); - pRet = sqlite3Fts3MallocZero(nByte + nStr+1); + pRet = sqlite3_malloc(nByte + nStr+1); if( pRet ){ + memset(pRet, 0, nByte); pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet; - pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] - + sizeof(u32)*((int)nElem+1); - pRet->nElem = (int)nElem; + pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1); + pRet->nElem = nElem; pRet->zMatchinfo = ((char*)pRet) + nByte; memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); pRet->aRef[0] = 1; } @@ -204197,12 +162851,12 @@ } static void fts3MIBufferFree(void *p){ MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]); - assert( (u32*)p==&pBuf->aMatchinfo[1] - || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2] + assert( (u32*)p==&pBuf->aMatchinfo[1] + || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2] ); if( (u32*)p==&pBuf->aMatchinfo[1] ){ pBuf->aRef[1] = 0; }else{ pBuf->aRef[2] = 0; @@ -204225,11 +162879,11 @@ else if( p->aRef[2]==0 ){ p->aRef[2] = 1; aOut = &p->aMatchinfo[p->nElem+2]; xRet = fts3MIBufferFree; }else{ - aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32)); + aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32)); if( aOut ){ xRet = sqlite3_free; if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32)); } } @@ -204254,11 +162908,11 @@ sqlite3_free(p); } } } -/* +/* ** End of MatchinfoBuffer code. *************************************************************************/ /* @@ -204279,18 +162933,18 @@ ** When this function is called, *pp points to the start of an element of ** the list. *piPos contains the value of the previous entry in the list. ** After it returns, *piPos contains the value of the next element of the ** list and *pp is advanced to the following varint. */ -static void fts3GetDeltaPosition(char **pp, i64 *piPos){ +static void fts3GetDeltaPosition(char **pp, int *piPos){ int iVal; *pp += fts3GetVarint32(*pp, &iVal); *piPos += (iVal-2); } /* -** Helper function for sqlite3Fts3ExprIterate() (see below). +** Helper function for fts3ExprIterate() (see below). */ static int fts3ExprIterate2( Fts3Expr *pExpr, /* Expression to iterate phrases of */ int *piPhrase, /* Pointer to phrase counter */ int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ @@ -204315,27 +162969,28 @@ /* ** Iterate through all phrase nodes in an FTS3 query, except those that ** are part of a sub-tree that is the right-hand-side of a NOT operator. ** For each phrase node found, the supplied callback function is invoked. ** -** If the callback function returns anything other than SQLITE_OK, +** If the callback function returns anything other than SQLITE_OK, ** the iteration is abandoned and the error code returned immediately. ** Otherwise, SQLITE_OK is returned after a callback has been made for ** all eligible phrase nodes. */ -SQLITE_PRIVATE int sqlite3Fts3ExprIterate( +static int fts3ExprIterate( Fts3Expr *pExpr, /* Expression to iterate phrases of */ int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ void *pCtx /* Second argument to pass to callback */ ){ int iPhrase = 0; /* Variable used as the phrase counter */ return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); } + /* -** This is an sqlite3Fts3ExprIterate() callback used while loading the -** doclists for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also +** This is an fts3ExprIterate() callback used while loading the doclists +** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also ** fts3ExprLoadDoclists(). */ static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ int rc = SQLITE_OK; Fts3Phrase *pPhrase = pExpr->pPhrase; @@ -204349,27 +163004,27 @@ return rc; } /* ** Load the doclists for each phrase in the query associated with FTS3 cursor -** pCsr. +** pCsr. ** -** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable -** phrases in the expression (all phrases except those directly or -** indirectly descended from the right-hand-side of a NOT operator). If +** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable +** phrases in the expression (all phrases except those directly or +** indirectly descended from the right-hand-side of a NOT operator). If ** pnToken is not NULL, then it is set to the number of tokens in all ** matchable phrases of the expression. */ static int fts3ExprLoadDoclists( Fts3Cursor *pCsr, /* Fts3 cursor for current query */ int *pnPhrase, /* OUT: Number of phrases in query */ int *pnToken /* OUT: Number of tokens in query */ ){ int rc; /* Return Code */ - LoadDoclistCtx sCtx = {0,0,0}; /* Context for sqlite3Fts3ExprIterate() */ + LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ sCtx.pCsr = pCsr; - rc = sqlite3Fts3ExprIterate(pCsr->pExpr,fts3ExprLoadDoclistsCb,(void*)&sCtx); + rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); if( pnPhrase ) *pnPhrase = sCtx.nPhrase; if( pnToken ) *pnToken = sCtx.nToken; return rc; } @@ -204378,23 +163033,23 @@ pExpr->iPhrase = iPhrase; return SQLITE_OK; } static int fts3ExprPhraseCount(Fts3Expr *pExpr){ int nPhrase = 0; - (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); + (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); return nPhrase; } /* -** Advance the position list iterator specified by the first two +** Advance the position list iterator specified by the first two ** arguments so that it points to the first element with a value greater ** than or equal to parameter iNext. */ -static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){ +static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){ char *pIter = *ppIter; if( pIter ){ - i64 iIter = *piIter; + int iIter = *piIter; while( iIternSnippet>=0 ); pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; for(i=0; inPhrase; i++){ SnippetPhrase *pPhrase = &pIter->aPhrase[i]; fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); @@ -204453,11 +163107,11 @@ return 0; } /* -** Retrieve information about the current candidate snippet of snippet +** Retrieve information about the current candidate snippet of snippet ** iterator pIter. */ static void fts3SnippetDetails( SnippetIter *pIter, /* Snippet iterator */ u64 mCovered, /* Bitmask of phrases already covered */ @@ -204474,26 +163128,25 @@ for(i=0; inPhrase; i++){ SnippetPhrase *pPhrase = &pIter->aPhrase[i]; if( pPhrase->pTail ){ char *pCsr = pPhrase->pTail; - i64 iCsr = pPhrase->iTail; + int iCsr = pPhrase->iTail; - while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){ + while( iCsr<(iStart+pIter->nSnippet) ){ int j; - u64 mPhrase = (u64)1 << (i%64); + u64 mPhrase = (u64)1 << i; u64 mPos = (u64)1 << (iCsr - iStart); - assert( iCsr>=iStart && (iCsr - iStart)<=64 ); - assert( i>=0 ); + assert( iCsr>=iStart ); if( (mCover|mCovered)&mPhrase ){ iScore++; }else{ iScore += 1000; } mCover |= mPhrase; - for(j=0; jnToken && jnSnippet; j++){ + for(j=0; jnToken; j++){ mHighlight |= (mPos>>j); } if( 0==(*pCsr & 0x0FE) ) break; fts3GetDeltaPosition(&pCsr, &iCsr); @@ -204507,13 +163160,12 @@ *pmCover = mCover; *pmHighlight = mHighlight; } /* -** This function is an sqlite3Fts3ExprIterate() callback used by -** fts3BestSnippet(). Each invocation populates an element of the -** SnippetIter.aPhrase[] array. +** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). +** Each invocation populates an element of the SnippetIter.aPhrase[] array. */ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ SnippetIter *p = (SnippetIter *)ctx; SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; char *pCsr; @@ -204521,39 +163173,36 @@ pPhrase->nToken = pExpr->pPhrase->nToken; rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr); assert( rc==SQLITE_OK || pCsr==0 ); if( pCsr ){ - i64 iFirst = 0; + int iFirst = 0; pPhrase->pList = pCsr; fts3GetDeltaPosition(&pCsr, &iFirst); - if( iFirst<0 ){ - rc = FTS_CORRUPT_VTAB; - }else{ - pPhrase->pHead = pCsr; - pPhrase->pTail = pCsr; - pPhrase->iHead = iFirst; - pPhrase->iTail = iFirst; - } + assert( iFirst>=0 ); + pPhrase->pHead = pCsr; + pPhrase->pTail = pCsr; + pPhrase->iHead = iFirst; + pPhrase->iTail = iFirst; }else{ assert( rc!=SQLITE_OK || ( - pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 + pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 )); } return rc; } /* -** Select the fragment of text consisting of nFragment contiguous tokens +** Select the fragment of text consisting of nFragment contiguous tokens ** from column iCol that represent the "best" snippet. The best snippet ** is the snippet with the highest score, where scores are calculated ** by adding: ** ** (a) +1 point for each occurrence of a matchable phrase in the snippet. ** -** (b) +1000 points for the first occurrence of each matchable phrase in +** (b) +1000 points for the first occurrence of each matchable phrase in ** the snippet for which the corresponding mCovered bit is not set. ** ** The selected snippet parameters are stored in structure *pFragment before ** returning. The score of the selected snippet is stored in *piScore ** before returning. @@ -204568,11 +163217,11 @@ int *piScore /* OUT: Score of snippet pFragment */ ){ int rc; /* Return Code */ int nList; /* Number of phrases in expression */ SnippetIter sIter; /* Iterates through snippet candidates */ - sqlite3_int64 nByte; /* Number of bytes of space to allocate */ + int nByte; /* Number of bytes of space to allocate */ int iBestScore = -1; /* Best snippet score found so far */ int i; /* Loop counter */ memset(&sIter, 0, sizeof(sIter)); @@ -204586,36 +163235,35 @@ /* Now that it is known how many phrases there are, allocate and zero ** the required space using malloc(). */ nByte = sizeof(SnippetPhrase) * nList; - sIter.aPhrase = (SnippetPhrase *)sqlite3Fts3MallocZero(nByte); + sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte); if( !sIter.aPhrase ){ return SQLITE_NOMEM; } + memset(sIter.aPhrase, 0, nByte); /* Initialize the contents of the SnippetIter object. Then iterate through ** the set of phrases in the expression to populate the aPhrase[] array. */ sIter.pCsr = pCsr; sIter.iCol = iCol; sIter.nSnippet = nSnippet; sIter.nPhrase = nList; sIter.iCurrent = -1; - rc = sqlite3Fts3ExprIterate( - pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter - ); + rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter); if( rc==SQLITE_OK ){ /* Set the *pmSeen output variable. */ for(i=0; iiCol = iCol; while( !fts3SnippetNextCandidate(&sIter) ){ int iPos; @@ -204657,12 +163305,12 @@ /* If there is insufficient space allocated at StrBuffer.z, use realloc() ** to grow the buffer until so that it is big enough to accomadate the ** appended data. */ if( pStr->n+nAppend+1>=pStr->nAlloc ){ - sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100; - char *zNew = sqlite3_realloc64(pStr->z, nAlloc); + int nAlloc = pStr->nAlloc+nAppend+100; + char *zNew = sqlite3_realloc(pStr->z, nAlloc); if( !zNew ){ return SQLITE_NOMEM; } pStr->z = zNew; pStr->nAlloc = nAlloc; @@ -204683,21 +163331,21 @@ ** that requires highlighting. For example, if 'X' is a highlighted term ** and '.' is a non-highlighted term, BestSnippet() may select: ** ** ........X.....X ** -** This function "shifts" the beginning of the snippet forward in the -** document so that there are approximately the same number of +** This function "shifts" the beginning of the snippet forward in the +** document so that there are approximately the same number of ** non-highlighted terms to the right of the final highlighted term as there ** are to the left of the first highlighted term. For example, to this: ** ** ....X.....X.... ** ** This is done as part of extracting the snippet text, not when selecting ** the snippet. Snippet selection is done based on doclists only, so there -** is no way for fts3BestSnippet() to know whether or not the document -** actually contains terms that follow the final highlighted term. +** is no way for fts3BestSnippet() to know whether or not the document +** actually contains terms that follow the final highlighted term. */ static int fts3SnippetShift( Fts3Table *pTab, /* FTS3 table snippet comes from */ int iLangid, /* Language id to use in tokenizing */ int nSnippet, /* Number of tokens desired for snippet */ @@ -204713,11 +163361,10 @@ int nRight; /* Tokens to the right of last highlight */ int nDesired; /* Ideal number of tokens to shift forward */ for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); - assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 ); nDesired = (nLeft-nRight)/2; /* Ideally, the start of the snippet should be pushed forward in the ** document nDesired tokens. This block checks if there are actually ** nDesired tokens to the right of the snippet. If so, *piPos and @@ -204783,11 +163430,11 @@ int iPos = pFragment->iPos; /* First token of snippet */ u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ int iCol = pFragment->iCol+1; /* Query column to extract text from */ sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ - + zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); if( zDoc==0 ){ if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ return SQLITE_NOMEM; } @@ -204823,11 +163470,11 @@ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ /* Special case - the last token of the snippet is also the last token ** of the column. Append any punctuation that occurred between the end - ** of the previous token and the end of the document to the output. + ** of the previous token and the end of the document to the output. ** Then break out of the loop. */ rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); } break; } @@ -204840,11 +163487,11 @@ ); isShiftDone = 1; /* Now that the shift has been done, check if the initial "..." are ** required. They are required if (a) this is not the first fragment, - ** or (b) this fragment does not begin at position 0 of its column. + ** or (b) this fragment does not begin at position 0 of its column. */ if( rc==SQLITE_OK ){ if( iPos>0 || iFragment>0 ){ rc = fts3StringAppend(pOut, zEllipsis, -1); }else if( iBegin ){ @@ -204876,12 +163523,12 @@ return rc; } /* -** This function is used to count the entries in a column-list (a -** delta-encoded list of term offsets within a single column of a single +** This function is used to count the entries in a column-list (a +** delta-encoded list of term offsets within a single column of a single ** row). When this function is called, *ppCollist should point to the ** beginning of the first varint in the column-list (the varint that ** contains the position of the first matching term in the column data). ** Before returning, *ppCollist is set to point to the first byte after ** the last varint in the column-list (either the 0x00 signifying the end @@ -204906,11 +163553,11 @@ } /* ** This function gathers 'y' or 'b' data for a single phrase. */ -static int fts3ExprLHits( +static void fts3ExprLHits( Fts3Expr *pExpr, /* Phrase expression node */ MatchInfo *p /* Matchinfo context */ ){ Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab; int iStart; @@ -204923,11 +163570,11 @@ iStart = pExpr->iPhrase * p->nCol; }else{ iStart = pExpr->iPhrase * ((p->nCol + 31) / 32); } - if( pIter ) while( 1 ){ + while( 1 ){ int nHit = fts3ColumnlistCount(&pIter); if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ if( p->flag==FTS3_MATCHINFO_LHITS ){ p->aMatchinfo[iStart + iCol] = (u32)nHit; }else if( nHit ){ @@ -204936,42 +163583,38 @@ } assert( *pIter==0x00 || *pIter==0x01 ); if( *pIter!=0x01 ) break; pIter++; pIter += fts3GetVarint32(pIter, &iCol); - if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB; } - return SQLITE_OK; } /* ** Gather the results for matchinfo directives 'y' and 'b'. */ -static int fts3ExprLHitGather( +static void fts3ExprLHitGather( Fts3Expr *pExpr, MatchInfo *p ){ - int rc = SQLITE_OK; assert( (pExpr->pLeft==0)==(pExpr->pRight==0) ); if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ if( pExpr->pLeft ){ - rc = fts3ExprLHitGather(pExpr->pLeft, p); - if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p); + fts3ExprLHitGather(pExpr->pLeft, p); + fts3ExprLHitGather(pExpr->pRight, p); }else{ - rc = fts3ExprLHits(pExpr, p); + fts3ExprLHits(pExpr, p); } } - return rc; } /* -** sqlite3Fts3ExprIterate() callback used to collect the "global" matchinfo -** stats for a single query. +** fts3ExprIterate() callback used to collect the "global" matchinfo stats +** for a single query. ** -** sqlite3Fts3ExprIterate() callback to load the 'global' elements of a -** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements -** of the matchinfo array that are constant for all rows returned by the +** fts3ExprIterate() callback to load the 'global' elements of a +** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements +** of the matchinfo array that are constant for all rows returned by the ** current query. ** ** Argument pCtx is actually a pointer to a struct of type MatchInfo. This ** function populates Matchinfo.aMatchinfo[] as follows: ** @@ -204983,11 +163626,11 @@ ** where X is the number of matches for phrase iPhrase is column iCol of all ** rows of the table. Y is the number of rows for which column iCol contains ** at least one instance of phrase iPhrase. ** ** If the phrase pExpr consists entirely of deferred tokens, then all X and -** Y values are set to nDoc, where nDoc is the number of documents in the +** Y values are set to nDoc, where nDoc is the number of documents in the ** file system. This is done because the full-text index doclist is required ** to calculate these values properly, and the full-text index doclist is ** not available for deferred tokens. */ static int fts3ExprGlobalHitsCb( @@ -205000,12 +163643,12 @@ p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol] ); } /* -** sqlite3Fts3ExprIterate() callback used to collect the "local" part of the -** FTS3_MATCHINFO_HITS array. The local stats are those elements of the +** fts3ExprIterate() callback used to collect the "local" part of the +** FTS3_MATCHINFO_HITS array. The local stats are those elements of the ** array that are different for each row returned by the query. */ static int fts3ExprLocalHitsCb( Fts3Expr *pExpr, /* Phrase expression node */ int iPhrase, /* Phrase number */ @@ -205028,11 +163671,11 @@ return rc; } static int fts3MatchinfoCheck( - Fts3Table *pTab, + Fts3Table *pTab, char cArg, char **pzErr ){ if( (cArg==FTS3_MATCHINFO_NPHRASE) || (cArg==FTS3_MATCHINFO_NCOL) @@ -205048,17 +163691,17 @@ } sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg); return SQLITE_ERROR; } -static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ - size_t nVal; /* Number of integers output by cArg */ +static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ + int nVal; /* Number of integers output by cArg */ switch( cArg ){ case FTS3_MATCHINFO_NDOC: - case FTS3_MATCHINFO_NPHRASE: - case FTS3_MATCHINFO_NCOL: + case FTS3_MATCHINFO_NPHRASE: + case FTS3_MATCHINFO_NCOL: nVal = 1; break; case FTS3_MATCHINFO_AVGLENGTH: case FTS3_MATCHINFO_LENGTH: @@ -205085,46 +163728,34 @@ static int fts3MatchinfoSelectDoctotal( Fts3Table *pTab, sqlite3_stmt **ppStmt, sqlite3_int64 *pnDoc, - const char **paLen, - const char **ppEnd + const char **paLen ){ sqlite3_stmt *pStmt; const char *a; - const char *pEnd; sqlite3_int64 nDoc; - int n; - if( !*ppStmt ){ int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt); if( rc!=SQLITE_OK ) return rc; } pStmt = *ppStmt; assert( sqlite3_data_count(pStmt)==1 ); - n = sqlite3_column_bytes(pStmt, 0); a = sqlite3_column_blob(pStmt, 0); - if( a==0 ){ - return FTS_CORRUPT_VTAB; - } - pEnd = a + n; - a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc); - if( nDoc<=0 || a>pEnd ){ - return FTS_CORRUPT_VTAB; - } - *pnDoc = nDoc; + a += sqlite3Fts3GetVarint(a, &nDoc); + if( nDoc==0 ) return FTS_CORRUPT_VTAB; + *pnDoc = (u32)nDoc; if( paLen ) *paLen = a; - if( ppEnd ) *ppEnd = pEnd; return SQLITE_OK; } /* -** An instance of the following structure is used to store state while +** An instance of the following structure is used to store state while ** iterating through a multi-column position-list corresponding to the ** hits for a single phrase on a single row in order to calculate the ** values for a matchinfo() FTS3_MATCHINFO_LCS request. */ typedef struct LcsIterator LcsIterator; @@ -205133,11 +163764,11 @@ int iPosOffset; /* Tokens count up to end of this phrase */ char *pRead; /* Cursor used to iterate through aDoclist */ int iPos; /* Current position */ }; -/* +/* ** If LcsIterator.iCol is set to the following value, the iterator has ** finished iterating through all offsets for all columns. */ #define LCS_ITERATOR_FINISHED 0x7FFFFFFF; @@ -205155,16 +163786,14 @@ ** Advance the iterator passed as an argument to the next position. Return ** 1 if the iterator is at EOF or if it now points to the start of the ** position list for the next column. */ static int fts3LcsIteratorAdvance(LcsIterator *pIter){ - char *pRead; + char *pRead = pIter->pRead; sqlite3_int64 iRead; int rc = 0; - if( NEVER(pIter==0) ) return 1; - pRead = pIter->pRead; pRead += sqlite3Fts3GetVarint(pRead, &iRead); if( iRead==0 || iRead==1 ){ pRead = 0; rc = 1; }else{ @@ -205172,35 +163801,35 @@ } pIter->pRead = pRead; return rc; } - + /* -** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. +** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. ** ** If the call is successful, the longest-common-substring lengths for each -** column are written into the first nCol elements of the pInfo->aMatchinfo[] +** column are written into the first nCol elements of the pInfo->aMatchinfo[] ** array before returning. SQLITE_OK is returned in this case. ** ** Otherwise, if an error occurs, an SQLite error code is returned and the -** data written to the first nCol elements of pInfo->aMatchinfo[] is +** data written to the first nCol elements of pInfo->aMatchinfo[] is ** undefined. */ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ LcsIterator *aIter; int i; int iCol; int nToken = 0; - int rc = SQLITE_OK; /* Allocate and populate the array of LcsIterator objects. The array ** contains one element for each matchable phrase in the query. **/ - aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase); + aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase); if( !aIter ) return SQLITE_NOMEM; - (void)sqlite3Fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); + memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase); + (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); for(i=0; inPhrase; i++){ LcsIterator *pIter = &aIter[i]; nToken -= pIter->pExpr->pPhrase->nToken; pIter->iPosOffset = nToken; @@ -205209,20 +163838,17 @@ for(iCol=0; iColnCol; iCol++){ int nLcs = 0; /* LCS value for this column */ int nLive = 0; /* Number of iterators in aIter not at EOF */ for(i=0; inPhrase; i++){ + int rc; LcsIterator *pIt = &aIter[i]; rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead); - if( rc!=SQLITE_OK ) goto matchinfo_lcs_out; + if( rc!=SQLITE_OK ) return rc; if( pIt->pRead ){ pIt->iPos = pIt->iPosOffset; - fts3LcsIteratorAdvance(pIt); - if( pIt->pRead==0 ){ - rc = FTS_CORRUPT_VTAB; - goto matchinfo_lcs_out; - } + fts3LcsIteratorAdvance(&aIter[i]); nLive++; } } while( nLive>0 ){ @@ -205250,18 +163876,17 @@ } pInfo->aMatchinfo[iCol] = nLcs; } - matchinfo_lcs_out: sqlite3_free(aIter); - return rc; + return SQLITE_OK; } /* ** Populate the buffer pInfo->aMatchinfo[] with an array of integers to -** be returned by the matchinfo() function. Argument zArg contains the +** be returned by the matchinfo() function. Argument zArg contains the ** format string passed as the second argument to matchinfo (or the ** default value "pcx" if no second argument was specified). The format ** string has already been validated and the pInfo->aMatchinfo[] array ** is guaranteed to be large enough for the output. ** @@ -205268,11 +163893,11 @@ ** If bGlobal is true, then populate all fields of the matchinfo() output. ** If it is false, then assume that those fields that do not change between ** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS) ** have already been populated. ** -** Return SQLITE_OK if successful, or an SQLite error code if an error +** Return SQLITE_OK if successful, or an SQLite error code if an error ** occurs. If a value other than SQLITE_OK is returned, the state the ** pInfo->aMatchinfo[] buffer is left in is undefined. */ static int fts3MatchinfoValues( Fts3Cursor *pCsr, /* FTS3 cursor object */ @@ -205293,36 +163918,31 @@ break; case FTS3_MATCHINFO_NCOL: if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol; break; - + case FTS3_MATCHINFO_NDOC: if( bGlobal ){ sqlite3_int64 nDoc = 0; - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0); + rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0); pInfo->aMatchinfo[0] = (u32)nDoc; } break; - case FTS3_MATCHINFO_AVGLENGTH: + case FTS3_MATCHINFO_AVGLENGTH: if( bGlobal ){ sqlite3_int64 nDoc; /* Number of rows in table */ const char *a; /* Aggregate column length array */ - const char *pEnd; /* First byte past end of length array */ - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd); + rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a); if( rc==SQLITE_OK ){ int iCol; for(iCol=0; iColnCol; iCol++){ u32 iVal; sqlite3_int64 nToken; a += sqlite3Fts3GetVarint(a, &nToken); - if( a>pEnd ){ - rc = SQLITE_CORRUPT_VTAB; - break; - } iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc); pInfo->aMatchinfo[iCol] = iVal; } } } @@ -205332,18 +163952,13 @@ sqlite3_stmt *pSelectDocsize = 0; rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize); if( rc==SQLITE_OK ){ int iCol; const char *a = sqlite3_column_blob(pSelectDocsize, 0); - const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0); for(iCol=0; iColnCol; iCol++){ sqlite3_int64 nToken; - a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken); - if( a>pEnd ){ - rc = SQLITE_CORRUPT_VTAB; - break; - } + a += sqlite3Fts3GetVarint(a, &nToken); pInfo->aMatchinfo[iCol] = (u32)nToken; } } sqlite3_reset(pSelectDocsize); break; @@ -205356,13 +163971,13 @@ } break; case FTS3_MATCHINFO_LHITS_BM: case FTS3_MATCHINFO_LHITS: { - size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); + int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); memset(pInfo->aMatchinfo, 0, nZero); - rc = fts3ExprLHitGather(pCsr->pExpr, pInfo); + fts3ExprLHitGather(pCsr->pExpr, pInfo); break; } default: { Fts3Expr *pExpr; @@ -205370,18 +163985,18 @@ pExpr = pCsr->pExpr; rc = fts3ExprLoadDoclists(pCsr, 0, 0); if( rc!=SQLITE_OK ) break; if( bGlobal ){ if( pCsr->pDeferred ){ - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0); + rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0); if( rc!=SQLITE_OK ) break; } - rc = sqlite3Fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); + rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); sqlite3Fts3EvalTestDeferred(pCsr, &rc); if( rc!=SQLITE_OK ) break; } - (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); + (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); break; } } pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); @@ -205391,11 +164006,11 @@ return rc; } /* -** Populate pCsr->aMatchinfo[] with data for the current row. The +** Populate pCsr->aMatchinfo[] with data for the current row. The ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). */ static void fts3GetMatchinfo( sqlite3_context *pCtx, /* Return results here */ Fts3Cursor *pCsr, /* FTS3 Cursor object */ @@ -205411,25 +164026,25 @@ memset(&sInfo, 0, sizeof(MatchInfo)); sInfo.pCursor = pCsr; sInfo.nCol = pTab->nColumn; - /* If there is cached matchinfo() data, but the format string for the - ** cache does not match the format string for this request, discard + /* If there is cached matchinfo() data, but the format string for the + ** cache does not match the format string for this request, discard ** the cached data. */ if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){ sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); pCsr->pMIBuffer = 0; } /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the - ** matchinfo function has been called for this query. In this case + ** matchinfo function has been called for this query. In this case ** allocate the array used to accumulate the matchinfo data and ** initialize those elements that are constant for every row. */ if( pCsr->pMIBuffer==0 ){ - size_t nMatchinfo = 0; /* Number of u32 elements in match-info */ + int nMatchinfo = 0; /* Number of u32 elements in match-info */ int i; /* Used to iterate through zArg */ /* Determine the number of phrases in the query */ pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr); sInfo.nPhrase = pCsr->nPhrase; @@ -205495,11 +164110,11 @@ int i; StrBuffer res = {0, 0, 0}; /* The returned text includes up to four fragments of text extracted from ** the data in the current row. The first iteration of the for(...) loop - ** below attempts to locate a single fragment of text nToken tokens in + ** below attempts to locate a single fragment of text nToken tokens in ** size that contains at least one instance of all phrases in the query ** expression that appear in the current row. If such a fragment of text ** cannot be found, the second iteration of the loop attempts to locate ** a pair of fragments, and so on. */ @@ -205510,14 +164125,10 @@ if( !pCsr->pExpr ){ sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); return; } - /* Limit the snippet length to 64 tokens. */ - if( nToken<-64 ) nToken = -64; - if( nToken>+64 ) nToken = +64; - for(nSnippet=1; 1; nSnippet++){ int iSnip; /* Loop counter 0..nSnippet-1 */ u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ @@ -205566,11 +164177,11 @@ } assert( nFToken>0 ); for(i=0; ipCsr, pExpr, p->iCol, &pList); nTerm = pExpr->pPhrase->nToken; if( pList ){ fts3GetDeltaPosition(&pList, &iPos); - assert_fts3_nc( iPos>=0 ); + assert( iPos>=0 ); } for(iTerm=0; iTermaTerm[p->iTerm++]; pT->iOff = nTerm-iTerm-1; @@ -205656,19 +164267,19 @@ /* Count the number of terms in the query */ rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); if( rc!=SQLITE_OK ) goto offsets_out; /* Allocate the array of TermOffset iterators. */ - sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken); + sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken); if( 0==sCtx.aTerm ){ rc = SQLITE_NOMEM; goto offsets_out; } sCtx.iDocid = pCsr->iPrevId; sCtx.pCsr = pCsr; - /* Loop through the table columns, appending offset information to + /* Loop through the table columns, appending offset information to ** string-buffer res for each column. */ for(iCol=0; iColnColumn; iCol++){ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ const char *ZDUMMY; /* Dummy argument used with xNext() */ @@ -205677,25 +164288,23 @@ int iEnd = 0; int iCurrent = 0; const char *zDoc; int nDoc; - /* Initialize the contents of sCtx.aTerm[] for column iCol. This - ** operation may fail if the database contains corrupt records. + /* Initialize the contents of sCtx.aTerm[] for column iCol. There is + ** no way that this operation can fail, so the return code from + ** fts3ExprIterate() can be discarded. */ sCtx.iCol = iCol; sCtx.iTerm = 0; - rc = sqlite3Fts3ExprIterate( - pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx - ); - if( rc!=SQLITE_OK ) goto offsets_out; + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx); - /* Retreive the text stored in column iCol. If an SQL NULL is stored + /* Retreive the text stored in column iCol. If an SQL NULL is stored ** in column iCol, jump immediately to the next iteration of the loop. ** If an OOM occurs while retrieving the data (this can happen if SQLite - ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM - ** to the caller. + ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM + ** to the caller. */ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); if( zDoc==0 ){ if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ @@ -205727,11 +164336,11 @@ if( !pTerm ){ /* All offsets for this column have been gathered. */ rc = SQLITE_DONE; }else{ - assert_fts3_nc( iCurrent<=iMinPos ); + assert( iCurrent<=iMinPos ); if( 0==(0xFE&*pTerm->pList) ){ pTerm->pList = 0; }else{ fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); } @@ -205738,11 +164347,11 @@ while( rc==SQLITE_OK && iCurrentxNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); } if( rc==SQLITE_OK ){ char aBuffer[64]; - sqlite3_snprintf(sizeof(aBuffer), aBuffer, + sqlite3_snprintf(sizeof(aBuffer), aBuffer, "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart ); rc = fts3StringAppend(&res, aBuffer, -1); }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){ rc = FTS_CORRUPT_VTAB; @@ -205883,11 +164492,11 @@ typedef struct unicode_tokenizer unicode_tokenizer; typedef struct unicode_cursor unicode_cursor; struct unicode_tokenizer { sqlite3_tokenizer base; - int eRemoveDiacritic; + int bRemoveDiacritic; int nException; int *aiException; }; struct unicode_cursor { @@ -205919,11 +164528,11 @@ ** all characters in string zIn/nIn to be separators (if bAlnum==0) or ** token characters (if bAlnum==1). ** ** For each codepoint in the zIn/nIn string, this function checks if the ** sqlite3FtsUnicodeIsalnum() function already returns the desired result. -** If so, no action is taken. Otherwise, the codepoint is added to the +** If so, no action is taken. Otherwise, the codepoint is added to the ** unicode_tokenizer.aiException[] array. For the purposes of tokenization, ** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all ** codepoints in the aiException[] array. ** ** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() @@ -205945,29 +164554,29 @@ assert( bAlnum==0 || bAlnum==1 ); while( zaiException,(p->nException+nEntry)*sizeof(int)); + aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int)); if( aNew==0 ) return SQLITE_NOMEM; nNew = p->nException; z = (const unsigned char *)zIn; while( zi; j--) aNew[j] = aNew[j-1]; @@ -206028,24 +164637,21 @@ int rc = SQLITE_OK; pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer)); if( pNew==NULL ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(unicode_tokenizer)); - pNew->eRemoveDiacritic = 1; + pNew->bRemoveDiacritic = 1; for(i=0; rc==SQLITE_OK && ieRemoveDiacritic = 1; + pNew->bRemoveDiacritic = 1; } else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){ - pNew->eRemoveDiacritic = 0; - } - else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){ - pNew->eRemoveDiacritic = 2; + pNew->bRemoveDiacritic = 0; } else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){ rc = unicodeAddExceptions(pNew, 1, &z[11], n-11); } else if( n>=11 && memcmp("separators=", z, 11)==0 ){ @@ -206066,11 +164672,11 @@ } /* ** Prepare to begin tokenizing a particular string. The input ** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in +** used to incrementally tokenize this string is returned in ** *ppCursor. */ static int unicodeOpen( sqlite3_tokenizer *p, /* The tokenizer */ const char *aInput, /* Input string */ @@ -206086,11 +164692,10 @@ memset(pCsr, 0, sizeof(unicode_cursor)); pCsr->aInput = (const unsigned char *)aInput; if( aInput==0 ){ pCsr->nInput = 0; - pCsr->aInput = (const unsigned char*)""; }else if( nInput<0 ){ pCsr->nInput = (int)strlen(aInput); }else{ pCsr->nInput = nInput; } @@ -206131,11 +164736,11 @@ const unsigned char *zStart = z; const unsigned char *zEnd; const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput]; /* Scan past any delimiter characters before the start of the next token. - ** Return SQLITE_DONE early if this takes us all the way to the end of + ** Return SQLITE_DONE early if this takes us all the way to the end of ** the input. */ while( zzToken)>=(pCsr->nAlloc-4) ){ - char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64); + char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64); if( !zNew ) return SQLITE_NOMEM; zOut = &zNew[zOut - pCsr->zToken]; pCsr->zToken = zNew; pCsr->nAlloc += 64; } /* Write the folded case of the last character read to the output */ zEnd = z; - iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic); + iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic); if( iOut ){ WRITE_UTF8(zOut, iOut); } /* If the cursor is not at EOF, read the next character */ if( z>=zTerm ) break; READ_UTF8(z, zTerm, iCode); - }while( unicodeIsAlnum(p, (int)iCode) + }while( unicodeIsAlnum(p, (int)iCode) || sqlite3FtsUnicodeIsdiacritic((int)iCode) ); /* Set the output variables and return. */ pCsr->iOff = (int)(z - pCsr->aInput); @@ -206178,11 +164783,11 @@ *piPos = pCsr->iToken++; return SQLITE_OK; } /* -** Set *ppModule to a pointer to the sqlite3_tokenizer_module +** Set *ppModule to a pointer to the sqlite3_tokenizer_module ** structure for the unicode tokenizer. */ SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){ static const sqlite3_tokenizer_module module = { 0, @@ -206200,11 +164805,11 @@ #endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */ /************** End of fts3_unicode.c ****************************************/ /************** Begin file fts3_unicode2.c ***********************************/ /* -** 2012-05-25 +** 2012 May 25 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. @@ -206233,15 +164838,15 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){ /* Each unsigned integer in the following array corresponds to a contiguous ** range of unicode codepoints that are not either letters or numbers (i.e. ** codepoints for which this function should return 0). ** - ** The most significant 22 bits in each 32-bit value contain the first + ** The most significant 22 bits in each 32-bit value contain the first ** codepoint in the range. The least significant 10 bits are used to store - ** the size of the range (always at least 1). In other words, the value - ** ((C<<22) + N) represents a range of N codepoints starting with codepoint - ** C. It is not possible to represent a range larger than 1023 codepoints + ** the size of the range (always at least 1). In other words, the value + ** ((C<<22) + N) represents a range of N codepoints starting with codepoint + ** C. It is not possible to represent a range larger than 1023 codepoints ** using this format. */ static const unsigned int aEntry[] = { 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, @@ -206360,52 +164965,36 @@ ** of the ASCII letter only. For example, if passed 235 - "LATIN ** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER ** E"). The resuls of passing a codepoint that corresponds to an ** uppercase letter are undefined. */ -static int remove_diacritic(int c, int bComplex){ +static int remove_diacritic(int c){ unsigned short aDia[] = { - 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, - 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, - 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, - 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, - 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896, - 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106, - 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344, - 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198, - 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468, - 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704, - 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914, - 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218, - 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554, - 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766, - 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118, - 63182, 63242, 63274, 63310, 63368, 63390, + 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, + 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, + 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, + 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, + 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928, + 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234, + 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504, + 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529, + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, + 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, + 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, + 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, + 62924, 63050, 63082, 63274, 63390, }; -#define HIBIT ((unsigned char)0x80) - unsigned char aChar[] = { - '\0', 'a', 'c', 'e', 'i', 'n', - 'o', 'u', 'y', 'y', 'a', 'c', - 'd', 'e', 'e', 'g', 'h', 'i', - 'j', 'k', 'l', 'n', 'o', 'r', - 's', 't', 'u', 'u', 'w', 'y', - 'z', 'o', 'u', 'a', 'i', 'o', - 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o', - 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a', - 'e', 'i', 'o', 'r', 'u', 's', - 't', 'h', 'a', 'e', 'o'|HIBIT, 'o', - 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', 'a', 'b', - 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT, - 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT, - 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n', - 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's', - 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w', - 'w', 'x', 'y', 'z', 'h', 't', - 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT, - 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT, - 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y', + char aChar[] = { + '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c', + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', + 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', + 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', + 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', + 'e', 'i', 'o', 'u', 'y', }; unsigned int key = (((unsigned int)c)<<3) | 0x00000007; int iRes = 0; int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; @@ -206418,12 +165007,11 @@ }else{ iHi = iTest-1; } } assert( key>=aDia[iRes] ); - if( bComplex==0 && (aChar[iRes] & 0x80) ) return c; - return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F); + return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]); } /* ** Return true if the argument interpreted as a unicode codepoint @@ -206432,12 +165020,12 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){ unsigned int mask0 = 0x08029FDF; unsigned int mask1 = 0x000361F8; if( c<768 || c>817 ) return 0; return (c < 768+32) ? - (mask0 & ((unsigned int)1 << (c-768))) : - (mask1 & ((unsigned int)1 << (c-768-32))); + (mask0 & (1 << (c-768))) : + (mask1 & (1 << (c-768-32))); } /* ** Interpret the argument as a unicode codepoint. If the codepoint @@ -206446,11 +165034,11 @@ ** Otherwise, return a copy of the argument. ** ** The results are undefined if the value passed to this function ** is less than zero. */ -SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ +SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ /* Each entry in the following array defines a rule for folding a range ** of codepoints to lower case. The rule applies to a range of nRange ** codepoints starting at codepoint iCode. ** ** If the least significant bit in flags is clear, then the rule applies @@ -206523,23 +165111,23 @@ {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, - {65313, 14, 26}, + {65313, 14, 26}, }; static const unsigned short aiOff[] = { - 1, 2, 8, 15, 16, 26, 28, 32, - 37, 38, 40, 48, 63, 64, 69, 71, - 79, 80, 116, 202, 203, 205, 206, 207, - 209, 210, 211, 213, 214, 217, 218, 219, - 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, - 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, - 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, - 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, - 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, - 65514, 65521, 65527, 65528, 65529, + 1, 2, 8, 15, 16, 26, 28, 32, + 37, 38, 40, 48, 63, 64, 69, 71, + 79, 80, 116, 202, 203, 205, 206, 207, + 209, 210, 211, 213, 214, 217, 218, 219, + 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, + 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, + 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, + 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, + 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, + 65514, 65521, 65527, 65528, 65529, }; int ret = c; assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); @@ -206569,15 +165157,13 @@ if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; assert( ret>0 ); } - if( eRemoveDiacritic ){ - ret = remove_diacritic(ret, eRemoveDiacritic==2); - } + if( bRemoveDiacritic ) ret = remove_diacritic(ret); } - + else if( c>=66560 && c<66600 ){ ret = c + 40; } return ret; @@ -206584,5479 +165170,10 @@ } #endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */ #endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ /************** End of fts3_unicode2.c ***************************************/ -/************** Begin file json.c ********************************************/ -/* -** 2015-08-12 -** -** 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. -** -****************************************************************************** -** -** SQLite JSON functions. -** -** This file began as an extension in ext/misc/json1.c in 2015. That -** extension proved so useful that it has now been moved into the core. -** -** The original design stored all JSON as pure text, canonical RFC-8259. -** Support for JSON-5 extensions was added with version 3.42.0 (2023-05-16). -** All generated JSON text still conforms strictly to RFC-8259, but text -** with JSON-5 extensions is accepted as input. -** -** Beginning with version 3.45.0 (circa 2024-01-01), these routines also -** accept BLOB values that have JSON encoded using a binary representation -** called "JSONB". The name JSONB comes from PostgreSQL, however the on-disk -** format SQLite JSONB is completely different and incompatible with -** PostgreSQL JSONB. -** -** Decoding and interpreting JSONB is still O(N) where N is the size of -** the input, the same as text JSON. However, the constant of proportionality -** for JSONB is much smaller due to faster parsing. The size of each -** element in JSONB is encoded in its header, so there is no need to search -** for delimiters using persnickety syntax rules. JSONB seems to be about -** 3x faster than text JSON as a result. JSONB is also tends to be slightly -** smaller than text JSON, by 5% or 10%, but there are corner cases where -** JSONB can be slightly larger. So you are not far mistaken to say that -** a JSONB blob is the same size as the equivalent RFC-8259 text. -** -** -** THE JSONB ENCODING: -** -** Every JSON element is encoded in JSONB as a header and a payload. -** The header is between 1 and 9 bytes in size. The payload is zero -** or more bytes. -** -** The lower 4 bits of the first byte of the header determines the -** element type: -** -** 0: NULL -** 1: TRUE -** 2: FALSE -** 3: INT -- RFC-8259 integer literal -** 4: INT5 -- JSON5 integer literal -** 5: FLOAT -- RFC-8259 floating point literal -** 6: FLOAT5 -- JSON5 floating point literal -** 7: TEXT -- Text literal acceptable to both SQL and JSON -** 8: TEXTJ -- Text containing RFC-8259 escapes -** 9: TEXT5 -- Text containing JSON5 and/or RFC-8259 escapes -** 10: TEXTRAW -- Text containing unescaped syntax characters -** 11: ARRAY -** 12: OBJECT -** -** The other three possible values (13-15) are reserved for future -** enhancements. -** -** The upper 4 bits of the first byte determine the size of the header -** and sometimes also the size of the payload. If X is the first byte -** of the element and if X>>4 is between 0 and 11, then the payload -** will be that many bytes in size and the header is exactly one byte -** in size. Other four values for X>>4 (12-15) indicate that the header -** is more than one byte in size and that the payload size is determined -** by the remainder of the header, interpreted as a unsigned big-endian -** integer. -** -** Value of X>>4 Size integer Total header size -** ------------- -------------------- ----------------- -** 12 1 byte (0-255) 2 -** 13 2 byte (0-65535) 3 -** 14 4 byte (0-4294967295) 5 -** 15 8 byte (0-1.8e19) 9 -** -** The payload size need not be expressed in its minimal form. For example, -** if the payload size is 10, the size can be expressed in any of 5 different -** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by on 0x0a byte, -** (3) (X>>4)==13 followed by 0x00 and 0x0a, (4) (X>>4)==14 followed by -** 0x00 0x00 0x00 0x0a, or (5) (X>>4)==15 followed by 7 bytes of 0x00 and -** a single byte of 0x0a. The shorter forms are preferred, of course, but -** sometimes when generating JSONB, the payload size is not known in advance -** and it is convenient to reserve sufficient header space to cover the -** largest possible payload size and then come back later and patch up -** the size when it becomes known, resulting in a non-minimal encoding. -** -** The value (X>>4)==15 is not actually used in the current implementation -** (as SQLite is currently unable handle BLOBs larger than about 2GB) -** but is included in the design to allow for future enhancements. -** -** The payload follows the header. NULL, TRUE, and FALSE have no payload and -** their payload size must always be zero. The payload for INT, INT5, -** FLOAT, FLOAT5, TEXT, TEXTJ, TEXT5, and TEXTROW is text. Note that the -** "..." or '...' delimiters are omitted from the various text encodings. -** The payload for ARRAY and OBJECT is a list of additional elements that -** are the content for the array or object. The payload for an OBJECT -** must be an even number of elements. The first element of each pair is -** the label and must be of type TEXT, TEXTJ, TEXT5, or TEXTRAW. -** -** A valid JSONB blob consists of a single element, as described above. -** Usually this will be an ARRAY or OBJECT element which has many more -** elements as its content. But the overall blob is just a single element. -** -** Input validation for JSONB blobs simply checks that the element type -** code is between 0 and 12 and that the total size of the element -** (header plus payload) is the same as the size of the BLOB. If those -** checks are true, the BLOB is assumed to be JSONB and processing continues. -** Errors are only raised if some other miscoding is discovered during -** processing. -** -** Additional information can be found in the doc/jsonb.md file of the -** canonical SQLite source tree. -*/ -#ifndef SQLITE_OMIT_JSON -/* #include "sqliteInt.h" */ - -/* JSONB element types -*/ -#define JSONB_NULL 0 /* "null" */ -#define JSONB_TRUE 1 /* "true" */ -#define JSONB_FALSE 2 /* "false" */ -#define JSONB_INT 3 /* integer acceptable to JSON and SQL */ -#define JSONB_INT5 4 /* integer in 0x000 notation */ -#define JSONB_FLOAT 5 /* float acceptable to JSON and SQL */ -#define JSONB_FLOAT5 6 /* float with JSON5 extensions */ -#define JSONB_TEXT 7 /* Text compatible with both JSON and SQL */ -#define JSONB_TEXTJ 8 /* Text with JSON escapes */ -#define JSONB_TEXT5 9 /* Text with JSON-5 escape */ -#define JSONB_TEXTRAW 10 /* SQL text that needs escaping for JSON */ -#define JSONB_ARRAY 11 /* An array */ -#define JSONB_OBJECT 12 /* An object */ - -/* Human-readable names for the JSONB values. The index for each -** string must correspond to the JSONB_* integer above. -*/ -static const char * const jsonbType[] = { - "null", "true", "false", "integer", "integer", - "real", "real", "text", "text", "text", - "text", "array", "object", "", "", "", "" -}; - -/* -** Growing our own isspace() routine this way is twice as fast as -** the library isspace() function, resulting in a 7% overall performance -** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). -*/ -static const char jsonIsSpace[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x]) - -/* -** The set of all space characters recognized by jsonIsspace(). -** Useful as the second argument to strspn(). -*/ -static const char jsonSpaces[] = "\011\012\015\040"; - -/* -** Characters that are special to JSON. Control characters, -** '"' and '\\' and '\''. Actually, '\'' is not special to -** canonical JSON, but it is special in JSON-5, so we include -** it in the set of special characters. -*/ -static const char jsonIsOk[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; - -/* Objects */ -typedef struct JsonCache JsonCache; -typedef struct JsonString JsonString; -typedef struct JsonParse JsonParse; - -/* -** Magic number used for the JSON parse cache in sqlite3_get_auxdata() -*/ -#define JSON_CACHE_ID (-429938) /* Cache entry */ -#define JSON_CACHE_SIZE 4 /* Max number of cache entries */ - -/* -** jsonUnescapeOneChar() returns this invalid code point if it encounters -** a syntax error. -*/ -#define JSON_INVALID_CHAR 0x99999 - -/* A cache mapping JSON text into JSONB blobs. -** -** Each cache entry is a JsonParse object with the following restrictions: -** -** * The bReadOnly flag must be set -** -** * The aBlob[] array must be owned by the JsonParse object. In other -** words, nBlobAlloc must be non-zero. -** -** * eEdit and delta must be zero. -** -** * zJson must be an RCStr. In other words bJsonIsRCStr must be true. -*/ -struct JsonCache { - sqlite3 *db; /* Database connection */ - int nUsed; /* Number of active entries in the cache */ - JsonParse *a[JSON_CACHE_SIZE]; /* One line for each cache entry */ -}; - -/* An instance of this object represents a JSON string -** under construction. Really, this is a generic string accumulator -** that can be and is used to create strings other than JSON. -** -** If the generated string is longer than will fit into the zSpace[] buffer, -** then it will be an RCStr string. This aids with caching of large -** JSON strings. -*/ -struct JsonString { - sqlite3_context *pCtx; /* Function context - put error messages here */ - char *zBuf; /* Append JSON content here */ - u64 nAlloc; /* Bytes of storage available in zBuf[] */ - u64 nUsed; /* Bytes of zBuf[] currently used */ - u8 bStatic; /* True if zBuf is static space */ - u8 eErr; /* True if an error has been encountered */ - char zSpace[100]; /* Initial static space */ -}; - -/* Allowed values for JsonString.eErr */ -#define JSTRING_OOM 0x01 /* Out of memory */ -#define JSTRING_MALFORMED 0x02 /* Malformed JSONB */ -#define JSTRING_ERR 0x04 /* Error already sent to sqlite3_result */ - -/* The "subtype" set for text JSON values passed through using -** sqlite3_result_subtype() and sqlite3_value_subtype(). -*/ -#define JSON_SUBTYPE 74 /* Ascii for "J" */ - -/* -** Bit values for the flags passed into various SQL function implementations -** via the sqlite3_user_data() value. -*/ -#define JSON_JSON 0x01 /* Result is always JSON */ -#define JSON_SQL 0x02 /* Result is always SQL */ -#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ -#define JSON_ISSET 0x04 /* json_set(), not json_insert() */ -#define JSON_BLOB 0x08 /* Use the BLOB output format */ - - -/* A parsed JSON value. Lifecycle: -** -** 1. JSON comes in and is parsed into a JSONB value in aBlob. The -** original text is stored in zJson. This step is skipped if the -** input is JSONB instead of text JSON. -** -** 2. The aBlob[] array is searched using the JSON path notation, if needed. -** -** 3. Zero or more changes are made to aBlob[] (via json_remove() or -** json_replace() or json_patch() or similar). -** -** 4. New JSON text is generated from the aBlob[] for output. This step -** is skipped if the function is one of the jsonb_* functions that -** returns JSONB instead of text JSON. -*/ -struct JsonParse { - u8 *aBlob; /* JSONB representation of JSON value */ - u32 nBlob; /* Bytes of aBlob[] actually used */ - u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */ - char *zJson; /* Json text used for parsing */ - sqlite3 *db; /* The database connection to which this object belongs */ - int nJson; /* Length of the zJson string in bytes */ - u32 nJPRef; /* Number of references to this object */ - u32 iErr; /* Error location in zJson[] */ - u16 iDepth; /* Nesting depth */ - u8 nErr; /* Number of errors seen */ - u8 oom; /* Set to true if out of memory */ - u8 bJsonIsRCStr; /* True if zJson is an RCStr */ - u8 hasNonstd; /* True if input uses non-standard features like JSON5 */ - u8 bReadOnly; /* Do not modify. */ - /* Search and edit information. See jsonLookupStep() */ - u8 eEdit; /* Edit operation to apply */ - int delta; /* Size change due to the edit */ - u32 nIns; /* Number of bytes to insert */ - u32 iLabel; /* Location of label if search landed on an object value */ - u8 *aIns; /* Content to be inserted */ -}; - -/* Allowed values for JsonParse.eEdit */ -#define JEDIT_DEL 1 /* Delete if exists */ -#define JEDIT_REPL 2 /* Overwrite if exists */ -#define JEDIT_INS 3 /* Insert if not exists */ -#define JEDIT_SET 4 /* Insert or overwrite */ - -/* -** Maximum nesting depth of JSON for this implementation. -** -** This limit is needed to avoid a stack overflow in the recursive -** descent parser. A depth of 1000 is far deeper than any sane JSON -** should go. Historical note: This limit was 2000 prior to version 3.42.0 -*/ -#ifndef SQLITE_JSON_MAX_DEPTH -# define JSON_MAX_DEPTH 1000 -#else -# define JSON_MAX_DEPTH SQLITE_JSON_MAX_DEPTH -#endif - -/* -** Allowed values for the flgs argument to jsonParseFuncArg(); -*/ -#define JSON_EDITABLE 0x01 /* Generate a writable JsonParse object */ -#define JSON_KEEPERROR 0x02 /* Return non-NULL even if there is an error */ - -/************************************************************************** -** Forward references -**************************************************************************/ -static void jsonReturnStringAsBlob(JsonString*); -static int jsonFuncArgMightBeBinary(sqlite3_value *pJson); -static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*); -static void jsonReturnParse(sqlite3_context*,JsonParse*); -static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); -static void jsonParseFree(JsonParse*); -static u32 jsonbPayloadSize(const JsonParse*, u32, u32*); -static u32 jsonUnescapeOneChar(const char*, u32, u32*); - -/************************************************************************** -** Utility routines for dealing with JsonCache objects -**************************************************************************/ - -/* -** Free a JsonCache object. -*/ -static void jsonCacheDelete(JsonCache *p){ - int i; - for(i=0; inUsed; i++){ - jsonParseFree(p->a[i]); - } - sqlite3DbFree(p->db, p); -} -static void jsonCacheDeleteGeneric(void *p){ - jsonCacheDelete((JsonCache*)p); -} - -/* -** Insert a new entry into the cache. If the cache is full, expel -** the least recently used entry. Return SQLITE_OK on success or a -** result code otherwise. -** -** Cache entries are stored in age order, oldest first. -*/ -static int jsonCacheInsert( - sqlite3_context *ctx, /* The SQL statement context holding the cache */ - JsonParse *pParse /* The parse object to be added to the cache */ -){ - JsonCache *p; - - assert( pParse->zJson!=0 ); - assert( pParse->bJsonIsRCStr ); - assert( pParse->delta==0 ); - p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); - if( p==0 ){ - sqlite3 *db = sqlite3_context_db_handle(ctx); - p = sqlite3DbMallocZero(db, sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; - p->db = db; - sqlite3_set_auxdata(ctx, JSON_CACHE_ID, p, jsonCacheDeleteGeneric); - p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); - if( p==0 ) return SQLITE_NOMEM; - } - if( p->nUsed >= JSON_CACHE_SIZE ){ - jsonParseFree(p->a[0]); - memmove(p->a, &p->a[1], (JSON_CACHE_SIZE-1)*sizeof(p->a[0])); - p->nUsed = JSON_CACHE_SIZE-1; - } - assert( pParse->nBlobAlloc>0 ); - pParse->eEdit = 0; - pParse->nJPRef++; - pParse->bReadOnly = 1; - p->a[p->nUsed] = pParse; - p->nUsed++; - return SQLITE_OK; -} - -/* -** Search for a cached translation the json text supplied by pArg. Return -** the JsonParse object if found. Return NULL if not found. -** -** When a match if found, the matching entry is moved to become the -** most-recently used entry if it isn't so already. -** -** The JsonParse object returned still belongs to the Cache and might -** be deleted at any moment. If the caller whants the JsonParse to -** linger, it needs to increment the nPJRef reference counter. -*/ -static JsonParse *jsonCacheSearch( - sqlite3_context *ctx, /* The SQL statement context holding the cache */ - sqlite3_value *pArg /* Function argument containing SQL text */ -){ - JsonCache *p; - int i; - const char *zJson; - int nJson; - - if( sqlite3_value_type(pArg)!=SQLITE_TEXT ){ - return 0; - } - zJson = (const char*)sqlite3_value_text(pArg); - if( zJson==0 ) return 0; - nJson = sqlite3_value_bytes(pArg); - - p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID); - if( p==0 ){ - return 0; - } - for(i=0; inUsed; i++){ - if( p->a[i]->zJson==zJson ) break; - } - if( i>=p->nUsed ){ - for(i=0; inUsed; i++){ - if( p->a[i]->nJson!=nJson ) continue; - if( memcmp(p->a[i]->zJson, zJson, nJson)==0 ) break; - } - } - if( inUsed ){ - if( inUsed-1 ){ - /* Make the matching entry the most recently used entry */ - JsonParse *tmp = p->a[i]; - memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp)); - p->a[p->nUsed-1] = tmp; - i = p->nUsed - 1; - } - assert( p->a[i]->delta==0 ); - return p->a[i]; - }else{ - return 0; - } -} - -/************************************************************************** -** Utility routines for dealing with JsonString objects -**************************************************************************/ - -/* Turn uninitialized bulk memory into a valid JsonString object -** holding a zero-length string. -*/ -static void jsonStringZero(JsonString *p){ - p->zBuf = p->zSpace; - p->nAlloc = sizeof(p->zSpace); - p->nUsed = 0; - p->bStatic = 1; -} - -/* Initialize the JsonString object -*/ -static void jsonStringInit(JsonString *p, sqlite3_context *pCtx){ - p->pCtx = pCtx; - p->eErr = 0; - jsonStringZero(p); -} - -/* Free all allocated memory and reset the JsonString object back to its -** initial state. -*/ -static void jsonStringReset(JsonString *p){ - if( !p->bStatic ) sqlite3RCStrUnref(p->zBuf); - jsonStringZero(p); -} - -/* Report an out-of-memory (OOM) condition -*/ -static void jsonStringOom(JsonString *p){ - p->eErr |= JSTRING_OOM; - if( p->pCtx ) sqlite3_result_error_nomem(p->pCtx); - jsonStringReset(p); -} - -/* Enlarge pJson->zBuf so that it can hold at least N more bytes. -** Return zero on success. Return non-zero on an OOM error -*/ -static int jsonStringGrow(JsonString *p, u32 N){ - u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; - char *zNew; - if( p->bStatic ){ - if( p->eErr ) return 1; - zNew = sqlite3RCStrNew(nTotal); - if( zNew==0 ){ - jsonStringOom(p); - return SQLITE_NOMEM; - } - memcpy(zNew, p->zBuf, (size_t)p->nUsed); - p->zBuf = zNew; - p->bStatic = 0; - }else{ - p->zBuf = sqlite3RCStrResize(p->zBuf, nTotal); - if( p->zBuf==0 ){ - p->eErr |= JSTRING_OOM; - jsonStringZero(p); - return SQLITE_NOMEM; - } - } - p->nAlloc = nTotal; - return SQLITE_OK; -} - -/* Append N bytes from zIn onto the end of the JsonString string. -*/ -static SQLITE_NOINLINE void jsonStringExpandAndAppend( - JsonString *p, - const char *zIn, - u32 N -){ - assert( N>0 ); - if( jsonStringGrow(p,N) ) return; - memcpy(p->zBuf+p->nUsed, zIn, N); - p->nUsed += N; -} -static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ - if( N==0 ) return; - if( N+p->nUsed >= p->nAlloc ){ - jsonStringExpandAndAppend(p,zIn,N); - }else{ - memcpy(p->zBuf+p->nUsed, zIn, N); - p->nUsed += N; - } -} -static void jsonAppendRawNZ(JsonString *p, const char *zIn, u32 N){ - assert( N>0 ); - if( N+p->nUsed >= p->nAlloc ){ - jsonStringExpandAndAppend(p,zIn,N); - }else{ - memcpy(p->zBuf+p->nUsed, zIn, N); - p->nUsed += N; - } -} - -/* Append formatted text (not to exceed N bytes) to the JsonString. -*/ -static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ - va_list ap; - if( (p->nUsed + N >= p->nAlloc) && jsonStringGrow(p, N) ) return; - va_start(ap, zFormat); - sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); - va_end(ap); - p->nUsed += (int)strlen(p->zBuf+p->nUsed); -} - -/* Append a single character -*/ -static SQLITE_NOINLINE void jsonAppendCharExpand(JsonString *p, char c){ - if( jsonStringGrow(p,1) ) return; - p->zBuf[p->nUsed++] = c; -} -static void jsonAppendChar(JsonString *p, char c){ - if( p->nUsed>=p->nAlloc ){ - jsonAppendCharExpand(p,c); - }else{ - p->zBuf[p->nUsed++] = c; - } -} - -/* Remove a single character from the end of the string -*/ -static void jsonStringTrimOneChar(JsonString *p){ - if( p->eErr==0 ){ - assert( p->nUsed>0 ); - p->nUsed--; - } -} - - -/* Make sure there is a zero terminator on p->zBuf[] -** -** Return true on success. Return false if an OOM prevents this -** from happening. -*/ -static int jsonStringTerminate(JsonString *p){ - jsonAppendChar(p, 0); - jsonStringTrimOneChar(p); - return p->eErr==0; -} - -/* Append a comma separator to the output buffer, if the previous -** character is not '[' or '{'. -*/ -static void jsonAppendSeparator(JsonString *p){ - char c; - if( p->nUsed==0 ) return; - c = p->zBuf[p->nUsed-1]; - if( c=='[' || c=='{' ) return; - jsonAppendChar(p, ','); -} - -/* c is a control character. Append the canonical JSON representation -** of that control character to p. -** -** This routine assumes that the output buffer has already been enlarged -** sufficiently to hold the worst-case encoding plus a nul terminator. -*/ -static void jsonAppendControlChar(JsonString *p, u8 c){ - static const char aSpecial[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - assert( sizeof(aSpecial)==32 ); - assert( aSpecial['\b']=='b' ); - assert( aSpecial['\f']=='f' ); - assert( aSpecial['\n']=='n' ); - assert( aSpecial['\r']=='r' ); - assert( aSpecial['\t']=='t' ); - assert( c>=0 && cnUsed+7 <= p->nAlloc ); - if( aSpecial[c] ){ - p->zBuf[p->nUsed] = '\\'; - p->zBuf[p->nUsed+1] = aSpecial[c]; - p->nUsed += 2; - }else{ - p->zBuf[p->nUsed] = '\\'; - p->zBuf[p->nUsed+1] = 'u'; - p->zBuf[p->nUsed+2] = '0'; - p->zBuf[p->nUsed+3] = '0'; - p->zBuf[p->nUsed+4] = "0123456789abcdef"[c>>4]; - p->zBuf[p->nUsed+5] = "0123456789abcdef"[c&0xf]; - p->nUsed += 6; - } -} - -/* Append the N-byte string in zIn to the end of the JsonString string -** under construction. Enclose the string in double-quotes ("...") and -** escape any double-quotes or backslash characters contained within the -** string. -** -** This routine is a high-runner. There is a measurable performance -** increase associated with unwinding the jsonIsOk[] loop. -*/ -static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ - u32 k; - u8 c; - const u8 *z = (const u8*)zIn; - if( z==0 ) return; - if( (N+p->nUsed+2 >= p->nAlloc) && jsonStringGrow(p,N+2)!=0 ) return; - p->zBuf[p->nUsed++] = '"'; - while( 1 /*exit-by-break*/ ){ - k = 0; - /* The following while() is the 4-way unwound equivalent of - ** - ** while( k=N ){ - while( k=N ){ - if( k>0 ){ - memcpy(&p->zBuf[p->nUsed], z, k); - p->nUsed += k; - } - break; - } - if( k>0 ){ - memcpy(&p->zBuf[p->nUsed], z, k); - p->nUsed += k; - z += k; - N -= k; - } - c = z[0]; - if( c=='"' || c=='\\' ){ - if( (p->nUsed+N+3 > p->nAlloc) && jsonStringGrow(p,N+3)!=0 ) return; - p->zBuf[p->nUsed++] = '\\'; - p->zBuf[p->nUsed++] = c; - }else if( c=='\'' ){ - p->zBuf[p->nUsed++] = c; - }else{ - if( (p->nUsed+N+7 > p->nAlloc) && jsonStringGrow(p,N+7)!=0 ) return; - jsonAppendControlChar(p, c); - } - z++; - N--; - } - p->zBuf[p->nUsed++] = '"'; - assert( p->nUsednAlloc ); -} - -/* -** Append an sqlite3_value (such as a function parameter) to the JSON -** string under construction in p. -*/ -static void jsonAppendSqlValue( - JsonString *p, /* Append to this JSON string */ - sqlite3_value *pValue /* Value to append */ -){ - switch( sqlite3_value_type(pValue) ){ - case SQLITE_NULL: { - jsonAppendRawNZ(p, "null", 4); - break; - } - case SQLITE_FLOAT: { - jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue)); - break; - } - case SQLITE_INTEGER: { - const char *z = (const char*)sqlite3_value_text(pValue); - u32 n = (u32)sqlite3_value_bytes(pValue); - jsonAppendRaw(p, z, n); - break; - } - case SQLITE_TEXT: { - const char *z = (const char*)sqlite3_value_text(pValue); - u32 n = (u32)sqlite3_value_bytes(pValue); - if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ - jsonAppendRaw(p, z, n); - }else{ - jsonAppendString(p, z, n); - } - break; - } - default: { - if( jsonFuncArgMightBeBinary(pValue) ){ - JsonParse px; - memset(&px, 0, sizeof(px)); - px.aBlob = (u8*)sqlite3_value_blob(pValue); - px.nBlob = sqlite3_value_bytes(pValue); - jsonTranslateBlobToText(&px, 0, p); - }else if( p->eErr==0 ){ - sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); - p->eErr = JSTRING_ERR; - jsonStringReset(p); - } - break; - } - } -} - -/* Make the text in p (which is probably a generated JSON text string) -** the result of the SQL function. -** -** The JsonString is reset. -** -** If pParse and ctx are both non-NULL, then the SQL string in p is -** loaded into the zJson field of the pParse object as a RCStr and the -** pParse is added to the cache. -*/ -static void jsonReturnString( - JsonString *p, /* String to return */ - JsonParse *pParse, /* JSONB source or NULL */ - sqlite3_context *ctx /* Where to cache */ -){ - assert( (pParse!=0)==(ctx!=0) ); - assert( ctx==0 || ctx==p->pCtx ); - if( p->eErr==0 ){ - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(p->pCtx)); - if( flags & JSON_BLOB ){ - jsonReturnStringAsBlob(p); - }else if( p->bStatic ){ - sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, - SQLITE_TRANSIENT, SQLITE_UTF8); - }else if( jsonStringTerminate(p) ){ - if( pParse && pParse->bJsonIsRCStr==0 && pParse->nBlobAlloc>0 ){ - int rc; - pParse->zJson = sqlite3RCStrRef(p->zBuf); - pParse->nJson = p->nUsed; - pParse->bJsonIsRCStr = 1; - rc = jsonCacheInsert(ctx, pParse); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(ctx); - jsonStringReset(p); - return; - } - } - sqlite3_result_text64(p->pCtx, sqlite3RCStrRef(p->zBuf), p->nUsed, - sqlite3RCStrUnref, - SQLITE_UTF8); - }else{ - sqlite3_result_error_nomem(p->pCtx); - } - }else if( p->eErr & JSTRING_OOM ){ - sqlite3_result_error_nomem(p->pCtx); - }else if( p->eErr & JSTRING_MALFORMED ){ - sqlite3_result_error(p->pCtx, "malformed JSON", -1); - } - jsonStringReset(p); -} - -/************************************************************************** -** Utility routines for dealing with JsonParse objects -**************************************************************************/ - -/* -** Reclaim all memory allocated by a JsonParse object. But do not -** delete the JsonParse object itself. -*/ -static void jsonParseReset(JsonParse *pParse){ - assert( pParse->nJPRef<=1 ); - if( pParse->bJsonIsRCStr ){ - sqlite3RCStrUnref(pParse->zJson); - pParse->zJson = 0; - pParse->nJson = 0; - pParse->bJsonIsRCStr = 0; - } - if( pParse->nBlobAlloc ){ - sqlite3DbFree(pParse->db, pParse->aBlob); - pParse->aBlob = 0; - pParse->nBlob = 0; - pParse->nBlobAlloc = 0; - } -} - -/* -** Decrement the reference count on the JsonParse object. When the -** count reaches zero, free the object. -*/ -static void jsonParseFree(JsonParse *pParse){ - if( pParse ){ - if( pParse->nJPRef>1 ){ - pParse->nJPRef--; - }else{ - jsonParseReset(pParse); - sqlite3DbFree(pParse->db, pParse); - } - } -} - -/************************************************************************** -** Utility routines for the JSON text parser -**************************************************************************/ - -/* -** Translate a single byte of Hex into an integer. -** This routine only gives a correct answer if h really is a valid hexadecimal -** character: 0..9a..fA..F. But unlike sqlite3HexToInt(), it does not -** assert() if the digit is not hex. -*/ -static u8 jsonHexToInt(int h){ -#ifdef SQLITE_ASCII - h += 9*(1&(h>>6)); -#endif -#ifdef SQLITE_EBCDIC - h += 9*(1&~(h>>4)); -#endif - return (u8)(h & 0xf); -} - -/* -** Convert a 4-byte hex string into an integer -*/ -static u32 jsonHexToInt4(const char *z){ - u32 v; - v = (jsonHexToInt(z[0])<<12) - + (jsonHexToInt(z[1])<<8) - + (jsonHexToInt(z[2])<<4) - + jsonHexToInt(z[3]); - return v; -} - -/* -** Return true if z[] begins with 2 (or more) hexadecimal digits -*/ -static int jsonIs2Hex(const char *z){ - return sqlite3Isxdigit(z[0]) && sqlite3Isxdigit(z[1]); -} - -/* -** Return true if z[] begins with 4 (or more) hexadecimal digits -*/ -static int jsonIs4Hex(const char *z){ - return jsonIs2Hex(z) && jsonIs2Hex(&z[2]); -} - -/* -** Return the number of bytes of JSON5 whitespace at the beginning of -** the input string z[]. -** -** JSON5 whitespace consists of any of the following characters: -** -** Unicode UTF-8 Name -** U+0009 09 horizontal tab -** U+000a 0a line feed -** U+000b 0b vertical tab -** U+000c 0c form feed -** U+000d 0d carriage return -** U+0020 20 space -** U+00a0 c2 a0 non-breaking space -** U+1680 e1 9a 80 ogham space mark -** U+2000 e2 80 80 en quad -** U+2001 e2 80 81 em quad -** U+2002 e2 80 82 en space -** U+2003 e2 80 83 em space -** U+2004 e2 80 84 three-per-em space -** U+2005 e2 80 85 four-per-em space -** U+2006 e2 80 86 six-per-em space -** U+2007 e2 80 87 figure space -** U+2008 e2 80 88 punctuation space -** U+2009 e2 80 89 thin space -** U+200a e2 80 8a hair space -** U+2028 e2 80 a8 line separator -** U+2029 e2 80 a9 paragraph separator -** U+202f e2 80 af narrow no-break space (NNBSP) -** U+205f e2 81 9f medium mathematical space (MMSP) -** U+3000 e3 80 80 ideographical space -** U+FEFF ef bb bf byte order mark -** -** In addition, comments between '/', '*' and '*', '/' and -** from '/', '/' to end-of-line are also considered to be whitespace. -*/ -static int json5Whitespace(const char *zIn){ - int n = 0; - const u8 *z = (u8*)zIn; - while( 1 /*exit by "goto whitespace_done"*/ ){ - switch( z[n] ){ - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x20: { - n++; - break; - } - case '/': { - if( z[n+1]=='*' && z[n+2]!=0 ){ - int j; - for(j=n+3; z[j]!='/' || z[j-1]!='*'; j++){ - if( z[j]==0 ) goto whitespace_done; - } - n = j+1; - break; - }else if( z[n+1]=='/' ){ - int j; - char c; - for(j=n+2; (c = z[j])!=0; j++){ - if( c=='\n' || c=='\r' ) break; - if( 0xe2==(u8)c && 0x80==(u8)z[j+1] - && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]) - ){ - j += 2; - break; - } - } - n = j; - if( z[n] ) n++; - break; - } - goto whitespace_done; - } - case 0xc2: { - if( z[n+1]==0xa0 ){ - n += 2; - break; - } - goto whitespace_done; - } - case 0xe1: { - if( z[n+1]==0x9a && z[n+2]==0x80 ){ - n += 3; - break; - } - goto whitespace_done; - } - case 0xe2: { - if( z[n+1]==0x80 ){ - u8 c = z[n+2]; - if( c<0x80 ) goto whitespace_done; - if( c<=0x8a || c==0xa8 || c==0xa9 || c==0xaf ){ - n += 3; - break; - } - }else if( z[n+1]==0x81 && z[n+2]==0x9f ){ - n += 3; - break; - } - goto whitespace_done; - } - case 0xe3: { - if( z[n+1]==0x80 && z[n+2]==0x80 ){ - n += 3; - break; - } - goto whitespace_done; - } - case 0xef: { - if( z[n+1]==0xbb && z[n+2]==0xbf ){ - n += 3; - break; - } - goto whitespace_done; - } - default: { - goto whitespace_done; - } - } - } - whitespace_done: - return n; -} - -/* -** Extra floating-point literals to allow in JSON. -*/ -static const struct NanInfName { - char c1; - char c2; - char n; - char eType; - char nRepl; - char *zMatch; - char *zRepl; -} aNanInfName[] = { - { 'i', 'I', 3, JSONB_FLOAT, 7, "inf", "9.0e999" }, - { 'i', 'I', 8, JSONB_FLOAT, 7, "infinity", "9.0e999" }, - { 'n', 'N', 3, JSONB_NULL, 4, "NaN", "null" }, - { 'q', 'Q', 4, JSONB_NULL, 4, "QNaN", "null" }, - { 's', 'S', 4, JSONB_NULL, 4, "SNaN", "null" }, -}; - - -/* -** Report the wrong number of arguments for json_insert(), json_replace() -** or json_set(). -*/ -static void jsonWrongNumArgs( - sqlite3_context *pCtx, - const char *zFuncName -){ - char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", - zFuncName); - sqlite3_result_error(pCtx, zMsg, -1); - sqlite3_free(zMsg); -} - -/**************************************************************************** -** Utility routines for dealing with the binary BLOB representation of JSON -****************************************************************************/ - -/* -** Expand pParse->aBlob so that it holds at least N bytes. -** -** Return the number of errors. -*/ -static int jsonBlobExpand(JsonParse *pParse, u32 N){ - u8 *aNew; - u32 t; - assert( N>pParse->nBlobAlloc ); - if( pParse->nBlobAlloc==0 ){ - t = 100; - }else{ - t = pParse->nBlobAlloc*2; - } - if( tdb, pParse->aBlob, t); - if( aNew==0 ){ pParse->oom = 1; return 1; } - pParse->aBlob = aNew; - pParse->nBlobAlloc = t; - return 0; -} - -/* -** If pParse->aBlob is not previously editable (because it is taken -** from sqlite3_value_blob(), as indicated by the fact that -** pParse->nBlobAlloc==0 and pParse->nBlob>0) then make it editable -** by making a copy into space obtained from malloc. -** -** Return true on success. Return false on OOM. -*/ -static int jsonBlobMakeEditable(JsonParse *pParse, u32 nExtra){ - u8 *aOld; - u32 nSize; - assert( !pParse->bReadOnly ); - if( pParse->oom ) return 0; - if( pParse->nBlobAlloc>0 ) return 1; - aOld = pParse->aBlob; - nSize = pParse->nBlob + nExtra; - pParse->aBlob = 0; - if( jsonBlobExpand(pParse, nSize) ){ - return 0; - } - assert( pParse->nBlobAlloc >= pParse->nBlob + nExtra ); - memcpy(pParse->aBlob, aOld, pParse->nBlob); - return 1; -} - -/* Expand pParse->aBlob and append one bytes. -*/ -static SQLITE_NOINLINE void jsonBlobExpandAndAppendOneByte( - JsonParse *pParse, - u8 c -){ - jsonBlobExpand(pParse, pParse->nBlob+1); - if( pParse->oom==0 ){ - assert( pParse->nBlob+1<=pParse->nBlobAlloc ); - pParse->aBlob[pParse->nBlob++] = c; - } -} - -/* Append a single character. -*/ -static void jsonBlobAppendOneByte(JsonParse *pParse, u8 c){ - if( pParse->nBlob >= pParse->nBlobAlloc ){ - jsonBlobExpandAndAppendOneByte(pParse, c); - }else{ - pParse->aBlob[pParse->nBlob++] = c; - } -} - -/* Slow version of jsonBlobAppendNode() that first resizes the -** pParse->aBlob structure. -*/ -static void jsonBlobAppendNode(JsonParse*,u8,u32,const void*); -static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode( - JsonParse *pParse, - u8 eType, - u32 szPayload, - const void *aPayload -){ - if( jsonBlobExpand(pParse, pParse->nBlob+szPayload+9) ) return; - jsonBlobAppendNode(pParse, eType, szPayload, aPayload); -} - - -/* Append an node type byte together with the payload size and -** possibly also the payload. -** -** If aPayload is not NULL, then it is a pointer to the payload which -** is also appended. If aPayload is NULL, the pParse->aBlob[] array -** is resized (if necessary) so that it is big enough to hold the -** payload, but the payload is not appended and pParse->nBlob is left -** pointing to where the first byte of payload will eventually be. -*/ -static void jsonBlobAppendNode( - JsonParse *pParse, /* The JsonParse object under construction */ - u8 eType, /* Node type. One of JSONB_* */ - u32 szPayload, /* Number of bytes of payload */ - const void *aPayload /* The payload. Might be NULL */ -){ - u8 *a; - if( pParse->nBlob+szPayload+9 > pParse->nBlobAlloc ){ - jsonBlobExpandAndAppendNode(pParse,eType,szPayload,aPayload); - return; - } - assert( pParse->aBlob!=0 ); - a = &pParse->aBlob[pParse->nBlob]; - if( szPayload<=11 ){ - a[0] = eType | (szPayload<<4); - pParse->nBlob += 1; - }else if( szPayload<=0xff ){ - a[0] = eType | 0xc0; - a[1] = szPayload & 0xff; - pParse->nBlob += 2; - }else if( szPayload<=0xffff ){ - a[0] = eType | 0xd0; - a[1] = (szPayload >> 8) & 0xff; - a[2] = szPayload & 0xff; - pParse->nBlob += 3; - }else{ - a[0] = eType | 0xe0; - a[1] = (szPayload >> 24) & 0xff; - a[2] = (szPayload >> 16) & 0xff; - a[3] = (szPayload >> 8) & 0xff; - a[4] = szPayload & 0xff; - pParse->nBlob += 5; - } - if( aPayload ){ - pParse->nBlob += szPayload; - memcpy(&pParse->aBlob[pParse->nBlob-szPayload], aPayload, szPayload); - } -} - -/* Change the payload size for the node at index i to be szPayload. -*/ -static int jsonBlobChangePayloadSize( - JsonParse *pParse, - u32 i, - u32 szPayload -){ - u8 *a; - u8 szType; - u8 nExtra; - u8 nNeeded; - int delta; - if( pParse->oom ) return 0; - a = &pParse->aBlob[i]; - szType = a[0]>>4; - if( szType<=11 ){ - nExtra = 0; - }else if( szType==12 ){ - nExtra = 1; - }else if( szType==13 ){ - nExtra = 2; - }else{ - nExtra = 4; - } - if( szPayload<=11 ){ - nNeeded = 0; - }else if( szPayload<=0xff ){ - nNeeded = 1; - }else if( szPayload<=0xffff ){ - nNeeded = 2; - }else{ - nNeeded = 4; - } - delta = nNeeded - nExtra; - if( delta ){ - u32 newSize = pParse->nBlob + delta; - if( delta>0 ){ - if( newSize>pParse->nBlobAlloc && jsonBlobExpand(pParse, newSize) ){ - return 0; /* OOM error. Error state recorded in pParse->oom. */ - } - a = &pParse->aBlob[i]; - memmove(&a[1+delta], &a[1], pParse->nBlob - (i+1)); - }else{ - memmove(&a[1], &a[1-delta], pParse->nBlob - (i+1-delta)); - } - pParse->nBlob = newSize; - } - if( nNeeded==0 ){ - a[0] = (a[0] & 0x0f) | (szPayload<<4); - }else if( nNeeded==1 ){ - a[0] = (a[0] & 0x0f) | 0xc0; - a[1] = szPayload & 0xff; - }else if( nNeeded==2 ){ - a[0] = (a[0] & 0x0f) | 0xd0; - a[1] = (szPayload >> 8) & 0xff; - a[2] = szPayload & 0xff; - }else{ - a[0] = (a[0] & 0x0f) | 0xe0; - a[1] = (szPayload >> 24) & 0xff; - a[2] = (szPayload >> 16) & 0xff; - a[3] = (szPayload >> 8) & 0xff; - a[4] = szPayload & 0xff; - } - return delta; -} - -/* -** If z[0] is 'u' and is followed by exactly 4 hexadecimal character, -** then set *pOp to JSONB_TEXTJ and return true. If not, do not make -** any changes to *pOp and return false. -*/ -static int jsonIs4HexB(const char *z, int *pOp){ - if( z[0]!='u' ) return 0; - if( !jsonIs4Hex(&z[1]) ) return 0; - *pOp = JSONB_TEXTJ; - return 1; -} - -/* -** Check a single element of the JSONB in pParse for validity. -** -** The element to be checked starts at offset i and must end at on the -** last byte before iEnd. -** -** Return 0 if everything is correct. Return the 1-based byte offset of the -** error if a problem is detected. (In other words, if the error is at offset -** 0, return 1). -*/ -static u32 jsonbValidityCheck( - const JsonParse *pParse, /* Input JSONB. Only aBlob and nBlob are used */ - u32 i, /* Start of element as pParse->aBlob[i] */ - u32 iEnd, /* One more than the last byte of the element */ - u32 iDepth /* Current nesting depth */ -){ - u32 n, sz, j, k; - const u8 *z; - u8 x; - if( iDepth>JSON_MAX_DEPTH ) return i+1; - sz = 0; - n = jsonbPayloadSize(pParse, i, &sz); - if( NEVER(n==0) ) return i+1; /* Checked by caller */ - if( NEVER(i+n+sz!=iEnd) ) return i+1; /* Checked by caller */ - z = pParse->aBlob; - x = z[i] & 0x0f; - switch( x ){ - case JSONB_NULL: - case JSONB_TRUE: - case JSONB_FALSE: { - return n+sz==1 ? 0 : i+1; - } - case JSONB_INT: { - if( sz<1 ) return i+1; - j = i+n; - if( z[j]=='-' ){ - j++; - if( sz<2 ) return i+1; - } - k = i+n+sz; - while( jk ) return j+1; - if( z[j+1]!='.' && z[j+1]!='e' && z[j+1]!='E' ) return j+1; - j++; - } - for(; j0 ) return j+1; - if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){ - return j+1; - } - seen = 1; - continue; - } - if( z[j]=='e' || z[j]=='E' ){ - if( seen==2 ) return j+1; - if( j==k-1 ) return j+1; - if( z[j+1]=='+' || z[j+1]=='-' ){ - j++; - if( j==k-1 ) return j+1; - } - seen = 2; - continue; - } - return j+1; - } - if( seen==0 ) return i+1; - return 0; - } - case JSONB_TEXT: { - j = i+n; - k = j+sz; - while( j=k ){ - return j+1; - }else if( strchr("\"\\/bfnrt",z[j+1])!=0 ){ - j++; - }else if( z[j+1]=='u' ){ - if( j+5>=k ) return j+1; - if( !jsonIs4Hex((const char*)&z[j+2]) ) return j+1; - j++; - }else if( x!=JSONB_TEXT5 ){ - return j+1; - }else{ - u32 c = 0; - u32 szC = jsonUnescapeOneChar((const char*)&z[j], k-j, &c); - if( c==JSON_INVALID_CHAR ) return j+1; - j += szC - 1; - } - } - j++; - } - return 0; - } - case JSONB_TEXTRAW: { - return 0; - } - case JSONB_ARRAY: { - u32 sub; - j = i+n; - k = j+sz; - while( jk ) return j+1; - sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); - if( sub ) return sub; - j += n + sz; - } - assert( j==k ); - return 0; - } - case JSONB_OBJECT: { - u32 cnt = 0; - u32 sub; - j = i+n; - k = j+sz; - while( jk ) return j+1; - if( (cnt & 1)==0 ){ - x = z[j] & 0x0f; - if( xJSONB_TEXTRAW ) return j+1; - } - sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); - if( sub ) return sub; - cnt++; - j += n + sz; - } - assert( j==k ); - if( (cnt & 1)!=0 ) return j+1; - return 0; - } - default: { - return i+1; - } - } -} - -/* -** Translate a single element of JSON text at pParse->zJson[i] into -** its equivalent binary JSONB representation. Append the translation into -** pParse->aBlob[] beginning at pParse->nBlob. The size of -** pParse->aBlob[] is increased as necessary. -** -** Return the index of the first character past the end of the element parsed, -** or one of the following special result codes: -** -** 0 End of input -** -1 Syntax error or OOM -** -2 '}' seen \ -** -3 ']' seen \___ For these returns, pParse->iErr is set to -** -4 ',' seen / the index in zJson[] of the seen character -** -5 ':' seen / -*/ -static int jsonTranslateTextToBlob(JsonParse *pParse, u32 i){ - char c; - u32 j; - u32 iThis, iStart; - int x; - u8 t; - const char *z = pParse->zJson; -json_parse_restart: - switch( (u8)z[i] ){ - case '{': { - /* Parse object */ - iThis = pParse->nBlob; - jsonBlobAppendNode(pParse, JSONB_OBJECT, pParse->nJson-i, 0); - if( ++pParse->iDepth > JSON_MAX_DEPTH ){ - pParse->iErr = i; - return -1; - } - iStart = pParse->nBlob; - for(j=i+1;;j++){ - u32 iBlob = pParse->nBlob; - x = jsonTranslateTextToBlob(pParse, j); - if( x<=0 ){ - int op; - if( x==(-2) ){ - j = pParse->iErr; - if( pParse->nBlob!=(u32)iStart ) pParse->hasNonstd = 1; - break; - } - j += json5Whitespace(&z[j]); - op = JSONB_TEXT; - if( sqlite3JsonId1(z[j]) - || (z[j]=='\\' && jsonIs4HexB(&z[j+1], &op)) - ){ - int k = j+1; - while( (sqlite3JsonId2(z[k]) && json5Whitespace(&z[k])==0) - || (z[k]=='\\' && jsonIs4HexB(&z[k+1], &op)) - ){ - k++; - } - assert( iBlob==pParse->nBlob ); - jsonBlobAppendNode(pParse, op, k-j, &z[j]); - pParse->hasNonstd = 1; - x = k; - }else{ - if( x!=-1 ) pParse->iErr = j; - return -1; - } - } - if( pParse->oom ) return -1; - t = pParse->aBlob[iBlob] & 0x0f; - if( tJSONB_TEXTRAW ){ - pParse->iErr = j; - return -1; - } - j = x; - if( z[j]==':' ){ - j++; - }else{ - if( jsonIsspace(z[j]) ){ - /* strspn() is not helpful here */ - do{ j++; }while( jsonIsspace(z[j]) ); - if( z[j]==':' ){ - j++; - goto parse_object_value; - } - } - x = jsonTranslateTextToBlob(pParse, j); - if( x!=(-5) ){ - if( x!=(-1) ) pParse->iErr = j; - return -1; - } - j = pParse->iErr+1; - } - parse_object_value: - x = jsonTranslateTextToBlob(pParse, j); - if( x<=0 ){ - if( x!=(-1) ) pParse->iErr = j; - return -1; - } - j = x; - if( z[j]==',' ){ - continue; - }else if( z[j]=='}' ){ - break; - }else{ - if( jsonIsspace(z[j]) ){ - j += 1 + (u32)strspn(&z[j+1], jsonSpaces); - if( z[j]==',' ){ - continue; - }else if( z[j]=='}' ){ - break; - } - } - x = jsonTranslateTextToBlob(pParse, j); - if( x==(-4) ){ - j = pParse->iErr; - continue; - } - if( x==(-2) ){ - j = pParse->iErr; - break; - } - } - pParse->iErr = j; - return -1; - } - jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart); - pParse->iDepth--; - return j+1; - } - case '[': { - /* Parse array */ - iThis = pParse->nBlob; - assert( i<=(u32)pParse->nJson ); - jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0); - iStart = pParse->nBlob; - if( pParse->oom ) return -1; - if( ++pParse->iDepth > JSON_MAX_DEPTH ){ - pParse->iErr = i; - return -1; - } - for(j=i+1;;j++){ - x = jsonTranslateTextToBlob(pParse, j); - if( x<=0 ){ - if( x==(-3) ){ - j = pParse->iErr; - if( pParse->nBlob!=iStart ) pParse->hasNonstd = 1; - break; - } - if( x!=(-1) ) pParse->iErr = j; - return -1; - } - j = x; - if( z[j]==',' ){ - continue; - }else if( z[j]==']' ){ - break; - }else{ - if( jsonIsspace(z[j]) ){ - j += 1 + (u32)strspn(&z[j+1], jsonSpaces); - if( z[j]==',' ){ - continue; - }else if( z[j]==']' ){ - break; - } - } - x = jsonTranslateTextToBlob(pParse, j); - if( x==(-4) ){ - j = pParse->iErr; - continue; - } - if( x==(-3) ){ - j = pParse->iErr; - break; - } - } - pParse->iErr = j; - return -1; - } - jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart); - pParse->iDepth--; - return j+1; - } - case '\'': { - u8 opcode; - char cDelim; - pParse->hasNonstd = 1; - opcode = JSONB_TEXT; - goto parse_string; - case '"': - /* Parse string */ - opcode = JSONB_TEXT; - parse_string: - cDelim = z[i]; - j = i+1; - while( 1 /*exit-by-break*/ ){ - if( jsonIsOk[(u8)z[j]] ){ - if( !jsonIsOk[(u8)z[j+1]] ){ - j += 1; - }else if( !jsonIsOk[(u8)z[j+2]] ){ - j += 2; - }else{ - j += 3; - continue; - } - } - c = z[j]; - if( c==cDelim ){ - break; - }else if( c=='\\' ){ - c = z[++j]; - if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' - || c=='n' || c=='r' || c=='t' - || (c=='u' && jsonIs4Hex(&z[j+1])) ){ - if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ; - }else if( c=='\'' || c=='0' || c=='v' || c=='\n' - || (0xe2==(u8)c && 0x80==(u8)z[j+1] - && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2])) - || (c=='x' && jsonIs2Hex(&z[j+1])) ){ - opcode = JSONB_TEXT5; - pParse->hasNonstd = 1; - }else if( c=='\r' ){ - if( z[j+1]=='\n' ) j++; - opcode = JSONB_TEXT5; - pParse->hasNonstd = 1; - }else{ - pParse->iErr = j; - return -1; - } - }else if( c<=0x1f ){ - if( c==0 ){ - pParse->iErr = j; - return -1; - } - /* Control characters are not allowed in canonical JSON string - ** literals, but are allowed in JSON5 string literals. */ - opcode = JSONB_TEXT5; - pParse->hasNonstd = 1; - }else if( c=='"' ){ - opcode = JSONB_TEXT5; - } - j++; - } - jsonBlobAppendNode(pParse, opcode, j-1-i, &z[i+1]); - return j+1; - } - case 't': { - if( strncmp(z+i,"true",4)==0 && !sqlite3Isalnum(z[i+4]) ){ - jsonBlobAppendOneByte(pParse, JSONB_TRUE); - return i+4; - } - pParse->iErr = i; - return -1; - } - case 'f': { - if( strncmp(z+i,"false",5)==0 && !sqlite3Isalnum(z[i+5]) ){ - jsonBlobAppendOneByte(pParse, JSONB_FALSE); - return i+5; - } - pParse->iErr = i; - return -1; - } - case '+': { - u8 seenE; - pParse->hasNonstd = 1; - t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ - goto parse_number; - case '.': - if( sqlite3Isdigit(z[i+1]) ){ - pParse->hasNonstd = 1; - t = 0x03; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ - seenE = 0; - goto parse_number_2; - } - pParse->iErr = i; - return -1; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* Parse number */ - t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */ - parse_number: - seenE = 0; - assert( '-' < '0' ); - assert( '+' < '0' ); - assert( '.' < '0' ); - c = z[i]; - - if( c<='0' ){ - if( c=='0' ){ - if( (z[i+1]=='x' || z[i+1]=='X') && sqlite3Isxdigit(z[i+2]) ){ - assert( t==0x00 ); - pParse->hasNonstd = 1; - t = 0x01; - for(j=i+3; sqlite3Isxdigit(z[j]); j++){} - goto parse_number_finish; - }else if( sqlite3Isdigit(z[i+1]) ){ - pParse->iErr = i+1; - return -1; - } - }else{ - if( !sqlite3Isdigit(z[i+1]) ){ - /* JSON5 allows for "+Infinity" and "-Infinity" using exactly - ** that case. SQLite also allows these in any case and it allows - ** "+inf" and "-inf". */ - if( (z[i+1]=='I' || z[i+1]=='i') - && sqlite3StrNICmp(&z[i+1], "inf",3)==0 - ){ - pParse->hasNonstd = 1; - if( z[i]=='-' ){ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); - }else{ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); - } - return i + (sqlite3StrNICmp(&z[i+4],"inity",5)==0 ? 9 : 4); - } - if( z[i+1]=='.' ){ - pParse->hasNonstd = 1; - t |= 0x01; - goto parse_number_2; - } - pParse->iErr = i; - return -1; - } - if( z[i+1]=='0' ){ - if( sqlite3Isdigit(z[i+2]) ){ - pParse->iErr = i+1; - return -1; - }else if( (z[i+2]=='x' || z[i+2]=='X') && sqlite3Isxdigit(z[i+3]) ){ - pParse->hasNonstd = 1; - t |= 0x01; - for(j=i+4; sqlite3Isxdigit(z[j]); j++){} - goto parse_number_finish; - } - } - } - } - - parse_number_2: - for(j=i+1;; j++){ - c = z[j]; - if( sqlite3Isdigit(c) ) continue; - if( c=='.' ){ - if( (t & 0x02)!=0 ){ - pParse->iErr = j; - return -1; - } - t |= 0x02; - continue; - } - if( c=='e' || c=='E' ){ - if( z[j-1]<'0' ){ - if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ - pParse->hasNonstd = 1; - t |= 0x01; - }else{ - pParse->iErr = j; - return -1; - } - } - if( seenE ){ - pParse->iErr = j; - return -1; - } - t |= 0x02; - seenE = 1; - c = z[j+1]; - if( c=='+' || c=='-' ){ - j++; - c = z[j+1]; - } - if( c<'0' || c>'9' ){ - pParse->iErr = j; - return -1; - } - continue; - } - break; - } - if( z[j-1]<'0' ){ - if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ - pParse->hasNonstd = 1; - t |= 0x01; - }else{ - pParse->iErr = j; - return -1; - } - } - parse_number_finish: - assert( JSONB_INT+0x01==JSONB_INT5 ); - assert( JSONB_FLOAT+0x01==JSONB_FLOAT5 ); - assert( JSONB_INT+0x02==JSONB_FLOAT ); - if( z[i]=='+' ) i++; - jsonBlobAppendNode(pParse, JSONB_INT+t, j-i, &z[i]); - return j; - } - case '}': { - pParse->iErr = i; - return -2; /* End of {...} */ - } - case ']': { - pParse->iErr = i; - return -3; /* End of [...] */ - } - case ',': { - pParse->iErr = i; - return -4; /* List separator */ - } - case ':': { - pParse->iErr = i; - return -5; /* Object label/value separator */ - } - case 0: { - return 0; /* End of file */ - } - case 0x09: - case 0x0a: - case 0x0d: - case 0x20: { - i += 1 + (u32)strspn(&z[i+1], jsonSpaces); - goto json_parse_restart; - } - case 0x0b: - case 0x0c: - case '/': - case 0xc2: - case 0xe1: - case 0xe2: - case 0xe3: - case 0xef: { - j = json5Whitespace(&z[i]); - if( j>0 ){ - i += j; - pParse->hasNonstd = 1; - goto json_parse_restart; - } - pParse->iErr = i; - return -1; - } - case 'n': { - if( strncmp(z+i,"null",4)==0 && !sqlite3Isalnum(z[i+4]) ){ - jsonBlobAppendOneByte(pParse, JSONB_NULL); - return i+4; - } - /* fall-through into the default case that checks for NaN */ - /* no break */ deliberate_fall_through - } - default: { - u32 k; - int nn; - c = z[i]; - for(k=0; khasNonstd = 1; - return i + nn; - } - pParse->iErr = i; - return -1; /* Syntax error */ - } - } /* End switch(z[i]) */ -} - - -/* -** Parse a complete JSON string. Return 0 on success or non-zero if there -** are any errors. If an error occurs, free all memory held by pParse, -** but not pParse itself. -** -** pParse must be initialized to an empty parse object prior to calling -** this routine. -*/ -static int jsonConvertTextToBlob( - JsonParse *pParse, /* Initialize and fill this JsonParse object */ - sqlite3_context *pCtx /* Report errors here */ -){ - int i; - const char *zJson = pParse->zJson; - i = jsonTranslateTextToBlob(pParse, 0); - if( pParse->oom ) i = -1; - if( i>0 ){ -#ifdef SQLITE_DEBUG - assert( pParse->iDepth==0 ); - if( sqlite3Config.bJsonSelfcheck ){ - assert( jsonbValidityCheck(pParse, 0, pParse->nBlob, 0)==0 ); - } -#endif - while( jsonIsspace(zJson[i]) ) i++; - if( zJson[i] ){ - i += json5Whitespace(&zJson[i]); - if( zJson[i] ){ - if( pCtx ) sqlite3_result_error(pCtx, "malformed JSON", -1); - jsonParseReset(pParse); - return 1; - } - pParse->hasNonstd = 1; - } - } - if( i<=0 ){ - if( pCtx!=0 ){ - if( pParse->oom ){ - sqlite3_result_error_nomem(pCtx); - }else{ - sqlite3_result_error(pCtx, "malformed JSON", -1); - } - } - jsonParseReset(pParse); - return 1; - } - return 0; -} - -/* -** The input string pStr is a well-formed JSON text string. Convert -** this into the JSONB format and make it the return value of the -** SQL function. -*/ -static void jsonReturnStringAsBlob(JsonString *pStr){ - JsonParse px; - memset(&px, 0, sizeof(px)); - jsonStringTerminate(pStr); - if( pStr->eErr ){ - sqlite3_result_error_nomem(pStr->pCtx); - return; - } - px.zJson = pStr->zBuf; - px.nJson = pStr->nUsed; - px.db = sqlite3_context_db_handle(pStr->pCtx); - (void)jsonTranslateTextToBlob(&px, 0); - if( px.oom ){ - sqlite3DbFree(px.db, px.aBlob); - sqlite3_result_error_nomem(pStr->pCtx); - }else{ - assert( px.nBlobAlloc>0 ); - assert( !px.bReadOnly ); - sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, SQLITE_DYNAMIC); - } -} - -/* The byte at index i is a node type-code. This routine -** determines the payload size for that node and writes that -** payload size in to *pSz. It returns the offset from i to the -** beginning of the payload. Return 0 on error. -*/ -static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){ - u8 x; - u32 sz; - u32 n; - if( NEVER(i>pParse->nBlob) ){ - *pSz = 0; - return 0; - } - x = pParse->aBlob[i]>>4; - if( x<=11 ){ - sz = x; - n = 1; - }else if( x==12 ){ - if( i+1>=pParse->nBlob ){ - *pSz = 0; - return 0; - } - sz = pParse->aBlob[i+1]; - n = 2; - }else if( x==13 ){ - if( i+2>=pParse->nBlob ){ - *pSz = 0; - return 0; - } - sz = (pParse->aBlob[i+1]<<8) + pParse->aBlob[i+2]; - n = 3; - }else if( x==14 ){ - if( i+4>=pParse->nBlob ){ - *pSz = 0; - return 0; - } - sz = ((u32)pParse->aBlob[i+1]<<24) + (pParse->aBlob[i+2]<<16) + - (pParse->aBlob[i+3]<<8) + pParse->aBlob[i+4]; - n = 5; - }else{ - if( i+8>=pParse->nBlob - || pParse->aBlob[i+1]!=0 - || pParse->aBlob[i+2]!=0 - || pParse->aBlob[i+3]!=0 - || pParse->aBlob[i+4]!=0 - ){ - *pSz = 0; - return 0; - } - sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) + - (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8]; - n = 9; - } - if( (i64)i+sz+n > pParse->nBlob - && (i64)i+sz+n > pParse->nBlob-pParse->delta - ){ - sz = 0; - n = 0; - } - *pSz = sz; - return n; -} - - -/* -** Translate the binary JSONB representation of JSON beginning at -** pParse->aBlob[i] into a JSON text string. Append the JSON -** text onto the end of pOut. Return the index in pParse->aBlob[] -** of the first byte past the end of the element that is translated. -** -** If an error is detected in the BLOB input, the pOut->eErr flag -** might get set to JSTRING_MALFORMED. But not all BLOB input errors -** are detected. So a malformed JSONB input might either result -** in an error, or in incorrect JSON. -** -** The pOut->eErr JSTRING_OOM flag is set on a OOM. -*/ -static u32 jsonTranslateBlobToText( - const JsonParse *pParse, /* the complete parse of the JSON */ - u32 i, /* Start rendering at this index */ - JsonString *pOut /* Write JSON here */ -){ - u32 sz, n, j, iEnd; - - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ){ - pOut->eErr |= JSTRING_MALFORMED; - return pParse->nBlob+1; - } - switch( pParse->aBlob[i] & 0x0f ){ - case JSONB_NULL: { - jsonAppendRawNZ(pOut, "null", 4); - return i+1; - } - case JSONB_TRUE: { - jsonAppendRawNZ(pOut, "true", 4); - return i+1; - } - case JSONB_FALSE: { - jsonAppendRawNZ(pOut, "false", 5); - return i+1; - } - case JSONB_INT: - case JSONB_FLOAT: { - if( sz==0 ) goto malformed_jsonb; - jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz); - break; - } - case JSONB_INT5: { /* Integer literal in hexadecimal notation */ - u32 k = 2; - sqlite3_uint64 u = 0; - const char *zIn = (const char*)&pParse->aBlob[i+n]; - int bOverflow = 0; - if( sz==0 ) goto malformed_jsonb; - if( zIn[0]=='-' ){ - jsonAppendChar(pOut, '-'); - k++; - }else if( zIn[0]=='+' ){ - k++; - } - for(; keErr |= JSTRING_MALFORMED; - break; - }else if( (u>>60)!=0 ){ - bOverflow = 1; - }else{ - u = u*16 + sqlite3HexToInt(zIn[k]); - } - } - jsonPrintf(100,pOut,bOverflow?"9.0e999":"%llu", u); - break; - } - case JSONB_FLOAT5: { /* Float literal missing digits beside "." */ - u32 k = 0; - const char *zIn = (const char*)&pParse->aBlob[i+n]; - if( sz==0 ) goto malformed_jsonb; - if( zIn[0]=='-' ){ - jsonAppendChar(pOut, '-'); - k++; - } - if( zIn[k]=='.' ){ - jsonAppendChar(pOut, '0'); - } - for(; kaBlob[i+n], sz); - jsonAppendChar(pOut, '"'); - break; - } - case JSONB_TEXT5: { - const char *zIn; - u32 k; - u32 sz2 = sz; - zIn = (const char*)&pParse->aBlob[i+n]; - jsonAppendChar(pOut, '"'); - while( sz2>0 ){ - for(k=0; k0 ){ - jsonAppendRawNZ(pOut, zIn, k); - if( k>=sz2 ){ - break; - } - zIn += k; - sz2 -= k; - } - if( zIn[0]=='"' ){ - jsonAppendRawNZ(pOut, "\\\"", 2); - zIn++; - sz2--; - continue; - } - if( zIn[0]<=0x1f ){ - if( pOut->nUsed+7>pOut->nAlloc && jsonStringGrow(pOut,7) ) break; - jsonAppendControlChar(pOut, zIn[0]); - zIn++; - sz2--; - continue; - } - assert( zIn[0]=='\\' ); - assert( sz2>=1 ); - if( sz2<2 ){ - pOut->eErr |= JSTRING_MALFORMED; - break; - } - switch( (u8)zIn[1] ){ - case '\'': - jsonAppendChar(pOut, '\''); - break; - case 'v': - jsonAppendRawNZ(pOut, "\\u0009", 6); - break; - case 'x': - if( sz2<4 ){ - pOut->eErr |= JSTRING_MALFORMED; - sz2 = 2; - break; - } - jsonAppendRawNZ(pOut, "\\u00", 4); - jsonAppendRawNZ(pOut, &zIn[2], 2); - zIn += 2; - sz2 -= 2; - break; - case '0': - jsonAppendRawNZ(pOut, "\\u0000", 6); - break; - case '\r': - if( sz2>2 && zIn[2]=='\n' ){ - zIn++; - sz2--; - } - break; - case '\n': - break; - case 0xe2: - /* '\' followed by either U+2028 or U+2029 is ignored as - ** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29. - ** U+2029 is the same except for the last byte */ - if( sz2<4 - || 0x80!=(u8)zIn[2] - || (0xa8!=(u8)zIn[3] && 0xa9!=(u8)zIn[3]) - ){ - pOut->eErr |= JSTRING_MALFORMED; - sz2 = 2; - break; - } - zIn += 2; - sz2 -= 2; - break; - default: - jsonAppendRawNZ(pOut, zIn, 2); - break; - } - assert( sz2>=2 ); - zIn += 2; - sz2 -= 2; - } - jsonAppendChar(pOut, '"'); - break; - } - case JSONB_TEXTRAW: { - jsonAppendString(pOut, (const char*)&pParse->aBlob[i+n], sz); - break; - } - case JSONB_ARRAY: { - jsonAppendChar(pOut, '['); - j = i+n; - iEnd = j+sz; - while( jeErr==0 ){ - j = jsonTranslateBlobToText(pParse, j, pOut); - jsonAppendChar(pOut, ','); - } - if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; - if( sz>0 ) jsonStringTrimOneChar(pOut); - jsonAppendChar(pOut, ']'); - break; - } - case JSONB_OBJECT: { - int x = 0; - jsonAppendChar(pOut, '{'); - j = i+n; - iEnd = j+sz; - while( jeErr==0 ){ - j = jsonTranslateBlobToText(pParse, j, pOut); - jsonAppendChar(pOut, (x++ & 1) ? ',' : ':'); - } - if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; - if( sz>0 ) jsonStringTrimOneChar(pOut); - jsonAppendChar(pOut, '}'); - break; - } - - default: { - malformed_jsonb: - pOut->eErr |= JSTRING_MALFORMED; - break; - } - } - return i+n+sz; -} - -/* Context for recursion of json_pretty() -*/ -typedef struct JsonPretty JsonPretty; -struct JsonPretty { - JsonParse *pParse; /* The BLOB being rendered */ - JsonString *pOut; /* Generate pretty output into this string */ - const char *zIndent; /* Use this text for indentation */ - u32 szIndent; /* Bytes in zIndent[] */ - u32 nIndent; /* Current level of indentation */ -}; - -/* Append indentation to the pretty JSON under construction */ -static void jsonPrettyIndent(JsonPretty *pPretty){ - u32 jj; - for(jj=0; jjnIndent; jj++){ - jsonAppendRaw(pPretty->pOut, pPretty->zIndent, pPretty->szIndent); - } -} - -/* -** Translate the binary JSONB representation of JSON beginning at -** pParse->aBlob[i] into a JSON text string. Append the JSON -** text onto the end of pOut. Return the index in pParse->aBlob[] -** of the first byte past the end of the element that is translated. -** -** This is a variant of jsonTranslateBlobToText() that "pretty-prints" -** the output. Extra whitespace is inserted to make the JSON easier -** for humans to read. -** -** If an error is detected in the BLOB input, the pOut->eErr flag -** might get set to JSTRING_MALFORMED. But not all BLOB input errors -** are detected. So a malformed JSONB input might either result -** in an error, or in incorrect JSON. -** -** The pOut->eErr JSTRING_OOM flag is set on a OOM. -*/ -static u32 jsonTranslateBlobToPrettyText( - JsonPretty *pPretty, /* Pretty-printing context */ - u32 i /* Start rendering at this index */ -){ - u32 sz, n, j, iEnd; - const JsonParse *pParse = pPretty->pParse; - JsonString *pOut = pPretty->pOut; - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ){ - pOut->eErr |= JSTRING_MALFORMED; - return pParse->nBlob+1; - } - switch( pParse->aBlob[i] & 0x0f ){ - case JSONB_ARRAY: { - j = i+n; - iEnd = j+sz; - jsonAppendChar(pOut, '['); - if( jnIndent++; - while( pOut->eErr==0 ){ - jsonPrettyIndent(pPretty); - j = jsonTranslateBlobToPrettyText(pPretty, j); - if( j>=iEnd ) break; - jsonAppendRawNZ(pOut, ",\n", 2); - } - jsonAppendChar(pOut, '\n'); - pPretty->nIndent--; - jsonPrettyIndent(pPretty); - } - jsonAppendChar(pOut, ']'); - i = iEnd; - break; - } - case JSONB_OBJECT: { - j = i+n; - iEnd = j+sz; - jsonAppendChar(pOut, '{'); - if( jnIndent++; - while( pOut->eErr==0 ){ - jsonPrettyIndent(pPretty); - j = jsonTranslateBlobToText(pParse, j, pOut); - if( j>iEnd ){ - pOut->eErr |= JSTRING_MALFORMED; - break; - } - jsonAppendRawNZ(pOut, ": ", 2); - j = jsonTranslateBlobToPrettyText(pPretty, j); - if( j>=iEnd ) break; - jsonAppendRawNZ(pOut, ",\n", 2); - } - jsonAppendChar(pOut, '\n'); - pPretty->nIndent--; - jsonPrettyIndent(pPretty); - } - jsonAppendChar(pOut, '}'); - i = iEnd; - break; - } - default: { - i = jsonTranslateBlobToText(pParse, i, pOut); - break; - } - } - return i; -} - - -/* Return true if the input pJson -** -** For performance reasons, this routine does not do a detailed check of the -** input BLOB to ensure that it is well-formed. Hence, false positives are -** possible. False negatives should never occur, however. -*/ -static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){ - u32 sz, n; - const u8 *aBlob; - int nBlob; - JsonParse s; - if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0; - aBlob = sqlite3_value_blob(pJson); - nBlob = sqlite3_value_bytes(pJson); - if( nBlob<1 ) return 0; - if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0; - memset(&s, 0, sizeof(s)); - s.aBlob = (u8*)aBlob; - s.nBlob = nBlob; - n = jsonbPayloadSize(&s, 0, &sz); - if( n==0 ) return 0; - if( sz+n!=(u32)nBlob ) return 0; - if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0; - return sz+n==(u32)nBlob; -} - -/* -** Given that a JSONB_ARRAY object starts at offset i, return -** the number of entries in that array. -*/ -static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){ - u32 n, sz, i, iEnd; - u32 k = 0; - n = jsonbPayloadSize(pParse, iRoot, &sz); - iEnd = iRoot+n+sz; - for(i=iRoot+n; n>0 && idelta. -*/ -static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){ - u32 sz = 0; - u32 nBlob; - assert( pParse->delta!=0 ); - assert( pParse->nBlobAlloc >= pParse->nBlob ); - nBlob = pParse->nBlob; - pParse->nBlob = pParse->nBlobAlloc; - (void)jsonbPayloadSize(pParse, iRoot, &sz); - pParse->nBlob = nBlob; - sz += pParse->delta; - pParse->delta += jsonBlobChangePayloadSize(pParse, iRoot, sz); -} - -/* -** Modify the JSONB blob at pParse->aBlob by removing nDel bytes of -** content beginning at iDel, and replacing them with nIns bytes of -** content given by aIns. -** -** nDel may be zero, in which case no bytes are removed. But iDel is -** still important as new bytes will be insert beginning at iDel. -** -** aIns may be zero, in which case space is created to hold nIns bytes -** beginning at iDel, but that space is uninitialized. -** -** Set pParse->oom if an OOM occurs. -*/ -static void jsonBlobEdit( - JsonParse *pParse, /* The JSONB to be modified is in pParse->aBlob */ - u32 iDel, /* First byte to be removed */ - u32 nDel, /* Number of bytes to remove */ - const u8 *aIns, /* Content to insert */ - u32 nIns /* Bytes of content to insert */ -){ - i64 d = (i64)nIns - (i64)nDel; - if( d!=0 ){ - if( pParse->nBlob + d > pParse->nBlobAlloc ){ - jsonBlobExpand(pParse, pParse->nBlob+d); - if( pParse->oom ) return; - } - memmove(&pParse->aBlob[iDel+nIns], - &pParse->aBlob[iDel+nDel], - pParse->nBlob - (iDel+nDel)); - pParse->nBlob += d; - pParse->delta += d; - } - if( nIns && aIns ) memcpy(&pParse->aBlob[iDel], aIns, nIns); -} - -/* -** Return the number of escaped newlines to be ignored. -** An escaped newline is a one of the following byte sequences: -** -** 0x5c 0x0a -** 0x5c 0x0d -** 0x5c 0x0d 0x0a -** 0x5c 0xe2 0x80 0xa8 -** 0x5c 0xe2 0x80 0xa9 -*/ -static u32 jsonBytesToBypass(const char *z, u32 n){ - u32 i = 0; - while( i+10 ); - assert( z[0]=='\\' ); - if( n<2 ){ - *piOut = JSON_INVALID_CHAR; - return n; - } - switch( (u8)z[1] ){ - case 'u': { - u32 v, vlo; - if( n<6 ){ - *piOut = JSON_INVALID_CHAR; - return n; - } - v = jsonHexToInt4(&z[2]); - if( (v & 0xfc00)==0xd800 - && n>=12 - && z[6]=='\\' - && z[7]=='u' - && ((vlo = jsonHexToInt4(&z[8]))&0xfc00)==0xdc00 - ){ - *piOut = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000; - return 12; - }else{ - *piOut = v; - return 6; - } - } - case 'b': { *piOut = '\b'; return 2; } - case 'f': { *piOut = '\f'; return 2; } - case 'n': { *piOut = '\n'; return 2; } - case 'r': { *piOut = '\r'; return 2; } - case 't': { *piOut = '\t'; return 2; } - case 'v': { *piOut = '\v'; return 2; } - case '0': { *piOut = 0; return 2; } - case '\'': - case '"': - case '/': - case '\\':{ *piOut = z[1]; return 2; } - case 'x': { - if( n<4 ){ - *piOut = JSON_INVALID_CHAR; - return n; - } - *piOut = (jsonHexToInt(z[2])<<4) | jsonHexToInt(z[3]); - return 4; - } - case 0xe2: - case '\r': - case '\n': { - u32 nSkip = jsonBytesToBypass(z, n); - if( nSkip==0 ){ - *piOut = JSON_INVALID_CHAR; - return n; - }else if( nSkip==n ){ - *piOut = 0; - return n; - }else if( z[nSkip]=='\\' ){ - return nSkip + jsonUnescapeOneChar(&z[nSkip], n-nSkip, piOut); - }else{ - int sz = sqlite3Utf8ReadLimited((u8*)&z[nSkip], n-nSkip, piOut); - return nSkip + sz; - } - } - default: { - *piOut = JSON_INVALID_CHAR; - return 2; - } - } -} - - -/* -** Compare two object labels. Return 1 if they are equal and -** 0 if they differ. -** -** In this version, we know that one or the other or both of the -** two comparands contains an escape sequence. -*/ -static SQLITE_NOINLINE int jsonLabelCompareEscaped( - const char *zLeft, /* The left label */ - u32 nLeft, /* Size of the left label in bytes */ - int rawLeft, /* True if zLeft contains no escapes */ - const char *zRight, /* The right label */ - u32 nRight, /* Size of the right label in bytes */ - int rawRight /* True if zRight is escape-free */ -){ - u32 cLeft, cRight; - assert( rawLeft==0 || rawRight==0 ); - while( 1 /*exit-by-return*/ ){ - if( nLeft==0 ){ - cLeft = 0; - }else if( rawLeft || zLeft[0]!='\\' ){ - cLeft = ((u8*)zLeft)[0]; - if( cLeft>=0xc0 ){ - int sz = sqlite3Utf8ReadLimited((u8*)zLeft, nLeft, &cLeft); - zLeft += sz; - nLeft -= sz; - }else{ - zLeft++; - nLeft--; - } - }else{ - u32 n = jsonUnescapeOneChar(zLeft, nLeft, &cLeft); - zLeft += n; - assert( n<=nLeft ); - nLeft -= n; - } - if( nRight==0 ){ - cRight = 0; - }else if( rawRight || zRight[0]!='\\' ){ - cRight = ((u8*)zRight)[0]; - if( cRight>=0xc0 ){ - int sz = sqlite3Utf8ReadLimited((u8*)zRight, nRight, &cRight); - zRight += sz; - nRight -= sz; - }else{ - zRight++; - nRight--; - } - }else{ - u32 n = jsonUnescapeOneChar(zRight, nRight, &cRight); - zRight += n; - assert( n<=nRight ); - nRight -= n; - } - if( cLeft!=cRight ) return 0; - if( cLeft==0 ) return 1; - } -} - -/* -** Compare two object labels. Return 1 if they are equal and -** 0 if they differ. Return -1 if an OOM occurs. -*/ -static int jsonLabelCompare( - const char *zLeft, /* The left label */ - u32 nLeft, /* Size of the left label in bytes */ - int rawLeft, /* True if zLeft contains no escapes */ - const char *zRight, /* The right label */ - u32 nRight, /* Size of the right label in bytes */ - int rawRight /* True if zRight is escape-free */ -){ - if( rawLeft && rawRight ){ - /* Simpliest case: Neither label contains escapes. A simple - ** memcmp() is sufficient. */ - if( nLeft!=nRight ) return 0; - return memcmp(zLeft, zRight, nLeft)==0; - }else{ - return jsonLabelCompareEscaped(zLeft, nLeft, rawLeft, - zRight, nRight, rawRight); - } -} - -/* -** Error returns from jsonLookupStep() -*/ -#define JSON_LOOKUP_ERROR 0xffffffff -#define JSON_LOOKUP_NOTFOUND 0xfffffffe -#define JSON_LOOKUP_PATHERROR 0xfffffffd -#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR) - -/* Forward declaration */ -static u32 jsonLookupStep(JsonParse*,u32,const char*,u32); - - -/* This helper routine for jsonLookupStep() populates pIns with -** binary data that is to be inserted into pParse. -** -** In the common case, pIns just points to pParse->aIns and pParse->nIns. -** But if the zPath of the original edit operation includes path elements -** that go deeper, additional substructure must be created. -** -** For example: -** -** json_insert('{}', '$.a.b.c', 123); -** -** The search stops at '$.a' But additional substructure must be -** created for the ".b.c" part of the patch so that the final result -** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with -** the binary equivalent of {"b":{"c":123}} so that it can be inserted. -** -** The caller is responsible for resetting pIns when it has finished -** using the substructure. -*/ -static u32 jsonCreateEditSubstructure( - JsonParse *pParse, /* The original JSONB that is being edited */ - JsonParse *pIns, /* Populate this with the blob data to insert */ - const char *zTail /* Tail of the path that determins substructure */ -){ - static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT }; - int rc; - memset(pIns, 0, sizeof(*pIns)); - pIns->db = pParse->db; - if( zTail[0]==0 ){ - /* No substructure. Just insert what is given in pParse. */ - pIns->aBlob = pParse->aIns; - pIns->nBlob = pParse->nIns; - rc = 0; - }else{ - /* Construct the binary substructure */ - pIns->nBlob = 1; - pIns->aBlob = (u8*)&emptyObject[zTail[0]=='.']; - pIns->eEdit = pParse->eEdit; - pIns->nIns = pParse->nIns; - pIns->aIns = pParse->aIns; - rc = jsonLookupStep(pIns, 0, zTail, 0); - pParse->oom |= pIns->oom; - } - return rc; /* Error code only */ -} - -/* -** Search along zPath to find the Json element specified. Return an -** index into pParse->aBlob[] for the start of that element's value. -** -** If the value found by this routine is the value half of label/value pair -** within an object, then set pPath->iLabel to the start of the corresponding -** label, before returning. -** -** Return one of the JSON_LOOKUP error codes if problems are seen. -** -** This routine will also modify the blob. If pParse->eEdit is one of -** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be -** made to the selected value. If an edit is performed, then the return -** value does not necessarily point to the select element. If an edit -** is performed, the return value is only useful for detecting error -** conditions. -*/ -static u32 jsonLookupStep( - JsonParse *pParse, /* The JSON to search */ - u32 iRoot, /* Begin the search at this element of aBlob[] */ - const char *zPath, /* The path to search */ - u32 iLabel /* Label if iRoot is a value of in an object */ -){ - u32 i, j, k, nKey, sz, n, iEnd, rc; - const char *zKey; - u8 x; - - if( zPath[0]==0 ){ - if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){ - n = jsonbPayloadSize(pParse, iRoot, &sz); - sz += n; - if( pParse->eEdit==JEDIT_DEL ){ - if( iLabel>0 ){ - sz += iRoot - iLabel; - iRoot = iLabel; - } - jsonBlobEdit(pParse, iRoot, sz, 0, 0); - }else if( pParse->eEdit==JEDIT_INS ){ - /* Already exists, so json_insert() is a no-op */ - }else{ - /* json_set() or json_replace() */ - jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns); - } - } - pParse->iLabel = iLabel; - return iRoot; - } - if( zPath[0]=='.' ){ - int rawKey = 1; - x = pParse->aBlob[iRoot]; - zPath++; - if( zPath[0]=='"' ){ - zKey = zPath + 1; - for(i=1; zPath[i] && zPath[i]!='"'; i++){ - if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++; - } - nKey = i-1; - if( zPath[i] ){ - i++; - }else{ - return JSON_LOOKUP_PATHERROR; - } - testcase( nKey==0 ); - rawKey = memchr(zKey, '\\', nKey)==0; - }else{ - zKey = zPath; - for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} - nKey = i; - if( nKey==0 ){ - return JSON_LOOKUP_PATHERROR; - } - } - if( (x & 0x0f)!=JSONB_OBJECT ) return JSON_LOOKUP_NOTFOUND; - n = jsonbPayloadSize(pParse, iRoot, &sz); - j = iRoot + n; /* j is the index of a label */ - iEnd = j+sz; - while( jaBlob[j] & 0x0f; - if( xJSONB_TEXTRAW ) return JSON_LOOKUP_ERROR; - n = jsonbPayloadSize(pParse, j, &sz); - if( n==0 ) return JSON_LOOKUP_ERROR; - k = j+n; /* k is the index of the label text */ - if( k+sz>=iEnd ) return JSON_LOOKUP_ERROR; - zLabel = (const char*)&pParse->aBlob[k]; - rawLabel = x==JSONB_TEXT || x==JSONB_TEXTRAW; - if( jsonLabelCompare(zKey, nKey, rawKey, zLabel, sz, rawLabel) ){ - u32 v = k+sz; /* v is the index of the value */ - if( ((pParse->aBlob[v])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR; - n = jsonbPayloadSize(pParse, v, &sz); - if( n==0 || v+n+sz>iEnd ) return JSON_LOOKUP_ERROR; - assert( j>0 ); - rc = jsonLookupStep(pParse, v, &zPath[i], j); - if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); - return rc; - } - j = k+sz; - if( ((pParse->aBlob[j])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR; - n = jsonbPayloadSize(pParse, j, &sz); - if( n==0 ) return JSON_LOOKUP_ERROR; - j += n+sz; - } - if( j>iEnd ) return JSON_LOOKUP_ERROR; - if( pParse->eEdit>=JEDIT_INS ){ - u32 nIns; /* Total bytes to insert (label+value) */ - JsonParse v; /* BLOB encoding of the value to be inserted */ - JsonParse ix; /* Header of the label to be inserted */ - testcase( pParse->eEdit==JEDIT_INS ); - testcase( pParse->eEdit==JEDIT_SET ); - memset(&ix, 0, sizeof(ix)); - ix.db = pParse->db; - jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0); - pParse->oom |= ix.oom; - rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]); - if( !JSON_LOOKUP_ISERROR(rc) - && jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob) - ){ - assert( !pParse->oom ); - nIns = ix.nBlob + nKey + v.nBlob; - jsonBlobEdit(pParse, j, 0, 0, nIns); - if( !pParse->oom ){ - assert( pParse->aBlob!=0 ); /* Because pParse->oom!=0 */ - assert( ix.aBlob!=0 ); /* Because pPasre->oom!=0 */ - memcpy(&pParse->aBlob[j], ix.aBlob, ix.nBlob); - k = j + ix.nBlob; - memcpy(&pParse->aBlob[k], zKey, nKey); - k += nKey; - memcpy(&pParse->aBlob[k], v.aBlob, v.nBlob); - if( ALWAYS(pParse->delta) ) jsonAfterEditSizeAdjust(pParse, iRoot); - } - } - jsonParseReset(&v); - jsonParseReset(&ix); - return rc; - } - }else if( zPath[0]=='[' ){ - x = pParse->aBlob[iRoot] & 0x0f; - if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND; - n = jsonbPayloadSize(pParse, iRoot, &sz); - k = 0; - i = 1; - while( sqlite3Isdigit(zPath[i]) ){ - k = k*10 + zPath[i] - '0'; - i++; - } - if( i<2 || zPath[i]!=']' ){ - if( zPath[1]=='#' ){ - k = jsonbArrayCount(pParse, iRoot); - i = 2; - if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ - unsigned int nn = 0; - i = 3; - do{ - nn = nn*10 + zPath[i] - '0'; - i++; - }while( sqlite3Isdigit(zPath[i]) ); - if( nn>k ) return JSON_LOOKUP_NOTFOUND; - k -= nn; - } - if( zPath[i]!=']' ){ - return JSON_LOOKUP_PATHERROR; - } - }else{ - return JSON_LOOKUP_PATHERROR; - } - } - j = iRoot+n; - iEnd = j+sz; - while( jdelta ) jsonAfterEditSizeAdjust(pParse, iRoot); - return rc; - } - k--; - n = jsonbPayloadSize(pParse, j, &sz); - if( n==0 ) return JSON_LOOKUP_ERROR; - j += n+sz; - } - if( j>iEnd ) return JSON_LOOKUP_ERROR; - if( k>0 ) return JSON_LOOKUP_NOTFOUND; - if( pParse->eEdit>=JEDIT_INS ){ - JsonParse v; - testcase( pParse->eEdit==JEDIT_INS ); - testcase( pParse->eEdit==JEDIT_SET ); - rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]); - if( !JSON_LOOKUP_ISERROR(rc) - && jsonBlobMakeEditable(pParse, v.nBlob) - ){ - assert( !pParse->oom ); - jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob); - } - jsonParseReset(&v); - if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); - return rc; - } - }else{ - return JSON_LOOKUP_PATHERROR; - } - return JSON_LOOKUP_NOTFOUND; -} - -/* -** Convert a JSON BLOB into text and make that text the return value -** of an SQL function. -*/ -static void jsonReturnTextJsonFromBlob( - sqlite3_context *ctx, - const u8 *aBlob, - u32 nBlob -){ - JsonParse x; - JsonString s; - - if( NEVER(aBlob==0) ) return; - memset(&x, 0, sizeof(x)); - x.aBlob = (u8*)aBlob; - x.nBlob = nBlob; - jsonStringInit(&s, ctx); - jsonTranslateBlobToText(&x, 0, &s); - jsonReturnString(&s, 0, 0); -} - - -/* -** Return the value of the BLOB node at index i. -** -** If the value is a primitive, return it as an SQL value. -** If the value is an array or object, return it as either -** JSON text or the BLOB encoding, depending on the JSON_B flag -** on the userdata. -*/ -static void jsonReturnFromBlob( - JsonParse *pParse, /* Complete JSON parse tree */ - u32 i, /* Index of the node */ - sqlite3_context *pCtx, /* Return value for this function */ - int textOnly /* return text JSON. Disregard user-data */ -){ - u32 n, sz; - int rc; - sqlite3 *db = sqlite3_context_db_handle(pCtx); - - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ){ - sqlite3_result_error(pCtx, "malformed JSON", -1); - return; - } - switch( pParse->aBlob[i] & 0x0f ){ - case JSONB_NULL: { - if( sz ) goto returnfromblob_malformed; - sqlite3_result_null(pCtx); - break; - } - case JSONB_TRUE: { - if( sz ) goto returnfromblob_malformed; - sqlite3_result_int(pCtx, 1); - break; - } - case JSONB_FALSE: { - if( sz ) goto returnfromblob_malformed; - sqlite3_result_int(pCtx, 0); - break; - } - case JSONB_INT5: - case JSONB_INT: { - sqlite3_int64 iRes = 0; - char *z; - int bNeg = 0; - char x; - if( sz==0 ) goto returnfromblob_malformed; - x = (char)pParse->aBlob[i+n]; - if( x=='-' ){ - if( sz<2 ) goto returnfromblob_malformed; - n++; - sz--; - bNeg = 1; - } - z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); - if( z==0 ) goto returnfromblob_oom; - rc = sqlite3DecOrHexToI64(z, &iRes); - sqlite3DbFree(db, z); - if( rc==0 ){ - sqlite3_result_int64(pCtx, bNeg ? -iRes : iRes); - }else if( rc==3 && bNeg ){ - sqlite3_result_int64(pCtx, SMALLEST_INT64); - }else if( rc==1 ){ - goto returnfromblob_malformed; - }else{ - if( bNeg ){ n--; sz++; } - goto to_double; - } - break; - } - case JSONB_FLOAT5: - case JSONB_FLOAT: { - double r; - char *z; - if( sz==0 ) goto returnfromblob_malformed; - to_double: - z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); - if( z==0 ) goto returnfromblob_oom; - rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); - sqlite3DbFree(db, z); - if( rc<=0 ) goto returnfromblob_malformed; - sqlite3_result_double(pCtx, r); - break; - } - case JSONB_TEXTRAW: - case JSONB_TEXT: { - sqlite3_result_text(pCtx, (char*)&pParse->aBlob[i+n], sz, - SQLITE_TRANSIENT); - break; - } - case JSONB_TEXT5: - case JSONB_TEXTJ: { - /* Translate JSON formatted string into raw text */ - u32 iIn, iOut; - const char *z; - char *zOut; - u32 nOut = sz; - z = (const char*)&pParse->aBlob[i+n]; - zOut = sqlite3DbMallocRaw(db, nOut+1); - if( zOut==0 ) goto returnfromblob_oom; - for(iIn=iOut=0; iIn=2 ); - zOut[iOut++] = (char)(0xc0 | (v>>6)); - zOut[iOut++] = 0x80 | (v&0x3f); - }else if( v<0x10000 ){ - assert( szEscape>=3 ); - zOut[iOut++] = 0xe0 | (v>>12); - zOut[iOut++] = 0x80 | ((v>>6)&0x3f); - zOut[iOut++] = 0x80 | (v&0x3f); - }else if( v==JSON_INVALID_CHAR ){ - /* Silently ignore illegal unicode */ - }else{ - assert( szEscape>=4 ); - zOut[iOut++] = 0xf0 | (v>>18); - zOut[iOut++] = 0x80 | ((v>>12)&0x3f); - zOut[iOut++] = 0x80 | ((v>>6)&0x3f); - zOut[iOut++] = 0x80 | (v&0x3f); - } - iIn += szEscape - 1; - }else{ - zOut[iOut++] = c; - } - } /* end for() */ - assert( iOut<=nOut ); - zOut[iOut] = 0; - sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC); - break; - } - case JSONB_ARRAY: - case JSONB_OBJECT: { - int flags = textOnly ? 0 : SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx)); - if( flags & JSON_BLOB ){ - sqlite3_result_blob(pCtx, &pParse->aBlob[i], sz+n, SQLITE_TRANSIENT); - }else{ - jsonReturnTextJsonFromBlob(pCtx, &pParse->aBlob[i], sz+n); - } - break; - } - default: { - goto returnfromblob_malformed; - } - } - return; - -returnfromblob_oom: - sqlite3_result_error_nomem(pCtx); - return; - -returnfromblob_malformed: - sqlite3_result_error(pCtx, "malformed JSON", -1); - return; -} - -/* -** pArg is a function argument that might be an SQL value or a JSON -** value. Figure out what it is and encode it as a JSONB blob. -** Return the results in pParse. -** -** pParse is uninitialized upon entry. This routine will handle the -** initialization of pParse. The result will be contained in -** pParse->aBlob and pParse->nBlob. pParse->aBlob might be dynamically -** allocated (if pParse->nBlobAlloc is greater than zero) in which case -** the caller is responsible for freeing the space allocated to pParse->aBlob -** when it has finished with it. Or pParse->aBlob might be a static string -** or a value obtained from sqlite3_value_blob(pArg). -** -** If the argument is a BLOB that is clearly not a JSONB, then this -** function might set an error message in ctx and return non-zero. -** It might also set an error message and return non-zero on an OOM error. -*/ -static int jsonFunctionArgToBlob( - sqlite3_context *ctx, - sqlite3_value *pArg, - JsonParse *pParse -){ - int eType = sqlite3_value_type(pArg); - static u8 aNull[] = { 0x00 }; - memset(pParse, 0, sizeof(pParse[0])); - pParse->db = sqlite3_context_db_handle(ctx); - switch( eType ){ - default: { - pParse->aBlob = aNull; - pParse->nBlob = 1; - return 0; - } - case SQLITE_BLOB: { - if( jsonFuncArgMightBeBinary(pArg) ){ - pParse->aBlob = (u8*)sqlite3_value_blob(pArg); - pParse->nBlob = sqlite3_value_bytes(pArg); - }else{ - sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1); - return 1; - } - break; - } - case SQLITE_TEXT: { - const char *zJson = (const char*)sqlite3_value_text(pArg); - int nJson = sqlite3_value_bytes(pArg); - if( zJson==0 ) return 1; - if( sqlite3_value_subtype(pArg)==JSON_SUBTYPE ){ - pParse->zJson = (char*)zJson; - pParse->nJson = nJson; - if( jsonConvertTextToBlob(pParse, ctx) ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - sqlite3DbFree(pParse->db, pParse->aBlob); - memset(pParse, 0, sizeof(pParse[0])); - return 1; - } - }else{ - jsonBlobAppendNode(pParse, JSONB_TEXTRAW, nJson, zJson); - } - break; - } - case SQLITE_FLOAT: { - double r = sqlite3_value_double(pArg); - if( NEVER(sqlite3IsNaN(r)) ){ - jsonBlobAppendNode(pParse, JSONB_NULL, 0, 0); - }else{ - int n = sqlite3_value_bytes(pArg); - const char *z = (const char*)sqlite3_value_text(pArg); - if( z==0 ) return 1; - if( z[0]=='I' ){ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999"); - }else if( z[0]=='-' && z[1]=='I' ){ - jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999"); - }else{ - jsonBlobAppendNode(pParse, JSONB_FLOAT, n, z); - } - } - break; - } - case SQLITE_INTEGER: { - int n = sqlite3_value_bytes(pArg); - const char *z = (const char*)sqlite3_value_text(pArg); - if( z==0 ) return 1; - jsonBlobAppendNode(pParse, JSONB_INT, n, z); - break; - } - } - if( pParse->oom ){ - sqlite3_result_error_nomem(ctx); - return 1; - }else{ - return 0; - } -} - -/* -** Generate a bad path error. -** -** If ctx is not NULL then push the error message into ctx and return NULL. -** If ctx is NULL, then return the text of the error message. -*/ -static char *jsonBadPathError( - sqlite3_context *ctx, /* The function call containing the error */ - const char *zPath /* The path with the problem */ -){ - char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); - if( ctx==0 ) return zMsg; - if( zMsg ){ - sqlite3_result_error(ctx, zMsg, -1); - sqlite3_free(zMsg); - }else{ - sqlite3_result_error_nomem(ctx); - } - return 0; -} - -/* argv[0] is a BLOB that seems likely to be a JSONB. Subsequent -** arguments come in parse where each pair contains a JSON path and -** content to insert or set at that patch. Do the updates -** and return the result. -** -** The specific operation is determined by eEdit, which can be one -** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET. -*/ -static void jsonInsertIntoBlob( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv, - int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */ -){ - int i; - u32 rc = 0; - const char *zPath = 0; - int flgs; - JsonParse *p; - JsonParse ax; - - assert( (argc&1)==1 ); - flgs = argc==1 ? 0 : JSON_EDITABLE; - p = jsonParseFuncArg(ctx, argv[0], flgs); - if( p==0 ) return; - for(i=1; inBlob, ax.aBlob, ax.nBlob); - } - rc = 0; - }else{ - p->eEdit = eEdit; - p->nIns = ax.nBlob; - p->aIns = ax.aBlob; - p->delta = 0; - rc = jsonLookupStep(p, 0, zPath+1, 0); - } - jsonParseReset(&ax); - if( rc==JSON_LOOKUP_NOTFOUND ) continue; - if( JSON_LOOKUP_ISERROR(rc) ) goto jsonInsertIntoBlob_patherror; - } - jsonReturnParse(ctx, p); - jsonParseFree(p); - return; - -jsonInsertIntoBlob_patherror: - jsonParseFree(p); - if( rc==JSON_LOOKUP_ERROR ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - }else{ - jsonBadPathError(ctx, zPath); - } - return; -} - -/* -** If pArg is a blob that seems like a JSONB blob, then initialize -** p to point to that JSONB and return TRUE. If pArg does not seem like -** a JSONB blob, then return FALSE; -** -** This routine is only called if it is already known that pArg is a -** blob. The only open question is whether or not the blob appears -** to be a JSONB blob. -*/ -static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){ - u32 n, sz = 0; - p->aBlob = (u8*)sqlite3_value_blob(pArg); - p->nBlob = (u32)sqlite3_value_bytes(pArg); - if( p->nBlob==0 ){ - p->aBlob = 0; - return 0; - } - if( NEVER(p->aBlob==0) ){ - return 0; - } - if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT - && (n = jsonbPayloadSize(p, 0, &sz))>0 - && sz+n==p->nBlob - && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0) - ){ - return 1; - } - p->aBlob = 0; - p->nBlob = 0; - return 0; -} - -/* -** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob, -** from the SQL function argument pArg. Return a pointer to the new -** JsonParse object. -** -** Ownership of the new JsonParse object is passed to the caller. The -** caller should invoke jsonParseFree() on the return value when it -** has finished using it. -** -** If any errors are detected, an appropriate error messages is set -** using sqlite3_result_error() or the equivalent and this routine -** returns NULL. This routine also returns NULL if the pArg argument -** is an SQL NULL value, but no error message is set in that case. This -** is so that SQL functions that are given NULL arguments will return -** a NULL value. -*/ -static JsonParse *jsonParseFuncArg( - sqlite3_context *ctx, - sqlite3_value *pArg, - u32 flgs -){ - int eType; /* Datatype of pArg */ - JsonParse *p = 0; /* Value to be returned */ - JsonParse *pFromCache = 0; /* Value taken from cache */ - sqlite3 *db; /* The database connection */ - - assert( ctx!=0 ); - eType = sqlite3_value_type(pArg); - if( eType==SQLITE_NULL ){ - return 0; - } - pFromCache = jsonCacheSearch(ctx, pArg); - if( pFromCache ){ - pFromCache->nJPRef++; - if( (flgs & JSON_EDITABLE)==0 ){ - return pFromCache; - } - } - db = sqlite3_context_db_handle(ctx); -rebuild_from_cache: - p = sqlite3DbMallocZero(db, sizeof(*p)); - if( p==0 ) goto json_pfa_oom; - memset(p, 0, sizeof(*p)); - p->db = db; - p->nJPRef = 1; - if( pFromCache!=0 ){ - u32 nBlob = pFromCache->nBlob; - p->aBlob = sqlite3DbMallocRaw(db, nBlob); - if( p->aBlob==0 ) goto json_pfa_oom; - memcpy(p->aBlob, pFromCache->aBlob, nBlob); - p->nBlobAlloc = p->nBlob = nBlob; - p->hasNonstd = pFromCache->hasNonstd; - jsonParseFree(pFromCache); - return p; - } - if( eType==SQLITE_BLOB ){ - if( jsonArgIsJsonb(pArg,p) ){ - if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){ - goto json_pfa_oom; - } - return p; - } - /* If the blob is not valid JSONB, fall through into trying to cast - ** the blob into text which is then interpreted as JSON. (tag-20240123-a) - ** - ** This goes against all historical documentation about how the SQLite - ** JSON functions were suppose to work. From the beginning, blob was - ** reserved for expansion and a blob value should have raised an error. - ** But it did not, due to a bug. And many applications came to depend - ** upon this buggy behavior, espeically when using the CLI and reading - ** JSON text using readfile(), which returns a blob. For this reason - ** we will continue to support the bug moving forward. - ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d - */ - } - p->zJson = (char*)sqlite3_value_text(pArg); - p->nJson = sqlite3_value_bytes(pArg); - if( db->mallocFailed ) goto json_pfa_oom; - if( p->nJson==0 ) goto json_pfa_malformed; - assert( p->zJson!=0 ); - if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){ - if( flgs & JSON_KEEPERROR ){ - p->nErr = 1; - return p; - }else{ - jsonParseFree(p); - return 0; - } - }else{ - int isRCStr = sqlite3ValueIsOfClass(pArg, sqlite3RCStrUnref); - int rc; - if( !isRCStr ){ - char *zNew = sqlite3RCStrNew( p->nJson ); - if( zNew==0 ) goto json_pfa_oom; - memcpy(zNew, p->zJson, p->nJson); - p->zJson = zNew; - p->zJson[p->nJson] = 0; - }else{ - sqlite3RCStrRef(p->zJson); - } - p->bJsonIsRCStr = 1; - rc = jsonCacheInsert(ctx, p); - if( rc==SQLITE_NOMEM ) goto json_pfa_oom; - if( flgs & JSON_EDITABLE ){ - pFromCache = p; - p = 0; - goto rebuild_from_cache; - } - } - return p; - -json_pfa_malformed: - if( flgs & JSON_KEEPERROR ){ - p->nErr = 1; - return p; - }else{ - jsonParseFree(p); - sqlite3_result_error(ctx, "malformed JSON", -1); - return 0; - } - -json_pfa_oom: - jsonParseFree(pFromCache); - jsonParseFree(p); - sqlite3_result_error_nomem(ctx); - return 0; -} - -/* -** Make the return value of a JSON function either the raw JSONB blob -** or make it JSON text, depending on whether the JSON_BLOB flag is -** set on the function. -*/ -static void jsonReturnParse( - sqlite3_context *ctx, - JsonParse *p -){ - int flgs; - if( p->oom ){ - sqlite3_result_error_nomem(ctx); - return; - } - flgs = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - if( flgs & JSON_BLOB ){ - if( p->nBlobAlloc>0 && !p->bReadOnly ){ - sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_DYNAMIC); - p->nBlobAlloc = 0; - }else{ - sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_TRANSIENT); - } - }else{ - JsonString s; - jsonStringInit(&s, ctx); - p->delta = 0; - jsonTranslateBlobToText(p, 0, &s); - jsonReturnString(&s, p, ctx); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } -} - -/**************************************************************************** -** SQL functions used for testing and debugging -****************************************************************************/ - -#if SQLITE_DEBUG -/* -** Decode JSONB bytes in aBlob[] starting at iStart through but not -** including iEnd. Indent the -** content by nIndent spaces. -*/ -static void jsonDebugPrintBlob( - JsonParse *pParse, /* JSON content */ - u32 iStart, /* Start rendering here */ - u32 iEnd, /* Do not render this byte or any byte after this one */ - int nIndent, /* Indent by this many spaces */ - sqlite3_str *pOut /* Generate output into this sqlite3_str object */ -){ - while( iStartaBlob[iStart] & 0x0f; - u32 savedNBlob = pParse->nBlob; - sqlite3_str_appendf(pOut, "%5d:%*s", iStart, nIndent, ""); - if( pParse->nBlobAlloc>pParse->nBlob ){ - pParse->nBlob = pParse->nBlobAlloc; - } - nn = n = jsonbPayloadSize(pParse, iStart, &sz); - if( nn==0 ) nn = 1; - if( sz>0 && xaBlob[iStart+i]); - } - if( n==0 ){ - sqlite3_str_appendf(pOut, " ERROR invalid node size\n"); - iStart = n==0 ? iStart+1 : iEnd; - continue; - } - pParse->nBlob = savedNBlob; - if( iStart+n+sz>iEnd ){ - iEnd = iStart+n+sz; - if( iEnd>pParse->nBlob ){ - if( pParse->nBlobAlloc>0 && iEnd>pParse->nBlobAlloc ){ - iEnd = pParse->nBlobAlloc; - }else{ - iEnd = pParse->nBlob; - } - } - } - sqlite3_str_appendall(pOut," <-- "); - switch( x ){ - case JSONB_NULL: sqlite3_str_appendall(pOut,"null"); break; - case JSONB_TRUE: sqlite3_str_appendall(pOut,"true"); break; - case JSONB_FALSE: sqlite3_str_appendall(pOut,"false"); break; - case JSONB_INT: sqlite3_str_appendall(pOut,"int"); break; - case JSONB_INT5: sqlite3_str_appendall(pOut,"int5"); break; - case JSONB_FLOAT: sqlite3_str_appendall(pOut,"float"); break; - case JSONB_FLOAT5: sqlite3_str_appendall(pOut,"float5"); break; - case JSONB_TEXT: sqlite3_str_appendall(pOut,"text"); break; - case JSONB_TEXTJ: sqlite3_str_appendall(pOut,"textj"); break; - case JSONB_TEXT5: sqlite3_str_appendall(pOut,"text5"); break; - case JSONB_TEXTRAW: sqlite3_str_appendall(pOut,"textraw"); break; - case JSONB_ARRAY: { - sqlite3_str_appendf(pOut,"array, %u bytes\n", sz); - jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); - showContent = 0; - break; - } - case JSONB_OBJECT: { - sqlite3_str_appendf(pOut, "object, %u bytes\n", sz); - jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2, pOut); - showContent = 0; - break; - } - default: { - sqlite3_str_appendall(pOut, "ERROR: unknown node type\n"); - showContent = 0; - break; - } - } - if( showContent ){ - if( sz==0 && x<=JSONB_FALSE ){ - sqlite3_str_append(pOut, "\n", 1); - }else{ - u32 j; - sqlite3_str_appendall(pOut, ": \""); - for(j=iStart+n; jaBlob[j]; - if( c<0x20 || c>=0x7f ) c = '.'; - sqlite3_str_append(pOut, (char*)&c, 1); - } - sqlite3_str_append(pOut, "\"\n", 2); - } - } - iStart += n + sz; - } -} -static void jsonShowParse(JsonParse *pParse){ - sqlite3_str out; - char zBuf[1000]; - if( pParse==0 ){ - printf("NULL pointer\n"); - return; - }else{ - printf("nBlobAlloc = %u\n", pParse->nBlobAlloc); - printf("nBlob = %u\n", pParse->nBlob); - printf("delta = %d\n", pParse->delta); - if( pParse->nBlob==0 ) return; - printf("content (bytes 0..%u):\n", pParse->nBlob-1); - } - sqlite3StrAccumInit(&out, 0, zBuf, sizeof(zBuf), 1000000); - jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0, &out); - printf("%s", sqlite3_str_value(&out)); - sqlite3_str_reset(&out); -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -** SQL function: json_parse(JSON) -** -** Parse JSON using jsonParseFuncArg(). Return text that is a -** human-readable dump of the binary JSONB for the input parameter. -*/ -static void jsonParseFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p; /* The parse */ - sqlite3_str out; - - assert( argc>=1 ); - sqlite3StrAccumInit(&out, 0, 0, 0, 1000000); - p = jsonParseFuncArg(ctx, argv[0], 0); - if( p==0 ) return; - if( argc==1 ){ - jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out); - sqlite3_result_text64(ctx,out.zText,out.nChar,SQLITE_TRANSIENT,SQLITE_UTF8); - }else{ - jsonShowParse(p); - } - jsonParseFree(p); - sqlite3_str_reset(&out); -} -#endif /* SQLITE_DEBUG */ - -/**************************************************************************** -** Scalar SQL function implementations -****************************************************************************/ - -/* -** Implementation of the json_quote(VALUE) function. Return a JSON value -** corresponding to the SQL value input. Mostly this means putting -** double-quotes around strings and returning the unquoted string "null" -** when given a NULL input. -*/ -static void jsonQuoteFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonString jx; - UNUSED_PARAMETER(argc); - - jsonStringInit(&jx, ctx); - jsonAppendSqlValue(&jx, argv[0]); - jsonReturnString(&jx, 0, 0); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); -} - -/* -** Implementation of the json_array(VALUE,...) function. Return a JSON -** array that contains all values given in arguments. Or if any argument -** is a BLOB, throw an error. -*/ -static void jsonArrayFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - int i; - JsonString jx; - - jsonStringInit(&jx, ctx); - jsonAppendChar(&jx, '['); - for(i=0; iaBlob[i] & 0x0f)==JSONB_ARRAY ){ - cnt = jsonbArrayCount(p, i); - } - if( !eErr ) sqlite3_result_int64(ctx, cnt); - jsonParseFree(p); -} - -/* True if the string is all alphanumerics and underscores */ -static int jsonAllAlphanum(const char *z, int n){ - int i; - for(i=0; i"(JSON,PATH) -** "->>"(JSON,PATH) -** -** Return the element described by PATH. Return NULL if that PATH element -** is not found. -** -** If JSON_JSON is set or if more that one PATH argument is supplied then -** always return a JSON representation of the result. If JSON_SQL is set, -** then always return an SQL representation of the result. If neither flag -** is present and argc==2, then return JSON for objects and arrays and SQL -** for all other values. -** -** When multiple PATH arguments are supplied, the result is a JSON array -** containing the result of each PATH. -** -** Abbreviated JSON path expressions are allows if JSON_ABPATH, for -** compatibility with PG. -*/ -static void jsonExtractFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p = 0; /* The parse */ - int flags; /* Flags associated with the function */ - int i; /* Loop counter */ - JsonString jx; /* String for array result */ - - if( argc<2 ) return; - p = jsonParseFuncArg(ctx, argv[0], 0); - if( p==0 ) return; - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - jsonStringInit(&jx, ctx); - if( argc>2 ){ - jsonAppendChar(&jx, '['); - } - for(i=1; i and ->> operators accept abbreviated PATH arguments. This - ** is mostly for compatibility with PostgreSQL, but also for - ** convenience. - ** - ** NUMBER ==> $[NUMBER] // PG compatible - ** LABEL ==> $.LABEL // PG compatible - ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience - ** - ** Updated 2024-05-27: If the NUMBER is negative, then PG counts from - ** the right of the array. Hence for negative NUMBER: - ** - ** NUMBER ==> $[#NUMBER] // PG compatible - */ - jsonStringInit(&jx, ctx); - if( sqlite3_value_type(argv[i])==SQLITE_INTEGER ){ - jsonAppendRawNZ(&jx, "[", 1); - if( zPath[0]=='-' ) jsonAppendRawNZ(&jx,"#",1); - jsonAppendRaw(&jx, zPath, nPath); - jsonAppendRawNZ(&jx, "]", 2); - }else if( jsonAllAlphanum(zPath, nPath) ){ - jsonAppendRawNZ(&jx, ".", 1); - jsonAppendRaw(&jx, zPath, nPath); - }else if( zPath[0]=='[' && nPath>=3 && zPath[nPath-1]==']' ){ - jsonAppendRaw(&jx, zPath, nPath); - }else{ - jsonAppendRawNZ(&jx, ".\"", 2); - jsonAppendRaw(&jx, zPath, nPath); - jsonAppendRawNZ(&jx, "\"", 1); - } - jsonStringTerminate(&jx); - j = jsonLookupStep(p, 0, jx.zBuf, 0); - jsonStringReset(&jx); - }else{ - jsonBadPathError(ctx, zPath); - goto json_extract_error; - } - if( jnBlob ){ - if( argc==2 ){ - if( flags & JSON_JSON ){ - jsonStringInit(&jx, ctx); - jsonTranslateBlobToText(p, j, &jx); - jsonReturnString(&jx, 0, 0); - jsonStringReset(&jx); - assert( (flags & JSON_BLOB)==0 ); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - }else{ - jsonReturnFromBlob(p, j, ctx, 0); - if( (flags & (JSON_SQL|JSON_BLOB))==0 - && (p->aBlob[j]&0x0f)>=JSONB_ARRAY - ){ - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - } - }else{ - jsonAppendSeparator(&jx); - jsonTranslateBlobToText(p, j, &jx); - } - }else if( j==JSON_LOOKUP_NOTFOUND ){ - if( argc==2 ){ - goto json_extract_error; /* Return NULL if not found */ - }else{ - jsonAppendSeparator(&jx); - jsonAppendRawNZ(&jx, "null", 4); - } - }else if( j==JSON_LOOKUP_ERROR ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - goto json_extract_error; - }else{ - jsonBadPathError(ctx, zPath); - goto json_extract_error; - } - } - if( argc>2 ){ - jsonAppendChar(&jx, ']'); - jsonReturnString(&jx, 0, 0); - if( (flags & JSON_BLOB)==0 ){ - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - } -json_extract_error: - jsonStringReset(&jx); - jsonParseFree(p); - return; -} - -/* -** Return codes for jsonMergePatch() -*/ -#define JSON_MERGE_OK 0 /* Success */ -#define JSON_MERGE_BADTARGET 1 /* Malformed TARGET blob */ -#define JSON_MERGE_BADPATCH 2 /* Malformed PATCH blob */ -#define JSON_MERGE_OOM 3 /* Out-of-memory condition */ - -/* -** RFC-7396 MergePatch for two JSONB blobs. -** -** pTarget is the target. pPatch is the patch. The target is updated -** in place. The patch is read-only. -** -** The original RFC-7396 algorithm is this: -** -** define MergePatch(Target, Patch): -** if Patch is an Object: -** if Target is not an Object: -** Target = {} # Ignore the contents and set it to an empty Object -** for each Name/Value pair in Patch: -** if Value is null: -** if Name exists in Target: -** remove the Name/Value pair from Target -** else: -** Target[Name] = MergePatch(Target[Name], Value) -** return Target -** else: -** return Patch -** -** Here is an equivalent algorithm restructured to show the actual -** implementation: -** -** 01 define MergePatch(Target, Patch): -** 02 if Patch is not an Object: -** 03 return Patch -** 04 else: // if Patch is an Object -** 05 if Target is not an Object: -** 06 Target = {} -** 07 for each Name/Value pair in Patch: -** 08 if Name exists in Target: -** 09 if Value is null: -** 10 remove the Name/Value pair from Target -** 11 else -** 12 Target[name] = MergePatch(Target[Name], Value) -** 13 else if Value is not NULL: -** 14 if Value is not an Object: -** 15 Target[name] = Value -** 16 else: -** 17 Target[name] = MergePatch('{}',value) -** 18 return Target -** | -** ^---- Line numbers referenced in comments in the implementation -*/ -static int jsonMergePatch( - JsonParse *pTarget, /* The JSON parser that contains the TARGET */ - u32 iTarget, /* Index of TARGET in pTarget->aBlob[] */ - const JsonParse *pPatch, /* The PATCH */ - u32 iPatch /* Index of PATCH in pPatch->aBlob[] */ -){ - u8 x; /* Type of a single node */ - u32 n, sz=0; /* Return values from jsonbPayloadSize() */ - u32 iTCursor; /* Cursor position while scanning the target object */ - u32 iTStart; /* First label in the target object */ - u32 iTEndBE; /* Original first byte past end of target, before edit */ - u32 iTEnd; /* Current first byte past end of target */ - u8 eTLabel; /* Node type of the target label */ - u32 iTLabel = 0; /* Index of the label */ - u32 nTLabel = 0; /* Header size in bytes for the target label */ - u32 szTLabel = 0; /* Size of the target label payload */ - u32 iTValue = 0; /* Index of the target value */ - u32 nTValue = 0; /* Header size of the target value */ - u32 szTValue = 0; /* Payload size for the target value */ - - u32 iPCursor; /* Cursor position while scanning the patch */ - u32 iPEnd; /* First byte past the end of the patch */ - u8 ePLabel; /* Node type of the patch label */ - u32 iPLabel; /* Start of patch label */ - u32 nPLabel; /* Size of header on the patch label */ - u32 szPLabel; /* Payload size of the patch label */ - u32 iPValue; /* Start of patch value */ - u32 nPValue; /* Header size for the patch value */ - u32 szPValue; /* Payload size of the patch value */ - - assert( iTarget>=0 && iTargetnBlob ); - assert( iPatch>=0 && iPatchnBlob ); - x = pPatch->aBlob[iPatch] & 0x0f; - if( x!=JSONB_OBJECT ){ /* Algorithm line 02 */ - u32 szPatch; /* Total size of the patch, header+payload */ - u32 szTarget; /* Total size of the target, header+payload */ - n = jsonbPayloadSize(pPatch, iPatch, &sz); - szPatch = n+sz; - sz = 0; - n = jsonbPayloadSize(pTarget, iTarget, &sz); - szTarget = n+sz; - jsonBlobEdit(pTarget, iTarget, szTarget, pPatch->aBlob+iPatch, szPatch); - return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; /* Line 03 */ - } - x = pTarget->aBlob[iTarget] & 0x0f; - if( x!=JSONB_OBJECT ){ /* Algorithm line 05 */ - n = jsonbPayloadSize(pTarget, iTarget, &sz); - jsonBlobEdit(pTarget, iTarget+n, sz, 0, 0); - x = pTarget->aBlob[iTarget]; - pTarget->aBlob[iTarget] = (x & 0xf0) | JSONB_OBJECT; - } - n = jsonbPayloadSize(pPatch, iPatch, &sz); - if( NEVER(n==0) ) return JSON_MERGE_BADPATCH; - iPCursor = iPatch+n; - iPEnd = iPCursor+sz; - n = jsonbPayloadSize(pTarget, iTarget, &sz); - if( NEVER(n==0) ) return JSON_MERGE_BADTARGET; - iTStart = iTarget+n; - iTEndBE = iTStart+sz; - - while( iPCursoraBlob[iPCursor] & 0x0f; - if( ePLabelJSONB_TEXTRAW ){ - return JSON_MERGE_BADPATCH; - } - nPLabel = jsonbPayloadSize(pPatch, iPCursor, &szPLabel); - if( nPLabel==0 ) return JSON_MERGE_BADPATCH; - iPValue = iPCursor + nPLabel + szPLabel; - if( iPValue>=iPEnd ) return JSON_MERGE_BADPATCH; - nPValue = jsonbPayloadSize(pPatch, iPValue, &szPValue); - if( nPValue==0 ) return JSON_MERGE_BADPATCH; - iPCursor = iPValue + nPValue + szPValue; - if( iPCursor>iPEnd ) return JSON_MERGE_BADPATCH; - - iTCursor = iTStart; - iTEnd = iTEndBE + pTarget->delta; - while( iTCursoraBlob[iTCursor] & 0x0f; - if( eTLabelJSONB_TEXTRAW ){ - return JSON_MERGE_BADTARGET; - } - nTLabel = jsonbPayloadSize(pTarget, iTCursor, &szTLabel); - if( nTLabel==0 ) return JSON_MERGE_BADTARGET; - iTValue = iTLabel + nTLabel + szTLabel; - if( iTValue>=iTEnd ) return JSON_MERGE_BADTARGET; - nTValue = jsonbPayloadSize(pTarget, iTValue, &szTValue); - if( nTValue==0 ) return JSON_MERGE_BADTARGET; - if( iTValue + nTValue + szTValue > iTEnd ) return JSON_MERGE_BADTARGET; - isEqual = jsonLabelCompare( - (const char*)&pPatch->aBlob[iPLabel+nPLabel], - szPLabel, - (ePLabel==JSONB_TEXT || ePLabel==JSONB_TEXTRAW), - (const char*)&pTarget->aBlob[iTLabel+nTLabel], - szTLabel, - (eTLabel==JSONB_TEXT || eTLabel==JSONB_TEXTRAW)); - if( isEqual ) break; - iTCursor = iTValue + nTValue + szTValue; - } - x = pPatch->aBlob[iPValue] & 0x0f; - if( iTCursoroom) ) return JSON_MERGE_OOM; - }else{ - /* Algorithm line 12 */ - int rc, savedDelta = pTarget->delta; - pTarget->delta = 0; - rc = jsonMergePatch(pTarget, iTValue, pPatch, iPValue); - if( rc ) return rc; - pTarget->delta += savedDelta; - } - }else if( x>0 ){ /* Algorithm line 13 */ - /* No match and patch value is not NULL */ - u32 szNew = szPLabel+nPLabel; - if( (pPatch->aBlob[iPValue] & 0x0f)!=JSONB_OBJECT ){ /* Line 14 */ - jsonBlobEdit(pTarget, iTEnd, 0, 0, szPValue+nPValue+szNew); - if( pTarget->oom ) return JSON_MERGE_OOM; - memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew); - memcpy(&pTarget->aBlob[iTEnd+szNew], - &pPatch->aBlob[iPValue], szPValue+nPValue); - }else{ - int rc, savedDelta; - jsonBlobEdit(pTarget, iTEnd, 0, 0, szNew+1); - if( pTarget->oom ) return JSON_MERGE_OOM; - memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew); - pTarget->aBlob[iTEnd+szNew] = 0x00; - savedDelta = pTarget->delta; - pTarget->delta = 0; - rc = jsonMergePatch(pTarget, iTEnd+szNew,pPatch,iPValue); - if( rc ) return rc; - pTarget->delta += savedDelta; - } - } - } - if( pTarget->delta ) jsonAfterEditSizeAdjust(pTarget, iTarget); - return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; -} - - -/* -** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON -** object that is the result of running the RFC 7396 MergePatch() algorithm -** on the two arguments. -*/ -static void jsonPatchFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *pTarget; /* The TARGET */ - JsonParse *pPatch; /* The PATCH */ - int rc; /* Result code */ - - UNUSED_PARAMETER(argc); - assert( argc==2 ); - pTarget = jsonParseFuncArg(ctx, argv[0], JSON_EDITABLE); - if( pTarget==0 ) return; - pPatch = jsonParseFuncArg(ctx, argv[1], 0); - if( pPatch ){ - rc = jsonMergePatch(pTarget, 0, pPatch, 0); - if( rc==JSON_MERGE_OK ){ - jsonReturnParse(ctx, pTarget); - }else if( rc==JSON_MERGE_OOM ){ - sqlite3_result_error_nomem(ctx); - }else{ - sqlite3_result_error(ctx, "malformed JSON", -1); - } - jsonParseFree(pPatch); - } - jsonParseFree(pTarget); -} - - -/* -** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON -** object that contains all name/value given in arguments. Or if any name -** is not a string or if any value is a BLOB, throw an error. -*/ -static void jsonObjectFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - int i; - JsonString jx; - const char *z; - u32 n; - - if( argc&1 ){ - sqlite3_result_error(ctx, "json_object() requires an even number " - "of arguments", -1); - return; - } - jsonStringInit(&jx, ctx); - jsonAppendChar(&jx, '{'); - for(i=0; i1 ? JSON_EDITABLE : 0); - if( p==0 ) return; - for(i=1; ieEdit = JEDIT_DEL; - p->delta = 0; - rc = jsonLookupStep(p, 0, zPath+1, 0); - if( JSON_LOOKUP_ISERROR(rc) ){ - if( rc==JSON_LOOKUP_NOTFOUND ){ - continue; /* No-op */ - }else if( rc==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath); - }else{ - sqlite3_result_error(ctx, "malformed JSON", -1); - } - goto json_remove_done; - } - } - jsonReturnParse(ctx, p); - jsonParseFree(p); - return; - -json_remove_patherror: - jsonBadPathError(ctx, zPath); - -json_remove_done: - jsonParseFree(p); - return; -} - -/* -** json_replace(JSON, PATH, VALUE, ...) -** -** Replace the value at PATH with VALUE. If PATH does not already exist, -** this routine is a no-op. If JSON or PATH is malformed, throw an error. -*/ -static void jsonReplaceFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - if( argc<1 ) return; - if( (argc&1)==0 ) { - jsonWrongNumArgs(ctx, "replace"); - return; - } - jsonInsertIntoBlob(ctx, argc, argv, JEDIT_REPL); -} - - -/* -** json_set(JSON, PATH, VALUE, ...) -** -** Set the value at PATH to VALUE. Create the PATH if it does not already -** exist. Overwrite existing values that do exist. -** If JSON or PATH is malformed, throw an error. -** -** json_insert(JSON, PATH, VALUE, ...) -** -** Create PATH and initialize it to VALUE. If PATH already exists, this -** routine is a no-op. If JSON or PATH is malformed, throw an error. -*/ -static void jsonSetFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - int bIsSet = (flags&JSON_ISSET)!=0; - - if( argc<1 ) return; - if( (argc&1)==0 ) { - jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); - return; - } - jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS); -} - -/* -** json_type(JSON) -** json_type(JSON, PATH) -** -** Return the top-level "type" of a JSON string. json_type() raises an -** error if either the JSON or PATH inputs are not well-formed. -*/ -static void jsonTypeFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p; /* The parse */ - const char *zPath = 0; - u32 i; - - p = jsonParseFuncArg(ctx, argv[0], 0); - if( p==0 ) return; - if( argc==2 ){ - zPath = (const char*)sqlite3_value_text(argv[1]); - if( zPath==0 ) goto json_type_done; - if( zPath[0]!='$' ){ - jsonBadPathError(ctx, zPath); - goto json_type_done; - } - i = jsonLookupStep(p, 0, zPath+1, 0); - if( JSON_LOOKUP_ISERROR(i) ){ - if( i==JSON_LOOKUP_NOTFOUND ){ - /* no-op */ - }else if( i==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath); - }else{ - sqlite3_result_error(ctx, "malformed JSON", -1); - } - goto json_type_done; - } - }else{ - i = 0; - } - sqlite3_result_text(ctx, jsonbType[p->aBlob[i]&0x0f], -1, SQLITE_STATIC); -json_type_done: - jsonParseFree(p); -} - -/* -** json_pretty(JSON) -** json_pretty(JSON, INDENT) -** -** Return text that is a pretty-printed rendering of the input JSON. -** If the argument is not valid JSON, return NULL. -** -** The INDENT argument is text that is used for indentation. If omitted, -** it defaults to four spaces (the same as PostgreSQL). -*/ -static void jsonPrettyFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonString s; /* The output string */ - JsonPretty x; /* Pretty printing context */ - - memset(&x, 0, sizeof(x)); - x.pParse = jsonParseFuncArg(ctx, argv[0], 0); - if( x.pParse==0 ) return; - x.pOut = &s; - jsonStringInit(&s, ctx); - if( argc==1 || (x.zIndent = (const char*)sqlite3_value_text(argv[1]))==0 ){ - x.zIndent = " "; - x.szIndent = 4; - }else{ - x.szIndent = (u32)strlen(x.zIndent); - } - jsonTranslateBlobToPrettyText(&x, 0); - jsonReturnString(&s, 0, 0); - jsonParseFree(x.pParse); -} - -/* -** json_valid(JSON) -** json_valid(JSON, FLAGS) -** -** Check the JSON argument to see if it is well-formed. The FLAGS argument -** encodes the various constraints on what is meant by "well-formed": -** -** 0x01 Canonical RFC-8259 JSON text -** 0x02 JSON text with optional JSON-5 extensions -** 0x04 Superficially appears to be JSONB -** 0x08 Strictly well-formed JSONB -** -** If the FLAGS argument is omitted, it defaults to 1. Useful values for -** FLAGS include: -** -** 1 Strict canonical JSON text -** 2 JSON text perhaps with JSON-5 extensions -** 4 Superficially appears to be JSONB -** 5 Canonical JSON text or superficial JSONB -** 6 JSON-5 text or superficial JSONB -** 8 Strict JSONB -** 9 Canonical JSON text or strict JSONB -** 10 JSON-5 text or strict JSONB -** -** Other flag combinations are redundant. For example, every canonical -** JSON text is also well-formed JSON-5 text, so FLAG values 2 and 3 -** are the same. Similarly, any input that passes a strict JSONB validation -** will also pass the superficial validation so 12 through 15 are the same -** as 8 through 11 respectively. -** -** This routine runs in linear time to validate text and when doing strict -** JSONB validation. Superficial JSONB validation is constant time, -** assuming the BLOB is already in memory. The performance advantage -** of superficial JSONB validation is why that option is provided. -** Application developers can choose to do fast superficial validation or -** slower strict validation, according to their specific needs. -** -** Only the lower four bits of the FLAGS argument are currently used. -** Higher bits are reserved for future expansion. To facilitate -** compatibility, the current implementation raises an error if any bit -** in FLAGS is set other than the lower four bits. -** -** The original circa 2015 implementation of the JSON routines in -** SQLite only supported canonical RFC-8259 JSON text and the json_valid() -** function only accepted one argument. That is why the default value -** for the FLAGS argument is 1, since FLAGS=1 causes this routine to only -** recognize canonical RFC-8259 JSON text as valid. The extra FLAGS -** argument was added when the JSON routines were extended to support -** JSON5-like extensions and binary JSONB stored in BLOBs. -** -** Return Values: -** -** * Raise an error if FLAGS is outside the range of 1 to 15. -** * Return NULL if the input is NULL -** * Return 1 if the input is well-formed. -** * Return 0 if the input is not well-formed. -*/ -static void jsonValidFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *p; /* The parse */ - u8 flags = 1; - u8 res = 0; - if( argc==2 ){ - i64 f = sqlite3_value_int64(argv[1]); - if( f<1 || f>15 ){ - sqlite3_result_error(ctx, "FLAGS parameter to json_valid() must be" - " between 1 and 15", -1); - return; - } - flags = f & 0x0f; - } - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_NULL: { -#ifdef SQLITE_LEGACY_JSON_VALID - /* Incorrect legacy behavior was to return FALSE for a NULL input */ - sqlite3_result_int(ctx, 0); -#endif - return; - } - case SQLITE_BLOB: { - if( jsonFuncArgMightBeBinary(argv[0]) ){ - if( flags & 0x04 ){ - /* Superficial checking only - accomplished by the - ** jsonFuncArgMightBeBinary() call above. */ - res = 1; - }else if( flags & 0x08 ){ - /* Strict checking. Check by translating BLOB->TEXT->BLOB. If - ** no errors occur, call that a "strict check". */ - JsonParse px; - u32 iErr; - memset(&px, 0, sizeof(px)); - px.aBlob = (u8*)sqlite3_value_blob(argv[0]); - px.nBlob = sqlite3_value_bytes(argv[0]); - iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1); - res = iErr==0; - } - break; - } - /* Fall through into interpreting the input as text. See note - ** above at tag-20240123-a. */ - /* no break */ deliberate_fall_through - } - default: { - JsonParse px; - if( (flags & 0x3)==0 ) break; - memset(&px, 0, sizeof(px)); - - p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR); - if( p ){ - if( p->oom ){ - sqlite3_result_error_nomem(ctx); - }else if( p->nErr ){ - /* no-op */ - }else if( (flags & 0x02)!=0 || p->hasNonstd==0 ){ - res = 1; - } - jsonParseFree(p); - }else{ - sqlite3_result_error_nomem(ctx); - } - break; - } - } - sqlite3_result_int(ctx, res); -} - -/* -** json_error_position(JSON) -** -** If the argument is NULL, return NULL -** -** If the argument is BLOB, do a full validity check and return non-zero -** if the check fails. The return value is the approximate 1-based offset -** to the byte of the element that contains the first error. -** -** Otherwise interpret the argument is TEXT (even if it is numeric) and -** return the 1-based character position for where the parser first recognized -** that the input was not valid JSON, or return 0 if the input text looks -** ok. JSON-5 extensions are accepted. -*/ -static void jsonErrorFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - i64 iErrPos = 0; /* Error position to be returned */ - JsonParse s; - - assert( argc==1 ); - UNUSED_PARAMETER(argc); - memset(&s, 0, sizeof(s)); - s.db = sqlite3_context_db_handle(ctx); - if( jsonFuncArgMightBeBinary(argv[0]) ){ - s.aBlob = (u8*)sqlite3_value_blob(argv[0]); - s.nBlob = sqlite3_value_bytes(argv[0]); - iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1); - }else{ - s.zJson = (char*)sqlite3_value_text(argv[0]); - if( s.zJson==0 ) return; /* NULL input or OOM */ - s.nJson = sqlite3_value_bytes(argv[0]); - if( jsonConvertTextToBlob(&s,0) ){ - if( s.oom ){ - iErrPos = -1; - }else{ - /* Convert byte-offset s.iErr into a character offset */ - u32 k; - assert( s.zJson!=0 ); /* Because s.oom is false */ - for(k=0; kzBuf==0 ){ - jsonStringInit(pStr, ctx); - jsonAppendChar(pStr, '['); - }else if( pStr->nUsed>1 ){ - jsonAppendChar(pStr, ','); - } - pStr->pCtx = ctx; - jsonAppendSqlValue(pStr, argv[0]); - } -} -static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ - JsonString *pStr; - pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); - if( pStr ){ - int flags; - pStr->pCtx = ctx; - jsonAppendChar(pStr, ']'); - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - if( pStr->eErr ){ - jsonReturnString(pStr, 0, 0); - return; - }else if( flags & JSON_BLOB ){ - jsonReturnStringAsBlob(pStr); - if( isFinal ){ - if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); - }else{ - jsonStringTrimOneChar(pStr); - } - return; - }else if( isFinal ){ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : - sqlite3RCStrUnref); - pStr->bStatic = 1; - }else{ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); - jsonStringTrimOneChar(pStr); - } - }else{ - sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); - } - sqlite3_result_subtype(ctx, JSON_SUBTYPE); -} -static void jsonArrayValue(sqlite3_context *ctx){ - jsonArrayCompute(ctx, 0); -} -static void jsonArrayFinal(sqlite3_context *ctx){ - jsonArrayCompute(ctx, 1); -} - -#ifndef SQLITE_OMIT_WINDOWFUNC -/* -** This method works for both json_group_array() and json_group_object(). -** It works by removing the first element of the group by searching forward -** to the first comma (",") that is not within a string and deleting all -** text through that comma. -*/ -static void jsonGroupInverse( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - unsigned int i; - int inStr = 0; - int nNest = 0; - char *z; - char c; - JsonString *pStr; - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); -#ifdef NEVER - /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will - ** always have been called to initialize it */ - if( NEVER(!pStr) ) return; -#endif - z = pStr->zBuf; - for(i=1; inUsed && ((c = z[i])!=',' || inStr || nNest); i++){ - if( c=='"' ){ - inStr = !inStr; - }else if( c=='\\' ){ - i++; - }else if( !inStr ){ - if( c=='{' || c=='[' ) nNest++; - if( c=='}' || c==']' ) nNest--; - } - } - if( inUsed ){ - pStr->nUsed -= i; - memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); - z[pStr->nUsed] = 0; - }else{ - pStr->nUsed = 1; - } -} -#else -# define jsonGroupInverse 0 -#endif - - -/* -** json_group_obj(NAME,VALUE) -** -** Return a JSON object composed of all names and values in the aggregate. -*/ -static void jsonObjectStep( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonString *pStr; - const char *z; - u32 n; - UNUSED_PARAMETER(argc); - pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); - if( pStr ){ - if( pStr->zBuf==0 ){ - jsonStringInit(pStr, ctx); - jsonAppendChar(pStr, '{'); - }else if( pStr->nUsed>1 ){ - jsonAppendChar(pStr, ','); - } - pStr->pCtx = ctx; - z = (const char*)sqlite3_value_text(argv[0]); - n = sqlite3Strlen30(z); - jsonAppendString(pStr, z, n); - jsonAppendChar(pStr, ':'); - jsonAppendSqlValue(pStr, argv[1]); - } -} -static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ - JsonString *pStr; - pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); - if( pStr ){ - int flags; - jsonAppendChar(pStr, '}'); - pStr->pCtx = ctx; - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - if( pStr->eErr ){ - jsonReturnString(pStr, 0, 0); - return; - }else if( flags & JSON_BLOB ){ - jsonReturnStringAsBlob(pStr); - if( isFinal ){ - if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); - }else{ - jsonStringTrimOneChar(pStr); - } - return; - }else if( isFinal ){ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : - sqlite3RCStrUnref); - pStr->bStatic = 1; - }else{ - sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); - jsonStringTrimOneChar(pStr); - } - }else{ - sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); - } - sqlite3_result_subtype(ctx, JSON_SUBTYPE); -} -static void jsonObjectValue(sqlite3_context *ctx){ - jsonObjectCompute(ctx, 0); -} -static void jsonObjectFinal(sqlite3_context *ctx){ - jsonObjectCompute(ctx, 1); -} - - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/**************************************************************************** -** The json_each virtual table -****************************************************************************/ -typedef struct JsonParent JsonParent; -struct JsonParent { - u32 iHead; /* Start of object or array */ - u32 iValue; /* Start of the value */ - u32 iEnd; /* First byte past the end */ - u32 nPath; /* Length of path */ - i64 iKey; /* Key for JSONB_ARRAY */ -}; - -typedef struct JsonEachCursor JsonEachCursor; -struct JsonEachCursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - u32 iRowid; /* The rowid */ - u32 i; /* Index in sParse.aBlob[] of current row */ - u32 iEnd; /* EOF when i equals or exceeds this value */ - u32 nRoot; /* Size of the root path in bytes */ - u8 eType; /* Type of the container for element i */ - u8 bRecursive; /* True for json_tree(). False for json_each() */ - u32 nParent; /* Current nesting depth */ - u32 nParentAlloc; /* Space allocated for aParent[] */ - JsonParent *aParent; /* Parent elements of i */ - sqlite3 *db; /* Database connection */ - JsonString path; /* Current path */ - JsonParse sParse; /* Parse of the input JSON */ -}; -typedef struct JsonEachConnection JsonEachConnection; -struct JsonEachConnection { - sqlite3_vtab base; /* Base class - must be first */ - sqlite3 *db; /* Database connection */ -}; - - -/* Constructor for the json_each virtual table */ -static int jsonEachConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - JsonEachConnection *pNew; - int rc; - -/* Column numbers */ -#define JEACH_KEY 0 -#define JEACH_VALUE 1 -#define JEACH_TYPE 2 -#define JEACH_ATOM 3 -#define JEACH_ID 4 -#define JEACH_PARENT 5 -#define JEACH_FULLKEY 6 -#define JEACH_PATH 7 -/* The xBestIndex method assumes that the JSON and ROOT columns are -** the last two columns in the table. Should this ever changes, be -** sure to update the xBestIndex method. */ -#define JEACH_JSON 8 -#define JEACH_ROOT 9 - - UNUSED_PARAMETER(pzErr); - UNUSED_PARAMETER(argv); - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(pAux); - rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," - "json HIDDEN,root HIDDEN)"); - if( rc==SQLITE_OK ){ - pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew)); - *ppVtab = (sqlite3_vtab*)pNew; - if( pNew==0 ) return SQLITE_NOMEM; - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - pNew->db = db; - } - return rc; -} - -/* destructor for json_each virtual table */ -static int jsonEachDisconnect(sqlite3_vtab *pVtab){ - JsonEachConnection *p = (JsonEachConnection*)pVtab; - sqlite3DbFree(p->db, pVtab); - return SQLITE_OK; -} - -/* constructor for a JsonEachCursor object for json_each(). */ -static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - JsonEachConnection *pVtab = (JsonEachConnection*)p; - JsonEachCursor *pCur; - - UNUSED_PARAMETER(p); - pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur)); - if( pCur==0 ) return SQLITE_NOMEM; - pCur->db = pVtab->db; - jsonStringZero(&pCur->path); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* constructor for a JsonEachCursor object for json_tree(). */ -static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - int rc = jsonEachOpenEach(p, ppCursor); - if( rc==SQLITE_OK ){ - JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; - pCur->bRecursive = 1; - } - return rc; -} - -/* Reset a JsonEachCursor back to its original state. Free any memory -** held. */ -static void jsonEachCursorReset(JsonEachCursor *p){ - jsonParseReset(&p->sParse); - jsonStringReset(&p->path); - sqlite3DbFree(p->db, p->aParent); - p->iRowid = 0; - p->i = 0; - p->aParent = 0; - p->nParent = 0; - p->nParentAlloc = 0; - p->iEnd = 0; - p->eType = 0; -} - -/* Destructor for a jsonEachCursor object */ -static int jsonEachClose(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - jsonEachCursorReset(p); - - sqlite3DbFree(p->db, cur); - return SQLITE_OK; -} - -/* Return TRUE if the jsonEachCursor object has been advanced off the end -** of the JSON object */ -static int jsonEachEof(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - return p->i >= p->iEnd; -} - -/* -** If the cursor is currently pointing at the label of a object entry, -** then return the index of the value. For all other cases, return the -** current pointer position, which is the value. -*/ -static int jsonSkipLabel(JsonEachCursor *p){ - if( p->eType==JSONB_OBJECT ){ - u32 sz = 0; - u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz); - return p->i + n + sz; - }else{ - return p->i; - } -} - -/* -** Append the path name for the current element. -*/ -static void jsonAppendPathName(JsonEachCursor *p){ - assert( p->nParent>0 ); - assert( p->eType==JSONB_ARRAY || p->eType==JSONB_OBJECT ); - if( p->eType==JSONB_ARRAY ){ - jsonPrintf(30, &p->path, "[%lld]", p->aParent[p->nParent-1].iKey); - }else{ - u32 n, sz = 0, k, i; - const char *z; - int needQuote = 0; - n = jsonbPayloadSize(&p->sParse, p->i, &sz); - k = p->i + n; - z = (const char*)&p->sParse.aBlob[k]; - if( sz==0 || !sqlite3Isalpha(z[0]) ){ - needQuote = 1; - }else{ - for(i=0; ipath,".\"%.*s\"", sz, z); - }else{ - jsonPrintf(sz+2,&p->path,".%.*s", sz, z); - } - } -} - -/* Advance the cursor to the next element for json_tree() */ -static int jsonEachNext(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - int rc = SQLITE_OK; - if( p->bRecursive ){ - u8 x; - u8 levelChange = 0; - u32 n, sz = 0; - u32 i = jsonSkipLabel(p); - x = p->sParse.aBlob[i] & 0x0f; - n = jsonbPayloadSize(&p->sParse, i, &sz); - if( x==JSONB_OBJECT || x==JSONB_ARRAY ){ - JsonParent *pParent; - if( p->nParent>=p->nParentAlloc ){ - JsonParent *pNew; - u64 nNew; - nNew = p->nParentAlloc*2 + 3; - pNew = sqlite3DbRealloc(p->db, p->aParent, sizeof(JsonParent)*nNew); - if( pNew==0 ) return SQLITE_NOMEM; - p->nParentAlloc = (u32)nNew; - p->aParent = pNew; - } - levelChange = 1; - pParent = &p->aParent[p->nParent]; - pParent->iHead = p->i; - pParent->iValue = i; - pParent->iEnd = i + n + sz; - pParent->iKey = -1; - pParent->nPath = (u32)p->path.nUsed; - if( p->eType && p->nParent ){ - jsonAppendPathName(p); - if( p->path.eErr ) rc = SQLITE_NOMEM; - } - p->nParent++; - p->i = i + n; - }else{ - p->i = i + n + sz; - } - while( p->nParent>0 && p->i >= p->aParent[p->nParent-1].iEnd ){ - p->nParent--; - p->path.nUsed = p->aParent[p->nParent].nPath; - levelChange = 1; - } - if( levelChange ){ - if( p->nParent>0 ){ - JsonParent *pParent = &p->aParent[p->nParent-1]; - u32 iVal = pParent->iValue; - p->eType = p->sParse.aBlob[iVal] & 0x0f; - }else{ - p->eType = 0; - } - } - }else{ - u32 n, sz = 0; - u32 i = jsonSkipLabel(p); - n = jsonbPayloadSize(&p->sParse, i, &sz); - p->i = i + n + sz; - } - if( p->eType==JSONB_ARRAY && p->nParent ){ - p->aParent[p->nParent-1].iKey++; - } - p->iRowid++; - return rc; -} - -/* Length of the path for rowid==0 in bRecursive mode. -*/ -static int jsonEachPathLength(JsonEachCursor *p){ - u32 n = p->path.nUsed; - char *z = p->path.zBuf; - if( p->iRowid==0 && p->bRecursive && n>=2 ){ - while( n>1 ){ - n--; - if( z[n]=='[' || z[n]=='.' ){ - u32 x, sz = 0; - char cSaved = z[n]; - z[n] = 0; - assert( p->sParse.eEdit==0 ); - x = jsonLookupStep(&p->sParse, 0, z+1, 0); - z[n] = cSaved; - if( JSON_LOOKUP_ISERROR(x) ) continue; - if( x + jsonbPayloadSize(&p->sParse, x, &sz) == p->i ) break; - } - } - } - return n; -} - -/* Return the value of a column */ -static int jsonEachColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int iColumn /* Which column to return */ -){ - JsonEachCursor *p = (JsonEachCursor*)cur; - switch( iColumn ){ - case JEACH_KEY: { - if( p->nParent==0 ){ - u32 n, j; - if( p->nRoot==1 ) break; - j = jsonEachPathLength(p); - n = p->nRoot - j; - if( n==0 ){ - break; - }else if( p->path.zBuf[j]=='[' ){ - i64 x; - sqlite3Atoi64(&p->path.zBuf[j+1], &x, n-1, SQLITE_UTF8); - sqlite3_result_int64(ctx, x); - }else if( p->path.zBuf[j+1]=='"' ){ - sqlite3_result_text(ctx, &p->path.zBuf[j+2], n-3, SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(ctx, &p->path.zBuf[j+1], n-1, SQLITE_TRANSIENT); - } - break; - } - if( p->eType==JSONB_OBJECT ){ - jsonReturnFromBlob(&p->sParse, p->i, ctx, 1); - }else{ - assert( p->eType==JSONB_ARRAY ); - sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey); - } - break; - } - case JEACH_VALUE: { - u32 i = jsonSkipLabel(p); - jsonReturnFromBlob(&p->sParse, i, ctx, 1); - if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){ - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - break; - } - case JEACH_TYPE: { - u32 i = jsonSkipLabel(p); - u8 eType = p->sParse.aBlob[i] & 0x0f; - sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC); - break; - } - case JEACH_ATOM: { - u32 i = jsonSkipLabel(p); - if( (p->sParse.aBlob[i] & 0x0f)sParse, i, ctx, 1); - } - break; - } - case JEACH_ID: { - sqlite3_result_int64(ctx, (sqlite3_int64)p->i); - break; - } - case JEACH_PARENT: { - if( p->nParent>0 && p->bRecursive ){ - sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead); - } - break; - } - case JEACH_FULLKEY: { - u64 nBase = p->path.nUsed; - if( p->nParent ) jsonAppendPathName(p); - sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed, - SQLITE_TRANSIENT, SQLITE_UTF8); - p->path.nUsed = nBase; - break; - } - case JEACH_PATH: { - u32 n = jsonEachPathLength(p); - sqlite3_result_text64(ctx, p->path.zBuf, n, - SQLITE_TRANSIENT, SQLITE_UTF8); - break; - } - default: { - sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_STATIC); - break; - } - case JEACH_JSON: { - if( p->sParse.zJson==0 ){ - sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob, - SQLITE_TRANSIENT); - }else{ - sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT); - } - break; - } - } - return SQLITE_OK; -} - -/* Return the current rowid value */ -static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - JsonEachCursor *p = (JsonEachCursor*)cur; - *pRowid = p->iRowid; - return SQLITE_OK; -} - -/* The query strategy is to look for an equality constraint on the json -** column. Without such a constraint, the table cannot operate. idxNum is -** 1 if the constraint is found, 3 if the constraint and zRoot are found, -** and 0 otherwise. -*/ -static int jsonEachBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo -){ - int i; /* Loop counter or computed array index */ - int aIdx[2]; /* Index of constraints for JSON and ROOT */ - int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ - int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ - const struct sqlite3_index_constraint *pConstraint; - - /* This implementation assumes that JSON and ROOT are the last two - ** columns in the table */ - assert( JEACH_ROOT == JEACH_JSON+1 ); - UNUSED_PARAMETER(tab); - aIdx[0] = aIdx[1] = -1; - pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pConstraint++){ - int iCol; - int iMask; - if( pConstraint->iColumn < JEACH_JSON ) continue; - iCol = pConstraint->iColumn - JEACH_JSON; - assert( iCol==0 || iCol==1 ); - testcase( iCol==0 ); - iMask = 1 << iCol; - if( pConstraint->usable==0 ){ - unusableMask |= iMask; - }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - aIdx[iCol] = i; - idxMask |= iMask; - } - } - if( pIdxInfo->nOrderBy>0 - && pIdxInfo->aOrderBy[0].iColumn<0 - && pIdxInfo->aOrderBy[0].desc==0 - ){ - pIdxInfo->orderByConsumed = 1; - } - - if( (unusableMask & ~idxMask)!=0 ){ - /* If there are any unusable constraints on JSON or ROOT, then reject - ** this entire plan */ - return SQLITE_CONSTRAINT; - } - if( aIdx[0]<0 ){ - /* No JSON input. Leave estimatedCost at the huge value that it was - ** initialized to to discourage the query planner from selecting this - ** plan. */ - pIdxInfo->idxNum = 0; - }else{ - pIdxInfo->estimatedCost = 1.0; - i = aIdx[0]; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - pIdxInfo->aConstraintUsage[i].omit = 1; - if( aIdx[1]<0 ){ - pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ - }else{ - i = aIdx[1]; - pIdxInfo->aConstraintUsage[i].argvIndex = 2; - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ - } - } - return SQLITE_OK; -} - -/* Start a search on a new JSON string */ -static int jsonEachFilter( - sqlite3_vtab_cursor *cur, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - JsonEachCursor *p = (JsonEachCursor*)cur; - const char *zRoot = 0; - u32 i, n, sz; - - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(argc); - jsonEachCursorReset(p); - if( idxNum==0 ) return SQLITE_OK; - memset(&p->sParse, 0, sizeof(p->sParse)); - p->sParse.nJPRef = 1; - p->sParse.db = p->db; - if( jsonFuncArgMightBeBinary(argv[0]) ){ - p->sParse.nBlob = sqlite3_value_bytes(argv[0]); - p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]); - }else{ - p->sParse.zJson = (char*)sqlite3_value_text(argv[0]); - p->sParse.nJson = sqlite3_value_bytes(argv[0]); - if( p->sParse.zJson==0 ){ - p->i = p->iEnd = 0; - return SQLITE_OK; - } - if( jsonConvertTextToBlob(&p->sParse, 0) ){ - if( p->sParse.oom ){ - return SQLITE_NOMEM; - } - goto json_each_malformed_input; - } - } - if( idxNum==3 ){ - zRoot = (const char*)sqlite3_value_text(argv[1]); - if( zRoot==0 ) return SQLITE_OK; - if( zRoot[0]!='$' ){ - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; - } - p->nRoot = sqlite3Strlen30(zRoot); - if( zRoot[1]==0 ){ - i = p->i = 0; - p->eType = 0; - }else{ - i = jsonLookupStep(&p->sParse, 0, zRoot+1, 0); - if( JSON_LOOKUP_ISERROR(i) ){ - if( i==JSON_LOOKUP_NOTFOUND ){ - p->i = 0; - p->eType = 0; - p->iEnd = 0; - return SQLITE_OK; - } - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; - } - if( p->sParse.iLabel ){ - p->i = p->sParse.iLabel; - p->eType = JSONB_OBJECT; - }else{ - p->i = i; - p->eType = JSONB_ARRAY; - } - } - jsonAppendRaw(&p->path, zRoot, p->nRoot); - }else{ - i = p->i = 0; - p->eType = 0; - p->nRoot = 1; - jsonAppendRaw(&p->path, "$", 1); - } - p->nParent = 0; - n = jsonbPayloadSize(&p->sParse, i, &sz); - p->iEnd = i+n+sz; - if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){ - p->i = i + n; - p->eType = p->sParse.aBlob[i] & 0x0f; - p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent)); - if( p->aParent==0 ) return SQLITE_NOMEM; - p->nParent = 1; - p->nParentAlloc = 1; - p->aParent[0].iKey = 0; - p->aParent[0].iEnd = p->iEnd; - p->aParent[0].iHead = p->i; - p->aParent[0].iValue = i; - } - return SQLITE_OK; - -json_each_malformed_input: - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; -} - -/* The methods of the json_each virtual table */ -static sqlite3_module jsonEachModule = { - 0, /* iVersion */ - 0, /* xCreate */ - jsonEachConnect, /* xConnect */ - jsonEachBestIndex, /* xBestIndex */ - jsonEachDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - jsonEachOpenEach, /* xOpen - open a cursor */ - jsonEachClose, /* xClose - close a cursor */ - jsonEachFilter, /* xFilter - configure scan constraints */ - jsonEachNext, /* xNext - advance a cursor */ - jsonEachEof, /* xEof - check for end of scan */ - jsonEachColumn, /* xColumn - read data */ - jsonEachRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ -}; - -/* The methods of the json_tree virtual table. */ -static sqlite3_module jsonTreeModule = { - 0, /* iVersion */ - 0, /* xCreate */ - jsonEachConnect, /* xConnect */ - jsonEachBestIndex, /* xBestIndex */ - jsonEachDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - jsonEachOpenTree, /* xOpen - open a cursor */ - jsonEachClose, /* xClose - close a cursor */ - jsonEachFilter, /* xFilter - configure scan constraints */ - jsonEachNext, /* xNext - advance a cursor */ - jsonEachEof, /* xEof - check for end of scan */ - jsonEachColumn, /* xColumn - read data */ - jsonEachRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ -}; -#endif /* SQLITE_OMIT_VIRTUALTABLE */ -#endif /* !defined(SQLITE_OMIT_JSON) */ - -/* -** Register JSON functions. -*/ -SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ -#ifndef SQLITE_OMIT_JSON - static FuncDef aJsonFunc[] = { - /* sqlite3_result_subtype() ----, ,--- sqlite3_value_subtype() */ - /* | | */ - /* Uses cache ------, | | ,---- Returns JSONB */ - /* | | | | */ - /* Number of arguments ---, | | | | ,--- Flags */ - /* | | | | | | */ - JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc), - JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc), - JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc), - JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc), - JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc), - JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc), - JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc), - JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc), - JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc), - JFUNCTION(->, 2,1,1, 0,0,JSON_JSON, jsonExtractFunc), - JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc), - JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc), - JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc), - JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc), - JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc), - JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc), - JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc), - JFUNCTION(json_pretty, 1,1,0, 0,0,0, jsonPrettyFunc), - JFUNCTION(json_pretty, 2,1,0, 0,0,0, jsonPrettyFunc), - JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc), - JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc), - JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc), - JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc), - JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc), - JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc), - JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc), - JFUNCTION(json_type, 1,1,0, 0,0,0, jsonTypeFunc), - JFUNCTION(json_type, 2,1,0, 0,0,0, jsonTypeFunc), - JFUNCTION(json_valid, 1,1,0, 0,0,0, jsonValidFunc), - JFUNCTION(json_valid, 2,1,0, 0,0,0, jsonValidFunc), -#if SQLITE_DEBUG - JFUNCTION(json_parse, 1,1,0, 0,0,0, jsonParseFunc), -#endif - WAGGREGATE(json_group_array, 1, 0, 0, - jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| - SQLITE_DETERMINISTIC), - WAGGREGATE(jsonb_group_array, 1, JSON_BLOB, 0, - jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), - WAGGREGATE(json_group_object, 2, 0, 0, - jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), - WAGGREGATE(jsonb_group_object,2, JSON_BLOB, 0, - jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8| - SQLITE_DETERMINISTIC) - }; - sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); -#endif -} - -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) -/* -** Register the JSON table-valued functions -*/ -SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3 *db){ - int rc = SQLITE_OK; - static const struct { - const char *zName; - sqlite3_module *pModule; - } aMod[] = { - { "json_each", &jsonEachModule }, - { "json_tree", &jsonTreeModule }, - }; - unsigned int i; - for(i=0; i */ +/* #include */ +/* #include */ + +#ifndef SQLITE_AMALGAMATION #include "sqlite3rtree.h" typedef sqlite3_int64 i64; typedef sqlite3_uint64 u64; typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif -#if defined(NDEBUG) && defined(SQLITE_DEBUG) -# undef NDEBUG -#endif -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) -# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 -#endif -#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) -# define ALWAYS(X) (1) -# define NEVER(X) (0) -#elif !defined(NDEBUG) -# define ALWAYS(X) ((X)?1:(assert(0),0)) -# define NEVER(X) ((X)?(assert(0),1):0) -#else -# define ALWAYS(X) (X) -# define NEVER(X) (X) -#endif -#endif /* !defined(SQLITE_AMALGAMATION) */ - -/* Macro to check for 4-byte alignment. Only used inside of assert() */ -#ifdef SQLITE_DEBUG -# define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0) -#endif - -/* #include */ -/* #include */ -/* #include */ -/* #include */ +#endif /* The following macro is used to suppress compiler warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(x) (void)(x) @@ -212181,30 +165266,27 @@ typedef struct RtreeSearchPoint RtreeSearchPoint; /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ #define RTREE_MAX_DIMENSIONS 5 -/* Maximum number of auxiliary columns */ -#define RTREE_MAX_AUX_COLUMN 100 - /* Size of hash table Rtree.aHash. This hash table is not expected to -** ever contain very many entries, so a fixed number of buckets is +** ever contain very many entries, so a fixed number of buckets is ** used. */ #define HASHSIZE 97 /* The xBestIndex method of this virtual table requires an estimate of ** the number of rows in the virtual table to calculate the costs of ** various strategies. If possible, this estimate is loaded from the ** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum). -** Otherwise, if no sqlite_stat1 entry is available, use +** Otherwise, if no sqlite_stat1 entry is available, use ** RTREE_DEFAULT_ROWEST. */ #define RTREE_DEFAULT_ROWEST 1048576 #define RTREE_MIN_ROWEST 100 -/* +/* ** An rtree virtual-table object. */ struct Rtree { sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* Host database connection */ @@ -212212,33 +165294,24 @@ u8 nDim; /* Number of dimensions */ u8 nDim2; /* Twice the number of dimensions */ u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ u8 nBytesPerCell; /* Bytes consumed per cell */ u8 inWrTrans; /* True if inside write transaction */ - u8 nAux; /* # of auxiliary columns in %_rowid */ -#ifdef SQLITE_ENABLE_GEOPOLY - u8 nAuxNotNull; /* Number of initial not-null aux columns */ -#endif -#ifdef SQLITE_DEBUG - u8 bCorrupt; /* Shadow table corruption detected */ -#endif int iDepth; /* Current depth of the r-tree structure */ char *zDb; /* Name of database containing r-tree table */ - char *zName; /* Name of r-tree table */ - char *zNodeName; /* Name of the %_node table */ + char *zName; /* Name of r-tree table */ u32 nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ u32 nCursor; /* Number of open cursors */ - u32 nNodeRef; /* Number RtreeNodes with positive nRef */ - char *zReadAuxSql; /* SQL for statement to read aux data */ /* List of nodes removed during a CondenseTree operation. List is ** linked together via the pointer normally used for hash chains - - ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree + ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree ** headed by the node (leaf nodes have RtreeNode.iNode==0). */ RtreeNode *pDeleted; + int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */ /* Blob I/O on xxx_node */ sqlite3_blob *pNodeBlob; /* Statements to read/write/delete a record from xxx_node */ @@ -212253,14 +165326,11 @@ /* Statements to read/write/delete a record from xxx_parent */ sqlite3_stmt *pReadParent; sqlite3_stmt *pWriteParent; sqlite3_stmt *pDeleteParent; - /* Statement for writing to the "aux:" fields, if there are any */ - sqlite3_stmt *pWriteAux; - - RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ + RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ }; /* Possible values for Rtree.eCoordType: */ #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 @@ -212278,19 +165348,10 @@ typedef double RtreeDValue; /* High accuracy coordinate */ typedef float RtreeValue; /* Low accuracy coordinate */ # define RTREE_ZERO 0.0 #endif -/* -** Set the Rtree.bCorrupt flag -*/ -#ifdef SQLITE_DEBUG -# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1) -#else -# define RTREE_IS_CORRUPT(X) -#endif - /* ** When doing a search of an r-tree, instances of the following structure ** record intermediate results from the tree walk. ** ** The id is always a node-id. For iLevel>=1 the id is the node-id of @@ -212305,11 +165366,11 @@ u8 eWithin; /* PARTLY_WITHIN or FULLY_WITHIN */ u8 iCell; /* Cell index within the node */ }; /* -** The minimum number of cells allowed for a node is a third of the +** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: ** ** m = M/3 ** ** If an R*-tree "Reinsert" operation is required, the same number of @@ -212320,12 +165381,12 @@ #define RTREE_MAXCELLS 51 /* ** The smallest possible node-size is (512-64)==448 bytes. And the largest ** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). -** Therefore all non-root nodes must contain at least 3 entries. Since -** 3^40 is greater than 2^64, an r-tree structure always has a depth of +** Therefore all non-root nodes must contain at least 3 entries. Since +** 2^40 is greater than 2^64, an r-tree structure always has a depth of ** 40 or less. */ #define RTREE_MAX_DEPTH 40 @@ -212334,26 +165395,24 @@ ** used to cache the RtreeNode for RtreeCursor.sPoint. The remaining ** entries cache the RtreeNode for the first elements of the priority queue. */ #define RTREE_CACHE_SZ 5 -/* +/* ** An rtree cursor object. */ struct RtreeCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ u8 atEOF; /* True if at end of search */ u8 bPoint; /* True if sPoint is valid */ - u8 bAuxValid; /* True if pReadAux is valid */ int iStrategy; /* Copy of idxNum search parameter */ int nConstraint; /* Number of entries in aConstraint */ RtreeConstraint *aConstraint; /* Search constraints. */ int nPointAlloc; /* Number of slots allocated for aPoint[] */ int nPoint; /* Number of slots used in aPoint[] */ int mxLevel; /* iLevel value for root of the tree */ RtreeSearchPoint *aPoint; /* Priority queue for search points */ - sqlite3_stmt *pReadAux; /* Statement to read aux-data */ RtreeSearchPoint sPoint; /* Cached next search point */ RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ }; @@ -212407,18 +165466,12 @@ #define RTREE_GE 0x44 /* D */ #define RTREE_GT 0x45 /* E */ #define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */ #define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */ -/* Special operators available only on cursors. Needs to be consecutive -** with the normal values above, but must be less than RTREE_MATCH. These -** are used in the cursor for contraints such as x=NULL (RTREE_FALSE) or -** x<'xyz' (RTREE_TRUE) */ -#define RTREE_TRUE 0x3f /* ? */ -#define RTREE_FALSE 0x40 /* @ */ - -/* + +/* ** An rtree structure node. */ struct RtreeNode { RtreeNode *pParent; /* Parent node */ i64 iNode; /* The node number */ @@ -212429,11 +165482,11 @@ }; /* Return the number of cells in a node */ #define NCELL(pNode) readInt16(&(pNode)->zData[2]) -/* +/* ** A single cell from a node, deserialized */ struct RtreeCell { i64 iRowid; /* Node or entry ID */ RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; /* Bounding box coordinates */ @@ -212444,15 +165497,15 @@ ** This object becomes the sqlite3_user_data() for the SQL functions ** that are created by sqlite3_rtree_geometry_callback() and ** sqlite3_rtree_query_callback() and which appear on the right of MATCH ** operators in order to constrain a search. ** -** xGeom and xQueryFunc are the callback functions. Exactly one of +** xGeom and xQueryFunc are the callback functions. Exactly one of ** xGeom and xQueryFunc fields is non-NULL, depending on whether the ** SQL function was created using sqlite3_rtree_geometry_callback() or ** sqlite3_rtree_query_callback(). -** +** ** This object is deleted automatically by the destructor mechanism in ** sqlite3_create_function_v2(). */ struct RtreeGeomCallback { int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); @@ -212459,18 +165512,26 @@ int (*xQueryFunc)(sqlite3_rtree_query_info*); void (*xDestructor)(void*); void *pContext; }; + +/* +** Value for the first field of every RtreeMatchArg object. The MATCH +** operator tests that the first field of a blob operand matches this +** value to avoid operating on invalid blobs (which could cause a segfault). +*/ +#define RTREE_GEOMETRY_MAGIC 0x891245AB + /* ** An instance of this structure (in the form of a BLOB) is returned by ** the SQL functions that sqlite3_rtree_geometry_callback() and ** sqlite3_rtree_query_callback() create, and is read as the right-hand ** operand to the MATCH operator of an R-Tree. */ struct RtreeMatchArg { - u32 iSize; /* Size of this object */ + u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ sqlite3_value **apSqlParam; /* Original SQL parameter values */ RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ }; @@ -212497,33 +165558,11 @@ /* The testcase() macro should already be defined in the amalgamation. If ** it is not, make it a no-op. */ #ifndef SQLITE_AMALGAMATION -# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) - unsigned int sqlite3RtreeTestcase = 0; -# define testcase(X) if( X ){ sqlite3RtreeTestcase += __LINE__; } -# else -# define testcase(X) -# endif -#endif - -/* -** Make sure that the compiler intrinsics we desire are enabled when -** compiling with an appropriate version of MSVC unless prevented by -** the SQLITE_DISABLE_INTRINSIC define. -*/ -#if !defined(SQLITE_DISABLE_INTRINSIC) -# if defined(_MSC_VER) && _MSC_VER>=1400 -# if !defined(_WIN32_WCE) -/* # include */ -# pragma intrinsic(_byteswap_ulong) -# pragma intrinsic(_byteswap_uint64) -# else -/* # include */ -# endif -# endif +# define testcase(X) #endif /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. @@ -212531,27 +165570,21 @@ ** 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 ** at run-time. */ -#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */ -# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ -# define SQLITE_BYTEORDER 4321 -# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ -# define SQLITE_BYTEORDER 1234 -# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 -# define SQLITE_BYTEORDER 4321 -# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 -# else -# define SQLITE_BYTEORDER 0 -# endif +#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__) +# define SQLITE_BYTEORDER 1234 +#elif defined(sparc) || defined(__ppc__) +# define SQLITE_BYTEORDER 4321 +#else +# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ +#endif #endif /* What version of MSVC is being used. 0 means MSVC is not being used */ #ifndef MSVC_VERSION @@ -212568,22 +165601,22 @@ */ static int readInt16(u8 *p){ return (p[0]<<8) + p[1]; } static void readCoord(u8 *p, RtreeCoord *pCoord){ - assert( FOUR_BYTE_ALIGNED(p) ); + assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */ #if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 pCoord->u = _byteswap_ulong(*(u32*)p); #elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 pCoord->u = __builtin_bswap32(*(u32*)p); #elif SQLITE_BYTEORDER==4321 pCoord->u = *(u32*)p; #else pCoord->u = ( - (((u32)p[0]) << 24) + - (((u32)p[1]) << 16) + - (((u32)p[2]) << 8) + + (((u32)p[0]) << 24) + + (((u32)p[1]) << 16) + + (((u32)p[2]) << 8) + (((u32)p[3]) << 0) ); #endif } static i64 readInt64(u8 *p){ @@ -212599,17 +165632,17 @@ i64 x; memcpy(&x, p, 8); return x; #else return (i64)( - (((u64)p[0]) << 56) + - (((u64)p[1]) << 48) + - (((u64)p[2]) << 40) + - (((u64)p[3]) << 32) + - (((u64)p[4]) << 24) + - (((u64)p[5]) << 16) + - (((u64)p[6]) << 8) + + (((u64)p[0]) << 56) + + (((u64)p[1]) << 48) + + (((u64)p[2]) << 40) + + (((u64)p[3]) << 32) + + (((u64)p[4]) << 24) + + (((u64)p[5]) << 16) + + (((u64)p[6]) << 8) + (((u64)p[7]) << 0) ); #endif } @@ -212622,11 +165655,11 @@ p[0] = (i>> 8)&0xFF; p[1] = (i>> 0)&0xFF; } static int writeCoord(u8 *p, RtreeCoord *pCoord){ u32 i; - assert( FOUR_BYTE_ALIGNED(p) ); + assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */ assert( sizeof(RtreeCoord)==4 ); assert( sizeof(u32)==4 ); #if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 i = __builtin_bswap32(pCoord->u); memcpy(p, &i, 4); @@ -212670,11 +165703,10 @@ /* ** Increment the reference count of node p. */ static void nodeReference(RtreeNode *p){ if( p ){ - assert( p->nRef>0 ); p->nRef++; } } /* @@ -212687,12 +165719,12 @@ /* ** Given a node number iNode, return the corresponding key to use ** in the Rtree.aHash table. */ -static unsigned int nodeHash(i64 iNode){ - return ((unsigned)iNode) % HASHSIZE; +static int nodeHash(i64 iNode){ + return iNode % HASHSIZE; } /* ** Search the node hash table for node iNode. If found, return a pointer ** to it. Otherwise, return 0. @@ -212733,16 +165765,15 @@ ** assigned a node number when nodeWrite() is called to write the ** node contents out to the database. */ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ RtreeNode *pNode; - pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode) + pRtree->iNodeSize); + pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); if( pNode ){ memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; - pRtree->nNodeRef++; pNode->pParent = pParent; pNode->isDirty = 1; nodeReference(pParent); } return pNode; @@ -212750,13 +165781,15 @@ /* ** Clear the Rtree.pNodeBlob object */ static void nodeBlobReset(Rtree *pRtree){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - sqlite3_blob_close(pBlob); + if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){ + sqlite3_blob *pBlob = pRtree->pNodeBlob; + pRtree->pNodeBlob = 0; + sqlite3_blob_close(pBlob); + } } /* ** Obtain a reference to an r-tree node. */ @@ -212770,14 +165803,15 @@ RtreeNode *pNode = 0; /* Check if the requested node is already in the hash table. If so, ** increase its reference count and return it. */ - if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ - if( pParent && ALWAYS(pParent!=pNode->pParent) ){ - RTREE_IS_CORRUPT(pRtree); - return SQLITE_CORRUPT_VTAB; + if( (pNode = nodeHashLookup(pRtree, iNode)) ){ + assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); + if( pParent && !pNode->pParent ){ + nodeReference(pParent); + pNode->pParent = pParent; } pNode->nRef++; *ppNode = pNode; return SQLITE_OK; } @@ -212791,79 +165825,71 @@ nodeBlobReset(pRtree); if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM; } } if( pRtree->pNodeBlob==0 ){ - rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, pRtree->zNodeName, - "data", iNode, 0, + char *zTab = sqlite3_mprintf("%s_node", pRtree->zName); + if( zTab==0 ) return SQLITE_NOMEM; + rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0, &pRtree->pNodeBlob); + sqlite3_free(zTab); } if( rc ){ + nodeBlobReset(pRtree); *ppNode = 0; /* If unable to open an sqlite3_blob on the desired row, that can only ** be because the shadow tables hold erroneous data. */ - if( rc==SQLITE_ERROR ){ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); - } + if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB; }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){ - pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize); + pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize); if( !pNode ){ rc = SQLITE_NOMEM; }else{ pNode->pParent = pParent; pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; - pRtree->nNodeRef++; pNode->iNode = iNode; pNode->isDirty = 0; pNode->pNext = 0; rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData, pRtree->iNodeSize, 0); + nodeReference(pParent); } } /* If the root node was just loaded, set pRtree->iDepth to the height ** of the r-tree structure. A height of zero means all data is stored on ** the root node. A height of one means the children of the root node ** are the leaves, and so on. If the depth as specified on the root node ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt. */ - if( rc==SQLITE_OK && pNode && iNode==1 ){ + if( pNode && iNode==1 ){ pRtree->iDepth = readInt16(pNode->zData); if( pRtree->iDepth>RTREE_MAX_DEPTH ){ rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); } } /* If no error has occurred so far, check if the "number of entries" - ** field on the node is too large. If so, set the return code to + ** field on the node is too large. If so, set the return code to ** SQLITE_CORRUPT_VTAB. */ if( pNode && rc==SQLITE_OK ){ if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){ rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); } } if( rc==SQLITE_OK ){ if( pNode!=0 ){ - nodeReference(pParent); nodeHashInsert(pRtree, pNode); }else{ rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); } *ppNode = pNode; }else{ - nodeBlobReset(pRtree); - if( pNode ){ - pRtree->nNodeRef--; - sqlite3_free(pNode); - } + sqlite3_free(pNode); *ppNode = 0; } return rc; } @@ -212939,11 +165965,10 @@ } sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC); sqlite3_step(p); pNode->isDirty = 0; rc = sqlite3_reset(p); - sqlite3_bind_null(p, 2); if( pNode->iNode==0 && rc==SQLITE_OK ){ pNode->iNode = sqlite3_last_insert_rowid(pRtree->db); nodeHashInsert(pRtree, pNode); } } @@ -212956,14 +165981,12 @@ */ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){ int rc = SQLITE_OK; if( pNode ){ assert( pNode->nRef>0 ); - assert( pRtree->nNodeRef>0 ); pNode->nRef--; if( pNode->nRef==0 ){ - pRtree->nNodeRef--; if( pNode->iNode==1 ){ pRtree->iDepth = -1; } if( pNode->pParent ){ rc = nodeRelease(pRtree, pNode->pParent); @@ -213000,11 +166023,10 @@ RtreeNode *pNode, /* The node from which to extract a coordinate */ int iCell, /* The index of the cell within the node */ int iCoord, /* Which coordinate to extract */ RtreeCoord *pCoord /* OUT: Space to write result to */ ){ - assert( iCellzData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord); } /* ** Deserialize cell iCell of node pNode. Populate the structure pointed @@ -213036,11 +166058,11 @@ */ static int rtreeInit( sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int ); -/* +/* ** Rtree virtual table module xCreate method. */ static int rtreeCreate( sqlite3 *db, void *pAux, @@ -213049,11 +166071,11 @@ char **pzErr ){ return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1); } -/* +/* ** Rtree virtual table module xConnect method. */ static int rtreeConnect( sqlite3 *db, void *pAux, @@ -213077,46 +166099,43 @@ */ static void rtreeRelease(Rtree *pRtree){ pRtree->nBusy--; if( pRtree->nBusy==0 ){ pRtree->inWrTrans = 0; - assert( pRtree->nCursor==0 ); + pRtree->nCursor = 0; nodeBlobReset(pRtree); - assert( pRtree->nNodeRef==0 || pRtree->bCorrupt ); sqlite3_finalize(pRtree->pWriteNode); sqlite3_finalize(pRtree->pDeleteNode); sqlite3_finalize(pRtree->pReadRowid); sqlite3_finalize(pRtree->pWriteRowid); sqlite3_finalize(pRtree->pDeleteRowid); sqlite3_finalize(pRtree->pReadParent); sqlite3_finalize(pRtree->pWriteParent); sqlite3_finalize(pRtree->pDeleteParent); - sqlite3_finalize(pRtree->pWriteAux); - sqlite3_free(pRtree->zReadAuxSql); sqlite3_free(pRtree); } } -/* +/* ** Rtree virtual table module xDisconnect method. */ static int rtreeDisconnect(sqlite3_vtab *pVtab){ rtreeRelease((Rtree *)pVtab); return SQLITE_OK; } -/* +/* ** Rtree virtual table module xDestroy method. */ static int rtreeDestroy(sqlite3_vtab *pVtab){ Rtree *pRtree = (Rtree *)pVtab; int rc; char *zCreate = sqlite3_mprintf( "DROP TABLE '%q'.'%q_node';" "DROP TABLE '%q'.'%q_rowid';" "DROP TABLE '%q'.'%q_parent';", - pRtree->zDb, pRtree->zName, + pRtree->zDb, pRtree->zName, pRtree->zDb, pRtree->zName, pRtree->zDb, pRtree->zName ); if( !zCreate ){ rc = SQLITE_NOMEM; @@ -213130,19 +166149,19 @@ } return rc; } -/* +/* ** Rtree virtual table module xOpen method. */ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ int rc = SQLITE_NOMEM; Rtree *pRtree = (Rtree *)pVTab; RtreeCursor *pCsr; - pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor)); + pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor)); if( pCsr ){ memset(pCsr, 0, sizeof(RtreeCursor)); pCsr->base.pVtab = pVTab; rc = SQLITE_OK; pRtree->nCursor++; @@ -213152,16 +166171,13 @@ return rc; } /* -** Reset a cursor back to its initial state. +** Free the RtreeCursor.aConstraint[] array and its contents. */ -static void resetCursor(RtreeCursor *pCsr){ - Rtree *pRtree = (Rtree *)(pCsr->base.pVtab); - int ii; - sqlite3_stmt *pStmt; +static void freeCursorConstraints(RtreeCursor *pCsr){ if( pCsr->aConstraint ){ int i; /* Used to iterate through constraint array */ for(i=0; inConstraint; i++){ sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo; if( pInfo ){ @@ -213170,40 +166186,33 @@ } } sqlite3_free(pCsr->aConstraint); pCsr->aConstraint = 0; } - for(ii=0; iiaNode[ii]); - sqlite3_free(pCsr->aPoint); - pStmt = pCsr->pReadAux; - memset(pCsr, 0, sizeof(RtreeCursor)); - pCsr->base.pVtab = (sqlite3_vtab*)pRtree; - pCsr->pReadAux = pStmt; - } -/* +/* ** Rtree virtual table module xClose method. */ static int rtreeClose(sqlite3_vtab_cursor *cur){ Rtree *pRtree = (Rtree *)(cur->pVtab); + int ii; RtreeCursor *pCsr = (RtreeCursor *)cur; assert( pRtree->nCursor>0 ); - resetCursor(pCsr); - sqlite3_finalize(pCsr->pReadAux); + freeCursorConstraints(pCsr); + sqlite3_free(pCsr->aPoint); + for(ii=0; iiaNode[ii]); sqlite3_free(pCsr); pRtree->nCursor--; - if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){ - nodeBlobReset(pRtree); - } + nodeBlobReset(pRtree); return SQLITE_OK; } /* ** Rtree virtual table module xEof method. ** -** Return non-zero if the cursor does not currently point to a valid +** Return non-zero if the cursor does not currently point to a valid ** record (i.e if the scan has finished), or zero otherwise. */ static int rtreeEof(sqlite3_vtab_cursor *cur){ RtreeCursor *pCsr = (RtreeCursor *)cur; return pCsr->atEOF; @@ -213255,11 +166264,11 @@ } #endif /* ** Check the RTree node or entry given by pCellData and p against the MATCH -** constraint pConstraint. +** constraint pConstraint. */ static int rtreeCallbackConstraint( RtreeConstraint *pConstraint, /* The constraint to test */ int eInt, /* True if RTree holding integer coordinates */ u8 *pCellData, /* Raw cell content */ @@ -213328,11 +166337,11 @@ } } return rc; } -/* +/* ** Check the internal RTree node given by pCellData against constraint p. ** If this constraint cannot be satisfied by any child within the node, ** set *peWithin to NOT_WITHIN. */ static void rtreeNonleafConstraint( @@ -213346,40 +166355,28 @@ /* p->iCoord might point to either a lower or upper bound coordinate ** in a coordinate pair. But make pCellData point to the lower bound. */ pCellData += 8 + 4*(p->iCoord&0xfe); - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE - || p->op==RTREE_FALSE ); - assert( FOUR_BYTE_ALIGNED(pCellData) ); - switch( p->op ){ - case RTREE_TRUE: return; /* Always satisfied */ - case RTREE_FALSE: break; /* Never satisfied */ - case RTREE_EQ: - RTREE_DECODE_COORD(eInt, pCellData, val); - /* val now holds the lower bound of the coordinate pair */ - if( p->u.rValue>=val ){ - pCellData += 4; - RTREE_DECODE_COORD(eInt, pCellData, val); - /* val now holds the upper bound of the coordinate pair */ - if( p->u.rValue<=val ) return; - } - break; - case RTREE_LE: - case RTREE_LT: - RTREE_DECODE_COORD(eInt, pCellData, val); - /* val now holds the lower bound of the coordinate pair */ - if( p->u.rValue>=val ) return; - break; - - default: - pCellData += 4; - RTREE_DECODE_COORD(eInt, pCellData, val); - /* val now holds the upper bound of the coordinate pair */ - if( p->u.rValue<=val ) return; - break; + assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE + || p->op==RTREE_GT || p->op==RTREE_EQ ); + assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */ + switch( p->op ){ + case RTREE_LE: + case RTREE_LT: + case RTREE_EQ: + RTREE_DECODE_COORD(eInt, pCellData, val); + /* val now holds the lower bound of the coordinate pair */ + if( p->u.rValue>=val ) return; + if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */ + /* Fall through for the RTREE_EQ case */ + + default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */ + pCellData += 4; + RTREE_DECODE_COORD(eInt, pCellData, val); + /* val now holds the upper bound of the coordinate pair */ + if( p->u.rValue<=val ) return; } *peWithin = NOT_WITHIN; } /* @@ -213398,35 +166395,32 @@ u8 *pCellData, /* Raw cell content as appears on disk */ int *peWithin /* Adjust downward, as appropriate */ ){ RtreeDValue xN; /* Coordinate value converted to a double */ - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE - || p->op==RTREE_FALSE ); + assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE + || p->op==RTREE_GT || p->op==RTREE_EQ ); pCellData += 8 + p->iCoord*4; - assert( FOUR_BYTE_ALIGNED(pCellData) ); + assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */ RTREE_DECODE_COORD(eInt, pCellData, xN); switch( p->op ){ - case RTREE_TRUE: return; /* Always satisfied */ - case RTREE_FALSE: break; /* Never satisfied */ - case RTREE_LE: if( xN <= p->u.rValue ) return; break; - case RTREE_LT: if( xN < p->u.rValue ) return; break; - case RTREE_GE: if( xN >= p->u.rValue ) return; break; - case RTREE_GT: if( xN > p->u.rValue ) return; break; - default: if( xN == p->u.rValue ) return; break; + case RTREE_LE: if( xN <= p->u.rValue ) return; break; + case RTREE_LT: if( xN < p->u.rValue ) return; break; + case RTREE_GE: if( xN >= p->u.rValue ) return; break; + case RTREE_GT: if( xN > p->u.rValue ) return; break; + default: if( xN == p->u.rValue ) return; break; } *peWithin = NOT_WITHIN; } /* -** One of the cells in node pNode is guaranteed to have a 64-bit +** One of the cells in node pNode is guaranteed to have a 64-bit ** integer value equal to iRowid. Return the index of this cell. */ static int nodeRowidIndex( - Rtree *pRtree, - RtreeNode *pNode, + Rtree *pRtree, + RtreeNode *pNode, i64 iRowid, int *piIndex ){ int ii; int nCell = NCELL(pNode); @@ -213435,26 +166429,24 @@ if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){ *piIndex = ii; return SQLITE_OK; } } - RTREE_IS_CORRUPT(pRtree); return SQLITE_CORRUPT_VTAB; } /* ** Return the index of the cell containing a pointer to node pNode ** in its parent. If pNode is the root node, return -1. */ static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){ RtreeNode *pParent = pNode->pParent; - if( ALWAYS(pParent) ){ + if( pParent ){ return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex); - }else{ - *piIndex = -1; - return SQLITE_OK; } + *piIndex = -1; + return SQLITE_OK; } /* ** Compare two search points. Return negative, zero, or positive if the first ** is less than, equal to, or greater than the second. @@ -213530,11 +166522,11 @@ ){ int i, j; RtreeSearchPoint *pNew; if( pCur->nPoint>=pCur->nPointAlloc ){ int nNew = pCur->nPointAlloc*2 + 8; - pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); + pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); if( pNew==0 ) return 0; pCur->aPoint = pNew; pCur->nPointAlloc = nNew; } i = pCur->nPoint++; @@ -213565,23 +166557,22 @@ ){ RtreeSearchPoint *pNew, *pFirst; pFirst = rtreeSearchPointFirst(pCur); pCur->anQueue[iLevel]++; if( pFirst==0 - || pFirst->rScore>rScore + || pFirst->rScore>rScore || (pFirst->rScore==rScore && pFirst->iLevel>iLevel) ){ if( pCur->bPoint ){ int ii; pNew = rtreeEnqueue(pCur, rScore, iLevel); if( pNew==0 ) return 0; ii = (int)(pNew - pCur->aPoint) + 1; - assert( ii==1 ); - if( ALWAYS(iiaNode[ii]==0 ); pCur->aNode[ii] = pCur->aNode[0]; - }else{ + }else{ nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); } pCur->aNode[0] = 0; *pNew = pCur->sPoint; } @@ -213635,11 +166626,11 @@ p->aNode[i] = 0; } if( p->bPoint ){ p->anQueue[p->sPoint.iLevel]--; p->bPoint = 0; - }else if( ALWAYS(p->nPoint) ){ + }else if( p->nPoint ){ p->anQueue[p->aPoint[0].iLevel]--; n = --p->nPoint; p->aPoint[0] = p->aPoint[n]; if( naNode[1] = p->aNode[n+1]; @@ -213686,18 +166677,17 @@ int eInt; RtreeSearchPoint x; eInt = pRtree->eCoordType==RTREE_COORD_INT32; while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ - u8 *pCellData; pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); if( rc ) return rc; nCell = NCELL(pNode); assert( nCell<200 ); - pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell); while( p->iCellzData + (4+pRtree->nBytesPerCell*p->iCell); eWithin = FULLY_WITHIN; for(ii=0; iiaConstraint + ii; if( pConstraint->op>=RTREE_MATCH ){ rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p, @@ -213706,27 +166696,17 @@ }else if( p->iLevel==1 ){ rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin); }else{ rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin); } - if( eWithin==NOT_WITHIN ){ - p->iCell++; - pCellData += pRtree->nBytesPerCell; - break; - } - } - if( eWithin==NOT_WITHIN ) continue; - p->iCell++; + if( eWithin==NOT_WITHIN ) break; + } + p->iCell++; + if( eWithin==NOT_WITHIN ) continue; x.iLevel = p->iLevel - 1; if( x.iLevel ){ x.id = readInt64(pCellData); - for(ii=0; iinPoint; ii++){ - if( pCur->aPoint[ii].id==x.id ){ - RTREE_IS_CORRUPT(pRtree); - return SQLITE_CORRUPT_VTAB; - } - } x.iCell = 0; }else{ x.id = p->id; x.iCell = p->iCell - 1; } @@ -213750,47 +166730,39 @@ } pCur->atEOF = p==0; return SQLITE_OK; } -/* +/* ** Rtree virtual table module xNext method. */ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; int rc = SQLITE_OK; /* Move to the next entry that matches the configured constraints. */ RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); - if( pCsr->bAuxValid ){ - pCsr->bAuxValid = 0; - sqlite3_reset(pCsr->pReadAux); - } rtreeSearchPointPop(pCsr); rc = rtreeStepToLeaf(pCsr); return rc; } -/* +/* ** Rtree virtual table module xRowid method. */ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); int rc = SQLITE_OK; RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - if( rc==SQLITE_OK && ALWAYS(p) ){ - if( p->iCell>=NCELL(pNode) ){ - rc = SQLITE_ABORT; - }else{ - *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); - } + if( rc==SQLITE_OK && p ){ + *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); } return rc; } -/* +/* ** Rtree virtual table module xColumn method. */ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ Rtree *pRtree = (Rtree *)cur->pVtab; RtreeCursor *pCsr = (RtreeCursor *)cur; @@ -213798,15 +166770,14 @@ RtreeCoord c; int rc = SQLITE_OK; RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); if( rc ) return rc; - if( NEVER(p==0) ) return SQLITE_OK; - if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT; + if( p==0 ) return SQLITE_OK; if( i==0 ){ sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); - }else if( i<=pRtree->nDim2 ){ + }else{ nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); }else @@ -213813,36 +166784,16 @@ #endif { assert( pRtree->eCoordType==RTREE_COORD_INT32 ); sqlite3_result_int(ctx, c.i); } - }else{ - if( !pCsr->bAuxValid ){ - if( pCsr->pReadAux==0 ){ - rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, - &pCsr->pReadAux, 0); - if( rc ) return rc; - } - sqlite3_bind_int64(pCsr->pReadAux, 1, - nodeGetRowid(pRtree, pNode, p->iCell)); - rc = sqlite3_step(pCsr->pReadAux); - if( rc==SQLITE_ROW ){ - pCsr->bAuxValid = 1; - }else{ - sqlite3_reset(pCsr->pReadAux); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - return rc; - } - } - sqlite3_result_value(ctx, - sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); } return SQLITE_OK; } -/* -** Use nodeAcquire() to obtain the leaf node containing the record with +/* +** Use nodeAcquire() to obtain the leaf node containing the record with ** rowid iRowid. If successful, set *ppLeaf to point to the node and ** return SQLITE_OK. If there is no such record in the table, set ** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf ** to zero and return an SQLite error code. */ @@ -213871,21 +166822,37 @@ ** as the second argument for a MATCH constraint. The value passed as the ** first argument to this function is the right-hand operand to the MATCH ** operator. */ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ - RtreeMatchArg *pBlob, *pSrc; /* BLOB returned by geometry function */ + RtreeMatchArg *pBlob; /* BLOB returned by geometry function */ sqlite3_rtree_query_info *pInfo; /* Callback information */ + int nBlob; /* Size of the geometry function blob */ + int nExpected; /* Expected size of the BLOB */ - pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg"); - if( pSrc==0 ) return SQLITE_ERROR; - pInfo = (sqlite3_rtree_query_info*) - sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize ); + /* Check that value is actually a blob. */ + if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; + + /* Check that the blob is roughly the right size. */ + nBlob = sqlite3_value_bytes(pValue); + if( nBlob<(int)sizeof(RtreeMatchArg) ){ + return SQLITE_ERROR; + } + + pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); if( !pInfo ) return SQLITE_NOMEM; memset(pInfo, 0, sizeof(*pInfo)); pBlob = (RtreeMatchArg*)&pInfo[1]; - memcpy(pBlob, pSrc, pSrc->iSize); + + memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); + nExpected = (int)(sizeof(RtreeMatchArg) + + pBlob->nParam*sizeof(sqlite3_value*) + + (pBlob->nParam-1)*sizeof(RtreeDValue)); + if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ + sqlite3_free(pInfo); + return SQLITE_ERROR; + } pInfo->pContext = pBlob->cb.pContext; pInfo->nParam = pBlob->nParam; pInfo->aParam = pBlob->aParam; pInfo->apSqlParam = pBlob->apSqlParam; @@ -213897,17 +166864,15 @@ } pCons->pInfo = pInfo; return SQLITE_OK; } -SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); - -/* +/* ** Rtree virtual table module xFilter method. */ static int rtreeFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; @@ -213917,29 +166882,23 @@ int iCell = 0; rtreeReference(pRtree); /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ - resetCursor(pCsr); + freeCursorConstraints(pCsr); + sqlite3_free(pCsr->aPoint); + memset(pCsr, 0, sizeof(RtreeCursor)); + pCsr->base.pVtab = (sqlite3_vtab*)pRtree; pCsr->iStrategy = idxNum; if( idxNum==1 ){ /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ RtreeSearchPoint *p; /* Search point for the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); i64 iNode = 0; - int eType = sqlite3_value_numeric_type(argv[0]); - if( eType==SQLITE_INTEGER - || (eType==SQLITE_FLOAT - && 0==sqlite3IntFloatCompare(iRowid,sqlite3_value_double(argv[0]))) - ){ - rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); - }else{ - rc = SQLITE_OK; - pLeaf = 0; - } + rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); if( rc==SQLITE_OK && pLeaf!=0 ){ p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); assert( p!=0 ); /* Always returns pCsr->sPoint */ pCsr->aNode[0] = pLeaf; p->id = iNode; @@ -213949,16 +166908,16 @@ RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); }else{ pCsr->atEOF = 1; } }else{ - /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array - ** with the configured constraints. + /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array + ** with the configured constraints. */ rc = nodeAcquire(pRtree, 1, 0, &pRoot); if( rc==SQLITE_OK && argc>0 ){ - pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc); + pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); pCsr->nConstraint = argc; if( !pCsr->aConstraint ){ rc = SQLITE_NOMEM; }else{ memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); @@ -213965,11 +166924,10 @@ memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); assert( (idxStr==0 && argc==0) || (idxStr && (int)strlen(idxStr)==argc*2) ); for(ii=0; iiaConstraint[ii]; - int eType = sqlite3_value_numeric_type(argv[ii]); p->op = idxStr[ii*2]; p->iCoord = idxStr[ii*2+1]-'0'; if( p->op>=RTREE_MATCH ){ /* A MATCH operator. The right-hand-side must be a blob that ** can be cast into an RtreeMatchArg object. One created using @@ -213980,49 +166938,24 @@ break; } p->pInfo->nCoord = pRtree->nDim2; p->pInfo->anQueue = pCsr->anQueue; p->pInfo->mxLevel = pRtree->iDepth + 1; - }else if( eType==SQLITE_INTEGER ){ - sqlite3_int64 iVal = sqlite3_value_int64(argv[ii]); -#ifdef SQLITE_RTREE_INT_ONLY - p->u.rValue = iVal; -#else - p->u.rValue = (double)iVal; - if( iVal>=((sqlite3_int64)1)<<48 - || iVal<=-(((sqlite3_int64)1)<<48) - ){ - if( p->op==RTREE_LT ) p->op = RTREE_LE; - if( p->op==RTREE_GT ) p->op = RTREE_GE; - } -#endif - }else if( eType==SQLITE_FLOAT ){ + }else{ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); #else p->u.rValue = sqlite3_value_double(argv[ii]); #endif - }else{ - p->u.rValue = RTREE_ZERO; - if( eType==SQLITE_NULL ){ - p->op = RTREE_FALSE; - }else if( p->op==RTREE_LT || p->op==RTREE_LE ){ - p->op = RTREE_TRUE; - }else{ - p->op = RTREE_FALSE; - } } } } } if( rc==SQLITE_OK ){ RtreeSearchPoint *pNew; - assert( pCsr->bPoint==0 ); /* Due to the resetCursor() call above */ pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); - if( NEVER(pNew==0) ){ /* Because pCsr->bPoint was FALSE */ - return SQLITE_NOMEM; - } + if( pNew==0 ) return SQLITE_NOMEM; pNew->id = 1; pNew->iCell = 0; pNew->eWithin = PARTLY_WITHIN; assert( pCsr->bPoint==1 ); pCsr->aNode[0] = pRoot; @@ -214037,22 +166970,22 @@ return rc; } /* ** Rtree virtual table module xBestIndex method. There are three -** table scan strategies to choose from (in order from most to +** table scan strategies to choose from (in order from most to ** least desirable): ** ** idxNum idxStr Strategy ** ------------------------------------------------ ** 1 Unused Direct lookup by rowid. ** 2 See below R-tree query or full-table scan. ** ------------------------------------------------ ** ** If strategy 1 is used, then idxStr is not meaningful. If strategy -** 2 is used, idxStr is formatted to contain 2 bytes for each -** constraint used. The first two bytes of idxStr correspond to +** 2 is used, idxStr is formatted to contain 2 bytes for each +** constraint used. The first two bytes of idxStr correspond to ** the constraint in sqlite3_index_info.aConstraintUsage[] with ** (argvIndex==1) etc. ** ** The first of each pair of bytes in idxStr identifies the constraint ** operator as follows: @@ -214094,12 +167027,12 @@ assert( pIdxInfo->idxStr==0 ); for(ii=0; iinConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - if( bMatch==0 && p->usable - && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ + if( bMatch==0 && p->usable + && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ /* We have an equality constraint on the rowid. Use strategy 1. */ int jj; for(jj=0; jjaConstraintUsage[jj].argvIndex = 0; @@ -214108,53 +167041,44 @@ pIdxInfo->idxNum = 1; pIdxInfo->aConstraintUsage[ii].argvIndex = 1; pIdxInfo->aConstraintUsage[jj].omit = 1; /* This strategy involves a two rowid lookups on an B-Tree structures - ** and then a linear search of an R-Tree node. This should be - ** considered almost as quick as a direct rowid lookup (for which + ** and then a linear search of an R-Tree node. This should be + ** considered almost as quick as a direct rowid lookup (for which ** sqlite uses an internal cost of 0.0). It is expected to return ** a single row. - */ + */ pIdxInfo->estimatedCost = 30.0; pIdxInfo->estimatedRows = 1; - pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; return SQLITE_OK; } - if( p->usable - && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2) - || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) - ){ + if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ u8 op; - u8 doOmit = 1; switch( p->op ){ - case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; doOmit = 0; break; - case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; doOmit = 0; break; - case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; - case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; doOmit = 0; break; - case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; - case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break; - default: op = 0; break; - } - if( op ){ - zIdxStr[iIdx++] = op; - zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0'); - pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); - pIdxInfo->aConstraintUsage[ii].omit = doOmit; - } + case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; + case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; + case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; + case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; + case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; + default: + assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); + op = RTREE_MATCH; + break; + } + zIdxStr[iIdx++] = op; + zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0'); + pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); + pIdxInfo->aConstraintUsage[ii].omit = 1; } } pIdxInfo->idxNum = 2; pIdxInfo->needToFreeIdxStr = 1; - if( iIdx>0 ){ - pIdxInfo->idxStr = sqlite3_malloc( iIdx+1 ); - if( pIdxInfo->idxStr==0 ){ - return SQLITE_NOMEM; - } - memcpy(pIdxInfo->idxStr, zIdxStr, iIdx+1); + if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ + return SQLITE_NOMEM; } nRow = pRtree->nRowEst >> (iIdx/2); pIdxInfo->estimatedCost = (double)6.0 * (double)nRow; pIdxInfo->estimatedRows = nRow; @@ -214179,15 +167103,15 @@ } }else #endif { switch( pRtree->nDim ){ - case 5: area = (i64)p->aCoord[9].i - (i64)p->aCoord[8].i; - case 4: area *= (i64)p->aCoord[7].i - (i64)p->aCoord[6].i; - case 3: area *= (i64)p->aCoord[5].i - (i64)p->aCoord[4].i; - case 2: area *= (i64)p->aCoord[3].i - (i64)p->aCoord[2].i; - default: area *= (i64)p->aCoord[1].i - (i64)p->aCoord[0].i; + case 5: area = p->aCoord[9].i - p->aCoord[8].i; + case 4: area *= p->aCoord[7].i - p->aCoord[6].i; + case 3: area *= p->aCoord[5].i - p->aCoord[4].i; + case 2: area *= p->aCoord[3].i - p->aCoord[2].i; + default: area *= p->aCoord[1].i - p->aCoord[0].i; } } return area; } @@ -214229,30 +167153,39 @@ ** Return true if the area covered by p2 is a subset of the area covered ** by p1. False otherwise. */ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ int ii; - if( pRtree->eCoordType==RTREE_COORD_INT32 ){ - for(ii=0; iinDim2; ii+=2){ - RtreeCoord *a1 = &p1->aCoord[ii]; - RtreeCoord *a2 = &p2->aCoord[ii]; - if( a2[0].ia1[1].i ) return 0; - } - }else{ - for(ii=0; iinDim2; ii+=2){ - RtreeCoord *a1 = &p1->aCoord[ii]; - RtreeCoord *a2 = &p2->aCoord[ii]; - if( a2[0].fa1[1].f ) return 0; + int isInt = (pRtree->eCoordType==RTREE_COORD_INT32); + for(ii=0; iinDim2; ii+=2){ + RtreeCoord *a1 = &p1->aCoord[ii]; + RtreeCoord *a2 = &p2->aCoord[ii]; + if( (!isInt && (a2[0].fa1[1].f)) + || ( isInt && (a2[0].ia1[1].i)) + ){ + return 0; } } return 1; } + +/* +** Return the amount cell p would grow by if it were unioned with pCell. +*/ +static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ + RtreeDValue area; + RtreeCell cell; + memcpy(&cell, p, sizeof(RtreeCell)); + area = cellArea(pRtree, &cell); + cellUnion(pRtree, &cell, pCell); + return (cellArea(pRtree, &cell)-area); +} static RtreeDValue cellOverlap( - Rtree *pRtree, - RtreeCell *p, - RtreeCell *aCell, + Rtree *pRtree, + RtreeCell *p, + RtreeCell *aCell, int nCell ){ int ii; RtreeDValue overlap = RTREE_ZERO; for(ii=0; iiiDepth-iHeight); ii++){ int iCell; sqlite3_int64 iBest = 0; - int bFound = 0; - RtreeDValue fMinGrowth = RTREE_ZERO; - RtreeDValue fMinArea = RTREE_ZERO; - int nCell = NCELL(pNode); - RtreeNode *pChild = 0; - - /* First check to see if there is are any cells in pNode that completely - ** contains pCell. If two or more cells in pNode completely contain pCell - ** then pick the smallest. - */ - for(iCell=0; iCellpParent ){ RtreeNode *pParent = p->pParent; RtreeCell cell; int iCell; - cnt++; - if( NEVER(cnt>100) ){ - RTREE_IS_CORRUPT(pRtree); - return SQLITE_CORRUPT_VTAB; - } - rc = nodeParentIndex(pRtree, p, &iCell); - if( NEVER(rc!=SQLITE_OK) ){ - RTREE_IS_CORRUPT(pRtree); + if( nodeParentIndex(pRtree, p, &iCell) ){ return SQLITE_CORRUPT_VTAB; } nodeGetCell(pRtree, pParent, iCell, &cell); if( !cellContains(pRtree, &cell, pCell) ){ cellUnion(pRtree, &cell, pCell); nodeOverwriteCell(pRtree, pParent, &cell, iCell); } - + p = pParent; } return SQLITE_OK; } @@ -214409,14 +167319,85 @@ } static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int); +/* +** Arguments aIdx, aDistance and aSpare all point to arrays of size +** nIdx. The aIdx array contains the set of integers from 0 to +** (nIdx-1) in no particular order. This function sorts the values +** in aIdx according to the indexed values in aDistance. For +** example, assuming the inputs: +** +** aIdx = { 0, 1, 2, 3 } +** aDistance = { 5.0, 2.0, 7.0, 6.0 } +** +** this function sets the aIdx array to contain: +** +** aIdx = { 0, 1, 2, 3 } +** +** The aSpare array is used as temporary working space by the +** sorting algorithm. +*/ +static void SortByDistance( + int *aIdx, + int nIdx, + RtreeDValue *aDistance, + int *aSpare +){ + if( nIdx>1 ){ + int iLeft = 0; + int iRight = 0; + + int nLeft = nIdx/2; + int nRight = nIdx-nLeft; + int *aLeft = aIdx; + int *aRight = &aIdx[nLeft]; + + SortByDistance(aLeft, nLeft, aDistance, aSpare); + SortByDistance(aRight, nRight, aDistance, aSpare); + + memcpy(aSpare, aLeft, sizeof(int)*nLeft); + aLeft = aSpare; + + while( iLeft1 ){ int iLeft = 0; @@ -214497,13 +167478,13 @@ int iBestDim = 0; int iBestSplit = 0; RtreeDValue fBestMargin = RTREE_ZERO; - sqlite3_int64 nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int)); + int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int)); - aaSorted = (int **)sqlite3_malloc64(nByte); + aaSorted = (int **)sqlite3_malloc(nByte); if( !aaSorted ){ return SQLITE_NOMEM; } aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell]; @@ -214523,12 +167504,12 @@ RtreeDValue fBestArea = RTREE_ZERO; int iBestLeft = 0; int nLeft; for( - nLeft=RTREE_MINCELLS(pRtree); - nLeft<=(nCell-RTREE_MINCELLS(pRtree)); + nLeft=RTREE_MINCELLS(pRtree); + nLeft<=(nCell-RTREE_MINCELLS(pRtree)); nLeft++ ){ RtreeCell left; RtreeCell right; int kk; @@ -214579,30 +167560,25 @@ return SQLITE_OK; } static int updateMapping( - Rtree *pRtree, - i64 iRowid, - RtreeNode *pNode, + Rtree *pRtree, + i64 iRowid, + RtreeNode *pNode, int iHeight ){ int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64); xSetMapping = ((iHeight==0)?rowidWrite:parentWrite); if( iHeight>0 ){ RtreeNode *pChild = nodeHashLookup(pRtree, iRowid); - RtreeNode *p; - for(p=pNode; p; p=p->pParent){ - if( p==pChild ) return SQLITE_CORRUPT_VTAB; - } if( pChild ){ nodeRelease(pRtree, pChild->pParent); nodeReference(pNode); pChild->pParent = pNode; } } - if( NEVER(pNode==0) ) return SQLITE_ERROR; return xSetMapping(pRtree, iRowid, pNode->iNode); } static int SplitNode( Rtree *pRtree, @@ -214622,14 +167598,14 @@ RtreeNode *pRight = 0; RtreeCell leftbbox; RtreeCell rightbbox; - /* Allocate an array and populate it with a copy of pCell and + /* Allocate an array and populate it with a copy of pCell and ** all cells from node pLeft. Then zero the original node. */ - aCell = sqlite3_malloc64((sizeof(RtreeCell)+sizeof(int))*(nCell+1)); + aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1)); if( !aCell ){ rc = SQLITE_NOMEM; goto splitnode_out; } aiUsed = (int *)&aCell[nCell+1]; @@ -214648,11 +167624,11 @@ pNode->isDirty = 1; writeInt16(pNode->zData, pRtree->iDepth); }else{ pLeft = pNode; pRight = nodeNew(pRtree, pLeft->pParent); - pLeft->nRef++; + nodeReference(pLeft); } if( !pLeft || !pRight ){ rc = SQLITE_NOMEM; goto splitnode_out; @@ -214688,16 +167664,15 @@ } }else{ RtreeNode *pParent = pLeft->pParent; int iCell; rc = nodeParentIndex(pRtree, pLeft, &iCell); - if( ALWAYS(rc==SQLITE_OK) ){ + if( rc==SQLITE_OK ){ nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); rc = AdjustTree(pRtree, pParent, &leftbbox); - assert( rc==SQLITE_OK ); } - if( NEVER(rc!=SQLITE_OK) ){ + if( rc!=SQLITE_OK ){ goto splitnode_out; } } if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){ goto splitnode_out; @@ -214740,18 +167715,18 @@ sqlite3_free(aCell); return rc; } /* -** If node pLeaf is not the root of the r-tree and its pParent pointer is +** If node pLeaf is not the root of the r-tree and its pParent pointer is ** still NULL, load all ancestor nodes of pLeaf into memory and populate ** the pLeaf->pParent chain all the way up to the root node. ** ** This operation is required when a row is deleted (or updated - an update ** is implemented as a delete followed by an insert). SQLite provides the ** rowid of the row to delete, which can be used to find the leaf on which -** the entry resides (argument pLeaf). Once the leaf is located, this +** the entry resides (argument pLeaf). Once the leaf is located, this ** function is called to determine its ancestry. */ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){ int rc = SQLITE_OK; RtreeNode *pChild = pLeaf; @@ -214768,20 +167743,17 @@ ** want to do this as it leads to a memory leak when trying to delete ** the referenced counted node structures. */ iNode = sqlite3_column_int64(pRtree->pReadParent, 0); for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent); - if( pTest==0 ){ + if( !pTest ){ rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent); } } rc = sqlite3_reset(pRtree->pReadParent); if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK && !pChild->pParent ){ - RTREE_IS_CORRUPT(pRtree); - rc = SQLITE_CORRUPT_VTAB; - } + if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB; pChild = pChild->pParent; } return rc; } @@ -214799,11 +167771,10 @@ rc = nodeParentIndex(pRtree, pNode, &iCell); if( rc==SQLITE_OK ){ pParent = pNode->pParent; pNode->pParent = 0; rc = deleteCell(pRtree, pParent, iCell, iHeight+1); - testcase( rc!=SQLITE_OK ); } rc2 = nodeRelease(pRtree, pParent); if( rc==SQLITE_OK ){ rc = rc2; } @@ -214822,11 +167793,11 @@ sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode); sqlite3_step(pRtree->pDeleteParent); if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){ return rc; } - + /* Remove the node from the in-memory hash table and link it into ** the Rtree.pDeleted list. Its contents will be re-inserted later on. */ nodeHashDelete(pRtree, pNode); pNode->iNode = iHeight; @@ -214837,13 +167808,13 @@ return SQLITE_OK; } static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ RtreeNode *pParent = pNode->pParent; - int rc = SQLITE_OK; + int rc = SQLITE_OK; if( pParent ){ - int ii; + int ii; int nCell = NCELL(pNode); RtreeCell box; /* Bounding box for pNode */ nodeGetCell(pRtree, pNode, 0, &box); for(ii=1; iinDim; iDim++){ + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); + } + } + for(iDim=0; iDimnDim; iDim++){ + aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); + } + + for(ii=0; iinDim; iDim++){ + RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - + DCOORD(aCell[ii].aCoord[iDim*2])); + aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); + } + } + + SortByDistance(aOrder, nCell, aDistance, aSpare); + nodeZero(pRtree, pNode); + + for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){ + RtreeCell *p = &aCell[aOrder[ii]]; + nodeInsertCell(pRtree, pNode, p); + if( p->iRowid==pCell->iRowid ){ + if( iHeight==0 ){ + rc = rowidWrite(pRtree, p->iRowid, pNode->iNode); + }else{ + rc = parentWrite(pRtree, p->iRowid, pNode->iNode); + } + } + } + if( rc==SQLITE_OK ){ + rc = fixBoundingBox(pRtree, pNode); + } + for(; rc==SQLITE_OK && iiiNode currently contains + ** the height of the sub-tree headed by the cell. + */ + RtreeNode *pInsert; + RtreeCell *p = &aCell[aOrder[ii]]; + rc = ChooseLeaf(pRtree, p, iHeight, &pInsert); + if( rc==SQLITE_OK ){ + int rc2; + rc = rtreeInsertCell(pRtree, pInsert, p, iHeight); + rc2 = nodeRelease(pRtree, pInsert); + if( rc==SQLITE_OK ){ + rc = rc2; + } + } + } + + sqlite3_free(aCell); + return rc; +} /* -** Insert cell pCell into node pNode. Node pNode is the head of a +** Insert cell pCell into node pNode. Node pNode is the head of a ** subtree iHeight high (leaf nodes have iHeight==0). */ static int rtreeInsertCell( Rtree *pRtree, RtreeNode *pNode, @@ -214913,14 +167985,19 @@ nodeReference(pNode); pChild->pParent = pNode; } } if( nodeInsertCell(pRtree, pNode, pCell) ){ - rc = SplitNode(pRtree, pNode, pCell, iHeight); + if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ + rc = SplitNode(pRtree, pNode, pCell, iHeight); + }else{ + pRtree->iReinsertHeight = iHeight; + rc = Reinsert(pRtree, pNode, pCell, iHeight); + } }else{ rc = AdjustTree(pRtree, pNode, pCell); - if( ALWAYS(rc==SQLITE_OK) ){ + if( rc==SQLITE_OK ){ if( iHeight==0 ){ rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); }else{ rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); } @@ -214956,11 +168033,11 @@ } /* ** Select a currently unused rowid for a new r-tree record. */ -static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){ +static int newRowid(Rtree *pRtree, i64 *piRowid){ int rc; sqlite3_bind_null(pRtree->pWriteRowid, 1); sqlite3_bind_null(pRtree->pWriteRowid, 2); sqlite3_step(pRtree->pWriteRowid); rc = sqlite3_reset(pRtree->pWriteRowid); @@ -214973,29 +168050,25 @@ */ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ int rc; /* Return code */ RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ int iCell; /* Index of iDelete cell in pLeaf */ - RtreeNode *pRoot = 0; /* Root node of rtree structure */ + RtreeNode *pRoot; /* Root node of rtree structure */ /* Obtain a reference to the root node to initialize Rtree.iDepth */ rc = nodeAcquire(pRtree, 1, 0, &pRoot); - /* Obtain a reference to the leaf node that contains the entry - ** about to be deleted. + /* Obtain a reference to the leaf node that contains the entry + ** about to be deleted. */ if( rc==SQLITE_OK ){ rc = findLeafNode(pRtree, iDelete, &pLeaf, 0); } -#ifdef CORRUPT_DB - assert( pLeaf!=0 || rc!=SQLITE_OK || CORRUPT_DB ); -#endif - /* Delete the cell in question from the leaf node. */ - if( rc==SQLITE_OK && pLeaf ){ + if( rc==SQLITE_OK ){ int rc2; rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell); if( rc==SQLITE_OK ){ rc = deleteCell(pRtree, pLeaf, iCell, 0); } @@ -215011,22 +168084,22 @@ sqlite3_step(pRtree->pDeleteRowid); rc = sqlite3_reset(pRtree->pDeleteRowid); } /* Check if the root node now has exactly one child. If so, remove - ** it, schedule the contents of the child for reinsertion and + ** it, schedule the contents of the child for reinsertion and ** reduce the tree height by one. ** ** This is equivalent to copying the contents of the child into - ** the root node (the operation that Gutman's paper says to perform + ** the root node (the operation that Gutman's paper says to perform ** in this scenario). */ if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ int rc2; - RtreeNode *pChild = 0; + RtreeNode *pChild; i64 iChild = nodeGetRowid(pRtree, pRoot, 0); - rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); /* tag-20210916a */ + rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); if( rc==SQLITE_OK ){ rc = removeNode(pRtree, pChild, pRtree->iDepth-1); } rc2 = nodeRelease(pRtree, pChild); if( rc==SQLITE_OK ) rc = rc2; @@ -215041,11 +168114,10 @@ for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){ if( rc==SQLITE_OK ){ rc = reinsertNodeContent(pRtree, pLeaf); } pRtree->pDeleted = pLeaf->pNext; - pRtree->nNodeRef--; sqlite3_free(pLeaf); } /* Release the reference to the root node. */ if( rc==SQLITE_OK ){ @@ -215085,12 +168157,12 @@ return f; } #endif /* !defined(SQLITE_RTREE_INT_ONLY) */ /* -** A constraint has failed while inserting a row into an rtree table. -** Assuming no OOM error occurs, this function sets the error message +** A constraint has failed while inserting a row into an rtree table. +** Assuming no OOM error occurs, this function sets the error message ** (at pRtree->base.zErrMsg) to an appropriate value and returns ** SQLITE_CONSTRAINT. ** ** Parameter iCol is the index of the leftmost column involved in the ** constraint failure. If it is 0, then the constraint that failed is @@ -215099,11 +168171,11 @@ ** ** If an OOM occurs, SQLITE_NOMEM is returned instead of SQLITE_CONSTRAINT. */ static int rtreeConstraintError(Rtree *pRtree, int iCol){ sqlite3_stmt *pStmt = 0; - char *zSql; + char *zSql; int rc; assert( iCol==0 || iCol%2 ); zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", pRtree->zDb, pRtree->zName); if( zSql ){ @@ -215136,30 +168208,24 @@ /* ** The xUpdate method for rtree module virtual tables. */ static int rtreeUpdate( - sqlite3_vtab *pVtab, - int nData, - sqlite3_value **aData, + sqlite3_vtab *pVtab, + int nData, + sqlite3_value **azData, sqlite_int64 *pRowid ){ Rtree *pRtree = (Rtree *)pVtab; int rc = SQLITE_OK; RtreeCell cell; /* New cell to insert if nData>1 */ int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ - if( pRtree->nNodeRef ){ - /* Unable to write to the btree while another cursor is reading from it, - ** since the write might do a rebalance which would disrupt the read - ** cursor. */ - return SQLITE_LOCKED_VTAB; - } rtreeReference(pRtree); assert(nData>=1); - memset(&cell, 0, sizeof(cell)); + cell.iRowid = 0; /* Used only to suppress a compiler warning */ /* Constraint handling. A write operation on an r-tree table may return ** SQLITE_CONSTRAINT for two reasons: ** ** 1. A duplicate rowid value, or @@ -215170,51 +168236,50 @@ ** case, SQLITE_CONSTRAINT must be returned regardless of the ** conflict-handling mode specified by the user. */ if( nData>1 ){ int ii; - int nn = nData - 4; - if( nn > pRtree->nDim2 ) nn = pRtree->nDim2; - /* Populate the cell.aCoord[] array. The first coordinate is aData[3]. + /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. ** ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared ** with "column" that are interpreted as table constraints. ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5)); ** This problem was discovered after years of use, so we silently ignore ** these kinds of misdeclared tables to avoid breaking any legacy. */ + assert( nData<=(pRtree->nDim2 + 3) ); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; iicell.aCoord[ii+1].f ){ rc = rtreeConstraintError(pRtree, ii+1); goto constraint; } } }else #endif { - for(ii=0; iicell.aCoord[ii+1].i ){ rc = rtreeConstraintError(pRtree, ii+1); goto constraint; } } } - /* If a rowid value was supplied, check if it is already present in + /* If a rowid value was supplied, check if it is already present in ** the table. If so, the constraint has failed. */ - if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ - cell.iRowid = sqlite3_value_int64(aData[2]); - if( sqlite3_value_type(aData[0])==SQLITE_NULL - || sqlite3_value_int64(aData[0])!=cell.iRowid + if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){ + cell.iRowid = sqlite3_value_int64(azData[2]); + if( sqlite3_value_type(azData[0])==SQLITE_NULL + || sqlite3_value_int64(azData[0])!=cell.iRowid ){ int steprc; sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); steprc = sqlite3_step(pRtree->pReadRowid); rc = sqlite3_reset(pRtree->pReadRowid); @@ -215229,53 +168294,44 @@ } bHaveRowid = 1; } } - /* If aData[0] is not an SQL NULL value, it is the rowid of a + /* If azData[0] is not an SQL NULL value, it is the rowid of a ** record to delete from the r-tree table. The following block does ** just that. */ - if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ - rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); + if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ + rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0])); } - /* If the aData[] array contains more than one element, elements - ** (aData[2]..aData[argc-1]) contain a new record to insert into + /* If the azData[] array contains more than one element, elements + ** (azData[2]..azData[argc-1]) contain a new record to insert into ** the r-tree structure. */ if( rc==SQLITE_OK && nData>1 ){ /* Insert the new record into the r-tree */ RtreeNode *pLeaf = 0; /* Figure out the rowid of the new row. */ if( bHaveRowid==0 ){ - rc = rtreeNewRowid(pRtree, &cell.iRowid); + rc = newRowid(pRtree, &cell.iRowid); } *pRowid = cell.iRowid; if( rc==SQLITE_OK ){ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); } if( rc==SQLITE_OK ){ int rc2; + pRtree->iReinsertHeight = -1; rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); rc2 = nodeRelease(pRtree, pLeaf); if( rc==SQLITE_OK ){ rc = rc2; } } - if( rc==SQLITE_OK && pRtree->nAux ){ - sqlite3_stmt *pUp = pRtree->pWriteAux; - int jj; - sqlite3_bind_int64(pUp, 1, *pRowid); - for(jj=0; jjnAux; jj++){ - sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); - } - sqlite3_step(pUp); - rc = sqlite3_reset(pUp); - } } constraint: rtreeRelease(pRtree); return rc; @@ -215285,11 +168341,11 @@ ** Called when a transaction starts. */ static int rtreeBeginTransaction(sqlite3_vtab *pVtab){ Rtree *pRtree = (Rtree *)pVtab; assert( pRtree->inWrTrans==0 ); - pRtree->inWrTrans = 1; + pRtree->inWrTrans++; return SQLITE_OK; } /* ** Called when a transaction completes (either by COMMIT or ROLLBACK). @@ -215299,13 +168355,10 @@ Rtree *pRtree = (Rtree *)pVtab; pRtree->inWrTrans = 0; nodeBlobReset(pRtree); return SQLITE_OK; } -static int rtreeRollback(sqlite3_vtab *pVtab){ - return rtreeEndTransaction(pVtab); -} /* ** The xRename method for rtree module virtual tables. */ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){ @@ -215313,12 +168366,12 @@ int rc = SQLITE_NOMEM; char *zSql = sqlite3_mprintf( "ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";" "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";" "ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";" - , pRtree->zDb, pRtree->zName, zNewName - , pRtree->zDb, pRtree->zName, zNewName + , pRtree->zDb, pRtree->zName, zNewName + , pRtree->zDb, pRtree->zName, zNewName , pRtree->zDb, pRtree->zName, zNewName ); if( zSql ){ nodeBlobReset(pRtree); rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0); @@ -215329,12 +168382,12 @@ /* ** The xSavepoint method. ** ** This module does not need to do anything to support savepoints. However, -** it uses this hook to close any open blob handle. This is done because a -** DROP TABLE command - which fortunately always opens a savepoint - cannot +** it uses this hook to close any open blob handle. This is done because a +** DROP TABLE command - which fortunately always opens a savepoint - cannot ** succeed if there are any open blob handles. i.e. if the blob handle were ** not closed here, the following would fail: ** ** BEGIN; ** INSERT INTO rtree... @@ -215341,11 +168394,11 @@ ** DROP TABLE ; -- Would fail with SQLITE_LOCKED ** COMMIT; */ static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ Rtree *pRtree = (Rtree *)pVtab; - u8 iwt = pRtree->inWrTrans; + int iwt = pRtree->inWrTrans; UNUSED_PARAMETER(iSavepoint); pRtree->inWrTrans = 0; nodeBlobReset(pRtree); pRtree->inWrTrans = iwt; return SQLITE_OK; @@ -215359,11 +168412,11 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){ const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'"; char *zSql; sqlite3_stmt *p; int rc; - i64 nRow = RTREE_MIN_ROWEST; + i64 nRow = 0; rc = sqlite3_table_column_metadata( db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 ); if( rc!=SQLITE_OK ){ @@ -215376,38 +168429,29 @@ }else{ rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0); if( rc==SQLITE_OK ){ if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0); rc = sqlite3_finalize(p); + }else if( rc!=SQLITE_NOMEM ){ + rc = SQLITE_OK; + } + + if( rc==SQLITE_OK ){ + if( nRow==0 ){ + pRtree->nRowEst = RTREE_DEFAULT_ROWEST; + }else{ + pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST); + } } sqlite3_free(zSql); } - pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST); + return rc; } - -/* -** Return true if zName is the extension on one of the shadow tables used -** by this module. -*/ -static int rtreeShadowName(const char *zName){ - static const char *azName[] = { - "node", "parent", "rowid" - }; - unsigned int i; - for(i=0; idb = db; if( isCreate ){ - char *zCreate; - sqlite3_str *p = sqlite3_str_new(db); - int ii; - sqlite3_str_appendf(p, - "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno", - zDb, zPrefix); - for(ii=0; iinAux; ii++){ - sqlite3_str_appendf(p,",a%d",ii); - } - sqlite3_str_appendf(p, - ");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);", - zDb, zPrefix); - sqlite3_str_appendf(p, - "CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);", - zDb, zPrefix); - sqlite3_str_appendf(p, - "INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))", - zDb, zPrefix, pRtree->iNodeSize); - zCreate = sqlite3_str_finish(p); + char *zCreate = sqlite3_mprintf( +"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" +"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" +"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY," + " parentnode INTEGER);" +"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", + zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize + ); if( !zCreate ){ return SQLITE_NOMEM; } rc = sqlite3_exec(db, zCreate, 0, 0, 0); sqlite3_free(zCreate); @@ -215502,59 +168532,18 @@ appStmt[6] = &pRtree->pWriteParent; appStmt[7] = &pRtree->pDeleteParent; rc = rtreeQueryStat1(db, pRtree); for(i=0; inAux==0 ){ - zFormat = azSql[i]; - }else { - /* An UPSERT is very slightly slower than REPLACE, but it is needed - ** if there are auxiliary columns */ - zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)" - "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno"; - } - zSql = sqlite3_mprintf(zFormat, zDb, zPrefix); + char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix); if( zSql ){ - rc = sqlite3_prepare_v3(db, zSql, -1, f, appStmt[i], 0); - }else{ - rc = SQLITE_NOMEM; - } - sqlite3_free(zSql); - } - if( pRtree->nAux && rc!=SQLITE_NOMEM ){ - pRtree->zReadAuxSql = sqlite3_mprintf( - "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1", - zDb, zPrefix); - if( pRtree->zReadAuxSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - sqlite3_str *p = sqlite3_str_new(db); - int ii; - char *zSql; - sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix); - for(ii=0; iinAux; ii++){ - if( ii ) sqlite3_str_append(p, ",", 1); -#ifdef SQLITE_ENABLE_GEOPOLY - if( iinAuxNotNull ){ - sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii); - }else -#endif - { - sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); - } - } - sqlite3_str_appendf(p, " WHERE rowid=?1"); - zSql = sqlite3_str_finish(p); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v3(db, zSql, -1, f, &pRtree->pWriteAux, 0); - sqlite3_free(zSql); - } - } + rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + appStmt[i], 0); + }else{ + rc = SQLITE_NOMEM; + } + sqlite3_free(zSql); } return rc; } @@ -215588,13 +168577,13 @@ ** ** If this function is being called as part of an xConnect(), then the rtree ** table already exists. In this case the node-size is determined by inspecting ** the root node of the tree. ** -** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. -** This ensures that each node is stored on a single database page. If the -** database page-size is so large that more than RTREE_MAXCELLS entries +** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. +** This ensures that each node is stored on a single database page. If the +** database page-size is so large that more than RTREE_MAXCELLS entries ** would fit in a single node, use a smaller node-size. */ static int getNodeSize( sqlite3 *db, /* Database handle */ Rtree *pRtree, /* Rtree handle */ @@ -215622,30 +168611,21 @@ ); rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); if( rc!=SQLITE_OK ){ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); }else if( pRtree->iNodeSize<(512-64) ){ - rc = SQLITE_CORRUPT_VTAB; - RTREE_IS_CORRUPT(pRtree); + rc = SQLITE_CORRUPT; *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"", pRtree->zName); } } sqlite3_free(zSql); return rc; } -/* -** Return the length of a token -*/ -static int rtreeTokenLength(const char *z){ - int dummy = 0; - return sqlite3GetToken((const unsigned char*)z,&dummy); -} - -/* +/* ** This function is the implementation of both the xConnect and xCreate ** methods of the r-tree virtual table. ** ** argv[0] -> module name ** argv[1] -> database name @@ -215663,119 +168643,85 @@ int rc = SQLITE_OK; Rtree *pRtree; int nDb; /* Length of string argv[1] */ int nName; /* Length of string argv[2] */ int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); - sqlite3_str *pSql; - char *zSql; - int ii = 4; - int iErr; const char *aErrMsg[] = { 0, /* 0 */ "Wrong number of columns for an rtree table", /* 1 */ "Too few columns for an rtree table", /* 2 */ - "Too many columns for an rtree table", /* 3 */ - "Auxiliary rtree columns must be last" /* 4 */ + "Too many columns for an rtree table" /* 3 */ }; - assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */ - if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){ - *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]); + int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; + if( aErrMsg[iErr] ){ + *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); return SQLITE_ERROR; } sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - /* Allocate the sqlite3_vtab structure */ nDb = (int)strlen(argv[1]); nName = (int)strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); + pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); if( !pRtree ){ return SQLITE_NOMEM; } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName*2+8); + memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); pRtree->nBusy = 1; pRtree->base.pModule = &rtreeModule; pRtree->zDb = (char *)&pRtree[1]; pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->zNodeName = &pRtree->zName[nName+1]; + pRtree->nDim = (u8)((argc-4)/2); + pRtree->nDim2 = pRtree->nDim*2; + pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; pRtree->eCoordType = (u8)eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); - memcpy(pRtree->zNodeName, argv[2], nName); - memcpy(&pRtree->zNodeName[nName], "_node", 6); + /* Figure out the node size to use. */ + rc = getNodeSize(db, pRtree, isCreate, pzErr); /* Create/Connect to the underlying relational database schema. If ** that is successful, call sqlite3_declare_vtab() to configure ** the r-tree table schema. */ - pSql = sqlite3_str_new(db); - sqlite3_str_appendf(pSql, "CREATE TABLE x(%.*s INT", - rtreeTokenLength(argv[3]), argv[3]); - for(ii=4; iinAux++; - sqlite3_str_appendf(pSql, ",%.*s", rtreeTokenLength(zArg+1), zArg+1); - }else if( pRtree->nAux>0 ){ - break; - }else{ - static const char *azFormat[] = {",%.*s REAL", ",%.*s INT"}; - pRtree->nDim2++; - sqlite3_str_appendf(pSql, azFormat[eCoordType], - rtreeTokenLength(zArg), zArg); - } - } - sqlite3_str_appendf(pSql, ");"); - zSql = sqlite3_str_finish(pSql); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else if( iinDim = pRtree->nDim2/2; - if( pRtree->nDim<1 ){ - iErr = 2; - }else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){ - iErr = 3; - }else if( pRtree->nDim2 % 2 ){ - iErr = 1; - }else{ - iErr = 0; - } - if( iErr ){ - *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); - goto rtreeInit_fail; - } - pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; - - /* Figure out the node size to use. */ - rc = getNodeSize(db, pRtree, isCreate, pzErr); - if( rc ) goto rtreeInit_fail; - rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); - if( rc ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - goto rtreeInit_fail; - } - - *ppVtab = (sqlite3_vtab *)pRtree; - return SQLITE_OK; - -rtreeInit_fail: - if( rc==SQLITE_OK ) rc = SQLITE_ERROR; - assert( *ppVtab==0 ); - assert( pRtree->nBusy==1 ); - rtreeRelease(pRtree); + if( rc==SQLITE_OK ){ + if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + }else{ + char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); + char *zTmp; + int ii; + for(ii=4; zSql && iinBusy==1 ); + rtreeRelease(pRtree); + } return rc; } /* @@ -215789,54 +168735,57 @@ ** ** SELECT rtreenode(2, data) FROM rt_node; ** ** The human readable string takes the form of a Tcl list with one ** entry for each cell in the r-tree node. Each entry is itself a -** list, containing the 8-byte rowid/pageno followed by the +** list, containing the 8-byte rowid/pageno followed by the ** *2 coordinates. */ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ + char *zText = 0; RtreeNode node; Rtree tree; int ii; - int nData; - int errCode; - sqlite3_str *pOut; UNUSED_PARAMETER(nArg); memset(&node, 0, sizeof(RtreeNode)); memset(&tree, 0, sizeof(Rtree)); tree.nDim = (u8)sqlite3_value_int(apArg[0]); - if( tree.nDim<1 || tree.nDim>5 ) return; tree.nDim2 = tree.nDim*2; tree.nBytesPerCell = 8 + 8 * tree.nDim; node.zData = (u8 *)sqlite3_value_blob(apArg[1]); - if( node.zData==0 ) return; - nData = sqlite3_value_bytes(apArg[1]); - if( nData<4 ) return; - if( nData0 ) sqlite3_str_append(pOut, " ", 1); - sqlite3_str_appendf(pOut, "{%lld", cell.iRowid); + sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); + nCell = (int)strlen(zCell); for(jj=0; jjrc==SQLITE_OK ) pCheck->rc = rc; -} - -/* -** The second and subsequent arguments to this function are a format string -** and printf style arguments. This function formats the string and attempts -** to compile it as an SQL statement. -** -** If successful, a pointer to the new SQL statement is returned. Otherwise, -** NULL is returned and an error code left in RtreeCheck.rc. -*/ -static sqlite3_stmt *rtreeCheckPrepare( - RtreeCheck *pCheck, /* RtreeCheck object */ - const char *zFmt, ... /* Format string and trailing args */ -){ - va_list ap; - char *z; - sqlite3_stmt *pRet = 0; - - va_start(ap, zFmt); - z = sqlite3_vmprintf(zFmt, ap); - - if( pCheck->rc==SQLITE_OK ){ - if( z==0 ){ - pCheck->rc = SQLITE_NOMEM; - }else{ - pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0); - } - } - - sqlite3_free(z); - va_end(ap); - return pRet; -} - -/* -** The second and subsequent arguments to this function are a printf() -** style format string and arguments. This function formats the string and -** appends it to the report being accumuated in pCheck. -*/ -static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){ - va_list ap; - va_start(ap, zFmt); - if( pCheck->rc==SQLITE_OK && pCheck->nErrrc = SQLITE_NOMEM; - }else{ - pCheck->zReport = sqlite3_mprintf("%z%s%z", - pCheck->zReport, (pCheck->zReport ? "\n" : ""), z - ); - if( pCheck->zReport==0 ){ - pCheck->rc = SQLITE_NOMEM; - } - } - pCheck->nErr++; - } - va_end(ap); -} - -/* -** This function is a no-op if there is already an error code stored -** in the RtreeCheck object indicated by the first argument. NULL is -** returned in this case. -** -** Otherwise, the contents of rtree table node iNode are loaded from -** the database and copied into a buffer obtained from sqlite3_malloc(). -** If no error occurs, a pointer to the buffer is returned and (*pnNode) -** is set to the size of the buffer in bytes. -** -** Or, if an error does occur, NULL is returned and an error code left -** in the RtreeCheck object. The final value of *pnNode is undefined in -** this case. -*/ -static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){ - u8 *pRet = 0; /* Return value */ - - if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){ - pCheck->pGetNode = rtreeCheckPrepare(pCheck, - "SELECT data FROM %Q.'%q_node' WHERE nodeno=?", - pCheck->zDb, pCheck->zTab - ); - } - - if( pCheck->rc==SQLITE_OK ){ - sqlite3_bind_int64(pCheck->pGetNode, 1, iNode); - if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){ - int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0); - const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0); - pRet = sqlite3_malloc64(nNode); - if( pRet==0 ){ - pCheck->rc = SQLITE_NOMEM; - }else{ - memcpy(pRet, pNode, nNode); - *pnNode = nNode; - } - } - rtreeCheckReset(pCheck, pCheck->pGetNode); - if( pCheck->rc==SQLITE_OK && pRet==0 ){ - rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode); - } - } - - return pRet; -} - -/* -** This function is used to check that the %_parent (if bLeaf==0) or %_rowid -** (if bLeaf==1) table contains a specified entry. The schemas of the -** two tables are: -** -** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) -** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) -** -** In both cases, this function checks that there exists an entry with -** IPK value iKey and the second column set to iVal. -** -*/ -static void rtreeCheckMapping( - RtreeCheck *pCheck, /* RtreeCheck object */ - int bLeaf, /* True for a leaf cell, false for interior */ - i64 iKey, /* Key for mapping */ - i64 iVal /* Expected value for mapping */ -){ - int rc; - sqlite3_stmt *pStmt; - const char *azSql[2] = { - "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1", - "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1" - }; - - assert( bLeaf==0 || bLeaf==1 ); - if( pCheck->aCheckMapping[bLeaf]==0 ){ - pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck, - azSql[bLeaf], pCheck->zDb, pCheck->zTab - ); - } - if( pCheck->rc!=SQLITE_OK ) return; - - pStmt = pCheck->aCheckMapping[bLeaf]; - sqlite3_bind_int64(pStmt, 1, iKey); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_DONE ){ - rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table", - iKey, iVal, (bLeaf ? "%_rowid" : "%_parent") - ); - }else if( rc==SQLITE_ROW ){ - i64 ii = sqlite3_column_int64(pStmt, 0); - if( ii!=iVal ){ - rtreeCheckAppendMsg(pCheck, - "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)", - iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal - ); - } - } - rtreeCheckReset(pCheck, pStmt); -} - -/* -** Argument pCell points to an array of coordinates stored on an rtree page. -** This function checks that the coordinates are internally consistent (no -** x1>x2 conditions) and adds an error message to the RtreeCheck object -** if they are not. -** -** Additionally, if pParent is not NULL, then it is assumed to point to -** the array of coordinates on the parent page that bound the page -** containing pCell. In this case it is also verified that the two -** sets of coordinates are mutually consistent and an error message added -** to the RtreeCheck object if they are not. -*/ -static void rtreeCheckCellCoord( - RtreeCheck *pCheck, - i64 iNode, /* Node id to use in error messages */ - int iCell, /* Cell number to use in error messages */ - u8 *pCell, /* Pointer to cell coordinates */ - u8 *pParent /* Pointer to parent coordinates */ -){ - RtreeCoord c1, c2; - RtreeCoord p1, p2; - int i; - - for(i=0; inDim; i++){ - readCoord(&pCell[4*2*i], &c1); - readCoord(&pCell[4*(2*i + 1)], &c2); - - /* printf("%e, %e\n", c1.u.f, c2.u.f); */ - if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){ - rtreeCheckAppendMsg(pCheck, - "Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode - ); - } - - if( pParent ){ - readCoord(&pParent[4*2*i], &p1); - readCoord(&pParent[4*(2*i + 1)], &p2); - - if( (pCheck->bInt ? c1.ibInt ? c2.i>p2.i : c2.f>p2.f) - ){ - rtreeCheckAppendMsg(pCheck, - "Dimension %d of cell %d on node %lld is corrupt relative to parent" - , i, iCell, iNode - ); - } - } - } -} - -/* -** Run rtreecheck() checks on node iNode, which is at depth iDepth within -** the r-tree structure. Argument aParent points to the array of coordinates -** that bound node iNode on the parent node. -** -** If any problems are discovered, an error message is appended to the -** report accumulated in the RtreeCheck object. -*/ -static void rtreeCheckNode( - RtreeCheck *pCheck, - int iDepth, /* Depth of iNode (0==leaf) */ - u8 *aParent, /* Buffer containing parent coords */ - i64 iNode /* Node to check */ -){ - u8 *aNode = 0; - int nNode = 0; - - assert( iNode==1 || aParent!=0 ); - assert( pCheck->nDim>0 ); - - aNode = rtreeCheckGetNode(pCheck, iNode, &nNode); - if( aNode ){ - if( nNode<4 ){ - rtreeCheckAppendMsg(pCheck, - "Node %lld is too small (%d bytes)", iNode, nNode - ); - }else{ - int nCell; /* Number of cells on page */ - int i; /* Used to iterate through cells */ - if( aParent==0 ){ - iDepth = readInt16(aNode); - if( iDepth>RTREE_MAX_DEPTH ){ - rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth); - sqlite3_free(aNode); - return; - } - } - nCell = readInt16(&aNode[2]); - if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){ - rtreeCheckAppendMsg(pCheck, - "Node %lld is too small for cell count of %d (%d bytes)", - iNode, nCell, nNode - ); - }else{ - for(i=0; inDim*2*4)]; - i64 iVal = readInt64(pCell); - rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent); - - if( iDepth>0 ){ - rtreeCheckMapping(pCheck, 0, iVal, iNode); - rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal); - pCheck->nNonLeaf++; - }else{ - rtreeCheckMapping(pCheck, 1, iVal, iNode); - pCheck->nLeaf++; - } - } - } - } - sqlite3_free(aNode); - } -} - -/* -** The second argument to this function must be either "_rowid" or -** "_parent". This function checks that the number of entries in the -** %_rowid or %_parent table is exactly nExpect. If not, it adds -** an error message to the report in the RtreeCheck object indicated -** by the first argument. -*/ -static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){ - if( pCheck->rc==SQLITE_OK ){ - sqlite3_stmt *pCount; - pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'", - pCheck->zDb, pCheck->zTab, zTbl - ); - if( pCount ){ - if( sqlite3_step(pCount)==SQLITE_ROW ){ - i64 nActual = sqlite3_column_int64(pCount, 0); - if( nActual!=nExpect ){ - rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table" - " - expected %lld, actual %lld" , zTbl, nExpect, nActual - ); - } - } - pCheck->rc = sqlite3_finalize(pCount); - } - } -} - -/* -** This function does the bulk of the work for the rtree integrity-check. -** It is called by rtreecheck(), which is the SQL function implementation. -*/ -static int rtreeCheckTable( - sqlite3 *db, /* Database handle to access db through */ - const char *zDb, /* Name of db ("main", "temp" etc.) */ - const char *zTab, /* Name of rtree table to check */ - char **pzReport /* OUT: sqlite3_malloc'd report text */ -){ - RtreeCheck check; /* Common context for various routines */ - sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ - int nAux = 0; /* Number of extra columns. */ - - /* Initialize the context object */ - memset(&check, 0, sizeof(check)); - check.db = db; - check.zDb = zDb; - check.zTab = zTab; - - /* Find the number of auxiliary columns */ - pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); - if( pStmt ){ - nAux = sqlite3_column_count(pStmt) - 2; - sqlite3_finalize(pStmt); - }else - if( check.rc!=SQLITE_NOMEM ){ - check.rc = SQLITE_OK; - } - - /* Find number of dimensions in the rtree table. */ - pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab); - if( pStmt ){ - int rc; - check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2; - if( check.nDim<1 ){ - rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree"); - }else if( SQLITE_ROW==sqlite3_step(pStmt) ){ - check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER); - } - rc = sqlite3_finalize(pStmt); - if( rc!=SQLITE_CORRUPT ) check.rc = rc; - } - - /* Do the actual integrity-check */ - if( check.nDim>=1 ){ - if( check.rc==SQLITE_OK ){ - rtreeCheckNode(&check, 0, 0, 1); - } - rtreeCheckCount(&check, "_rowid", check.nLeaf); - rtreeCheckCount(&check, "_parent", check.nNonLeaf); - } - - /* Finalize SQL statements used by the integrity-check */ - sqlite3_finalize(check.pGetNode); - sqlite3_finalize(check.aCheckMapping[0]); - sqlite3_finalize(check.aCheckMapping[1]); - - *pzReport = check.zReport; - return check.rc; -} - -/* -** Implementation of the xIntegrity method for Rtree. -*/ -static int rtreeIntegrity( - sqlite3_vtab *pVtab, /* The virtual table to check */ - const char *zSchema, /* Schema in which the virtual table lives */ - const char *zName, /* Name of the virtual table */ - int isQuick, /* True for a quick_check */ - char **pzErr /* Write results here */ -){ - Rtree *pRtree = (Rtree*)pVtab; - int rc; - assert( pzErr!=0 && *pzErr==0 ); - UNUSED_PARAMETER(zSchema); - UNUSED_PARAMETER(zName); - UNUSED_PARAMETER(isQuick); - rc = rtreeCheckTable(pRtree->db, pRtree->zDb, pRtree->zName, pzErr); - if( rc==SQLITE_OK && *pzErr ){ - *pzErr = sqlite3_mprintf("In RTree %s.%s:\n%z", - pRtree->zDb, pRtree->zName, *pzErr); - if( (*pzErr)==0 ) rc = SQLITE_NOMEM; - } - return rc; -} - -/* -** Usage: -** -** rtreecheck(); -** rtreecheck(, ); -** -** Invoking this SQL function runs an integrity-check on the named rtree -** table. The integrity-check verifies the following: -** -** 1. For each cell in the r-tree structure (%_node table), that: -** -** a) for each dimension, (coord1 <= coord2). -** -** b) unless the cell is on the root node, that the cell is bounded -** by the parent cell on the parent node. -** -** c) for leaf nodes, that there is an entry in the %_rowid -** table corresponding to the cell's rowid value that -** points to the correct node. -** -** d) for cells on non-leaf nodes, that there is an entry in the -** %_parent table mapping from the cell's child node to the -** node that it resides on. -** -** 2. That there are the same number of entries in the %_rowid table -** as there are leaf cells in the r-tree structure, and that there -** is a leaf cell that corresponds to each entry in the %_rowid table. -** -** 3. That there are the same number of entries in the %_parent table -** as there are non-leaf cells in the r-tree structure, and that -** there is a non-leaf cell that corresponds to each entry in the -** %_parent table. -*/ -static void rtreecheck( - sqlite3_context *ctx, - int nArg, - sqlite3_value **apArg -){ - if( nArg!=1 && nArg!=2 ){ - sqlite3_result_error(ctx, - "wrong number of arguments to function rtreecheck()", -1 - ); - }else{ - int rc; - char *zReport = 0; - const char *zDb = (const char*)sqlite3_value_text(apArg[0]); - const char *zTab; - if( nArg==1 ){ - zTab = zDb; - zDb = "main"; - }else{ - zTab = (const char*)sqlite3_value_text(apArg[1]); - } - rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport); - if( rc==SQLITE_OK ){ - sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT); - }else{ - sqlite3_result_error_code(ctx, rc); - } - sqlite3_free(zReport); - } -} - -/* Conditionally include the geopoly code */ -#ifdef SQLITE_ENABLE_GEOPOLY -/************** Include geopoly.c in the middle of rtree.c *******************/ -/************** Begin file geopoly.c *****************************************/ -/* -** 2018-05-25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file implements an alternative R-Tree virtual table that -** uses polygons to express the boundaries of 2-dimensional objects. -** -** This file is #include-ed onto the end of "rtree.c" so that it has -** access to all of the R-Tree internals. -*/ -/* #include */ - -/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ -#ifdef GEOPOLY_ENABLE_DEBUG - static int geo_debug = 0; -# define GEODEBUG(X) if(geo_debug)printf X -#else -# define GEODEBUG(X) -#endif - -/* Character class routines */ -#ifdef sqlite3Isdigit - /* Use the SQLite core versions if this routine is part of the - ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) -# define safe_isxdigit(x) sqlite3Isxdigit(x) -#else - /* Use the standard library for separate compilation */ -#include /* amalgamator: keep */ -# define safe_isdigit(x) isdigit((unsigned char)(x)) -# define safe_isalnum(x) isalnum((unsigned char)(x)) -# define safe_isxdigit(x) isxdigit((unsigned char)(x)) -#endif - -#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ -/* -** Growing our own isspace() routine this way is twice as fast as -** the library isspace() function. -*/ -static const char geopolyIsSpace[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x]) -#endif /* JSON NULL - back to original code */ - -/* Compiler and version */ -#ifndef GCC_VERSION -#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) -# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) -#else -# define GCC_VERSION 0 -#endif -#endif -#ifndef MSVC_VERSION -#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) -# define MSVC_VERSION _MSC_VER -#else -# define MSVC_VERSION 0 -#endif -#endif - -/* Datatype for coordinates -*/ -typedef float GeoCoord; - -/* -** Internal representation of a polygon. -** -** The polygon consists of a sequence of vertexes. There is a line -** segment between each pair of vertexes, and one final segment from -** the last vertex back to the first. (This differs from the GeoJSON -** standard in which the final vertex is a repeat of the first.) -** -** The polygon follows the right-hand rule. The area to the right of -** each segment is "outside" and the area to the left is "inside". -** -** The on-disk representation consists of a 4-byte header followed by -** the values. The 4-byte header is: -** -** encoding (1 byte) 0=big-endian, 1=little-endian -** nvertex (3 bytes) Number of vertexes as a big-endian integer -** -** Enough space is allocated for 4 coordinates, to work around over-zealous -** warnings coming from some compiler (notably, clang). In reality, the size -** of each GeoPoly memory allocate is adjusted as necessary so that the -** GeoPoly.a[] array at the end is the appropriate size. -*/ -typedef struct GeoPoly GeoPoly; -struct GeoPoly { - int nVertex; /* Number of vertexes */ - unsigned char hdr[4]; /* Header for on-disk representation */ - GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ -}; - -/* The size of a memory allocation needed for a GeoPoly object sufficient -** to hold N coordinate pairs. -*/ -#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) - -/* Macros to access coordinates of a GeoPoly. -** We have to use these macros, rather than just say p->a[i] in order -** to silence (incorrect) UBSAN warnings if the array index is too large. -*/ -#define GeoX(P,I) (((GeoCoord*)(P)->a)[(I)*2]) -#define GeoY(P,I) (((GeoCoord*)(P)->a)[(I)*2+1]) - - -/* -** State of a parse of a GeoJSON input. -*/ -typedef struct GeoParse GeoParse; -struct GeoParse { - const unsigned char *z; /* Unparsed input */ - int nVertex; /* Number of vertexes in a[] */ - int nAlloc; /* Space allocated to a[] */ - int nErr; /* Number of errors encountered */ - GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ -}; - -/* Do a 4-byte byte swap */ -static void geopolySwab32(unsigned char *a){ - unsigned char t = a[0]; - a[0] = a[3]; - a[3] = t; - t = a[1]; - a[1] = a[2]; - a[2] = t; -} - -/* Skip whitespace. Return the next non-whitespace character. */ -static char geopolySkipSpace(GeoParse *p){ - while( fast_isspace(p->z[0]) ) p->z++; - return p->z[0]; -} - -/* Parse out a number. Write the value into *pVal if pVal!=0. -** return non-zero on success and zero if the next token is not a number. -*/ -static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ - char c = geopolySkipSpace(p); - const unsigned char *z = p->z; - int j = 0; - int seenDP = 0; - int seenE = 0; - if( c=='-' ){ - j = 1; - c = z[j]; - } - if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; - for(;; j++){ - c = z[j]; - if( safe_isdigit(c) ) continue; - if( c=='.' ){ - if( z[j-1]=='-' ) return 0; - if( seenDP ) return 0; - seenDP = 1; - continue; - } - if( c=='e' || c=='E' ){ - if( z[j-1]<'0' ) return 0; - if( seenE ) return -1; - seenDP = seenE = 1; - c = z[j+1]; - if( c=='+' || c=='-' ){ - j++; - c = z[j+1]; - } - if( c<'0' || c>'9' ) return 0; - continue; - } - break; - } - if( z[j-1]<'0' ) return 0; - if( pVal ){ -#ifdef SQLITE_AMALGAMATION - /* The sqlite3AtoF() routine is much much faster than atof(), if it - ** is available */ - double r; - (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); - *pVal = r; -#else - *pVal = (GeoCoord)atof((const char*)p->z); -#endif - } - p->z += j; - return 1; -} - -/* -** If the input is a well-formed JSON array of coordinates with at least -** four coordinates and where each coordinate is itself a two-value array, -** then convert the JSON into a GeoPoly object and return a pointer to -** that object. -** -** If any error occurs, return NULL. -*/ -static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ - GeoParse s; - int rc = SQLITE_OK; - memset(&s, 0, sizeof(s)); - s.z = z; - if( geopolySkipSpace(&s)=='[' ){ - s.z++; - while( geopolySkipSpace(&s)=='[' ){ - int ii = 0; - char c; - s.z++; - if( s.nVertex>=s.nAlloc ){ - GeoCoord *aNew; - s.nAlloc = s.nAlloc*2 + 16; - aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); - if( aNew==0 ){ - rc = SQLITE_NOMEM; - s.nErr++; - break; - } - s.a = aNew; - } - while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ - ii++; - if( ii==2 ) s.nVertex++; - c = geopolySkipSpace(&s); - s.z++; - if( c==',' ) continue; - if( c==']' && ii>=2 ) break; - s.nErr++; - rc = SQLITE_ERROR; - goto parse_json_err; - } - if( geopolySkipSpace(&s)==',' ){ - s.z++; - continue; - } - break; - } - if( geopolySkipSpace(&s)==']' - && s.nVertex>=4 - && s.a[0]==s.a[s.nVertex*2-2] - && s.a[1]==s.a[s.nVertex*2-1] - && (s.z++, geopolySkipSpace(&s)==0) - ){ - GeoPoly *pOut; - int x = 1; - s.nVertex--; /* Remove the redundant vertex at the end */ - pOut = sqlite3_malloc64( GEOPOLY_SZ((sqlite3_int64)s.nVertex) ); - x = 1; - if( pOut==0 ) goto parse_json_err; - pOut->nVertex = s.nVertex; - memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); - pOut->hdr[0] = *(unsigned char*)&x; - pOut->hdr[1] = (s.nVertex>>16)&0xff; - pOut->hdr[2] = (s.nVertex>>8)&0xff; - pOut->hdr[3] = s.nVertex&0xff; - sqlite3_free(s.a); - if( pRc ) *pRc = SQLITE_OK; - return pOut; - }else{ - s.nErr++; - rc = SQLITE_ERROR; - } - } -parse_json_err: - if( pRc ) *pRc = rc; - sqlite3_free(s.a); - return 0; -} - -/* -** Given a function parameter, try to interpret it as a polygon, either -** in the binary format or JSON text. Compute a GeoPoly object and -** return a pointer to that object. Or if the input is not a well-formed -** polygon, put an error message in sqlite3_context and return NULL. -*/ -static GeoPoly *geopolyFuncParam( - sqlite3_context *pCtx, /* Context for error messages */ - sqlite3_value *pVal, /* The value to decode */ - int *pRc /* Write error here */ -){ - GeoPoly *p = 0; - int nByte; - testcase( pCtx==0 ); - if( sqlite3_value_type(pVal)==SQLITE_BLOB - && (nByte = sqlite3_value_bytes(pVal))>=(int)(4+6*sizeof(GeoCoord)) - ){ - const unsigned char *a = sqlite3_value_blob(pVal); - int nVertex; - if( a==0 ){ - if( pCtx ) sqlite3_result_error_nomem(pCtx); - return 0; - } - nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; - if( (a[0]==0 || a[0]==1) - && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte - ){ - p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); - if( p==0 ){ - if( pRc ) *pRc = SQLITE_NOMEM; - if( pCtx ) sqlite3_result_error_nomem(pCtx); - }else{ - int x = 1; - p->nVertex = nVertex; - memcpy(p->hdr, a, nByte); - if( a[0] != *(unsigned char*)&x ){ - int ii; - for(ii=0; iihdr[0] ^= 1; - } - } - } - if( pRc ) *pRc = SQLITE_OK; - return p; - }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ - const unsigned char *zJson = sqlite3_value_text(pVal); - if( zJson==0 ){ - if( pRc ) *pRc = SQLITE_NOMEM; - return 0; - } - return geopolyParseJson(zJson, pRc); - }else{ - if( pRc ) *pRc = SQLITE_ERROR; - return 0; - } -} - -/* -** Implementation of the geopoly_blob(X) function. -** -** If the input is a well-formed Geopoly BLOB or JSON string -** then return the BLOB representation of the polygon. Otherwise -** return NULL. -*/ -static void geopolyBlobFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -/* -** SQL function: geopoly_json(X) -** -** Interpret X as a polygon and render it as a JSON array -** of coordinates. Or, if X is not a valid polygon, return NULL. -*/ -static void geopolyJsonFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - sqlite3 *db = sqlite3_context_db_handle(context); - sqlite3_str *x = sqlite3_str_new(db); - int i; - sqlite3_str_append(x, "[", 1); - for(i=0; inVertex; i++){ - sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i)); - } - sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0)); - sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); - sqlite3_free(p); - } -} - -/* -** SQL function: geopoly_svg(X, ....) -** -** Interpret X as a polygon and render it as a SVG . -** Additional arguments are added as attributes to the . -*/ -static void geopolySvgFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p; - if( argc<1 ) return; - p = geopolyFuncParam(context, argv[0], 0); - if( p ){ - sqlite3 *db = sqlite3_context_db_handle(context); - sqlite3_str *x = sqlite3_str_new(db); - int i; - char cSep = '\''; - sqlite3_str_appendf(x, ""); - sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); - sqlite3_free(p); - } -} - -/* -** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) -** -** Transform and/or translate a polygon as follows: -** -** x1 = A*x0 + B*y0 + E -** y1 = C*x0 + D*y0 + F -** -** For a translation: -** -** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) -** -** Rotate by R around the point (0,0): -** -** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) -*/ -static void geopolyXformFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - double A = sqlite3_value_double(argv[1]); - double B = sqlite3_value_double(argv[2]); - double C = sqlite3_value_double(argv[3]); - double D = sqlite3_value_double(argv[4]); - double E = sqlite3_value_double(argv[5]); - double F = sqlite3_value_double(argv[6]); - GeoCoord x1, y1, x0, y0; - int ii; - (void)argc; - if( p ){ - for(ii=0; iinVertex; ii++){ - x0 = GeoX(p,ii); - y0 = GeoY(p,ii); - x1 = (GeoCoord)(A*x0 + B*y0 + E); - y1 = (GeoCoord)(C*x0 + D*y0 + F); - GeoX(p,ii) = x1; - GeoY(p,ii) = y1; - } - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -/* -** Compute the area enclosed by the polygon. -** -** This routine can also be used to detect polygons that rotate in -** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). -** This routine returns a negative value for clockwise (CW) polygons. -*/ -static double geopolyArea(GeoPoly *p){ - double rArea = 0.0; - int ii; - for(ii=0; iinVertex-1; ii++){ - rArea += (GeoX(p,ii) - GeoX(p,ii+1)) /* (x0 - x1) */ - * (GeoY(p,ii) + GeoY(p,ii+1)) /* (y0 + y1) */ - * 0.5; - } - rArea += (GeoX(p,ii) - GeoX(p,0)) /* (xN - x0) */ - * (GeoY(p,ii) + GeoY(p,0)) /* (yN + y0) */ - * 0.5; - return rArea; -} - -/* -** Implementation of the geopoly_area(X) function. -** -** If the input is a well-formed Geopoly BLOB then return the area -** enclosed by the polygon. If the polygon circulates clockwise instead -** of counterclockwise (as it should) then return the negative of the -** enclosed area. Otherwise return NULL. -*/ -static void geopolyAreaFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - sqlite3_result_double(context, geopolyArea(p)); - sqlite3_free(p); - } -} - -/* -** Implementation of the geopoly_ccw(X) function. -** -** If the rotation of polygon X is clockwise (incorrect) instead of -** counter-clockwise (the correct winding order according to RFC7946) -** then reverse the order of the vertexes in polygon X. -** -** In other words, this routine returns a CCW polygon regardless of the -** winding order of its input. -** -** Use this routine to sanitize historical inputs that that sometimes -** contain polygons that wind in the wrong direction. -*/ -static void geopolyCcwFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyFuncParam(context, argv[0], 0); - (void)argc; - if( p ){ - if( geopolyArea(p)<0.0 ){ - int ii, jj; - for(ii=1, jj=p->nVertex-1; iihdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -#define GEOPOLY_PI 3.1415926535897932385 - -/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi -*/ -static double geopolySine(double r){ - assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); - if( r>=1.5*GEOPOLY_PI ){ - r -= 2.0*GEOPOLY_PI; - } - if( r>=0.5*GEOPOLY_PI ){ - return -geopolySine(r-GEOPOLY_PI); - }else{ - double r2 = r*r; - double r3 = r2*r; - double r5 = r3*r2; - return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; - } -} - -/* -** Function: geopoly_regular(X,Y,R,N) -** -** Construct a simple, convex, regular polygon centered at X, Y -** with circumradius R and with N sides. -*/ -static void geopolyRegularFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - double x = sqlite3_value_double(argv[0]); - double y = sqlite3_value_double(argv[1]); - double r = sqlite3_value_double(argv[2]); - int n = sqlite3_value_int(argv[3]); - int i; - GeoPoly *p; - (void)argc; - - if( n<3 || r<=0.0 ) return; - if( n>1000 ) n = 1000; - p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); - if( p==0 ){ - sqlite3_result_error_nomem(context); - return; - } - i = 1; - p->hdr[0] = *(unsigned char*)&i; - p->hdr[1] = 0; - p->hdr[2] = (n>>8)&0xff; - p->hdr[3] = n&0xff; - for(i=0; ihdr, 4+8*n, SQLITE_TRANSIENT); - sqlite3_free(p); -} - -/* -** If pPoly is a polygon, compute its bounding box. Then: -** -** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL -** (2) otherwise, compute a GeoPoly for the bounding box and return the -** new GeoPoly -** -** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from -** the bounding box in aCoord and return a pointer to that GeoPoly. -*/ -static GeoPoly *geopolyBBox( - sqlite3_context *context, /* For recording the error */ - sqlite3_value *pPoly, /* The polygon */ - RtreeCoord *aCoord, /* Results here */ - int *pRc /* Error code here */ -){ - GeoPoly *pOut = 0; - GeoPoly *p; - float mnX, mxX, mnY, mxY; - if( pPoly==0 && aCoord!=0 ){ - p = 0; - mnX = aCoord[0].f; - mxX = aCoord[1].f; - mnY = aCoord[2].f; - mxY = aCoord[3].f; - goto geopolyBboxFill; - }else{ - p = geopolyFuncParam(context, pPoly, pRc); - } - if( p ){ - int ii; - mnX = mxX = GeoX(p,0); - mnY = mxY = GeoY(p,0); - for(ii=1; iinVertex; ii++){ - double r = GeoX(p,ii); - if( rmxX ) mxX = (float)r; - r = GeoY(p,ii); - if( rmxY ) mxY = (float)r; - } - if( pRc ) *pRc = SQLITE_OK; - if( aCoord==0 ){ - geopolyBboxFill: - pOut = sqlite3_realloc64(p, GEOPOLY_SZ(4)); - if( pOut==0 ){ - sqlite3_free(p); - if( context ) sqlite3_result_error_nomem(context); - if( pRc ) *pRc = SQLITE_NOMEM; - return 0; - } - pOut->nVertex = 4; - ii = 1; - pOut->hdr[0] = *(unsigned char*)ⅈ - pOut->hdr[1] = 0; - pOut->hdr[2] = 0; - pOut->hdr[3] = 4; - GeoX(pOut,0) = mnX; - GeoY(pOut,0) = mnY; - GeoX(pOut,1) = mxX; - GeoY(pOut,1) = mnY; - GeoX(pOut,2) = mxX; - GeoY(pOut,2) = mxY; - GeoX(pOut,3) = mnX; - GeoY(pOut,3) = mxY; - }else{ - sqlite3_free(p); - aCoord[0].f = mnX; - aCoord[1].f = mxX; - aCoord[2].f = mnY; - aCoord[3].f = mxY; - } - }else if( aCoord ){ - memset(aCoord, 0, sizeof(RtreeCoord)*4); - } - return pOut; -} - -/* -** Implementation of the geopoly_bbox(X) SQL function. -*/ -static void geopolyBBoxFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); - (void)argc; - if( p ){ - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - -/* -** State vector for the geopoly_group_bbox() aggregate function. -*/ -typedef struct GeoBBox GeoBBox; -struct GeoBBox { - int isInit; - RtreeCoord a[4]; -}; - - -/* -** Implementation of the geopoly_group_bbox(X) aggregate SQL function. -*/ -static void geopolyBBoxStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - RtreeCoord a[4]; - int rc = SQLITE_OK; - (void)argc; - (void)geopolyBBox(context, argv[0], a, &rc); - if( rc==SQLITE_OK ){ - GeoBBox *pBBox; - pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); - if( pBBox==0 ) return; - if( pBBox->isInit==0 ){ - pBBox->isInit = 1; - memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); - }else{ - if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; - if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; - if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; - if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; - } - } -} -static void geopolyBBoxFinal( - sqlite3_context *context -){ - GeoPoly *p; - GeoBBox *pBBox; - pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); - if( pBBox==0 ) return; - p = geopolyBBox(context, 0, pBBox->a, 0); - if( p ){ - sqlite3_result_blob(context, p->hdr, - 4+8*p->nVertex, SQLITE_TRANSIENT); - sqlite3_free(p); - } -} - - -/* -** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). -** Returns: -** -** +2 x0,y0 is on the line segement -** -** +1 x0,y0 is beneath line segment -** -** 0 x0,y0 is not on or beneath the line segment or the line segment -** is vertical and x0,y0 is not on the line segment -** -** The left-most coordinate min(x1,x2) is not considered to be part of -** the line segment for the purposes of this analysis. -*/ -static int pointBeneathLine( - double x0, double y0, - double x1, double y1, - double x2, double y2 -){ - double y; - if( x0==x1 && y0==y1 ) return 2; - if( x1x2 ) return 0; - }else if( x1>x2 ){ - if( x0<=x2 || x0>x1 ) return 0; - }else{ - /* Vertical line segment */ - if( x0!=x1 ) return 0; - if( y0y1 && y0>y2 ) return 0; - return 2; - } - y = y1 + (y2-y1)*(x0-x1)/(x2-x1); - if( y0==y ) return 2; - if( y0nVertex-1; ii++){ - v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii), - GeoX(p1,ii+1),GeoY(p1,ii+1)); - if( v==2 ) break; - cnt += v; - } - if( v!=2 ){ - v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii), - GeoX(p1,0), GeoY(p1,0)); - } - if( v==2 ){ - sqlite3_result_int(context, 1); - }else if( ((v+cnt)&1)==0 ){ - sqlite3_result_int(context, 0); - }else{ - sqlite3_result_int(context, 2); - } - sqlite3_free(p1); -} - -/* Forward declaration */ -static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); - -/* -** SQL function: geopoly_within(P1,P2) -** -** Return +2 if P1 and P2 are the same polygon -** Return +1 if P2 is contained within P1 -** Return 0 if any part of P2 is on the outside of P1 -** -*/ -static void geopolyWithinFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); - GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); - (void)argc; - if( p1 && p2 ){ - int x = geopolyOverlap(p1, p2); - if( x<0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); - } - } - sqlite3_free(p1); - sqlite3_free(p2); -} - -/* Objects used by the overlap algorihm. */ -typedef struct GeoEvent GeoEvent; -typedef struct GeoSegment GeoSegment; -typedef struct GeoOverlap GeoOverlap; -struct GeoEvent { - double x; /* X coordinate at which event occurs */ - int eType; /* 0 for ADD, 1 for REMOVE */ - GeoSegment *pSeg; /* The segment to be added or removed */ - GeoEvent *pNext; /* Next event in the sorted list */ -}; -struct GeoSegment { - double C, B; /* y = C*x + B */ - double y; /* Current y value */ - float y0; /* Initial y value */ - unsigned char side; /* 1 for p1, 2 for p2 */ - unsigned int idx; /* Which segment within the side */ - GeoSegment *pNext; /* Next segment in a list sorted by y */ -}; -struct GeoOverlap { - GeoEvent *aEvent; /* Array of all events */ - GeoSegment *aSegment; /* Array of all segments */ - int nEvent; /* Number of events */ - int nSegment; /* Number of segments */ -}; - -/* -** Add a single segment and its associated events. -*/ -static void geopolyAddOneSegment( - GeoOverlap *p, - GeoCoord x0, - GeoCoord y0, - GeoCoord x1, - GeoCoord y1, - unsigned char side, - unsigned int idx -){ - GeoSegment *pSeg; - GeoEvent *pEvent; - if( x0==x1 ) return; /* Ignore vertical segments */ - if( x0>x1 ){ - GeoCoord t = x0; - x0 = x1; - x1 = t; - t = y0; - y0 = y1; - y1 = t; - } - pSeg = p->aSegment + p->nSegment; - p->nSegment++; - pSeg->C = (y1-y0)/(x1-x0); - pSeg->B = y1 - x1*pSeg->C; - pSeg->y0 = y0; - pSeg->side = side; - pSeg->idx = idx; - pEvent = p->aEvent + p->nEvent; - p->nEvent++; - pEvent->x = x0; - pEvent->eType = 0; - pEvent->pSeg = pSeg; - pEvent = p->aEvent + p->nEvent; - p->nEvent++; - pEvent->x = x1; - pEvent->eType = 1; - pEvent->pSeg = pSeg; -} - - - -/* -** Insert all segments and events for polygon pPoly. -*/ -static void geopolyAddSegments( - GeoOverlap *p, /* Add segments to this Overlap object */ - GeoPoly *pPoly, /* Take all segments from this polygon */ - unsigned char side /* The side of pPoly */ -){ - unsigned int i; - GeoCoord *x; - for(i=0; i<(unsigned)pPoly->nVertex-1; i++){ - x = &GeoX(pPoly,i); - geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); - } - x = &GeoX(pPoly,i); - geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); -} - -/* -** Merge two lists of sorted events by X coordinate -*/ -static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ - GeoEvent head, *pLast; - head.pNext = 0; - pLast = &head; - while( pRight && pLeft ){ - if( pRight->x <= pLeft->x ){ - pLast->pNext = pRight; - pLast = pRight; - pRight = pRight->pNext; - }else{ - pLast->pNext = pLeft; - pLast = pLeft; - pLeft = pLeft->pNext; - } - } - pLast->pNext = pRight ? pRight : pLeft; - return head.pNext; -} - -/* -** Sort an array of nEvent event objects into a list. -*/ -static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ - int mx = 0; - int i, j; - GeoEvent *p; - GeoEvent *a[50]; - for(i=0; ipNext = 0; - for(j=0; j=mx ) mx = j+1; - } - p = 0; - for(i=0; iy - pLeft->y; - if( r==0.0 ) r = pRight->C - pLeft->C; - if( r<0.0 ){ - pLast->pNext = pRight; - pLast = pRight; - pRight = pRight->pNext; - }else{ - pLast->pNext = pLeft; - pLast = pLeft; - pLeft = pLeft->pNext; - } - } - pLast->pNext = pRight ? pRight : pLeft; - return head.pNext; -} - -/* -** Sort a list of GeoSegments in order of increasing Y and in the event of -** a tie, increasing C (slope). -*/ -static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ - int mx = 0; - int i; - GeoSegment *p; - GeoSegment *a[50]; - while( pList ){ - p = pList; - pList = pList->pNext; - p->pNext = 0; - for(i=0; i=mx ) mx = i+1; - } - p = 0; - for(i=0; inVertex + p2->nVertex + 2; - GeoOverlap *p; - sqlite3_int64 nByte; - GeoEvent *pThisEvent; - double rX; - int rc = 0; - int needSort = 0; - GeoSegment *pActive = 0; - GeoSegment *pSeg; - unsigned char aOverlap[4]; - - nByte = sizeof(GeoEvent)*nVertex*2 - + sizeof(GeoSegment)*nVertex - + sizeof(GeoOverlap); - p = sqlite3_malloc64( nByte ); - if( p==0 ) return -1; - p->aEvent = (GeoEvent*)&p[1]; - p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; - p->nEvent = p->nSegment = 0; - geopolyAddSegments(p, p1, 1); - geopolyAddSegments(p, p2, 2); - pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); - rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0; - memset(aOverlap, 0, sizeof(aOverlap)); - while( pThisEvent ){ - if( pThisEvent->x!=rX ){ - GeoSegment *pPrev = 0; - int iMask = 0; - GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); - rX = pThisEvent->x; - if( needSort ){ - GEODEBUG(("SORT\n")); - pActive = geopolySortSegmentsByYAndC(pActive); - needSort = 0; - } - for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ - if( pPrev ){ - if( pPrev->y!=pSeg->y ){ - GEODEBUG(("MASK: %d\n", iMask)); - aOverlap[iMask] = 1; - } - } - iMask ^= pSeg->side; - pPrev = pSeg; - } - pPrev = 0; - for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ - double y = pSeg->C*rX + pSeg->B; - GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); - pSeg->y = y; - if( pPrev ){ - if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ - rc = 1; - GEODEBUG(("Crossing: %d.%d and %d.%d\n", - pPrev->side, pPrev->idx, - pSeg->side, pSeg->idx)); - goto geopolyOverlapDone; - }else if( pPrev->y!=pSeg->y ){ - GEODEBUG(("MASK: %d\n", iMask)); - aOverlap[iMask] = 1; - } - } - iMask ^= pSeg->side; - pPrev = pSeg; - } - } - GEODEBUG(("%s %d.%d C=%g B=%g\n", - pThisEvent->eType ? "RM " : "ADD", - pThisEvent->pSeg->side, pThisEvent->pSeg->idx, - pThisEvent->pSeg->C, - pThisEvent->pSeg->B)); - if( pThisEvent->eType==0 ){ - /* Add a segment */ - pSeg = pThisEvent->pSeg; - pSeg->y = pSeg->y0; - pSeg->pNext = pActive; - pActive = pSeg; - needSort = 1; - }else{ - /* Remove a segment */ - if( pActive==pThisEvent->pSeg ){ - pActive = ALWAYS(pActive) ? pActive->pNext : 0; - }else{ - for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ - if( pSeg->pNext==pThisEvent->pSeg ){ - pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0; - break; - } - } - } - } - pThisEvent = pThisEvent->pNext; - } - if( aOverlap[3]==0 ){ - rc = 0; - }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ - rc = 3; - }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ - rc = 2; - }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ - rc = 4; - }else{ - rc = 1; - } - -geopolyOverlapDone: - sqlite3_free(p); - return rc; -} - -/* -** SQL function: geopoly_overlap(P1,P2) -** -** Determine whether or not P1 and P2 overlap. Return value: -** -** 0 The two polygons are disjoint -** 1 They overlap -** 2 P1 is completely contained within P2 -** 3 P2 is completely contained within P1 -** 4 P1 and P2 are the same polygon -** NULL Either P1 or P2 or both are not valid polygons -*/ -static void geopolyOverlapFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); - GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); - (void)argc; - if( p1 && p2 ){ - int x = geopolyOverlap(p1, p2); - if( x<0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_int(context, x); - } - } - sqlite3_free(p1); - sqlite3_free(p2); -} - -/* -** Enable or disable debugging output -*/ -static void geopolyDebugFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - (void)context; - (void)argc; -#ifdef GEOPOLY_ENABLE_DEBUG - geo_debug = sqlite3_value_int(argv[0]); -#else - (void)argv; -#endif -} - -/* -** This function is the implementation of both the xConnect and xCreate -** methods of the geopoly virtual table. -** -** argv[0] -> module name -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> column names... -*/ -static int geopolyInit( - sqlite3 *db, /* Database connection */ - void *pAux, /* One of the RTREE_COORD_* constants */ - int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ - sqlite3_vtab **ppVtab, /* OUT: New virtual table */ - char **pzErr, /* OUT: Error message, if any */ - int isCreate /* True for xCreate, false for xConnect */ -){ - int rc = SQLITE_OK; - Rtree *pRtree; - sqlite3_int64 nDb; /* Length of string argv[1] */ - sqlite3_int64 nName; /* Length of string argv[2] */ - sqlite3_str *pSql; - char *zSql; - int ii; - (void)pAux; - - sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - - /* Allocate the sqlite3_vtab structure */ - nDb = strlen(argv[1]); - nName = strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); - if( !pRtree ){ - return SQLITE_NOMEM; - } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName*2+8); - pRtree->nBusy = 1; - pRtree->base.pModule = &rtreeModule; - pRtree->zDb = (char *)&pRtree[1]; - pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->zNodeName = &pRtree->zName[nName+1]; - pRtree->eCoordType = RTREE_COORD_REAL32; - pRtree->nDim = 2; - pRtree->nDim2 = 4; - memcpy(pRtree->zDb, argv[1], nDb); - memcpy(pRtree->zName, argv[2], nName); - memcpy(pRtree->zNodeName, argv[2], nName); - memcpy(&pRtree->zNodeName[nName], "_node", 6); - - - /* Create/Connect to the underlying relational database schema. If - ** that is successful, call sqlite3_declare_vtab() to configure - ** the r-tree table schema. - */ - pSql = sqlite3_str_new(db); - sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); - pRtree->nAux = 1; /* Add one for _shape */ - pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */ - for(ii=3; iinAux++; - sqlite3_str_appendf(pSql, ",%s", argv[ii]); - } - sqlite3_str_appendf(pSql, ");"); - zSql = sqlite3_str_finish(pSql); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - sqlite3_free(zSql); - if( rc ) goto geopolyInit_fail; - pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; - - /* Figure out the node size to use. */ - rc = getNodeSize(db, pRtree, isCreate, pzErr); - if( rc ) goto geopolyInit_fail; - rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); - if( rc ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - goto geopolyInit_fail; - } - - *ppVtab = (sqlite3_vtab *)pRtree; - return SQLITE_OK; - -geopolyInit_fail: - if( rc==SQLITE_OK ) rc = SQLITE_ERROR; - assert( *ppVtab==0 ); - assert( pRtree->nBusy==1 ); - rtreeRelease(pRtree); - return rc; -} - - -/* -** GEOPOLY virtual table module xCreate method. -*/ -static int geopolyCreate( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); -} - -/* -** GEOPOLY virtual table module xConnect method. -*/ -static int geopolyConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); -} - - -/* -** GEOPOLY virtual table module xFilter method. -** -** Query plans: -** -** 1 rowid lookup -** 2 search for objects overlapping the same bounding box -** that contains polygon argv[0] -** 3 search for objects overlapping the same bounding box -** that contains polygon argv[0] -** 4 full table scan -*/ -static int geopolyFilter( - sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ - int idxNum, /* Query plan */ - const char *idxStr, /* Not Used */ - int argc, sqlite3_value **argv /* Parameters to the query plan */ -){ - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - RtreeNode *pRoot = 0; - int rc = SQLITE_OK; - int iCell = 0; - (void)idxStr; - - rtreeReference(pRtree); - - /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ - resetCursor(pCsr); - - pCsr->iStrategy = idxNum; - if( idxNum==1 ){ - /* Special case - lookup by rowid. */ - RtreeNode *pLeaf; /* Leaf on which the required cell resides */ - RtreeSearchPoint *p; /* Search point for the leaf */ - i64 iRowid = sqlite3_value_int64(argv[0]); - i64 iNode = 0; - rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); - if( rc==SQLITE_OK && pLeaf!=0 ){ - p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); - assert( p!=0 ); /* Always returns pCsr->sPoint */ - pCsr->aNode[0] = pLeaf; - p->id = iNode; - p->eWithin = PARTLY_WITHIN; - rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); - p->iCell = (u8)iCell; - RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); - }else{ - pCsr->atEOF = 1; - } - }else{ - /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array - ** with the configured constraints. - */ - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - if( rc==SQLITE_OK && idxNum<=3 ){ - RtreeCoord bbox[4]; - RtreeConstraint *p; - assert( argc==1 ); - assert( argv[0]!=0 ); - geopolyBBox(0, argv[0], bbox, &rc); - if( rc ){ - goto geopoly_filter_end; - } - pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); - pCsr->nConstraint = 4; - if( p==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); - memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); - if( idxNum==2 ){ - /* Overlap query */ - p->op = 'B'; - p->iCoord = 0; - p->u.rValue = bbox[1].f; - p++; - p->op = 'D'; - p->iCoord = 1; - p->u.rValue = bbox[0].f; - p++; - p->op = 'B'; - p->iCoord = 2; - p->u.rValue = bbox[3].f; - p++; - p->op = 'D'; - p->iCoord = 3; - p->u.rValue = bbox[2].f; - }else{ - /* Within query */ - p->op = 'D'; - p->iCoord = 0; - p->u.rValue = bbox[0].f; - p++; - p->op = 'B'; - p->iCoord = 1; - p->u.rValue = bbox[1].f; - p++; - p->op = 'D'; - p->iCoord = 2; - p->u.rValue = bbox[2].f; - p++; - p->op = 'B'; - p->iCoord = 3; - p->u.rValue = bbox[3].f; - } - } - } - if( rc==SQLITE_OK ){ - RtreeSearchPoint *pNew; - pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - goto geopoly_filter_end; - } - pNew->id = 1; - pNew->iCell = 0; - pNew->eWithin = PARTLY_WITHIN; - assert( pCsr->bPoint==1 ); - pCsr->aNode[0] = pRoot; - pRoot = 0; - RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); - rc = rtreeStepToLeaf(pCsr); - } - } - -geopoly_filter_end: - nodeRelease(pRtree, pRoot); - rtreeRelease(pRtree); - return rc; -} - -/* -** Rtree virtual table module xBestIndex method. There are three -** table scan strategies to choose from (in order from most to -** least desirable): -** -** idxNum idxStr Strategy -** ------------------------------------------------ -** 1 "rowid" Direct lookup by rowid. -** 2 "rtree" R-tree overlap query using geopoly_overlap() -** 3 "rtree" R-tree within query using geopoly_within() -** 4 "fullscan" full-table scan. -** ------------------------------------------------ -*/ -static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int ii; - int iRowidTerm = -1; - int iFuncTerm = -1; - int idxNum = 0; - (void)tab; - - for(ii=0; iinConstraint; ii++){ - struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - if( !p->usable ) continue; - if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - iRowidTerm = ii; - break; - } - if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ - /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap() - ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within(). - ** See geopolyFindFunction() */ - iFuncTerm = ii; - idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2; - } - } - - if( iRowidTerm>=0 ){ - pIdxInfo->idxNum = 1; - pIdxInfo->idxStr = "rowid"; - pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; - pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; - pIdxInfo->estimatedCost = 30.0; - pIdxInfo->estimatedRows = 1; - pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; - return SQLITE_OK; - } - if( iFuncTerm>=0 ){ - pIdxInfo->idxNum = idxNum; - pIdxInfo->idxStr = "rtree"; - pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; - pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; - pIdxInfo->estimatedCost = 300.0; - pIdxInfo->estimatedRows = 10; - return SQLITE_OK; - } - pIdxInfo->idxNum = 4; - pIdxInfo->idxStr = "fullscan"; - pIdxInfo->estimatedCost = 3000000.0; - pIdxInfo->estimatedRows = 100000; - return SQLITE_OK; -} - - -/* -** GEOPOLY virtual table module xColumn method. -*/ -static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - Rtree *pRtree = (Rtree *)cur->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)cur; - RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); - int rc = SQLITE_OK; - RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - - if( rc ) return rc; - if( p==0 ) return SQLITE_OK; - if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK; - if( i<=pRtree->nAux ){ - if( !pCsr->bAuxValid ){ - if( pCsr->pReadAux==0 ){ - rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, - &pCsr->pReadAux, 0); - if( rc ) return rc; - } - sqlite3_bind_int64(pCsr->pReadAux, 1, - nodeGetRowid(pRtree, pNode, p->iCell)); - rc = sqlite3_step(pCsr->pReadAux); - if( rc==SQLITE_ROW ){ - pCsr->bAuxValid = 1; - }else{ - sqlite3_reset(pCsr->pReadAux); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - return rc; - } - } - sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); - } - return SQLITE_OK; -} - - -/* -** The xUpdate method for GEOPOLY module virtual tables. -** -** For DELETE: -** -** argv[0] = the rowid to be deleted -** -** For INSERT: -** -** argv[0] = SQL NULL -** argv[1] = rowid to insert, or an SQL NULL to select automatically -** argv[2] = _shape column -** argv[3] = first application-defined column.... -** -** For UPDATE: -** -** argv[0] = rowid to modify. Never NULL -** argv[1] = rowid after the change. Never NULL -** argv[2] = new value for _shape -** argv[3] = new value for first application-defined column.... -*/ -static int geopolyUpdate( - sqlite3_vtab *pVtab, - int nData, - sqlite3_value **aData, - sqlite_int64 *pRowid -){ - Rtree *pRtree = (Rtree *)pVtab; - int rc = SQLITE_OK; - RtreeCell cell; /* New cell to insert if nData>1 */ - i64 oldRowid; /* The old rowid */ - int oldRowidValid; /* True if oldRowid is valid */ - i64 newRowid; /* The new rowid */ - int newRowidValid; /* True if newRowid is valid */ - int coordChange = 0; /* Change in coordinates */ - - if( pRtree->nNodeRef ){ - /* Unable to write to the btree while another cursor is reading from it, - ** since the write might do a rebalance which would disrupt the read - ** cursor. */ - return SQLITE_LOCKED_VTAB; - } - rtreeReference(pRtree); - assert(nData>=1); - - oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; - oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; - newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; - newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; - cell.iRowid = newRowid; - - if( nData>1 /* not a DELETE */ - && (!oldRowidValid /* INSERT */ - || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */ - || oldRowid!=newRowid) /* Rowid change */ - ){ - assert( aData[2]!=0 ); - geopolyBBox(0, aData[2], cell.aCoord, &rc); - if( rc ){ - if( rc==SQLITE_ERROR ){ - pVtab->zErrMsg = - sqlite3_mprintf("_shape does not contain a valid polygon"); - } - goto geopoly_update_end; - } - coordChange = 1; - - /* If a rowid value was supplied, check if it is already present in - ** the table. If so, the constraint has failed. */ - if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){ - int steprc; - sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); - steprc = sqlite3_step(pRtree->pReadRowid); - rc = sqlite3_reset(pRtree->pReadRowid); - if( SQLITE_ROW==steprc ){ - if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ - rc = rtreeDeleteRowid(pRtree, cell.iRowid); - }else{ - rc = rtreeConstraintError(pRtree, 0); - } - } - } - } - - /* If aData[0] is not an SQL NULL value, it is the rowid of a - ** record to delete from the r-tree table. The following block does - ** just that. - */ - if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ - rc = rtreeDeleteRowid(pRtree, oldRowid); - } - - /* If the aData[] array contains more than one element, elements - ** (aData[2]..aData[argc-1]) contain a new record to insert into - ** the r-tree structure. - */ - if( rc==SQLITE_OK && nData>1 && coordChange ){ - /* Insert the new record into the r-tree */ - RtreeNode *pLeaf = 0; - if( !newRowidValid ){ - rc = rtreeNewRowid(pRtree, &cell.iRowid); - } - *pRowid = cell.iRowid; - if( rc==SQLITE_OK ){ - rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); - } - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); - rc2 = nodeRelease(pRtree, pLeaf); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - /* Change the data */ - if( rc==SQLITE_OK && nData>1 ){ - sqlite3_stmt *pUp = pRtree->pWriteAux; - int jj; - int nChange = 0; - sqlite3_bind_int64(pUp, 1, cell.iRowid); - assert( pRtree->nAux>=1 ); - if( sqlite3_value_nochange(aData[2]) ){ - sqlite3_bind_null(pUp, 2); - }else{ - GeoPoly *p = 0; - if( sqlite3_value_type(aData[2])==SQLITE_TEXT - && (p = geopolyFuncParam(0, aData[2], &rc))!=0 - && rc==SQLITE_OK - ){ - sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); - }else{ - sqlite3_bind_value(pUp, 2, aData[2]); - } - sqlite3_free(p); - nChange = 1; - } - for(jj=1; jjiSize = nBlob; + pBlob->magic = RTREE_GEOMETRY_MAGIC; pBlob->cb = pGeomCtx[0]; pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg]; pBlob->nParam = nArg; for(i=0; iapSqlParam[i] = sqlite3_value_dup(aArg[i]); @@ -218292,11 +168903,11 @@ } if( memErr ){ sqlite3_result_error_nomem(ctx); rtreeMatchArgFree(pBlob); }else{ - sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree); + sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree); } } } /* @@ -218315,11 +168926,11 @@ if( !pGeomCtx ) return SQLITE_NOMEM; pGeomCtx->xGeom = xGeom; pGeomCtx->xQueryFunc = 0; pGeomCtx->xDestructor = 0; pGeomCtx->pContext = pContext; - return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, + return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback ); } /* @@ -218335,24 +168946,21 @@ ){ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ /* Allocate and populate the context object. */ pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); - if( !pGeomCtx ){ - if( xDestructor ) xDestructor(pContext); - return SQLITE_NOMEM; - } + if( !pGeomCtx ) return SQLITE_NOMEM; pGeomCtx->xGeom = 0; pGeomCtx->xQueryFunc = xQueryFunc; pGeomCtx->xDestructor = xDestructor; pGeomCtx->pContext = pContext; - return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, + return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback ); } -#ifndef SQLITE_CORE +#if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif SQLITE_API int sqlite3_rtree_init( sqlite3 *db, @@ -218379,13 +168987,13 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $ ** -** This file implements an integration between the ICU library -** ("International Components for Unicode", an open-source library -** for handling unicode data) and SQLite. The integration uses +** This file implements an integration between the ICU library +** ("International Components for Unicode", an open-source library +** for handling unicode data) and SQLite. The integration uses ** ICU to provide the following to SQLite: ** ** * An implementation of the SQL regexp() function (and hence REGEXP ** operator) using the ICU uregex_XX() APIs. ** @@ -218392,17 +169000,15 @@ ** * Implementations of the SQL scalar upper() and lower() functions ** for case mapping. ** ** * Integration of ICU and SQLite collation sequences. ** -** * An implementation of the LIKE operator that uses ICU to +** * An implementation of the LIKE operator that uses ICU to ** provide case-independent matching. */ -#if !defined(SQLITE_CORE) \ - || defined(SQLITE_ENABLE_ICU) \ - || defined(SQLITE_ENABLE_ICU_COLLATIONS) +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) /* Include ICU headers */ #include #include #include @@ -218415,30 +169021,10 @@ SQLITE_EXTENSION_INIT1 #else /* #include "sqlite3.h" */ #endif -/* -** This function is called when an ICU function called from within -** the implementation of an SQL scalar function returns an error. -** -** The scalar function context passed as the first argument is -** loaded with an error message based on the following two args. -*/ -static void icuFunctionError( - sqlite3_context *pCtx, /* SQLite scalar function context */ - const char *zName, /* Name of ICU function that failed */ - UErrorCode e /* Error code returned by ICU function */ -){ - char zBuf[128]; - sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); - zBuf[127] = '\0'; - sqlite3_result_error(pCtx, zBuf, -1); -} - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) - /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. */ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH @@ -218484,27 +169070,27 @@ } /* ** Compare two UTF-8 strings for equality where the first string is -** a "LIKE" expression. Return true (1) if they are the same and +** a "LIKE" expression. Return true (1) if they are the same and ** false (0) if they are different. */ static int icuLikeCompare( const uint8_t *zPattern, /* LIKE pattern */ const uint8_t *zString, /* The UTF-8 string to compare against */ const UChar32 uEsc /* The escape character */ ){ - static const uint32_t MATCH_ONE = (uint32_t)'_'; - static const uint32_t MATCH_ALL = (uint32_t)'%'; + static const int MATCH_ONE = (UChar32)'_'; + static const int MATCH_ALL = (UChar32)'%'; int prevEscape = 0; /* True if the previous character was uEsc */ while( 1 ){ /* Read (and consume) the next character from the input pattern. */ - uint32_t uPattern; + UChar32 uPattern; SQLITE_ICU_READ_UTF8(zPattern, uPattern); if( uPattern==0 ) break; /* There are now 4 possibilities: ** @@ -218511,16 +169097,16 @@ ** 1. uPattern is an unescaped match-all character "%", ** 2. uPattern is an unescaped match-one character "_", ** 3. uPattern is an unescaped escape character, or ** 4. uPattern is to be handled as an ordinary character */ - if( uPattern==MATCH_ALL && !prevEscape && uPattern!=(uint32_t)uEsc ){ + if( !prevEscape && uPattern==MATCH_ALL ){ /* Case 1. */ uint8_t c; /* Skip any MATCH_ALL or MATCH_ONE characters that follow a - ** MATCH_ALL. For each MATCH_ONE, skip one character in the + ** MATCH_ALL. For each MATCH_ONE, skip one character in the ** test string. */ while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){ if( c==MATCH_ONE ){ if( *zString==0 ) return 0; @@ -218537,25 +169123,25 @@ } SQLITE_ICU_SKIP_UTF8(zString); } return 0; - }else if( uPattern==MATCH_ONE && !prevEscape && uPattern!=(uint32_t)uEsc ){ + }else if( !prevEscape && uPattern==MATCH_ONE ){ /* Case 2. */ if( *zString==0 ) return 0; SQLITE_ICU_SKIP_UTF8(zString); - }else if( uPattern==(uint32_t)uEsc && !prevEscape ){ + }else if( !prevEscape && uPattern==uEsc){ /* Case 3. */ prevEscape = 1; }else{ /* Case 4. */ - uint32_t uString; + UChar32 uString; SQLITE_ICU_READ_UTF8(zString, uString); - uString = (uint32_t)u_foldCase((UChar32)uString, U_FOLD_CASE_DEFAULT); - uPattern = (uint32_t)u_foldCase((UChar32)uPattern, U_FOLD_CASE_DEFAULT); + uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); + uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); if( uString!=uPattern ){ return 0; } prevEscape = 0; } @@ -218569,19 +169155,19 @@ ** the build-in LIKE operator. The first argument to the function is the ** pattern and the second argument is the string. So, the SQL statements: ** ** A LIKE B ** -** is implemented as like(B, A). If there is an escape character E, +** is implemented as like(B, A). If there is an escape character E, ** ** A LIKE B ESCAPE E ** ** is mapped to like(B, A, E). */ static void icuLikeFunc( - sqlite3_context *context, - int argc, + sqlite3_context *context, + int argc, sqlite3_value **argv ){ const unsigned char *zA = sqlite3_value_text(argv[0]); const unsigned char *zB = sqlite3_value_text(argv[1]); UChar32 uEsc = 0; @@ -218603,20 +169189,38 @@ const unsigned char *zE = sqlite3_value_text(argv[2]); int i = 0; if( zE==0 ) return; U8_NEXT(zE, i, nE, uEsc); if( i!=nE){ - sqlite3_result_error(context, + sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } } if( zA && zB ){ sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc)); } } + +/* +** This function is called when an ICU function called from within +** the implementation of an SQL scalar function returns an error. +** +** The scalar function context passed as the first argument is +** loaded with an error message based on the following two args. +*/ +static void icuFunctionError( + sqlite3_context *pCtx, /* SQLite scalar function context */ + const char *zName, /* Name of ICU function that failed */ + UErrorCode e /* Error code returned by ICU function */ +){ + char zBuf[128]; + sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); + zBuf[127] = '\0'; + sqlite3_result_error(pCtx, zBuf, -1); +} /* ** Function to delete compiled regexp objects. Registered as ** a destructor function with sqlite3_set_auxdata(). */ @@ -218626,11 +169230,11 @@ } /* ** Implementation of SQLite REGEXP operator. This scalar function takes ** two arguments. The first is a regular expression pattern to compile -** the second is a string to match against that pattern. If either +** the second is a string to match against that pattern. If either ** argument is an SQL NULL, then NULL Is returned. Otherwise, the result ** is 1 if the string matches the pattern, or 0 otherwise. ** ** SQLite maps the regexp() function to the regexp() operator such ** that the following two are equivalent: @@ -218650,12 +169254,12 @@ UBool res; const UChar *zString = sqlite3_value_text16(apArg[1]); (void)nArg; /* Unused parameter */ - /* If the left hand side of the regexp operator is NULL, - ** then the result is also NULL. + /* If the left hand side of the regexp operator is NULL, + ** then the result is also NULL. */ if( !zString ){ return; } @@ -218667,13 +169271,12 @@ } pExpr = uregex_open(zPattern, -1, 0, 0, &status); if( U_SUCCESS(status) ){ sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete); - pExpr = sqlite3_get_auxdata(p, 0); - } - if( !pExpr ){ + }else{ + assert(!pExpr); icuFunctionError(p, "uregex_open", status); return; } } @@ -218690,11 +169293,11 @@ icuFunctionError(p, "uregex_matches", status); return; } /* Set the text that the regular expression operates on to a NULL - ** pointer. This is not really necessary, but it is tidier than + ** pointer. This is not really necessary, but it is tidier than ** leaving the regular expression object configured with an invalid ** pointer after this function returns. */ uregex_setText(pExpr, 0, 0, &status); @@ -218701,19 +169304,19 @@ /* Return 1 or 0. */ sqlite3_result_int(p, res ? 1 : 0); } /* -** Implementations of scalar functions for case mapping - upper() and +** Implementations of scalar functions for case mapping - upper() and ** lower(). Function upper() converts its input to upper-case (ABC). ** Function lower() converts to lower-case (abc). ** ** ICU provides two types of case mapping, "general" case mapping and ** "language specific". Refer to ICU documentation for the differences ** between the two. ** -** To utilise "general" case mapping, the upper() or lower() scalar +** To utilise "general" case mapping, the upper() or lower() scalar ** functions are invoked with one argument: ** ** upper('ABC') -> 'abc' ** lower('abc') -> 'ABC' ** @@ -218780,12 +169383,10 @@ return; } assert( 0 ); /* Unreachable */ } -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ - /* ** Collation sequence destructor function. The pCtx argument points to ** a UCollator structure previously allocated using ucol_open(). */ static void icuCollationDel(void *pCtx){ @@ -218817,11 +169418,11 @@ } /* ** Implementation of the scalar function icu_load_collation(). ** -** This scalar function is used to add ICU collation based collation +** This scalar function is used to add ICU collation based collation ** types to an SQLite database connection. It is intended to be called ** as follows: ** ** SELECT icu_load_collation(, ); ** @@ -218828,22 +169429,22 @@ ** Where is a string containing an ICU locale identifier (i.e. ** "en_AU", "tr_TR" etc.) and is the name of the ** collation sequence to create. */ static void icuLoadCollation( - sqlite3_context *p, - int nArg, + sqlite3_context *p, + int nArg, sqlite3_value **apArg ){ sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); UErrorCode status = U_ZERO_ERROR; const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ const char *zName; /* SQL Collation sequence name (eg. "japanese") */ UCollator *pUCollator; /* ICU library collation object */ int rc; /* Return code from sqlite3_create_collation_x() */ - assert(nArg==2 || nArg==3); + assert(nArg==2); (void)nArg; /* Unused parameter */ zLocale = (const char *)sqlite3_value_text(apArg[0]); zName = (const char *)sqlite3_value_text(apArg[1]); if( !zLocale || !zName ){ @@ -218854,44 +169455,12 @@ if( !U_SUCCESS(status) ){ icuFunctionError(p, "ucol_open", status); return; } assert(p); - if(nArg==3){ - const char *zOption = (const char*)sqlite3_value_text(apArg[2]); - static const struct { - const char *zName; - UColAttributeValue val; - } aStrength[] = { - { "PRIMARY", UCOL_PRIMARY }, - { "SECONDARY", UCOL_SECONDARY }, - { "TERTIARY", UCOL_TERTIARY }, - { "DEFAULT", UCOL_DEFAULT_STRENGTH }, - { "QUARTERNARY", UCOL_QUATERNARY }, - { "IDENTICAL", UCOL_IDENTICAL }, - }; - unsigned int i; - for(i=0; i=sizeof(aStrength)/sizeof(aStrength[0]) ){ - sqlite3_str *pStr = sqlite3_str_new(sqlite3_context_db_handle(p)); - sqlite3_str_appendf(pStr, - "unknown collation strength \"%s\" - should be one of:", - zOption); - for(i=0; izName, p->nArg, p->enc, + db, p->zName, p->nArg, p->enc, p->iContext ? (void*)db : (void*)0, p->xFunc, 0, 0 ); } return rc; } -#ifndef SQLITE_CORE +#if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif SQLITE_API int sqlite3_icu_init( - sqlite3 *db, + sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3IcuInit(db); @@ -219019,11 +169585,11 @@ int n = 0; if( argc>0 ){ n = strlen(argv[0])+1; } - p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n); + p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n); if( !p ){ return SQLITE_NOMEM; } memset(p, 0, sizeof(IcuTokenizer)); @@ -219047,11 +169613,11 @@ } /* ** Prepare to begin tokenizing a particular string. The input ** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in +** used to incrementally tokenize this string is returned in ** *ppCursor. */ static int icuOpen( sqlite3_tokenizer *pTokenizer, /* The tokenizer */ const char *zInput, /* Input string */ @@ -219076,11 +169642,11 @@ zInput = ""; }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; - pCsr = (IcuCursor *)sqlite3_malloc64( + pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ ); if( !pCsr ){ @@ -219089,11 +169655,11 @@ memset(pCsr, 0, sizeof(IcuCursor)); pCsr->aChar = (UChar *)&pCsr[1]; pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3]; pCsr->aOffset[iOut] = iInput; - U8_NEXT(zInput, iInput, nInput, c); + U8_NEXT(zInput, iInput, nInput, c); while( c>0 ){ int isError = 0; c = u_foldCase(c, opt); U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); if( isError ){ @@ -219235,55 +169801,55 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** -** OVERVIEW +** OVERVIEW ** ** The RBU extension requires that the RBU update be packaged as an ** SQLite database. The tables it expects to find are described in ** sqlite3rbu.h. Essentially, for each table xyz in the target database ** that the user wishes to write to, a corresponding data_xyz table is ** created in the RBU database and populated with one row for each row to ** update, insert or delete from the target table. -** +** ** The update proceeds in three stages: -** +** ** 1) The database is updated. The modified database pages are written ** to a *-oal file. A *-oal file is just like a *-wal file, except ** that it is named "-oal" instead of "-wal". ** Because regular SQLite clients do not look for file named ** "-oal", they go on using the original database in ** rollback mode while the *-oal file is being generated. -** +** ** During this stage RBU does not update the database by writing ** directly to the target tables. Instead it creates "imposter" ** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses ** to update each b-tree individually. All updates required by each ** b-tree are completed before moving on to the next, and all ** updates are done in sorted key order. -** +** ** 2) The "-oal" file is moved to the equivalent "-wal" ** location using a call to rename(2). Before doing this the RBU ** module takes an EXCLUSIVE lock on the database file, ensuring ** that there are no other active readers. -** +** ** Once the EXCLUSIVE lock is released, any other database readers ** detect the new *-wal file and read the database in wal mode. At ** this point they see the new version of the database - including ** the updates made as part of the RBU update. -** -** 3) The new *-wal file is checkpointed. This proceeds in the same way +** +** 3) The new *-wal file is checkpointed. This proceeds in the same way ** as a regular database checkpoint, except that a single frame is ** checkpointed each time sqlite3rbu_step() is called. If the RBU ** handle is closed before the entire *-wal file is checkpointed, ** the checkpoint progress is saved in the RBU database and the ** checkpoint can be resumed by another RBU client at some point in ** the future. ** ** POTENTIAL PROBLEMS -** +** ** The rename() call might not be portable. And RBU is not currently ** syncing the directory after renaming the file. ** ** When state is saved, any commit to the *-oal file and the commit to ** the RBU update database are not atomic. So if the power fails at the @@ -219301,11 +169867,11 @@ ** At present, for an UPDATE, both the new.* and old.* records are ** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all ** fields are collected. This means we're probably writing a lot more ** data to disk when saving the state of an ongoing update to the RBU ** update database than is strictly necessary. -** +** */ /* #include */ /* #include */ /* #include */ @@ -219325,46 +169891,46 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** -** This file contains the public interface for the RBU extension. +** This file contains the public interface for the RBU extension. */ /* ** SUMMARY ** -** Writing a transaction containing a large number of operations on +** Writing a transaction containing a large number of operations on ** b-tree indexes that are collectively larger than the available cache -** memory can be very inefficient. +** memory can be very inefficient. ** ** The problem is that in order to update a b-tree, the leaf page (at least) ** containing the entry being inserted or deleted must be modified. If the -** working set of leaves is larger than the available cache memory, then a -** single leaf that is modified more than once as part of the transaction +** working set of leaves is larger than the available cache memory, then a +** single leaf that is modified more than once as part of the transaction ** may be loaded from or written to the persistent media multiple times. ** Additionally, because the index updates are likely to be applied in -** random order, access to pages within the database is also likely to be in +** random order, access to pages within the database is also likely to be in ** random order, which is itself quite inefficient. ** ** One way to improve the situation is to sort the operations on each index ** by index key before applying them to the b-tree. This leads to an IO ** pattern that resembles a single linear scan through the index b-tree, -** and all but guarantees each modified leaf page is loaded and stored +** and all but guarantees each modified leaf page is loaded and stored ** exactly once. SQLite uses this trick to improve the performance of ** CREATE INDEX commands. This extension allows it to be used to improve ** the performance of large transactions on existing databases. ** -** Additionally, this extension allows the work involved in writing the -** large transaction to be broken down into sub-transactions performed -** sequentially by separate processes. This is useful if the system cannot -** guarantee that a single update process will run for long enough to apply -** the entire update, for example because the update is being applied on a -** mobile device that is frequently rebooted. Even after the writer process +** Additionally, this extension allows the work involved in writing the +** large transaction to be broken down into sub-transactions performed +** sequentially by separate processes. This is useful if the system cannot +** guarantee that a single update process will run for long enough to apply +** the entire update, for example because the update is being applied on a +** mobile device that is frequently rebooted. Even after the writer process ** has committed one or more sub-transactions, other database clients continue -** to read from the original database snapshot. In other words, partially -** applied transactions are not visible to other clients. +** to read from the original database snapshot. In other words, partially +** applied transactions are not visible to other clients. ** ** "RBU" stands for "Resumable Bulk Update". As in a large database update ** transmitted via a wireless network to a mobile device. A transaction ** applied using this extension is hence refered to as an "RBU update". ** @@ -219376,13 +169942,13 @@ ** * The transaction must consist of INSERT, UPDATE and DELETE operations ** only. ** ** * INSERT statements may not use any default values. ** -** * UPDATE and DELETE statements must identify their target rows by +** * UPDATE and DELETE statements must identify their target rows by ** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY -** KEY fields may not be updated or deleted. If the table being written +** KEY fields may not be updated or deleted. If the table being written ** has no PRIMARY KEY, affected rows must be identified by rowid. ** ** * UPDATE statements may not modify PRIMARY KEY columns. ** ** * No triggers will be fired. @@ -219395,14 +169961,14 @@ ** ** ** PREPARATION ** ** An "RBU update" is stored as a separate SQLite database. A database -** containing an RBU update is an "RBU database". For each table in the +** containing an RBU update is an "RBU database". For each table in the ** target database to be updated, the RBU database should contain a table ** named "data_" containing the same set of columns as the -** target table, and one more - "rbu_control". The data_% table should +** target table, and one more - "rbu_control". The data_% table should ** have no PRIMARY KEY or UNIQUE constraints, but each column should have ** the same type as the corresponding column in the target database. ** The "rbu_control" column should have no type at all. For example, if ** the target database contains: ** @@ -219413,26 +169979,26 @@ ** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control); ** ** The order of the columns in the data_% table does not matter. ** ** Instead of a regular table, the RBU database may also contain virtual -** tables or views named using the data_ naming scheme. +** tables or view named using the data_ naming scheme. ** -** Instead of the plain data_ naming scheme, RBU database tables +** Instead of the plain data_ naming scheme, RBU database tables ** may also be named data_, where is any sequence ** of zero or more numeric characters (0-9). This can be significant because -** tables within the RBU database are always processed in order sorted by +** tables within the RBU database are always processed in order sorted by ** name. By judicious selection of the portion of the names ** of the RBU tables the user can therefore control the order in which they ** are processed. This can be useful, for example, to ensure that "external ** content" FTS4 tables are updated before their underlying content tables. ** ** If the target database table is a virtual table or a table that has no -** PRIMARY KEY declaration, the data_% table must also contain a column -** named "rbu_rowid". This column is mapped to the table's implicit primary -** key column - "rowid". Virtual tables for which the "rowid" column does -** not function like a primary key value cannot be updated using RBU. For +** PRIMARY KEY declaration, the data_% table must also contain a column +** named "rbu_rowid". This column is mapped to the tables implicit primary +** key column - "rowid". Virtual tables for which the "rowid" column does +** not function like a primary key value cannot be updated using RBU. For ** example, if the target db contains either of the following: ** ** CREATE VIRTUAL TABLE x1 USING fts3(a, b); ** CREATE TABLE x1(a, b) ** @@ -219451,39 +170017,39 @@ ** Either of the following input table schemas may be used: ** ** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control); ** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control); ** -** For each row to INSERT into the target database as part of the RBU +** For each row to INSERT into the target database as part of the RBU ** update, the corresponding data_% table should contain a single record ** with the "rbu_control" column set to contain integer value 0. The -** other columns should be set to the values that make up the new record -** to insert. +** other columns should be set to the values that make up the new record +** to insert. ** -** If the target database table has an INTEGER PRIMARY KEY, it is not -** possible to insert a NULL value into the IPK column. Attempting to +** If the target database table has an INTEGER PRIMARY KEY, it is not +** possible to insert a NULL value into the IPK column. Attempting to ** do so results in an SQLITE_MISMATCH error. ** -** For each row to DELETE from the target database as part of the RBU +** For each row to DELETE from the target database as part of the RBU ** update, the corresponding data_% table should contain a single record ** with the "rbu_control" column set to contain integer value 1. The ** real primary key values of the row to delete should be stored in the ** corresponding columns of the data_% table. The values stored in the ** other columns are not used. ** -** For each row to UPDATE from the target database as part of the RBU +** For each row to UPDATE from the target database as part of the RBU ** update, the corresponding data_% table should contain a single record ** with the "rbu_control" column set to contain a value of type text. -** The real primary key values identifying the row to update should be +** The real primary key values identifying the row to update should be ** stored in the corresponding columns of the data_% table row, as should -** the new values of all columns being update. The text value in the +** the new values of all columns being update. The text value in the ** "rbu_control" column must contain the same number of characters as ** there are columns in the target database table, and must consist entirely -** of 'x' and '.' characters (or in some special cases 'd' - see below). For +** of 'x' and '.' characters (or in some special cases 'd' - see below). For ** each column that is being updated, the corresponding character is set to ** 'x'. For those that remain as they are, the corresponding character of the -** rbu_control value should be set to '.'. For example, given the tables +** rbu_control value should be set to '.'. For example, given the tables ** above, the update statement: ** ** UPDATE t1 SET c = 'usa' WHERE a = 4; ** ** is represented by the data_t1 row created by: @@ -219493,51 +170059,51 @@ ** Instead of an 'x' character, characters of the rbu_control value specified ** for UPDATEs may also be set to 'd'. In this case, instead of updating the ** target table with the value stored in the corresponding data_% column, the ** user-defined SQL function "rbu_delta()" is invoked and the result stored in ** the target table column. rbu_delta() is invoked with two arguments - the -** original value currently stored in the target table column and the +** original value currently stored in the target table column and the ** value specified in the data_xxx table. ** ** For example, this row: ** ** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d'); ** -** is similar to an UPDATE statement such as: +** is similar to an UPDATE statement such as: ** ** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4; ** -** Finally, if an 'f' character appears in place of a 'd' or 's' in an +** Finally, if an 'f' character appears in place of a 'd' or 's' in an ** ota_control string, the contents of the data_xxx table column is assumed ** to be a "fossil delta" - a patch to be applied to a blob value in the ** format used by the fossil source-code management system. In this case -** the existing value within the target database table must be of type BLOB. +** the existing value within the target database table must be of type BLOB. ** It is replaced by the result of applying the specified fossil delta to ** itself. ** ** If the target database table is a virtual table or a table with no PRIMARY -** KEY, the rbu_control value should not include a character corresponding +** KEY, the rbu_control value should not include a character corresponding ** to the rbu_rowid value. For example, this: ** -** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) +** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) ** VALUES(NULL, 'usa', 12, '.x'); ** ** causes a result similar to: ** ** UPDATE ft1 SET b = 'usa' WHERE rowid = 12; ** ** The data_xxx tables themselves should have no PRIMARY KEY declarations. ** However, RBU is more efficient if reading the rows in from each data_xxx ** table in "rowid" order is roughly the same as reading them sorted by -** the PRIMARY KEY of the corresponding target database table. In other -** words, rows should be sorted using the destination table PRIMARY KEY +** the PRIMARY KEY of the corresponding target database table. In other +** words, rows should be sorted using the destination table PRIMARY KEY ** fields before they are inserted into the data_xxx tables. ** ** USAGE ** -** The API declared below allows an application to apply an RBU update -** stored on disk to an existing target database. Essentially, the +** The API declared below allows an application to apply an RBU update +** stored on disk to an existing target database. Essentially, the ** application: ** ** 1) Opens an RBU handle using the sqlite3rbu_open() function. ** ** 2) Registers any required virtual table modules with the database @@ -219544,28 +170110,28 @@ ** handle returned by sqlite3rbu_db(). Also, if required, register ** the rbu_delta() implementation. ** ** 3) Calls the sqlite3rbu_step() function one or more times on ** the new handle. Each call to sqlite3rbu_step() performs a single -** b-tree operation, so thousands of calls may be required to apply +** b-tree operation, so thousands of calls may be required to apply ** a complete update. ** ** 4) Calls sqlite3rbu_close() to close the RBU update handle. If ** sqlite3rbu_step() has been called enough times to completely ** apply the update to the target database, then the RBU database -** is marked as fully applied. Otherwise, the state of the RBU -** update application is saved in the RBU database for later +** is marked as fully applied. Otherwise, the state of the RBU +** update application is saved in the RBU database for later ** resumption. ** ** See comments below for more detail on APIs. ** ** If an update is only partially applied to the target database by the -** time sqlite3rbu_close() is called, various state information is saved +** time sqlite3rbu_close() is called, various state information is saved ** within the RBU database. This allows subsequent processes to automatically ** resume the RBU update from where it left off. ** -** To remove all RBU extension state information, returning an RBU database +** To remove all RBU extension state information, returning an RBU database ** to its original contents, it is sufficient to drop all tables that begin ** with the prefix "rbu_" ** ** DATABASE LOCKING ** @@ -219597,25 +170163,25 @@ ** ** Argument zTarget is the path to the target database. Argument zRbu is ** the path to the RBU database. Each call to this function must be matched ** by a call to sqlite3rbu_close(). When opening the databases, RBU passes ** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget -** or zRbu begin with "file:", it will be interpreted as an SQLite +** or zRbu begin with "file:", it will be interpreted as an SQLite ** database URI, not a regular file name. ** -** If the zState argument is passed a NULL value, the RBU extension stores -** the current state of the update (how many rows have been updated, which +** If the zState argument is passed a NULL value, the RBU extension stores +** the current state of the update (how many rows have been updated, which ** indexes are yet to be updated etc.) within the RBU database itself. This ** can be convenient, as it means that the RBU application does not need to -** organize removing a separate state file after the update is concluded. -** Or, if zState is non-NULL, it must be a path to a database file in which +** organize removing a separate state file after the update is concluded. +** Or, if zState is non-NULL, it must be a path to a database file in which ** the RBU extension can store the state of the update. ** ** When resuming an RBU update, the zState argument must be passed the same ** value as when the RBU update was started. ** -** Once the RBU update is finished, the RBU extension does not +** Once the RBU update is finished, the RBU extension does not ** automatically remove any zState database file, even if it created it. ** ** By default, RBU uses the default VFS to access the files on disk. To ** use a VFS other than the default, an SQLite "file:" URI containing a ** "vfs=..." option may be passed as the zTarget option. @@ -219624,81 +170190,55 @@ ** SQLite's built-in VFSs, including the multiplexor VFS. However it does ** not work out of the box with zipvfs. Refer to the comment describing ** the zipvfs_create_vfs() API below for details on using RBU with zipvfs. */ SQLITE_API sqlite3rbu *sqlite3rbu_open( - const char *zTarget, + const char *zTarget, const char *zRbu, const char *zState ); /* ** Open an RBU handle to perform an RBU vacuum on database file zTarget. ** An RBU vacuum is similar to SQLite's built-in VACUUM command, except ** that it can be suspended and resumed like an RBU update. ** -** The second argument to this function identifies a database in which -** to store the state of the RBU vacuum operation if it is suspended. The +** The second argument to this function identifies a database in which +** to store the state of the RBU vacuum operation if it is suspended. The ** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum ** operation, the state database should either not exist or be empty -** (contain no tables). If an RBU vacuum is suspended by calling +** (contain no tables). If an RBU vacuum is suspended by calling ** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has -** returned SQLITE_DONE, the vacuum state is stored in the state database. +** returned SQLITE_DONE, the vacuum state is stored in the state database. ** The vacuum can be resumed by calling this function to open a new RBU ** handle specifying the same target and state databases. ** ** If the second argument passed to this function is NULL, then the ** name of the state database is "-vacuum", where ** is the name of the target database file. In this case, on UNIX, if the ** state database is not already present in the file-system, it is created ** with the same permissions as the target db is made. ** -** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the -** state database ends with "-vactmp". This name is reserved for internal -** use. -** ** This function does not delete the state database after an RBU vacuum ** is completed, even if it created it. However, if the call to ** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents ** of the state tables within the state database are zeroed. This way, -** the next call to sqlite3rbu_vacuum() opens a handle that starts a +** the next call to sqlite3rbu_vacuum() opens a handle that starts a ** new RBU vacuum operation. ** ** As with sqlite3rbu_open(), Zipvfs users should rever to the comment -** describing the sqlite3rbu_create_vfs() API function below for -** a description of the complications associated with using RBU with +** describing the sqlite3rbu_create_vfs() API function below for +** a description of the complications associated with using RBU with ** zipvfs databases. */ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( - const char *zTarget, + const char *zTarget, const char *zState ); /* -** Configure a limit for the amount of temp space that may be used by -** the RBU handle passed as the first argument. The new limit is specified -** in bytes by the second parameter. If it is positive, the limit is updated. -** If the second parameter to this function is passed zero, then the limit -** is removed entirely. If the second parameter is negative, the limit is -** not modified (this is useful for querying the current limit). -** -** In all cases the returned value is the current limit in bytes (zero -** indicates unlimited). -** -** If the temp space limit is exceeded during operation, an SQLITE_FULL -** error is returned. -*/ -SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64); - -/* -** Return the current amount of temp file space, in bytes, currently used by -** the RBU handle passed as the only argument. -*/ -SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*); - -/* -** Internally, each RBU connection uses a separate SQLite database +** Internally, each RBU connection uses a separate SQLite database ** connection to access the target and rbu update databases. This ** API allows the application direct access to these database handles. ** ** The first argument passed to this function must be a valid, open, RBU ** handle. The second argument should be passed zero to access the target @@ -219705,14 +170245,14 @@ ** database handle, or non-zero to access the rbu update database handle. ** Accessing the underlying database handles may be useful in the ** following scenarios: ** ** * If any target tables are virtual tables, it may be necessary to -** call sqlite3_create_module() on the target database handle to +** call sqlite3_create_module() on the target database handle to ** register the required virtual table implementations. ** -** * If the data_xxx tables in the RBU source database are virtual +** * If the data_xxx tables in the RBU source database are virtual ** tables, the application may need to call sqlite3_create_module() on ** the rbu update db handle to any required virtual table ** implementations. ** ** * If the application uses the "rbu_delta()" feature described above, @@ -219727,16 +170267,16 @@ ** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db(). */ SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu); /* -** Do some work towards applying the RBU update to the target db. +** Do some work towards applying the RBU update to the target db. ** -** Return SQLITE_DONE if the update has been completely applied, or +** Return SQLITE_DONE if the update has been completely applied, or ** SQLITE_OK if no error occurs but there remains work to do to apply -** the RBU update. If an error does occur, some other error code is -** returned. +** the RBU update. If an error does occur, some other error code is +** returned. ** ** Once a call to sqlite3rbu_step() has returned a value other than ** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops ** that immediately return the same value. */ @@ -219745,19 +170285,19 @@ /* ** Force RBU to save its state to disk. ** ** If a power failure or application crash occurs during an update, following ** system recovery RBU may resume the update from the point at which the state -** was last saved. In other words, from the most recent successful call to +** was last saved. In other words, from the most recent successful call to ** sqlite3rbu_close() or this function. ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu); /* -** Close an RBU handle. +** Close an RBU handle. ** ** If the RBU update has been completely applied, mark the RBU database ** as fully applied. Otherwise, assuming no error has occurred, save the ** current state of the RBU update appliation to the RBU database. ** @@ -219767,24 +170307,24 @@ ** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted ** English language error message. It is the responsibility of the caller to ** eventually free any such buffer using sqlite3_free(). ** ** Otherwise, if no error occurs, this function returns SQLITE_OK if the -** update has been partially applied, or SQLITE_DONE if it has been +** update has been partially applied, or SQLITE_DONE if it has been ** completely applied. */ SQLITE_API int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); /* -** Return the total number of key-value operations (inserts, deletes or +** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current RBU update was started. */ SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); /* -** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100) +** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100) ** progress indications for the two stages of an RBU update. This API may ** be useful for driving GUI progress indicators and similar. ** ** An RBU update is divided into two stages: ** @@ -219793,20 +170333,20 @@ ** main database. ** ** The update is visible to non-RBU clients during stage 2. During stage 1 ** non-RBU reader clients may see the original database. ** -** If this API is called during stage 2 of the update, output variable +** If this API is called during stage 2 of the update, output variable ** (*pnOne) is set to 10000 to indicate that stage 1 has finished and (*pnTwo) ** to a value between 0 and 10000 to indicate the permyriadage progress of -** stage 2. A value of 5000 indicates that stage 2 is half finished, +** stage 2. A value of 5000 indicates that stage 2 is half finished, ** 9000 indicates that it is 90% finished, and so on. ** -** If this API is called during stage 1 of the update, output variable +** If this API is called during stage 1 of the update, output variable ** (*pnTwo) is set to 0 to indicate that stage 2 has not yet started. The -** value to which (*pnOne) is set depends on whether or not the RBU -** database contains an "rbu_count" table. The rbu_count table, if it +** value to which (*pnOne) is set depends on whether or not the RBU +** database contains an "rbu_count" table. The rbu_count table, if it ** exists, must contain the same columns as the following: ** ** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID; ** ** There must be one row in the table for each source (data_xxx) table within @@ -219819,11 +170359,11 @@ ** permyriadage progress of the same stage. If the rbu_count table does ** not exist, then (*pnOne) is set to -1 during stage 1. If the rbu_count ** table exists but is not correctly populated, the value of the *pnOne ** output variable during stage 1 is undefined. */ -SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo); +SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); /* ** Obtain an indication as to the current stage of an RBU update or vacuum. ** This function always returns one of the SQLITE_RBU_STATE_XXX constants ** defined in this file. Return values should be interpreted as follows: @@ -219858,55 +170398,27 @@ #define SQLITE_RBU_STATE_CHECKPOINT 3 #define SQLITE_RBU_STATE_DONE 4 #define SQLITE_RBU_STATE_ERROR 5 SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu); - -/* -** As part of applying an RBU update or performing an RBU vacuum operation, -** the system must at one point move the *-oal file to the equivalent *-wal -** path. Normally, it does this by invoking POSIX function rename(2) directly. -** Except on WINCE platforms, where it uses win32 API MoveFileW(). This -** function may be used to register a callback that the RBU module will invoke -** instead of one of these APIs. -** -** If a callback is registered with an RBU handle, it invokes it instead -** of rename(2) when it needs to move a file within the file-system. The -** first argument passed to the xRename() callback is a copy of the second -** argument (pArg) passed to this function. The second is the full path -** to the file to move and the third the full path to which it should be -** moved. The callback function should return SQLITE_OK to indicate -** success. If an error occurs, it should return an SQLite error code. -** In this case the RBU operation will be abandoned and the error returned -** to the RBU user. -** -** Passing a NULL pointer in place of the xRename argument to this function -** restores the default behaviour. -*/ -SQLITE_API void sqlite3rbu_rename_handler( - sqlite3rbu *pRbu, - void *pArg, - int (*xRename)(void *pArg, const char *zOld, const char *zNew) -); - /* ** Create an RBU VFS named zName that accesses the underlying file-system -** via existing VFS zParent. Or, if the zParent parameter is passed NULL, +** via existing VFS zParent. Or, if the zParent parameter is passed NULL, ** then the new RBU VFS uses the default system VFS to access the file-system. -** The new object is registered as a non-default VFS with SQLite before +** The new object is registered as a non-default VFS with SQLite before ** returning. ** ** Part of the RBU implementation uses a custom VFS object. Usually, this -** object is created and deleted automatically by RBU. +** object is created and deleted automatically by RBU. ** ** The exception is for applications that also use zipvfs. In this case, ** the custom VFS must be explicitly created by the user before the RBU ** handle is opened. The RBU VFS should be installed so that the zipvfs -** VFS uses the RBU VFS, which in turn uses any other VFS layers in use +** VFS uses the RBU VFS, which in turn uses any other VFS layers in use ** (for example multiplexor) to access the file-system. For example, -** to assemble an RBU enabled VFS stack that uses both zipvfs and +** to assemble an RBU enabled VFS stack that uses both zipvfs and ** multiplexor (error checking omitted): ** ** // Create a VFS named "multiplex" (not the default). ** sqlite3_multiplex_initialize(0, 0); ** @@ -219924,13 +170436,13 @@ ** ** Because the default VFS created above includes a RBU functionality, it ** may be used by RBU clients. Attempting to use RBU with a zipvfs VFS stack ** that does not include the RBU layer results in an error. ** -** The overhead of adding the "rbu" VFS to the system is negligible for -** non-RBU users. There is no harm in an application accessing the -** file-system via "rbu" all the time, even if it only uses RBU functionality +** The overhead of adding the "rbu" VFS to the system is negligible for +** non-RBU users. There is no harm in an application accessing the +** file-system via "rbu" all the time, even if it only uses RBU functionality ** occasionally. */ SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent); /* @@ -219957,50 +170469,36 @@ #endif /* Maximum number of prepared UPDATE statements held by this module */ #define SQLITE_RBU_UPDATE_CACHESIZE 16 -/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM -** to enable checksum verification. -*/ -#ifndef RBU_ENABLE_DELTA_CKSUM -# define RBU_ENABLE_DELTA_CKSUM 0 -#endif - /* ** Swap two objects of type TYPE. */ #if !defined(SQLITE_AMALGAMATION) # define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} #endif - -/* -** Name of the URI option that causes RBU to take an exclusive lock as -** part of the incremental checkpoint operation. -*/ -#define RBU_EXCLUSIVE_CHECKPOINT "rbu_exclusive_checkpoint" - /* ** The rbu_state table is used to save the state of a partially applied ** update so that it can be resumed later. The table consists of integer ** keys mapped to values as follows: ** ** RBU_STATE_STAGE: ** May be set to integer values 1, 2, 4 or 5. As follows: ** 1: the *-rbu file is currently under construction. -** 2: the *-rbu file has been constructed, but not yet moved +** 2: the *-rbu file has been constructed, but not yet moved ** to the *-wal path. ** 4: the checkpoint is underway. ** 5: the rbu update has been checkpointed. ** ** RBU_STATE_TBL: -** Only valid if STAGE==1. The target database name of the table +** Only valid if STAGE==1. The target database name of the table ** currently being written. ** ** RBU_STATE_IDX: -** Only valid if STAGE==1. The target database name of the index +** Only valid if STAGE==1. The target database name of the index ** currently being written, or NULL if the main table is currently being ** updated. ** ** RBU_STATE_ROW: ** Only valid if STAGE==1. Number of rows already processed for the current @@ -220016,19 +170514,15 @@ ** cases when another client appends frames to the *-wal file in the ** middle of an incremental checkpoint (an incremental checkpoint cannot ** be continued if this happens). ** ** RBU_STATE_COOKIE: -** Valid if STAGE==1. The current change-counter cookie value in the +** Valid if STAGE==1. The current change-counter cookie value in the ** target db file. ** ** RBU_STATE_OALSZ: ** Valid if STAGE==1. The size in bytes of the *-oal file. -** -** RBU_STATE_DATATBL: -** Only valid if STAGE==1. The RBU database name of the table -** currently being read. */ #define RBU_STATE_STAGE 1 #define RBU_STATE_TBL 2 #define RBU_STATE_IDX 3 #define RBU_STATE_ROW 4 @@ -220035,11 +170529,10 @@ #define RBU_STATE_PROGRESS 5 #define RBU_STATE_CKPT 6 #define RBU_STATE_COOKIE 7 #define RBU_STATE_OALSZ 8 #define RBU_STATE_PHASEONESTEP 9 -#define RBU_STATE_DATATBL 10 #define RBU_STAGE_OAL 1 #define RBU_STAGE_MOVE 2 #define RBU_STAGE_CAPTURE 3 #define RBU_STAGE_CKPT 4 @@ -220050,21 +170543,19 @@ "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" typedef struct RbuFrame RbuFrame; typedef struct RbuObjIter RbuObjIter; typedef struct RbuState RbuState; -typedef struct RbuSpan RbuSpan; typedef struct rbu_vfs rbu_vfs; typedef struct rbu_file rbu_file; typedef struct RbuUpdateStmt RbuUpdateStmt; #if !defined(SQLITE_AMALGAMATION) typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef sqlite3_int64 i64; -typedef sqlite3_uint64 u64; #endif /* ** These values must match the values defined in wal.c for the equivalent ** locks. These are not magic numbers as they are part of the SQLite file @@ -220080,11 +170571,10 @@ ** A structure to store values read from the rbu_state table in memory. */ struct RbuState { int eStage; char *zTbl; - char *zDataTbl; char *zIdx; i64 iWalCksum; int nRow; i64 nProgress; u32 iCookie; @@ -220096,35 +170586,25 @@ char *zMask; /* Copy of update mask used with pUpdate */ sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ RbuUpdateStmt *pNext; }; -struct RbuSpan { - const char *zSpan; - int nSpan; -}; - /* ** An iterator of this type is used to iterate through all objects in ** the target database that require updating. For each such table, the ** iterator visits, in order: ** -** * the table itself, +** * the table itself, ** * each index of the table (zero or more points to visit), and ** * a special "cleanup table" state. ** ** abIndexed: ** If the table has no indexes on it, abIndexed is set to NULL. Otherwise, ** it points to an array of flags nTblCol elements in size. The flag is ** set for each column that is either a part of the PK or a part of an ** index. Or clear otherwise. -** -** If there are one or more partial indexes on the table, all fields of -** this array set set to 1. This is because in that case, the module has -** no way to tell which fields will be required to add and remove entries -** from the partial indexes. -** +** */ struct RbuObjIter { sqlite3_stmt *pTblIter; /* Iterate through tables */ sqlite3_stmt *pIdxIter; /* Index iterator */ int nTblCol; /* Size of azTblCol[] array */ @@ -220150,13 +170630,10 @@ int nCol; /* Number of columns in current object */ sqlite3_stmt *pSelect; /* Source data */ sqlite3_stmt *pInsert; /* Statement for INSERT operations */ sqlite3_stmt *pDelete; /* Statement for DELETE ops */ sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ - int nIdxCol; - RbuSpan *aIdxCol; - char *zIdxSql; /* Last UPDATE used (for PK b-tree updates only), or NULL. */ RbuUpdateStmt *pRbuUpdate; }; @@ -220197,37 +170674,16 @@ struct RbuFrame { u32 iDbPage; u32 iWalFrame; }; -#ifndef UNUSED_PARAMETER -/* -** The following macros are used to suppress compiler warnings and to -** make it clear to human readers when a function parameter is deliberately -** left unused within the body of a function. This usually happens when -** a function is called via a function pointer. For example the -** implementation of an SQL aggregate step callback may not use the -** parameter indicating the number of arguments passed to the aggregate, -** if it knows that this is enforced elsewhere. -** -** When a function parameter is not used at all within the body of a function, -** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. -** However, these macros may also be used to suppress warnings related to -** parameters that may or may not be used depending on compilation options. -** For example those parameters only used in assert() statements. In these -** cases the parameters are named as per the usual conventions. -*/ -#define UNUSED_PARAMETER(x) (void)(x) -#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) -#endif - /* ** RBU handle. ** ** nPhaseOneStep: ** If the RBU database contains an rbu_count table, this value is set to -** a running estimate of the number of b-tree operations required to +** a running estimate of the number of b-tree operations required to ** finish populating the *-oal file. This allows the sqlite3_bp_progress() ** API to calculate the permyriadage progress of populating the *-oal file ** using the formula: ** ** permyriadage = (10000 * nProgress) / nPhaseOneStep @@ -220243,11 +170699,11 @@ ** This estimate is accurate if the RBU update consists entirely of ** INSERT operations. However, it is inaccurate if: ** ** * the RBU update contains any UPDATE operations. If the PK specified ** for an UPDATE operation does not exist in the target table, then -** no b-tree operations are required on index b-trees. Or if the +** no b-tree operations are required on index b-trees. Or if the ** specified PK does exist, then (nIndex*2) such operations are ** required (one delete and one insert on each index b-tree). ** ** * the RBU update contains any DELETE operations for which the specified ** PK does not exist. In this case no operations are required on index @@ -220269,19 +170725,17 @@ char *zState; /* Path to state db (or NULL if zRbu) */ char zStateDb[5]; /* Db name for state ("stat" or "main") */ int rc; /* Value returned by last rbu_step() call */ char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ - sqlite3_int64 nProgress; /* Rows processed for all objects */ + int nProgress; /* Rows processed for all objects */ RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ const char *zVfsName; /* Name of automatically created rbu vfs */ rbu_file *pTargetFd; /* File handle open on target db */ int nPagePerSector; /* Pages per sector for pTargetFd */ i64 iOalSz; i64 nPhaseOneStep; - void *pRenameArg; - int (*xRename)(void*, const char*, const char*); /* The following state variables are used as part of the incremental ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding ** function rbuSetupCheckpoint() for details. */ u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ @@ -220290,48 +170744,35 @@ int nFrameAlloc; /* Allocated size of aFrame[] array */ RbuFrame *aFrame; int pgsz; u8 *aBuf; i64 iWalCksum; - i64 szTemp; /* Current size of all temp files in use */ - i64 szTempLimit; /* Total size limit for temp files */ /* Used in RBU vacuum mode only */ int nRbu; /* Number of RBU VFS in the stack */ rbu_file *pRbuFd; /* Fd for main db of dbRbu */ }; /* ** An rbu VFS is implemented using an instance of this structure. -** -** Variable pRbu is only non-NULL for automatically created RBU VFS objects. -** It is NULL for RBU VFS objects created explicitly using -** sqlite3rbu_create_vfs(). It is used to track the total amount of temp -** space used by the RBU handle. */ struct rbu_vfs { sqlite3_vfs base; /* rbu VFS shim methods */ sqlite3_vfs *pRealVfs; /* Underlying VFS */ sqlite3_mutex *mutex; /* Mutex to protect pMain */ - sqlite3rbu *pRbu; /* Owner RBU object */ - rbu_file *pMain; /* List of main db files */ - rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ + rbu_file *pMain; /* Linked list of main db files */ }; /* ** Each file opened by an rbu VFS is represented by an instance of ** the following structure. -** -** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable -** "sz" is set to the current size of the database file. */ struct rbu_file { sqlite3_file base; /* sqlite3_file methods */ sqlite3_file *pReal; /* Underlying file handle */ rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ - i64 sz; /* Size of file in bytes (temp only) */ int openFlags; /* Flags this file was opened with */ u32 iCookie; /* Cookie value for main db files */ u8 iWriteVer; /* "write-version" value for main db files */ u8 bNolock; /* True to fail EXCLUSIVE locks */ @@ -220341,11 +170782,10 @@ char *zDel; /* Delete this when closing file */ const char *zWal; /* Wal filename for this main db file */ rbu_file *pWalFd; /* Wal file descriptor for this main db */ rbu_file *pMainNext; /* Next MAIN_DB file */ - rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ }; /* ** True for an RBU vacuum handle, or false otherwise. */ @@ -220386,16 +170826,15 @@ unsigned char *zStart = z; while( (c = zValue[0x7f&*(z++)])>=0 ){ v = (v<<6) + c; } z--; - *pLen -= (int)(z - zStart); + *pLen -= z - zStart; *pz = (char*)z; return v; } -#if RBU_ENABLE_DELTA_CKSUM /* ** Compute a 32-bit checksum on the N-byte buffer. Return the result. */ static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){ const unsigned char *z = (const unsigned char *)zIn; @@ -220426,11 +170865,10 @@ case 1: sum3 += (z[0] << 24); default: ; } return sum3; } -#endif /* ** Apply a delta. ** ** The output buffer should be big enough to hold the whole output @@ -220457,11 +170895,11 @@ int lenDelta, /* Length of the delta */ char *zOut /* Write the output into this preallocated buffer */ ){ unsigned int limit; unsigned int total = 0; -#if RBU_ENABLE_DELTA_CKSUM +#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST char *zOrigOut = zOut; #endif limit = rbuDeltaGetInt(&zDelta, &lenDelta); if( *zDelta!='\n' ){ @@ -220512,11 +170950,11 @@ break; } case ';': { zDelta++; lenDelta--; zOut[0] = 0; -#if RBU_ENABLE_DELTA_CKSUM +#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){ /* ERROR: bad checksum */ return -1; } #endif @@ -220571,11 +171009,10 @@ int nOut; int nOut2; char *aOut; assert( argc==2 ); - UNUSED_PARAMETER(argc); nOrig = sqlite3_value_bytes(argv[0]); aOrig = (const char*)sqlite3_value_blob(argv[0]); nDelta = sqlite3_value_bytes(argv[1]); aDelta = (const char*)sqlite3_value_blob(argv[1]); @@ -220591,11 +171028,10 @@ if( aOut==0 ){ sqlite3_result_error_nomem(context); }else{ nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut); if( nOut2!=nOut ){ - sqlite3_free(aOut); sqlite3_result_error(context, "corrupt fossil delta", -1); }else{ sqlite3_result_blob(context, aOut, nOut, sqlite3_free); } } @@ -220603,19 +171039,19 @@ /* ** Prepare the SQL statement in buffer zSql against database handle db. ** If successful, set *ppStmt to point to the new statement and return -** SQLITE_OK. +** SQLITE_OK. ** ** Otherwise, if an error does occur, set *ppStmt to NULL and return ** an SQLite error code. Additionally, set output variable *pzErrmsg to ** point to a buffer containing an error message. It is the responsibility ** of the caller to (eventually) free this buffer using sqlite3_free(). */ static int prepareAndCollectError( - sqlite3 *db, + sqlite3 *db, sqlite3_stmt **ppStmt, char **pzErrmsg, const char *zSql ){ int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); @@ -220643,13 +171079,13 @@ } /* ** Unless it is NULL, argument zSql points to a buffer allocated using ** sqlite3_malloc containing an SQL statement. This function prepares the SQL -** statement against database db and frees the buffer. If statement -** compilation is successful, *ppStmt is set to point to the new statement -** handle and SQLITE_OK is returned. +** statement against database db and frees the buffer. If statement +** compilation is successful, *ppStmt is set to point to the new statement +** handle and SQLITE_OK is returned. ** ** Otherwise, if an error occurs, *ppStmt is set to NULL and an error code ** returned. In this case, *pzErrmsg may also be set to point to an error ** message. It is the responsibility of the caller to free this error message ** buffer using sqlite3_free(). @@ -220656,11 +171092,11 @@ ** ** If argument zSql is NULL, this function assumes that an OOM has occurred. ** In this case SQLITE_NOMEM is returned and *ppStmt set to NULL. */ static int prepareFreeAndCollectError( - sqlite3 *db, + sqlite3 *db, sqlite3_stmt **ppStmt, char **pzErrmsg, char *zSql ){ int rc; @@ -220711,22 +171147,17 @@ RbuUpdateStmt *pTmp = pUp->pNext; sqlite3_finalize(pUp->pUpdate); sqlite3_free(pUp); pUp = pTmp; } - sqlite3_free(pIter->aIdxCol); - sqlite3_free(pIter->zIdxSql); - + pIter->pSelect = 0; pIter->pInsert = 0; pIter->pDelete = 0; pIter->pRbuUpdate = 0; pIter->pTmpInsert = 0; pIter->nCol = 0; - pIter->nIdxCol = 0; - pIter->aIdxCol = 0; - pIter->zIdxSql = 0; } /* ** Clean up any resources allocated as part of the iterator object passed ** as the only argument. @@ -220740,20 +171171,20 @@ } /* ** Advance the iterator to the next position. ** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the next entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the +** If no error occurs, SQLITE_OK is returned and the iterator is left +** pointing to the next entry. Otherwise, an error code and message is +** left in the RBU handle passed as the first argument. A copy of the ** error code is returned. */ static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ int rc = p->rc; if( rc==SQLITE_OK ){ - /* Free any SQLite statements used while processing the previous object */ + /* Free any SQLite statements used while processing the previous object */ rbuObjIterClearStatements(pIter); if( pIter->zIdx==0 ){ rc = sqlite3_exec(p->dbMain, "DROP TRIGGER IF EXISTS temp.rbu_insert_tr;" "DROP TRIGGER IF EXISTS temp.rbu_update1_tr;" @@ -220769,11 +171200,10 @@ pIter->bCleanup = 0; rc = sqlite3_step(pIter->pTblIter); if( rc!=SQLITE_ROW ){ rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); pIter->zTbl = 0; - pIter->zDataTbl = 0; }else{ pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM; } @@ -220809,11 +171239,11 @@ /* ** The implementation of the rbu_target_name() SQL function. This function ** accepts one or two arguments. The first argument is the name of a table - ** the name of a table in the RBU database. The second, if it is present, is 1 -** for a view or 0 for a table. +** for a view or 0 for a table. ** ** For a non-vacuum RBU handle, if the table name matches the pattern: ** ** data[0-9]_ ** @@ -220838,11 +171268,10 @@ assert( argc==1 || argc==2 ); zIn = (const char*)sqlite3_value_text(argv[0]); if( zIn ){ if( rbuIsVacuum(p) ){ - assert( argc==2 || argc==1 ); if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); } }else{ if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ @@ -220857,32 +171286,32 @@ } /* ** Initialize the iterator structure passed as the second argument. ** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the first entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the +** If no error occurs, SQLITE_OK is returned and the iterator is left +** pointing to the first entry. Otherwise, an error code and message is +** left in the RBU handle passed as the first argument. A copy of the ** error code is returned. */ static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ int rc; memset(pIter, 0, sizeof(RbuObjIter)); - rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, + rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, sqlite3_mprintf( "SELECT rbu_target_name(name, type='view') AS target, name " - "FROM sqlite_schema " + "FROM sqlite_master " "WHERE type IN ('table', 'view') AND target IS NOT NULL " " %s " "ORDER BY name" , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : "")); if( rc==SQLITE_OK ){ rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " - " FROM main.sqlite_schema " + " FROM main.sqlite_master " " WHERE type='index' AND tbl_name = ?" ); } pIter->bCleanup = 1; @@ -220894,11 +171323,11 @@ ** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs, ** an error code is stored in the RBU handle passed as the first argument. ** ** If an error has already occurred (p->rc is already set to something other ** than SQLITE_OK), then this function returns NULL without modifying the -** stored error code. In this case it still calls sqlite3_free() on any +** stored error code. In this case it still calls sqlite3_free() on any ** printf() parameters associated with %z conversions. */ static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){ char *zSql = 0; va_list ap; @@ -220940,20 +171369,20 @@ va_end(ap); return p->rc; } /* -** Attempt to allocate and return a pointer to a zeroed block of nByte -** bytes. +** Attempt to allocate and return a pointer to a zeroed block of nByte +** bytes. ** -** If an error (i.e. an OOM condition) occurs, return NULL and leave an -** error code in the rbu handle passed as the first argument. Or, if an -** error has already occurred when this function is called, return NULL +** If an error (i.e. an OOM condition) occurs, return NULL and leave an +** error code in the rbu handle passed as the first argument. Or, if an +** error has already occurred when this function is called, return NULL ** immediately without attempting the allocation or modifying the stored ** error code. */ -static void *rbuMalloc(sqlite3rbu *p, sqlite3_int64 nByte){ +static void *rbuMalloc(sqlite3rbu *p, int nByte){ void *pRet = 0; if( p->rc==SQLITE_OK ){ assert( nByte>0 ); pRet = sqlite3_malloc64(nByte); if( pRet==0 ){ @@ -220970,11 +171399,11 @@ ** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that ** there is room for at least nCol elements. If an OOM occurs, store an ** error code in the RBU handle passed as the first argument. */ static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ - sqlite3_int64 nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; + int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; char **azNew; azNew = (char**)rbuMalloc(p, nByte); if( azNew ){ pIter->azTblCol = azNew; @@ -220997,19 +171426,18 @@ ** if the allocation succeeds, (*pRc) is left unchanged. */ static char *rbuStrndup(const char *zStr, int *pRc){ char *zRet = 0; - if( *pRc==SQLITE_OK ){ - if( zStr ){ - size_t nCopy = strlen(zStr) + 1; - zRet = (char*)sqlite3_malloc64(nCopy); - if( zRet ){ - memcpy(zRet, zStr, nCopy); - }else{ - *pRc = SQLITE_NOMEM; - } + assert( *pRc==SQLITE_OK ); + if( zStr ){ + size_t nCopy = strlen(zStr) + 1; + zRet = (char*)sqlite3_malloc64(nCopy); + if( zRet ){ + memcpy(zRet, zStr, nCopy); + }else{ + *pRc = SQLITE_NOMEM; } } return zRet; } @@ -221042,24 +171470,24 @@ ** RBU_PK_EXTERNAL: Table has an external PK index. ** RBU_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. ** RBU_PK_VTAB: Table is a virtual table. ** ** Argument *piPk is also of type (int*), and also points to an output -** parameter. Unless the table has an external primary key index +** parameter. Unless the table has an external primary key index ** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, ** if the table does have an external primary key index, then *piPk ** is set to the root page number of the primary key index before ** returning. ** ** ALGORITHM: ** -** if( no entry exists in sqlite_schema ){ +** if( no entry exists in sqlite_master ){ ** return RBU_PK_NOTABLE ** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ ** return RBU_PK_VTAB ** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ -** if( the index that is the pk exists in sqlite_schema ){ +** if( the index that is the pk exists in sqlite_master ){ ** *piPK = rootpage of that index. ** return RBU_PK_EXTERNAL ** }else{ ** return RBU_PK_WITHOUT_ROWID ** } @@ -221075,27 +171503,25 @@ int *peType, int *piTnum, int *piPk ){ /* - ** 0) SELECT count(*) FROM sqlite_schema where name=%Q AND IsVirtual(%Q) + ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q) ** 1) PRAGMA index_list = ? - ** 2) SELECT count(*) FROM sqlite_schema where name=%Q + ** 2) SELECT count(*) FROM sqlite_master where name=%Q ** 3) PRAGMA table_info = ? */ sqlite3_stmt *aStmt[4] = {0, 0, 0, 0}; *peType = RBU_PK_NOTABLE; *piPk = 0; assert( p->rc==SQLITE_OK ); - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, sqlite3_mprintf( - "SELECT " - " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM')," - " rootpage" - " FROM sqlite_schema" + "SELECT (sql LIKE 'create virtual%%'), rootpage" + " FROM sqlite_master" " WHERE name=%Q", zTab )); if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ /* Either an error, or no such table. */ goto rbuTableType_end; @@ -221104,21 +171530,21 @@ *peType = RBU_PK_VTAB; /* virtual table */ goto rbuTableType_end; } *piTnum = sqlite3_column_int(aStmt[0], 1); - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, sqlite3_mprintf("PRAGMA index_list=%Q",zTab) ); if( p->rc ) goto rbuTableType_end; while( sqlite3_step(aStmt[1])==SQLITE_ROW ){ const u8 *zOrig = sqlite3_column_text(aStmt[1], 3); const u8 *zIdx = sqlite3_column_text(aStmt[1], 1); if( zOrig && zIdx && zOrig[0]=='p' ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, sqlite3_mprintf( - "SELECT rootpage FROM sqlite_schema WHERE name = %Q", zIdx + "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx )); if( p->rc==SQLITE_OK ){ if( sqlite3_step(aStmt[2])==SQLITE_ROW ){ *piPk = sqlite3_column_int(aStmt[2], 0); *peType = RBU_PK_EXTERNAL; @@ -221128,11 +171554,11 @@ } goto rbuTableType_end; } } - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, sqlite3_mprintf("PRAGMA table_info=%Q",zTab) ); if( p->rc==SQLITE_OK ){ while( sqlite3_step(aStmt[3])==SQLITE_ROW ){ if( sqlite3_column_int(aStmt[3],5)>0 ){ @@ -221167,25 +171593,18 @@ } pIter->nIndex = 0; while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ const char *zIdx = (const char*)sqlite3_column_text(pList, 1); - int bPartial = sqlite3_column_int(pList, 4); sqlite3_stmt *pXInfo = 0; if( zIdx==0 ) break; - if( bPartial ){ - memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol); - } p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int iCid = sqlite3_column_int(pXInfo, 1); if( iCid>=0 ) pIter->abIndexed[iCid] = 1; - if( iCid==-2 ){ - memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol); - } } rbuFinalize(p, pXInfo); bIndex = 1; pIter->nIndex++; } @@ -221204,11 +171623,11 @@ ** If they are not already populated, populate the pIter->azTblCol[], ** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to ** the table (not index) that the iterator currently points to. ** ** Return SQLITE_OK if successful, or an SQLite error code otherwise. If -** an error does occur, an error code and error message are also left in +** an error does occur, an error code and error message are also left in ** the RBU handle. */ static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ if( pIter->azTblCol==0 ){ sqlite3_stmt *pStmt = 0; @@ -221226,19 +171645,19 @@ p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); } if( p->rc ) return p->rc; if( pIter->zIdx==0 ) pIter->iTnum = iTnum; - assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK + assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK || pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_WITHOUT_ROWID || pIter->eType==RBU_PK_VTAB ); /* Populate the azTblCol[] and nTblCol variables based on the columns ** of the input table. Ignore any input table columns that begin with ** "rbu_". */ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, sqlite3_mprintf("SELECT * FROM '%q'", pIter->zDataTbl) ); if( p->rc==SQLITE_OK ){ nCol = sqlite3_column_count(pStmt); rbuAllocateIterArrays(p, pIter, nCol); @@ -221270,11 +171689,11 @@ /* Check that all non-HIDDEN columns in the destination table are also ** present in the input table. Populate the abTblPk[], azTblType[] and ** aiTblOrder[] arrays at the same time. */ if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl) ); } while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ const char *zName = (const char*)sqlite3_column_text(pStmt, 1); @@ -221296,12 +171715,11 @@ SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); } pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); - assert( iPk>=0 ); - pIter->abTblPk[iOrder] = (u8)iPk; + pIter->abTblPk[iOrder] = (iPk!=0); pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); iOrder++; } } @@ -221313,12 +171731,12 @@ return p->rc; } /* -** This function constructs and returns a pointer to a nul-terminated -** string containing some SQL clause or list based on one or more of the +** This function constructs and returns a pointer to a nul-terminated +** string containing some SQL clause or list based on one or more of the ** column names currently stored in the pIter->azTblCol[] array. */ static char *rbuObjIterGetCollist( sqlite3rbu *p, /* RBU object */ RbuObjIter *pIter /* Object iterator for column names */ @@ -221333,236 +171751,27 @@ } return zList; } /* -** Return a comma separated list of the quoted PRIMARY KEY column names, -** in order, for the current table. Before each column name, add the text -** zPre. After each column name, add the zPost text. Use zSeparator as -** the separator text (usually ", "). -*/ -static char *rbuObjIterGetPkList( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter, /* Object iterator for column names */ - const char *zPre, /* Before each quoted column name */ - const char *zSeparator, /* Separator to use between columns */ - const char *zPost /* After each quoted column name */ -){ - int iPk = 1; - char *zRet = 0; - const char *zSep = ""; - while( 1 ){ - int i; - for(i=0; inTblCol; i++){ - if( (int)pIter->abTblPk[i]==iPk ){ - const char *zCol = pIter->azTblCol[i]; - zRet = rbuMPrintf(p, "%z%s%s\"%w\"%s", zRet, zSep, zPre, zCol, zPost); - zSep = zSeparator; - break; - } - } - if( i==pIter->nTblCol ) break; - iPk++; - } - return zRet; -} - -/* -** This function is called as part of restarting an RBU vacuum within -** stage 1 of the process (while the *-oal file is being built) while -** updating a table (not an index). The table may be a rowid table or -** a WITHOUT ROWID table. It queries the target database to find the -** largest key that has already been written to the target table and -** constructs a WHERE clause that can be used to extract the remaining -** rows from the source table. For a rowid table, the WHERE clause -** is of the form: -** -** "WHERE _rowid_ > ?" -** -** and for WITHOUT ROWID tables: -** -** "WHERE (key1, key2) > (?, ?)" -** -** Instead of "?" placeholders, the actual WHERE clauses created by -** this function contain literal SQL values. -*/ -static char *rbuVacuumTableStart( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter, /* RBU iterator object */ - int bRowid, /* True for a rowid table */ - const char *zWrite /* Target table name prefix */ -){ - sqlite3_stmt *pMax = 0; - char *zRet = 0; - if( bRowid ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, - sqlite3_mprintf( - "SELECT max(_rowid_) FROM \"%s%w\"", zWrite, pIter->zTbl - ) - ); - if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ - sqlite3_int64 iMax = sqlite3_column_int64(pMax, 0); - zRet = rbuMPrintf(p, " WHERE _rowid_ > %lld ", iMax); - } - rbuFinalize(p, pMax); - }else{ - char *zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", " DESC"); - char *zSelect = rbuObjIterGetPkList(p, pIter, "quote(", "||','||", ")"); - char *zList = rbuObjIterGetPkList(p, pIter, "", ", ", ""); - - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, - sqlite3_mprintf( - "SELECT %s FROM \"%s%w\" ORDER BY %s LIMIT 1", - zSelect, zWrite, pIter->zTbl, zOrder - ) - ); - if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ - const char *zVal = (const char*)sqlite3_column_text(pMax, 0); - zRet = rbuMPrintf(p, " WHERE (%s) > (%s) ", zList, zVal); - } - rbuFinalize(p, pMax); - } - - sqlite3_free(zOrder); - sqlite3_free(zSelect); - sqlite3_free(zList); - } - return zRet; -} - -/* -** This function is called as part of restating an RBU vacuum when the -** current operation is writing content to an index. If possible, it -** queries the target index b-tree for the largest key already written to -** it, then composes and returns an expression that can be used in a WHERE -** clause to select the remaining required rows from the source table. -** It is only possible to return such an expression if: -** -** * The index contains no DESC columns, and -** * The last key written to the index before the operation was -** suspended does not contain any NULL values. -** -** The expression is of the form: -** -** (index-field1, index-field2, ...) > (?, ?, ...) -** -** except that the "?" placeholders are replaced with literal values. -** -** If the expression cannot be created, NULL is returned. In this case, -** the caller has to use an OFFSET clause to extract only the required -** rows from the sourct table, just as it does for an RBU update operation. -*/ -static char *rbuVacuumIndexStart( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter /* RBU iterator object */ -){ - char *zOrder = 0; - char *zLhs = 0; - char *zSelect = 0; - char *zVector = 0; - char *zRet = 0; - int bFailed = 0; - const char *zSep = ""; - int iCol = 0; - sqlite3_stmt *pXInfo = 0; - - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol; - if( sqlite3_column_int(pXInfo, 3) ){ - bFailed = 1; - break; - } - - if( iCid<0 ){ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else{ - zCol = "_rowid_"; - } - }else{ - zCol = pIter->azTblCol[iCid]; - } - - zLhs = rbuMPrintf(p, "%z%s \"%w\" COLLATE %Q", - zLhs, zSep, zCol, zCollate - ); - zOrder = rbuMPrintf(p, "%z%s \"rbu_imp_%d%w\" COLLATE %Q DESC", - zOrder, zSep, iCol, zCol, zCollate - ); - zSelect = rbuMPrintf(p, "%z%s quote(\"rbu_imp_%d%w\")", - zSelect, zSep, iCol, zCol - ); - zSep = ", "; - iCol++; - } - rbuFinalize(p, pXInfo); - if( bFailed ) goto index_start_out; - - if( p->rc==SQLITE_OK ){ - sqlite3_stmt *pSel = 0; - - p->rc = prepareFreeAndCollectError(p->dbMain, &pSel, &p->zErrmsg, - sqlite3_mprintf("SELECT %s FROM \"rbu_imp_%w\" ORDER BY %s LIMIT 1", - zSelect, pIter->zTbl, zOrder - ) - ); - if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){ - zSep = ""; - for(iCol=0; iColnCol; iCol++){ - const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol); - if( zQuoted==0 ){ - p->rc = SQLITE_NOMEM; - }else if( zQuoted[0]=='N' ){ - bFailed = 1; - break; - } - zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted); - zSep = ", "; - } - - if( !bFailed ){ - zRet = rbuMPrintf(p, "(%s) > (%s)", zLhs, zVector); - } - } - rbuFinalize(p, pSel); - } - - index_start_out: - sqlite3_free(zOrder); - sqlite3_free(zSelect); - sqlite3_free(zVector); - sqlite3_free(zLhs); - return zRet; -} - -/* -** This function is used to create a SELECT list (the list of SQL -** expressions that follows a SELECT keyword) for a SELECT statement -** used to read from an data_xxx or rbu_tmp_xxx table while updating the -** index object currently indicated by the iterator object passed as the -** second argument. A "PRAGMA index_xinfo = " statement is used +** This function is used to create a SELECT list (the list of SQL +** expressions that follows a SELECT keyword) for a SELECT statement +** used to read from an data_xxx or rbu_tmp_xxx table while updating the +** index object currently indicated by the iterator object passed as the +** second argument. A "PRAGMA index_xinfo = " statement is used ** to obtain the required information. ** ** If the index is of the following form: ** ** CREATE INDEX i1 ON t1(c, b COLLATE nocase); ** -** and "t1" is a table with an explicit INTEGER PRIMARY KEY column +** and "t1" is a table with an explicit INTEGER PRIMARY KEY column ** "ipk", the returned string is: ** ** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'" ** -** As well as the returned string, three other malloc'd strings are +** As well as the returned string, three other malloc'd strings are ** returned via output parameters. As follows: ** ** pzImposterCols: ... ** pzImposterPk: ... ** pzWhere: ... @@ -221595,48 +171804,40 @@ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol = 0; + const char *zCol; const char *zType; - if( iCid==-2 ){ - int iSeq = sqlite3_column_int(pXInfo, 0); - zRet = sqlite3_mprintf("%z%s(%.*s) COLLATE %Q", zRet, zCom, - pIter->aIdxCol[iSeq].nSpan, pIter->aIdxCol[iSeq].zSpan, zCollate - ); - zType = ""; - }else { - if( iCid<0 ){ - /* An integer primary key. If the table has an explicit IPK, use - ** its name. Otherwise, use "rbu_rowid". */ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else if( rbuIsVacuum(p) ){ - zCol = "_rowid_"; - }else{ - zCol = "rbu_rowid"; - } - zType = "INTEGER"; - }else{ - zCol = pIter->azTblCol[iCid]; - zType = pIter->azTblType[iCid]; - } - zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom,zCol,zCollate); - } - + if( iCid<0 ){ + /* An integer primary key. If the table has an explicit IPK, use + ** its name. Otherwise, use "rbu_rowid". */ + if( pIter->eType==RBU_PK_IPK ){ + int i; + for(i=0; pIter->abTblPk[i]==0; i++); + assert( inTblCol ); + zCol = pIter->azTblCol[i]; + }else if( rbuIsVacuum(p) ){ + zCol = "_rowid_"; + }else{ + zCol = "rbu_rowid"; + } + zType = "INTEGER"; + }else{ + zCol = pIter->azTblCol[iCid]; + zType = pIter->azTblType[iCid]; + } + + zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ const char *zOrder = (bDesc ? " DESC" : ""); - zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", + zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", zImpPK, zCom, nBind, zCol, zOrder ); } - zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", + zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", zImpCols, zCom, nBind, zCol, zType, zCollate ); zWhere = sqlite3_mprintf( "%z%s\"rbu_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol ); @@ -221678,11 +171879,11 @@ ** ** For tables with implicit rowids - RBU_PK_EXTERNAL and RBU_PK_NONE, append ** the text ", old._rowid_" to the returned value. */ static char *rbuObjIterGetOldlist( - sqlite3rbu *p, + sqlite3rbu *p, RbuObjIter *pIter, const char *zObj ){ char *zList = 0; if( p->rc==SQLITE_OK && pIter->abIndexed ){ @@ -221719,11 +171920,11 @@ ** Return the string: ** ** "b = ?1 AND c = ?2" */ static char *rbuObjIterGetWhere( - sqlite3rbu *p, + sqlite3rbu *p, RbuObjIter *pIter ){ char *zList = 0; if( pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE ){ zList = rbuMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1); @@ -221734,11 +171935,11 @@ if( pIter->abTblPk[i] ){ zList = rbuMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1); zSep = " AND "; } } - zList = rbuMPrintf(p, + zList = rbuMPrintf(p, "_rowid_ = (SELECT id FROM rbu_imposter2 WHERE %z)", zList ); }else{ const char *zSep = ""; @@ -221774,11 +171975,11 @@ ** passed as the second argument currently points to if the rbu_control ** column of the data_xxx table entry is set to zMask. ** ** The memory for the returned string is obtained from sqlite3_malloc(). ** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). +** sqlite3_free(). ** ** If an OOM error is encountered when allocating space for the new ** string, an error code is left in the rbu handle passed as the first ** argument and NULL is returned. Or, if an error has already occurred ** when this function is called, NULL is returned immediately, without @@ -221798,23 +171999,23 @@ }else{ const char *zSep = ""; for(i=0; inTblCol; i++){ char c = zMask[pIter->aiSrcOrder[i]]; if( c=='x' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", + zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, pIter->azTblCol[i], i+1 ); zSep = ", "; } else if( c=='d' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)", + zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)", zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 ); zSep = ", "; } else if( c=='f' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_fossil_delta(\"%w\", ?%d)", + zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_fossil_delta(\"%w\", ?%d)", zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 ); zSep = ", "; } } @@ -221828,21 +172029,21 @@ ** "?" expressions. For example, if nByte is 3, return a pointer to ** a buffer containing the string "?,?,?". ** ** The memory for the returned string is obtained from sqlite3_malloc(). ** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). +** sqlite3_free(). ** ** If an OOM error is encountered when allocating space for the new ** string, an error code is left in the rbu handle passed as the first ** argument and NULL is returned. Or, if an error has already occurred ** when this function is called, NULL is returned immediately, without ** attempting the allocation or modifying the stored error code. */ static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){ char *zRet = 0; - sqlite3_int64 nByte = 2*(sqlite3_int64)nBind + 1; + int nByte = nBind*2 + 1; zRet = (char*)rbuMalloc(p, nByte); if( zRet ){ int i; for(i=0; izIdx==0 ); if( p->rc==SQLITE_OK ){ const char *zSep = "PRIMARY KEY("; sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */ sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = */ - + p->rc = prepareFreeAndCollectError(p->dbMain, &pXList, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) ); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXList) ){ const char *zOrig = (const char*)sqlite3_column_text(pXList,3); @@ -221908,11 +172109,11 @@ /* ** This function creates the second imposter table used when writing to ** a table b-tree where the table has an external primary key. If the ** iterator passed as the second argument does not currently point to ** a table (not index) with an external primary key, this function is a -** no-op. +** no-op. ** ** Assuming the iterator does point to a table with an external PK, this ** function creates a WITHOUT ROWID imposter table named "rbu_imposter2" ** used to access that PK index. For example, if the target table is ** declared as follows: @@ -221935,12 +172136,12 @@ char *zPk = 0; /* Used to build up table PK declaration */ /* Figure out the name of the primary key index for the current table. ** This is needed for the argument to "PRAGMA index_xinfo". Set ** zIdx to point to a nul-terminated string containing this name. */ - p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, - "SELECT name FROM sqlite_schema WHERE rootpage = ?" + p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, + "SELECT name FROM sqlite_master WHERE rootpage = ?" ); if( p->rc==SQLITE_OK ){ sqlite3_bind_int(pQuery, 1, tnum); if( SQLITE_ROW==sqlite3_step(pQuery) ){ zIdx = (const char*)sqlite3_column_text(pQuery, 0); @@ -221957,11 +172158,11 @@ int bKey = sqlite3_column_int(pXInfo, 5); if( bKey ){ int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, + zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, iCid, pIter->azTblType[iCid], zCollate ); zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); zComma = ", "; } @@ -221969,19 +172170,19 @@ zCols = rbuMPrintf(p, "%z, id INTEGER", zCols); rbuFinalize(p, pXInfo); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", + "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", zCols, zPk ); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); } } /* -** If an error has already occurred when this function is called, it +** If an error has already occurred when this function is called, it ** immediately returns zero (without doing any work). Or, if an error ** occurs during the execution of this function, it sets the error code ** in the sqlite3rbu object indicated by the first argument and returns ** zero. ** @@ -221990,13 +172191,13 @@ ** attempts to create any imposter table required to write to the main ** table b-tree of the table before returning. Non-zero is returned if ** an imposter table are created, or zero otherwise. ** ** An imposter table is required in all cases except RBU_PK_VTAB. Only -** virtual tables are written to directly. The imposter table has the -** same schema as the actual target table (less any UNIQUE constraints). -** More precisely, the "same schema" means the same columns, types, +** virtual tables are written to directly. The imposter table has the +** same schema as the actual target table (less any UNIQUE constraints). +** More precisely, the "same schema" means the same columns, types, ** collation sequences. For tables that do not have an external PRIMARY ** KEY, it also means the same PRIMARY KEY declaration. */ static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ if( p->rc==SQLITE_OK && pIter->eType!=RBU_PK_VTAB ){ @@ -222018,11 +172219,11 @@ if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ /* If the target table column is an "INTEGER PRIMARY KEY", add ** "PRIMARY KEY" to the imposter table column declaration. */ zPk = "PRIMARY KEY "; } - zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", + zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, (pIter->abNotNull[iCol] ? " NOT NULL" : "") ); zComma = ", "; } @@ -222033,12 +172234,12 @@ zSql = rbuMPrintf(p, "%z, %z", zSql, zPk); } } sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s", - pIter->zTbl, zSql, + rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s", + pIter->zTbl, zSql, (pIter->eType==RBU_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "") ); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); } } @@ -222048,16 +172249,16 @@ ** Specifically a statement of the form: ** ** INSERT INTO rbu_tmp_xxx VALUES(?, ?, ? ...); ** ** The number of bound variables is equal to the number of columns in -** the target table, plus one (for the rbu_control column), plus one more -** (for the rbu_rowid column) if the target table is an implicit IPK or +** the target table, plus one (for the rbu_control column), plus one more +** (for the rbu_rowid column) if the target table is an implicit IPK or ** virtual table. */ static void rbuObjIterPrepareTmpInsert( - sqlite3rbu *p, + sqlite3rbu *p, RbuObjIter *pIter, const char *zCollist, const char *zRbuRowid ){ int bRbuRowid = (pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE); @@ -222064,28 +172265,28 @@ char *zBind = rbuObjIterGetBindlist(p, pIter->nTblCol + 1 + bRbuRowid); if( zBind ){ assert( pIter->pTmpInsert==0 ); p->rc = prepareFreeAndCollectError( p->dbRbu, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf( - "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)", + "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)", p->zStateDb, pIter->zDataTbl, zCollist, zRbuRowid, zBind )); } } static void rbuTmpInsertFunc( - sqlite3_context *pCtx, + sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ sqlite3rbu *p = sqlite3_user_data(pCtx); int rc = SQLITE_OK; int i; assert( sqlite3_value_int(apVal[0])!=0 - || p->objiter.eType==RBU_PK_EXTERNAL - || p->objiter.eType==RBU_PK_NONE + || p->objiter.eType==RBU_PK_EXTERNAL + || p->objiter.eType==RBU_PK_NONE ); if( sqlite3_value_int(apVal[0])!=0 ){ p->nPhaseOneStep += p->objiter.nIndex; } @@ -222100,112 +172301,17 @@ if( rc!=SQLITE_OK ){ sqlite3_result_error_code(pCtx, rc); } } -static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ - sqlite3_stmt *pStmt = 0; - int rc = p->rc; - char *zRet = 0; - - assert( pIter->zIdxSql==0 && pIter->nIdxCol==0 && pIter->aIdxCol==0 ); - - if( rc==SQLITE_OK ){ - rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, - "SELECT trim(sql) FROM sqlite_schema WHERE type='index' AND name=?" - ); - } - if( rc==SQLITE_OK ){ - int rc2; - rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - char *zSql = (char*)sqlite3_column_text(pStmt, 0); - if( zSql ){ - pIter->zIdxSql = zSql = rbuStrndup(zSql, &rc); - } - if( zSql ){ - int nParen = 0; /* Number of open parenthesis */ - int i; - int iIdxCol = 0; - int nIdxAlloc = 0; - for(i=0; zSql[i]; i++){ - char c = zSql[i]; - - /* If necessary, grow the pIter->aIdxCol[] array */ - if( iIdxCol==nIdxAlloc ){ - RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc( - pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan) - ); - if( aIdxCol==0 ){ - rc = SQLITE_NOMEM; - break; - } - pIter->aIdxCol = aIdxCol; - nIdxAlloc += 16; - } - - if( c=='(' ){ - if( nParen==0 ){ - assert( iIdxCol==0 ); - pIter->aIdxCol[0].zSpan = &zSql[i+1]; - } - nParen++; - } - else if( c==')' ){ - nParen--; - if( nParen==0 ){ - int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan); - pIter->aIdxCol[iIdxCol++].nSpan = nSpan; - i++; - break; - } - }else if( c==',' && nParen==1 ){ - int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan); - pIter->aIdxCol[iIdxCol++].nSpan = nSpan; - pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1]; - }else if( c=='"' || c=='\'' || c=='`' ){ - for(i++; 1; i++){ - if( zSql[i]==c ){ - if( zSql[i+1]!=c ) break; - i++; - } - } - }else if( c=='[' ){ - for(i++; 1; i++){ - if( zSql[i]==']' ) break; - } - }else if( c=='-' && zSql[i+1]=='-' ){ - for(i=i+2; zSql[i] && zSql[i]!='\n'; i++); - if( zSql[i]=='\0' ) break; - }else if( c=='/' && zSql[i+1]=='*' ){ - for(i=i+2; zSql[i] && (zSql[i]!='*' || zSql[i+1]!='/'); i++); - if( zSql[i]=='\0' ) break; - i++; - } - } - if( zSql[i] ){ - zRet = rbuStrndup(&zSql[i], &rc); - } - pIter->nIdxCol = iIdxCol; - } - } - - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - } - - p->rc = rc; - return zRet; -} - /* -** Ensure that the SQLite statement handles required to update the -** target database object currently indicated by the iterator passed +** Ensure that the SQLite statement handles required to update the +** target database object currently indicated by the iterator passed ** as the second argument are available. */ static int rbuObjIterPrepareAll( - sqlite3rbu *p, + sqlite3rbu *p, RbuObjIter *pIter, int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */ ){ assert( pIter->bCleanup==0 ); if( pIter->pSelect==0 && rbuObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){ @@ -222224,15 +172330,13 @@ const char *zTbl = pIter->zTbl; char *zImposterCols = 0; /* Columns for imposter table */ char *zImposterPK = 0; /* Primary key declaration for imposter */ char *zWhere = 0; /* WHERE clause on PK columns */ char *zBind = 0; - char *zPart = 0; int nBind = 0; assert( pIter->eType!=RBU_PK_VTAB ); - zPart = rbuObjIterGetIndexWhere(p, pIter); zCollist = rbuObjIterGetIndexCols( p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind ); zBind = rbuObjIterGetBindlist(p, nBind); @@ -222264,62 +172368,43 @@ /* Create the SELECT statement to read keys in sorted order */ if( p->rc==SQLITE_OK ){ char *zSql; if( rbuIsVacuum(p) ){ - char *zStart = 0; - if( nOffset ){ - zStart = rbuVacuumIndexStart(p, pIter); - if( zStart ){ - sqlite3_free(zLimit); - zLimit = 0; - } - } - zSql = sqlite3_mprintf( - "SELECT %s, 0 AS rbu_control FROM '%q' %s %s %s ORDER BY %s%s", - zCollist, + "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s", + zCollist, pIter->zDataTbl, - zPart, - (zStart ? (zPart ? "AND" : "WHERE") : ""), zStart, zCollist, zLimit ); - sqlite3_free(zStart); }else if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s ORDER BY %s%s", + "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", zCollist, p->zStateDb, pIter->zDataTbl, - zPart, zCollist, zLimit + zCollist, zLimit ); }else{ zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s " + "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " "UNION ALL " "SELECT %s, rbu_control FROM '%q' " - "%s %s typeof(rbu_control)='integer' AND rbu_control!=1 " + "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " "ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, zPart, - zCollist, pIter->zDataTbl, - zPart, - (zPart ? "AND" : "WHERE"), + zCollist, p->zStateDb, pIter->zDataTbl, + zCollist, pIter->zDataTbl, zCollist, zLimit ); } - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbRbu,&pIter->pSelect,pz,zSql); - }else{ - sqlite3_free(zSql); - } + p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); } sqlite3_free(zImposterCols); sqlite3_free(zImposterPK); sqlite3_free(zWhere); sqlite3_free(zBind); - sqlite3_free(zPart); }else{ int bRbuRowid = (pIter->eType==RBU_PK_VTAB) ||(pIter->eType==RBU_PK_NONE) ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)); const char *zTbl = pIter->zTbl; /* Table this step applies to */ @@ -222340,11 +172425,11 @@ /* Create the INSERT statement to write to the target PK b-tree */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, sqlite3_mprintf( - "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", + "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings ) ); } @@ -222408,46 +172493,22 @@ } /* Create the SELECT statement to read keys from data_xxx */ if( p->rc==SQLITE_OK ){ const char *zRbuRowid = ""; - char *zStart = 0; - char *zOrder = 0; if( bRbuRowid ){ zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid"; } - - if( rbuIsVacuum(p) ){ - if( nOffset ){ - zStart = rbuVacuumTableStart(p, pIter, bRbuRowid, zWrite); - if( zStart ){ - sqlite3_free(zLimit); - zLimit = 0; - } - } - if( bRbuRowid ){ - zOrder = rbuMPrintf(p, "_rowid_"); - }else{ - zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", ""); - } - } - - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, - sqlite3_mprintf( - "SELECT %s,%s rbu_control%s FROM '%q'%s %s %s %s", - zCollist, - (rbuIsVacuum(p) ? "0 AS " : ""), - zRbuRowid, - pIter->zDataTbl, (zStart ? zStart : ""), - (zOrder ? "ORDER BY" : ""), zOrder, - zLimit - ) - ); - } - sqlite3_free(zStart); - sqlite3_free(zOrder); + p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, + sqlite3_mprintf( + "SELECT %s,%s rbu_control%s FROM '%q'%s", + zCollist, + (rbuIsVacuum(p) ? "0 AS " : ""), + zRbuRowid, + pIter->zDataTbl, zLimit + ) + ); } sqlite3_free(zWhere); sqlite3_free(zOldlist); sqlite3_free(zNewlist); @@ -222454,20 +172515,20 @@ sqlite3_free(zBindings); } sqlite3_free(zCollist); sqlite3_free(zLimit); } - + return p->rc; } /* ** Set output variable *ppStmt to point to an UPDATE statement that may ** be used to update the imposter table for the main table b-tree of the -** table object that pIter currently points to, assuming that the +** table object that pIter currently points to, assuming that the ** rbu_control column of the data_xyz table contains zMask. -** +** ** If the zMask string does not specify any columns to update, then this ** is not an error. Output variable *ppStmt is set to NULL in this case. */ static int rbuGetUpdateStmt( sqlite3rbu *p, /* RBU handle */ @@ -222490,11 +172551,11 @@ pUp = *pp; if( strcmp(pUp->zMask, zMask)==0 ){ *pp = pUp->pNext; pUp->pNext = pIter->pRbuUpdate; pIter->pRbuUpdate = pUp; - *ppStmt = pUp->pUpdate; + *ppStmt = pUp->pUpdate; return SQLITE_OK; } nUp++; } assert( pUp==0 || pUp->pNext==0 ); @@ -222520,11 +172581,11 @@ if( zSet ){ const char *zPrefix = ""; if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_"; - zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", + zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", zPrefix, pIter->zTbl, zSet, zWhere ); p->rc = prepareFreeAndCollectError( p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate ); @@ -222536,12 +172597,12 @@ return p->rc; } static sqlite3 *rbuOpenDbhandle( - sqlite3rbu *p, - const char *zName, + sqlite3rbu *p, + const char *zName, int bUseVfs ){ sqlite3 *db = 0; if( p->rc==SQLITE_OK ){ const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; @@ -222559,19 +172620,18 @@ ** Free an RbuState object allocated by rbuLoadState(). */ static void rbuFreeState(RbuState *p){ if( p ){ sqlite3_free(p->zTbl); - sqlite3_free(p->zDataTbl); sqlite3_free(p->zIdx); sqlite3_free(p); } } /* -** Allocate an RbuState object and load the contents of the rbu_state -** table into it. Return a pointer to the new object. It is the +** Allocate an RbuState object and load the contents of the rbu_state +** table into it. Return a pointer to the new object. It is the ** responsibility of the caller to eventually free the object using ** sqlite3_free(). ** ** If an error occurs, leave an error code and message in the rbu handle ** and return NULL. @@ -222583,11 +172643,11 @@ int rc2; pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); if( pRet==0 ) return 0; - rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, + rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) ); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ switch( sqlite3_column_int(pStmt, 0) ){ case RBU_STATE_STAGE: @@ -222623,21 +172683,17 @@ case RBU_STATE_COOKIE: pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_OALSZ: - pRet->iOalSz = sqlite3_column_int64(pStmt, 1); + pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_PHASEONESTEP: pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); break; - case RBU_STATE_DATATBL: - pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - default: rc = SQLITE_CORRUPT; break; } } @@ -222650,29 +172706,23 @@ /* ** Open the database handle and attach the RBU database as "rbu". If an ** error occurs, leave an error code and message in the RBU handle. -** -** If argument dbMain is not NULL, then it is a database handle already -** open on the target database. Use this handle instead of opening a new -** one. */ -static void rbuOpenDatabase(sqlite3rbu *p, sqlite3 *dbMain, int *pbRetry){ +static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){ assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); - assert( dbMain==0 || rbuIsVacuum(p)==0 ); /* Open the RBU database */ p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); - p->dbMain = dbMain; if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); if( p->zState==0 ){ const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); - p->zState = rbuMPrintf(p, "file:///%s-vacuum?modeof=%s", zFile, zFile); + p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile); } } /* If using separate RBU and state databases, attach the state database to ** the RBU db handle now. */ @@ -222697,13 +172747,13 @@ if( p->rc==SQLITE_OK ){ int rc2; int bOk = 0; sqlite3_stmt *pCnt = 0; p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg, - "SELECT count(*) FROM stat.sqlite_schema" + "SELECT count(*) FROM stat.sqlite_master" ); - if( p->rc==SQLITE_OK + if( p->rc==SQLITE_OK && sqlite3_step(pCnt)==SQLITE_ROW && 1==sqlite3_column_int(pCnt, 0) ){ bOk = 1; } @@ -222712,11 +172762,11 @@ if( p->rc==SQLITE_OK && bOk==0 ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("invalid state database"); } - + if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0); } } } @@ -222766,11 +172816,11 @@ if( *zExtra++=='?' ) break; } if( *zExtra=='\0' ) zExtra = 0; } - zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s", + zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s", sqlite3_db_filename(p->dbRbu, "main"), (zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra) ); if( zTarget==0 ){ @@ -222781,33 +172831,33 @@ sqlite3_free(zTarget); } } if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, + p->rc = sqlite3_create_function(p->dbMain, "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 ); } if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, + p->rc = sqlite3_create_function(p->dbMain, "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0 ); } if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbRbu, + p->rc = sqlite3_create_function(p->dbRbu, "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 ); } if( p->rc==SQLITE_OK ){ p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); } - rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_schema"); + rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); - /* Mark the database file just opened as an RBU target database. If + /* Mark the database file just opened as an RBU target database. If ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. ** This is an error. */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); } @@ -222847,42 +172897,40 @@ int i, sz; sz = (int)strlen(z)&0xffffff; for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4); } -#else - UNUSED_PARAMETER2(zBase,z); #endif } /* -** Return the current wal-index header checksum for the target database +** Return the current wal-index header checksum for the target database ** as a 64-bit integer. ** -** The checksum is store in the first page of xShmMap memory as an 8-byte +** The checksum is store in the first page of xShmMap memory as an 8-byte ** blob starting at byte offset 40. */ static i64 rbuShmChecksum(sqlite3rbu *p){ i64 iRet = 0; if( p->rc==SQLITE_OK ){ sqlite3_file *pDb = p->pTargetFd->pReal; u32 volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); if( p->rc==SQLITE_OK ){ - iRet = (i64)(((u64)ptr[10] << 32) + ptr[11]); + iRet = ((i64)ptr[10] << 32) + ptr[11]; } } return iRet; } /* ** This function is called as part of initializing or reinitializing an -** incremental checkpoint. +** incremental checkpoint. ** -** It populates the sqlite3rbu.aFrame[] array with the set of -** (wal frame -> db page) copy operations required to checkpoint the -** current wal file, and obtains the set of shm locks required to safely +** It populates the sqlite3rbu.aFrame[] array with the set of +** (wal frame -> db page) copy operations required to checkpoint the +** current wal file, and obtains the set of shm locks required to safely ** perform the copy operations directly on the file-system. ** ** If argument pState is not NULL, then the incremental checkpoint is ** being resumed. In this case, if the checksum of the wal-index-header ** following recovery is not the same as the checksum saved in the RbuState @@ -222896,11 +172944,11 @@ ** recovered. Running a read-statement here to ensure that doing so ** does not interfere with the "capture" process below. */ if( pState==0 ){ p->eStage = 0; if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_schema", 0, 0, 0); + p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0); } } /* Assuming no error has occurred, run a "restart" checkpoint with the ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following @@ -222913,30 +172961,30 @@ ** * Attempts to read from the *-wal file or write to the database file ** do not perform any IO. Instead, the frame/page combinations that ** would be read/written are recorded in the sqlite3rbu.aFrame[] ** array. ** - ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, + ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, ** READ0 and CHECKPOINT locks taken as part of the checkpoint are ** no-ops. These locks will not be released until the connection ** is closed. ** - ** * Attempting to xSync() the database file causes an SQLITE_NOTICE + ** * Attempting to xSync() the database file causes an SQLITE_INTERNAL ** error. ** ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the - ** checkpoint below fails with SQLITE_NOTICE, and leaves the aFrame[] - ** array populated with a set of (frame -> page) mappings. Because the - ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy - ** data from the wal file into the database file according to the + ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[] + ** array populated with a set of (frame -> page) mappings. Because the + ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy + ** data from the wal file into the database file according to the ** contents of aFrame[]. */ if( p->rc==SQLITE_OK ){ int rc2; p->eStage = RBU_STAGE_CAPTURE; rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); - if( rc2!=SQLITE_NOTICE ) p->rc = rc2; + if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; } if( p->rc==SQLITE_OK && p->nFrame>0 ){ p->eStage = RBU_STAGE_CKPT; p->nStep = (pState ? pState->nRow : 0); @@ -222958,13 +173006,13 @@ p->nPagePerSector = nSectorSize / p->pgsz; }else{ p->nPagePerSector = 1; } - /* Call xSync() on the wal file. This causes SQLite to sync the - ** directory in which the target database and the wal file reside, in - ** case it has not been synced since the rename() call in + /* Call xSync() on the wal file. This causes SQLite to sync the + ** directory in which the target database and the wal file reside, in + ** case it has not been synced since the rename() call in ** rbuMoveOalFile(). */ p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL); } } } @@ -222978,11 +173026,11 @@ const u32 mReq = (1<mLock!=mReq ){ pRbu->rc = SQLITE_BUSY; - return SQLITE_NOTICE_RBU; + return SQLITE_INTERNAL; } pRbu->pgsz = iAmt; if( pRbu->nFrame==pRbu->nFrameAlloc ){ int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; @@ -223001,11 +173049,11 @@ return SQLITE_OK; } /* ** Called when a page of data is written to offset iOff of the database -** file while the rbu handle is in capture mode. Record the page number +** file while the rbu handle is in capture mode. Record the page number ** of the page being written in the aFrame[] array. */ static int rbuCaptureDbWrite(sqlite3rbu *pRbu, i64 iOff){ pRbu->aFrame[pRbu->nFrame-1].iDbPage = (u32)(iOff / pRbu->pgsz) + 1; return SQLITE_OK; @@ -223028,53 +173076,21 @@ iOff = (i64)(pFrame->iDbPage-1) * p->pgsz; p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff); } -/* -** This value is copied from the definition of ZIPVFS_CTRL_FILE_POINTER -** in zipvfs.h. -*/ -#define RBU_ZIPVFS_CTRL_FILE_POINTER 230439 - -/* -** Take an EXCLUSIVE lock on the database file. Return SQLITE_OK if -** successful, or an SQLite error code otherwise. -*/ -static int rbuLockDatabase(sqlite3 *db){ - int rc = SQLITE_OK; - sqlite3_file *fd = 0; - - sqlite3_file_control(db, "main", RBU_ZIPVFS_CTRL_FILE_POINTER, &fd); - if( fd ){ - sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd); - rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED); - if( rc==SQLITE_OK ){ - rc = fd->pMethods->xUnlock(fd, SQLITE_LOCK_NONE); - } - sqlite3_file_control(db, "main", RBU_ZIPVFS_CTRL_FILE_POINTER, &fd); - }else{ - sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd); - } - - if( rc==SQLITE_OK && fd->pMethods ){ - rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED); - if( rc==SQLITE_OK ){ - rc = fd->pMethods->xLock(fd, SQLITE_LOCK_EXCLUSIVE); - } - } - return rc; -} - -/* -** Return true if the database handle passed as the only argument -** was opened with the rbu_exclusive_checkpoint=1 URI parameter -** specified. Or false otherwise. -*/ -static int rbuExclusiveCheckpoint(sqlite3 *db){ - const char *zUri = sqlite3_db_filename(db, 0); - return sqlite3_uri_boolean(zUri, RBU_EXCLUSIVE_CHECKPOINT, 0); + +/* +** Take an EXCLUSIVE lock on the database file. +*/ +static void rbuLockDatabase(sqlite3rbu *p){ + sqlite3_file *pReal = p->pTargetFd->pReal; + assert( p->rc==SQLITE_OK ); + p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED); + if( p->rc==SQLITE_OK ){ + p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE); + } } #if defined(_WIN32_WCE) static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){ int nChar; @@ -223101,11 +173117,11 @@ /* ** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock ** on the database file. This proc moves the *-oal file to the *-wal path, ** then reopens the database file (this time in vanilla, non-oal, WAL mode). -** If an error occurs, leave an error code and error message in the rbu +** If an error occurs, leave an error code and error message in the rbu ** handle. */ static void rbuMoveOalFile(sqlite3rbu *p){ const char *zBase = sqlite3_db_filename(p->dbMain, "main"); const char *zMove = zBase; @@ -223123,47 +173139,58 @@ if( zWal==0 || zOal==0 ){ p->rc = SQLITE_NOMEM; }else{ /* Move the *-oal file to *-wal. At this point connection p->db is ** holding a SHARED lock on the target database file (because it is - ** in WAL mode). So no other connection may be writing the db. + ** in WAL mode). So no other connection may be writing the db. ** ** In order to ensure that there are no database readers, an EXCLUSIVE ** lock is obtained here before the *-oal is moved to *-wal. */ - sqlite3 *dbMain = 0; - rbuFileSuffix3(zBase, zWal); - rbuFileSuffix3(zBase, zOal); - - /* Re-open the databases. */ - rbuObjIterFinalize(&p->objiter); - sqlite3_close(p->dbRbu); - sqlite3_close(p->dbMain); - p->dbMain = 0; - p->dbRbu = 0; - - dbMain = rbuOpenDbhandle(p, p->zTarget, 1); - if( dbMain ){ - assert( p->rc==SQLITE_OK ); - p->rc = rbuLockDatabase(dbMain); - } - - if( p->rc==SQLITE_OK ){ - p->rc = p->xRename(p->pRenameArg, zOal, zWal); - } - - if( p->rc!=SQLITE_OK - || rbuIsVacuum(p) - || rbuExclusiveCheckpoint(dbMain)==0 - ){ - sqlite3_close(dbMain); - dbMain = 0; - } - - if( p->rc==SQLITE_OK ){ - rbuOpenDatabase(p, dbMain, 0); - rbuSetupCheckpoint(p, 0); + rbuLockDatabase(p); + if( p->rc==SQLITE_OK ){ + rbuFileSuffix3(zBase, zWal); + rbuFileSuffix3(zBase, zOal); + + /* Re-open the databases. */ + rbuObjIterFinalize(&p->objiter); + sqlite3_close(p->dbRbu); + sqlite3_close(p->dbMain); + p->dbMain = 0; + p->dbRbu = 0; + +#if defined(_WIN32_WCE) + { + LPWSTR zWideOal; + LPWSTR zWideWal; + + zWideOal = rbuWinUtf8ToUnicode(zOal); + if( zWideOal ){ + zWideWal = rbuWinUtf8ToUnicode(zWal); + if( zWideWal ){ + if( MoveFileW(zWideOal, zWideWal) ){ + p->rc = SQLITE_OK; + }else{ + p->rc = SQLITE_IOERR; + } + sqlite3_free(zWideWal); + }else{ + p->rc = SQLITE_IOERR_NOMEM; + } + sqlite3_free(zWideOal); + }else{ + p->rc = SQLITE_IOERR_NOMEM; + } + } +#else + p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK; +#endif + + if( p->rc==SQLITE_OK ){ + rbuOpenDatabase(p, 0); + rbuSetupCheckpoint(p, 0); + } } } sqlite3_free(zWal); sqlite3_free(zOal); @@ -223270,12 +173297,12 @@ for(i=0; inCol; i++){ /* If this is an INSERT into a table b-tree and the table has an ** explicit INTEGER PRIMARY KEY, check that this is not an attempt ** to write a NULL into the IPK column. That is not permitted. */ - if( eType==RBU_INSERT - && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] + if( eType==RBU_INSERT + && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL ){ p->rc = SQLITE_MISMATCH; p->zErrmsg = sqlite3_mprintf("datatype mismatch"); return; @@ -223288,22 +173315,22 @@ pVal = sqlite3_column_value(pIter->pSelect, i); p->rc = sqlite3_bind_value(pWriter, i+1, pVal); if( p->rc ) return; } if( pIter->zIdx==0 ){ - if( pIter->eType==RBU_PK_VTAB - || pIter->eType==RBU_PK_NONE - || (pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)) + if( pIter->eType==RBU_PK_VTAB + || pIter->eType==RBU_PK_NONE + || (pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)) ){ - /* For a virtual table, or a table with no primary key, the + /* For a virtual table, or a table with no primary key, the ** SELECT statement is: ** ** SELECT , rbu_control, rbu_rowid FROM .... ** ** Hence column_value(pIter->nCol+1). */ - assertColumnName(pIter->pSelect, pIter->nCol+1, + assertColumnName(pIter->pSelect, pIter->nCol+1, rbuIsVacuum(p) ? "rowid" : "rbu_rowid" ); pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); } @@ -223363,12 +173390,12 @@ pVal = sqlite3_column_value(pIter->pSelect, i); if( pIter->abTblPk[i] || c!='.' ){ p->rc = sqlite3_bind_value(pUpdate, i+1, pVal); } } - if( p->rc==SQLITE_OK - && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) + if( p->rc==SQLITE_OK + && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) ){ /* Bind the rbu_rowid value to column _rowid_ */ assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal); @@ -223394,11 +173421,11 @@ if( p->rc==SQLITE_OK ){ sqlite3 *dbread = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain); int iCookie = 1000000; sqlite3_stmt *pStmt; - p->rc = prepareAndCollectError(dbread, &pStmt, &p->zErrmsg, + p->rc = prepareAndCollectError(dbread, &pStmt, &p->zErrmsg, "PRAGMA schema_version" ); if( p->rc==SQLITE_OK ){ /* Coverage: it may be that this sqlite3_step() cannot fail. There ** is already a transaction open, so the prepared statement cannot @@ -223426,34 +173453,32 @@ sqlite3_stmt *pInsert = 0; rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd); int rc; assert( p->zErrmsg==0 ); - rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg, + rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg, sqlite3_mprintf( "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES " "(%d, %d), " "(%d, %Q), " "(%d, %Q), " "(%d, %d), " - "(%d, %lld), " + "(%d, %d), " "(%d, %lld), " "(%d, %lld), " "(%d, %lld), " - "(%d, %lld), " - "(%d, %Q) ", + "(%d, %lld) ", p->zStateDb, RBU_STATE_STAGE, eStage, - RBU_STATE_TBL, p->objiter.zTbl, - RBU_STATE_IDX, p->objiter.zIdx, - RBU_STATE_ROW, p->nStep, + RBU_STATE_TBL, p->objiter.zTbl, + RBU_STATE_IDX, p->objiter.zIdx, + RBU_STATE_ROW, p->nStep, RBU_STATE_PROGRESS, p->nProgress, RBU_STATE_CKPT, p->iWalCksum, RBU_STATE_COOKIE, (i64)pFd->iCookie, RBU_STATE_OALSZ, p->iOalSz, - RBU_STATE_PHASEONESTEP, p->nPhaseOneStep, - RBU_STATE_DATATBL, p->objiter.zDataTbl + RBU_STATE_PHASEONESTEP, p->nPhaseOneStep ) ); assert( pInsert==0 || rc==SQLITE_OK ); if( rc==SQLITE_OK ){ @@ -223464,11 +173489,11 @@ } } /* -** The second argument passed to this function is the name of a PRAGMA +** The second argument passed to this function is the name of a PRAGMA ** setting - "page_size", "auto_vacuum", "user_version" or "application_id". ** This function executes the following on sqlite3rbu.dbRbu: ** ** "PRAGMA main.$zPragma" ** @@ -223483,11 +173508,11 @@ ** dbRbu to dbMain. */ static void rbuCopyPragma(sqlite3rbu *p, const char *zPragma){ if( p->rc==SQLITE_OK ){ sqlite3_stmt *pPragma = 0; - p->rc = prepareFreeAndCollectError(p->dbRbu, &pPragma, &p->zErrmsg, + p->rc = prepareFreeAndCollectError(p->dbRbu, &pPragma, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.%s", zPragma) ); if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPragma) ){ p->rc = rbuMPrintfExec(p, p->dbMain, "PRAGMA main.%s = %d", zPragma, sqlite3_column_int(pPragma, 0) @@ -223496,11 +173521,11 @@ rbuFinalize(p, pPragma); } } /* -** The RBU handle passed as the only argument has just been opened and +** The RBU handle passed as the only argument has just been opened and ** the state database is empty. If this RBU handle was opened for an ** RBU vacuum operation, create the schema in the target db. */ static void rbuCreateTargetSchema(sqlite3rbu *p){ sqlite3_stmt *pSql = 0; @@ -223507,12 +173532,12 @@ sqlite3_stmt *pInsert = 0; assert( rbuIsVacuum(p) ); p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=1", 0,0, &p->zErrmsg); if( p->rc==SQLITE_OK ){ - p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, - "SELECT sql FROM sqlite_schema WHERE sql!='' AND rootpage!=0" + p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, + "SELECT sql FROM sqlite_master WHERE sql!='' AND rootpage!=0" " AND name!='sqlite_sequence' " " ORDER BY type DESC" ); } @@ -223522,18 +173547,18 @@ } rbuFinalize(p, pSql); if( p->rc!=SQLITE_OK ) return; if( p->rc==SQLITE_OK ){ - p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, - "SELECT * FROM sqlite_schema WHERE rootpage=0 OR rootpage IS NULL" + p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, + "SELECT * FROM sqlite_master WHERE rootpage=0 OR rootpage IS NULL" ); } if( p->rc==SQLITE_OK ){ - p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg, - "INSERT INTO sqlite_schema VALUES(?,?,?,?,?)" + p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg, + "INSERT INTO sqlite_master VALUES(?,?,?,?,?)" ); } while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){ int i; @@ -223569,15 +173594,15 @@ } while( p->rc==SQLITE_OK && pIter->zTbl ){ if( pIter->bCleanup ){ - /* Clean up the rbu_tmp_xxx table for the previous table. It + /* Clean up the rbu_tmp_xxx table for the previous table. It ** cannot be dropped as there are currently active SQL statements. ** But the contents can be deleted. */ if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ - rbuMPrintfExec(p, p->dbRbu, + rbuMPrintfExec(p, p->dbRbu, "DELETE FROM %s.'rbu_tmp_%q'", p->zStateDb, pIter->zDataTbl ); } }else{ rbuObjIterPrepareAll(p, pIter, 0); @@ -223623,31 +173648,31 @@ case RBU_STAGE_CKPT: { if( p->rc==SQLITE_OK ){ if( p->nStep>=p->nFrame ){ sqlite3_file *pDb = p->pTargetFd->pReal; - + /* Sync the db file */ p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); - + /* Update nBackfill */ if( p->rc==SQLITE_OK ){ void volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, &ptr); if( p->rc==SQLITE_OK ){ ((u32 volatile*)ptr)[24] = p->iMaxFrame; } } - + if( p->rc==SQLITE_OK ){ p->eStage = RBU_STAGE_DONE; p->rc = SQLITE_DONE; } }else{ /* At one point the following block copied a single frame from the ** wal file to the database file. So that one call to sqlite3rbu_step() - ** checkpointed a single frame. + ** checkpointed a single frame. ** ** However, if the sector-size is larger than the page-size, and the ** application calls sqlite3rbu_savestate() or close() immediately ** after this step, then rbu_step() again, then a power failure occurs, ** then the database page written here may be damaged. Work around @@ -223657,11 +173682,11 @@ do{ RbuFrame *pFrame = &p->aFrame[p->nStep]; iSector = (pFrame->iDbPage-1) / p->nPagePerSector; rbuCheckpointFrame(p, pFrame); p->nStep++; - }while( p->nStepnFrame + }while( p->nStepnFrame && iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector) && p->rc==SQLITE_OK ); } p->nProgress++; @@ -223703,14 +173728,13 @@ assert( p->rc==SQLITE_OK ); if( pState->zTbl ){ RbuObjIter *pIter = &p->objiter; int rc = SQLITE_OK; - while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup + while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup || rbuStrCompare(pIter->zIdx, pState->zIdx) - || (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl)) - || (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl)) + || rbuStrCompare(pIter->zTbl, pState->zTbl) )){ rc = rbuObjIterNext(p, pIter); } if( rc==SQLITE_OK && !pIter->zTbl ){ @@ -223733,12 +173757,11 @@ ** leave an error code and error message in the rbu handle. */ static void rbuDeleteOalFile(sqlite3rbu *p){ char *zOal = rbuMPrintf(p, "%s-oal", p->zTarget); if( zOal ){ - sqlite3_vfs *pVfs = 0; - sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_VFS_POINTER, &pVfs); + sqlite3_vfs *pVfs = sqlite3_vfs_find(0); assert( pVfs && p->rc==SQLITE_OK && p->zErrmsg==0 ); pVfs->xDelete(pVfs, zOal, 0); sqlite3_free(zOal); } } @@ -223759,11 +173782,10 @@ p->rc = sqlite3rbu_create_vfs(zRnd, 0); if( p->rc==SQLITE_OK ){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd); assert( pVfs ); p->zVfsName = pVfs->zName; - ((rbu_vfs*)pVfs)->pRbu = p; } } /* ** Destroy the private VFS created for the rbu handle passed as the only @@ -223780,25 +173802,23 @@ ** This user-defined SQL function is invoked with a single argument - the ** name of a table expected to appear in the target database. It returns ** the number of auxilliary indexes on the table. */ static void rbuIndexCntFunc( - sqlite3_context *pCtx, + sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx); sqlite3_stmt *pStmt = 0; char *zErrmsg = 0; int rc; - sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain); assert( nVal==1 ); - UNUSED_PARAMETER(nVal); - - rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg, - sqlite3_mprintf("SELECT count(*) FROM sqlite_schema " + + rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg, + sqlite3_mprintf("SELECT count(*) FROM sqlite_master " "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0])) ); if( rc!=SQLITE_OK ){ sqlite3_result_error(pCtx, zErrmsg, -1); }else{ @@ -223808,11 +173828,11 @@ } rc = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ){ sqlite3_result_int(pCtx, nIndex); }else{ - sqlite3_result_error(pCtx, sqlite3_errmsg(db), -1); + sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1); } } sqlite3_free(zErrmsg); } @@ -223827,38 +173847,38 @@ ** There should be one row in the table for each data_xxx table in the ** database. The 'tbl' column should contain the name of a data_xxx table, ** and the cnt column the number of rows it contains. ** ** sqlite3rbu.nPhaseOneStep is initialized to the sum of (1 + nIndex) * cnt -** for all rows in the rbu_count table, where nIndex is the number of +** for all rows in the rbu_count table, where nIndex is the number of ** indexes on the corresponding target database table. */ static void rbuInitPhaseOneSteps(sqlite3rbu *p){ if( p->rc==SQLITE_OK ){ sqlite3_stmt *pStmt = 0; int bExists = 0; /* True if rbu_count exists */ p->nPhaseOneStep = -1; - p->rc = sqlite3_create_function(p->dbRbu, + p->rc = sqlite3_create_function(p->dbRbu, "rbu_index_cnt", 1, SQLITE_UTF8, (void*)p, rbuIndexCntFunc, 0, 0 ); - + /* Check for the rbu_count table. If it does not exist, or if an error ** occurs, nPhaseOneStep will be left set to -1. */ if( p->rc==SQLITE_OK ){ p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - "SELECT 1 FROM sqlite_schema WHERE tbl_name = 'rbu_count'" + "SELECT 1 FROM sqlite_master WHERE tbl_name = 'rbu_count'" ); } if( p->rc==SQLITE_OK ){ if( SQLITE_ROW==sqlite3_step(pStmt) ){ bExists = 1; } p->rc = sqlite3_finalize(pStmt); } - + if( p->rc==SQLITE_OK && bExists ){ p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, "SELECT sum(cnt * (1 + rbu_index_cnt(rbu_target_name(tbl))))" "FROM rbu_count" ); @@ -223872,11 +173892,11 @@ } } static sqlite3rbu *openRbuHandle( - const char *zTarget, + const char *zTarget, const char *zRbu, const char *zState ){ sqlite3rbu *p; size_t nTarget = zTarget ? strlen(zTarget) : 0; @@ -223887,11 +173907,10 @@ if( p ){ RbuState *pState = 0; /* Create the custom VFS. */ memset(p, 0, sizeof(sqlite3rbu)); - sqlite3rbu_rename_handler(p, 0, 0); rbuCreateVfs(p); /* Open the target, RBU and state databases */ if( p->rc==SQLITE_OK ){ char *pCsr = (char*)&p[1]; @@ -223911,24 +173930,24 @@ /* If the first attempt to open the database file fails and the bRetry ** flag it set, this means that the db was not opened because it seemed ** to be a wal-mode db. But, this may have happened due to an earlier ** RBU vacuum operation leaving an old wal file in the directory. ** If this is the case, it will have been checkpointed and deleted - ** when the handle was closed and a second attempt to open the + ** when the handle was closed and a second attempt to open the ** database may succeed. */ - rbuOpenDatabase(p, 0, &bRetry); + rbuOpenDatabase(p, &bRetry); if( bRetry ){ - rbuOpenDatabase(p, 0, 0); + rbuOpenDatabase(p, 0); } } if( p->rc==SQLITE_OK ){ pState = rbuLoadState(p); assert( pState || p->rc!=SQLITE_OK ); if( p->rc==SQLITE_OK ){ - if( pState->eStage==0 ){ + if( pState->eStage==0 ){ rbuDeleteOalFile(p); rbuInitPhaseOneSteps(p); p->eStage = RBU_STAGE_OAL; }else{ p->eStage = pState->eStage; @@ -223948,19 +173967,19 @@ p->eStage = RBU_STAGE_CKPT; p->nStep = 0; } } - if( p->rc==SQLITE_OK + if( p->rc==SQLITE_OK && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE) && pState->eStage!=0 ){ rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd); - if( pFd->iCookie!=pState->iCookie ){ + if( pFd->iCookie!=pState->iCookie ){ /* At this point (pTargetFd->iCookie) contains the value of the - ** change-counter cookie (the thing that gets incremented when a - ** transaction is committed in rollback mode) currently stored on + ** change-counter cookie (the thing that gets incremented when a + ** transaction is committed in rollback mode) currently stored on ** page 1 of the database file. */ p->rc = SQLITE_BUSY; p->zErrmsg = sqlite3_mprintf("database modified during rbu %s", (rbuIsVacuum(p) ? "vacuum" : "update") ); @@ -223993,11 +174012,11 @@ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); } /* Check if the main database is a zipvfs db. If it is, set the upper - ** level pager to use "journal_mode=off". This prevents it from + ** level pager to use "journal_mode=off". This prevents it from ** generating a large journal using a temp file. */ if( p->rc==SQLITE_OK ){ int frc = sqlite3_file_control(db, "main", SQLITE_FCNTL_ZIPVFS, 0); if( frc==SQLITE_OK ){ p->rc = sqlite3_exec( @@ -224010,18 +174029,10 @@ } } }else if( p->eStage==RBU_STAGE_MOVE ){ /* no-op */ }else if( p->eStage==RBU_STAGE_CKPT ){ - if( !rbuIsVacuum(p) && rbuExclusiveCheckpoint(p->dbMain) ){ - /* If the rbu_exclusive_checkpoint=1 URI parameter was specified - ** and an incremental checkpoint is being resumed, attempt an - ** exclusive lock on the db file. If this fails, so be it. */ - p->eStage = RBU_STAGE_DONE; - rbuLockDatabase(p->dbMain); - p->eStage = RBU_STAGE_CKPT; - } rbuSetupCheckpoint(p, pState); }else if( p->eStage==RBU_STAGE_DONE ){ p->rc = SQLITE_DONE; }else{ p->rc = SQLITE_CORRUPT; @@ -224047,35 +174058,30 @@ } return pRet; } /* -** Open and return a new RBU handle. +** Open and return a new RBU handle. */ SQLITE_API sqlite3rbu *sqlite3rbu_open( - const char *zTarget, + const char *zTarget, const char *zRbu, const char *zState ){ if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); } + /* TODO: Check that zTarget and zRbu are non-NULL */ return openRbuHandle(zTarget, zRbu, zState); } /* ** Open a handle to begin or resume an RBU VACUUM operation. */ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( - const char *zTarget, + const char *zTarget, const char *zState ){ if( zTarget==0 ){ return rbuMisuseError(); } - if( zState ){ - size_t n = strlen(zState); - if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){ - return rbuMisuseError(); - } - } /* TODO: Check that both arguments are non-NULL */ return openRbuHandle(0, zTarget, zState); } /* @@ -224136,12 +174142,12 @@ /* Close any open statement handles. */ rbuObjIterFinalize(&p->objiter); /* If this is an RBU vacuum handle and the vacuum has either finished - ** successfully or encountered an error, delete the contents of the - ** state table. This causes the next call to sqlite3rbu_vacuum() + ** successfully or encountered an error, delete the contents of the + ** state table. This causes the next call to sqlite3rbu_vacuum() ** specifying the current target and state databases to start a new ** vacuum from scratch. */ if( rbuIsVacuum(p) && p->rc!=SQLITE_OK && p->dbRbu ){ int rc2 = sqlite3_exec(p->dbRbu, "DELETE FROM stat.rbu_state", 0, 0, 0); if( p->rc==SQLITE_DONE && rc2!=SQLITE_OK ) p->rc = rc2; @@ -224148,11 +174154,10 @@ } /* Close the open database handle and VFS object. */ sqlite3_close(p->dbRbu); sqlite3_close(p->dbMain); - assert( p->szTemp==0 ); rbuDeleteVfs(p); sqlite3_free(p->aBuf); sqlite3_free(p->aFrame); rbuEditErrmsg(p); @@ -224170,11 +174175,11 @@ } return rc; } /* -** Return the total number of key-value operations (inserts, deletes or +** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current RBU update was started. */ SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ return pRbu->nProgress; @@ -224268,91 +174273,39 @@ rc = p->rc; if( p->eStage==RBU_STAGE_OAL ){ assert( rc!=SQLITE_DONE ); if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0); - if( rc==SQLITE_OK ){ - const char *zBegin = rbuIsVacuum(p) ? "BEGIN" : "BEGIN IMMEDIATE"; - rc = sqlite3_exec(p->dbRbu, zBegin, 0, 0, 0); - } + if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0); if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0); } p->rc = rc; return rc; } -/* -** Default xRename callback for RBU. -*/ -static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){ - int rc = SQLITE_OK; - UNUSED_PARAMETER(pArg); -#if defined(_WIN32_WCE) - { - LPWSTR zWideOld; - LPWSTR zWideNew; - - zWideOld = rbuWinUtf8ToUnicode(zOld); - if( zWideOld ){ - zWideNew = rbuWinUtf8ToUnicode(zNew); - if( zWideNew ){ - if( MoveFileW(zWideOld, zWideNew) ){ - rc = SQLITE_OK; - }else{ - rc = SQLITE_IOERR; - } - sqlite3_free(zWideNew); - }else{ - rc = SQLITE_IOERR_NOMEM; - } - sqlite3_free(zWideOld); - }else{ - rc = SQLITE_IOERR_NOMEM; - } - } -#else - rc = rename(zOld, zNew) ? SQLITE_IOERR : SQLITE_OK; -#endif - return rc; -} - -SQLITE_API void sqlite3rbu_rename_handler( - sqlite3rbu *pRbu, - void *pArg, - int (*xRename)(void *pArg, const char *zOld, const char *zNew) -){ - if( xRename ){ - pRbu->xRename = xRename; - pRbu->pRenameArg = pArg; - }else{ - pRbu->xRename = xDefaultRename; - pRbu->pRenameArg = 0; - } -} - /************************************************************************** ** Beginning of RBU VFS shim methods. The VFS shim modifies the behaviour ** of a standard VFS in the following ways: ** -** 1. Whenever the first page of a main database file is read or +** 1. Whenever the first page of a main database file is read or ** written, the value of the change-counter cookie is stored in ** rbu_file.iCookie. Similarly, the value of the "write-version" ** database header field is stored in rbu_file.iWriteVer. This ensures ** that the values are always trustworthy within an open transaction. ** ** 2. Whenever an SQLITE_OPEN_WAL file is opened, the (rbu_file.pWalFd) ** member variable of the associated database file descriptor is set -** to point to the new file. A mutex protected linked list of all main -** db fds opened using a particular RBU VFS is maintained at +** to point to the new file. A mutex protected linked list of all main +** db fds opened using a particular RBU VFS is maintained at ** rbu_vfs.pMain to facilitate this. ** -** 3. Using a new file-control "SQLITE_FCNTL_RBU", a main db rbu_file +** 3. Using a new file-control "SQLITE_FCNTL_RBU", a main db rbu_file ** object can be marked as the target database of an RBU update. This ** turns on the following extra special behaviour: ** -** 3a. If xAccess() is called to check if there exists a *-wal file +** 3a. If xAccess() is called to check if there exists a *-wal file ** associated with an RBU target database currently in RBU_STAGE_OAL ** stage (preparing the *-oal file), the following special handling ** applies: ** ** * if the *-wal file does exist, return SQLITE_CANTOPEN. An RBU @@ -224361,38 +174314,37 @@ ** * if the *-wal file does not exist, set the output parameter to ** non-zero (to tell SQLite that it does exist) anyway. ** ** Then, when xOpen() is called to open the *-wal file associated with ** the RBU target in RBU_STAGE_OAL stage, instead of opening the *-wal -** file, the rbu vfs opens the corresponding *-oal file instead. +** file, the rbu vfs opens the corresponding *-oal file instead. ** ** 3b. The *-shm pages returned by xShmMap() for a target db file in ** RBU_STAGE_OAL mode are actually stored in heap memory. This is to ** avoid creating a *-shm file on disk. Additionally, xShmLock() calls ** are no-ops on target database files in RBU_STAGE_OAL mode. This is -** because assert() statements in some VFS implementations fail if +** because assert() statements in some VFS implementations fail if ** xShmLock() is called before xShmMap(). ** ** 3c. If an EXCLUSIVE lock is attempted on a target database file in any -** mode except RBU_STAGE_DONE (all work completed and checkpointed), it +** mode except RBU_STAGE_DONE (all work completed and checkpointed), it ** fails with an SQLITE_BUSY error. This is to stop RBU connections ** from automatically checkpointing a *-wal (or *-oal) file from within ** sqlite3_close(). ** ** 3d. In RBU_STAGE_CAPTURE mode, all xRead() calls on the wal file, and -** all xWrite() calls on the target database file perform no IO. +** all xWrite() calls on the target database file perform no IO. ** Instead the frame and page numbers that would be read and written ** are recorded. Additionally, successful attempts to obtain exclusive -** xShmLock() WRITER, CHECKPOINTER and READ0 locks on the target +** xShmLock() WRITER, CHECKPOINTER and READ0 locks on the target ** database file are recorded. xShmLock() calls to unlock the same ** locks are no-ops (so that once obtained, these locks are never ** relinquished). Finally, calls to xSync() on the target database -** file fail with SQLITE_NOTICE errors. +** file fail with SQLITE_INTERNAL errors. */ static void rbuUnlockShm(rbu_file *p){ - assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); if( p->pRbu ){ int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock; int i; for(i=0; ipRbu->mLock ){ @@ -224401,85 +174353,10 @@ } p->pRbu->mLock = 0; } } -/* -*/ -static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){ - sqlite3rbu *pRbu = pFd->pRbu; - i64 nDiff = nNew - pFd->sz; - pRbu->szTemp += nDiff; - pFd->sz = nNew; - assert( pRbu->szTemp>=0 ); - if( pRbu->szTempLimit && pRbu->szTemp>pRbu->szTempLimit ) return SQLITE_FULL; - return SQLITE_OK; -} - -/* -** Add an item to the main-db lists, if it is not already present. -** -** There are two main-db lists. One for all file descriptors, and one -** for all file descriptors with rbu_file.pDb!=0. If the argument has -** rbu_file.pDb!=0, then it is assumed to already be present on the -** main list and is only added to the pDb!=0 list. -*/ -static void rbuMainlistAdd(rbu_file *p){ - rbu_vfs *pRbuVfs = p->pRbuVfs; - rbu_file *pIter; - assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) ); - sqlite3_mutex_enter(pRbuVfs->mutex); - if( p->pRbu==0 ){ - for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext); - p->pMainNext = pRbuVfs->pMain; - pRbuVfs->pMain = p; - }else{ - for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){} - if( pIter==0 ){ - p->pMainRbuNext = pRbuVfs->pMainRbu; - pRbuVfs->pMainRbu = p; - } - } - sqlite3_mutex_leave(pRbuVfs->mutex); -} - -/* -** Remove an item from the main-db lists. -*/ -static void rbuMainlistRemove(rbu_file *p){ - rbu_file **pp; - sqlite3_mutex_enter(p->pRbuVfs->mutex); - for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){} - if( *pp ) *pp = p->pMainNext; - p->pMainNext = 0; - for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){} - if( *pp ) *pp = p->pMainRbuNext; - p->pMainRbuNext = 0; - sqlite3_mutex_leave(p->pRbuVfs->mutex); -} - -/* -** Given that zWal points to a buffer containing a wal file name passed to -** either the xOpen() or xAccess() VFS method, search the main-db list for -** a file-handle opened by the same database connection on the corresponding -** database file. -** -** If parameter bRbu is true, only search for file-descriptors with -** rbu_file.pDb!=0. -*/ -static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){ - rbu_file *pDb; - sqlite3_mutex_enter(pRbuVfs->mutex); - if( bRbu ){ - for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){} - }else{ - for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} - } - sqlite3_mutex_leave(pRbuVfs->mutex); - return pDb; -} - /* ** Close an rbu file. */ static int rbuVfsClose(sqlite3_file *pFile){ rbu_file *p = (rbu_file*)pFile; @@ -224493,30 +174370,27 @@ sqlite3_free(p->apShm); p->apShm = 0; sqlite3_free(p->zDel); if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ - const sqlite3_io_methods *pMeth = p->pReal->pMethods; - rbuMainlistRemove(p); + rbu_file **pp; + sqlite3_mutex_enter(p->pRbuVfs->mutex); + for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); + *pp = p->pMainNext; + sqlite3_mutex_leave(p->pRbuVfs->mutex); rbuUnlockShm(p); - if( pMeth->iVersion>1 && pMeth->xShmUnmap ){ - pMeth->xShmUnmap(p->pReal, 0); - } - } - else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ - rbuUpdateTempSize(p, 0); - } - assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p ); + p->pReal->pMethods->xShmUnmap(p->pReal, 0); + } /* Close the underlying file handle */ rc = p->pReal->pMethods->xClose(p->pReal); return rc; } /* -** Read and return an unsigned 32-bit big-endian integer from the buffer +** Read and return an unsigned 32-bit big-endian integer from the buffer ** passed as the only argument. */ static u32 rbuGetU32(u8 *aBuf){ return ((u32)aBuf[0] << 24) + ((u32)aBuf[1] << 16) @@ -224542,13 +174416,13 @@ /* ** Read data from an rbuVfs-file. */ static int rbuVfsRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, + sqlite3_file *pFile, + void *zBuf, + int iAmt, sqlite_int64 iOfst ){ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc; @@ -224555,24 +174429,24 @@ if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ assert( p->openFlags & SQLITE_OPEN_WAL ); rc = rbuCaptureWalRead(p->pRbu, iOfst, iAmt); }else{ - if( pRbu && pRbu->eStage==RBU_STAGE_OAL - && (p->openFlags & SQLITE_OPEN_WAL) - && iOfst>=pRbu->iOalSz + if( pRbu && pRbu->eStage==RBU_STAGE_OAL + && (p->openFlags & SQLITE_OPEN_WAL) + && iOfst>=pRbu->iOalSz ){ rc = SQLITE_OK; memset(zBuf, 0, iAmt); }else{ rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); #if 1 - /* If this is being called to read the first page of the target - ** database as part of an rbu vacuum operation, synthesize the + /* If this is being called to read the first page of the target + ** database as part of an rbu vacuum operation, synthesize the ** contents of the first page if it does not yet exist. Otherwise, ** SQLite will not check for a *-wal file. */ - if( pRbu && rbuIsVacuum(pRbu) + if( pRbu && rbuIsVacuum(pRbu) && rc==SQLITE_IOERR_SHORT_READ && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) && pRbu->rc==SQLITE_OK ){ sqlite3_file *pFd = (sqlite3_file*)pRbu->pRbuFd; @@ -224608,13 +174482,13 @@ /* ** Write data to an rbuVfs-file. */ static int rbuVfsWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, + sqlite3_file *pFile, + const void *zBuf, + int iAmt, sqlite_int64 iOfst ){ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc; @@ -224621,23 +174495,15 @@ if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); rc = rbuCaptureDbWrite(p->pRbu, iOfst); }else{ - if( pRbu ){ - if( pRbu->eStage==RBU_STAGE_OAL - && (p->openFlags & SQLITE_OPEN_WAL) - && iOfst>=pRbu->iOalSz - ){ - pRbu->iOalSz = iAmt + iOfst; - }else if( p->openFlags & SQLITE_OPEN_DELETEONCLOSE ){ - i64 szNew = iAmt+iOfst; - if( szNew>p->sz ){ - rc = rbuUpdateTempSize(p, szNew); - if( rc!=SQLITE_OK ) return rc; - } - } + if( pRbu && pRbu->eStage==RBU_STAGE_OAL + && (p->openFlags & SQLITE_OPEN_WAL) + && iOfst>=pRbu->iOalSz + ){ + pRbu->iOalSz = iAmt + iOfst; } rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ /* These look like magic numbers. But they are stable, as they are part ** of the definition of the SQLite file format, which may not change. */ @@ -224652,14 +174518,10 @@ /* ** Truncate an rbuVfs-file. */ static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ rbu_file *p = (rbu_file*)pFile; - if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ - int rc = rbuUpdateTempSize(p, size); - if( rc!=SQLITE_OK ) return rc; - } return p->pReal->pMethods->xTruncate(p->pReal, size); } /* ** Sync an rbuVfs-file. @@ -224666,11 +174528,11 @@ */ static int rbuVfsSync(sqlite3_file *pFile, int flags){ rbu_file *p = (rbu_file *)pFile; if( p->pRbu && p->pRbu->eStage==RBU_STAGE_CAPTURE ){ if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ - return SQLITE_NOTICE_RBU; + return SQLITE_INTERNAL; } return SQLITE_OK; } return p->pReal->pMethods->xSync(p->pReal, flags); } @@ -224683,14 +174545,14 @@ int rc; rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); /* If this is an RBU vacuum operation and this is the target database, ** pretend that it has at least one page. Otherwise, SQLite will not - ** check for the existance of a *-wal file. rbuVfsRead() contains + ** check for the existance of a *-wal file. rbuVfsRead() contains ** similar logic. */ - if( rc==SQLITE_OK && *pSize==0 - && p->pRbu && rbuIsVacuum(p->pRbu) + if( rc==SQLITE_OK && *pSize==0 + && p->pRbu && rbuIsVacuum(p->pRbu) && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ *pSize = 1024; } return rc; @@ -224703,14 +174565,14 @@ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc = SQLITE_OK; assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( eLock==SQLITE_LOCK_EXCLUSIVE + if( eLock==SQLITE_LOCK_EXCLUSIVE && (p->bNolock || (pRbu && pRbu->eStage!=RBU_STAGE_DONE)) ){ - /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this + /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this ** prevents it from checkpointing the database from sqlite3_close(). */ rc = SQLITE_BUSY; }else{ rc = p->pReal->pMethods->xLock(p->pReal, eLock); } @@ -224762,11 +174624,10 @@ rc = SQLITE_ERROR; pRbu->zErrmsg = sqlite3_mprintf("rbu/zipvfs setup error"); }else if( rc==SQLITE_NOTFOUND ){ pRbu->pTargetFd = p; p->pRbu = pRbu; - rbuMainlistAdd(p); if( p->pWalFd ) p->pWalFd->pRbu = pRbu; rc = SQLITE_OK; } } return rc; @@ -224817,28 +174678,29 @@ #ifdef SQLITE_AMALGAMATION assert( WAL_CKPT_LOCK==1 ); #endif assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( pRbu && ( - pRbu->eStage==RBU_STAGE_OAL - || pRbu->eStage==RBU_STAGE_MOVE - || pRbu->eStage==RBU_STAGE_DONE - )){ - /* Prevent SQLite from taking a shm-lock on the target file when it - ** is supplying heap memory to the upper layer in place of *-shm - ** segments. */ + if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){ + /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from + ** taking this lock also prevents any checkpoints from occurring. + ** todo: really, it's not clear why this might occur, as + ** wal_autocheckpoint ought to be turned off. */ if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY; }else{ int bCapture = 0; - if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ + if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE) + && pRbu && pRbu->eStage==RBU_STAGE_CAPTURE + && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0) + ){ bCapture = 1; } + if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){ rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); if( bCapture && rc==SQLITE_OK ){ - pRbu->mLock |= ((1<mLock |= (1 << ofst); } } } return rc; @@ -224846,42 +174708,38 @@ /* ** Obtain a pointer to a mapping of a single 32KiB page of the *-shm file. */ static int rbuVfsShmMap( - sqlite3_file *pFile, - int iRegion, - int szRegion, - int isWrite, + sqlite3_file *pFile, + int iRegion, + int szRegion, + int isWrite, void volatile **pp ){ rbu_file *p = (rbu_file*)pFile; int rc = SQLITE_OK; int eStage = (p->pRbu ? p->pRbu->eStage : 0); /* If not in RBU_STAGE_OAL, allow this call to pass through. Or, if this - ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space + ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space ** instead of a file on disk. */ assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( eStage==RBU_STAGE_OAL ){ - sqlite3_int64 nByte = (iRegion+1) * sizeof(char*); - char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte); - - /* This is an RBU connection that uses its own heap memory for the - ** pages of the *-shm file. Since no other process can have run - ** recovery, the connection must request *-shm pages in order - ** from start to finish. */ - assert( iRegion==p->nShm ); - if( apNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); - p->apShm = apNew; - p->nShm = iRegion+1; - } - - if( rc==SQLITE_OK ){ + if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ + if( iRegion<=p->nShm ){ + int nByte = (iRegion+1) * sizeof(char*); + char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte); + if( apNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); + p->apShm = apNew; + p->nShm = iRegion+1; + } + } + + if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ char *pNew = (char*)sqlite3_malloc64(szRegion); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(pNew, 0, szRegion); @@ -224926,10 +174784,51 @@ rbuUnlockShm(p); rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); } return rc; } + +/* +** Given that zWal points to a buffer containing a wal file name passed to +** either the xOpen() or xAccess() VFS method, return a pointer to the +** file-handle opened by the same database connection on the corresponding +** database file. +*/ +static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ + rbu_file *pDb; + sqlite3_mutex_enter(pRbuVfs->mutex); + for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} + sqlite3_mutex_leave(pRbuVfs->mutex); + return pDb; +} + +/* +** A main database named zName has just been opened. The following +** function returns a pointer to a buffer owned by SQLite that contains +** the name of the *-wal file this db connection will use. SQLite +** happens to pass a pointer to this buffer when using xAccess() +** or xOpen() to operate on the *-wal file. +*/ +static const char *rbuMainToWal(const char *zName, int flags){ + int n = (int)strlen(zName); + const char *z = &zName[n]; + if( flags & SQLITE_OPEN_URI ){ + int odd = 0; + while( 1 ){ + if( z[0]==0 ){ + odd = 1 - odd; + if( odd && z[1]==0 ) break; + } + z++; + } + z += 2; + }else{ + while( *z==0 ) z++; + } + z += (n + 8 + 1); + return z; +} /* ** Open an rbu file handle. */ static int rbuVfsOpen( @@ -224957,29 +174856,10 @@ rbuVfsShmLock, /* xShmLock */ rbuVfsShmBarrier, /* xShmBarrier */ rbuVfsShmUnmap, /* xShmUnmap */ 0, 0 /* xFetch, xUnfetch */ }; - static sqlite3_io_methods rbuvfs_io_methods1 = { - 1, /* iVersion */ - rbuVfsClose, /* xClose */ - rbuVfsRead, /* xRead */ - rbuVfsWrite, /* xWrite */ - rbuVfsTruncate, /* xTruncate */ - rbuVfsSync, /* xSync */ - rbuVfsFileSize, /* xFileSize */ - rbuVfsLock, /* xLock */ - rbuVfsUnlock, /* xUnlock */ - rbuVfsCheckReservedLock, /* xCheckReservedLock */ - rbuVfsFileControl, /* xFileControl */ - rbuVfsSectorSize, /* xSectorSize */ - rbuVfsDeviceCharacteristics, /* xDeviceCharacteristics */ - 0, 0, 0, 0, 0, 0 - }; - - - rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; rbu_file *pFd = (rbu_file *)pFile; int rc = SQLITE_OK; const char *zOpen = zName; @@ -224994,35 +174874,47 @@ /* A main database has just been opened. The following block sets ** (pFd->zWal) to point to a buffer owned by SQLite that contains ** the name of the *-wal file this db connection will use. SQLite ** happens to pass a pointer to this buffer when using xAccess() ** or xOpen() to operate on the *-wal file. */ - pFd->zWal = sqlite3_filename_wal(zName); + pFd->zWal = rbuMainToWal(zName, flags); } else if( flags & SQLITE_OPEN_WAL ){ - rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0); + rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); if( pDb ){ if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ - /* This call is to open a *-wal file. Intead, open the *-oal. */ - size_t nOpen; + /* This call is to open a *-wal file. Intead, open the *-oal. This + ** code ensures that the string passed to xOpen() is terminated by a + ** pair of '\0' bytes in case the VFS attempts to extract a URI + ** parameter from it. */ + const char *zBase = zName; + size_t nCopy; + char *zCopy; if( rbuIsVacuum(pDb->pRbu) ){ - zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main"); - zOpen = sqlite3_filename_wal(zOpen); + zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main"); + zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI); } - nOpen = strlen(zOpen); - ((char*)zOpen)[nOpen-3] = 'o'; + nCopy = strlen(zBase); + zCopy = sqlite3_malloc64(nCopy+2); + if( zCopy ){ + memcpy(zCopy, zBase, nCopy); + zCopy[nCopy-3] = 'o'; + zCopy[nCopy] = '\0'; + zCopy[nCopy+1] = '\0'; + zOpen = (const char*)(pFd->zDel = zCopy); + }else{ + rc = SQLITE_NOMEM; + } pFd->pRbu = pDb->pRbu; } pDb->pWalFd = pFd; } } - }else{ - pFd->pRbu = pRbuVfs->pRbu; } - if( oflags & SQLITE_OPEN_MAIN_DB - && sqlite3_uri_boolean(zName, "rbu_memory", 0) + if( oflags & SQLITE_OPEN_MAIN_DB + && sqlite3_uri_boolean(zName, "rbu_memory", 0) ){ assert( oflags & SQLITE_OPEN_MAIN_DB ); oflags = SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; zOpen = 0; @@ -225030,21 +174922,19 @@ if( rc==SQLITE_OK ){ rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, oflags, pOutFlags); } if( pFd->pReal->pMethods ){ - const sqlite3_io_methods *pMeth = pFd->pReal->pMethods; /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods ** pointer and, if the file is a main database file, link it into the ** mutex protected linked list of all such files. */ - if( pMeth->iVersion<2 || pMeth->xShmLock==0 ){ - pFile->pMethods = &rbuvfs_io_methods1; - }else{ - pFile->pMethods = &rbuvfs_io_methods; - } + pFile->pMethods = &rbuvfs_io_methods; if( flags & SQLITE_OPEN_MAIN_DB ){ - rbuMainlistAdd(pFd); + sqlite3_mutex_enter(pRbuVfs->mutex); + pFd->pMainNext = pRbuVfs->pMain; + pRbuVfs->pMain = pFd; + sqlite3_mutex_leave(pRbuVfs->mutex); } }else{ sqlite3_free(pFd->zDel); } @@ -225062,13 +174952,13 @@ /* ** Test for access permissions. Return true if the requested permission ** is available, or false otherwise. */ static int rbuVfsAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, + sqlite3_vfs *pVfs, + const char *zPath, + int flags, int *pResOut ){ rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; int rc; @@ -225080,27 +174970,24 @@ ** the following special handling is activated: ** ** a) if the *-wal file does exist, return SQLITE_CANTOPEN. This ** ensures that the RBU extension never tries to update a database ** in wal mode, even if the first page of the database file has - ** been damaged. + ** been damaged. ** ** b) if the *-wal file does not exist, claim that it does anyway, ** causing SQLite to call xOpen() to open it. This call will also ** be intercepted (see the rbuVfsOpen() function) and the *-oal ** file opened instead. */ if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ - rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1); - if( pDb && pDb->pRbu->eStage==RBU_STAGE_OAL ){ - assert( pDb->pRbu ); + rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath); + if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ if( *pResOut ){ rc = SQLITE_CANTOPEN; }else{ - sqlite3_int64 sz = 0; - rc = rbuVfsFileSize(&pDb->base, &sz); - *pResOut = (sz>0); + *pResOut = 1; } } } return rc; @@ -225110,13 +174997,13 @@ ** Populate buffer zOut with the full canonical pathname corresponding ** to the pathname in zPath. zOut is guaranteed to point to a buffer ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. */ static int rbuVfsFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, char *zOut ){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xFullPathname(pRealVfs, zPath, nOut, zOut); } @@ -225130,11 +175017,11 @@ return pRealVfs->xDlOpen(pRealVfs, zPath); } /* ** Populate the buffer zErrMsg (size nByte bytes) with a human readable -** utf-8 string describing the most recent error encountered associated +** utf-8 string describing the most recent error encountered associated ** with dynamic libraries. */ static void rbuVfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; pRealVfs->xDlError(pRealVfs, nByte, zErrMsg); @@ -225142,12 +175029,12 @@ /* ** Return a pointer to the symbol zSymbol in the dynamic library pHandle. */ static void (*rbuVfsDlSym( - sqlite3_vfs *pVfs, - void *pArg, + sqlite3_vfs *pVfs, + void *pArg, const char *zSym ))(void){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xDlSym(pRealVfs, pArg, zSym); } @@ -225160,20 +175047,20 @@ pRealVfs->xDlClose(pRealVfs, pHandle); } #endif /* SQLITE_OMIT_LOAD_EXTENSION */ /* -** Populate the buffer pointed to by zBufOut with nByte bytes of +** Populate the buffer pointed to by zBufOut with nByte bytes of ** random data. */ static int rbuVfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xRandomness(pRealVfs, nByte, zBufOut); } /* -** Sleep for nMicro microseconds. Return the number of microseconds +** Sleep for nMicro microseconds. Return the number of microseconds ** actually slept. */ static int rbuVfsSleep(sqlite3_vfs *pVfs, int nMicro){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xSleep(pRealVfs, nMicro); @@ -225189,13 +175076,10 @@ /* ** No-op. */ static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){ - UNUSED_PARAMETER(pVfs); - UNUSED_PARAMETER(a); - UNUSED_PARAMETER(b); return 0; } /* ** Deregister and destroy an RBU vfs created by an earlier call to @@ -225288,24 +175172,10 @@ } return rc; } -/* -** Configure the aggregate temp file size limit for this RBU handle. -*/ -SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu *pRbu, sqlite3_int64 n){ - if( n>=0 ){ - pRbu->szTempLimit = n; - } - return pRbu->szTempLimit; -} - -SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){ - return pRbu->szTemp; -} - /**************************************************************************/ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ @@ -225323,11 +175193,11 @@ ** ****************************************************************************** ** ** This file contains an implementation of the "dbstat" virtual table. ** -** The dbstat virtual table is used to extract low-level storage +** The dbstat virtual table is used to extract low-level formatting ** information from an SQLite database in order to implement the ** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script ** for an example implementation. ** ** Additional information is available on the "dbstat.html" page of the @@ -225336,37 +175206,28 @@ /* #include "sqliteInt.h" ** Requires access to internal data structures ** */ #if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) -/* -** The pager and btree modules arrange objects in memory so that there are -** always approximately 200 bytes of addressable memory following each page -** buffer. This way small buffer overreads caused by corrupt database pages -** do not cause undefined behaviour. This module pads each page buffer -** by the following number of bytes for the same purpose. -*/ -#define DBSTAT_PAGE_PADDING_BYTES 256 - /* ** Page paths: -** -** The value of the 'path' column describes the path taken from the -** root-node of the b-tree structure to each page. The value of the +** +** The value of the 'path' column describes the path taken from the +** root-node of the b-tree structure to each page. The value of the ** root-node path is '/'. ** ** The value of the path for the left-most child page of the root of ** a b-tree is '/000/'. (Btrees store content ordered from left to right ** so the pages to the left have smaller keys than the pages to the right.) ** The next to left-most child of the root page is -** '/001', and so on, each sibling page identified by a 3-digit hex +** '/001', and so on, each sibling page identified by a 3-digit hex ** value. The children of the 451st left-most sibling have paths such ** as '/1c2/000/, '/1c2/001/' etc. ** -** Overflow pages are specified by appending a '+' character and a +** Overflow pages are specified by appending a '+' character and a ** six-digit hexadecimal value to the path to the cell they are linked -** from. For example, the three overflow pages in a chain linked from +** from. For example, the three overflow pages in a chain linked from ** the left-most cell of the 450th child of the root page are identified ** by the paths: ** ** '/1c2/000+000000' // First page in overflow chain ** '/1c2/000+000001' // Second page in overflow chain @@ -225376,97 +175237,90 @@ ** the overflow pages associated with a cell will appear earlier in the ** sort-order than its child page: ** ** '/1c2/000/' // Left-most child of 451st child of root */ -static const char zDbstatSchema[] = - "CREATE TABLE x(" - " name TEXT," /* 0 Name of table or index */ - " path TEXT," /* 1 Path to page from root (NULL for agg) */ - " pageno INTEGER," /* 2 Page number (page count for aggregates) */ - " pagetype TEXT," /* 3 'internal', 'leaf', 'overflow', or NULL */ - " ncell INTEGER," /* 4 Cells on page (0 for overflow) */ - " payload INTEGER," /* 5 Bytes of payload on this page */ - " unused INTEGER," /* 6 Bytes of unused space on this page */ - " mx_payload INTEGER," /* 7 Largest payload size of all cells */ - " pgoffset INTEGER," /* 8 Offset of page in file (NULL for agg) */ - " pgsize INTEGER," /* 9 Size of the page (sum for aggregate) */ - " schema TEXT HIDDEN," /* 10 Database schema being analyzed */ - " aggregate BOOLEAN HIDDEN" /* 11 aggregate info for each table */ - ")" -; - -/* Forward reference to data structured used in this module */ +#define VTAB_SCHEMA \ + "CREATE TABLE xx( " \ + " name TEXT, /* Name of table or index */" \ + " path TEXT, /* Path to page from root */" \ + " pageno INTEGER, /* Page number */" \ + " pagetype TEXT, /* 'internal', 'leaf' or 'overflow' */" \ + " ncell INTEGER, /* Cells on page (0 for overflow) */" \ + " payload INTEGER, /* Bytes of payload on this page */" \ + " unused INTEGER, /* Bytes of unused space on this page */" \ + " mx_payload INTEGER, /* Largest payload size of all cells */" \ + " pgoffset INTEGER, /* Offset of page in file */" \ + " pgsize INTEGER, /* Size of the page */" \ + " schema TEXT HIDDEN /* Database schema being analyzed */" \ + ");" + + typedef struct StatTable StatTable; typedef struct StatCursor StatCursor; typedef struct StatPage StatPage; typedef struct StatCell StatCell; -/* Size information for a single cell within a btree page */ struct StatCell { int nLocal; /* Bytes of local payload */ u32 iChildPg; /* Child node (or 0 if this is a leaf) */ int nOvfl; /* Entries in aOvfl[] */ u32 *aOvfl; /* Array of overflow page numbers */ int nLastOvfl; /* Bytes of payload on final overflow page */ int iOvfl; /* Iterates through aOvfl[] */ }; -/* Size information for a single btree page */ struct StatPage { - u32 iPgno; /* Page number */ - u8 *aPg; /* Page buffer from sqlite3_malloc() */ - int iCell; /* Current cell */ + u32 iPgno; + DbPage *pPg; + int iCell; + char *zPath; /* Path to this page */ /* Variables populated by statDecodePage(): */ u8 flags; /* Copy of flags byte */ int nCell; /* Number of cells on page */ int nUnused; /* Number of unused bytes on page */ StatCell *aCell; /* Array of parsed cells */ u32 iRightChildPg; /* Right-child page number (or 0) */ - int nMxPayload; /* Largest payload of any cell on the page */ + int nMxPayload; /* Largest payload of any cell on this page */ }; -/* The cursor for scanning the dbstat virtual table */ struct StatCursor { - sqlite3_vtab_cursor base; /* base class. MUST BE FIRST! */ + sqlite3_vtab_cursor base; sqlite3_stmt *pStmt; /* Iterates through set of root pages */ - u8 isEof; /* After pStmt has returned SQLITE_DONE */ - u8 isAgg; /* Aggregate results for each table */ + int isEof; /* After pStmt has returned SQLITE_DONE */ int iDb; /* Schema used for this query */ - StatPage aPage[32]; /* Pages in path to current page */ + StatPage aPage[32]; int iPage; /* Current entry in aPage[] */ /* Values to return. */ - u32 iPageno; /* Value of 'pageno' column */ char *zName; /* Value of 'name' column */ char *zPath; /* Value of 'path' column */ + u32 iPageno; /* Value of 'pageno' column */ char *zPagetype; /* Value of 'pagetype' column */ - int nPage; /* Number of pages in current btree */ int nCell; /* Value of 'ncell' column */ + int nPayload; /* Value of 'payload' column */ + int nUnused; /* Value of 'unused' column */ int nMxPayload; /* Value of 'mx_payload' column */ - i64 nUnused; /* Value of 'unused' column */ - i64 nPayload; /* Value of 'payload' column */ i64 iOffset; /* Value of 'pgOffset' column */ - i64 szPage; /* Value of 'pgSize' column */ + int szPage; /* Value of 'pgSize' column */ }; -/* An instance of the DBSTAT virtual table */ struct StatTable { - sqlite3_vtab base; /* base class. MUST BE FIRST! */ - sqlite3 *db; /* Database connection that owns this vtab */ + sqlite3_vtab base; + sqlite3 *db; int iDb; /* Index of database to analyze */ }; #ifndef get2byte # define get2byte(x) ((x)[0]<<8 | (x)[1]) #endif /* -** Connect to or create a new DBSTAT virtual table. +** Connect to or create a statvfs virtual table. */ static int statConnect( sqlite3 *db, void *pAux, int argc, const char *const*argv, @@ -225474,11 +175328,10 @@ char **pzErr ){ StatTable *pTab = 0; int rc = SQLITE_OK; int iDb; - (void)pAux; if( argc>=4 ){ Token nm; sqlite3TokenInit(&nm, (char*)argv[3]); iDb = sqlite3FindDb(db, &nm); @@ -225487,12 +175340,11 @@ return SQLITE_ERROR; } }else{ iDb = 0; } - sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); - rc = sqlite3_declare_vtab(db, zDbstatSchema); + rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); if( rc==SQLITE_OK ){ pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); if( pTab==0 ) rc = SQLITE_NOMEM_BKPT; } @@ -225506,78 +175358,48 @@ *ppVtab = (sqlite3_vtab*)pTab; return rc; } /* -** Disconnect from or destroy the DBSTAT virtual table. +** Disconnect from or destroy a statvfs virtual table. */ static int statDisconnect(sqlite3_vtab *pVtab){ sqlite3_free(pVtab); return SQLITE_OK; } /* -** Compute the best query strategy and return the result in idxNum. +** There is no "best-index". This virtual table always does a linear +** scan. However, a schema=? constraint should cause this table to +** operate on a different database schema, so check for it. ** -** idxNum-Bit Meaning -** ---------- ---------------------------------------------- -** 0x01 There is a schema=? term in the WHERE clause -** 0x02 There is a name=? term in the WHERE clause -** 0x04 There is an aggregate=? term in the WHERE clause -** 0x08 Output should be ordered by name and path +** idxNum is normally 0, but will be 1 if a schema=? constraint exists. */ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int i; - int iSchema = -1; - int iName = -1; - int iAgg = -1; - (void)tab; + + pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ /* Look for a valid schema=? constraint. If found, change the idxNum to ** 1 and request the value of that constraint be sent to xFilter. And ** lower the cost estimate to encourage the constrained version to be ** used. */ for(i=0; inConstraint; i++){ + if( pIdxInfo->aConstraint[i].usable==0 ) continue; if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pIdxInfo->aConstraint[i].usable==0 ){ - /* Force DBSTAT table should always be the right-most table in a join */ - return SQLITE_CONSTRAINT; - } - switch( pIdxInfo->aConstraint[i].iColumn ){ - case 0: { /* name */ - iName = i; - break; - } - case 10: { /* schema */ - iSchema = i; - break; - } - case 11: { /* aggregate */ - iAgg = i; - break; - } - } - } - i = 0; - if( iSchema>=0 ){ - pIdxInfo->aConstraintUsage[iSchema].argvIndex = ++i; - pIdxInfo->aConstraintUsage[iSchema].omit = 1; - pIdxInfo->idxNum |= 0x01; - } - if( iName>=0 ){ - pIdxInfo->aConstraintUsage[iName].argvIndex = ++i; - pIdxInfo->idxNum |= 0x02; - } - if( iAgg>=0 ){ - pIdxInfo->aConstraintUsage[iAgg].argvIndex = ++i; - pIdxInfo->idxNum |= 0x04; - } - pIdxInfo->estimatedCost = 1.0; - - /* Records are always returned in ascending order of (name, path). - ** If this will satisfy the client, set the orderByConsumed flag so that + if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; + pIdxInfo->idxNum = 1; + pIdxInfo->estimatedCost = 1.0; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + break; + } + + + /* Records are always returned in ascending order of (name, path). + ** If this will satisfy the client, set the orderByConsumed flag so that ** SQLite does not do an external sort. */ if( ( pIdxInfo->nOrderBy==1 && pIdxInfo->aOrderBy[0].iColumn==0 && pIdxInfo->aOrderBy[0].desc==0 @@ -225588,19 +175410,17 @@ && pIdxInfo->aOrderBy[1].iColumn==1 && pIdxInfo->aOrderBy[1].desc==0 ) ){ pIdxInfo->orderByConsumed = 1; - pIdxInfo->idxNum |= 0x08; } - pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_HEX; return SQLITE_OK; } /* -** Open a new DBSTAT cursor. +** Open a new statvfs cursor. */ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ StatTable *pTab = (StatTable *)pVTab; StatCursor *pCsr; @@ -225615,83 +175435,56 @@ *ppCursor = (sqlite3_vtab_cursor *)pCsr; return SQLITE_OK; } -static void statClearCells(StatPage *p){ +static void statClearPage(StatPage *p){ int i; if( p->aCell ){ for(i=0; inCell; i++){ sqlite3_free(p->aCell[i].aOvfl); } sqlite3_free(p->aCell); } - p->nCell = 0; - p->aCell = 0; -} - -static void statClearPage(StatPage *p){ - u8 *aPg = p->aPg; - statClearCells(p); + sqlite3PagerUnref(p->pPg); sqlite3_free(p->zPath); memset(p, 0, sizeof(StatPage)); - p->aPg = aPg; } static void statResetCsr(StatCursor *pCsr){ int i; - /* In some circumstances, specifically if an OOM has occurred, the call - ** to sqlite3_reset() may cause the pager to be reset (emptied). It is - ** important that statClearPage() is called to free any page refs before - ** this happens. dbsqlfuzz 9ed3e4e3816219d3509d711636c38542bf3f40b1. */ + sqlite3_reset(pCsr->pStmt); for(i=0; iaPage); i++){ statClearPage(&pCsr->aPage[i]); - sqlite3_free(pCsr->aPage[i].aPg); - pCsr->aPage[i].aPg = 0; } - sqlite3_reset(pCsr->pStmt); pCsr->iPage = 0; sqlite3_free(pCsr->zPath); pCsr->zPath = 0; pCsr->isEof = 0; } -/* Resize the space-used counters inside of the cursor */ -static void statResetCounts(StatCursor *pCsr){ - pCsr->nCell = 0; - pCsr->nMxPayload = 0; - pCsr->nUnused = 0; - pCsr->nPayload = 0; - pCsr->szPage = 0; - pCsr->nPage = 0; -} - /* -** Close a DBSTAT cursor. +** Close a statvfs cursor. */ static int statClose(sqlite3_vtab_cursor *pCursor){ StatCursor *pCsr = (StatCursor *)pCursor; statResetCsr(pCsr); sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr); return SQLITE_OK; } -/* -** For a single cell on a btree page, compute the number of bytes of -** content (payload) stored on that page. That is to say, compute the -** number of bytes of content not found on overflow pages. -*/ -static int getLocalPayload( +static void getLocalPayload( int nUsable, /* Usable bytes per page */ u8 flags, /* Page flags */ - int nTotal /* Total record (payload) size */ + int nTotal, /* Total record (payload) size */ + int *pnLocal /* OUT: Bytes stored locally */ ){ int nLocal; int nMinLocal; int nMaxLocal; - + if( flags==0x0D ){ /* Table leaf node */ nMinLocal = (nUsable - 12) * 32 / 255 - 23; nMaxLocal = nUsable - 35; }else{ /* Index interior and leaf nodes */ nMinLocal = (nUsable - 12) * 32 / 255 - 23; @@ -225698,54 +175491,40 @@ nMaxLocal = (nUsable - 12) * 64 / 255 - 23; } nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4); if( nLocal>nMaxLocal ) nLocal = nMinLocal; - return nLocal; + *pnLocal = nLocal; } -/* Populate the StatPage object with information about the all -** cells found on the page currently under analysis. -*/ static int statDecodePage(Btree *pBt, StatPage *p){ int nUnused; int iOff; int nHdr; int isLeaf; int szPage; - u8 *aData = p->aPg; + u8 *aData = sqlite3PagerGetData(p->pPg); u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; p->flags = aHdr[0]; - if( p->flags==0x0A || p->flags==0x0D ){ - isLeaf = 1; - nHdr = 8; - }else if( p->flags==0x05 || p->flags==0x02 ){ - isLeaf = 0; - nHdr = 12; - }else{ - goto statPageIsCorrupt; - } - if( p->iPgno==1 ) nHdr += 100; p->nCell = get2byte(&aHdr[3]); p->nMxPayload = 0; - szPage = sqlite3BtreeGetPageSize(pBt); + + isLeaf = (p->flags==0x0A || p->flags==0x0D); + nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; nUnused += (int)aHdr[7]; iOff = get2byte(&aHdr[1]); while( iOff ){ - int iNext; - if( iOff>=szPage ) goto statPageIsCorrupt; nUnused += get2byte(&aData[iOff+2]); - iNext = get2byte(&aData[iOff]); - if( iNext0 ) goto statPageIsCorrupt; - iOff = iNext; + iOff = get2byte(&aData[iOff]); } p->nUnused = nUnused; p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); + szPage = sqlite3BtreeGetPageSize(pBt); if( p->nCell ){ int i; /* Used to iterate through cells */ int nUsable; /* Usable bytes per page */ @@ -225758,11 +175537,10 @@ for(i=0; inCell; i++){ StatCell *pCell = &p->aCell[i]; iOff = get2byte(&aData[nHdr+i*2]); - if( iOff=szPage ) goto statPageIsCorrupt; if( !isLeaf ){ pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); iOff += 4; } if( p->flags==0x05 ){ @@ -225774,21 +175552,18 @@ if( p->flags==0x0D ){ u64 dummy; iOff += sqlite3GetVarint(&aData[iOff], &dummy); } if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; - nLocal = getLocalPayload(nUsable, p->flags, nPayload); - if( nLocal<0 ) goto statPageIsCorrupt; + getLocalPayload(nUsable, p->flags, nPayload, &nLocal); pCell->nLocal = nLocal; + assert( nLocal>=0 ); assert( nPayload>=(u32)nLocal ); assert( nLocal<=(nUsable-35) ); if( nPayload>(u32)nLocal ){ int j; int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); - if( iOff+nLocal+4>nUsable || nPayload>0x7fffffff ){ - goto statPageIsCorrupt; - } pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT; pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); @@ -225798,25 +175573,20 @@ DbPage *pPg = 0; rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg, 0); if( rc!=SQLITE_OK ){ assert( pPg==0 ); return rc; - } + } pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg)); sqlite3PagerUnref(pPg); } } } } } return SQLITE_OK; - -statPageIsCorrupt: - p->flags = 0; - statClearCells(p); - return SQLITE_OK; } /* ** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on ** the current value of pCsr->iPageno. @@ -225826,61 +175596,27 @@ Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; Pager *pPager = sqlite3BtreePager(pBt); sqlite3_file *fd; sqlite3_int64 x[2]; - /* If connected to a ZIPVFS backend, find the page size and - ** offset from ZIPVFS. + /* The default page size and offset */ + pCsr->szPage = sqlite3BtreeGetPageSize(pBt); + pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1); + + /* If connected to a ZIPVFS backend, override the page size and + ** offset with actual values obtained from ZIPVFS. */ fd = sqlite3PagerFile(pPager); x[0] = pCsr->iPageno; - if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ + if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ pCsr->iOffset = x[0]; - pCsr->szPage += x[1]; - }else{ - /* Not ZIPVFS: The default page size and offset */ - pCsr->szPage += sqlite3BtreeGetPageSize(pBt); - pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1); - } -} - -/* -** Load a copy of the page data for page iPg into the buffer belonging -** to page object pPg. Allocate the buffer if necessary. Return SQLITE_OK -** if successful, or an SQLite error code otherwise. -*/ -static int statGetPage( - Btree *pBt, /* Load page from this b-tree */ - u32 iPg, /* Page number to load */ - StatPage *pPg /* Load page into this object */ -){ - int pgsz = sqlite3BtreeGetPageSize(pBt); - DbPage *pDbPage = 0; - int rc; - - if( pPg->aPg==0 ){ - pPg->aPg = (u8*)sqlite3_malloc(pgsz + DBSTAT_PAGE_PADDING_BYTES); - if( pPg->aPg==0 ){ - return SQLITE_NOMEM_BKPT; - } - memset(&pPg->aPg[pgsz], 0, DBSTAT_PAGE_PADDING_BYTES); - } - - rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPg, &pDbPage, 0); - if( rc==SQLITE_OK ){ - const u8 *a = sqlite3PagerGetData(pDbPage); - memcpy(pPg->aPg, a, pgsz); - sqlite3PagerUnref(pDbPage); - } - - return rc; -} - -/* -** Move a DBSTAT cursor to the next entry. Normally, the next -** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0), -** the next entry is the next btree. + pCsr->szPage = (int)x[1]; + } +} + +/* +** Move a statvfs cursor to the next entry in the file. */ static int statNext(sqlite3_vtab_cursor *pCursor){ int rc; int nPayload; char *z; @@ -225891,101 +175627,85 @@ sqlite3_free(pCsr->zPath); pCsr->zPath = 0; statNextRestart: - if( pCsr->iPage<0 ){ - /* Start measuring space on the next btree */ - statResetCounts(pCsr); + if( pCsr->aPage[0].pPg==0 ){ rc = sqlite3_step(pCsr->pStmt); if( rc==SQLITE_ROW ){ int nPage; u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1); sqlite3PagerPagecount(pPager, &nPage); if( nPage==0 ){ pCsr->isEof = 1; return sqlite3_reset(pCsr->pStmt); } - rc = statGetPage(pBt, iRoot, &pCsr->aPage[0]); + rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0); pCsr->aPage[0].iPgno = iRoot; pCsr->aPage[0].iCell = 0; - if( !pCsr->isAgg ){ - pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); - if( z==0 ) rc = SQLITE_NOMEM_BKPT; - } + pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); pCsr->iPage = 0; - pCsr->nPage = 1; + if( z==0 ) rc = SQLITE_NOMEM_BKPT; }else{ pCsr->isEof = 1; return sqlite3_reset(pCsr->pStmt); } }else{ - /* Continue analyzing the btree previously started */ + + /* Page p itself has already been visited. */ StatPage *p = &pCsr->aPage[pCsr->iPage]; - if( !pCsr->isAgg ) statResetCounts(pCsr); + while( p->iCellnCell ){ StatCell *pCell = &p->aCell[p->iCell]; - while( pCell->iOvflnOvfl ){ - int nUsable, iOvfl; + if( pCell->iOvflnOvfl ){ + int nUsable; sqlite3BtreeEnter(pBt); - nUsable = sqlite3BtreeGetPageSize(pBt) - + nUsable = sqlite3BtreeGetPageSize(pBt) - sqlite3BtreeGetReserveNoMutex(pBt); sqlite3BtreeLeave(pBt); - pCsr->nPage++; - statSizeAndOffset(pCsr); + pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); + pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; + pCsr->zPagetype = "overflow"; + pCsr->nCell = 0; + pCsr->nMxPayload = 0; + pCsr->zPath = z = sqlite3_mprintf( + "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl + ); if( pCell->iOvflnOvfl-1 ){ - pCsr->nPayload += nUsable - 4; + pCsr->nUnused = 0; + pCsr->nPayload = nUsable - 4; }else{ - pCsr->nPayload += pCell->nLastOvfl; - pCsr->nUnused += nUsable - 4 - pCell->nLastOvfl; + pCsr->nPayload = pCell->nLastOvfl; + pCsr->nUnused = nUsable - 4 - pCsr->nPayload; } - iOvfl = pCell->iOvfl; pCell->iOvfl++; - if( !pCsr->isAgg ){ - pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); - pCsr->iPageno = pCell->aOvfl[iOvfl]; - pCsr->zPagetype = "overflow"; - pCsr->zPath = z = sqlite3_mprintf( - "%s%.3x+%.6x", p->zPath, p->iCell, iOvfl - ); - return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK; - } + statSizeAndOffset(pCsr); + return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK; } if( p->iRightChildPg ) break; p->iCell++; } if( !p->iRightChildPg || p->iCell>p->nCell ){ statClearPage(p); + if( pCsr->iPage==0 ) return statNext(pCursor); pCsr->iPage--; - if( pCsr->isAgg && pCsr->iPage<0 ){ - /* label-statNext-done: When computing aggregate space usage over - ** an entire btree, this is the exit point from this function */ - return SQLITE_OK; - } goto statNextRestart; /* Tail recursion */ } pCsr->iPage++; - if( pCsr->iPage>=ArraySize(pCsr->aPage) ){ - statResetCsr(pCsr); - return SQLITE_CORRUPT_BKPT; - } assert( p==&pCsr->aPage[pCsr->iPage-1] ); if( p->iCell==p->nCell ){ p[1].iPgno = p->iRightChildPg; }else{ p[1].iPgno = p->aCell[p->iCell].iChildPg; } - rc = statGetPage(pBt, p[1].iPgno, &p[1]); - pCsr->nPage++; + rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0); p[1].iCell = 0; - if( !pCsr->isAgg ){ - p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); - if( z==0 ) rc = SQLITE_NOMEM_BKPT; - } + p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); p->iCell++; + if( z==0 ) rc = SQLITE_NOMEM_BKPT; } /* Populate the StatCursor fields with the values to be returned ** by the xColumn() and xRowid() methods. @@ -226011,27 +175731,20 @@ break; default: pCsr->zPagetype = "corrupted"; break; } - pCsr->nCell += p->nCell; - pCsr->nUnused += p->nUnused; - if( p->nMxPayload>pCsr->nMxPayload ) pCsr->nMxPayload = p->nMxPayload; - if( !pCsr->isAgg ){ - pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath); - if( z==0 ) rc = SQLITE_NOMEM_BKPT; - } + pCsr->nCell = p->nCell; + pCsr->nUnused = p->nUnused; + pCsr->nMxPayload = p->nMxPayload; + pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath); + if( z==0 ) rc = SQLITE_NOMEM_BKPT; nPayload = 0; for(i=0; inCell; i++){ nPayload += p->aCell[i].nLocal; } - pCsr->nPayload += nPayload; - - /* If computing aggregate space usage by btree, continue with the - ** next page. The loop will exit via the return at label-statNext-done - */ - if( pCsr->isAgg ) goto statNextRestart; + pCsr->nPayload = nPayload; } } return rc; } @@ -226039,140 +175752,98 @@ static int statEof(sqlite3_vtab_cursor *pCursor){ StatCursor *pCsr = (StatCursor *)pCursor; return pCsr->isEof; } -/* Initialize a cursor according to the query plan idxNum using the -** arguments in argv[0]. See statBestIndex() for a description of the -** meaning of the bits in idxNum. -*/ static int statFilter( - sqlite3_vtab_cursor *pCursor, + sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ StatCursor *pCsr = (StatCursor *)pCursor; StatTable *pTab = (StatTable*)(pCursor->pVtab); - sqlite3_str *pSql; /* Query of btrees to analyze */ - char *zSql; /* String value of pSql */ - int iArg = 0; /* Count of argv[] parameters used so far */ - int rc = SQLITE_OK; /* Result of this operation */ - const char *zName = 0; /* Only provide analysis of this table */ - (void)argc; - (void)idxStr; - - statResetCsr(pCsr); - sqlite3_finalize(pCsr->pStmt); - pCsr->pStmt = 0; - if( idxNum & 0x01 ){ - /* schema=? constraint is present. Get its value */ - const char *zDbase = (const char*)sqlite3_value_text(argv[iArg++]); + char *zSql; + int rc = SQLITE_OK; + char *zMaster; + + if( idxNum==1 ){ + const char *zDbase = (const char*)sqlite3_value_text(argv[0]); pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase); if( pCsr->iDb<0 ){ - pCsr->iDb = 0; - pCsr->isEof = 1; - return SQLITE_OK; + sqlite3_free(pCursor->pVtab->zErrMsg); + pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase); + return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM_BKPT; } }else{ pCsr->iDb = pTab->iDb; } - if( idxNum & 0x02 ){ - /* name=? constraint is present */ - zName = (const char*)sqlite3_value_text(argv[iArg++]); - } - if( idxNum & 0x04 ){ - /* aggregate=? constraint is present */ - pCsr->isAgg = sqlite3_value_double(argv[iArg++])!=0.0; - }else{ - pCsr->isAgg = 0; - } - pSql = sqlite3_str_new(pTab->db); - sqlite3_str_appendf(pSql, - "SELECT * FROM (" - "SELECT 'sqlite_schema' AS name,1 AS rootpage,'table' AS type" - " UNION ALL " - "SELECT name,rootpage,type" - " FROM \"%w\".sqlite_schema WHERE rootpage!=0)", - pTab->db->aDb[pCsr->iDb].zDbSName); - if( zName ){ - sqlite3_str_appendf(pSql, "WHERE name=%Q", zName); - } - if( idxNum & 0x08 ){ - sqlite3_str_appendf(pSql, " ORDER BY name"); - } - zSql = sqlite3_str_finish(pSql); + statResetCsr(pCsr); + sqlite3_finalize(pCsr->pStmt); + pCsr->pStmt = 0; + zMaster = pCsr->iDb==1 ? "sqlite_temp_master" : "sqlite_master"; + zSql = sqlite3_mprintf( + "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" + " UNION ALL " + "SELECT name, rootpage, type" + " FROM \"%w\".%s WHERE rootpage!=0" + " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster); if( zSql==0 ){ return SQLITE_NOMEM_BKPT; }else{ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0); sqlite3_free(zSql); } if( rc==SQLITE_OK ){ - pCsr->iPage = -1; rc = statNext(pCursor); } return rc; } static int statColumn( - sqlite3_vtab_cursor *pCursor, - sqlite3_context *ctx, + sqlite3_vtab_cursor *pCursor, + sqlite3_context *ctx, int i ){ StatCursor *pCsr = (StatCursor *)pCursor; switch( i ){ case 0: /* name */ sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT); break; case 1: /* path */ - if( !pCsr->isAgg ){ - sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); - } + sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); break; case 2: /* pageno */ - if( pCsr->isAgg ){ - sqlite3_result_int64(ctx, pCsr->nPage); - }else{ - sqlite3_result_int64(ctx, pCsr->iPageno); - } + sqlite3_result_int64(ctx, pCsr->iPageno); break; case 3: /* pagetype */ - if( !pCsr->isAgg ){ - sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC); - } + sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC); break; case 4: /* ncell */ - sqlite3_result_int64(ctx, pCsr->nCell); + sqlite3_result_int(ctx, pCsr->nCell); break; case 5: /* payload */ - sqlite3_result_int64(ctx, pCsr->nPayload); + sqlite3_result_int(ctx, pCsr->nPayload); break; case 6: /* unused */ - sqlite3_result_int64(ctx, pCsr->nUnused); + sqlite3_result_int(ctx, pCsr->nUnused); break; case 7: /* mx_payload */ - sqlite3_result_int64(ctx, pCsr->nMxPayload); + sqlite3_result_int(ctx, pCsr->nMxPayload); break; case 8: /* pgoffset */ - if( !pCsr->isAgg ){ - sqlite3_result_int64(ctx, pCsr->iOffset); - } + sqlite3_result_int64(ctx, pCsr->iOffset); break; case 9: /* pgsize */ - sqlite3_result_int64(ctx, pCsr->szPage); + sqlite3_result_int(ctx, pCsr->szPage); break; - case 10: { /* schema */ + default: { /* schema */ sqlite3 *db = sqlite3_context_db_handle(ctx); int iDb = pCsr->iDb; sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC); break; } - default: { /* aggregate */ - sqlite3_result_int(ctx, pCsr->isAgg); - break; - } } return SQLITE_OK; } static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ @@ -226207,523 +175878,18 @@ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } #elif defined(SQLITE_ENABLE_DBSTAT_VTAB) SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ /************** End of dbstat.c **********************************************/ -/************** Begin file dbpage.c ******************************************/ -/* -** 2017-10-11 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains an implementation of the "sqlite_dbpage" virtual table. -** -** The sqlite_dbpage virtual table is used to read or write whole raw -** pages of the database file. The pager interface is used so that -** uncommitted changes and changes recorded in the WAL file are correctly -** retrieved. -** -** Usage example: -** -** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123; -** -** This is an eponymous virtual table so it does not need to be created before -** use. The optional argument to the sqlite_dbpage() table name is the -** schema for the database file that is to be read. The default schema is -** "main". -** -** The data field of sqlite_dbpage table can be updated. The new -** value must be a BLOB which is the correct page size, otherwise the -** update fails. INSERT operations also work, and operate as if they -** where REPLACE. The size of the database can be extended by INSERT-ing -** new pages on the end. -** -** Rows may not be deleted. However, doing an INSERT to page number N -** with NULL page data causes the N-th page and all subsequent pages to be -** deleted and the database to be truncated. -*/ - -/* #include "sqliteInt.h" ** Requires access to internal data structures ** */ -#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ - && !defined(SQLITE_OMIT_VIRTUALTABLE) - -typedef struct DbpageTable DbpageTable; -typedef struct DbpageCursor DbpageCursor; - -struct DbpageCursor { - sqlite3_vtab_cursor base; /* Base class. Must be first */ - int pgno; /* Current page number */ - int mxPgno; /* Last page to visit on this scan */ - Pager *pPager; /* Pager being read/written */ - DbPage *pPage1; /* Page 1 of the database */ - int iDb; /* Index of database to analyze */ - int szPage; /* Size of each page in bytes */ -}; - -struct DbpageTable { - sqlite3_vtab base; /* Base class. Must be first */ - sqlite3 *db; /* The database */ - int iDbTrunc; /* Database to truncate */ - Pgno pgnoTrunc; /* Size to truncate to */ -}; - -/* Columns */ -#define DBPAGE_COLUMN_PGNO 0 -#define DBPAGE_COLUMN_DATA 1 -#define DBPAGE_COLUMN_SCHEMA 2 - - -/* -** Connect to or create a dbpagevfs virtual table. -*/ -static int dbpageConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - DbpageTable *pTab = 0; - int rc = SQLITE_OK; - (void)pAux; - (void)argc; - (void)argv; - (void)pzErr; - - sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); - sqlite3_vtab_config(db, SQLITE_VTAB_USES_ALL_SCHEMAS); - rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)"); - if( rc==SQLITE_OK ){ - pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable)); - if( pTab==0 ) rc = SQLITE_NOMEM_BKPT; - } - - assert( rc==SQLITE_OK || pTab==0 ); - if( rc==SQLITE_OK ){ - memset(pTab, 0, sizeof(DbpageTable)); - pTab->db = db; - } - - *ppVtab = (sqlite3_vtab*)pTab; - return rc; -} - -/* -** Disconnect from or destroy a dbpagevfs virtual table. -*/ -static int dbpageDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; -} - -/* -** idxNum: -** -** 0 schema=main, full table scan -** 1 schema=main, pgno=?1 -** 2 schema=?1, full table scan -** 3 schema=?1, pgno=?2 -*/ -static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int i; - int iPlan = 0; - (void)tab; - - /* If there is a schema= constraint, it must be honored. Report a - ** ridiculously large estimated cost if the schema= constraint is - ** unavailable - */ - for(i=0; inConstraint; i++){ - struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; - if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; - if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( !p->usable ){ - /* No solution. */ - return SQLITE_CONSTRAINT; - } - iPlan = 2; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - pIdxInfo->aConstraintUsage[i].omit = 1; - break; - } - - /* If we reach this point, it means that either there is no schema= - ** constraint (in which case we use the "main" schema) or else the - ** schema constraint was accepted. Lower the estimated cost accordingly - */ - pIdxInfo->estimatedCost = 1.0e6; - - /* Check for constraints against pgno */ - for(i=0; inConstraint; i++){ - struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; - if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - pIdxInfo->estimatedRows = 1; - pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; - pIdxInfo->estimatedCost = 1.0; - pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1; - pIdxInfo->aConstraintUsage[i].omit = 1; - iPlan |= 1; - break; - } - } - pIdxInfo->idxNum = iPlan; - - if( pIdxInfo->nOrderBy>=1 - && pIdxInfo->aOrderBy[0].iColumn<=0 - && pIdxInfo->aOrderBy[0].desc==0 - ){ - pIdxInfo->orderByConsumed = 1; - } - return SQLITE_OK; -} - -/* -** Open a new dbpagevfs cursor. -*/ -static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - DbpageCursor *pCsr; - - pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM_BKPT; - }else{ - memset(pCsr, 0, sizeof(DbpageCursor)); - pCsr->base.pVtab = pVTab; - pCsr->pgno = -1; - } - - *ppCursor = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Close a dbpagevfs cursor. -*/ -static int dbpageClose(sqlite3_vtab_cursor *pCursor){ - DbpageCursor *pCsr = (DbpageCursor *)pCursor; - if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Move a dbpagevfs cursor to the next entry in the file. -*/ -static int dbpageNext(sqlite3_vtab_cursor *pCursor){ - int rc = SQLITE_OK; - DbpageCursor *pCsr = (DbpageCursor *)pCursor; - pCsr->pgno++; - return rc; -} - -static int dbpageEof(sqlite3_vtab_cursor *pCursor){ - DbpageCursor *pCsr = (DbpageCursor *)pCursor; - return pCsr->pgno > pCsr->mxPgno; -} - -/* -** idxNum: -** -** 0 schema=main, full table scan -** 1 schema=main, pgno=?1 -** 2 schema=?1, full table scan -** 3 schema=?1, pgno=?2 -** -** idxStr is not used -*/ -static int dbpageFilter( - sqlite3_vtab_cursor *pCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - DbpageCursor *pCsr = (DbpageCursor *)pCursor; - DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; - int rc; - sqlite3 *db = pTab->db; - Btree *pBt; - - (void)idxStr; - - /* Default setting is no rows of result */ - pCsr->pgno = 1; - pCsr->mxPgno = 0; - - if( idxNum & 2 ){ - const char *zSchema; - assert( argc>=1 ); - zSchema = (const char*)sqlite3_value_text(argv[0]); - pCsr->iDb = sqlite3FindDbName(db, zSchema); - if( pCsr->iDb<0 ) return SQLITE_OK; - }else{ - pCsr->iDb = 0; - } - pBt = db->aDb[pCsr->iDb].pBt; - if( NEVER(pBt==0) ) return SQLITE_OK; - pCsr->pPager = sqlite3BtreePager(pBt); - pCsr->szPage = sqlite3BtreeGetPageSize(pBt); - pCsr->mxPgno = sqlite3BtreeLastPage(pBt); - if( idxNum & 1 ){ - assert( argc>(idxNum>>1) ); - pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]); - if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){ - pCsr->pgno = 1; - pCsr->mxPgno = 0; - }else{ - pCsr->mxPgno = pCsr->pgno; - } - }else{ - assert( pCsr->pgno==1 ); - } - if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); - rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0); - return rc; -} - -static int dbpageColumn( - sqlite3_vtab_cursor *pCursor, - sqlite3_context *ctx, - int i -){ - DbpageCursor *pCsr = (DbpageCursor *)pCursor; - int rc = SQLITE_OK; - switch( i ){ - case 0: { /* pgno */ - sqlite3_result_int(ctx, pCsr->pgno); - break; - } - case 1: { /* data */ - DbPage *pDbPage = 0; - if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){ - /* The pending byte page. Assume it is zeroed out. Attempting to - ** request this page from the page is an SQLITE_CORRUPT error. */ - sqlite3_result_zeroblob(ctx, pCsr->szPage); - }else{ - rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); - if( rc==SQLITE_OK ){ - sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage, - SQLITE_TRANSIENT); - } - sqlite3PagerUnref(pDbPage); - } - break; - } - default: { /* schema */ - sqlite3 *db = sqlite3_context_db_handle(ctx); - sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC); - break; - } - } - return rc; -} - -static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - DbpageCursor *pCsr = (DbpageCursor *)pCursor; - *pRowid = pCsr->pgno; - return SQLITE_OK; -} - -/* -** Open write transactions. Since we do not know in advance which database -** files will be written by the sqlite_dbpage virtual table, start a write -** transaction on them all. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. -*/ -static int dbpageBeginTrans(DbpageTable *pTab){ - sqlite3 *db = pTab->db; - int rc = SQLITE_OK; - int i; - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0); - } - return rc; -} - -static int dbpageUpdate( - sqlite3_vtab *pVtab, - int argc, - sqlite3_value **argv, - sqlite_int64 *pRowid -){ - DbpageTable *pTab = (DbpageTable *)pVtab; - Pgno pgno; - DbPage *pDbPage = 0; - int rc = SQLITE_OK; - char *zErr = 0; - int iDb; - Btree *pBt; - Pager *pPager; - int szPage; - int isInsert; - - (void)pRowid; - if( pTab->db->flags & SQLITE_Defensive ){ - zErr = "read-only"; - goto update_fail; - } - if( argc==1 ){ - zErr = "cannot delete"; - goto update_fail; - } - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - pgno = (Pgno)sqlite3_value_int(argv[2]); - isInsert = 1; - }else{ - pgno = sqlite3_value_int(argv[0]); - if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ - zErr = "cannot insert"; - goto update_fail; - } - isInsert = 0; - } - if( sqlite3_value_type(argv[4])==SQLITE_NULL ){ - iDb = 0; - }else{ - const char *zSchema = (const char*)sqlite3_value_text(argv[4]); - iDb = sqlite3FindDbName(pTab->db, zSchema); - if( iDb<0 ){ - zErr = "no such schema"; - goto update_fail; - } - } - pBt = pTab->db->aDb[iDb].pBt; - if( pgno<1 || NEVER(pBt==0) ){ - zErr = "bad page number"; - goto update_fail; - } - szPage = sqlite3BtreeGetPageSize(pBt); - if( sqlite3_value_type(argv[3])!=SQLITE_BLOB - || sqlite3_value_bytes(argv[3])!=szPage - ){ - if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){ - /* "INSERT INTO dbpage($PGNO,NULL)" causes page number $PGNO and - ** all subsequent pages to be deleted. */ - pTab->iDbTrunc = iDb; - pgno--; - pTab->pgnoTrunc = pgno; - }else{ - zErr = "bad page value"; - goto update_fail; - } - } - - if( dbpageBeginTrans(pTab)!=SQLITE_OK ){ - zErr = "failed to open transaction"; - goto update_fail; - } - - pPager = sqlite3BtreePager(pBt); - rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0); - if( rc==SQLITE_OK ){ - const void *pData = sqlite3_value_blob(argv[3]); - if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ - unsigned char *aPage = sqlite3PagerGetData(pDbPage); - memcpy(aPage, pData, szPage); - pTab->pgnoTrunc = 0; - } - }else{ - pTab->pgnoTrunc = 0; - } - sqlite3PagerUnref(pDbPage); - return rc; - -update_fail: - pTab->pgnoTrunc = 0; - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = sqlite3_mprintf("%s", zErr); - return SQLITE_ERROR; -} - -static int dbpageBegin(sqlite3_vtab *pVtab){ - DbpageTable *pTab = (DbpageTable *)pVtab; - pTab->pgnoTrunc = 0; - return SQLITE_OK; -} - -/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT -*/ -static int dbpageSync(sqlite3_vtab *pVtab){ - DbpageTable *pTab = (DbpageTable *)pVtab; - if( pTab->pgnoTrunc>0 ){ - Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt; - Pager *pPager = sqlite3BtreePager(pBt); - sqlite3BtreeEnter(pBt); - if( pTab->pgnoTruncpgnoTrunc); - } - sqlite3BtreeLeave(pBt); - } - pTab->pgnoTrunc = 0; - return SQLITE_OK; -} - -/* Cancel any pending truncate. -*/ -static int dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){ - DbpageTable *pTab = (DbpageTable *)pVtab; - pTab->pgnoTrunc = 0; - (void)notUsed1; - return SQLITE_OK; -} - -/* -** Invoke this routine to register the "dbpage" virtual table module -*/ -SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ - static sqlite3_module dbpage_module = { - 2, /* iVersion */ - dbpageConnect, /* xCreate */ - dbpageConnect, /* xConnect */ - dbpageBestIndex, /* xBestIndex */ - dbpageDisconnect, /* xDisconnect */ - dbpageDisconnect, /* xDestroy */ - dbpageOpen, /* xOpen - open a cursor */ - dbpageClose, /* xClose - close a cursor */ - dbpageFilter, /* xFilter - configure scan constraints */ - dbpageNext, /* xNext - advance a cursor */ - dbpageEof, /* xEof - check for end of scan */ - dbpageColumn, /* xColumn - read data */ - dbpageRowid, /* xRowid - read data */ - dbpageUpdate, /* xUpdate */ - dbpageBegin, /* xBegin */ - dbpageSync, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - dbpageRollbackTo, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ - }; - return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); -} -#elif defined(SQLITE_ENABLE_DBPAGE_VTAB) -SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } -#endif /* SQLITE_ENABLE_DBSTAT_VTAB */ - -/************** End of dbpage.c **********************************************/ /************** Begin file sqlite3session.c **********************************/ #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) /* #include "sqlite3session.h" */ /* #include */ @@ -226748,14 +175914,10 @@ # else # define SESSIONS_STRM_CHUNK_SIZE 1024 # endif #endif -#define SESSIONS_ROWID "_rowid_" - -static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; - typedef struct SessionHook SessionHook; struct SessionHook { void *pCtx; int (*xOld)(void*,int,sqlite3_value**); int (*xNew)(void*,int,sqlite3_value**); @@ -226767,21 +175929,16 @@ ** Session handle structure. */ struct sqlite3_session { sqlite3 *db; /* Database handle session is attached to */ char *zDb; /* Name of database session is attached to */ - int bEnableSize; /* True if changeset_size() enabled */ int bEnable; /* True if currently recording */ int bIndirect; /* True if all changes are indirect */ int bAutoAttach; /* True to auto-attach tables */ - int bImplicitPK; /* True to handle tables with implicit PK */ int rc; /* Non-zero if an error has occurred */ void *pFilterCtx; /* First argument to pass to xTableFilter */ int (*xTableFilter)(void *pCtx, const char *zTab); - i64 nMalloc; /* Number of bytes of data allocated */ - i64 nMaxChangesetSize; - sqlite3_value *pZeroBlob; /* Value containing X'' */ sqlite3_session *pNext; /* Next session object on same db. */ SessionTable *pTable; /* List of attached tables */ SessionHook hook; /* APIs to grab new and old data with */ }; @@ -226793,21 +175950,17 @@ int nBuf; /* Size of buffer aBuf */ int nAlloc; /* Size of allocation containing aBuf */ }; /* -** An object of this type is used internally as an abstraction for +** An object of this type is used internally as an abstraction for ** input data. Input data may be supplied either as a single large buffer ** (e.g. sqlite3changeset_start()) or using a stream function (e.g. ** sqlite3changeset_start_strm()). -** -** bNoDiscard: -** If true, then the only time data is discarded is as a result of explicit -** sessionDiscardData() calls. Not within every sessionInputBuffer() call. */ struct SessionInput { - int bNoDiscard; /* If true, do not discard in InputBuffer() */ + int bNoDiscard; /* If true, discard no data */ int iCurrent; /* Offset in aData[] of current change */ int iNext; /* Offset in aData[] of next change */ u8 *aData; /* Pointer to buffer containing changeset */ int nData; /* Number of bytes in aData */ @@ -226822,12 +175975,10 @@ */ struct sqlite3_changeset_iter { SessionInput in; /* Input buffer or stream */ SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ int bPatchset; /* True if this is a patchset */ - int bInvert; /* True to invert changeset */ - int bSkipEmpty; /* Skip noop UPDATE changes */ int rc; /* Iterator error code */ sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ char *zTab; /* Current table */ int nCol; /* Number of columns in zTab */ int op; /* Current operation */ @@ -226846,45 +175997,27 @@ ** table. ** ** The data associated with each hash-table entry is a structure containing ** a subset of the initial values that the modified row contained at the ** start of the session. Or no initial values if the row was inserted. -** -** pDfltStmt: -** This is only used by the sqlite3changegroup_xxx() APIs, not by -** regular sqlite3_session objects. It is a SELECT statement that -** selects the default value for each table column. For example, -** if the table is -** -** CREATE TABLE xx(a DEFAULT 1, b, c DEFAULT 'abc') -** -** then this variable is the compiled version of: -** -** SELECT 1, NULL, 'abc' */ struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ - int nCol; /* Number of non-hidden columns */ - int nTotalCol; /* Number of columns including hidden */ - int bStat1; /* True if this is sqlite_stat1 */ - int bRowid; /* True if this table uses rowid for PK */ + int nCol; /* Number of columns in table zName */ const char **azCol; /* Column names */ - const char **azDflt; /* Default value expressions */ - int *aiIdx; /* Index to pass to xNew/xOld */ u8 *abPK; /* Array of primary key flags */ int nEntry; /* Total number of entries in hash table */ int nChange; /* Size of apChange[] array */ SessionChange **apChange; /* Hash table buckets */ - sqlite3_stmt *pDfltStmt; }; -/* +/* ** RECORD FORMAT: ** -** The following record format is similar to (but not compatible with) that -** used in SQLite database files. This format is used as part of the +** The following record format is similar to (but not compatible with) that +** used in SQLite database files. This format is used as part of the ** change-set binary format, and so must be architecture independent. ** ** Unlike the SQLite database record format, each field is self-contained - ** there is no separation of header and data. Each field begins with a ** single byte describing its type, as follows: @@ -226914,11 +176047,11 @@ ** An 8-byte big-endian integer value. ** ** Real values: ** An 8-byte big-endian IEEE 754-2008 real value. ** -** Varint values are encoded in the same way as varints in the SQLite +** Varint values are encoded in the same way as varints in the SQLite ** record format. ** ** CHANGESET FORMAT: ** ** A changeset is a collection of DELETE, UPDATE and INSERT operations on @@ -226946,21 +176079,21 @@ ** the i'th column of the table, counting from left to right in the order ** in which columns were declared in the CREATE TABLE statement. ** ** The new.* record that is part of each INSERT change contains the values ** that make up the new row. Similarly, the old.* record that is part of each -** DELETE change contains the values that made up the row that was deleted +** DELETE change contains the values that made up the row that was deleted ** from the database. In the changeset format, the records that are part ** of INSERT or DELETE changes never contain any undefined (type byte 0x00) ** fields. ** ** Within the old.* record associated with an UPDATE change, all fields ** associated with table columns that are not PRIMARY KEY columns and are ** not modified by the UPDATE change are set to "undefined". Other fields ** are set to the values that made up the row before the UPDATE that the -** change records took place. Within the new.* record, fields associated -** with table columns modified by the UPDATE change contain the new +** change records took place. Within the new.* record, fields associated +** with table columns modified by the UPDATE change contain the new ** values. Fields associated with table columns that are not modified ** are set to "undefined". ** ** PATCHSET FORMAT: ** @@ -226982,79 +176115,41 @@ ** single record: (PK fields for DELETE, PK and modified fields for UPDATE, ** full record for INSERT). ** ** As in the changeset format, each field of the single record that is part ** of a patchset change is associated with the correspondingly positioned -** table column, counting from left to right within the CREATE TABLE +** table column, counting from left to right within the CREATE TABLE ** statement. ** ** For a DELETE change, all fields within the record except those associated -** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the -** values identifying the row to delete. +** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields +** contain the values identifying the row to delete. ** ** For an UPDATE change, all fields except those associated with PRIMARY KEY ** columns and columns that are modified by the UPDATE are set to "undefined". ** PRIMARY KEY fields contain the values identifying the table row to update, ** and fields associated with modified columns contain the new column values. ** ** The records associated with INSERT changes are in the same format as for ** changesets. It is not possible for a record associated with an INSERT ** change to contain a field set to "undefined". -** -** REBASE BLOB FORMAT: -** -** A rebase blob may be output by sqlite3changeset_apply_v2() and its -** streaming equivalent for use with the sqlite3_rebaser APIs to rebase -** existing changesets. A rebase blob contains one entry for each conflict -** resolved using either the OMIT or REPLACE strategies within the apply_v2() -** call. -** -** The format used for a rebase blob is very similar to that used for -** changesets. All entries related to a single table are grouped together. -** -** Each group of entries begins with a table header in changeset format: -** -** 1 byte: Constant 0x54 (capital 'T') -** Varint: Number of columns in the table. -** nCol bytes: 0x01 for PK columns, 0x00 otherwise. -** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. -** -** Followed by one or more entries associated with the table. -** -** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09). -** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT. -** record: (in the record format defined above). -** -** In a rebase blob, the first field is set to SQLITE_INSERT if the change -** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if -** it was a DELETE. The second field is set to 0x01 if the conflict -** resolution strategy was REPLACE, or 0x00 if it was OMIT. -** -** If the change that caused the conflict was a DELETE, then the single -** record is a copy of the old.* record from the original changeset. If it -** was an INSERT, then the single record is a copy of the new.* record. If -** the conflicting change was an UPDATE, then the single record is a copy -** of the new.* record with the PK fields filled in based on the original -** old.* record. */ /* ** For each row modified during a session, there exists a single instance of ** this structure stored in a SessionTable.aChange[] hash table. */ struct SessionChange { - u8 op; /* One of UPDATE, DELETE, INSERT */ - u8 bIndirect; /* True if this change is "indirect" */ - u16 nRecordField; /* Number of fields in aRecord[] */ - int nMaxSize; /* Max size of eventual changeset record */ + int op; /* One of UPDATE, DELETE, INSERT */ + int bIndirect; /* True if this change is "indirect" */ int nRecord; /* Number of bytes in buffer aRecord[] */ u8 *aRecord; /* Buffer containing old.* record */ SessionChange *pNext; /* For hash-table collisions */ }; /* -** Write a varint with value iVal into the buffer at aBuf. Return the +** Write a varint with value iVal into the buffer at aBuf. Return the ** number of bytes written. */ static int sessionVarintPut(u8 *aBuf, int iVal){ return putVarint32(aBuf, iVal); } @@ -227065,14 +176160,14 @@ static int sessionVarintLen(int iVal){ return sqlite3VarintLen(iVal); } /* -** Read a varint value from aBuf[] into *piVal. Return the number of +** Read a varint value from aBuf[] into *piVal. Return the number of ** bytes read. */ -static int sessionVarintGet(const u8 *aBuf, int *piVal){ +static int sessionVarintGet(u8 *aBuf, int *piVal){ return getVarint32(aBuf, *piVal); } /* Load an unaligned and unsigned 32-bit integer */ #define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) @@ -227104,38 +176199,38 @@ /* ** This function is used to serialize the contents of value pValue (see ** comment titled "RECORD FORMAT" above). ** -** If it is non-NULL, the serialized form of the value is written to +** If it is non-NULL, the serialized form of the value is written to ** buffer aBuf. *pnWrite is set to the number of bytes written before ** returning. Or, if aBuf is NULL, the only thing this function does is ** set *pnWrite. ** ** If no error occurs, SQLITE_OK is returned. Or, if an OOM error occurs -** within a call to sqlite3_value_text() (may fail if the db is utf-16)) +** within a call to sqlite3_value_text() (may fail if the db is utf-16)) ** SQLITE_NOMEM is returned. */ static int sessionSerializeValue( u8 *aBuf, /* If non-NULL, write serialized value here */ sqlite3_value *pValue, /* Value to serialize */ - sqlite3_int64 *pnWrite /* IN/OUT: Increment by bytes written */ + int *pnWrite /* IN/OUT: Increment by bytes written */ ){ int nByte; /* Size of serialized value in bytes */ if( pValue ){ int eType; /* Value type (SQLITE_NULL, TEXT etc.) */ - + eType = sqlite3_value_type(pValue); if( aBuf ) aBuf[0] = eType; - + switch( eType ){ - case SQLITE_NULL: + case SQLITE_NULL: nByte = 1; break; - - case SQLITE_INTEGER: + + case SQLITE_INTEGER: case SQLITE_FLOAT: if( aBuf ){ /* TODO: SQLite does something special to deal with mixed-endian ** floating point values (e.g. ARM7). This code probably should ** too. */ @@ -227148,33 +176243,33 @@ r = sqlite3_value_double(pValue); memcpy(&i, &r, 8); } sessionPutI64(&aBuf[1], i); } - nByte = 9; + nByte = 9; break; - + default: { u8 *z; int n; int nVarint; - + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); if( eType==SQLITE_TEXT ){ z = (u8 *)sqlite3_value_text(pValue); }else{ z = (u8 *)sqlite3_value_blob(pValue); } n = sqlite3_value_bytes(pValue); if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; nVarint = sessionVarintLen(n); - + if( aBuf ){ sessionVarintPut(&aBuf[1], n); - if( n>0 ) memcpy(&aBuf[nVarint + 1], z, n); + if( n ) memcpy(&aBuf[nVarint + 1], z, n); } - + nByte = 1 + nVarint + n; break; } } }else{ @@ -227184,30 +176279,10 @@ if( pnWrite ) *pnWrite += nByte; return SQLITE_OK; } -/* -** Allocate and return a pointer to a buffer nByte bytes in size. If -** pSession is not NULL, increase the sqlite3_session.nMalloc variable -** by the number of bytes allocated. -*/ -static void *sessionMalloc64(sqlite3_session *pSession, i64 nByte){ - void *pRet = sqlite3_malloc64(nByte); - if( pSession ) pSession->nMalloc += sqlite3_msize(pRet); - return pRet; -} - -/* -** Free buffer pFree, which must have been allocated by an earlier -** call to sessionMalloc64(). If pSession is not NULL, decrease the -** sqlite3_session.nMalloc counter by the number of bytes freed. -*/ -static void sessionFree(sqlite3_session *pSession, void *pFree){ - if( pSession ) pSession->nMalloc -= sqlite3_msize(pFree); - sqlite3_free(pFree); -} /* ** This macro is used to calculate hash key values for data structures. In ** order to use this macro, the entire data structure must be represented ** as a series of unsigned integers. In order to calculate a hash-key value @@ -227232,11 +176307,11 @@ h = HASH_APPEND(h, i & 0xFFFFFFFF); return HASH_APPEND(h, (i>>32)&0xFFFFFFFF); } /* -** Append the hash of the blob passed via the second and third arguments to +** Append the hash of the blob passed via the second and third arguments to ** the hash-key value passed as the first. Return the new hash-key value. */ static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){ int i; for(i=0; inTotalCol==pSession->hook.xCount(pSession->hook.pCtx) ); - if( pTab->bRowid ){ - h = sessionHashAppendI64(h, iRowid); - }else{ - assert( *pbNullPK==0 ); - for(i=0; inCol; i++){ - if( pTab->abPK[i] ){ - int rc; - int eType; - sqlite3_value *pVal; - int iIdx = pTab->aiIdx[i]; - - if( bNew ){ - rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal); - }else{ - rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal); - } - if( rc!=SQLITE_OK ) return rc; - - eType = sqlite3_value_type(pVal); - h = sessionHashAppendType(h, eType); - if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ - i64 iVal; - if( eType==SQLITE_INTEGER ){ - iVal = sqlite3_value_int64(pVal); - }else{ - double rVal = sqlite3_value_double(pVal); - assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); - memcpy(&iVal, &rVal, 8); - } - h = sessionHashAppendI64(h, iVal); - }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ - const u8 *z; - int n; - if( eType==SQLITE_TEXT ){ - z = (const u8 *)sqlite3_value_text(pVal); - }else{ - z = (const u8 *)sqlite3_value_blob(pVal); - } - n = sqlite3_value_bytes(pVal); - if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; - h = sessionHashAppendBlob(h, n, z); - }else{ - assert( eType==SQLITE_NULL ); - assert( pTab->bStat1==0 || i!=1 ); - *pbNullPK = 1; - } + assert( *pbNullPK==0 ); + assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) ); + for(i=0; inCol; i++){ + if( pTab->abPK[i] ){ + int rc; + int eType; + sqlite3_value *pVal; + + if( bNew ){ + rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); + }else{ + rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); + } + if( rc!=SQLITE_OK ) return rc; + + eType = sqlite3_value_type(pVal); + h = sessionHashAppendType(h, eType); + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + i64 iVal; + if( eType==SQLITE_INTEGER ){ + iVal = sqlite3_value_int64(pVal); + }else{ + double rVal = sqlite3_value_double(pVal); + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); + memcpy(&iVal, &rVal, 8); + } + h = sessionHashAppendI64(h, iVal); + }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + const u8 *z; + int n; + if( eType==SQLITE_TEXT ){ + z = (const u8 *)sqlite3_value_text(pVal); + }else{ + z = (const u8 *)sqlite3_value_blob(pVal); + } + n = sqlite3_value_bytes(pVal); + if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; + h = sessionHashAppendBlob(h, n, z); + }else{ + assert( eType==SQLITE_NULL ); + *pbNullPK = 1; } } } *piHash = (h % pTab->nChange); @@ -227331,16 +176399,14 @@ /* ** The buffer that the argument points to contains a serialized SQL value. ** Return the number of bytes of space occupied by the value (including ** the type byte). */ -static int sessionSerialLen(const u8 *a){ - int e; +static int sessionSerialLen(u8 *a){ + int e = *a; int n; - assert( a!=0 ); - e = *a; - if( e==0 || e==0xFF ) return 1; + if( e==0 ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; return sessionVarintGet(&a[1], &n) + 1 + n; } @@ -227366,16 +176432,16 @@ for(i=0; inCol; i++){ int eType = *a; int isPK = pTab->abPK[i]; if( bPkOnly && isPK==0 ) continue; - /* It is not possible for eType to be SQLITE_NULL here. The session + /* It is not possible for eType to be SQLITE_NULL here. The session ** module does not record changes for rows with NULL values stored in ** primary key columns. */ - assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT - || eType==SQLITE_TEXT || eType==SQLITE_BLOB - || eType==SQLITE_NULL || eType==0 + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT + || eType==SQLITE_TEXT || eType==SQLITE_BLOB + || eType==SQLITE_NULL || eType==0 ); assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); if( isPK ){ a++; @@ -227382,11 +176448,11 @@ h = sessionHashAppendType(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ h = sessionHashAppendI64(h, sessionGetI64(a)); a += 8; }else{ - int n; + int n; a += sessionVarintGet(a, &n); h = sessionHashAppendBlob(h, n, a); a += n; } }else{ @@ -227397,11 +176463,11 @@ } /* ** Arguments aLeft and aRight are pointers to change records for table pTab. ** This function returns true if the two records apply to the same row (i.e. -** have the same values stored in the primary key columns), or false +** have the same values stored in the primary key columns), or false ** otherwise. */ static int sessionChangeEqual( SessionTable *pTab, /* Table used for PK definition */ int bLeftPkOnly, /* True if aLeft[] contains PK fields only */ @@ -227416,11 +176482,11 @@ for(iCol=0; iColnCol; iCol++){ if( pTab->abPK[iCol] ){ int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); - if( n1!=n2 || memcmp(a1, a2, n1) ){ + if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ return 0; } a1 += n1; a2 += n2; }else{ @@ -227434,21 +176500,21 @@ /* ** Arguments aLeft and aRight both point to buffers containing change ** records with nCol columns. This function "merges" the two records into ** a single records which is written to the buffer at *paOut. *paOut is -** then set to point to one byte after the last byte written before +** then set to point to one byte after the last byte written before ** returning. ** -** The merging of records is done as follows: For each column, if the +** The merging of records is done as follows: For each column, if the ** aRight record contains a value for the column, copy the value from ** their. Otherwise, if aLeft contains a value, copy it. If neither ** record contains a value for a given column, then neither does the ** output record. */ static void sessionMergeRecord( - u8 **paOut, + u8 **paOut, int nCol, u8 *aLeft, u8 *aRight ){ u8 *a1 = aLeft; /* Cursor used to iterate through aLeft */ @@ -227474,17 +176540,17 @@ } /* ** This is a helper function used by sessionMergeUpdate(). ** -** When this function is called, both *paOne and *paTwo point to a value -** within a change record. Before it returns, both have been advanced so +** When this function is called, both *paOne and *paTwo point to a value +** within a change record. Before it returns, both have been advanced so ** as to point to the next value in the record. ** ** If, when this function is called, *paTwo points to a valid value (i.e. ** *paTwo[0] is not 0x00 - the "no value" placeholder), a copy of the *paTwo -** pointer is returned and *pnVal is set to the number of bytes in the +** pointer is returned and *pnVal is set to the number of bytes in the ** serialized value. Otherwise, a copy of *paOne is returned and *pnVal ** set to the number of bytes in the value at *paOne. If *paOne points ** to the "no value" placeholder, *pnVal is set to 1. In other words: ** ** if( *paTwo is valid ) return *paTwo; @@ -227579,12 +176645,12 @@ int nNew; u8 *aNew; aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); - if( bPatchset==0 - && (pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew))) + if( bPatchset==0 + && (pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew))) ){ *(aOut++) = '\0'; }else{ memcpy(aOut, aNew, nNew); aOut += nNew; @@ -227602,47 +176668,39 @@ ** if the pre-update-hook does not affect the same row as pChange, it returns ** false. */ static int sessionPreupdateEqual( sqlite3_session *pSession, /* Session object that owns SessionTable */ - i64 iRowid, /* Rowid value if pTab->bRowid */ SessionTable *pTab, /* Table associated with change */ SessionChange *pChange, /* Change to compare to */ int op /* Current pre-update operation */ ){ int iCol; /* Used to iterate through columns */ u8 *a = pChange->aRecord; /* Cursor used to scan change record */ - if( pTab->bRowid ){ - if( a[0]!=SQLITE_INTEGER ) return 0; - return sessionGetI64(&a[1])==iRowid; - } - assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); for(iCol=0; iColnCol; iCol++){ if( !pTab->abPK[iCol] ){ a += sessionSerialLen(a); }else{ sqlite3_value *pVal; /* Value returned by preupdate_new/old */ int rc; /* Error code from preupdate_new/old */ int eType = *a++; /* Type of value from change record */ - int iIdx = pTab->aiIdx[iCol]; /* The following calls to preupdate_new() and preupdate_old() can not ** fail. This is because they cache their return values, and by the ** time control flows to here they have already been called once from ** within sessionPreupdateHash(). The first two asserts below verify ** this (that the method has already been called). */ if( op==SQLITE_INSERT ){ /* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */ - rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal); + rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal); }else{ /* assert( db->pPreUpdate->pUnpacked ); */ - rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal); + rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal); } assert( rc==SQLITE_OK ); - (void)rc; /* Suppress warning about unused variable */ if( sqlite3_value_type(pVal)!=eType ) return 0; /* A SessionChange object never has a NULL value in a PK column */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT || eType==SQLITE_BLOB || eType==SQLITE_TEXT @@ -227667,43 +176725,38 @@ if( eType==SQLITE_TEXT ){ z = sqlite3_value_text(pVal); }else{ z = sqlite3_value_blob(pVal); } - if( n>0 && memcmp(a, z, n) ) return 0; + if( memcmp(a, z, n) ) return 0; a += n; + break; } } } return 1; } /* -** If required, grow the hash table used to store changes on table pTab +** If required, grow the hash table used to store changes on table pTab ** (part of the session pSession). If a fatal OOM error occurs, set the ** session object to failed and return SQLITE_ERROR. Otherwise, return ** SQLITE_OK. ** ** It is possible that a non-fatal OOM error occurs in this function. In ** that case the hash-table does not grow, but SQLITE_OK is returned anyway. ** Growing the hash table in this case is a performance optimization only, ** it is not required for correct operation. */ -static int sessionGrowHash( - sqlite3_session *pSession, /* For memory accounting. May be NULL */ - int bPatchset, - SessionTable *pTab -){ +static int sessionGrowHash(int bPatchset, SessionTable *pTab){ if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ int i; SessionChange **apNew; - sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128); + int nNew = (pTab->nChange ? pTab->nChange : 128) * 2; - apNew = (SessionChange**)sessionMalloc64( - pSession, sizeof(SessionChange*) * nNew - ); + apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew); if( apNew==0 ){ if( pTab->nChange==0 ){ return SQLITE_ERROR; } return SQLITE_OK; @@ -227720,21 +176773,23 @@ p->pNext = apNew[iHash]; apNew[iHash] = p; } } - sessionFree(pSession, pTab->apChange); + sqlite3_free(pTab->apChange); pTab->nChange = nNew; pTab->apChange = apNew; } return SQLITE_OK; } /* ** This function queries the database for the names of the columns of table -** zThis, in schema zDb. +** zThis, in schema zDb. It is expected that the table has nCol columns. If +** not, SQLITE_SCHEMA is returned and none of the output variables are +** populated. ** ** Otherwise, if they are not NULL, variable *pnCol is set to the number ** of columns in the database table and variable *pzTab is set to point to a ** nul-terminated copy of the table name. *pazCol (if not NULL) is set to ** point to an array of pointers to column names. And *pabPK (again, if not @@ -227741,865 +176796,275 @@ ** NULL) is set to point to an array of booleans - true if the corresponding ** column is part of the primary key. ** ** For example, if the table is declared as: ** -** CREATE TABLE tbl1(w, x DEFAULT 'abc', y, z, PRIMARY KEY(w, z)); +** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); ** -** Then the five output variables are populated as follows: +** Then the four output variables are populated as follows: ** ** *pnCol = 4 ** *pzTab = "tbl1" ** *pazCol = {"w", "x", "y", "z"} -** *pazDflt = {NULL, 'abc', NULL, NULL} ** *pabPK = {1, 0, 0, 1} ** ** All returned buffers are part of the same single allocation, which must -** be freed using sqlite3_free() by the caller +** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then +** pointer *pazCol should be freed to release all memory. Otherwise, pointer +** *pabPK. It is illegal for both pazCol and pabPK to be NULL. */ static int sessionTableInfo( - sqlite3_session *pSession, /* For memory accounting. May be NULL */ sqlite3 *db, /* Database connection */ const char *zDb, /* Name of attached database (e.g. "main") */ const char *zThis, /* Table name */ int *pnCol, /* OUT: number of columns */ - int *pnTotalCol, /* OUT: number of hidden columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ - const char ***pazDflt, /* OUT: Array of default value expressions */ - int **paiIdx, /* OUT: Array of xNew/xOld indexes */ - u8 **pabPK, /* OUT: Array of booleans - true for PK col */ - int *pbRowid /* OUT: True if only PK is a rowid */ + u8 **pabPK /* OUT: Array of booleans - true for PK col */ ){ char *zPragma; sqlite3_stmt *pStmt; int rc; - sqlite3_int64 nByte; + int nByte; int nDbCol = 0; int nThis; int i; u8 *pAlloc = 0; char **azCol = 0; - char **azDflt = 0; u8 *abPK = 0; - int *aiIdx = 0; - int bRowid = 0; /* Set to true to use rowid as PK */ assert( pazCol && pabPK ); - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pnTotalCol ) *pnTotalCol = 0; - if( paiIdx ) *paiIdx = 0; - if( pzTab ) *pzTab = 0; - if( pazDflt ) *pazDflt = 0; - nThis = sqlite3Strlen30(zThis); - if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){ - rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0); - if( rc==SQLITE_OK ){ - /* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */ - zPragma = sqlite3_mprintf( - "SELECT 0, 'tbl', '', 0, '', 1, 0 UNION ALL " - "SELECT 1, 'idx', '', 0, '', 2, 0 UNION ALL " - "SELECT 2, 'stat', '', 0, '', 0, 0" - ); - }else if( rc==SQLITE_ERROR ){ - zPragma = sqlite3_mprintf(""); - }else{ - return rc; - } - }else{ - zPragma = sqlite3_mprintf("PRAGMA '%q'.table_xinfo('%q')", zDb, zThis); - } - if( !zPragma ){ - return SQLITE_NOMEM; - } + zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); + if( !zPragma ) return SQLITE_NOMEM; rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); sqlite3_free(zPragma); - if( rc!=SQLITE_OK ){ - return rc; - } + if( rc!=SQLITE_OK ) return rc; nByte = nThis + 1; - bRowid = (pbRowid!=0); while( SQLITE_ROW==sqlite3_step(pStmt) ){ - nByte += sqlite3_column_bytes(pStmt, 1); /* name */ - nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */ - if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */ - nDbCol++; - } - if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */ - } - if( nDbCol==0 ) bRowid = 0; - nDbCol += bRowid; - nByte += strlen(SESSIONS_ROWID); + nByte += sqlite3_column_bytes(pStmt, 1); + nDbCol++; + } rc = sqlite3_reset(pStmt); if( rc==SQLITE_OK ){ - nByte += nDbCol * (sizeof(const char *)*2 +sizeof(int)+sizeof(u8) + 1 + 1); - pAlloc = sessionMalloc64(pSession, nByte); + nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); + pAlloc = sqlite3_malloc(nByte); if( pAlloc==0 ){ rc = SQLITE_NOMEM; - }else{ - memset(pAlloc, 0, nByte); } } if( rc==SQLITE_OK ){ azCol = (char **)pAlloc; - azDflt = (char**)&azCol[nDbCol]; - aiIdx = (int*)&azDflt[nDbCol]; - abPK = (u8 *)&aiIdx[nDbCol]; + pAlloc = (u8 *)&azCol[nDbCol]; + abPK = (u8 *)pAlloc; pAlloc = &abPK[nDbCol]; if( pzTab ){ memcpy(pAlloc, zThis, nThis+1); *pzTab = (char *)pAlloc; pAlloc += nThis+1; } - - i = 0; - if( bRowid ){ - size_t nName = strlen(SESSIONS_ROWID); - memcpy(pAlloc, SESSIONS_ROWID, nName+1); - azCol[i] = (char*)pAlloc; - pAlloc += nName+1; - abPK[i] = 1; - aiIdx[i] = -1; - i++; - } - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */ - int nName = sqlite3_column_bytes(pStmt, 1); - int nDflt = sqlite3_column_bytes(pStmt, 4); - const unsigned char *zName = sqlite3_column_text(pStmt, 1); - const unsigned char *zDflt = sqlite3_column_text(pStmt, 4); - - if( zName==0 ) break; - memcpy(pAlloc, zName, nName+1); - azCol[i] = (char *)pAlloc; - pAlloc += nName+1; - if( zDflt ){ - memcpy(pAlloc, zDflt, nDflt+1); - azDflt[i] = (char *)pAlloc; - pAlloc += nDflt+1; - }else{ - azDflt[i] = 0; - } - abPK[i] = sqlite3_column_int(pStmt, 5); - aiIdx[i] = sqlite3_column_int(pStmt, 0); - i++; - } - if( pnTotalCol ) (*pnTotalCol)++; - } - rc = sqlite3_reset(pStmt); + + i = 0; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nName = sqlite3_column_bytes(pStmt, 1); + const unsigned char *zName = sqlite3_column_text(pStmt, 1); + if( zName==0 ) break; + memcpy(pAlloc, zName, nName+1); + azCol[i] = (char *)pAlloc; + pAlloc += nName+1; + abPK[i] = sqlite3_column_int(pStmt, 5); + i++; + } + rc = sqlite3_reset(pStmt); + } /* If successful, populate the output variables. Otherwise, zero them and ** free any allocation made. An error code will be returned in this case. */ if( rc==SQLITE_OK ){ - *pazCol = (const char**)azCol; - if( pazDflt ) *pazDflt = (const char**)azDflt; + *pazCol = (const char **)azCol; *pabPK = abPK; *pnCol = nDbCol; - if( paiIdx ) *paiIdx = aiIdx; }else{ - sessionFree(pSession, azCol); + *pazCol = 0; + *pabPK = 0; + *pnCol = 0; + if( pzTab ) *pzTab = 0; + sqlite3_free(azCol); } - if( pbRowid ) *pbRowid = bRowid; sqlite3_finalize(pStmt); return rc; } /* -** This function is called to initialize the SessionTable.nCol, azCol[] -** abPK[] and azDflt[] members of SessionTable object pTab. If these -** fields are already initilialized, this function is a no-op. +** This function is only called from within a pre-update handler for a +** write to table pTab, part of session pSession. If this is the first +** write to this table, initalize the SessionTable.nCol, azCol[] and +** abPK[] arrays accordingly. ** ** If an error occurs, an error code is stored in sqlite3_session.rc and ** non-zero returned. Or, if no error occurs but the table has no primary ** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to -** indicate that updates on this table should be ignored. SessionTable.abPK +** indicate that updates on this table should be ignored. SessionTable.abPK ** is set to NULL in this case. */ -static int sessionInitTable( - sqlite3_session *pSession, /* Optional session handle */ - SessionTable *pTab, /* Table object to initialize */ - sqlite3 *db, /* Database handle to read schema from */ - const char *zDb /* Name of db - "main", "temp" etc. */ -){ - int rc = SQLITE_OK; - +static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); - rc = sessionTableInfo(pSession, db, zDb, - pTab->zName, &pTab->nCol, &pTab->nTotalCol, 0, &pTab->azCol, - &pTab->azDflt, &pTab->aiIdx, &abPK, - ((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0) + pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK ); - if( rc==SQLITE_OK ){ + if( pSession->rc==SQLITE_OK ){ int i; for(i=0; inCol; i++){ if( abPK[i] ){ pTab->abPK = abPK; break; } } - if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){ - pTab->bStat1 = 1; - } - - if( pSession && pSession->bEnableSize ){ - pSession->nMaxChangesetSize += ( - 1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1 - ); - } - } - } - - if( pSession ){ - pSession->rc = rc; - return (rc || pTab->abPK==0); - } - return rc; -} - -/* -** Re-initialize table object pTab. -*/ -static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){ - int nCol = 0; - int nTotalCol = 0; - const char **azCol = 0; - const char **azDflt = 0; - int *aiIdx = 0; - u8 *abPK = 0; - int bRowid = 0; - - assert( pSession->rc==SQLITE_OK ); - - pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, - pTab->zName, &nCol, &nTotalCol, 0, &azCol, &azDflt, &aiIdx, &abPK, - (pSession->bImplicitPK ? &bRowid : 0) - ); - if( pSession->rc==SQLITE_OK ){ - if( pTab->nCol>nCol || pTab->bRowid!=bRowid ){ - pSession->rc = SQLITE_SCHEMA; - }else{ - int ii; - int nOldCol = pTab->nCol; - for(ii=0; iinCol ){ - if( pTab->abPK[ii]!=abPK[ii] ){ - pSession->rc = SQLITE_SCHEMA; - } - }else if( abPK[ii] ){ - pSession->rc = SQLITE_SCHEMA; - } - } - - if( pSession->rc==SQLITE_OK ){ - const char **a = pTab->azCol; - pTab->azCol = azCol; - pTab->nCol = nCol; - pTab->nTotalCol = nTotalCol; - pTab->azDflt = azDflt; - pTab->abPK = abPK; - pTab->aiIdx = aiIdx; - azCol = a; - } - if( pSession->bEnableSize ){ - pSession->nMaxChangesetSize += (nCol - nOldCol); - pSession->nMaxChangesetSize += sessionVarintLen(nCol); - pSession->nMaxChangesetSize -= sessionVarintLen(nOldCol); - } - } - } - - sqlite3_free((char*)azCol); - return pSession->rc; -} - -/* -** Session-change object (*pp) contains an old.* record with fewer than -** nCol fields. This function updates it with the default values for -** the missing fields. -*/ -static void sessionUpdateOneChange( - sqlite3_session *pSession, /* For memory accounting */ - int *pRc, /* IN/OUT: Error code */ - SessionChange **pp, /* IN/OUT: Change object to update */ - int nCol, /* Number of columns now in table */ - sqlite3_stmt *pDflt /* SELECT */ -){ - SessionChange *pOld = *pp; - - while( pOld->nRecordFieldnRecordField; - int eType = sqlite3_column_type(pDflt, iField); - switch( eType ){ - case SQLITE_NULL: - nIncr = 1; - break; - case SQLITE_INTEGER: - case SQLITE_FLOAT: - nIncr = 9; - break; - default: { - int n = sqlite3_column_bytes(pDflt, iField); - nIncr = 1 + sessionVarintLen(n) + n; - assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); - break; - } - } - - nByte = nIncr + (sizeof(SessionChange) + pOld->nRecord); - pNew = sessionMalloc64(pSession, nByte); - if( pNew==0 ){ - *pRc = SQLITE_NOMEM; - return; - }else{ - memcpy(pNew, pOld, sizeof(SessionChange)); - pNew->aRecord = (u8*)&pNew[1]; - memcpy(pNew->aRecord, pOld->aRecord, pOld->nRecord); - pNew->aRecord[pNew->nRecord++] = (u8)eType; - switch( eType ){ - case SQLITE_INTEGER: { - i64 iVal = sqlite3_column_int64(pDflt, iField); - sessionPutI64(&pNew->aRecord[pNew->nRecord], iVal); - pNew->nRecord += 8; - break; - } - - case SQLITE_FLOAT: { - double rVal = sqlite3_column_double(pDflt, iField); - i64 iVal = 0; - memcpy(&iVal, &rVal, sizeof(rVal)); - sessionPutI64(&pNew->aRecord[pNew->nRecord], iVal); - pNew->nRecord += 8; - break; - } - - case SQLITE_TEXT: { - int n = sqlite3_column_bytes(pDflt, iField); - const char *z = (const char*)sqlite3_column_text(pDflt, iField); - pNew->nRecord += sessionVarintPut(&pNew->aRecord[pNew->nRecord], n); - memcpy(&pNew->aRecord[pNew->nRecord], z, n); - pNew->nRecord += n; - break; - } - - case SQLITE_BLOB: { - int n = sqlite3_column_bytes(pDflt, iField); - const u8 *z = (const u8*)sqlite3_column_blob(pDflt, iField); - pNew->nRecord += sessionVarintPut(&pNew->aRecord[pNew->nRecord], n); - memcpy(&pNew->aRecord[pNew->nRecord], z, n); - pNew->nRecord += n; - break; - } - - default: - assert( eType==SQLITE_NULL ); - break; - } - - sessionFree(pSession, pOld); - *pp = pOld = pNew; - pNew->nRecordField++; - pNew->nMaxSize += nIncr; - if( pSession ){ - pSession->nMaxChangesetSize += nIncr; - } - } - } -} - -/* -** Ensure that there is room in the buffer to append nByte bytes of data. -** If not, use sqlite3_realloc() to grow the buffer so that there is. -** -** If successful, return zero. Otherwise, if an OOM condition is encountered, -** set *pRc to SQLITE_NOMEM and return non-zero. -*/ -static int sessionBufferGrow(SessionBuffer *p, i64 nByte, int *pRc){ -#define SESSION_MAX_BUFFER_SZ (0x7FFFFF00 - 1) - i64 nReq = p->nBuf + nByte; - if( *pRc==SQLITE_OK && nReq>p->nAlloc ){ - u8 *aNew; - i64 nNew = p->nAlloc ? p->nAlloc : 128; - - do { - nNew = nNew*2; - }while( nNewSESSION_MAX_BUFFER_SZ ){ - nNew = SESSION_MAX_BUFFER_SZ; - if( nNewaBuf, nNew); - if( 0==aNew ){ - *pRc = SQLITE_NOMEM; - }else{ - p->aBuf = aNew; - p->nAlloc = nNew; - } - } - return (*pRc!=SQLITE_OK); -} - - -/* -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. Otherwise, append a string to the buffer. All bytes in the string -** up to (but not including) the nul-terminator are written to the buffer. -** -** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before -** returning. -*/ -static void sessionAppendStr( - SessionBuffer *p, - const char *zStr, - int *pRc -){ - int nStr = sqlite3Strlen30(zStr); - if( 0==sessionBufferGrow(p, nStr+1, pRc) ){ - memcpy(&p->aBuf[p->nBuf], zStr, nStr); - p->nBuf += nStr; - p->aBuf[p->nBuf] = 0x00; - } -} - -/* -** Format a string using printf() style formatting and then append it to the -** buffer using sessionAppendString(). -*/ -static void sessionAppendPrintf( - SessionBuffer *p, /* Buffer to append to */ - int *pRc, - const char *zFmt, - ... -){ - if( *pRc==SQLITE_OK ){ - char *zApp = 0; - va_list ap; - va_start(ap, zFmt); - zApp = sqlite3_vmprintf(zFmt, ap); - if( zApp==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - sessionAppendStr(p, zApp, pRc); - } - va_end(ap); - sqlite3_free(zApp); - } -} - -/* -** Prepare a statement against database handle db that SELECTs a single -** row containing the default values for each column in table pTab. For -** example, if pTab is declared as: -** -** CREATE TABLE pTab(a PRIMARY KEY, b DEFAULT 123, c DEFAULT 'abcd'); -** -** Then this function prepares and returns the SQL statement: -** -** SELECT NULL, 123, 'abcd'; -*/ -static int sessionPrepareDfltStmt( - sqlite3 *db, /* Database handle */ - SessionTable *pTab, /* Table to prepare statement for */ - sqlite3_stmt **ppStmt /* OUT: Statement handle */ -){ - SessionBuffer sql = {0,0,0}; - int rc = SQLITE_OK; - const char *zSep = " "; - int ii = 0; - - *ppStmt = 0; - sessionAppendPrintf(&sql, &rc, "SELECT"); - for(ii=0; iinCol; ii++){ - const char *zDflt = pTab->azDflt[ii] ? pTab->azDflt[ii] : "NULL"; - sessionAppendPrintf(&sql, &rc, "%s%s", zSep, zDflt); - zSep = ", "; - } - if( rc==SQLITE_OK ){ - rc = sqlite3_prepare_v2(db, (const char*)sql.aBuf, -1, ppStmt, 0); - } - sqlite3_free(sql.aBuf); - - return rc; -} - -/* -** Table pTab has one or more existing change-records with old.* records -** with fewer than pTab->nCol columns. This function updates all such -** change-records with the default values for the missing columns. -*/ -static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){ - sqlite3_stmt *pStmt = 0; - int rc = pSession->rc; - - rc = sessionPrepareDfltStmt(pSession->db, pTab, &pStmt); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - int ii = 0; - SessionChange **pp = 0; - for(ii=0; iinChange; ii++){ - for(pp=&pTab->apChange[ii]; *pp; pp=&((*pp)->pNext)){ - if( (*pp)->nRecordField!=pTab->nCol ){ - sessionUpdateOneChange(pSession, &rc, pp, pTab->nCol, pStmt); - } - } - } - } - - pSession->rc = rc; - rc = sqlite3_finalize(pStmt); - if( pSession->rc==SQLITE_OK ) pSession->rc = rc; - return pSession->rc; -} - -/* -** Versions of the four methods in object SessionHook for use with the -** sqlite_stat1 table. The purpose of this is to substitute a zero-length -** blob each time a NULL value is read from the "idx" column of the -** sqlite_stat1 table. -*/ -typedef struct SessionStat1Ctx SessionStat1Ctx; -struct SessionStat1Ctx { - SessionHook hook; - sqlite3_session *pSession; -}; -static int sessionStat1Old(void *pCtx, int iCol, sqlite3_value **ppVal){ - SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; - sqlite3_value *pVal = 0; - int rc = p->hook.xOld(p->hook.pCtx, iCol, &pVal); - if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){ - pVal = p->pSession->pZeroBlob; - } - *ppVal = pVal; - return rc; -} -static int sessionStat1New(void *pCtx, int iCol, sqlite3_value **ppVal){ - SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; - sqlite3_value *pVal = 0; - int rc = p->hook.xNew(p->hook.pCtx, iCol, &pVal); - if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){ - pVal = p->pSession->pZeroBlob; - } - *ppVal = pVal; - return rc; -} -static int sessionStat1Count(void *pCtx){ - SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; - return p->hook.xCount(p->hook.pCtx); -} -static int sessionStat1Depth(void *pCtx){ - SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; - return p->hook.xDepth(p->hook.pCtx); -} - -static int sessionUpdateMaxSize( - int op, - sqlite3_session *pSession, /* Session object pTab is attached to */ - SessionTable *pTab, /* Table that change applies to */ - SessionChange *pC /* Update pC->nMaxSize */ -){ - i64 nNew = 2; - if( pC->op==SQLITE_INSERT ){ - if( pTab->bRowid ) nNew += 9; - if( op!=SQLITE_DELETE ){ - int ii; - for(ii=0; iinCol; ii++){ - sqlite3_value *p = 0; - pSession->hook.xNew(pSession->hook.pCtx, pTab->aiIdx[ii], &p); - sessionSerializeValue(0, p, &nNew); - } - } - }else if( op==SQLITE_DELETE ){ - nNew += pC->nRecord; - if( sqlite3_preupdate_blobwrite(pSession->db)>=0 ){ - nNew += pC->nRecord; - } - }else{ - int ii; - u8 *pCsr = pC->aRecord; - if( pTab->bRowid ){ - nNew += 9 + 1; - pCsr += 9; - } - for(ii=pTab->bRowid; iinCol; ii++){ - int bChanged = 1; - int nOld = 0; - int eType; - int iIdx = pTab->aiIdx[ii]; - sqlite3_value *p = 0; - pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p); - if( p==0 ){ - return SQLITE_NOMEM; - } - - eType = *pCsr++; - switch( eType ){ - case SQLITE_NULL: - bChanged = sqlite3_value_type(p)!=SQLITE_NULL; - break; - - case SQLITE_FLOAT: - case SQLITE_INTEGER: { - if( eType==sqlite3_value_type(p) ){ - sqlite3_int64 iVal = sessionGetI64(pCsr); - if( eType==SQLITE_INTEGER ){ - bChanged = (iVal!=sqlite3_value_int64(p)); - }else{ - double dVal; - memcpy(&dVal, &iVal, 8); - bChanged = (dVal!=sqlite3_value_double(p)); - } - } - nOld = 8; - pCsr += 8; - break; - } - - default: { - int nByte; - nOld = sessionVarintGet(pCsr, &nByte); - pCsr += nOld; - nOld += nByte; - assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); - if( eType==sqlite3_value_type(p) - && nByte==sqlite3_value_bytes(p) - && (nByte==0 || 0==memcmp(pCsr, sqlite3_value_blob(p), nByte)) - ){ - bChanged = 0; - } - pCsr += nByte; - break; - } - } - - if( bChanged && pTab->abPK[ii] ){ - nNew = pC->nRecord + 2; - break; - } - - if( bChanged ){ - nNew += 1 + nOld; - sessionSerializeValue(0, p, &nNew); - }else if( pTab->abPK[ii] ){ - nNew += 2 + nOld; - }else{ - nNew += 2; - } - } - } - - if( nNew>pC->nMaxSize ){ - int nIncr = nNew - pC->nMaxSize; - pC->nMaxSize = nNew; - pSession->nMaxChangesetSize += nIncr; - } - return SQLITE_OK; -} - -/* -** This function is only called from with a pre-update-hook reporting a + } + } + return (pSession->rc || pTab->abPK==0); +} + +/* +** This function is only called from with a pre-update-hook reporting a ** change on table pTab (attached to session pSession). The type of change ** (UPDATE, INSERT, DELETE) is specified by the first argument. ** ** Unless one is already present or an error occurs, an entry is added ** to the changed-rows hash table associated with table pTab. */ static void sessionPreupdateOneChange( int op, /* One of SQLITE_UPDATE, INSERT, DELETE */ - i64 iRowid, sqlite3_session *pSession, /* Session object pTab is attached to */ SessionTable *pTab /* Table that change applies to */ ){ - int iHash; - int bNull = 0; + int iHash; + int bNull = 0; int rc = SQLITE_OK; - int nExpect = 0; - SessionStat1Ctx stat1 = {{0,0,0,0,0},0}; if( pSession->rc ) return; /* Load table details if required */ - if( sessionInitTable(pSession, pTab, pSession->db, pSession->zDb) ) return; + if( sessionInitTable(pSession, pTab) ) return; - /* Check the number of columns in this xPreUpdate call matches the + /* Check the number of columns in this xPreUpdate call matches the ** number of columns in the table. */ - nExpect = pSession->hook.xCount(pSession->hook.pCtx); - if( pTab->nTotalColnTotalCol!=nExpect ){ + if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ pSession->rc = SQLITE_SCHEMA; return; } /* Grow the hash table if required */ - if( sessionGrowHash(pSession, 0, pTab) ){ + if( sessionGrowHash(0, pTab) ){ pSession->rc = SQLITE_NOMEM; return; } - if( pTab->bStat1 ){ - stat1.hook = pSession->hook; - stat1.pSession = pSession; - pSession->hook.pCtx = (void*)&stat1; - pSession->hook.xNew = sessionStat1New; - pSession->hook.xOld = sessionStat1Old; - pSession->hook.xCount = sessionStat1Count; - pSession->hook.xDepth = sessionStat1Depth; - if( pSession->pZeroBlob==0 ){ - sqlite3_value *p = sqlite3ValueNew(0); - if( p==0 ){ - rc = SQLITE_NOMEM; - goto error_out; - } - sqlite3ValueSetStr(p, 0, "", 0, SQLITE_STATIC); - pSession->pZeroBlob = p; - } - } - /* Calculate the hash-key for this change. If the primary key of the row ** includes a NULL value, exit early. Such changes are ignored by the ** session module. */ - rc = sessionPreupdateHash( - pSession, iRowid, pTab, op==SQLITE_INSERT, &iHash, &bNull - ); + rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull); if( rc!=SQLITE_OK ) goto error_out; if( bNull==0 ){ /* Search the hash table for an existing record for this row. */ SessionChange *pC; for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ - if( sessionPreupdateEqual(pSession, iRowid, pTab, pC, op) ) break; + if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break; } if( pC==0 ){ /* Create a new change object containing all the old values (if ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK ** values (if this is an INSERT). */ - sqlite3_int64 nByte; /* Number of bytes to allocate */ + SessionChange *pChange; /* New change object */ + int nByte; /* Number of bytes to allocate */ int i; /* Used to iterate through columns */ - + assert( rc==SQLITE_OK ); pTab->nEntry++; - + /* Figure out how large an allocation is required */ nByte = sizeof(SessionChange); - for(i=pTab->bRowid; inCol; i++){ - int iIdx = pTab->aiIdx[i]; + for(i=0; inCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ - /* This may fail if the column has a non-NULL default and was added - ** using ALTER TABLE ADD COLUMN after this record was created. */ - rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p); + TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); + assert( trc==SQLITE_OK ); }else if( pTab->abPK[i] ){ - TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx,iIdx,&p); + TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); assert( trc==SQLITE_OK ); } - if( rc==SQLITE_OK ){ - /* This may fail if SQLite value p contains a utf-16 string that must - ** be converted to utf-8 and an OOM error occurs while doing so. */ - rc = sessionSerializeValue(0, p, &nByte); - } + /* This may fail if SQLite value p contains a utf-16 string that must + ** be converted to utf-8 and an OOM error occurs while doing so. */ + rc = sessionSerializeValue(0, p, &nByte); if( rc!=SQLITE_OK ) goto error_out; } - if( pTab->bRowid ){ - nByte += 9; /* Size of rowid field - an integer */ - } - + /* Allocate the change object */ - pC = (SessionChange*)sessionMalloc64(pSession, nByte); - if( !pC ){ + pChange = (SessionChange *)sqlite3_malloc(nByte); + if( !pChange ){ rc = SQLITE_NOMEM; goto error_out; }else{ - memset(pC, 0, sizeof(SessionChange)); - pC->aRecord = (u8 *)&pC[1]; + memset(pChange, 0, sizeof(SessionChange)); + pChange->aRecord = (u8 *)&pChange[1]; } - + /* Populate the change object. None of the preupdate_old(), ** preupdate_new() or SerializeValue() calls below may fail as all ** required values and encodings have already been cached in memory. ** It is not possible for an OOM to occur in this block. */ nByte = 0; - if( pTab->bRowid ){ - pC->aRecord[0] = SQLITE_INTEGER; - sessionPutI64(&pC->aRecord[1], iRowid); - nByte = 9; - } - for(i=pTab->bRowid; inCol; i++){ + for(i=0; inCol; i++){ sqlite3_value *p = 0; - int iIdx = pTab->aiIdx[i]; if( op!=SQLITE_INSERT ){ - pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p); + pSession->hook.xOld(pSession->hook.pCtx, i, &p); }else if( pTab->abPK[i] ){ - pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p); + pSession->hook.xNew(pSession->hook.pCtx, i, &p); } - sessionSerializeValue(&pC->aRecord[nByte], p, &nByte); + sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); } /* Add the change to the hash-table */ if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){ - pC->bIndirect = 1; + pChange->bIndirect = 1; } - pC->nRecordField = pTab->nCol; - pC->nRecord = nByte; - pC->op = op; - pC->pNext = pTab->apChange[iHash]; - pTab->apChange[iHash] = pC; + pChange->nRecord = nByte; + pChange->op = op; + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; }else if( pC->bIndirect ){ /* If the existing change is considered "indirect", but this current ** change is "direct", mark the change object as direct. */ - if( pSession->hook.xDepth(pSession->hook.pCtx)==0 - && pSession->bIndirect==0 + if( pSession->hook.xDepth(pSession->hook.pCtx)==0 + && pSession->bIndirect==0 ){ pC->bIndirect = 0; } } - - assert( rc==SQLITE_OK ); - if( pSession->bEnableSize ){ - rc = sessionUpdateMaxSize(op, pSession, pTab, pC); - } } - /* If an error has occurred, mark the session object as failed. */ error_out: - if( pTab->bStat1 ){ - pSession->hook = stat1.hook; - } if( rc!=SQLITE_OK ){ pSession->rc = rc; } } static int sessionFindTable( - sqlite3_session *pSession, + sqlite3_session *pSession, const char *zName, SessionTable **ppTab ){ int rc = SQLITE_OK; int nName = sqlite3Strlen30(zName); @@ -228612,19 +177077,15 @@ if( pRet==0 && pSession->bAutoAttach ){ /* If there is a table-filter configured, invoke it. If it returns 0, ** do not automatically add the new table. */ if( pSession->xTableFilter==0 - || pSession->xTableFilter(pSession->pFilterCtx, zName) + || pSession->xTableFilter(pSession->pFilterCtx, zName) ){ rc = sqlite3session_attach(pSession, zName); if( rc==SQLITE_OK ){ - pRet = pSession->pTable; - while( ALWAYS(pRet) && pRet->pNext ){ - pRet = pRet->pNext; - } - assert( pRet!=0 ); + for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext); assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ); } } } @@ -228647,30 +177108,27 @@ ){ sqlite3_session *pSession; int nDb = sqlite3Strlen30(zDb); assert( sqlite3_mutex_held(db->mutex) ); - (void)iKey1; - (void)iKey2; for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ SessionTable *pTab; - /* If this session is attached to a different database ("main", "temp" - ** etc.), or if it is not currently enabled, there is nothing to do. Skip + /* If this session is attached to a different database ("main", "temp" + ** etc.), or if it is not currently enabled, there is nothing to do. Skip ** to the next session object attached to this database. */ if( pSession->bEnable==0 ) continue; if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; pSession->rc = sessionFindTable(pSession, zName, &pTab); if( pTab ){ assert( pSession->rc==SQLITE_OK ); - assert( op==SQLITE_UPDATE || iKey1==iKey2 ); - sessionPreupdateOneChange(op, iKey1, pSession, pTab); + sessionPreupdateOneChange(op, pSession, pTab); if( op==SQLITE_UPDATE ){ - sessionPreupdateOneChange(SQLITE_INSERT, iKey2, pSession, pTab); + sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); } } } } @@ -228705,33 +177163,31 @@ } typedef struct SessionDiffCtx SessionDiffCtx; struct SessionDiffCtx { sqlite3_stmt *pStmt; - int bRowid; int nOldOff; }; /* ** The diff hook implementations. */ static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; - *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff+p->bRowid); + *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff); return SQLITE_OK; } static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; - *ppVal = sqlite3_column_value(p->pStmt, iVal+p->bRowid); + *ppVal = sqlite3_column_value(p->pStmt, iVal); return SQLITE_OK; } static int sessionDiffCount(void *pCtx){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; - return (p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt)) - p->bRowid; + return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt); } static int sessionDiffDepth(void *pCtx){ - (void)pCtx; return 0; } /* ** Install the diff hooks on the session object passed as the only @@ -228748,11 +177204,11 @@ pSession->hook.xDepth = sessionDiffDepth; } static char *sessionExprComparePK( int nCol, - const char *zDb1, const char *zDb2, + const char *zDb1, const char *zDb2, const char *zTab, const char **azCol, u8 *abPK ){ int i; const char *zSep = ""; @@ -228771,11 +177227,11 @@ return zRet; } static char *sessionExprCompareOther( int nCol, - const char *zDb1, const char *zDb2, + const char *zDb1, const char *zDb2, const char *zTab, const char **azCol, u8 *abPK ){ int i; const char *zSep = ""; @@ -228801,22 +177257,21 @@ return zRet; } static char *sessionSelectFindNew( + int nCol, const char *zDb1, /* Pick rows in this db only */ const char *zDb2, /* But not in this one */ - int bRowid, const char *zTbl, /* Table name */ const char *zExpr ){ - const char *zSel = (bRowid ? SESSIONS_ROWID ", *" : "*"); char *zRet = sqlite3_mprintf( - "SELECT %s FROM \"%w\".\"%w\" WHERE NOT EXISTS (" + "SELECT * FROM \"%w\".\"%w\" WHERE NOT EXISTS (" " SELECT 1 FROM \"%w\".\"%w\" WHERE %s" ")", - zSel, zDb1, zTbl, zDb2, zTbl, zExpr + zDb1, zTbl, zDb2, zTbl, zExpr ); return zRet; } static int sessionDiffFindNew( @@ -228826,13 +177281,11 @@ const char *zDb1, const char *zDb2, char *zExpr ){ int rc = SQLITE_OK; - char *zStmt = sessionSelectFindNew( - zDb1, zDb2, pTab->bRowid, pTab->zName, zExpr - ); + char *zStmt = sessionSelectFindNew(pTab->nCol, zDb1, zDb2, pTab->zName,zExpr); if( zStmt==0 ){ rc = SQLITE_NOMEM; }else{ sqlite3_stmt *pStmt; @@ -228839,48 +177292,25 @@ rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); if( rc==SQLITE_OK ){ SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; pDiffCtx->pStmt = pStmt; pDiffCtx->nOldOff = 0; - pDiffCtx->bRowid = pTab->bRowid; while( SQLITE_ROW==sqlite3_step(pStmt) ){ - i64 iRowid = (pTab->bRowid ? sqlite3_column_int64(pStmt, 0) : 0); - sessionPreupdateOneChange(op, iRowid, pSession, pTab); + sessionPreupdateOneChange(op, pSession, pTab); } rc = sqlite3_finalize(pStmt); } sqlite3_free(zStmt); } return rc; } -/* -** Return a comma-separated list of the fully-qualified (with both database -** and table name) column names from table pTab. e.g. -** -** "main"."t1"."a", "main"."t1"."b", "main"."t1"."c" -*/ -static char *sessionAllCols( - const char *zDb, - SessionTable *pTab -){ - int ii; - char *zRet = 0; - for(ii=0; iinCol; ii++){ - zRet = sqlite3_mprintf("%z%s\"%w\".\"%w\".\"%w\"", - zRet, (zRet ? ", " : ""), zDb, pTab->zName, pTab->azCol[ii] - ); - if( !zRet ) break; - } - return zRet; -} - static int sessionDiffFindModified( - sqlite3_session *pSession, - SessionTable *pTab, - const char *zFrom, + sqlite3_session *pSession, + SessionTable *pTab, + const char *zFrom, const char *zExpr ){ int rc = SQLITE_OK; char *zExpr2 = sessionExprCompareOther(pTab->nCol, @@ -228887,17 +177317,15 @@ pSession->zDb, zFrom, pTab->zName, pTab->azCol, pTab->abPK ); if( zExpr2==0 ){ rc = SQLITE_NOMEM; }else{ - char *z1 = sessionAllCols(pSession->zDb, pTab); - char *z2 = sessionAllCols(zFrom, pTab); char *zStmt = sqlite3_mprintf( - "SELECT %s,%s FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", - z1, z2, pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 + "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", + pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 ); - if( zStmt==0 || z1==0 || z2==0 ){ + if( zStmt==0 ){ rc = SQLITE_NOMEM; }else{ sqlite3_stmt *pStmt; rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); @@ -228904,19 +177332,16 @@ if( rc==SQLITE_OK ){ SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; pDiffCtx->pStmt = pStmt; pDiffCtx->nOldOff = pTab->nCol; while( SQLITE_ROW==sqlite3_step(pStmt) ){ - i64 iRowid = (pTab->bRowid ? sqlite3_column_int64(pStmt, 0) : 0); - sessionPreupdateOneChange(SQLITE_UPDATE, iRowid, pSession, pTab); + sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab); } rc = sqlite3_finalize(pStmt); } + sqlite3_free(zStmt); } - sqlite3_free(zStmt); - sqlite3_free(z1); - sqlite3_free(z2); } return rc; } @@ -228941,27 +177366,23 @@ SessionTable *pTo; /* Table zTbl */ /* Locate and if necessary initialize the target table object */ rc = sessionFindTable(pSession, zTbl, &pTo); if( pTo==0 ) goto diff_out; - if( sessionInitTable(pSession, pTo, pSession->db, pSession->zDb) ){ + if( sessionInitTable(pSession, pTo) ){ rc = pSession->rc; goto diff_out; } /* Check the table schemas match */ if( rc==SQLITE_OK ){ int bHasPk = 0; int bMismatch = 0; int nCol; /* Columns in zFrom.zTbl */ - int bRowid = 0; u8 *abPK; const char **azCol = 0; - rc = sessionTableInfo(0, db, zFrom, zTbl, - &nCol, 0, 0, &azCol, 0, 0, &abPK, - pSession->bImplicitPK ? &bRowid : 0 - ); + rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); if( rc==SQLITE_OK ){ if( pTo->nCol!=nCol ){ bMismatch = 1; }else{ int i; @@ -228969,26 +177390,25 @@ if( pTo->abPK[i]!=abPK[i] ) bMismatch = 1; if( sqlite3_stricmp(azCol[i], pTo->azCol[i]) ) bMismatch = 1; if( abPK[i] ) bHasPk = 1; } } + } sqlite3_free((char*)azCol); if( bMismatch ){ - if( pzErrMsg ){ - *pzErrMsg = sqlite3_mprintf("table schemas do not match"); - } + *pzErrMsg = sqlite3_mprintf("table schemas do not match"); rc = SQLITE_SCHEMA; } if( bHasPk==0 ){ /* Ignore tables with no primary keys */ goto diff_out; } } if( rc==SQLITE_OK ){ - zExpr = sessionExprComparePK(pTo->nCol, + zExpr = sessionExprComparePK(pTo->nCol, zDb, zFrom, pTo->zName, pTo->azCol, pTo->abPK ); } /* Find new rows */ @@ -229030,20 +177450,20 @@ /* Zero the output value in case an error occurs. */ *ppSession = 0; /* Allocate and populate the new session object. */ - pNew = (sqlite3_session *)sqlite3_malloc64(sizeof(sqlite3_session) + nDb + 1); + pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1); if( !pNew ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(sqlite3_session)); pNew->db = db; pNew->zDb = (char *)&pNew[1]; pNew->bEnable = 1; memcpy(pNew->zDb, zDb, nDb+1); sessionPreupdateHooks(pNew); - /* Add the new session object to the linked list of session objects + /* Add the new session object to the linked list of session objects ** attached to database handle $db. Do this under the cover of the db ** handle mutex. */ sqlite3_mutex_enter(sqlite3_db_mutex(db)); pOld = (sqlite3_session*)sqlite3_preupdate_hook(db, xPreUpdate, (void*)pNew); pNew->pNext = pOld; @@ -229055,11 +177475,11 @@ /* ** Free the list of table objects passed as the first argument. The contents ** of the changed-rows hash tables are also deleted. */ -static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){ +static void sessionDeleteTable(SessionTable *pList){ SessionTable *pNext; SessionTable *pTab; for(pTab=pList; pTab; pTab=pNext){ int i; @@ -229067,17 +177487,16 @@ for(i=0; inChange; i++){ SessionChange *p; SessionChange *pNextChange; for(p=pTab->apChange[i]; p; p=pNextChange){ pNextChange = p->pNext; - sessionFree(pSession, p); + sqlite3_free(p); } } - sqlite3_finalize(pTab->pDfltStmt); - sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */ - sessionFree(pSession, pTab->apChange); - sessionFree(pSession, pTab); + sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */ + sqlite3_free(pTab->apChange); + sqlite3_free(pTab); } } /* ** Delete a session object previously allocated using sqlite3session_create(). @@ -229097,25 +177516,24 @@ if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void*)pHead); break; } } sqlite3_mutex_leave(sqlite3_db_mutex(db)); - sqlite3ValueFree(pSession->pZeroBlob); - /* Delete all attached table objects. And the contents of their + /* Delete all attached table objects. And the contents of their ** associated hash-tables. */ - sessionDeleteTable(pSession, pSession->pTable); + sessionDeleteTable(pSession->pTable); - /* Free the session object. */ + /* Free the session object itself. */ sqlite3_free(pSession); } /* ** Set a table filter on a Session Object. */ SQLITE_API void sqlite3session_table_filter( - sqlite3_session *pSession, + sqlite3_session *pSession, int(*xFilter)(void*, const char*), void *pCtx /* First argument passed to xFilter */ ){ pSession->bAutoAttach = 1; pSession->pFilterCtx = pCtx; @@ -229150,17 +177568,16 @@ if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; } if( !pTab ){ /* Allocate new SessionTable object. */ - int nByte = sizeof(SessionTable) + nName + 1; - pTab = (SessionTable*)sessionMalloc64(pSession, nByte); + pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); if( !pTab ){ rc = SQLITE_NOMEM; }else{ /* Populate the new SessionTable object and link it into the list. - ** The new object must be linked onto the end of the list, not + ** The new object must be linked onto the end of the list, not ** simply added to the start of it in order to ensure that tables ** appear in the correct order when a changeset or patchset is ** eventually generated. */ SessionTable **ppTab; memset(pTab, 0, sizeof(SessionTable)); @@ -229173,10 +177590,36 @@ } sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); return rc; } + +/* +** Ensure that there is room in the buffer to append nByte bytes of data. +** If not, use sqlite3_realloc() to grow the buffer so that there is. +** +** If successful, return zero. Otherwise, if an OOM condition is encountered, +** set *pRc to SQLITE_NOMEM and return non-zero. +*/ +static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ + if( *pRc==SQLITE_OK && p->nAlloc-p->nBufnAlloc ? p->nAlloc : 128; + do { + nNew = nNew*2; + }while( nNew<(p->nBuf+nByte) ); + + aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); + if( 0==aNew ){ + *pRc = SQLITE_NOMEM; + }else{ + p->aBuf = aNew; + p->nAlloc = nNew; + } + } + return (*pRc!=SQLITE_OK); +} /* ** Append the value passed as the second argument to the buffer passed ** as the first. ** @@ -229185,11 +177628,11 @@ ** before returning. */ static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){ int rc = *pRc; if( rc==SQLITE_OK ){ - sqlite3_int64 nByte = 0; + int nByte = 0; rc = sessionSerializeValue(0, pVal, &nByte); sessionBufferGrow(p, nByte, &rc); if( rc==SQLITE_OK ){ rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0); p->nBuf += nByte; @@ -229198,12 +177641,12 @@ } } } /* -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. Otherwise, append a single byte to the buffer. +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a single byte to the buffer. ** ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. */ static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ @@ -229211,12 +177654,12 @@ p->aBuf[p->nBuf++] = v; } } /* -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. Otherwise, append a single varint to the buffer. +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a single varint to the buffer. ** ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. */ static void sessionAppendVarint(SessionBuffer *p, int v, int *pRc){ @@ -229224,30 +177667,50 @@ p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); } } /* -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. Otherwise, append a blob of data to the buffer. +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a blob of data to the buffer. ** ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. */ static void sessionAppendBlob( - SessionBuffer *p, - const u8 *aBlob, - int nBlob, + SessionBuffer *p, + const u8 *aBlob, + int nBlob, int *pRc ){ if( nBlob>0 && 0==sessionBufferGrow(p, nBlob, pRc) ){ memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); p->nBuf += nBlob; } } /* -** This function is a no-op if *pRc is other than SQLITE_OK when it is +** This function is a no-op if *pRc is other than SQLITE_OK when it is +** called. Otherwise, append a string to the buffer. All bytes in the string +** up to (but not including) the nul-terminator are written to the buffer. +** +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before +** returning. +*/ +static void sessionAppendStr( + SessionBuffer *p, + const char *zStr, + int *pRc +){ + int nStr = sqlite3Strlen30(zStr); + if( 0==sessionBufferGrow(p, nStr, pRc) ){ + memcpy(&p->aBuf[p->nBuf], zStr, nStr); + p->nBuf += nStr; + } +} + +/* +** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append the string representation of integer iVal ** to the buffer. No nul-terminator is written. ** ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. @@ -229261,13 +177724,13 @@ sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); sessionAppendStr(p, aBuf, pRc); } /* -** This function is a no-op if *pRc is other than SQLITE_OK when it is +** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append the string zStr enclosed in quotes (") and -** with any embedded quote characters escaped to the buffer. No +** with any embedded quote characters escaped to the buffer. No ** nul-terminator byte is written. ** ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. */ @@ -229274,11 +177737,11 @@ static void sessionAppendIdent( SessionBuffer *p, /* Buffer to a append to */ const char *zStr, /* String to quote, escape and append */ int *pRc /* IN/OUT: Error code */ ){ - int nStr = sqlite3Strlen30(zStr)*2 + 2 + 2; + int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1; if( 0==sessionBufferGrow(p, nStr, pRc) ){ char *zOut = (char *)&p->aBuf[p->nBuf]; const char *zIn = zStr; *zOut++ = '"'; while( *zIn ){ @@ -229285,11 +177748,10 @@ if( *zIn=='"' ) *zOut++ = '"'; *zOut++ = *(zIn++); } *zOut++ = '"'; p->nBuf = (int)((u8 *)zOut - p->aBuf); - p->aBuf[p->nBuf] = 0x00; } } /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is @@ -229337,12 +177799,12 @@ } } /* ** -** This function appends an update change to the buffer (see the comments -** under "CHANGESET FORMAT" at the top of the file). An update change +** This function appends an update change to the buffer (see the comments +** under "CHANGESET FORMAT" at the top of the file). An update change ** consists of: ** ** 1 byte: SQLITE_UPDATE (0x17) ** n bytes: old.* record (see RECORD FORMAT) ** m bytes: new.* record (see RECORD FORMAT) @@ -229353,14 +177815,14 @@ ** at the current version of the row (the new.* values). ** ** If all of the old.* values are equal to their corresponding new.* value ** (i.e. nothing has changed), then no data at all is appended to the buffer. ** -** Otherwise, the old.* record contains all primary key values and the -** original values of any fields that have been modified. The new.* record +** Otherwise, the old.* record contains all primary key values and the +** original values of any fields that have been modified. The new.* record ** contains the new values of only those fields that have been modified. -*/ +*/ static int sessionAppendUpdate( SessionBuffer *pBuf, /* Buffer to append to */ int bPatchset, /* True for "patchset", 0 for "changeset" */ sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ SessionChange *p, /* Object containing old values */ @@ -229371,11 +177833,10 @@ int bNoop = 1; /* Set to zero if any values are modified */ int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */ int i; /* Used to iterate through columns */ u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ - assert( abPK!=0 ); sessionAppendByte(pBuf, SQLITE_UPDATE, &rc); sessionAppendByte(pBuf, p->bIndirect, &rc); for(i=0; i FROM zDb.zTab WHERE (pk1, pk2,...) IS (?1, ?2,...) -** -** where is: -** -** 1 AND (?A OR ?1 IS ) AND ... -** -** for each non-pk . +** SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ... */ static int sessionSelectStmt( sqlite3 *db, /* Database handle */ - int bIgnoreNoop, const char *zDb, /* Database name */ const char *zTab, /* Table name */ - int bRowid, int nCol, /* Number of columns in table */ const char **azCol, /* Names of table columns */ u8 *abPK, /* PRIMARY KEY array */ sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ ){ int rc = SQLITE_OK; - char *zSql = 0; - const char *zSep = ""; - int nSql = -1; - int i; - - SessionBuffer cols = {0, 0, 0}; - SessionBuffer nooptest = {0, 0, 0}; - SessionBuffer pkfield = {0, 0, 0}; - SessionBuffer pkvar = {0, 0, 0}; - - sessionAppendStr(&nooptest, ", 1", &rc); - - if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){ - sessionAppendStr(&nooptest, " AND (?6 OR ?3 IS stat)", &rc); - sessionAppendStr(&pkfield, "tbl, idx", &rc); - sessionAppendStr(&pkvar, - "?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc - ); - sessionAppendStr(&cols, "tbl, ?2, stat", &rc); - }else{ - #if 0 - if( bRowid ){ - sessionAppendStr(&cols, SESSIONS_ROWID, &rc); - } - #endif - for(i=0; idb; /* Source database handle */ SessionTable *pTab; /* Used to iterate through attached tables */ SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ int rc; /* Return code */ - assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) ); - assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) ); + assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) ); /* Zero the output variables in case an error occurs. If this session ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), ** this call will be a no-op. */ if( xOutput==0 ){ - assert( pnChangeset!=0 && ppChangeset!=0 ); *pnChangeset = 0; *ppChangeset = 0; } if( pSession->rc ) return pSession->rc; @@ -229758,64 +178142,64 @@ sqlite3_mutex_enter(sqlite3_db_mutex(db)); for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ const char *zName = pTab->zName; + int nCol; /* Number of columns in table */ + u8 *abPK; /* Primary key array */ + const char **azCol = 0; /* Table columns */ int i; /* Used to iterate through hash buckets */ sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ int nRewind = buf.nBuf; /* Initial size of write buffer */ int nNoop; /* Size of buffer after writing tbl header */ - int nOldCol = pTab->nCol; /* Check the table schema is still Ok. */ - rc = sessionReinitTable(pSession, pTab); - if( rc==SQLITE_OK && pTab->nCol!=nOldCol ){ - rc = sessionUpdateChanges(pSession, pTab); + rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK); + if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){ + rc = SQLITE_SCHEMA; } /* Write a table header */ sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ - rc = sessionSelectStmt(db, 0, pSession->zDb, - zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel - ); + rc = sessionSelectStmt( + db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); } nNoop = buf.nBuf; for(i=0; inChange && rc==SQLITE_OK; i++){ SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - rc = sessionSelectBind(pSel, pTab->nCol, pTab->abPK, p); + rc = sessionSelectBind(pSel, nCol, abPK, p); if( rc!=SQLITE_OK ) continue; if( sqlite3_step(pSel)==SQLITE_ROW ){ if( p->op==SQLITE_INSERT ){ int iCol; sessionAppendByte(&buf, SQLITE_INSERT, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); - for(iCol=0; iColnCol; iCol++){ + for(iCol=0; iColabPK!=0 ); - rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, pTab->abPK); + rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK); } }else if( p->op!=SQLITE_INSERT ){ - rc = sessionAppendDelete(&buf, bPatchset, p, pTab->nCol,pTab->abPK); + rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK); } if( rc==SQLITE_OK ){ rc = sqlite3_reset(pSel); } - /* If the buffer is now larger than sessions_strm_chunk_size, pass + /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass ** its contents to the xOutput() callback. */ - if( xOutput - && rc==SQLITE_OK - && buf.nBuf>nNoop - && buf.nBuf>sessions_strm_chunk_size + if( xOutput + && rc==SQLITE_OK + && buf.nBuf>nNoop + && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); nNoop = -1; buf.nBuf = 0; } @@ -229825,10 +178209,11 @@ sqlite3_finalize(pSel); if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } + sqlite3_free((char*)azCol); /* cast works around VC++ bug */ } } if( rc==SQLITE_OK ){ if( xOutput==0 ){ @@ -229845,29 +178230,22 @@ sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } /* -** Obtain a changeset object containing all changes recorded by the +** Obtain a changeset object containing all changes recorded by the ** session object passed as the first argument. ** -** It is the responsibility of the caller to eventually free the buffer +** It is the responsibility of the caller to eventually free the buffer ** using sqlite3_free(). */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ){ - int rc; - - if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE; - rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset); - assert( rc || pnChangeset==0 - || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize - ); - return rc; + return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset); } /* ** Streaming version of sqlite3session_changeset(). */ @@ -229874,11 +178252,10 @@ SQLITE_API int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ){ - if( xOutput==0 ) return SQLITE_MISUSE; return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0); } /* ** Streaming version of sqlite3session_patchset(). @@ -229886,27 +178263,25 @@ SQLITE_API int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ){ - if( xOutput==0 ) return SQLITE_MISUSE; return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0); } /* -** Obtain a patchset object containing all changes recorded by the +** Obtain a patchset object containing all changes recorded by the ** session object passed as the first argument. ** -** It is the responsibility of the caller to eventually free the buffer +** It is the responsibility of the caller to eventually free the buffer ** using sqlite3_free(). */ SQLITE_API int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ void **ppPatchset /* OUT: Buffer containing changeset */ ){ - if( pnPatchset==0 || ppPatchset==0 ) return SQLITE_MISUSE; return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset); } /* ** Enable or disable the session object passed as the first argument. @@ -229951,74 +178326,19 @@ sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); return (ret==0); } -/* -** Return the amount of heap memory in use. -*/ -SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){ - return pSession->nMalloc; -} - -/* -** Configure the session object passed as the first argument. -*/ -SQLITE_API int sqlite3session_object_config(sqlite3_session *pSession, int op, void *pArg){ - int rc = SQLITE_OK; - switch( op ){ - case SQLITE_SESSION_OBJCONFIG_SIZE: { - int iArg = *(int*)pArg; - if( iArg>=0 ){ - if( pSession->pTable ){ - rc = SQLITE_MISUSE; - }else{ - pSession->bEnableSize = (iArg!=0); - } - } - *(int*)pArg = pSession->bEnableSize; - break; - } - - case SQLITE_SESSION_OBJCONFIG_ROWID: { - int iArg = *(int*)pArg; - if( iArg>=0 ){ - if( pSession->pTable ){ - rc = SQLITE_MISUSE; - }else{ - pSession->bImplicitPK = (iArg!=0); - } - } - *(int*)pArg = pSession->bImplicitPK; - break; - } - - default: - rc = SQLITE_MISUSE; - } - - return rc; -} - -/* -** Return the maximum size of sqlite3session_changeset() output. -*/ -SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession){ - return pSession->nMaxChangesetSize; -} - /* ** Do the work for either sqlite3changeset_start() or start_strm(). */ static int sessionChangesetStart( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int nChangeset, /* Size of buffer pChangeset in bytes */ - void *pChangeset, /* Pointer to buffer containing changeset */ - int bInvert, /* True to invert changeset */ - int bSkipEmpty /* True to skip empty UPDATE changes */ + void *pChangeset /* Pointer to buffer containing changeset */ ){ sqlite3_changeset_iter *pRet; /* Iterator to return */ int nByte; /* Number of bytes to allocate for iterator */ assert( xInput==0 || (pChangeset==0 && nChangeset==0) ); @@ -230034,12 +178354,10 @@ pRet->in.aData = (u8 *)pChangeset; pRet->in.nData = nChangeset; pRet->in.xInput = xInput; pRet->in.pIn = pIn; pRet->in.bEof = (xInput ? 0 : 1); - pRet->bInvert = bInvert; - pRet->bSkipEmpty = bSkipEmpty; /* Populate the output variable and return success. */ *pp = pRet; return SQLITE_OK; } @@ -230050,20 +178368,11 @@ SQLITE_API int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ int nChangeset, /* Size of buffer pChangeset in bytes */ void *pChangeset /* Pointer to buffer containing changeset */ ){ - return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0, 0); -} -SQLITE_API int sqlite3changeset_start_v2( - sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ - int nChangeset, /* Size of buffer pChangeset in bytes */ - void *pChangeset, /* Pointer to buffer containing changeset */ - int flags -){ - int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); - return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert, 0); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); } /* ** Streaming version of sqlite3changeset_start(). */ @@ -230070,28 +178379,19 @@ SQLITE_API int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ){ - return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0, 0); -} -SQLITE_API int sqlite3changeset_start_v2_strm( - sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int flags -){ - int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); - return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert, 0); + return sessionChangesetStart(pp, xInput, pIn, 0, 0); } /* ** If the SessionInput object passed as the only argument is a streaming ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ - if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){ + if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); } @@ -230110,11 +178410,11 @@ */ static int sessionInputBuffer(SessionInput *pIn, int nByte){ int rc = SQLITE_OK; if( pIn->xInput ){ while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ - int nNew = sessions_strm_chunk_size; + int nNew = SESSIONS_STRM_CHUNK_SIZE; if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew); if( nNew==0 ){ @@ -230156,11 +178456,11 @@ *ppRec = aRec; } /* ** This function sets the value of the sqlite3_value object passed as the -** first argument to a copy of the string or blob held in the aData[] +** first argument to a copy of the string or blob held in the aData[] ** buffer. SQLITE_OK is returned if successful, or SQLITE_NOMEM if an OOM ** error occurs. */ static int sessionValueSetStr( sqlite3_value *pVal, /* Set the value of this object */ @@ -230167,14 +178467,14 @@ u8 *aData, /* Buffer containing string or blob data */ int nData, /* Size of buffer aData[] in bytes */ u8 enc /* String encoding (0 for blobs) */ ){ /* In theory this code could just pass SQLITE_TRANSIENT as the final - ** argument to sqlite3ValueSetStr() and have the copy created + ** argument to sqlite3ValueSetStr() and have the copy created ** automatically. But doing so makes it difficult to detect any OOM ** error. Hence the code to create the copy externally. */ - u8 *aCopy = sqlite3_malloc64((sqlite3_int64)nData+1); + u8 *aCopy = sqlite3_malloc(nData+1); if( aCopy==0 ) return SQLITE_NOMEM; memcpy(aCopy, aData, nData); sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free); return SQLITE_OK; } @@ -230205,66 +178505,51 @@ */ static int sessionReadRecord( SessionInput *pIn, /* Input data */ int nCol, /* Number of values in record */ u8 *abPK, /* Array of primary key flags, or NULL */ - sqlite3_value **apOut, /* Write values to this array */ - int *pbEmpty + sqlite3_value **apOut /* Write values to this array */ ){ int i; /* Used to iterate through columns */ int rc = SQLITE_OK; - assert( pbEmpty==0 || *pbEmpty==0 ); - if( pbEmpty ) *pbEmpty = 1; for(i=0; iiNext>=pIn->nData ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - eType = pIn->aData[pIn->iNext++]; - assert( apOut[i]==0 ); - if( eType ){ - if( pbEmpty ) *pbEmpty = 0; - apOut[i] = sqlite3ValueNew(0); - if( !apOut[i] ) rc = SQLITE_NOMEM; - } - } + eType = pIn->aData[pIn->iNext++]; + } + + assert( apOut[i]==0 ); + if( eType ){ + apOut[i] = sqlite3ValueNew(0); + if( !apOut[i] ) rc = SQLITE_NOMEM; } if( rc==SQLITE_OK ){ u8 *aVal = &pIn->aData[pIn->iNext]; if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ int nByte; pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); if( rc==SQLITE_OK ){ - if( nByte<0 || nByte>pIn->nData-pIn->iNext ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); - rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); - pIn->iNext += nByte; - } - } + u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); + rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); + } + pIn->iNext += nByte; } if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ - if( (pIn->nData-pIn->iNext)<8 ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - sqlite3_int64 v = sessionGetI64(aVal); - if( eType==SQLITE_INTEGER ){ - sqlite3VdbeMemSetInt64(apOut[i], v); - }else{ - double d; - memcpy(&d, &v, 8); - sqlite3VdbeMemSetDouble(apOut[i], d); - } - pIn->iNext += 8; - } + sqlite3_int64 v = sessionGetI64(aVal); + if( eType==SQLITE_INTEGER ){ + sqlite3VdbeMemSetInt64(apOut[i], v); + }else{ + double d; + memcpy(&d, &v, 8); + sqlite3VdbeMemSetDouble(apOut[i], d); + } + pIn->iNext += 8; } } } return rc; @@ -230276,11 +178561,11 @@ ** ** + number of columns in table (varint) ** + array of PK flags (1 byte per column), ** + table name (nul terminated). ** -** This function ensures that all of the above is present in the input +** This function ensures that all of the above is present in the input ** buffer (i.e. that it can be accessed without any calls to xInput()). ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. ** The input pointer is not moved. */ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ @@ -230289,23 +178574,12 @@ int nRead = 0; rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); - /* The hard upper limit for the number of columns in an SQLite - ** database table is, according to sqliteLimit.h, 32676. So - ** consider any table-header that purports to have more than 65536 - ** columns to be corrupt. This is convenient because otherwise, - ** if the (nCol>65536) condition below were omitted, a sufficiently - ** large value for nCol may cause nRead to wrap around and become - ** negative. Leading to a crash. */ - if( nCol<0 || nCol>65536 ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = sessionInputBuffer(pIn, nRead+nCol+100); - nRead += nCol; - } + rc = sessionInputBuffer(pIn, nRead+nCol+100); + nRead += nCol; } while( rc==SQLITE_OK ){ while( (pIn->iNext + nRead)nData && pIn->aData[pIn->iNext + nRead] ){ nRead++; @@ -230359,12 +178633,12 @@ ** ** + number of columns in table (varint) ** + array of PK flags (1 byte per column), ** + table name (nul terminated). ** -** This function decodes the table-header and populates the p->nCol, -** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is +** This function decodes the table-header and populates the p->nCol, +** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is ** also allocated or resized according to the new value of p->nCol. The ** input pointer is left pointing to the byte following the table header. ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code ** is returned and the final values of the various fields enumerated above @@ -230378,61 +178652,55 @@ rc = sessionChangesetBufferTblhdr(&p->in, &nCopy); if( rc==SQLITE_OK ){ int nByte; int nVarint; nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); - if( p->nCol>0 ){ - nCopy -= nVarint; - p->in.iNext += nVarint; - nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; - p->tblhdr.nBuf = 0; - sessionBufferGrow(&p->tblhdr, nByte, &rc); - }else{ - rc = SQLITE_CORRUPT_BKPT; - } + nCopy -= nVarint; + p->in.iNext += nVarint; + nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; + p->tblhdr.nBuf = 0; + sessionBufferGrow(&p->tblhdr, nByte, &rc); } if( rc==SQLITE_OK ){ - size_t iPK = sizeof(sqlite3_value*)*p->nCol*2; + int iPK = sizeof(sqlite3_value*)*p->nCol*2; memset(p->tblhdr.aBuf, 0, iPK); memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy); p->in.iNext += nCopy; } p->apValue = (sqlite3_value**)p->tblhdr.aBuf; - if( p->apValue==0 ){ - p->abPK = 0; - p->zTab = 0; - }else{ - p->abPK = (u8*)&p->apValue[p->nCol*2]; - p->zTab = p->abPK ? (char*)&p->abPK[p->nCol] : 0; - } + p->abPK = (u8*)&p->apValue[p->nCol*2]; + p->zTab = (char*)&p->abPK[p->nCol]; return (p->rc = rc); } /* -** Advance the changeset iterator to the next change. The differences between -** this function and sessionChangesetNext() are that -** -** * If pbEmpty is not NULL and the change is a no-op UPDATE (an UPDATE -** that modifies no columns), this function sets (*pbEmpty) to 1. -** -** * If the iterator is configured to skip no-op UPDATEs, -** sessionChangesetNext() does that. This function does not. -*/ -static int sessionChangesetNextOne( +** Advance the changeset iterator to the next change. +** +** If both paRec and pnRec are NULL, then this function works like the public +** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the +** sqlite3changeset_new() and old() APIs may be used to query for values. +** +** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change +** record is written to *paRec before returning and the number of bytes in +** the record to *pnRec. +** +** Either way, this function returns SQLITE_ROW if the iterator is +** successfully advanced to the next change in the changeset, an SQLite +** error code if an error occurs, or SQLITE_DONE if there are no further +** changes in the changeset. +*/ +static int sessionChangesetNext( sqlite3_changeset_iter *p, /* Changeset iterator */ u8 **paRec, /* If non-NULL, store record pointer here */ - int *pnRec, /* If non-NULL, store size of record here */ - int *pbNew, /* If non-NULL, true if new table */ - int *pbEmpty + int *pnRec /* If non-NULL, store size of record here */ ){ int i; u8 op; assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); - assert( pbEmpty==0 || *pbEmpty==0 ); /* If the iterator is in the error-state, return immediately. */ if( p->rc!=SQLITE_OK ) return p->rc; /* Free the current contents of p->apValue[], if any. */ @@ -230448,43 +178716,35 @@ ** sufficient either for the 'T' or 'P' byte and the varint that follows ** it, or for the two single byte values otherwise. */ p->rc = sessionInputBuffer(&p->in, 2); if( p->rc!=SQLITE_OK ) return p->rc; - sessionDiscardData(&p->in); - p->in.iCurrent = p->in.iNext; - /* If the iterator is already at the end of the changeset, return DONE. */ if( p->in.iNext>=p->in.nData ){ return SQLITE_DONE; } + sessionDiscardData(&p->in); + p->in.iCurrent = p->in.iNext; + op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ - if( pbNew ) *pbNew = 1; p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; p->in.iCurrent = p->in.iNext; if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; op = p->in.aData[p->in.iNext++]; } - if( p->zTab==0 || (p->bPatchset && p->bInvert) ){ - /* The first record in the changeset is not a table header. Must be a - ** corrupt changeset. */ - assert( p->in.iNext==1 || p->zTab ); - return (p->rc = SQLITE_CORRUPT_BKPT); - } - p->op = op; p->bIndirect = p->in.aData[p->in.iNext++]; if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ return (p->rc = SQLITE_CORRUPT_BKPT); } - if( paRec ){ + if( paRec ){ int nVal; /* Number of values to buffer */ if( p->bPatchset==0 && op==SQLITE_UPDATE ){ nVal = p->nCol * 2; }else if( p->bPatchset && op==SQLITE_DELETE ){ nVal = 0; @@ -230495,106 +178755,53 @@ p->rc = sessionChangesetBufferRecord(&p->in, nVal, pnRec); if( p->rc!=SQLITE_OK ) return p->rc; *paRec = &p->in.aData[p->in.iNext]; p->in.iNext += *pnRec; }else{ - sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue); - sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]); /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ u8 *abPK = p->bPatchset ? p->abPK : 0; - p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld, 0); + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ - p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew, pbEmpty); + p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); if( p->rc!=SQLITE_OK ) return p->rc; } - if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){ + if( p->bPatchset && p->op==SQLITE_UPDATE ){ /* If this is an UPDATE that is part of a patchset, then all PK and ** modified fields are present in the new.* record. The old.* record ** is currently completely empty. This block shifts the PK fields from ** new.* to old.*, to accommodate the code that reads these arrays. */ for(i=0; inCol; i++){ - assert( p->bPatchset==0 || p->apValue[i]==0 ); + assert( p->apValue[i]==0 ); + assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); if( p->abPK[i] ){ - assert( p->apValue[i]==0 ); p->apValue[i] = p->apValue[i+p->nCol]; - if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); p->apValue[i+p->nCol] = 0; } } - }else if( p->bInvert ){ - if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE; - else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT; - } - - /* If this is an UPDATE that is part of a changeset, then check that - ** there are no fields in the old.* record that are not (a) PK fields, - ** or (b) also present in the new.* record. - ** - ** Such records are technically corrupt, but the rebaser was at one - ** point generating them. Under most circumstances this is benign, but - ** can cause spurious SQLITE_RANGE errors when applying the changeset. */ - if( p->bPatchset==0 && p->op==SQLITE_UPDATE){ - for(i=0; inCol; i++){ - if( p->abPK[i]==0 && p->apValue[i+p->nCol]==0 ){ - sqlite3ValueFree(p->apValue[i]); - p->apValue[i] = 0; - } - } } } return SQLITE_ROW; } -/* -** Advance the changeset iterator to the next change. -** -** If both paRec and pnRec are NULL, then this function works like the public -** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the -** sqlite3changeset_new() and old() APIs may be used to query for values. -** -** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change -** record is written to *paRec before returning and the number of bytes in -** the record to *pnRec. -** -** Either way, this function returns SQLITE_ROW if the iterator is -** successfully advanced to the next change in the changeset, an SQLite -** error code if an error occurs, or SQLITE_DONE if there are no further -** changes in the changeset. -*/ -static int sessionChangesetNext( - sqlite3_changeset_iter *p, /* Changeset iterator */ - u8 **paRec, /* If non-NULL, store record pointer here */ - int *pnRec, /* If non-NULL, store size of record here */ - int *pbNew /* If non-NULL, true if new table */ -){ - int bEmpty; - int rc; - do { - bEmpty = 0; - rc = sessionChangesetNextOne(p, paRec, pnRec, pbNew, &bEmpty); - }while( rc==SQLITE_ROW && p->bSkipEmpty && bEmpty); - return rc; -} - /* ** Advance an iterator created by sqlite3changeset_start() to the next ** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE ** or SQLITE_CORRUPT. ** ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ - return sessionChangesetNext(p, 0, 0, 0); + return sessionChangesetNext(p, 0, 0); } /* ** The following function extracts information on the current change ** from a changeset iterator. It may only be called after changeset_next() @@ -230694,11 +178901,11 @@ #define sessionChangesetNew(pIter, iVal) (pIter)->apValue[(pIter)->nCol+(iVal)] #define sessionChangesetOld(pIter, iVal) (pIter)->apValue[(iVal)] /* ** This function may only be called with a changeset iterator that has been -** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT +** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT ** conflict-handler function. Otherwise, SQLITE_MISUSE is returned. ** ** If successful, *ppValue is set to point to an sqlite3_value structure ** containing the iVal'th value of the conflicting record. ** @@ -230839,11 +179046,11 @@ case SQLITE_UPDATE: { int iCol; if( 0==apVal ){ - apVal = (sqlite3_value **)sqlite3_malloc64(sizeof(apVal[0])*nCol*2); + apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2); if( 0==apVal ){ rc = SQLITE_NOMEM; goto finished_invert; } memset(apVal, 0, sizeof(apVal[0])*nCol*2); @@ -230853,13 +179060,13 @@ sessionAppendByte(&sOut, eType, &rc); sessionAppendByte(&sOut, pInput->aData[pInput->iNext+1], &rc); /* Read the old.* and new.* records for the update change. */ pInput->iNext += 2; - rc = sessionReadRecord(pInput, nCol, 0, &apVal[0], 0); + rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]); if( rc==SQLITE_OK ){ - rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol], 0); + rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]); } /* Write the new old.* record. Consists of the PK columns from the ** original old.* record, and the other values from the original ** new.* record. */ @@ -230891,23 +179098,23 @@ rc = SQLITE_CORRUPT_BKPT; goto finished_invert; } assert( rc==SQLITE_OK ); - if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){ + if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; if( rc!=SQLITE_OK ) goto finished_invert; } } assert( rc==SQLITE_OK ); - if( pnInverted && ALWAYS(ppInverted) ){ + if( pnInverted ){ *pnInverted = sOut.nBuf; *ppInverted = sOut.aBuf; sOut.aBuf = 0; - }else if( sOut.nBuf>0 && ALWAYS(xOutput!=0) ){ + }else if( sOut.nBuf>0 ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); } finished_invert: sqlite3_free(sOut.aBuf); @@ -230956,201 +179163,25 @@ rc = sessionChangesetInvert(&sInput, xOutput, pOut, 0, 0); sqlite3_free(sInput.buf.aBuf); return rc; } - -typedef struct SessionUpdate SessionUpdate; -struct SessionUpdate { - sqlite3_stmt *pStmt; - u32 *aMask; - SessionUpdate *pNext; -}; - typedef struct SessionApplyCtx SessionApplyCtx; struct SessionApplyCtx { sqlite3 *db; sqlite3_stmt *pDelete; /* DELETE statement */ + sqlite3_stmt *pUpdate; /* UPDATE statement */ sqlite3_stmt *pInsert; /* INSERT statement */ sqlite3_stmt *pSelect; /* SELECT statement */ int nCol; /* Size of azCol[] and abPK[] arrays */ const char **azCol; /* Array of column names */ u8 *abPK; /* Boolean array - true if column is in PK */ - u32 *aUpdateMask; /* Used by sessionUpdateFind */ - SessionUpdate *pUp; - int bStat1; /* True if table is sqlite_stat1 */ + int bDeferConstraints; /* True to defer constraints */ - int bInvertConstraints; /* Invert when iterating constraints buffer */ SessionBuffer constraints; /* Deferred constraints are stored here */ - SessionBuffer rebase; /* Rebase information (if any) here */ - u8 bRebaseStarted; /* If table header is already in rebase */ - u8 bRebase; /* True to collect rebase information */ - u8 bIgnoreNoop; /* True to ignore no-op conflicts */ - int bRowid; }; -/* Number of prepared UPDATE statements to cache. */ -#define SESSION_UPDATE_CACHE_SZ 12 - -/* -** Find a prepared UPDATE statement suitable for the UPDATE step currently -** being visited by the iterator. The UPDATE is of the form: -** -** UPDATE tbl SET col = ?, col2 = ? WHERE pk1 IS ? AND pk2 IS ? -*/ -static int sessionUpdateFind( - sqlite3_changeset_iter *pIter, - SessionApplyCtx *p, - int bPatchset, - sqlite3_stmt **ppStmt -){ - int rc = SQLITE_OK; - SessionUpdate *pUp = 0; - int nCol = pIter->nCol; - int nU32 = (pIter->nCol+33)/32; - int ii; - - if( p->aUpdateMask==0 ){ - p->aUpdateMask = sqlite3_malloc(nU32*sizeof(u32)); - if( p->aUpdateMask==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - memset(p->aUpdateMask, 0, nU32*sizeof(u32)); - rc = SQLITE_CORRUPT; - for(ii=0; iinCol; ii++){ - if( sessionChangesetNew(pIter, ii) ){ - p->aUpdateMask[ii/32] |= (1<<(ii%32)); - rc = SQLITE_OK; - } - } - } - - if( rc==SQLITE_OK ){ - if( bPatchset ) p->aUpdateMask[nCol/32] |= (1<<(nCol%32)); - - if( p->pUp ){ - int nUp = 0; - SessionUpdate **pp = &p->pUp; - while( 1 ){ - nUp++; - if( 0==memcmp(p->aUpdateMask, (*pp)->aMask, nU32*sizeof(u32)) ){ - pUp = *pp; - *pp = pUp->pNext; - pUp->pNext = p->pUp; - p->pUp = pUp; - break; - } - - if( (*pp)->pNext ){ - pp = &(*pp)->pNext; - }else{ - if( nUp>=SESSION_UPDATE_CACHE_SZ ){ - sqlite3_finalize((*pp)->pStmt); - sqlite3_free(*pp); - *pp = 0; - } - break; - } - } - } - - if( pUp==0 ){ - int nByte = sizeof(SessionUpdate) * nU32*sizeof(u32); - int bStat1 = (sqlite3_stricmp(pIter->zTab, "sqlite_stat1")==0); - pUp = (SessionUpdate*)sqlite3_malloc(nByte); - if( pUp==0 ){ - rc = SQLITE_NOMEM; - }else{ - const char *zSep = ""; - SessionBuffer buf; - - memset(&buf, 0, sizeof(buf)); - pUp->aMask = (u32*)&pUp[1]; - memcpy(pUp->aMask, p->aUpdateMask, nU32*sizeof(u32)); - - sessionAppendStr(&buf, "UPDATE main.", &rc); - sessionAppendIdent(&buf, pIter->zTab, &rc); - sessionAppendStr(&buf, " SET ", &rc); - - /* Create the assignments part of the UPDATE */ - for(ii=0; iinCol; ii++){ - if( p->abPK[ii]==0 && sessionChangesetNew(pIter, ii) ){ - sessionAppendStr(&buf, zSep, &rc); - sessionAppendIdent(&buf, p->azCol[ii], &rc); - sessionAppendStr(&buf, " = ?", &rc); - sessionAppendInteger(&buf, ii*2+1, &rc); - zSep = ", "; - } - } - - /* Create the WHERE clause part of the UPDATE */ - zSep = ""; - sessionAppendStr(&buf, " WHERE ", &rc); - for(ii=0; iinCol; ii++){ - if( p->abPK[ii] || (bPatchset==0 && sessionChangesetOld(pIter, ii)) ){ - sessionAppendStr(&buf, zSep, &rc); - if( bStat1 && ii==1 ){ - assert( sqlite3_stricmp(p->azCol[ii], "idx")==0 ); - sessionAppendStr(&buf, - "idx IS CASE " - "WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL " - "ELSE ?4 END ", &rc - ); - }else{ - sessionAppendIdent(&buf, p->azCol[ii], &rc); - sessionAppendStr(&buf, " IS ?", &rc); - sessionAppendInteger(&buf, ii*2+2, &rc); - } - zSep = " AND "; - } - } - - if( rc==SQLITE_OK ){ - char *zSql = (char*)buf.aBuf; - rc = sqlite3_prepare_v2(p->db, zSql, buf.nBuf, &pUp->pStmt, 0); - } - - if( rc!=SQLITE_OK ){ - sqlite3_free(pUp); - pUp = 0; - }else{ - pUp->pNext = p->pUp; - p->pUp = pUp; - } - sqlite3_free(buf.aBuf); - } - } - } - - assert( (rc==SQLITE_OK)==(pUp!=0) ); - if( pUp ){ - *ppStmt = pUp->pStmt; - }else{ - *ppStmt = 0; - } - return rc; -} - -/* -** Free all cached UPDATE statements. -*/ -static void sessionUpdateFree(SessionApplyCtx *p){ - SessionUpdate *pUp; - SessionUpdate *pNext; - for(pUp=p->pUp; pUp; pUp=pNext){ - pNext = pUp->pNext; - sqlite3_finalize(pUp->pStmt); - sqlite3_free(pUp); - } - p->pUp = 0; - sqlite3_free(p->aUpdateMask); - p->aUpdateMask = 0; -} - /* ** Formulate a statement to DELETE a row from database db. Assuming a table ** structure like this: ** ** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); @@ -231175,11 +179206,11 @@ const char *zSep = ""; int rc = SQLITE_OK; SessionBuffer buf = {0, 0, 0}; int nPk = 0; - sessionAppendStr(&buf, "DELETE FROM main.", &rc); + sessionAppendStr(&buf, "DELETE FROM ", &rc); sessionAppendIdent(&buf, zTab, &rc); sessionAppendStr(&buf, " WHERE ", &rc); for(i=0; inCol; i++){ if( p->abPK[i] ){ @@ -231215,10 +179246,106 @@ } sqlite3_free(buf.aBuf); return rc; } + +/* +** Formulate and prepare a statement to UPDATE a row from database db. +** Assuming a table structure like this: +** +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); +** +** The UPDATE statement looks like this: +** +** UPDATE x SET +** a = CASE WHEN ?2 THEN ?3 ELSE a END, +** b = CASE WHEN ?5 THEN ?6 ELSE b END, +** c = CASE WHEN ?8 THEN ?9 ELSE c END, +** d = CASE WHEN ?11 THEN ?12 ELSE d END +** WHERE a = ?1 AND c = ?7 AND (?13 OR +** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND +** ) +** +** For each column in the table, there are three variables to bind: +** +** ?(i*3+1) The old.* value of the column, if any. +** ?(i*3+2) A boolean flag indicating that the value is being modified. +** ?(i*3+3) The new.* value of the column, if any. +** +** Also, a boolean flag that, if set to true, causes the statement to update +** a row even if the non-PK values do not match. This is required if the +** conflict-handler is invoked with CHANGESET_DATA and returns +** CHANGESET_REPLACE. This is variable "?(nCol*3+1)". +** +** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left +** pointing to the prepared version of the SQL statement. +*/ +static int sessionUpdateRow( + sqlite3 *db, /* Database handle */ + const char *zTab, /* Table name */ + SessionApplyCtx *p /* Session changeset-apply context */ +){ + int rc = SQLITE_OK; + int i; + const char *zSep = ""; + SessionBuffer buf = {0, 0, 0}; + + /* Append "UPDATE tbl SET " */ + sessionAppendStr(&buf, "UPDATE ", &rc); + sessionAppendIdent(&buf, zTab, &rc); + sessionAppendStr(&buf, " SET ", &rc); + + /* Append the assignments */ + for(i=0; inCol; i++){ + sessionAppendStr(&buf, zSep, &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = CASE WHEN ?", &rc); + sessionAppendInteger(&buf, i*3+2, &rc); + sessionAppendStr(&buf, " THEN ?", &rc); + sessionAppendInteger(&buf, i*3+3, &rc); + sessionAppendStr(&buf, " ELSE ", &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " END", &rc); + zSep = ", "; + } + + /* Append the PK part of the WHERE clause */ + sessionAppendStr(&buf, " WHERE ", &rc); + for(i=0; inCol; i++){ + if( p->abPK[i] ){ + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " = ?", &rc); + sessionAppendInteger(&buf, i*3+1, &rc); + sessionAppendStr(&buf, " AND ", &rc); + } + } + + /* Append the non-PK part of the WHERE clause */ + sessionAppendStr(&buf, " (?", &rc); + sessionAppendInteger(&buf, p->nCol*3+1, &rc); + sessionAppendStr(&buf, " OR 1", &rc); + for(i=0; inCol; i++){ + if( !p->abPK[i] ){ + sessionAppendStr(&buf, " AND (?", &rc); + sessionAppendInteger(&buf, i*3+2, &rc); + sessionAppendStr(&buf, "=0 OR ", &rc); + sessionAppendIdent(&buf, p->azCol[i], &rc); + sessionAppendStr(&buf, " IS ?", &rc); + sessionAppendInteger(&buf, i*3+1, &rc); + sessionAppendStr(&buf, ")", &rc); + } + } + sessionAppendStr(&buf, ")", &rc); + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0); + } + sqlite3_free(buf.aBuf); + + return rc; +} /* ** Formulate and prepare an SQL statement to query table zTab by primary ** key. Assuming the following table structure: ** @@ -231234,14 +179361,12 @@ static int sessionSelectRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ SessionApplyCtx *p /* Session changeset-apply context */ ){ - /* TODO */ - return sessionSelectStmt(db, p->bIgnoreNoop, - "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect - ); + return sessionSelectStmt( + db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); } /* ** Formulate and prepare an INSERT statement to add a record to table zTab. ** For example: @@ -231279,41 +179404,12 @@ } sqlite3_free(buf.aBuf); return rc; } -static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){ - return sqlite3_prepare_v2(db, zSql, -1, pp, 0); -} - -/* -** Prepare statements for applying changes to the sqlite_stat1 table. -** These are similar to those created by sessionSelectRow(), -** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for -** other tables. -*/ -static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ - int rc = sessionSelectRow(db, "sqlite_stat1", p); - if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, &p->pInsert, - "INSERT INTO main.sqlite_stat1 VALUES(?1, " - "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, " - "?3)" - ); - } - if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, &p->pDelete, - "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " - "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " - "AND (?4 OR stat IS ?3)" - ); - } - return rc; -} - -/* -** A wrapper around sqlite3_bind_value() that detects an extra problem. +/* +** A wrapper around sqlite3_bind_value() that detects an extra problem. ** See comments in the body of this function for details. */ static int sessionBindValue( sqlite3_stmt *pStmt, /* Statement to bind value to */ int i, /* Parameter number to bind to */ @@ -231332,19 +179428,19 @@ } return sqlite3_bind_value(pStmt, i, pVal); } /* -** Iterator pIter must point to an SQLITE_INSERT entry. This function +** Iterator pIter must point to an SQLITE_INSERT entry. This function ** transfers new.* values from the current iterator entry to statement ** pStmt. The table being inserted into has nCol columns. ** -** New.* value $i from the iterator is bound to variable ($i+1) of +** New.* value $i from the iterator is bound to variable ($i+1) of ** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1) ** are transfered to the statement. Otherwise, if abPK is not NULL, it points -** to an array nCol elements in size. In this case only those values for -** which abPK[$i] is true are read from the iterator and bound to the +** to an array nCol elements in size. In this case only those values for +** which abPK[$i] is true are read from the iterator and bound to the ** statement. ** ** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK. */ static int sessionBindRow( @@ -231356,131 +179452,64 @@ ){ int i; int rc = SQLITE_OK; /* Neither sqlite3changeset_old or sqlite3changeset_new can fail if the - ** argument iterator points to a suitable entry. Make sure that xValue - ** is one of these to guarantee that it is safe to ignore the return + ** argument iterator points to a suitable entry. Make sure that xValue + ** is one of these to guarantee that it is safe to ignore the return ** in the code below. */ assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new ); for(i=0; rc==SQLITE_OK && ipSelect; int rc; /* Return code */ int nCol; /* Number of columns in table */ int op; /* Changset operation (SQLITE_UPDATE etc.) */ const char *zDummy; /* Unused */ - sqlite3_clear_bindings(pSelect); sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); - rc = sessionBindRow(pIter, + rc = sessionBindRow(pIter, op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old, - nCol, p->abPK, pSelect + nCol, abPK, pSelect ); - if( op!=SQLITE_DELETE && p->bIgnoreNoop ){ - int ii; - for(ii=0; rc==SQLITE_OK && iiabPK[ii]==0 ){ - sqlite3_value *pVal = 0; - sqlite3changeset_new(pIter, ii, &pVal); - sqlite3_bind_int(pSelect, ii+1+nCol, (pVal==0)); - if( pVal ) rc = sessionBindValue(pSelect, ii+1, pVal); - } - } - } - if( rc==SQLITE_OK ){ rc = sqlite3_step(pSelect); if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect); } - return rc; -} - -/* -** This function is called from within sqlite3changeset_apply_v2() when -** a conflict is encountered and resolved using conflict resolution -** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE).. -** It adds a conflict resolution record to the buffer in -** SessionApplyCtx.rebase, which will eventually be returned to the caller -** of apply_v2() as the "rebase" buffer. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. -*/ -static int sessionRebaseAdd( - SessionApplyCtx *p, /* Apply context */ - int eType, /* Conflict resolution (OMIT or REPLACE) */ - sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ -){ - int rc = SQLITE_OK; - if( p->bRebase ){ - int i; - int eOp = pIter->op; - if( p->bRebaseStarted==0 ){ - /* Append a table-header to the rebase buffer */ - const char *zTab = pIter->zTab; - sessionAppendByte(&p->rebase, 'T', &rc); - sessionAppendVarint(&p->rebase, p->nCol, &rc); - sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); - sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); - p->bRebaseStarted = 1; - } - - assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); - assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); - - sessionAppendByte(&p->rebase, - (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc - ); - sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); - for(i=0; inCol; i++){ - sqlite3_value *pVal = 0; - if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ - sqlite3changeset_old(pIter, i, &pVal); - }else{ - sqlite3changeset_new(pIter, i, &pVal); - } - sessionAppendValue(&p->rebase, pVal, &rc); - } - } return rc; } /* ** Invoke the conflict handler for the change that the changeset iterator @@ -231511,11 +179540,11 @@ ** If pbReplace is not NULL, and a record with a matching PK is found, and ** the conflict handler function returns SQLITE_CHANGESET_REPLACE, *pbReplace ** is set to non-zero before returning SQLITE_OK. ** ** If the conflict handler returns SQLITE_CHANGESET_ABORT, SQLITE_ABORT is -** returned. Or, if the conflict handler returns an invalid value, +** returned. Or, if the conflict handler returns an invalid value, ** SQLITE_MISUSE. If the conflict handler returns SQLITE_CHANGESET_OMIT, ** this function returns SQLITE_OK. */ static int sessionConflictHandler( int eType, /* Either CHANGESET_DATA or CONFLICT */ @@ -231537,35 +179566,29 @@ assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT ); assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND ); /* Bind the new.* PRIMARY KEY values to the SELECT statement. */ if( pbReplace ){ - rc = sessionSeekToRow(pIter, p); + rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect); }else{ rc = SQLITE_OK; } if( rc==SQLITE_ROW ){ /* There exists another row with the new.* primary key. */ - if( p->bIgnoreNoop - && sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1) - ){ - res = SQLITE_CHANGESET_OMIT; - }else{ - pIter->pConflict = p->pSelect; - res = xConflict(pCtx, eType, pIter); - pIter->pConflict = 0; - } + pIter->pConflict = p->pSelect; + res = xConflict(pCtx, eType, pIter); + pIter->pConflict = 0; rc = sqlite3_reset(p->pSelect); }else if( rc==SQLITE_OK ){ if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ /* Instead of invoking the conflict handler, append the change blob ** to the SessionApplyCtx.constraints buffer. */ u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); - return SQLITE_OK; + res = SQLITE_CHANGESET_OMIT; }else{ /* No other row with the new.* primary key. */ res = xConflict(pCtx, eType+1, pIter); if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; } @@ -231587,13 +179610,10 @@ default: rc = SQLITE_MISUSE; break; } - if( rc==SQLITE_OK ){ - rc = sessionRebaseAdd(p, res, pIter); - } } return rc; } @@ -231607,20 +179627,20 @@ ** instead. Or, if pbRetry is not NULL and a CHANGESET_DATA conflict occurs, ** invoke the conflict handler. If it returns CHANGESET_REPLACE, set *pbRetry ** to true before returning. In this case the caller will invoke this function ** again, this time with pbRetry set to NULL. ** -** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is +** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is ** encountered invoke the conflict handler with CHANGESET_CONSTRAINT instead. ** Or, if pbReplace is not NULL, invoke it with CHANGESET_CONFLICT. If such ** an invocation returns SQLITE_CHANGESET_REPLACE, set *pbReplace to true ** before retrying. In this case the caller attempts to remove the conflicting -** row before invoking this function again, this time with pbReplace set +** row before invoking this function again, this time with pbReplace set ** to NULL. ** ** If any conflict handler returns SQLITE_CHANGESET_ABORT, this function -** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is +** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is ** returned. */ static int sessionApplyOneOp( sqlite3_changeset_iter *pIter, /* Changeset iterator */ SessionApplyCtx *p, /* changeset_apply() context */ @@ -231632,11 +179652,11 @@ const char *zDummy; int op; int nCol; int rc = SQLITE_OK; - assert( p->pDelete && p->pInsert && p->pSelect ); + assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect ); assert( p->azCol && p->abPK ); assert( !pbReplace || *pbReplace==0 ); sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); @@ -231660,11 +179680,11 @@ } if( rc!=SQLITE_OK ) return rc; sqlite3_step(p->pDelete); rc = sqlite3_reset(p->pDelete); - if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 && p->bIgnoreNoop==0 ){ + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ rc = sessionConflictHandler( SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry ); }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( @@ -231672,32 +179692,33 @@ ); } }else if( op==SQLITE_UPDATE ){ int i; - sqlite3_stmt *pUp = 0; - int bPatchset = (pbRetry==0 || pIter->bPatchset); - - rc = sessionUpdateFind(pIter, p, bPatchset, &pUp); /* Bind values to the UPDATE statement. */ for(i=0; rc==SQLITE_OK && iabPK[i] || (bPatchset==0 && pOld) ){ - rc = sessionBindValue(pUp, i*2+2, pOld); + + sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew); + if( pOld ){ + rc = sessionBindValue(p->pUpdate, i*3+1, pOld); } if( rc==SQLITE_OK && pNew ){ - rc = sessionBindValue(pUp, i*2+1, pNew); + rc = sessionBindValue(p->pUpdate, i*3+3, pNew); } } + if( rc==SQLITE_OK ){ + sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset); + } if( rc!=SQLITE_OK ) return rc; /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict, ** the result will be SQLITE_OK with 0 rows modified. */ - sqlite3_step(pUp); - rc = sqlite3_reset(pUp); + sqlite3_step(p->pUpdate); + rc = sqlite3_reset(p->pUpdate); if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ /* A NOTFOUND or DATA error. Search the table to see if it contains ** a row with a matching primary key. If so, this is a DATA conflict. ** Otherwise, if there is no primary key match, it is a NOTFOUND. */ @@ -231713,29 +179734,15 @@ ); } }else{ assert( op==SQLITE_INSERT ); - if( p->bStat1 ){ - /* Check if there is a conflicting row. For sqlite_stat1, this needs - ** to be done using a SELECT, as there is no PRIMARY KEY in the - ** database schema to throw an exception if a duplicate is inserted. */ - rc = sessionSeekToRow(pIter, p); - if( rc==SQLITE_ROW ){ - rc = SQLITE_CONSTRAINT; - sqlite3_reset(p->pSelect); - } - } - - if( rc==SQLITE_OK ){ - rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); - if( rc!=SQLITE_OK ) return rc; - - sqlite3_step(p->pInsert); - rc = sqlite3_reset(p->pInsert); - } - + rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_step(p->pInsert); + rc = sqlite3_reset(p->pInsert); if( (rc&0xff)==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace ); } @@ -231748,11 +179755,11 @@ ** Attempt to apply the change that the iterator passed as the first argument ** currently points to to the database. If a conflict is encountered, invoke ** the conflict handler callback. ** ** The difference between this function and sessionApplyOne() is that this -** function handles the case where the conflict-handler is invoked and +** function handles the case where the conflict-handler is invoked and ** returns SQLITE_CHANGESET_REPLACE - indicating that the change should be ** retried in some manner. */ static int sessionApplyOneWithRetry( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -231764,46 +179771,46 @@ int bReplace = 0; int bRetry = 0; int rc; rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); - if( rc==SQLITE_OK ){ - /* If the bRetry flag is set, the change has not been applied due to an - ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and - ** a row with the correct PK is present in the db, but one or more other - ** fields do not contain the expected values) and the conflict handler - ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, - ** but pass NULL as the final argument so that sessionApplyOneOp() ignores - ** the SQLITE_CHANGESET_DATA problem. */ - if( bRetry ){ - assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); - } - - /* If the bReplace flag is set, the change is an INSERT that has not - ** been performed because the database already contains a row with the - ** specified primary key and the conflict handler returned - ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row - ** before reattempting the INSERT. */ - else if( bReplace ){ - assert( pIter->op==SQLITE_INSERT ); - rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sessionBindRow(pIter, - sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); - sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); - } - if( rc==SQLITE_OK ){ - sqlite3_step(pApply->pDelete); - rc = sqlite3_reset(pApply->pDelete); - } - if( rc==SQLITE_OK ){ - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); - } + assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); + + /* If the bRetry flag is set, the change has not been applied due to an + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and + ** a row with the correct PK is present in the db, but one or more other + ** fields do not contain the expected values) and the conflict handler + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores + ** the SQLITE_CHANGESET_DATA problem. */ + if( bRetry ){ + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + + /* If the bReplace flag is set, the change is an INSERT that has not + ** been performed because the database already contains a row with the + ** specified primary key and the conflict handler returned + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row + ** before reattempting the INSERT. */ + else if( bReplace ){ + assert( pIter->op==SQLITE_INSERT ); + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sessionBindRow(pIter, + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pApply->pDelete); + rc = sqlite3_reset(pApply->pDelete); + } + if( rc==SQLITE_OK ){ + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); } } return rc; } @@ -231810,11 +179817,11 @@ /* ** Retry the changes accumulated in the pApply->constraints buffer. */ static int sessionRetryConstraints( - sqlite3 *db, + sqlite3 *db, int bPatchset, const char *zTab, SessionApplyCtx *pApply, int(*xConflict)(void*, int, sqlite3_changeset_iter*), void *pCtx /* First argument passed to xConflict */ @@ -231824,15 +179831,13 @@ while( pApply->constraints.nBuf ){ sqlite3_changeset_iter *pIter2 = 0; SessionBuffer cons = pApply->constraints; memset(&pApply->constraints, 0, sizeof(SessionBuffer)); - rc = sessionChangesetStart( - &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1 - ); + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); if( rc==SQLITE_OK ){ - size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*); + int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); int rc2; pIter2->bPatchset = bPatchset; pIter2->zTab = (char*)zTab; pIter2->nCol = pApply->nCol; pIter2->abPK = pApply->abPK; @@ -231860,11 +179865,11 @@ return rc; } /* ** Argument pIter is a changeset iterator that has been initialized, but -** not yet passed to sqlite3changeset_next(). This function applies the +** not yet passed to sqlite3changeset_next(). This function applies the ** changeset to the main database attached to handle "db". The supplied ** conflict handler callback is invoked to resolve any conflicts encountered ** while applying the change. */ static int sessionChangesetApply( @@ -231877,46 +179882,33 @@ int(*xConflict)( void *pCtx, /* Copy of fifth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase information */ - int flags /* SESSION_APPLY_XXX flags */ + void *pCtx /* First argument passed to xConflict */ ){ int schemaMismatch = 0; - int rc = SQLITE_OK; /* Return code */ + int rc; /* Return code */ const char *zTab = 0; /* Name of current table */ int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ SessionApplyCtx sApply; /* changeset_apply() context object */ int bPatchset; - u64 savedFlag = db->flags & SQLITE_FkNoAction; assert( xConflict!=0 ); - sqlite3_mutex_enter(sqlite3_db_mutex(db)); - if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){ - db->flags |= ((u64)SQLITE_FkNoAction); - db->aDb[0].pSchema->schema_cookie -= 32; - } - pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); - sApply.bRebase = (ppRebase && pnRebase); - sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); - sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP); - if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ - rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); - } + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; int op; const char *zNew; - + sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0); if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ u8 *abPK; @@ -231923,29 +179915,20 @@ rc = sessionRetryConstraints( db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx ); if( rc!=SQLITE_OK ) break; - sessionUpdateFree(&sApply); sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_finalize(sApply.pDelete); + sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pSelect); + memset(&sApply, 0, sizeof(sApply)); sApply.db = db; - sApply.pDelete = 0; - sApply.pInsert = 0; - sApply.pSelect = 0; - sApply.nCol = 0; - sApply.azCol = 0; - sApply.abPK = 0; - sApply.bStat1 = 0; sApply.bDeferConstraints = 1; - sApply.bRebaseStarted = 0; - sApply.bRowid = 0; - memset(&sApply.constraints, 0, sizeof(SessionBuffer)); - /* If an xFilter() callback was specified, invoke it now. If the + /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns ** non-zero, proceed. */ schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); @@ -231958,30 +179941,29 @@ }else{ int nMinCol = 0; int i; sqlite3changeset_pk(pIter, &abPK, 0); - rc = sessionTableInfo(0, db, "main", zNew, - &sApply.nCol, 0, &zTab, &sApply.azCol, 0, 0, - &sApply.abPK, &sApply.bRowid + rc = sessionTableInfo( + db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK ); if( rc!=SQLITE_OK ) break; for(i=0; iflags & SQLITE_FkNoAction ); - db->flags &= ~((u64)SQLITE_FkNoAction); - db->aDb[0].pSchema->schema_cookie -= 32; - } sqlite3_mutex_leave(sqlite3_db_mutex(db)); - return rc; -} - -/* -** Apply the changeset passed via pChangeset/nChangeset to the main -** database attached to handle "db". -*/ -SQLITE_API int sqlite3changeset_apply_v2( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -){ - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); - int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1); - - if( rc==SQLITE_OK ){ - rc = sessionChangesetApply( - db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags - ); - } - return rc; } /* ** Apply the changeset passed via pChangeset/nChangeset to the main database @@ -232133,47 +180054,23 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ){ - return sqlite3changeset_apply_v2( - db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0 - ); + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); + } + return rc; } /* ** Apply the changeset passed via xInput/pIn to the main database ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ -SQLITE_API int sqlite3changeset_apply_v2_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -){ - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); - int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1); - if( rc==SQLITE_OK ){ - rc = sessionChangesetApply( - db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags - ); - } - return rc; -} 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 */ int(*xFilter)( @@ -232185,120 +180082,59 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ){ - return sqlite3changeset_apply_v2_strm( - db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0 - ); + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); + } + return rc; } /* ** sqlite3_changegroup handle. */ struct sqlite3_changegroup { int rc; /* Error code */ int bPatch; /* True to accumulate patchsets */ SessionTable *pList; /* List of tables in current patch */ - SessionBuffer rec; - - sqlite3 *db; /* Configured by changegroup_schema() */ - char *zDb; /* Configured by changegroup_schema() */ }; /* ** This function is called to merge two changes to the same row together as ** part of an sqlite3changeset_concat() operation. A new change object is ** allocated and a pointer to it stored in *ppNew. */ static int sessionChangeMerge( SessionTable *pTab, /* Table structure */ - int bRebase, /* True for a rebase hash-table */ int bPatchset, /* True for patchsets */ SessionChange *pExist, /* Existing change */ int op2, /* Second change operation */ int bIndirect, /* True if second change is indirect */ u8 *aRec, /* Second change record */ int nRec, /* Number of bytes in aRec */ SessionChange **ppNew /* OUT: Merged change */ ){ SessionChange *pNew = 0; - int rc = SQLITE_OK; - assert( aRec!=0 ); if( !pExist ){ - pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec); + pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); if( !pNew ){ return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SessionChange)); pNew->op = op2; pNew->bIndirect = bIndirect; + pNew->nRecord = nRec; pNew->aRecord = (u8*)&pNew[1]; - if( bIndirect==0 || bRebase==0 ){ - pNew->nRecord = nRec; - memcpy(pNew->aRecord, aRec, nRec); - }else{ - int i; - u8 *pIn = aRec; - u8 *pOut = pNew->aRecord; - for(i=0; inCol; i++){ - int nIn = sessionSerialLen(pIn); - if( *pIn==0 ){ - *pOut++ = 0; - }else if( pTab->abPK[i]==0 ){ - *pOut++ = 0xFF; - }else{ - memcpy(pOut, pIn, nIn); - pOut += nIn; - } - pIn += nIn; - } - pNew->nRecord = pOut - pNew->aRecord; - } - }else if( bRebase ){ - if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){ - *ppNew = pExist; - }else{ - sqlite3_int64 nByte = nRec + pExist->nRecord + sizeof(SessionChange); - pNew = (SessionChange*)sqlite3_malloc64(nByte); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - int i; - u8 *a1 = pExist->aRecord; - u8 *a2 = aRec; - u8 *pOut; - - memset(pNew, 0, nByte); - pNew->bIndirect = bIndirect || pExist->bIndirect; - pNew->op = op2; - pOut = pNew->aRecord = (u8*)&pNew[1]; - - for(i=0; inCol; i++){ - int n1 = sessionSerialLen(a1); - int n2 = sessionSerialLen(a2); - if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){ - *pOut++ = 0xFF; - }else if( *a2==0 ){ - memcpy(pOut, a1, n1); - pOut += n1; - }else{ - memcpy(pOut, a2, n2); - pOut += n2; - } - a1 += n1; - a2 += n2; - } - pNew->nRecord = pOut - pNew->aRecord; - } - sqlite3_free(pExist); - } + memcpy(pNew->aRecord, aRec, nRec); }else{ int op1 = pExist->op; - /* + /* ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. ** op1=INSERT, op2=UPDATE -> INSERT. ** op1=INSERT, op2=DELETE -> (none) ** ** op1=UPDATE, op2=INSERT -> Unsupported. Discard op2. @@ -232306,11 +180142,11 @@ ** op1=UPDATE, op2=DELETE -> DELETE. ** ** op1=DELETE, op2=INSERT -> UPDATE. ** op1=DELETE, op2=UPDATE -> Unsupported. Discard op2. ** op1=DELETE, op2=DELETE -> Unsupported. Discard op2. - */ + */ if( (op1==SQLITE_INSERT && op2==SQLITE_INSERT) || (op1==SQLITE_UPDATE && op2==SQLITE_INSERT) || (op1==SQLITE_DELETE && op2==SQLITE_UPDATE) || (op1==SQLITE_DELETE && op2==SQLITE_DELETE) ){ @@ -232318,18 +180154,18 @@ }else if( op1==SQLITE_INSERT && op2==SQLITE_DELETE ){ sqlite3_free(pExist); assert( pNew==0 ); }else{ u8 *aExist = pExist->aRecord; - sqlite3_int64 nByte; + int nByte; u8 *aCsr; /* Allocate a new SessionChange object. Ensure that the aRecord[] ** buffer of the new object is large enough to hold any record that ** may be generated by combining the input records. */ nByte = sizeof(SessionChange) + pExist->nRecord + nRec; - pNew = (SessionChange *)sqlite3_malloc64(nByte); + pNew = (SessionChange *)sqlite3_malloc(nByte); if( !pNew ){ sqlite3_free(pExist); return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SessionChange)); @@ -232384,250 +180220,92 @@ sqlite3_free(pExist); } } *ppNew = pNew; - return rc; -} - -/* -** Check if a changeset entry with nCol columns and the PK array passed -** as the final argument to this function is compatible with SessionTable -** pTab. If so, return 1. Otherwise, if they are incompatible in some way, -** return 0. -*/ -static int sessionChangesetCheckCompat( - SessionTable *pTab, - int nCol, - u8 *abPK -){ - if( pTab->azCol && nColnCol ){ - int ii; - for(ii=0; iinCol; ii++){ - u8 bPK = (ii < nCol) ? abPK[ii] : 0; - if( pTab->abPK[ii]!=bPK ) return 0; - } - return 1; - } - return (pTab->nCol==nCol && 0==memcmp(abPK, pTab->abPK, nCol)); -} - -static int sessionChangesetExtendRecord( - sqlite3_changegroup *pGrp, - SessionTable *pTab, - int nCol, - int op, - const u8 *aRec, - int nRec, - SessionBuffer *pOut -){ - int rc = SQLITE_OK; - int ii = 0; - - assert( pTab->azCol ); - assert( nColnCol ); - - pOut->nBuf = 0; - if( op==SQLITE_INSERT || (op==SQLITE_DELETE && pGrp->bPatch==0) ){ - /* Append the missing default column values to the record. */ - sessionAppendBlob(pOut, aRec, nRec, &rc); - if( rc==SQLITE_OK && pTab->pDfltStmt==0 ){ - rc = sessionPrepareDfltStmt(pGrp->db, pTab, &pTab->pDfltStmt); - if( rc==SQLITE_OK && SQLITE_ROW!=sqlite3_step(pTab->pDfltStmt) ){ - rc = sqlite3_errcode(pGrp->db); - } - } - for(ii=nCol; rc==SQLITE_OK && iinCol; ii++){ - int eType = sqlite3_column_type(pTab->pDfltStmt, ii); - sessionAppendByte(pOut, eType, &rc); - switch( eType ){ - case SQLITE_FLOAT: - case SQLITE_INTEGER: { - i64 iVal; - if( eType==SQLITE_INTEGER ){ - iVal = sqlite3_column_int64(pTab->pDfltStmt, ii); - }else{ - double rVal = sqlite3_column_int64(pTab->pDfltStmt, ii); - memcpy(&iVal, &rVal, sizeof(i64)); - } - if( SQLITE_OK==sessionBufferGrow(pOut, 8, &rc) ){ - sessionPutI64(&pOut->aBuf[pOut->nBuf], iVal); - pOut->nBuf += 8; - } - break; - } - - case SQLITE_BLOB: - case SQLITE_TEXT: { - int n = sqlite3_column_bytes(pTab->pDfltStmt, ii); - sessionAppendVarint(pOut, n, &rc); - if( eType==SQLITE_TEXT ){ - const u8 *z = (const u8*)sqlite3_column_text(pTab->pDfltStmt, ii); - sessionAppendBlob(pOut, z, n, &rc); - }else{ - const u8 *z = (const u8*)sqlite3_column_blob(pTab->pDfltStmt, ii); - sessionAppendBlob(pOut, z, n, &rc); - } - break; - } - - default: - assert( eType==SQLITE_NULL ); - break; - } - } - }else if( op==SQLITE_UPDATE ){ - /* Append missing "undefined" entries to the old.* record. And, if this - ** is an UPDATE, to the new.* record as well. */ - int iOff = 0; - if( pGrp->bPatch==0 ){ - for(ii=0; iinCol-nCol); ii++){ - sessionAppendByte(pOut, 0x00, &rc); - } - } - - sessionAppendBlob(pOut, &aRec[iOff], nRec-iOff, &rc); - for(ii=0; ii<(pTab->nCol-nCol); ii++){ - sessionAppendByte(pOut, 0x00, &rc); - } - }else{ - assert( op==SQLITE_DELETE && pGrp->bPatch ); - sessionAppendBlob(pOut, aRec, nRec, &rc); - } - - return rc; -} - -/* -** Locate or create a SessionTable object that may be used to add the -** change currently pointed to by iterator pIter to changegroup pGrp. -** If successful, set output variable (*ppTab) to point to the table -** object and return SQLITE_OK. Otherwise, if some error occurs, return -** an SQLite error code and leave (*ppTab) set to NULL. -*/ -static int sessionChangesetFindTable( - sqlite3_changegroup *pGrp, - const char *zTab, - sqlite3_changeset_iter *pIter, - SessionTable **ppTab -){ - int rc = SQLITE_OK; - SessionTable *pTab = 0; - int nTab = (int)strlen(zTab); - u8 *abPK = 0; - int nCol = 0; - - *ppTab = 0; - sqlite3changeset_pk(pIter, &abPK, &nCol); - - /* Search the list for an existing table */ - for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ - if( 0==sqlite3_strnicmp(pTab->zName, zTab, nTab+1) ) break; - } - - /* If one was not found above, create a new table now */ - if( !pTab ){ - SessionTable **ppNew; - - pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nTab+1); - if( !pTab ){ - return SQLITE_NOMEM; - } - memset(pTab, 0, sizeof(SessionTable)); - pTab->nCol = nCol; - pTab->abPK = (u8*)&pTab[1]; - memcpy(pTab->abPK, abPK, nCol); - pTab->zName = (char*)&pTab->abPK[nCol]; - memcpy(pTab->zName, zTab, nTab+1); - - if( pGrp->db ){ - pTab->nCol = 0; - rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb); - if( rc ){ - assert( pTab->azCol==0 ); - sqlite3_free(pTab); - return rc; - } - } - - /* The new object must be linked on to the end of the list, not - ** simply added to the start of it. This is to ensure that the - ** tables within the output of sqlite3changegroup_output() are in - ** the right order. */ - for(ppNew=&pGrp->pList; *ppNew; ppNew=&(*ppNew)->pNext); - *ppNew = pTab; - } - - /* Check that the table is compatible. */ - if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){ - rc = SQLITE_SCHEMA; - } - - *ppTab = pTab; - return rc; -} - -/* -** Add the change currently indicated by iterator pIter to the hash table -** belonging to changegroup pGrp. -*/ -static int sessionOneChangeToHash( - sqlite3_changegroup *pGrp, - sqlite3_changeset_iter *pIter, - int bRebase -){ - int rc = SQLITE_OK; - int nCol = 0; - int op = 0; - int iHash = 0; - int bIndirect = 0; - SessionChange *pChange = 0; - SessionChange *pExist = 0; - SessionChange **pp = 0; - SessionTable *pTab = 0; - u8 *aRec = &pIter->in.aData[pIter->in.iCurrent + 2]; - int nRec = (pIter->in.iNext - pIter->in.iCurrent) - 2; - - assert( nRec>0 ); - - /* Ensure that only changesets, or only patchsets, but not a mixture - ** of both, are being combined. It is an error to try to combine a - ** changeset and a patchset. */ - if( pGrp->pList==0 ){ - pGrp->bPatch = pIter->bPatchset; - }else if( pIter->bPatchset!=pGrp->bPatch ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_OK ){ - const char *zTab = 0; - sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); - rc = sessionChangesetFindTable(pGrp, zTab, pIter, &pTab); - } - - if( rc==SQLITE_OK && nColnCol ){ - SessionBuffer *pBuf = &pGrp->rec; - rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, pBuf); - aRec = pBuf->aBuf; - nRec = pBuf->nBuf; - assert( pGrp->db ); - } - - if( rc==SQLITE_OK && sessionGrowHash(0, pIter->bPatchset, pTab) ){ - rc = SQLITE_NOMEM; - } - - if( rc==SQLITE_OK ){ - /* Search for existing entry. If found, remove it from the hash table. - ** Code below may link it back in. */ + return SQLITE_OK; +} + +/* +** Add all changes in the changeset traversed by the iterator passed as +** the first argument to the changegroup hash tables. +*/ +static int sessionChangesetToHash( + sqlite3_changeset_iter *pIter, /* Iterator to read from */ + sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ +){ + u8 *aRec; + int nRec; + int rc = SQLITE_OK; + SessionTable *pTab = 0; + + + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ + const char *zNew; + int nCol; + int op; + int iHash; + int bIndirect; + SessionChange *pChange; + SessionChange *pExist = 0; + SessionChange **pp; + + if( pGrp->pList==0 ){ + pGrp->bPatch = pIter->bPatchset; + }else if( pIter->bPatchset!=pGrp->bPatch ){ + rc = SQLITE_ERROR; + break; + } + + sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); + if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ + /* Search the list for a matching table */ + int nNew = (int)strlen(zNew); + u8 *abPK; + + sqlite3changeset_pk(pIter, &abPK, 0); + for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; + } + if( !pTab ){ + SessionTable **ppTab; + + pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1); + if( !pTab ){ + rc = SQLITE_NOMEM; + break; + } + memset(pTab, 0, sizeof(SessionTable)); + pTab->nCol = nCol; + pTab->abPK = (u8*)&pTab[1]; + memcpy(pTab->abPK, abPK, nCol); + pTab->zName = (char*)&pTab->abPK[nCol]; + memcpy(pTab->zName, zNew, nNew+1); + + /* The new object must be linked on to the end of the list, not + ** simply added to the start of it. This is to ensure that the + ** tables within the output of sqlite3changegroup_output() are in + ** the right order. */ + for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext); + *ppTab = pTab; + }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ + rc = SQLITE_SCHEMA; + break; + } + } + + if( sessionGrowHash(pIter->bPatchset, pTab) ){ + rc = SQLITE_NOMEM; + break; + } iHash = sessionChangeHash( pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange ); + + /* Search for existing entry. If found, remove it from the hash table. + ** Code below may link it back in. + */ for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ int bPkOnly1 = 0; int bPkOnly2 = 0; if( pIter->bPatchset ){ bPkOnly1 = (*pp)->op==SQLITE_DELETE; @@ -232638,44 +180316,20 @@ *pp = (*pp)->pNext; pTab->nEntry--; break; } } - } - if( rc==SQLITE_OK ){ - rc = sessionChangeMerge(pTab, bRebase, + rc = sessionChangeMerge(pTab, pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); - } - if( rc==SQLITE_OK && pChange ){ - pChange->pNext = pTab->apChange[iHash]; - pTab->apChange[iHash] = pChange; - pTab->nEntry++; - } - - if( rc==SQLITE_OK ) rc = pIter->rc; - return rc; -} - -/* -** Add all changes in the changeset traversed by the iterator passed as -** the first argument to the changegroup hash tables. -*/ -static int sessionChangesetToHash( - sqlite3_changeset_iter *pIter, /* Iterator to read from */ - sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ - int bRebase /* True if hash table is for rebasing */ -){ - u8 *aRec; - int nRec; - int rc = SQLITE_OK; - - pIter->in.bNoDiscard = 1; - while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){ - rc = sessionOneChangeToHash(pGrp, pIter, bRebase); - if( rc!=SQLITE_OK ) break; + if( rc ) break; + if( pChange ){ + pChange->pNext = pTab->apChange[iHash]; + pTab->apChange[iHash] = pChange; + pTab->nEntry++; + } } if( rc==SQLITE_OK ) rc = pIter->rc; return rc; } @@ -232684,11 +180338,11 @@ ** Serialize a changeset (or patchset) based on all changesets (or patchsets) ** added to the changegroup object passed as the first argument. ** ** If xOutput is not NULL, then the changeset/patchset is returned to the ** user via one or more calls to xOutput, as with the other streaming -** interfaces. +** interfaces. ** ** Or, if xOutput is NULL, then (*ppOut) is populated with a pointer to a ** buffer containing the output changeset before this function returns. In ** this case (*pnOut) is set to the size of the output buffer in bytes. It ** is the responsibility of the caller to free the output buffer using @@ -232709,11 +180363,11 @@ SessionBuffer buf = {0, 0, 0}; SessionTable *pTab; assert( xOutput==0 || (ppOut==0 && pnOut==0) ); /* Create the serialized output changeset based on the contents of the - ** hash tables attached to the SessionTable objects in list p->pList. + ** hash tables attached to the SessionTable objects in list p->pList. */ for(pTab=pGrp->pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ int i; if( pTab->nEntry==0 ) continue; @@ -232722,24 +180376,25 @@ SessionChange *p; for(p=pTab->apChange[i]; p; p=p->pNext){ sessionAppendByte(&buf, p->op, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); - if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){ - rc = xOutput(pOut, buf.aBuf, buf.nBuf); - buf.nBuf = 0; - } } } + + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; + } } if( rc==SQLITE_OK ){ if( xOutput ){ if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); - }else if( ppOut ){ + }else{ *ppOut = buf.aBuf; - if( pnOut ) *pnOut = buf.nBuf; + *pnOut = buf.nBuf; buf.aBuf = 0; } } sqlite3_free(buf.aBuf); @@ -232760,35 +180415,10 @@ } *pp = p; return rc; } -/* -** Provide a database schema to the changegroup object. -*/ -SQLITE_API int sqlite3changegroup_schema( - sqlite3_changegroup *pGrp, - sqlite3 *db, - const char *zDb -){ - int rc = SQLITE_OK; - - if( pGrp->pList || pGrp->db ){ - /* Cannot add a schema after one or more calls to sqlite3changegroup_add(), - ** or after sqlite3changegroup_schema() has already been called. */ - rc = SQLITE_MISUSE; - }else{ - pGrp->zDb = sqlite3_mprintf("%s", zDb); - if( pGrp->zDb==0 ){ - rc = SQLITE_NOMEM; - }else{ - pGrp->db = db; - } - } - return rc; -} - /* ** Add the changeset currently stored in buffer pData, size nData bytes, ** to changeset-group p. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ @@ -232795,33 +180425,16 @@ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, pGrp, 0); + rc = sessionChangesetToHash(pIter, pGrp); } sqlite3changeset_finalize(pIter); return rc; } -/* -** Add a single change to a changeset-group. -*/ -SQLITE_API int sqlite3changegroup_add_change( - sqlite3_changegroup *pGrp, - sqlite3_changeset_iter *pIter -){ - if( pIter->in.iCurrent==pIter->in.iNext - || pIter->rc!=SQLITE_OK - || pIter->bInvert - ){ - /* Iterator does not point to any valid entry or is an INVERT iterator. */ - return SQLITE_ERROR; - } - return sessionOneChangeToHash(pGrp, pIter, 0); -} - /* ** Obtain a buffer containing a changeset representing the concatenation ** of all changesets added to the group so far. */ SQLITE_API int sqlite3changegroup_output( @@ -232843,11 +180456,11 @@ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, pGrp, 0); + rc = sessionChangesetToHash(pIter, pGrp); } sqlite3changeset_finalize(pIter); return rc; } @@ -232854,11 +180467,11 @@ /* ** Streaming versions of changegroup_output(). */ SQLITE_API int sqlite3changegroup_output_strm( sqlite3_changegroup *pGrp, - int (*xOutput)(void *pOut, const void *pData, int nData), + int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ){ return sessionChangegroupOutput(pGrp, xOutput, pOut, 0, 0); } @@ -232865,18 +180478,16 @@ /* ** Delete a changegroup object. */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ if( pGrp ){ - sqlite3_free(pGrp->zDb); - sessionDeleteTable(0, pGrp->pList); - sqlite3_free(pGrp->rec.aBuf); + sessionDeleteTable(pGrp->pList); sqlite3_free(pGrp); } } -/* +/* ** Combine two changesets together. */ SQLITE_API int sqlite3changeset_concat( int nLeft, /* Number of bytes in lhs input */ void *pLeft, /* Lhs input changeset */ @@ -232930,416 +180541,2455 @@ sqlite3changegroup_delete(pGrp); return rc; } -/* -** Changeset rebaser handle. -*/ -struct sqlite3_rebaser { - sqlite3_changegroup grp; /* Hash table */ -}; - -/* -** Buffers a1 and a2 must both contain a sessions module record nCol -** fields in size. This function appends an nCol sessions module -** record to buffer pBuf that is a copy of a1, except that for -** each field that is undefined in a1[], swap in the field from a2[]. -*/ -static void sessionAppendRecordMerge( - SessionBuffer *pBuf, /* Buffer to append to */ - int nCol, /* Number of columns in each record */ - u8 *a1, int n1, /* Record 1 */ - u8 *a2, int n2, /* Record 2 */ - int *pRc /* IN/OUT: error code */ -){ - sessionBufferGrow(pBuf, n1+n2, pRc); - if( *pRc==SQLITE_OK ){ - int i; - u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; - for(i=0; inBuf = pOut-pBuf->aBuf; - assert( pBuf->nBuf<=pBuf->nAlloc ); - } -} - -/* -** This function is called when rebasing a local UPDATE change against one -** or more remote UPDATE changes. The aRec/nRec buffer contains the current -** old.* and new.* records for the change. The rebase buffer (a single -** record) is in aChange/nChange. The rebased change is appended to buffer -** pBuf. -** -** Rebasing the UPDATE involves: -** -** * Removing any changes to fields for which the corresponding field -** in the rebase buffer is set to "replaced" (type 0xFF). If this -** means the UPDATE change updates no fields, nothing is appended -** to the output buffer. -** -** * For each field modified by the local change for which the -** corresponding field in the rebase buffer is not "undefined" (0x00) -** or "replaced" (0xFF), the old.* value is replaced by the value -** in the rebase buffer. -*/ -static void sessionAppendPartialUpdate( - SessionBuffer *pBuf, /* Append record here */ - sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */ - u8 *aRec, int nRec, /* Local change */ - u8 *aChange, int nChange, /* Record to rebase against */ - int *pRc /* IN/OUT: Return Code */ -){ - sessionBufferGrow(pBuf, 2+nRec+nChange, pRc); - if( *pRc==SQLITE_OK ){ - int bData = 0; - u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; - int i; - u8 *a1 = aRec; - u8 *a2 = aChange; - - *pOut++ = SQLITE_UPDATE; - *pOut++ = pIter->bIndirect; - for(i=0; inCol; i++){ - int n1 = sessionSerialLen(a1); - int n2 = sessionSerialLen(a2); - if( pIter->abPK[i] || a2[0]==0 ){ - if( !pIter->abPK[i] && a1[0] ) bData = 1; - memcpy(pOut, a1, n1); - pOut += n1; - }else if( a2[0]!=0xFF && a1[0] ){ - bData = 1; - memcpy(pOut, a2, n2); - pOut += n2; - }else{ - *pOut++ = '\0'; - } - a1 += n1; - a2 += n2; - } - if( bData ){ - a2 = aChange; - for(i=0; inCol; i++){ - int n1 = sessionSerialLen(a1); - int n2 = sessionSerialLen(a2); - if( pIter->abPK[i] || a2[0]!=0xFF ){ - memcpy(pOut, a1, n1); - pOut += n1; - }else{ - *pOut++ = '\0'; - } - a1 += n1; - a2 += n2; - } - pBuf->nBuf = (pOut - pBuf->aBuf); - } - } -} - -/* -** pIter is configured to iterate through a changeset. This function rebases -** that changeset according to the current configuration of the rebaser -** object passed as the first argument. If no error occurs and argument xOutput -** is not NULL, then the changeset is returned to the caller by invoking -** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL, -** then (*ppOut) is set to point to a buffer containing the rebased changeset -** before this function returns. In this case (*pnOut) is set to the size of -** the buffer in bytes. It is the responsibility of the caller to eventually -** free the (*ppOut) buffer using sqlite3_free(). -** -** If an error occurs, an SQLite error code is returned. If ppOut and -** pnOut are not NULL, then the two output parameters are set to 0 before -** returning. -*/ -static int sessionRebase( - sqlite3_rebaser *p, /* Rebaser hash table */ - sqlite3_changeset_iter *pIter, /* Input data */ - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut, /* Context for xOutput callback */ - int *pnOut, /* OUT: Number of bytes in output changeset */ - void **ppOut /* OUT: Inverse of pChangeset */ -){ - int rc = SQLITE_OK; - u8 *aRec = 0; - int nRec = 0; - int bNew = 0; - SessionTable *pTab = 0; - SessionBuffer sOut = {0,0,0}; - - while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ - SessionChange *pChange = 0; - int bDone = 0; - - if( bNew ){ - const char *zTab = pIter->zTab; - for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ - if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; - } - bNew = 0; - - /* A patchset may not be rebased */ - if( pIter->bPatchset ){ - rc = SQLITE_ERROR; - } - - /* Append a table header to the output for this new table */ - sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc); - sessionAppendVarint(&sOut, pIter->nCol, &rc); - sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc); - sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc); - } - - if( pTab && rc==SQLITE_OK ){ - int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange); - - for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ - if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){ - break; - } - } - } - - if( pChange ){ - assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT ); - switch( pIter->op ){ - case SQLITE_INSERT: - if( pChange->op==SQLITE_INSERT ){ - bDone = 1; - if( pChange->bIndirect==0 ){ - sessionAppendByte(&sOut, SQLITE_UPDATE, &rc); - sessionAppendByte(&sOut, pIter->bIndirect, &rc); - sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc); - sessionAppendBlob(&sOut, aRec, nRec, &rc); - } - } - break; - - case SQLITE_UPDATE: - bDone = 1; - if( pChange->op==SQLITE_DELETE ){ - if( pChange->bIndirect==0 ){ - u8 *pCsr = aRec; - sessionSkipRecord(&pCsr, pIter->nCol); - sessionAppendByte(&sOut, SQLITE_INSERT, &rc); - sessionAppendByte(&sOut, pIter->bIndirect, &rc); - sessionAppendRecordMerge(&sOut, pIter->nCol, - pCsr, nRec-(pCsr-aRec), - pChange->aRecord, pChange->nRecord, &rc - ); - } - }else{ - sessionAppendPartialUpdate(&sOut, pIter, - aRec, nRec, pChange->aRecord, pChange->nRecord, &rc - ); - } - break; - - default: - assert( pIter->op==SQLITE_DELETE ); - bDone = 1; - if( pChange->op==SQLITE_INSERT ){ - sessionAppendByte(&sOut, SQLITE_DELETE, &rc); - sessionAppendByte(&sOut, pIter->bIndirect, &rc); - sessionAppendRecordMerge(&sOut, pIter->nCol, - pChange->aRecord, pChange->nRecord, aRec, nRec, &rc - ); - } - break; - } - } - - if( bDone==0 ){ - sessionAppendByte(&sOut, pIter->op, &rc); - sessionAppendByte(&sOut, pIter->bIndirect, &rc); - sessionAppendBlob(&sOut, aRec, nRec, &rc); - } - if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){ - rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); - sOut.nBuf = 0; - } - if( rc ) break; - } - - if( rc!=SQLITE_OK ){ - sqlite3_free(sOut.aBuf); - memset(&sOut, 0, sizeof(sOut)); - } - - if( rc==SQLITE_OK ){ - if( xOutput ){ - if( sOut.nBuf>0 ){ - rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); - } - }else if( ppOut ){ - *ppOut = (void*)sOut.aBuf; - *pnOut = sOut.nBuf; - sOut.aBuf = 0; - } - } - sqlite3_free(sOut.aBuf); - return rc; -} - -/* -** Create a new rebaser object. -*/ -SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ - int rc = SQLITE_OK; - sqlite3_rebaser *pNew; - - pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pNew, 0, sizeof(sqlite3_rebaser)); - } - *ppNew = pNew; - return rc; -} - -/* -** Call this one or more times to configure a rebaser. -*/ -SQLITE_API int sqlite3rebaser_configure( - sqlite3_rebaser *p, - int nRebase, const void *pRebase -){ - sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */ - int rc; /* Return code */ - rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase); - if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, &p->grp, 1); - } - sqlite3changeset_finalize(pIter); - return rc; -} - -/* -** Rebase a changeset according to current rebaser configuration -*/ -SQLITE_API int sqlite3rebaser_rebase( - sqlite3_rebaser *p, - int nIn, const void *pIn, - int *pnOut, void **ppOut -){ - sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ - int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); - - if( rc==SQLITE_OK ){ - rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); - sqlite3changeset_finalize(pIter); - } - - return rc; -} - -/* -** Rebase a changeset according to current rebaser configuration -*/ -SQLITE_API int sqlite3rebaser_rebase_strm( - sqlite3_rebaser *p, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -){ - sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); - - if( rc==SQLITE_OK ){ - rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); - sqlite3changeset_finalize(pIter); - } - - return rc; -} - -/* -** Destroy a rebaser object -*/ -SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){ - if( p ){ - sessionDeleteTable(0, p->grp.pList); - sqlite3_free(p->grp.rec.aBuf); - sqlite3_free(p); - } -} - -/* -** Global configuration -*/ -SQLITE_API int sqlite3session_config(int op, void *pArg){ - int rc = SQLITE_OK; - switch( op ){ - case SQLITE_SESSION_CONFIG_STRMSIZE: { - int *pInt = (int*)pArg; - if( *pInt>0 ){ - sessions_strm_chunk_size = *pInt; - } - *pInt = sessions_strm_chunk_size; - break; - } - default: - rc = SQLITE_MISUSE; - break; - } - return rc; -} - #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ /************** End of sqlite3session.c **************************************/ +/************** Begin file json1.c *******************************************/ +/* +** 2015-08-12 +** +** 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 SQLite extension implements JSON functions. The interface is +** modeled after MySQL JSON functions: +** +** https://dev.mysql.com/doc/refman/5.7/en/json.html +** +** For the time being, all JSON is stored as pure text. (We might add +** a JSONB type in the future which stores a binary encoding of JSON in +** a BLOB, but there is no support for JSONB in the current implementation. +** This implementation parses JSON text at 250 MB/s, so it is hard to see +** how JSONB might improve on that.) +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) +#if !defined(SQLITEINT_H) +/* #include "sqlite3ext.h" */ +#endif +SQLITE_EXTENSION_INIT1 +/* #include */ +/* #include */ +/* #include */ +/* #include */ + +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif + +#ifndef LARGEST_INT64 +# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +#endif + +/* +** Versions of isspace(), isalnum() and isdigit() to which it is safe +** to pass signed char values. +*/ +#ifdef sqlite3Isdigit + /* Use the SQLite core versions if this routine is part of the + ** SQLite amalgamation */ +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isxdigit(x) sqlite3Isxdigit(x) +#else + /* Use the standard library for separate compilation */ +#include /* amalgamator: keep */ +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +#endif + +/* +** Growing our own isspace() routine this way is twice as fast as +** the library isspace() function, resulting in a 7% overall performance +** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +*/ +static const char jsonIsSpace[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) + +#ifndef SQLITE_AMALGAMATION + /* Unsigned integer types. These are already defined in the sqliteInt.h, + ** but the definitions need to be repeated for separate compilation. */ + typedef sqlite3_uint64 u64; + typedef unsigned int u32; + typedef unsigned short int u16; + typedef unsigned char u8; +#endif + +/* Objects */ +typedef struct JsonString JsonString; +typedef struct JsonNode JsonNode; +typedef struct JsonParse JsonParse; + +/* An instance of this object represents a JSON string +** under construction. Really, this is a generic string accumulator +** that can be and is used to create strings other than JSON. +*/ +struct JsonString { + sqlite3_context *pCtx; /* Function context - put error messages here */ + char *zBuf; /* Append JSON content here */ + u64 nAlloc; /* Bytes of storage available in zBuf[] */ + u64 nUsed; /* Bytes of zBuf[] currently used */ + u8 bStatic; /* True if zBuf is static space */ + u8 bErr; /* True if an error has been encountered */ + char zSpace[100]; /* Initial static space */ +}; + +/* JSON type values +*/ +#define JSON_NULL 0 +#define JSON_TRUE 1 +#define JSON_FALSE 2 +#define JSON_INT 3 +#define JSON_REAL 4 +#define JSON_STRING 5 +#define JSON_ARRAY 6 +#define JSON_OBJECT 7 + +/* The "subtype" set for JSON values */ +#define JSON_SUBTYPE 74 /* Ascii for "J" */ + +/* +** Names of the various JSON types: +*/ +static const char * const jsonType[] = { + "null", "true", "false", "integer", "real", "text", "array", "object" +}; + +/* Bit values for the JsonNode.jnFlag field +*/ +#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ +#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ +#define JNODE_REMOVE 0x04 /* Do not output */ +#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */ +#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */ +#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ +#define JNODE_LABEL 0x40 /* Is a label of an object */ + + +/* A single node of parsed JSON +*/ +struct JsonNode { + u8 eType; /* One of the JSON_ type values */ + u8 jnFlags; /* JNODE flags */ + u32 n; /* Bytes of content, or number of sub-nodes */ + union { + const char *zJContent; /* Content for INT, REAL, and STRING */ + u32 iAppend; /* More terms for ARRAY and OBJECT */ + u32 iKey; /* Key for ARRAY objects in json_tree() */ + u32 iReplace; /* Replacement content for JNODE_REPLACE */ + JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */ + } u; +}; + +/* A completely parsed JSON string +*/ +struct JsonParse { + u32 nNode; /* Number of slots of aNode[] used */ + u32 nAlloc; /* Number of slots of aNode[] allocated */ + JsonNode *aNode; /* Array of nodes containing the parse */ + const char *zJson; /* Original JSON string */ + u32 *aUp; /* Index of parent of each node */ + u8 oom; /* Set to true if out of memory */ + u8 nErr; /* Number of errors seen */ + u16 iDepth; /* Nesting depth */ + int nJson; /* Length of the zJson string in bytes */ +}; + +/* +** Maximum nesting depth of JSON for this implementation. +** +** This limit is needed to avoid a stack overflow in the recursive +** descent parser. A depth of 2000 is far deeper than any sane JSON +** should go. +*/ +#define JSON_MAX_DEPTH 2000 + +/************************************************************************** +** Utility routines for dealing with JsonString objects +**************************************************************************/ + +/* Set the JsonString object to an empty string +*/ +static void jsonZero(JsonString *p){ + p->zBuf = p->zSpace; + p->nAlloc = sizeof(p->zSpace); + p->nUsed = 0; + p->bStatic = 1; +} + +/* Initialize the JsonString object +*/ +static void jsonInit(JsonString *p, sqlite3_context *pCtx){ + p->pCtx = pCtx; + p->bErr = 0; + jsonZero(p); +} + + +/* Free all allocated memory and reset the JsonString object back to its +** initial state. +*/ +static void jsonReset(JsonString *p){ + if( !p->bStatic ) sqlite3_free(p->zBuf); + jsonZero(p); +} + + +/* Report an out-of-memory (OOM) condition +*/ +static void jsonOom(JsonString *p){ + p->bErr = 1; + sqlite3_result_error_nomem(p->pCtx); + jsonReset(p); +} + +/* Enlarge pJson->zBuf so that it can hold at least N more bytes. +** Return zero on success. Return non-zero on an OOM error +*/ +static int jsonGrow(JsonString *p, u32 N){ + u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; + char *zNew; + if( p->bStatic ){ + if( p->bErr ) return 1; + zNew = sqlite3_malloc64(nTotal); + if( zNew==0 ){ + jsonOom(p); + return SQLITE_NOMEM; + } + memcpy(zNew, p->zBuf, (size_t)p->nUsed); + p->zBuf = zNew; + p->bStatic = 0; + }else{ + zNew = sqlite3_realloc64(p->zBuf, nTotal); + if( zNew==0 ){ + jsonOom(p); + return SQLITE_NOMEM; + } + p->zBuf = zNew; + } + p->nAlloc = nTotal; + return SQLITE_OK; +} + +/* Append N bytes from zIn onto the end of the JsonString string. +*/ +static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ + if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; + memcpy(p->zBuf+p->nUsed, zIn, N); + p->nUsed += N; +} + +/* Append formatted text (not to exceed N bytes) to the JsonString. +*/ +static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ + va_list ap; + if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; + va_start(ap, zFormat); + sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); + va_end(ap); + p->nUsed += (int)strlen(p->zBuf+p->nUsed); +} + +/* Append a single character +*/ +static void jsonAppendChar(JsonString *p, char c){ + if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; + p->zBuf[p->nUsed++] = c; +} + +/* Append a comma separator to the output buffer, if the previous +** character is not '[' or '{'. +*/ +static void jsonAppendSeparator(JsonString *p){ + char c; + if( p->nUsed==0 ) return; + c = p->zBuf[p->nUsed-1]; + if( c!='[' && c!='{' ) jsonAppendChar(p, ','); +} + +/* Append the N-byte string in zIn to the end of the JsonString string +** under construction. Enclose the string in "..." and escape +** any double-quotes or backslash characters contained within the +** string. +*/ +static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ + u32 i; + if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; + p->zBuf[p->nUsed++] = '"'; + for(i=0; inUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + }else if( c<=0x1f ){ + static const char aSpecial[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + assert( sizeof(aSpecial)==32 ); + assert( aSpecial['\b']=='b' ); + assert( aSpecial['\f']=='f' ); + assert( aSpecial['\n']=='n' ); + assert( aSpecial['\r']=='r' ); + assert( aSpecial['\t']=='t' ); + if( aSpecial[c] ){ + c = aSpecial[c]; + goto json_simple_escape; + } + if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + p->zBuf[p->nUsed++] = 'u'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0' + (c>>4); + c = "0123456789abcdef"[c&0xf]; + } + p->zBuf[p->nUsed++] = c; + } + p->zBuf[p->nUsed++] = '"'; + assert( p->nUsednAlloc ); +} + +/* +** Append a function parameter value to the JSON string under +** construction. +*/ +static void jsonAppendValue( + JsonString *p, /* Append to this JSON string */ + sqlite3_value *pValue /* Value to append */ +){ + switch( sqlite3_value_type(pValue) ){ + case SQLITE_NULL: { + jsonAppendRaw(p, "null", 4); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + jsonAppendRaw(p, z, n); + break; + } + case SQLITE_TEXT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ + jsonAppendRaw(p, z, n); + }else{ + jsonAppendString(p, z, n); + } + break; + } + default: { + if( p->bErr==0 ){ + sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); + p->bErr = 2; + jsonReset(p); + } + break; + } + } +} + + +/* Make the JSON in p the result of the SQL function. +*/ +static void jsonResult(JsonString *p){ + if( p->bErr==0 ){ + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, + SQLITE_UTF8); + jsonZero(p); + } + assert( p->bStatic ); +} + +/************************************************************************** +** Utility routines for dealing with JsonNode and JsonParse objects +**************************************************************************/ + +/* +** Return the number of consecutive JsonNode slots need to represent +** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and +** OBJECT types, the number might be larger. +** +** Appended elements are not counted. The value returned is the number +** by which the JsonNode counter should increment in order to go to the +** next peer value. +*/ +static u32 jsonNodeSize(JsonNode *pNode){ + return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; +} + +/* +** Reclaim all memory allocated by a JsonParse object. But do not +** delete the JsonParse object itself. +*/ +static void jsonParseReset(JsonParse *pParse){ + sqlite3_free(pParse->aNode); + pParse->aNode = 0; + pParse->nNode = 0; + pParse->nAlloc = 0; + sqlite3_free(pParse->aUp); + pParse->aUp = 0; +} + +/* +** Free a JsonParse object that was obtained from sqlite3_malloc(). +*/ +static void jsonParseFree(JsonParse *pParse){ + jsonParseReset(pParse); + sqlite3_free(pParse); +} + +/* +** Convert the JsonNode pNode into a pure JSON string and +** append to pOut. Subsubstructure is also included. Return +** the number of JsonNode objects that are encoded. +*/ +static void jsonRenderNode( + JsonNode *pNode, /* The node to render */ + JsonString *pOut, /* Write JSON here */ + sqlite3_value **aReplace /* Replacement values */ +){ + if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ + if( pNode->jnFlags & JNODE_REPLACE ){ + jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); + return; + } + pNode = pNode->u.pPatch; + } + switch( pNode->eType ){ + default: { + assert( pNode->eType==JSON_NULL ); + jsonAppendRaw(pOut, "null", 4); + break; + } + case JSON_TRUE: { + jsonAppendRaw(pOut, "true", 4); + break; + } + case JSON_FALSE: { + jsonAppendRaw(pOut, "false", 5); + break; + } + case JSON_STRING: { + if( pNode->jnFlags & JNODE_RAW ){ + jsonAppendString(pOut, pNode->u.zJContent, pNode->n); + break; + } + /* Fall through into the next case */ + } + case JSON_REAL: + case JSON_INT: { + jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case JSON_ARRAY: { + u32 j = 1; + jsonAppendChar(pOut, '['); + for(;;){ + while( j<=pNode->n ){ + if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ + jsonAppendSeparator(pOut); + jsonRenderNode(&pNode[j], pOut, aReplace); + } + j += jsonNodeSize(&pNode[j]); + } + if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + jsonAppendChar(pOut, ']'); + break; + } + case JSON_OBJECT: { + u32 j = 1; + jsonAppendChar(pOut, '{'); + for(;;){ + while( j<=pNode->n ){ + if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ + jsonAppendSeparator(pOut); + jsonRenderNode(&pNode[j], pOut, aReplace); + jsonAppendChar(pOut, ':'); + jsonRenderNode(&pNode[j+1], pOut, aReplace); + } + j += 1 + jsonNodeSize(&pNode[j+1]); + } + if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + jsonAppendChar(pOut, '}'); + break; + } + } +} + +/* +** Return a JsonNode and all its descendents as a JSON string. +*/ +static void jsonReturnJson( + JsonNode *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + JsonString s; + jsonInit(&s, pCtx); + jsonRenderNode(pNode, &s, aReplace); + jsonResult(&s); + sqlite3_result_subtype(pCtx, JSON_SUBTYPE); +} + +/* +** Make the JsonNode the return value of the function. +*/ +static void jsonReturn( + JsonNode *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + switch( pNode->eType ){ + default: { + assert( pNode->eType==JSON_NULL ); + sqlite3_result_null(pCtx); + break; + } + case JSON_TRUE: { + sqlite3_result_int(pCtx, 1); + break; + } + case JSON_FALSE: { + sqlite3_result_int(pCtx, 0); + break; + } + case JSON_INT: { + sqlite3_int64 i = 0; + const char *z = pNode->u.zJContent; + if( z[0]=='-' ){ z++; } + while( z[0]>='0' && z[0]<='9' ){ + unsigned v = *(z++) - '0'; + if( i>=LARGEST_INT64/10 ){ + if( i>LARGEST_INT64/10 ) goto int_as_real; + if( z[0]>='0' && z[0]<='9' ) goto int_as_real; + if( v==9 ) goto int_as_real; + if( v==8 ){ + if( pNode->u.zJContent[0]=='-' ){ + sqlite3_result_int64(pCtx, SMALLEST_INT64); + goto int_done; + }else{ + goto int_as_real; + } + } + } + i = i*10 + v; + } + if( pNode->u.zJContent[0]=='-' ){ i = -i; } + sqlite3_result_int64(pCtx, i); + int_done: + break; + int_as_real: /* fall through to real */; + } + case JSON_REAL: { + double r; +#ifdef SQLITE_AMALGAMATION + const char *z = pNode->u.zJContent; + sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); +#else + r = strtod(pNode->u.zJContent, 0); +#endif + sqlite3_result_double(pCtx, r); + break; + } + case JSON_STRING: { +#if 0 /* Never happens because JNODE_RAW is only set by json_set(), + ** json_insert() and json_replace() and those routines do not + ** call jsonReturn() */ + if( pNode->jnFlags & JNODE_RAW ){ + sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, + SQLITE_TRANSIENT); + }else +#endif + assert( (pNode->jnFlags & JNODE_RAW)==0 ); + if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){ + /* JSON formatted without any backslash-escapes */ + sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, + SQLITE_TRANSIENT); + }else{ + /* Translate JSON formatted string into raw text */ + u32 i; + u32 n = pNode->n; + const char *z = pNode->u.zJContent; + char *zOut; + u32 j; + zOut = sqlite3_malloc( n+1 ); + if( zOut==0 ){ + sqlite3_result_error_nomem(pCtx); + break; + } + for(i=1, j=0; i>6)); + zOut[j++] = 0x80 | (v&0x3f); + }else{ + zOut[j++] = (char)(0xe0 | (v>>12)); + zOut[j++] = 0x80 | ((v>>6)&0x3f); + zOut[j++] = 0x80 | (v&0x3f); + } + }else{ + if( c=='b' ){ + c = '\b'; + }else if( c=='f' ){ + c = '\f'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='r' ){ + c = '\r'; + }else if( c=='t' ){ + c = '\t'; + } + zOut[j++] = c; + } + } + } + zOut[j] = 0; + sqlite3_result_text(pCtx, zOut, j, sqlite3_free); + } + break; + } + case JSON_ARRAY: + case JSON_OBJECT: { + jsonReturnJson(pNode, pCtx, aReplace); + break; + } + } +} + +/* Forward reference */ +static int jsonParseAddNode(JsonParse*,u32,u32,const char*); + +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define JSON_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && _MSC_VER>=1310 +# define JSON_NOINLINE __declspec(noinline) +#else +# define JSON_NOINLINE +#endif + + +static JSON_NOINLINE int jsonParseAddNodeExpand( + JsonParse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + u32 nNew; + JsonNode *pNew; + assert( pParse->nNode>=pParse->nAlloc ); + if( pParse->oom ) return -1; + nNew = pParse->nAlloc*2 + 10; + pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew); + if( pNew==0 ){ + pParse->oom = 1; + return -1; + } + pParse->nAlloc = nNew; + pParse->aNode = pNew; + assert( pParse->nNodenAlloc ); + return jsonParseAddNode(pParse, eType, n, zContent); +} + +/* +** Create a new JsonNode instance based on the arguments and append that +** instance to the JsonParse. Return the index in pParse->aNode[] of the +** new node, or -1 if a memory allocation fails. +*/ +static int jsonParseAddNode( + JsonParse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + JsonNode *p; + if( pParse->nNode>=pParse->nAlloc ){ + return jsonParseAddNodeExpand(pParse, eType, n, zContent); + } + p = &pParse->aNode[pParse->nNode]; + p->eType = (u8)eType; + p->jnFlags = 0; + p->n = n; + p->u.zJContent = zContent; + return pParse->nNode++; +} + +/* +** Return true if z[] begins with 4 (or more) hexadecimal digits +*/ +static int jsonIs4Hex(const char *z){ + int i; + for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + return 1; +} + +/* +** Parse a single JSON value which begins at pParse->zJson[i]. Return the +** index of the first character past the end of the value parsed. +** +** Return negative for a syntax error. Special cases: return -2 if the +** first non-whitespace character is '}' and return -3 if the first +** non-whitespace character is ']'. +*/ +static int jsonParseValue(JsonParse *pParse, u32 i){ + char c; + u32 j; + int iThis; + int x; + JsonNode *pNode; + const char *z = pParse->zJson; + while( safe_isspace(z[i]) ){ i++; } + if( (c = z[i])=='{' ){ + /* Parse object */ + iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); + if( iThis<0 ) return -1; + for(j=i+1;;j++){ + while( safe_isspace(z[j]) ){ j++; } + if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; + x = jsonParseValue(pParse, j); + if( x<0 ){ + pParse->iDepth--; + if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1; + return -1; + } + if( pParse->oom ) return -1; + pNode = &pParse->aNode[pParse->nNode-1]; + if( pNode->eType!=JSON_STRING ) return -1; + pNode->jnFlags |= JNODE_LABEL; + j = x; + while( safe_isspace(z[j]) ){ j++; } + if( z[j]!=':' ) return -1; + j++; + x = jsonParseValue(pParse, j); + pParse->iDepth--; + if( x<0 ) return -1; + j = x; + while( safe_isspace(z[j]) ){ j++; } + c = z[j]; + if( c==',' ) continue; + if( c!='}' ) return -1; + break; + } + pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + return j+1; + }else if( c=='[' ){ + /* Parse array */ + iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); + if( iThis<0 ) return -1; + for(j=i+1;;j++){ + while( safe_isspace(z[j]) ){ j++; } + if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; + x = jsonParseValue(pParse, j); + pParse->iDepth--; + if( x<0 ){ + if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1; + return -1; + } + j = x; + while( safe_isspace(z[j]) ){ j++; } + c = z[j]; + if( c==',' ) continue; + if( c!=']' ) return -1; + break; + } + pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + return j+1; + }else if( c=='"' ){ + /* Parse string */ + u8 jnFlags = 0; + j = i+1; + for(;;){ + c = z[j]; + if( (c & ~0x1f)==0 ){ + /* Control characters are not allowed in strings */ + return -1; + } + if( c=='\\' ){ + c = z[++j]; + if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' + || c=='n' || c=='r' || c=='t' + || (c=='u' && jsonIs4Hex(z+j+1)) ){ + jnFlags = JNODE_ESCAPE; + }else{ + return -1; + } + }else if( c=='"' ){ + break; + } + j++; + } + jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]); + if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags; + return j+1; + }else if( c=='n' + && strncmp(z+i,"null",4)==0 + && !safe_isalnum(z[i+4]) ){ + jsonParseAddNode(pParse, JSON_NULL, 0, 0); + return i+4; + }else if( c=='t' + && strncmp(z+i,"true",4)==0 + && !safe_isalnum(z[i+4]) ){ + jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + return i+4; + }else if( c=='f' + && strncmp(z+i,"false",5)==0 + && !safe_isalnum(z[i+5]) ){ + jsonParseAddNode(pParse, JSON_FALSE, 0, 0); + return i+5; + }else if( c=='-' || (c>='0' && c<='9') ){ + /* Parse number */ + u8 seenDP = 0; + u8 seenE = 0; + assert( '-' < '0' ); + if( c<='0' ){ + j = c=='-' ? i+1 : i; + if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1; + } + j = i+1; + for(;; j++){ + c = z[j]; + if( c>='0' && c<='9' ) continue; + if( c=='.' ){ + if( z[j-1]=='-' ) return -1; + if( seenDP ) return -1; + seenDP = 1; + continue; + } + if( c=='e' || c=='E' ){ + if( z[j-1]<'0' ) return -1; + if( seenE ) return -1; + seenDP = seenE = 1; + c = z[j+1]; + if( c=='+' || c=='-' ){ + j++; + c = z[j+1]; + } + if( c<'0' || c>'9' ) return -1; + continue; + } + break; + } + if( z[j-1]<'0' ) return -1; + jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT, + j - i, &z[i]); + return j; + }else if( c=='}' ){ + return -2; /* End of {...} */ + }else if( c==']' ){ + return -3; /* End of [...] */ + }else if( c==0 ){ + return 0; /* End of file */ + }else{ + return -1; /* Syntax error */ + } +} + +/* +** Parse a complete JSON string. Return 0 on success or non-zero if there +** are any errors. If an error occurs, free all memory associated with +** pParse. +** +** pParse is uninitialized when this routine is called. +*/ +static int jsonParse( + JsonParse *pParse, /* Initialize and fill this JsonParse object */ + sqlite3_context *pCtx, /* Report errors here */ + const char *zJson /* Input JSON text to be parsed */ +){ + int i; + memset(pParse, 0, sizeof(*pParse)); + if( zJson==0 ) return 1; + pParse->zJson = zJson; + i = jsonParseValue(pParse, 0); + if( pParse->oom ) i = -1; + if( i>0 ){ + assert( pParse->iDepth==0 ); + while( safe_isspace(zJson[i]) ) i++; + if( zJson[i] ) i = -1; + } + if( i<=0 ){ + if( pCtx!=0 ){ + if( pParse->oom ){ + sqlite3_result_error_nomem(pCtx); + }else{ + sqlite3_result_error(pCtx, "malformed JSON", -1); + } + } + jsonParseReset(pParse); + return 1; + } + return 0; +} + +/* Mark node i of pParse as being a child of iParent. Call recursively +** to fill in all the descendants of node i. +*/ +static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ + JsonNode *pNode = &pParse->aNode[i]; + u32 j; + pParse->aUp[i] = iParent; + switch( pNode->eType ){ + case JSON_ARRAY: { + for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ + jsonParseFillInParentage(pParse, i+j, i); + } + break; + } + case JSON_OBJECT: { + for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ + pParse->aUp[i+j] = i; + jsonParseFillInParentage(pParse, i+j+1, i); + } + break; + } + default: { + break; + } + } +} + +/* +** Compute the parentage of all nodes in a completed parse. +*/ +static int jsonParseFindParents(JsonParse *pParse){ + u32 *aUp; + assert( pParse->aUp==0 ); + aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode ); + if( aUp==0 ){ + pParse->oom = 1; + return SQLITE_NOMEM; + } + jsonParseFillInParentage(pParse, 0, 0); + return SQLITE_OK; +} + +/* +** Magic number used for the JSON parse cache in sqlite3_get_auxdata() +*/ +#define JSON_CACHE_ID (-429938) + +/* +** Obtain a complete parse of the JSON found in the first argument +** of the argv array. Use the sqlite3_get_auxdata() cache for this +** parse if it is available. If the cache is not available or if it +** is no longer valid, parse the JSON again and return the new parse, +** and also register the new parse so that it will be available for +** future sqlite3_get_auxdata() calls. +*/ +static JsonParse *jsonParseCached( + sqlite3_context *pCtx, + sqlite3_value **argv +){ + const char *zJson = (const char*)sqlite3_value_text(argv[0]); + int nJson = sqlite3_value_bytes(argv[0]); + JsonParse *p; + if( zJson==0 ) return 0; + p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); + if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){ + p->nErr = 0; + return p; /* The cached entry matches, so return it */ + } + p = sqlite3_malloc( sizeof(*p) + nJson + 1 ); + if( p==0 ){ + sqlite3_result_error_nomem(pCtx); + return 0; + } + memset(p, 0, sizeof(*p)); + p->zJson = (char*)&p[1]; + memcpy((char*)p->zJson, zJson, nJson+1); + if( jsonParse(p, pCtx, p->zJson) ){ + sqlite3_free(p); + return 0; + } + p->nJson = nJson; + sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree); + return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); +} + +/* +** Compare the OBJECT label at pNode against zKey,nKey. Return true on +** a match. +*/ +static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ + if( pNode->jnFlags & JNODE_RAW ){ + if( pNode->n!=nKey ) return 0; + return strncmp(pNode->u.zJContent, zKey, nKey)==0; + }else{ + if( pNode->n!=nKey+2 ) return 0; + return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; + } +} + +/* forward declaration */ +static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**); + +/* +** Search along zPath to find the node specified. Return a pointer +** to that node, or NULL if zPath is malformed or if there is no such +** node. +** +** If pApnd!=0, then try to append new nodes to complete zPath if it is +** possible to do so and if no existing node corresponds to zPath. If +** new nodes are appended *pApnd is set to 1. +*/ +static JsonNode *jsonLookupStep( + JsonParse *pParse, /* The JSON to search */ + u32 iRoot, /* Begin the search at this node */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + const char **pzErr /* Make *pzErr point to any syntax error in zPath */ +){ + u32 i, j, nKey; + const char *zKey; + JsonNode *pRoot = &pParse->aNode[iRoot]; + if( zPath[0]==0 ) return pRoot; + if( zPath[0]=='.' ){ + if( pRoot->eType!=JSON_OBJECT ) return 0; + zPath++; + if( zPath[0]=='"' ){ + zKey = zPath + 1; + for(i=1; zPath[i] && zPath[i]!='"'; i++){} + nKey = i-1; + if( zPath[i] ){ + i++; + }else{ + *pzErr = zPath; + return 0; + } + }else{ + zKey = zPath; + for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} + nKey = i; + } + if( nKey==0 ){ + *pzErr = zPath; + return 0; + } + j = 1; + for(;;){ + while( j<=pRoot->n ){ + if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ + return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); + } + j++; + j += jsonNodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( pApnd ){ + u32 iStart, iLabel; + JsonNode *pNode; + iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); + iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); + zPath += i; + pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= JNODE_APPEND; + pParse->aNode[iLabel].jnFlags |= JNODE_RAW; + } + return pNode; + } + }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){ + if( pRoot->eType!=JSON_ARRAY ) return 0; + i = 0; + j = 1; + while( safe_isdigit(zPath[j]) ){ + i = i*10 + zPath[j] - '0'; + j++; + } + if( zPath[j]!=']' ){ + *pzErr = zPath; + return 0; + } + zPath += j + 1; + j = 1; + for(;;){ + while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ + if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; + j += jsonNodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( j<=pRoot->n ){ + return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); + } + if( i==0 && pApnd ){ + u32 iStart; + JsonNode *pNode; + iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); + pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= JNODE_APPEND; + } + return pNode; + } + }else{ + *pzErr = zPath; + } + return 0; +} + +/* +** Append content to pParse that will complete zPath. Return a pointer +** to the inserted node, or return NULL if the append fails. +*/ +static JsonNode *jsonLookupAppend( + JsonParse *pParse, /* Append content to the JSON parse */ + const char *zPath, /* Description of content to append */ + int *pApnd, /* Set this flag to 1 */ + const char **pzErr /* Make this point to any syntax error */ +){ + *pApnd = 1; + if( zPath[0]==0 ){ + jsonParseAddNode(pParse, JSON_NULL, 0, 0); + return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; + } + if( zPath[0]=='.' ){ + jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); + }else if( strncmp(zPath,"[0]",3)==0 ){ + jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); + }else{ + return 0; + } + if( pParse->oom ) return 0; + return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); +} + +/* +** Return the text of a syntax error message on a JSON path. Space is +** obtained from sqlite3_malloc(). +*/ +static char *jsonPathSyntaxError(const char *zErr){ + return sqlite3_mprintf("JSON path error near '%q'", zErr); +} + +/* +** Do a node lookup using zPath. Return a pointer to the node on success. +** Return NULL if not found or if there is an error. +** +** On an error, write an error message into pCtx and increment the +** pParse->nErr counter. +** +** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if +** nodes are appended. +*/ +static JsonNode *jsonLookup( + JsonParse *pParse, /* The JSON to search */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + sqlite3_context *pCtx /* Report errors here, if not NULL */ +){ + const char *zErr = 0; + JsonNode *pNode = 0; + char *zMsg; + + if( zPath==0 ) return 0; + if( zPath[0]!='$' ){ + zErr = zPath; + goto lookup_err; + } + zPath++; + pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); + if( zErr==0 ) return pNode; + +lookup_err: + pParse->nErr++; + assert( zErr!=0 && pCtx!=0 ); + zMsg = jsonPathSyntaxError(zErr); + if( zMsg ){ + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); + }else{ + sqlite3_result_error_nomem(pCtx); + } + return 0; +} + + +/* +** Report the wrong number of arguments for json_insert(), json_replace() +** or json_set(). +*/ +static void jsonWrongNumArgs( + sqlite3_context *pCtx, + const char *zFuncName +){ + char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", + zFuncName); + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); +} + +/* +** Mark all NULL entries in the Object passed in as JNODE_REMOVE. +*/ +static void jsonRemoveAllNulls(JsonNode *pNode){ + int i, n; + assert( pNode->eType==JSON_OBJECT ); + n = pNode->n; + for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ + switch( pNode[i].eType ){ + case JSON_NULL: + pNode[i].jnFlags |= JNODE_REMOVE; + break; + case JSON_OBJECT: + jsonRemoveAllNulls(&pNode[i]); + break; + } + } +} + + +/**************************************************************************** +** SQL functions used for testing and debugging +****************************************************************************/ + +#ifdef SQLITE_DEBUG +/* +** The json_parse(JSON) function returns a string which describes +** a parse of the JSON provided. Or it returns NULL if JSON is not +** well-formed. +*/ +static void jsonParseFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString s; /* Output string - not real JSON */ + JsonParse x; /* The parse */ + u32 i; + + assert( argc==1 ); + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + jsonParseFindParents(&x); + jsonInit(&s, ctx); + for(i=0; inNode ); + if( argc==2 ){ + const char *zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = jsonLookup(p, zPath, 0, ctx); + }else{ + pNode = p->aNode; + } + if( pNode==0 ){ + return; + } + if( pNode->eType==JSON_ARRAY ){ + assert( (pNode->jnFlags & JNODE_APPEND)==0 ); + for(i=1; i<=pNode->n; n++){ + i += jsonNodeSize(&pNode[i]); + } + } + sqlite3_result_int64(ctx, n); +} + +/* +** json_extract(JSON, PATH, ...) +** +** Return the element described by PATH. Return NULL if there is no +** PATH element. If there are multiple PATHs, then return a JSON array +** with the result from each path. Throw an error if the JSON or any PATH +** is malformed. +*/ +static void jsonExtractFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse *p; /* The parse */ + JsonNode *pNode; + const char *zPath; + JsonString jx; + int i; + + if( argc<2 ) return; + p = jsonParseCached(ctx, argv); + if( p==0 ) return; + jsonInit(&jx, ctx); + jsonAppendChar(&jx, '['); + for(i=1; inErr ) break; + if( argc>2 ){ + jsonAppendSeparator(&jx); + if( pNode ){ + jsonRenderNode(pNode, &jx, 0); + }else{ + jsonAppendRaw(&jx, "null", 4); + } + }else if( pNode ){ + jsonReturn(pNode, ctx, 0); + } + } + if( argc>2 && i==argc ){ + jsonAppendChar(&jx, ']'); + jsonResult(&jx); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } + jsonReset(&jx); +} + +/* This is the RFC 7396 MergePatch algorithm. +*/ +static JsonNode *jsonMergePatch( + JsonParse *pParse, /* The JSON parser that contains the TARGET */ + u32 iTarget, /* Node of the TARGET in pParse */ + JsonNode *pPatch /* The PATCH */ +){ + u32 i, j; + u32 iRoot; + JsonNode *pTarget; + if( pPatch->eType!=JSON_OBJECT ){ + return pPatch; + } + assert( iTarget>=0 && iTargetnNode ); + pTarget = &pParse->aNode[iTarget]; + assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); + if( pTarget->eType!=JSON_OBJECT ){ + jsonRemoveAllNulls(pPatch); + return pPatch; + } + iRoot = iTarget; + for(i=1; in; i += jsonNodeSize(&pPatch[i+1])+1){ + u32 nKey; + const char *zKey; + assert( pPatch[i].eType==JSON_STRING ); + assert( pPatch[i].jnFlags & JNODE_LABEL ); + nKey = pPatch[i].n; + zKey = pPatch[i].u.zJContent; + assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); + for(j=1; jn; j += jsonNodeSize(&pTarget[j+1])+1 ){ + assert( pTarget[j].eType==JSON_STRING ); + assert( pTarget[j].jnFlags & JNODE_LABEL ); + assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); + if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){ + if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break; + if( pPatch[i+1].eType==JSON_NULL ){ + pTarget[j+1].jnFlags |= JNODE_REMOVE; + }else{ + JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]); + if( pNew==0 ) return 0; + pTarget = &pParse->aNode[iTarget]; + if( pNew!=&pTarget[j+1] ){ + pTarget[j+1].u.pPatch = pNew; + pTarget[j+1].jnFlags |= JNODE_PATCH; + } + } + break; + } + } + if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ + int iStart, iPatch; + iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); + jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); + iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + if( pParse->oom ) return 0; + jsonRemoveAllNulls(pPatch); + pTarget = &pParse->aNode[iTarget]; + pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; + pParse->aNode[iRoot].u.iAppend = iStart - iRoot; + iRoot = iStart; + pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; + pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; + } + } + return pTarget; +} + +/* +** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON +** object that is the result of running the RFC 7396 MergePatch() algorithm +** on the two arguments. +*/ +static void jsonPatchFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The JSON that is being patched */ + JsonParse y; /* The patch */ + JsonNode *pResult; /* The result of the merge */ + + UNUSED_PARAM(argc); + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ + jsonParseReset(&x); + return; + } + pResult = jsonMergePatch(&x, 0, y.aNode); + assert( pResult!=0 || x.oom ); + if( pResult ){ + jsonReturnJson(pResult, ctx, 0); + }else{ + sqlite3_result_error_nomem(ctx); + } + jsonParseReset(&x); + jsonParseReset(&y); +} + + +/* +** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON +** object that contains all name/value given in arguments. Or if any name +** is not a string or if any value is a BLOB, throw an error. +*/ +static void jsonObjectFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + int i; + JsonString jx; + const char *z; + u32 n; + + if( argc&1 ){ + sqlite3_result_error(ctx, "json_object() requires an even number " + "of arguments", -1); + return; + } + jsonInit(&jx, ctx); + jsonAppendChar(&jx, '{'); + for(i=0; ijnFlags |= JNODE_REMOVE; + } + if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ + jsonReturnJson(x.aNode, ctx, 0); + } +remove_done: + jsonParseReset(&x); +} + +/* +** json_replace(JSON, PATH, VALUE, ...) +** +** Replace the value at PATH with VALUE. If PATH does not already exist, +** this routine is a no-op. If JSON or PATH is malformed, throw an error. +*/ +static void jsonReplaceFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + JsonNode *pNode; + const char *zPath; + u32 i; + + if( argc<1 ) return; + if( (argc&1)==0 ) { + jsonWrongNumArgs(ctx, "replace"); + return; + } + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + pNode = jsonLookup(&x, zPath, 0, ctx); + if( x.nErr ) goto replace_err; + if( pNode ){ + pNode->jnFlags |= (u8)JNODE_REPLACE; + pNode->u.iReplace = i + 1; + } + } + if( x.aNode[0].jnFlags & JNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + }else{ + jsonReturnJson(x.aNode, ctx, argv); + } +replace_err: + jsonParseReset(&x); +} + +/* +** json_set(JSON, PATH, VALUE, ...) +** +** Set the value at PATH to VALUE. Create the PATH if it does not already +** exist. Overwrite existing values that do exist. +** If JSON or PATH is malformed, throw an error. +** +** json_insert(JSON, PATH, VALUE, ...) +** +** Create PATH and initialize it to VALUE. If PATH already exists, this +** routine is a no-op. If JSON or PATH is malformed, throw an error. +*/ +static void jsonSetFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + JsonNode *pNode; + const char *zPath; + u32 i; + int bApnd; + int bIsSet = *(int*)sqlite3_user_data(ctx); + + if( argc<1 ) return; + if( (argc&1)==0 ) { + jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); + return; + } + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + bApnd = 0; + pNode = jsonLookup(&x, zPath, &bApnd, ctx); + if( x.oom ){ + sqlite3_result_error_nomem(ctx); + goto jsonSetDone; + }else if( x.nErr ){ + goto jsonSetDone; + }else if( pNode && (bApnd || bIsSet) ){ + pNode->jnFlags |= (u8)JNODE_REPLACE; + pNode->u.iReplace = i + 1; + } + } + if( x.aNode[0].jnFlags & JNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + }else{ + jsonReturnJson(x.aNode, ctx, argv); + } +jsonSetDone: + jsonParseReset(&x); +} + +/* +** json_type(JSON) +** json_type(JSON, PATH) +** +** Return the top-level "type" of a JSON string. Throw an error if +** either the JSON or PATH inputs are not well-formed. +*/ +static void jsonTypeFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + const char *zPath; + JsonNode *pNode; + + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + if( argc==2 ){ + zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = jsonLookup(&x, zPath, 0, ctx); + }else{ + pNode = x.aNode; + } + if( pNode ){ + sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); + } + jsonParseReset(&x); +} + +/* +** json_valid(JSON) +** +** Return 1 if JSON is a well-formed JSON string according to RFC-7159. +** Return 0 otherwise. +*/ +static void jsonValidFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + int rc = 0; + + UNUSED_PARAM(argc); + if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){ + rc = 1; + } + jsonParseReset(&x); + sqlite3_result_int(ctx, rc); +} + + +/**************************************************************************** +** Aggregate SQL function implementations +****************************************************************************/ +/* +** json_group_array(VALUE) +** +** Return a JSON array composed of all values in the aggregate. +*/ +static void jsonArrayStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString *pStr; + UNUSED_PARAM(argc); + pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + jsonInit(pStr, ctx); + jsonAppendChar(pStr, '['); + }else{ + jsonAppendChar(pStr, ','); + pStr->pCtx = ctx; + } + jsonAppendValue(pStr, argv[0]); + } +} +static void jsonArrayFinal(sqlite3_context *ctx){ + JsonString *pStr; + pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + pStr->pCtx = ctx; + jsonAppendChar(pStr, ']'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else{ + sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + } + }else{ + sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, JSON_SUBTYPE); +} + +/* +** json_group_obj(NAME,VALUE) +** +** Return a JSON object composed of all names and values in the aggregate. +*/ +static void jsonObjectStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString *pStr; + const char *z; + u32 n; + UNUSED_PARAM(argc); + pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + jsonInit(pStr, ctx); + jsonAppendChar(pStr, '{'); + }else{ + jsonAppendChar(pStr, ','); + pStr->pCtx = ctx; + } + z = (const char*)sqlite3_value_text(argv[0]); + n = (u32)sqlite3_value_bytes(argv[0]); + jsonAppendString(pStr, z, n); + jsonAppendChar(pStr, ':'); + jsonAppendValue(pStr, argv[1]); + } +} +static void jsonObjectFinal(sqlite3_context *ctx){ + JsonString *pStr; + pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + jsonAppendChar(pStr, '}'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else{ + sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + } + }else{ + sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, JSON_SUBTYPE); +} + + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/**************************************************************************** +** The json_each virtual table +****************************************************************************/ +typedef struct JsonEachCursor JsonEachCursor; +struct JsonEachCursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + u32 iRowid; /* The rowid */ + u32 iBegin; /* The first node of the scan */ + u32 i; /* Index in sParse.aNode[] of current row */ + u32 iEnd; /* EOF when i equals or exceeds this value */ + u8 eType; /* Type of top-level element */ + u8 bRecursive; /* True for json_tree(). False for json_each() */ + char *zJson; /* Input JSON */ + char *zRoot; /* Path by which to filter zJson */ + JsonParse sParse; /* Parse of the input JSON */ +}; + +/* Constructor for the json_each virtual table */ +static int jsonEachConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + sqlite3_vtab *pNew; + int rc; + +/* Column numbers */ +#define JEACH_KEY 0 +#define JEACH_VALUE 1 +#define JEACH_TYPE 2 +#define JEACH_ATOM 3 +#define JEACH_ID 4 +#define JEACH_PARENT 5 +#define JEACH_FULLKEY 6 +#define JEACH_PATH 7 +#define JEACH_JSON 8 +#define JEACH_ROOT 9 + + UNUSED_PARAM(pzErr); + UNUSED_PARAM(argv); + UNUSED_PARAM(argc); + UNUSED_PARAM(pAux); + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," + "json HIDDEN,root HIDDEN)"); + if( rc==SQLITE_OK ){ + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + } + return rc; +} + +/* destructor for json_each virtual table */ +static int jsonEachDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* constructor for a JsonEachCursor object for json_each(). */ +static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + JsonEachCursor *pCur; + + UNUSED_PARAM(p); + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* constructor for a JsonEachCursor object for json_tree(). */ +static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + int rc = jsonEachOpenEach(p, ppCursor); + if( rc==SQLITE_OK ){ + JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; + pCur->bRecursive = 1; + } + return rc; +} + +/* Reset a JsonEachCursor back to its original state. Free any memory +** held. */ +static void jsonEachCursorReset(JsonEachCursor *p){ + sqlite3_free(p->zJson); + sqlite3_free(p->zRoot); + jsonParseReset(&p->sParse); + p->iRowid = 0; + p->i = 0; + p->iEnd = 0; + p->eType = 0; + p->zJson = 0; + p->zRoot = 0; +} + +/* Destructor for a jsonEachCursor object */ +static int jsonEachClose(sqlite3_vtab_cursor *cur){ + JsonEachCursor *p = (JsonEachCursor*)cur; + jsonEachCursorReset(p); + sqlite3_free(cur); + return SQLITE_OK; +} + +/* Return TRUE if the jsonEachCursor object has been advanced off the end +** of the JSON object */ +static int jsonEachEof(sqlite3_vtab_cursor *cur){ + JsonEachCursor *p = (JsonEachCursor*)cur; + return p->i >= p->iEnd; +} + +/* Advance the cursor to the next element for json_tree() */ +static int jsonEachNext(sqlite3_vtab_cursor *cur){ + JsonEachCursor *p = (JsonEachCursor*)cur; + if( p->bRecursive ){ + if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; + p->i++; + p->iRowid++; + if( p->iiEnd ){ + u32 iUp = p->sParse.aUp[p->i]; + JsonNode *pUp = &p->sParse.aNode[iUp]; + p->eType = pUp->eType; + if( pUp->eType==JSON_ARRAY ){ + if( iUp==p->i-1 ){ + pUp->u.iKey = 0; + }else{ + pUp->u.iKey++; + } + } + } + }else{ + switch( p->eType ){ + case JSON_ARRAY: { + p->i += jsonNodeSize(&p->sParse.aNode[p->i]); + p->iRowid++; + break; + } + case JSON_OBJECT: { + p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); + p->iRowid++; + break; + } + default: { + p->i = p->iEnd; + break; + } + } + } + return SQLITE_OK; +} + +/* Append the name of the path for element i to pStr +*/ +static void jsonEachComputePath( + JsonEachCursor *p, /* The cursor */ + JsonString *pStr, /* Write the path here */ + u32 i /* Path to this element */ +){ + JsonNode *pNode, *pUp; + u32 iUp; + if( i==0 ){ + jsonAppendChar(pStr, '$'); + return; + } + iUp = p->sParse.aUp[i]; + jsonEachComputePath(p, pStr, iUp); + pNode = &p->sParse.aNode[i]; + pUp = &p->sParse.aNode[iUp]; + if( pUp->eType==JSON_ARRAY ){ + jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); + }else{ + assert( pUp->eType==JSON_OBJECT ); + if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; + assert( pNode->eType==JSON_STRING ); + assert( pNode->jnFlags & JNODE_LABEL ); + jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); + } +} + +/* Return the value of a column */ +static int jsonEachColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + JsonEachCursor *p = (JsonEachCursor*)cur; + JsonNode *pThis = &p->sParse.aNode[p->i]; + switch( i ){ + case JEACH_KEY: { + if( p->i==0 ) break; + if( p->eType==JSON_OBJECT ){ + jsonReturn(pThis, ctx, 0); + }else if( p->eType==JSON_ARRAY ){ + u32 iKey; + if( p->bRecursive ){ + if( p->iRowid==0 ) break; + iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; + }else{ + iKey = p->iRowid; + } + sqlite3_result_int64(ctx, (sqlite3_int64)iKey); + } + break; + } + case JEACH_VALUE: { + if( pThis->jnFlags & JNODE_LABEL ) pThis++; + jsonReturn(pThis, ctx, 0); + break; + } + case JEACH_TYPE: { + if( pThis->jnFlags & JNODE_LABEL ) pThis++; + sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); + break; + } + case JEACH_ATOM: { + if( pThis->jnFlags & JNODE_LABEL ) pThis++; + if( pThis->eType>=JSON_ARRAY ) break; + jsonReturn(pThis, ctx, 0); + break; + } + case JEACH_ID: { + sqlite3_result_int64(ctx, + (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); + break; + } + case JEACH_PARENT: { + if( p->i>p->iBegin && p->bRecursive ){ + sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); + } + break; + } + case JEACH_FULLKEY: { + JsonString x; + jsonInit(&x, ctx); + if( p->bRecursive ){ + jsonEachComputePath(p, &x, p->i); + }else{ + if( p->zRoot ){ + jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); + }else{ + jsonAppendChar(&x, '$'); + } + if( p->eType==JSON_ARRAY ){ + jsonPrintf(30, &x, "[%d]", p->iRowid); + }else{ + jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); + } + } + jsonResult(&x); + break; + } + case JEACH_PATH: { + if( p->bRecursive ){ + JsonString x; + jsonInit(&x, ctx); + jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); + jsonResult(&x); + break; + } + /* For json_each() path and root are the same so fall through + ** into the root case */ + } + default: { + const char *zRoot = p->zRoot; + if( zRoot==0 ) zRoot = "$"; + sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); + break; + } + case JEACH_JSON: { + assert( i==JEACH_JSON ); + sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); + break; + } + } + return SQLITE_OK; +} + +/* Return the current rowid value */ +static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + JsonEachCursor *p = (JsonEachCursor*)cur; + *pRowid = p->iRowid; + return SQLITE_OK; +} + +/* The query strategy is to look for an equality constraint on the json +** column. Without such a constraint, the table cannot operate. idxNum is +** 1 if the constraint is found, 3 if the constraint and zRoot are found, +** and 0 otherwise. +*/ +static int jsonEachBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; + int jsonIdx = -1; + int rootIdx = -1; + const struct sqlite3_index_constraint *pConstraint; + + UNUSED_PARAM(tab); + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + switch( pConstraint->iColumn ){ + case JEACH_JSON: jsonIdx = i; break; + case JEACH_ROOT: rootIdx = i; break; + default: /* no-op */ break; + } + } + if( jsonIdx<0 ){ + pIdxInfo->idxNum = 0; + pIdxInfo->estimatedCost = 1e99; + }else{ + pIdxInfo->estimatedCost = 1.0; + pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1; + pIdxInfo->aConstraintUsage[jsonIdx].omit = 1; + if( rootIdx<0 ){ + pIdxInfo->idxNum = 1; + }else{ + pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2; + pIdxInfo->aConstraintUsage[rootIdx].omit = 1; + pIdxInfo->idxNum = 3; + } + } + return SQLITE_OK; +} + +/* Start a search on a new JSON string */ +static int jsonEachFilter( + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + JsonEachCursor *p = (JsonEachCursor*)cur; + const char *z; + const char *zRoot = 0; + sqlite3_int64 n; + + UNUSED_PARAM(idxStr); + UNUSED_PARAM(argc); + jsonEachCursorReset(p); + if( idxNum==0 ) return SQLITE_OK; + z = (const char*)sqlite3_value_text(argv[0]); + if( z==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[0]); + p->zJson = sqlite3_malloc64( n+1 ); + if( p->zJson==0 ) return SQLITE_NOMEM; + memcpy(p->zJson, z, (size_t)n+1); + if( jsonParse(&p->sParse, 0, p->zJson) ){ + int rc = SQLITE_NOMEM; + if( p->sParse.oom==0 ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); + if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; + } + jsonEachCursorReset(p); + return rc; + }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ + jsonEachCursorReset(p); + return SQLITE_NOMEM; + }else{ + JsonNode *pNode = 0; + if( idxNum==3 ){ + const char *zErr = 0; + zRoot = (const char*)sqlite3_value_text(argv[1]); + if( zRoot==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[1]); + p->zRoot = sqlite3_malloc64( n+1 ); + if( p->zRoot==0 ) return SQLITE_NOMEM; + memcpy(p->zRoot, zRoot, (size_t)n+1); + if( zRoot[0]!='$' ){ + zErr = zRoot; + }else{ + pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); + } + if( zErr ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); + jsonEachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + }else if( pNode==0 ){ + return SQLITE_OK; + } + }else{ + pNode = p->sParse.aNode; + } + p->iBegin = p->i = (int)(pNode - p->sParse.aNode); + p->eType = pNode->eType; + if( p->eType>=JSON_ARRAY ){ + pNode->u.iKey = 0; + p->iEnd = p->i + pNode->n + 1; + if( p->bRecursive ){ + p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; + if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ + p->i--; + } + }else{ + p->i++; + } + }else{ + p->iEnd = p->i+1; + } + } + return SQLITE_OK; +} + +/* The methods of the json_each virtual table */ +static sqlite3_module jsonEachModule = { + 0, /* iVersion */ + 0, /* xCreate */ + jsonEachConnect, /* xConnect */ + jsonEachBestIndex, /* xBestIndex */ + jsonEachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + jsonEachOpenEach, /* xOpen - open a cursor */ + jsonEachClose, /* xClose - close a cursor */ + jsonEachFilter, /* xFilter - configure scan constraints */ + jsonEachNext, /* xNext - advance a cursor */ + jsonEachEof, /* xEof - check for end of scan */ + jsonEachColumn, /* xColumn - read data */ + jsonEachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0 /* xRollbackTo */ +}; + +/* The methods of the json_tree virtual table. */ +static sqlite3_module jsonTreeModule = { + 0, /* iVersion */ + 0, /* xCreate */ + jsonEachConnect, /* xConnect */ + jsonEachBestIndex, /* xBestIndex */ + jsonEachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + jsonEachOpenTree, /* xOpen - open a cursor */ + jsonEachClose, /* xClose - close a cursor */ + jsonEachFilter, /* xFilter - configure scan constraints */ + jsonEachNext, /* xNext - advance a cursor */ + jsonEachEof, /* xEof - check for end of scan */ + jsonEachColumn, /* xColumn - read data */ + jsonEachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0 /* xRollbackTo */ +}; +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/**************************************************************************** +** The following routines are the only publically visible identifiers in this +** file. Call the following routines in order to register the various SQL +** functions and the virtual table implemented by this file. +****************************************************************************/ + +SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ + int rc = SQLITE_OK; + unsigned int i; + static const struct { + const char *zName; + int nArg; + int flag; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "json", 1, 0, jsonRemoveFunc }, + { "json_array", -1, 0, jsonArrayFunc }, + { "json_array_length", 1, 0, jsonArrayLengthFunc }, + { "json_array_length", 2, 0, jsonArrayLengthFunc }, + { "json_extract", -1, 0, jsonExtractFunc }, + { "json_insert", -1, 0, jsonSetFunc }, + { "json_object", -1, 0, jsonObjectFunc }, + { "json_patch", 2, 0, jsonPatchFunc }, + { "json_quote", 1, 0, jsonQuoteFunc }, + { "json_remove", -1, 0, jsonRemoveFunc }, + { "json_replace", -1, 0, jsonReplaceFunc }, + { "json_set", -1, 1, jsonSetFunc }, + { "json_type", 1, 0, jsonTypeFunc }, + { "json_type", 2, 0, jsonTypeFunc }, + { "json_valid", 1, 0, jsonValidFunc }, + +#if SQLITE_DEBUG + /* DEBUG and TESTING functions */ + { "json_parse", 1, 0, jsonParseFunc }, + { "json_test1", 1, 0, jsonTest1Func }, +#endif + }; + static const struct { + const char *zName; + int nArg; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinal)(sqlite3_context*); + } aAgg[] = { + { "json_group_array", 1, jsonArrayStep, jsonArrayFinal }, + { "json_group_object", 2, jsonObjectStep, jsonObjectFinal }, + }; +#ifndef SQLITE_OMIT_VIRTUALTABLE + static const struct { + const char *zName; + sqlite3_module *pModule; + } aMod[] = { + { "json_each", &jsonEachModule }, + { "json_tree", &jsonTreeModule }, + }; +#endif + for(i=0; i */ -#endif -#ifdef HAVE_INTTYPES_H -/* #include */ -#endif /* ** 2014 May 31 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -233348,11 +182998,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** -** Interfaces to extend FTS5. Using the interfaces defined in this file, +** Interfaces to extend FTS5. Using the interfaces defined in this file, ** FTS5 may be extended with: ** ** * custom tokenizers, and ** * custom auxiliary functions. */ @@ -233393,23 +183043,23 @@ /* ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): -** Return a copy of the pUserData pointer passed to the xCreateFunction() -** API when the extension function was registered. +** Return a copy of the context pointer the extension function was +** registered with. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken ** to the total number of tokens in the FTS5 table. Or, if iCol is ** non-negative but less than the number of columns in the table, return -** the total number of tokens in column iCol, considering all rows in +** the total number of tokens in column iCol, considering all rows in ** the FTS5 table. ** ** If parameter iCol is greater than or equal to the number of columns ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is +** an OOM condition or IO error), an appropriate SQLite error code is ** returned. ** ** xColumnCount(pFts): ** Return the number of columns in the table. ** @@ -233419,60 +183069,58 @@ ** non-negative but less than the number of columns in the table, set ** *pnToken to the number of tokens in column iCol of the current row. ** ** If parameter iCol is greater than or equal to the number of columns ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is +** an OOM condition or IO error), an appropriate SQLite error code is ** returned. ** ** This function may be quite inefficient if used with an FTS5 table ** created with the "columnsize=0" option. ** ** xColumnText: -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the text of column iCol of -** the current document. If successful, (*pz) is set to point to a buffer +** This function attempts to retrieve the text of column iCol of the +** current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values ** of (*pz) and (*pn) are undefined. ** ** xPhraseCount: ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: -** If parameter iCol is less than zero, or greater than or equal to the -** number of phrases in the current query, as returned by xPhraseCount, -** 0 is returned. Otherwise, this function returns the number of tokens in -** phrase iPhrase of the query. Phrases are numbered starting from zero. +** Returns the number of tokens in phrase iPhrase of the query. Phrases +** are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within ** the query within the current row. Return SQLITE_OK if successful, or ** an error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option ** (i.e. if it is a contentless table), then this API always returns 0. ** ** xInst: ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). If iIdx is less than zero or greater than -** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. +** output by xInstCount(). ** -** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol +** Usually, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. SQLITE_OK is returned if successful, or an -** error code (i.e. SQLITE_NOMEM) if an error occurs. +** first token of the phrase. The exception is if the table was created +** with the offsets=0 option specified. In this case *piOff is always +** set to -1. +** +** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM) +** if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. +** "detail=none" or "detail=column" option. ** ** xRowid: ** Returns the rowid of the current row. ** ** xTokenize: @@ -233484,21 +183132,17 @@ ** ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the ** current query is executed. Any column filter that applies to -** phrase iPhrase of the current query is included in $p. For each -** row visited, the callback function passed as the fourth argument -** is invoked. The context and API objects passed to the callback +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback ** function may be used to access the properties of each matched row. -** Invoking Api.xUserData() returns a copy of the pointer passed as +** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** -** If parameter iPhrase is less than zero, or greater than or equal to -** the number of phrases in the query, as returned by xPhraseCount(), -** this function returns SQLITE_RANGE. -** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. ** Otherwise, the error code is propagated upwards. ** @@ -233507,18 +183151,18 @@ ** the callback, an SQLite error code is returned. ** ** ** xSetAuxdata(pFts5, pAux, xDelete) ** -** Save the pointer passed as the second argument as the extension function's +** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of -** the same MATCH query using the xGetAuxdata() API. +** of the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for -** each FTS query (MATCH expression). If the extension function is invoked -** more than once for a single FTS query, then all invocations share a +** each FTS query (MATCH expression). If the extension function is invoked +** more than once for a single FTS query, then all invocations share a ** single auxiliary data context. ** ** If there is already an auxiliary data pointer when this function is ** invoked, then it is replaced by the new pointer. If an xDelete callback ** was specified along with the original pointer, it is invoked at this @@ -233525,19 +183169,19 @@ ** point. ** ** The xDelete callback, if one is specified, is also invoked on the ** auxiliary data pointer after the FTS5 query has finished. ** -** If an error (e.g. an OOM condition) occurs within this function, +** If an error (e.g. an OOM condition) occurs within this function, an ** the auxiliary data is set to NULL and an error code returned. If the ** xDelete parameter was not NULL, it is invoked on the auxiliary data ** pointer before returning. ** ** ** xGetAuxdata(pFts5, bClear) ** -** Returns the current auxiliary data pointer for the fts5 extension +** Returns the current auxiliary data pointer for the fts5 extension ** function. See the xSetAuxdata() method for details. ** ** If the bClear argument is non-zero, then the auxiliary data is cleared ** (set to NULL) before this function returns. In this case the xDelete, ** if any, is not invoked. @@ -233553,11 +183197,11 @@ ** xPhraseFirst() ** This function is used, along with type Fts5PhraseIter and the xPhraseNext ** method, to iterate through all instances of a single query phrase within ** the current row. This is the same information as is accessible via the ** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient -** to use, this API may be faster under some circumstances. To iterate +** to use, this API may be faster under some circumstances. To iterate ** through instances of phrase iPhrase, use the following code: ** ** Fts5PhraseIter iter; ** int iCol, iOff; ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); @@ -233571,19 +183215,15 @@ ** modify this structure directly - it should only be used as shown above ** with the xPhraseFirst() and xPhraseNext() API methods (and by ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option ** (i.e. if it is a contentless table), then this API always iterates ** through an empty set (all calls to xPhraseFirst() set iCol to -1). ** -** In all cases, matches are visited in (column ASC, offset ASC) order. -** i.e. all those in column 0, sorted by offset, followed by those in -** column 1, etc. -** ** xPhraseNext() ** See xPhraseFirst above. ** ** xPhraseFirstColumn() ** This function and xPhraseNextColumn() are similar to the xPhraseFirst() @@ -233600,105 +183240,34 @@ ** ){ ** // Column iCol contains at least one instance of phrase iPhrase ** } ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" option. If the FTS5 table is created with either -** "detail=none" "content=" option (i.e. if it is a contentless table), -** then this API always iterates through an empty set (all calls to +** "detail=none" option. If the FTS5 table is created with either +** "detail=none" "content=" option (i.e. if it is a contentless table), +** then this API always iterates through an empty set (all calls to ** xPhraseFirstColumn() set iCol to -1). ** ** The information accessed using this API and its companion ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext ** (or xInst/xInstCount). The chief advantage of this API is that it is ** significantly more efficient than those alternatives when used with -** "detail=column" tables. +** "detail=column" tables. ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above. -** -** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase iPhrase of the current -** query. Before returning, output parameter *ppToken is set to point -** to a buffer containing the requested token, and *pnToken to the -** size of this buffer in bytes. -** -** If iPhrase or iToken are less than zero, or if iPhrase is greater than -** or equal to the number of phrases in the query as reported by -** xPhraseCount(), or if iToken is equal to or greater than the number of -** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken - are both zeroed. -** -** The output text is not a copy of the query text that specified the -** token. It is the output of the tokenizer module. For tokendata=1 -** tables, this includes any embedded 0x00 and trailing data. -** -** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase hit iIdx within the -** current row. If iIdx is less than zero or greater than or equal to the -** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, -** output variable (*ppToken) is set to point to a buffer containing the -** matching document token, and (*pnToken) to the size of that buffer in -** bytes. -** -** The output text is not a copy of the document text that was tokenized. -** It is the output of the tokenizer module. For tokendata=1 tables, this -** includes any embedded 0x00 and trailing data. -** -** This API may be slow in some cases if the token identified by parameters -** iIdx and iToken matched a prefix token in the query. In most cases, the -** first call to this API for each prefix token in the query is forced -** to scan the portion of the full-text index that matches the prefix -** token to collect the extra data required by this API. If the prefix -** token matches a large number of token instances in the document set, -** this may be a performance problem. -** -** If the user knows in advance that a query may use this API for a -** prefix token, FTS5 may be configured to collect all required data as part -** of the initial querying of the full-text index, avoiding the second scan -** entirely. This also causes prefix queries that do not use this API to -** run more slowly and use more memory. FTS5 may be configured in this way -** either on a per-table basis using the [FTS5 insttoken | 'insttoken'] -** option, or on a per-query basis using the -** [fts5_insttoken | fts5_insttoken()] user function. -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. -** -** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale) -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the locale associated -** with column iCol of the current row. Usually, there is no associated -** locale, and output parameters (*pzLocale) and (*pnLocale) are set -** to NULL and 0, respectively. However, if the fts5_locale() function -** was used to associate a locale with the value when it was inserted -** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated -** buffer containing the name of the locale in utf-8 encoding. (*pnLocale) -** is set to the size in bytes of the buffer, not including the -** nul-terminator. -** -** If successful, SQLITE_OK is returned. Or, if an error occurs, an -** SQLite error code is returned. The final value of the output parameters -** is undefined in this case. -** -** xTokenize_v2: -** Tokenize text using the tokenizer belonging to the FTS5 table. This -** API is the same as the xTokenize() API, except that it allows a tokenizer -** locale to be specified. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 4 */ + int iVersion; /* Currently always set to 3 */ void *(*xUserData)(Fts5Context*); int (*xColumnCount)(Fts5Context*); int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); - int (*xTokenize)(Fts5Context*, + int (*xTokenize)(Fts5Context*, const char *pText, int nText, /* Text to tokenize */ void *pCtx, /* Context passed to xToken() */ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ ); @@ -233721,114 +183290,91 @@ int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); - - /* Below this point are iVersion>=3 only */ - int (*xQueryToken)(Fts5Context*, - int iPhrase, int iToken, - const char **ppToken, int *pnToken - ); - int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); - - /* Below this point are iVersion>=4 only */ - int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xTokenize_v2)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - const char *pLocale, int nLocale, /* Locale to pass to tokenizer */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); }; -/* +/* ** CUSTOM AUXILIARY FUNCTIONS *************************************************************************/ /************************************************************************* ** CUSTOM TOKENIZERS ** -** Applications may also register custom tokenizer types. A tokenizer -** is registered by providing fts5 with a populated instance of the +** Applications may also register custom tokenizer types. A tokenizer +** is registered by providing fts5 with a populated instance of the ** following structure. All structure methods must be defined, setting ** any member of the fts5_tokenizer struct to NULL leads to undefined ** behaviour. The structure methods are expected to function as follows: ** ** xCreate: ** This function is used to allocate and initialize a tokenizer instance. ** A tokenizer instance is required to actually tokenize text. ** ** The first argument passed to this function is a copy of the (void*) -** pointer provided by the application when the fts5_tokenizer_v2 object -** was registered with FTS5 (the third argument to xCreateTokenizer()). +** pointer provided by the application when the fts5_tokenizer object +** was registered with FTS5 (the third argument to xCreateTokenizer()). ** The second and third arguments are an array of nul-terminated strings ** containing the tokenizer arguments, if any, specified following the ** tokenizer name as part of the CREATE VIRTUAL TABLE statement used ** to create the FTS5 table. ** -** The final argument is an output variable. If successful, (*ppOut) +** The final argument is an output variable. If successful, (*ppOut) ** should be set to point to the new tokenizer handle and SQLITE_OK ** returned. If an error occurs, some value other than SQLITE_OK should -** be returned. In this case, fts5 assumes that the final value of *ppOut +** be returned. In this case, fts5 assumes that the final value of *ppOut ** is undefined. ** ** xDelete: ** This function is invoked to delete a tokenizer handle previously ** allocated using xCreate(). Fts5 guarantees that this function will ** be invoked exactly once for each successful call to xCreate(). ** ** xTokenize: -** This function is expected to tokenize the nText byte string indicated +** This function is expected to tokenize the nText byte string indicated ** by argument pText. pText may or may not be nul-terminated. The first ** argument passed to this function is a pointer to an Fts5Tokenizer object ** returned by an earlier call to xCreate(). ** -** The third argument indicates the reason that FTS5 is requesting +** The second argument indicates the reason that FTS5 is requesting ** tokenization of the supplied text. This is always one of the following ** four values: ** **
                • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into ** or removed from the FTS table. The tokenizer is being invoked to ** determine the set of tokens to add to (or delete from) the ** FTS index. ** -**
                • FTS5_TOKENIZE_QUERY - A MATCH query is being executed -** against the FTS index. The tokenizer is being called to tokenize +**
                • FTS5_TOKENIZE_QUERY - A MATCH query is being executed +** against the FTS index. The tokenizer is being called to tokenize ** a bareword or quoted string specified as part of the query. ** **
                • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as ** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is ** followed by a "*" character, indicating that the last token ** returned by the tokenizer will be treated as a token prefix. ** -**
                • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to +**
                • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to ** satisfy an fts5_api.xTokenize() request made by an auxiliary ** function. Or an fts5_api.xColumnSize() request made by the same -** on a columnsize=0 database. +** on a columnsize=0 database. **
                ** -** The sixth and seventh arguments passed to xTokenize() - pLocale and -** nLocale - are a pointer to a buffer containing the locale to use for -** tokenization (e.g. "en_US") and its size in bytes, respectively. The -** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in -** which case nLocale is always 0) to indicate that the tokenizer should -** use its default locale. -** ** For each token in the input string, the supplied callback xToken() must ** be invoked. The first argument to it should be a copy of the pointer ** passed as the second argument to xTokenize(). The third and fourth ** arguments are a pointer to a buffer containing the token text, and the ** size of the token in bytes. The 4th and 5th arguments are the byte offsets ** of the first byte of and first byte immediately following the text from ** which the token is derived within the input. ** ** The second argument passed to the xToken() callback ("tflags") should -** normally be set to 0. The exception is if the tokenizer supports +** normally be set to 0. The exception is if the tokenizer supports ** synonyms. In this case see the discussion below for details. ** -** FTS5 assumes the xToken() callback is invoked for each token in the +** FTS5 assumes the xToken() callback is invoked for each token in the ** order that they occur within the input text. ** ** If an xToken() callback returns any value other than SQLITE_OK, then ** the tokenization should be abandoned and the xTokenize() method should ** immediately return a copy of the xToken() return value. Or, if the @@ -233835,86 +183381,62 @@ ** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, ** if an error occurs with the xTokenize() implementation itself, it ** may abandon the tokenization and return any error code other than ** SQLITE_OK or SQLITE_DONE. ** -** If the tokenizer is registered using an fts5_tokenizer_v2 object, -** then the xTokenize() method has two additional arguments - pLocale -** and nLocale. These specify the locale that the tokenizer should use -** for the current request. If pLocale and nLocale are both 0, then the -** tokenizer should use its default locale. Otherwise, pLocale points to -** an nLocale byte buffer containing the name of the locale to use as utf-8 -** text. pLocale is not nul-terminated. -** -** FTS5_TOKENIZER -** -** There is also an fts5_tokenizer object. This is an older, deprecated, -** version of fts5_tokenizer_v2. It is similar except that: -** -**
                  -**
                • There is no "iVersion" field, and -**
                • The xTokenize() method does not take a locale argument. -**
                -** -** Legacy fts5_tokenizer tokenizers must be registered using the -** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2(). -** -** Tokenizer implementations registered using either API may be retrieved -** using both xFindTokenizer() and xFindTokenizer_v2(). -** ** SYNONYM SUPPORT ** ** Custom tokenizers may also support synonyms. Consider a case in which a -** user wishes to query for a phrase such as "first place". Using the +** user wishes to query for a phrase such as "first place". Using the ** built-in tokenizers, the FTS5 query 'first + place' will match instances ** of "first place" within the document set, but not alternative forms ** such as "1st place". In some applications, it would be better to match ** all instances of "first place" or "1st place" regardless of which form ** the user specified in the MATCH query text. ** ** There are several ways to approach this in FTS5: ** -**
                1. By mapping all synonyms to a single token. In this case, using -** the above example, this means that the tokenizer returns the +**
                  1. By mapping all synonyms to a single token. In this case, the +** In the above example, this means that the tokenizer returns the ** same token for inputs "first" and "1st". Say that token is in ** fact "first", so that when the user inserts the document "I won ** 1st place" entries are added to the index for tokens "i", "won", ** "first" and "place". If the user then queries for '1st + place', ** the tokenizer substitutes "first" for "1st" and the query works ** as expected. ** -**
                  2. By querying the index for all synonyms of each query term -** separately. In this case, when tokenizing query text, the -** tokenizer may provide multiple synonyms for a single term -** within the document. FTS5 then queries the index for each -** synonym individually. For example, faced with the query: +**
                  3. By adding multiple synonyms for a single term to the FTS index. +** In this case, when tokenizing query text, the tokenizer may +** provide multiple synonyms for a single term within the document. +** FTS5 then queries the index for each synonym individually. For +** example, faced with the query: ** ** ** ... MATCH 'first place' ** ** the tokenizer offers both "1st" and "first" as synonyms for the -** first token in the MATCH query and FTS5 effectively runs a query +** first token in the MATCH query and FTS5 effectively runs a query ** similar to: ** ** ** ... MATCH '(first OR 1st) place' ** ** except that, for the purposes of auxiliary functions, the query -** still appears to contain just two phrases - "(first OR 1st)" +** still appears to contain just two phrases - "(first OR 1st)" ** being treated as a single phrase. ** **
                  4. By adding multiple synonyms for a single term to the FTS index. ** Using this method, when tokenizing document text, the tokenizer -** provides multiple synonyms for each token. So that when a +** provides multiple synonyms for each token. So that when a ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms -** when tokenizing query text (it should not - to do so would be -** inefficient), it doesn't matter if the user queries for -** 'first + place' or '1st + place', as there are entries in the +** when tokenizing query text (it should not - to do would be +** inefficient), it doesn't matter if the user queries for +** 'first + place' or '1st + place', as there are entires in the ** FTS index corresponding to both forms of the first token. **
                  ** ** Whether it is parsing document or query text, any call to xToken that ** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit @@ -233930,58 +183452,55 @@ ** xToken(pCtx, 0, "place", 5, 12, 17); ** ** ** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time ** xToken() is called. Multiple synonyms may be specified for a single token -** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. +** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. ** There is no limit to the number of synonyms that may be provided for a ** single token. ** -** In many cases, method (1) above is the best approach. It does not add +** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the -** token "first" is substituted for "1st" by the tokenizer, then the query: +** token "first" is subsituted for "1st" by the tokenizer, then the query: ** ** ** ... MATCH '1s*' ** ** will not match documents that contain the token "1st" (as the tokenizer ** will probably not map "1s" to any prefix of "first"). ** -** For full prefix support, method (3) may be preferred. In this case, +** For full prefix support, method (3) may be preferred. In this case, ** because the index contains entries for both "first" and "1st", prefix ** queries such as 'fi*' or '1s*' will match correctly. However, because ** extra entries are added to the FTS index, this method uses more space ** within the database. ** ** Method (2) offers a midpoint between (1) and (3). Using this method, -** a query such as '1s*' will match documents that contain the literal +** a query such as '1s*' will match documents that contain the literal ** token "1st", but not "first" (assuming the tokenizer is not able to ** provide synonyms for prefixes). However, a non-prefix query like '1st' ** will match against "1st" and "first". This method does not require -** extra disk space, as no extra entries are added to the FTS index. +** extra disk space, as no extra entries are added to the FTS index. ** On the other hand, it may require more CPU cycles to run MATCH queries, ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (3)) or query -** text (method (2)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (2)) or query +** text (method (3)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; -typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2; -struct fts5_tokenizer_v2 { - int iVersion; /* Currently always 2 */ - +typedef struct fts5_tokenizer fts5_tokenizer; +struct fts5_tokenizer { int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, + int (*xTokenize)(Fts5Tokenizer*, void *pCtx, int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - const char *pLocale, int nLocale, + const char *pText, int nText, int (*xToken)( void *pCtx, /* Copy of 2nd argument to xTokenize() */ int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Pointer to buffer containing token */ int nToken, /* Size of token in bytes */ @@ -233988,35 +183507,10 @@ int iStart, /* Byte offset of token within input text */ int iEnd /* Byte offset of end of token within input text */ ) ); }; - -/* -** New code should use the fts5_tokenizer_v2 type to define tokenizer -** implementations. The following type is included for legacy applications -** that still use it. -*/ -typedef struct fts5_tokenizer fts5_tokenizer; -struct fts5_tokenizer { - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); -}; - /* Flags that may be passed as the third argument to xTokenize() */ #define FTS5_TOKENIZE_QUERY 0x0001 #define FTS5_TOKENIZE_PREFIX 0x0002 #define FTS5_TOKENIZE_DOCUMENT 0x0004 @@ -234033,56 +183527,37 @@ /************************************************************************* ** FTS5 EXTENSION REGISTRATION API */ typedef struct fts5_api fts5_api; struct fts5_api { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ /* Create a new tokenizer */ int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pUserData, + void *pContext, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); /* Find an existing tokenizer */ int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppUserData, + void **ppContext, fts5_tokenizer *pTokenizer ); /* Create a new auxiliary function */ int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pUserData, + void *pContext, fts5_extension_function xFunction, void (*xDestroy)(void*) ); - - /* APIs below this point are only available if iVersion>=3 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void *pUserData, - fts5_tokenizer_v2 *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void **ppUserData, - fts5_tokenizer_v2 **ppTokenizer - ); }; /* ** END OF REGISTRATION API *************************************************************************/ @@ -234128,24 +183603,12 @@ #ifndef ArraySize # define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) #endif #define testcase(x) - -#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) -# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 -#endif -#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) -# define ALWAYS(X) (1) -# define NEVER(X) (0) -#elif !defined(NDEBUG) -# define ALWAYS(X) ((X)?1:(assert(0),0)) -# define NEVER(X) ((X)?(assert(0),1):0) -#else -# define ALWAYS(X) (X) -# define NEVER(X) (X) -#endif +#define ALWAYS(x) 1 +#define NEVER(x) 0 #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) /* @@ -234152,29 +183615,13 @@ ** Constants for the largest and smallest possible 64-bit signed integers. */ # define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) # define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) -/* The uptr type is an unsigned integer large enough to hold a pointer -*/ -#if defined(HAVE_STDINT_H) - typedef uintptr_t uptr; -#elif SQLITE_PTRSIZE==4 - typedef u32 uptr; -#else - typedef u64 uptr; -#endif - -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) -#else -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) -#endif - -#endif - -/* Truncate very long tokens to this many bytes. Hard limit is +#endif + +/* Truncate very long tokens to this many bytes. Hard limit is ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset ** field that occurs at the start of each leaf page (see fts5_index.c). */ #define FTS5_MAX_TOKEN_SIZE 32768 /* @@ -234182,15 +183629,10 @@ ** less than 32. If it is set to anything large than that, an #error ** directive in fts5_index.c will cause the build to fail. */ #define FTS5_MAX_PREFIX_INDEXES 31 -/* -** Maximum segments permitted in a single index -*/ -#define FTS5_MAX_SEGMENT 2000 - #define FTS5_DEFAULT_NEARDIST 10 #define FTS5_DEFAULT_RANK "bm25" /* Name of rank and rowid columns */ #define FTS5_RANK_NAME "rank" @@ -234203,26 +183645,20 @@ # define FTS5_CORRUPT SQLITE_CORRUPT_VTAB #endif /* ** The assert_nc() macro is similar to the assert() macro, except that it -** is used for assert() conditions that are true only if it can be +** is used for assert() conditions that are true only if it can be ** guranteed that the database is not corrupt. */ #ifdef SQLITE_DEBUG SQLITE_API extern int sqlite3_fts5_may_be_corrupt; # define assert_nc(x) assert(sqlite3_fts5_may_be_corrupt || (x)) #else # define assert_nc(x) assert(x) #endif -/* -** A version of memcmp() that does not cause asan errors if one of the pointer -** parameters is NULL and the number of bytes to compare is zero. -*/ -#define fts5Memcmp(s1, s2, n) ((n)<=0 ? 0 : memcmp((s1), (s2), (n))) - /* Mark a function parameter as unused, to suppress nuisance compiler ** warnings. */ #ifndef UNUSED_PARAM # define UNUSED_PARAM(X) (void)(X) #endif @@ -234232,11 +183668,11 @@ #endif typedef struct Fts5Global Fts5Global; typedef struct Fts5Colset Fts5Colset; -/* If a NEAR() clump or phrase may only match a specific set of columns, +/* If a NEAR() clump or phrase may only match a specific set of columns, ** then an object of the following type is used to record the set of columns. ** Each entry in the aiCol[] array is a column that may be matched. ** ** This object is used by fts5_expr.c and fts5_index.c. */ @@ -234251,49 +183687,33 @@ ** Interface to code in fts5_config.c. fts5_config.c contains contains code ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement. */ typedef struct Fts5Config Fts5Config; -typedef struct Fts5TokenizerConfig Fts5TokenizerConfig; - -struct Fts5TokenizerConfig { - Fts5Tokenizer *pTok; - fts5_tokenizer_v2 *pApi2; - fts5_tokenizer *pApi1; - const char **azArg; - int nArg; - int ePattern; /* FTS_PATTERN_XXX constant */ - const char *pLocale; /* Current locale to use */ - int nLocale; /* Size of pLocale in bytes */ -}; /* ** An instance of the following structure encodes all information that can ** be gleaned from the CREATE VIRTUAL TABLE statement. ** ** And all information loaded from the %_config table. ** ** nAutomerge: ** The minimum number of segments that an auto-merge operation should -** attempt to merge together. A value of 1 sets the object to use the +** attempt to merge together. A value of 1 sets the object to use the ** compile time default. Zero disables auto-merge altogether. ** -** bContentlessDelete: -** True if the contentless_delete option was present in the CREATE -** VIRTUAL TABLE statement. -** ** zContent: ** ** zContentRowid: -** The value of the content_rowid= option, if one was specified. Or +** The value of the content_rowid= option, if one was specified. Or ** the string "rowid" otherwise. This text is not quoted - if it is ** used as part of an SQL statement it needs to be quoted appropriately. ** ** zContentExprlist: ** ** pzErrmsg: -** This exists in order to allow the fts5_index.c module to return a +** This exists in order to allow the fts5_index.c module to return a ** decent error message if it encounters a file-format version it does ** not understand. ** ** bColumnsize: ** True if the %_docsize table is created. @@ -234302,77 +183722,59 @@ ** This is only used for debugging. If set to false, any prefix indexes ** are ignored. This value is configured using: ** ** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex); ** -** bLocale: -** Set to true if locale=1 was specified when the table was created. */ struct Fts5Config { sqlite3 *db; /* Database handle */ - Fts5Global *pGlobal; /* Global fts5 object for handle db */ char *zDb; /* Database holding FTS index (e.g. "main") */ char *zName; /* Name of FTS index */ int nCol; /* Number of columns */ char **azCol; /* Column names */ u8 *abUnindexed; /* True for unindexed columns */ int nPrefix; /* Number of prefix indexes */ int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */ int eContent; /* An FTS5_CONTENT value */ - int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */ - int bContentlessUnindexed; /* "contentless_unindexed=" option (dflt=0) */ - char *zContent; /* content table */ - char *zContentRowid; /* "content_rowid=" option value */ + char *zContent; /* content table */ + char *zContentRowid; /* "content_rowid=" option value */ int bColumnsize; /* "columnsize=" option value (dflt==1) */ - int bTokendata; /* "tokendata=" option value (dflt==0) */ - int bLocale; /* "locale=" option value (dflt==0) */ int eDetail; /* FTS5_DETAIL_XXX value */ char *zContentExprlist; - Fts5TokenizerConfig t; - int bLock; /* True when table is preparing statement */ - + Fts5Tokenizer *pTok; + fts5_tokenizer *pTokApi; /* Values loaded from the %_config table */ - int iVersion; /* fts5 file format 'version' */ int iCookie; /* Incremented when %_config is modified */ int pgsz; /* Approximate page size used in %_data */ int nAutomerge; /* 'automerge' setting */ int nCrisisMerge; /* Maximum allowed segments per level */ int nUsermerge; /* 'usermerge' setting */ int nHashSize; /* Bytes of memory for in-memory hash */ char *zRank; /* Name of rank function */ char *zRankArgs; /* Arguments to rank function */ - int bSecureDelete; /* 'secure-delete' */ - int nDeleteMerge; /* 'deletemerge' */ - int bPrefixInsttoken; /* 'prefix-insttoken' */ /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */ char **pzErrmsg; #ifdef SQLITE_DEBUG int bPrefixIndex; /* True to use prefix-indexes */ #endif }; -/* Current expected value of %_config table 'version' field. And -** the expected version if the 'secure-delete' option has ever been -** set on the table. */ -#define FTS5_CURRENT_VERSION 4 -#define FTS5_CURRENT_VERSION_SECUREDELETE 5 - -#define FTS5_CONTENT_NORMAL 0 -#define FTS5_CONTENT_NONE 1 -#define FTS5_CONTENT_EXTERNAL 2 -#define FTS5_CONTENT_UNINDEXED 3 - -#define FTS5_DETAIL_FULL 0 -#define FTS5_DETAIL_NONE 1 -#define FTS5_DETAIL_COLUMNS 2 - -#define FTS5_PATTERN_NONE 0 -#define FTS5_PATTERN_LIKE 65 /* matches SQLITE_INDEX_CONSTRAINT_LIKE */ -#define FTS5_PATTERN_GLOB 66 /* matches SQLITE_INDEX_CONSTRAINT_GLOB */ +/* Current expected value of %_config table 'version' field */ +#define FTS5_CURRENT_VERSION 4 + +#define FTS5_CONTENT_NORMAL 0 +#define FTS5_CONTENT_NONE 1 +#define FTS5_CONTENT_EXTERNAL 2 + +#define FTS5_DETAIL_FULL 0 +#define FTS5_DETAIL_NONE 1 +#define FTS5_DETAIL_COLUMNS 2 + + static int sqlite3Fts5ConfigParse( Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char** ); static void sqlite3Fts5ConfigFree(Fts5Config*); @@ -234395,12 +183797,10 @@ /* Set the value of a single config attribute */ static int sqlite3Fts5ConfigSetValue(Fts5Config*, const char*, sqlite3_value*, int*); static int sqlite3Fts5ConfigParseRank(const char*, char**, char**); -static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...); - /* ** End of interface to code in fts5_config.c. **************************************************************************/ /************************************************************************** @@ -234427,11 +183827,11 @@ static void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...); static char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...); #define fts5BufferZero(x) sqlite3Fts5BufferZero(x) -#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,(i64)c) +#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c) #define fts5BufferFree(a) sqlite3Fts5BufferFree(a) #define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) #define fts5BufferGrow(pRc,pBuf,nn) ( \ @@ -234441,12 +183841,12 @@ /* Write and decode big-endian 32-bit integer values */ static void sqlite3Fts5Put32(u8*, int); static int sqlite3Fts5Get32(const u8*); -#define FTS5_POS2COLUMN(iPos) (int)((iPos >> 32) & 0x7FFFFFFF) -#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF) +#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32) +#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF) typedef struct Fts5PoslistReader Fts5PoslistReader; struct Fts5PoslistReader { /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */ const u8 *a; /* Position list to iterate through */ @@ -234477,11 +183877,11 @@ int *pi, /* IN/OUT: Offset within a[] */ i64 *piOff /* IN/OUT: Current offset */ ); /* Malloc utility */ -static void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte); +static void *sqlite3Fts5MallocZero(int *pRc, int nByte); static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn); /* Character set tests (like isspace(), isalpha() etc.) */ static int sqlite3Fts5IsBareword(char t); @@ -234514,23 +183914,20 @@ #define sqlite3Fts5IterEof(x) ((x)->bEof) /* ** Values used as part of the flags argument passed to IndexQuery(). */ -#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ -#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ -#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ -#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ +#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ +#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ +#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ +#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ /* The following are used internally by the fts5_index.c module. They are ** defined here only to make it easier to avoid clashes with the flags ** above. */ -#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 -#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 -#define FTS5INDEX_QUERY_SKIPHASH 0x0040 -#define FTS5INDEX_QUERY_NOTOKENDATA 0x0080 -#define FTS5INDEX_QUERY_SCANONETERM 0x0100 +#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 +#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 /* ** Create/destroy an Fts5Index object. */ static int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); @@ -234538,31 +183935,31 @@ /* ** Return a simple checksum value based on the arguments. */ static u64 sqlite3Fts5IndexEntryCksum( - i64 iRowid, - int iCol, - int iPos, + i64 iRowid, + int iCol, + int iPos, int iIdx, const char *pTerm, int nTerm ); /* -** Argument p points to a buffer containing utf-8 text that is n bytes in +** Argument p points to a buffer containing utf-8 text that is n bytes in ** size. Return the number of bytes in the nChar character prefix of the ** buffer, or 0 if there are less than nChar characters in total. */ static int sqlite3Fts5IndexCharlenToBytelen( - const char *p, - int nByte, + const char *p, + int nByte, int nChar ); /* -** Open a new iterator to iterate though all rowids that match the +** Open a new iterator to iterate though all rowids that match the ** specified token or token prefix. */ static int sqlite3Fts5IndexQuery( Fts5Index *p, /* FTS index to query */ const char *pToken, int nToken, /* Token (or prefix) to query for */ @@ -234581,38 +183978,19 @@ /* ** Close an iterator opened by sqlite3Fts5IndexQuery(). */ static void sqlite3Fts5IterClose(Fts5IndexIter*); -/* -** Close the reader blob handle, if it is open. -*/ -static void sqlite3Fts5IndexCloseReader(Fts5Index*); - /* ** This interface is used by the fts5vocab module. */ static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); static int sqlite3Fts5IterNextScan(Fts5IndexIter*); -static void *sqlite3Fts5StructureRef(Fts5Index*); -static void sqlite3Fts5StructureRelease(void*); -static int sqlite3Fts5StructureTest(Fts5Index*, void*); - -/* -** Used by xInstToken(): -*/ -static int sqlite3Fts5IterToken( - Fts5IndexIter *pIndexIter, - const char *pToken, int nToken, - i64 iRowid, - int iCol, - int iOff, - const char **ppOut, int *pnOut -); - -/* -** Insert or remove data to or from the index. Each time a document is + + +/* +** Insert or remove data to or from the index. Each time a document is ** added to or removed from the index, this function is called one or more ** times. ** ** For an insert, it must be called once for each token in the new document. ** If the operation is a delete, it must be called (at least) once for each @@ -234643,11 +184021,11 @@ static int sqlite3Fts5IndexSync(Fts5Index *p); /* ** Discard any data stored in the in-memory hash tables. Do not write it ** to the database. Additionally, assume that the contents of the %_data -** table may have changed on disk. So any in-memory caches of %_data +** table may have changed on disk. So any in-memory caches of %_data ** records must be invalidated. */ static int sqlite3Fts5IndexRollback(Fts5Index *p); /* @@ -234657,22 +184035,22 @@ static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int); /* ** Functions called by the storage module as part of integrity-check. */ -static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum, int bUseCksum); +static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum); -/* -** Called during virtual module initialization to register UDF -** fts5_decode() with SQLite +/* +** Called during virtual module initialization to register UDF +** fts5_decode() with SQLite */ static int sqlite3Fts5IndexInit(sqlite3*); static int sqlite3Fts5IndexSetCookie(Fts5Index*, int); /* -** Return the total number of entries read from the %_data table by +** Return the total number of entries read from the %_data table by ** this connection since it was created. */ static int sqlite3Fts5IndexReads(Fts5Index *p); static int sqlite3Fts5IndexReinit(Fts5Index *p); @@ -234680,33 +184058,23 @@ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); static int sqlite3Fts5IndexReset(Fts5Index *p); static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); -static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin); -static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid); - -static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter*); - -/* Used to populate hash tables for xInstToken in detail=none/column mode. */ -static int sqlite3Fts5IndexIterWriteTokendata( - Fts5IndexIter*, const char*, int, i64 iRowid, int iCol, int iOff -); - /* ** End of interface to code in fts5_index.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_varint.c. +** Interface to code in fts5_varint.c. */ static int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v); static int sqlite3Fts5GetVarintLen(u32 iVal); static u8 sqlite3Fts5GetVarint(const unsigned char*, u64*); static int sqlite3Fts5PutVarint(unsigned char *p, u64 v); -#define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&(b)) +#define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&b) #define fts5GetVarint sqlite3Fts5GetVarint #define fts5FastGetVarint32(a, iOff, nVal) { \ nVal = (a)[iOff++]; \ if( nVal & 0x80 ){ \ @@ -234720,43 +184088,30 @@ ** End of interface to code in fts5_varint.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_main.c. -*/ - -/* -** Virtual-table object. -*/ -typedef struct Fts5Table Fts5Table; -struct Fts5Table { - sqlite3_vtab base; /* Base class used by SQLite core */ - Fts5Config *pConfig; /* Virtual table configuration */ - Fts5Index *pIndex; /* Full-text index */ -}; - -static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig); - -static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64); - -static int sqlite3Fts5FlushToDisk(Fts5Table*); - -static void sqlite3Fts5ClearLocale(Fts5Config *pConfig); -static void sqlite3Fts5SetLocale(Fts5Config *pConfig, const char *pLoc, int nLoc); - -static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal); -static int sqlite3Fts5DecodeLocaleValue(sqlite3_value *pVal, - const char **ppText, int *pnText, const char **ppLoc, int *pnLoc +** Interface to code in fts5.c. +*/ + +static int sqlite3Fts5GetTokenizer( + Fts5Global*, + const char **azArg, + int nArg, + Fts5Tokenizer**, + fts5_tokenizer**, + char **pzErr ); + +static Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **); /* ** End of interface to code in fts5.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_hash.c. +** Interface to code in fts5_hash.c. */ typedef struct Fts5Hash Fts5Hash; /* ** Create a hash table, free a hash table. @@ -234776,20 +184131,14 @@ /* ** Empty (but do not delete) a hash table. */ static void sqlite3Fts5HashClear(Fts5Hash*); -/* -** Return true if the hash is empty, false otherwise. -*/ -static int sqlite3Fts5HashIsEmpty(Fts5Hash*); - static int sqlite3Fts5HashQuery( Fts5Hash*, /* Hash table to query */ - int nPre, const char *pTerm, int nTerm, /* Query term */ - void **ppObj, /* OUT: Pointer to doclist for pTerm */ + const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ int *pnDoclist /* OUT: Size of doclist in bytes */ ); static int sqlite3Fts5HashScanInit( Fts5Hash*, /* Hash table to query */ @@ -234797,23 +184146,21 @@ ); static void sqlite3Fts5HashScanNext(Fts5Hash*); static int sqlite3Fts5HashScanEof(Fts5Hash*); static void sqlite3Fts5HashScanEntry(Fts5Hash *, const char **pzTerm, /* OUT: term (nul-terminated) */ - int *pnTerm, /* OUT: Size of term in bytes */ const u8 **ppDoclist, /* OUT: pointer to doclist */ int *pnDoclist /* OUT: size of doclist in bytes */ ); - /* ** End of interface to code in fts5_hash.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_storage.c. fts5_storage.c contains contains +** Interface to code in fts5_storage.c. fts5_storage.c contains contains ** code to access the data stored in the %_content and %_docsize tables. */ #define FTS5_STMT_SCAN_ASC 0 /* SELECT rowid, * FROM ... ORDER BY 1 ASC */ #define FTS5_STMT_SCAN_DESC 1 /* SELECT rowid, * FROM ... ORDER BY 1 DESC */ @@ -234826,15 +184173,15 @@ static int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName); static int sqlite3Fts5DropAll(Fts5Config*); static int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **); -static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**, int); -static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, int, sqlite3_value**, i64*); +static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**); +static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*); static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64); -static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg); +static int sqlite3Fts5StorageIntegrity(Fts5Storage *p); static int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**); static void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*); static int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol); @@ -234852,20 +184199,17 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p); static int sqlite3Fts5StorageOptimize(Fts5Storage *p); static int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge); static int sqlite3Fts5StorageReset(Fts5Storage *p); -static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage*); -static int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel); - /* ** End of interface to code in fts5_storage.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_expr.c. +** Interface to code in fts5_expr.c. */ typedef struct Fts5Expr Fts5Expr; typedef struct Fts5ExprNode Fts5ExprNode; typedef struct Fts5Parse Fts5Parse; typedef struct Fts5Token Fts5Token; @@ -234877,24 +184221,16 @@ int n; /* Size of buffer p in bytes */ }; /* Parse a MATCH expression. */ static int sqlite3Fts5ExprNew( - Fts5Config *pConfig, - int bPhraseToAnd, + Fts5Config *pConfig, int iCol, /* Column on LHS of MATCH operator */ const char *zExpr, - Fts5Expr **ppNew, + Fts5Expr **ppNew, char **pzErr ); -static int sqlite3Fts5ExprPattern( - Fts5Config *pConfig, - int bGlob, - int iCol, - const char *zText, - Fts5Expr **pp -); /* ** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc); ** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr); ** rc = sqlite3Fts5ExprNext(pExpr) @@ -234907,11 +184243,10 @@ static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax); static int sqlite3Fts5ExprEof(Fts5Expr*); static i64 sqlite3Fts5ExprRowid(Fts5Expr*); static void sqlite3Fts5ExprFree(Fts5Expr*); -static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2); /* Called during startup to register a UDF with SQLite */ static int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*); static int sqlite3Fts5ExprPhraseCount(Fts5Expr*); @@ -234927,14 +184262,10 @@ static int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**); static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *); -static int sqlite3Fts5ExprQueryToken(Fts5Expr*, int, int, const char**, int*); -static int sqlite3Fts5ExprInstToken(Fts5Expr*, i64, int, int, int, int, const char**, int*); -static void sqlite3Fts5ExprClearTokens(Fts5Expr*); - /******************************************* ** The fts5_expr.c API above this point is used by the other hand-written ** C code in this module. The interfaces below this point are called by ** the parser code in fts5parse.y. */ @@ -234953,27 +184284,25 @@ Fts5ExprNode *pLeft, Fts5ExprNode *pRight ); static Fts5ExprPhrase *sqlite3Fts5ParseTerm( - Fts5Parse *pParse, - Fts5ExprPhrase *pPhrase, + Fts5Parse *pParse, + Fts5ExprPhrase *pPhrase, Fts5Token *pToken, int bPrefix ); -static void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase*); - static Fts5ExprNearset *sqlite3Fts5ParseNearset( - Fts5Parse*, + Fts5Parse*, Fts5ExprNearset*, - Fts5ExprPhrase* + Fts5ExprPhrase* ); static Fts5Colset *sqlite3Fts5ParseColset( - Fts5Parse*, - Fts5Colset*, + Fts5Parse*, + Fts5Colset*, Fts5Token * ); static void sqlite3Fts5ParsePhraseFree(Fts5ExprPhrase*); static void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*); @@ -234990,34 +184319,29 @@ **************************************************************************/ /************************************************************************** -** Interface to code in fts5_aux.c. +** Interface to code in fts5_aux.c. */ static int sqlite3Fts5AuxInit(fts5_api*); /* ** End of interface to code in fts5_aux.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_tokenizer.c. +** Interface to code in fts5_tokenizer.c. */ static int sqlite3Fts5TokenizerInit(fts5_api*); -static int sqlite3Fts5TokenizerPattern( - int (*xCreate)(void*, const char**, int, Fts5Tokenizer**), - Fts5Tokenizer *pTok -); -static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*); /* ** End of interface to code in fts5_tokenizer.c. **************************************************************************/ /************************************************************************** -** Interface to code in fts5_vocab.c. +** Interface to code in fts5_vocab.c. */ static int sqlite3Fts5VocabInit(Fts5Global*, sqlite3*); /* @@ -235024,18 +184348,15 @@ ** End of interface to code in fts5_vocab.c. **************************************************************************/ /************************************************************************** -** Interface to automatically generated code in fts5_unicode2.c. +** Interface to automatically generated code in fts5_unicode2.c. */ +static int sqlite3Fts5UnicodeIsalnum(int c); static int sqlite3Fts5UnicodeIsdiacritic(int c); static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); - -static int sqlite3Fts5UnicodeCatParse(const char*, u8*); -static int sqlite3Fts5UnicodeCategory(u32 iCode); -static void sqlite3Fts5UnicodeAscii(u8*, u8*); /* ** End of interface to code in fts5_unicode2.c. **************************************************************************/ #endif @@ -235049,18 +184370,14 @@ #define FTS5_LCP 7 #define FTS5_RCP 8 #define FTS5_STRING 9 #define FTS5_LP 10 #define FTS5_RP 11 -#define FTS5_CARET 12 -#define FTS5_COMMA 13 -#define FTS5_PLUS 14 -#define FTS5_STAR 15 - -/* This file is automatically generated by Lemon from input grammar -** source file "fts5parse.y". -*/ +#define FTS5_COMMA 12 +#define FTS5_PLUS 13 +#define FTS5_STAR 14 + /* ** 2000-05-29 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -235081,10 +184398,11 @@ ** source file. ** ** The following is the concatenation of all %include directives from the ** input grammar file: */ +/* #include */ /************ Begin %include sections from the grammar ************************/ /* #include "fts5Int.h" */ /* #include "fts5parse.h" */ @@ -235110,30 +184428,15 @@ ** into sqlite3ParserAlloc(). The default is size_t. */ #define fts5YYMALLOCARGTYPE u64 /**************** End of %include directives **********************************/ -/* These constants specify the various numeric values for terminal symbols. -***************** Begin token definitions *************************************/ -#ifndef FTS5_OR -#define FTS5_OR 1 -#define FTS5_AND 2 -#define FTS5_NOT 3 -#define FTS5_TERM 4 -#define FTS5_COLON 5 -#define FTS5_MINUS 6 -#define FTS5_LCP 7 -#define FTS5_RCP 8 -#define FTS5_STRING 9 -#define FTS5_LP 10 -#define FTS5_RP 11 -#define FTS5_CARET 12 -#define FTS5_COMMA 13 -#define FTS5_PLUS 14 -#define FTS5_STAR 15 -#endif -/**************** End token definitions ***************************************/ +/* These constants specify the various numeric values for terminal symbols +** in a format understandable to "makeheaders". This section is blank unless +** "lemon" is run with the "-m" command-line option. +***************** Begin makeheaders token definitions *************************/ +/**************** End makeheaders token definitions ***************************/ /* The next sections is a series of control #defines. ** various aspects of the generated parser. ** fts5YYCODETYPE is the data type used to store the integer codes ** that represent terminal and non-terminal symbols. @@ -235154,49 +184457,40 @@ ** value associated with a terminal or non-terminal ** symbols. For example, for an "ID" terminal symbol, ** the minor type might be the name of the identifier. ** Each non-terminal can have a different minor type. ** Terminal symbols all have the same minor type, though. -** This macros defines the minor type for terminal +** This macros defines the minor type for terminal ** symbols. ** fts5YYMINORTYPE is the data type used for all minor types. ** This is typically a union of many types, one of ** which is sqlite3Fts5ParserFTS5TOKENTYPE. The entry in the union ** for terminal symbols is called "fts5yy0". ** fts5YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** sqlite3Fts5ParserARG_SDECL A static variable declaration for the %extra_argument ** sqlite3Fts5ParserARG_PDECL A parameter declaration for the %extra_argument -** sqlite3Fts5ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter ** sqlite3Fts5ParserARG_STORE Code to store %extra_argument into fts5yypParser ** sqlite3Fts5ParserARG_FETCH Code to extract %extra_argument from fts5yypParser -** sqlite3Fts5ParserCTX_* As sqlite3Fts5ParserARG_ except for %extra_context -** fts5YYREALLOC Name of the realloc() function to use -** fts5YYFREE Name of the free() function to use -** fts5YYDYNSTACK True if stack space should be extended on heap ** fts5YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. ** fts5YYNSTATE the combined number of states. ** fts5YYNRULE the number of rules in the grammar -** fts5YYNFTS5TOKEN Number of terminal symbols ** fts5YY_MAX_SHIFT Maximum value for shift actions ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions +** fts5YY_MIN_REDUCE Maximum value for reduce actions ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op -** fts5YY_MIN_REDUCE Minimum value for reduce actions -** fts5YY_MAX_REDUCE Maximum value for reduce actions -** fts5YY_MIN_DSTRCTR Minimum symbol value that has a destructor -** fts5YY_MAX_DSTRCTR Maximum symbol value that has a destructor */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ #define fts5YYCODETYPE unsigned char -#define fts5YYNOCODE 27 +#define fts5YYNOCODE 28 #define fts5YYACTIONTYPE unsigned char #define sqlite3Fts5ParserFTS5TOKENTYPE Fts5Token typedef union { int fts5yyinit; sqlite3Fts5ParserFTS5TOKENTYPE fts5yy0; @@ -235209,37 +184503,23 @@ #ifndef fts5YYSTACKDEPTH #define fts5YYSTACKDEPTH 100 #endif #define sqlite3Fts5ParserARG_SDECL Fts5Parse *pParse; #define sqlite3Fts5ParserARG_PDECL ,Fts5Parse *pParse -#define sqlite3Fts5ParserARG_PARAM ,pParse -#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; -#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; -#define fts5YYREALLOC realloc -#define fts5YYFREE free -#define fts5YYDYNSTACK 0 -#define sqlite3Fts5ParserCTX_SDECL -#define sqlite3Fts5ParserCTX_PDECL -#define sqlite3Fts5ParserCTX_PARAM -#define sqlite3Fts5ParserCTX_FETCH -#define sqlite3Fts5ParserCTX_STORE -#define fts5YYNSTATE 35 -#define fts5YYNRULE 28 -#define fts5YYNRULE_WITH_ACTION 28 -#define fts5YYNFTS5TOKEN 16 -#define fts5YY_MAX_SHIFT 34 -#define fts5YY_MIN_SHIFTREDUCE 52 -#define fts5YY_MAX_SHIFTREDUCE 79 -#define fts5YY_ERROR_ACTION 80 -#define fts5YY_ACCEPT_ACTION 81 -#define fts5YY_NO_ACTION 82 -#define fts5YY_MIN_REDUCE 83 -#define fts5YY_MAX_REDUCE 110 -#define fts5YY_MIN_DSTRCTR 16 -#define fts5YY_MAX_DSTRCTR 24 +#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse = fts5yypParser->pParse +#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse = pParse +#define fts5YYNSTATE 33 +#define fts5YYNRULE 27 +#define fts5YY_MAX_SHIFT 32 +#define fts5YY_MIN_SHIFTREDUCE 50 +#define fts5YY_MAX_SHIFTREDUCE 76 +#define fts5YY_MIN_REDUCE 77 +#define fts5YY_MAX_REDUCE 103 +#define fts5YY_ERROR_ACTION 104 +#define fts5YY_ACCEPT_ACTION 105 +#define fts5YY_NO_ACTION 106 /************* End control #defines *******************************************/ -#define fts5YY_NLOOKAHEAD ((int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]))) /* Define the fts5yytestcase() macro to be a no-op if is not already defined ** otherwise. ** ** Applications can choose to define fts5yytestcase() in the %include section @@ -235249,64 +184529,54 @@ */ #ifndef fts5yytestcase # define fts5yytestcase(X) #endif -/* Macro to determine if stack space has the ability to grow using -** heap memory. -*/ -#if fts5YYSTACKDEPTH<=0 || fts5YYDYNSTACK -# define fts5YYGROWABLESTACK 1 -#else -# define fts5YYGROWABLESTACK 0 -#endif - -/* Guarantee a minimum number of initial stack slots. -*/ -#if fts5YYSTACKDEPTH<=0 -# undef fts5YYSTACKDEPTH -# define fts5YYSTACKDEPTH 2 /* Need a minimum stack size */ -#endif - /* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an -** action integer. +** action integer. ** ** Suppose the action integer is N. Then the action is determined as ** follows ** ** 0 <= N <= fts5YY_MAX_SHIFT Shift N. That is, push the lookahead ** token onto the stack and goto state N. ** ** N between fts5YY_MIN_SHIFTREDUCE Shift to an arbitrary state then ** and fts5YY_MAX_SHIFTREDUCE reduce by rule N-fts5YY_MIN_SHIFTREDUCE. +** +** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE +** and fts5YY_MAX_REDUCE ** ** N == fts5YY_ERROR_ACTION A syntax error has occurred. ** ** N == fts5YY_ACCEPT_ACTION The parser accepts its input. ** ** N == fts5YY_NO_ACTION No such action. Denotes unused ** slots in the fts5yy_action[] table. ** -** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE -** and fts5YY_MAX_REDUCE -** ** The action table is constructed as a single large table named fts5yy_action[]. ** Given state S and lookahead X, the action is computed as either: ** ** (A) N = fts5yy_action[ fts5yy_shift_ofst[S] + X ] ** (B) N = fts5yy_default[S] ** -** The (A) formula is preferred. The B formula is used instead if -** fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X. +** The (A) formula is preferred. The B formula is used instead if: +** (1) The fts5yy_shift_ofst[S]+X value is out of range, or +** (2) fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X, or +** (3) fts5yy_shift_ofst[S] equal fts5YY_SHIFT_USE_DFLT. +** (Implementation note: fts5YY_SHIFT_USE_DFLT is chosen so that +** fts5YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) ** ** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the fts5yy_reduce_ofst[] array is used in place of -** the fts5yy_shift_ofst[] array. +** the fts5yy_shift_ofst[] array and fts5YY_REDUCE_USE_DFLT is used in place of +** fts5YY_SHIFT_USE_DFLT. ** ** The following are the tables generated in this section: ** ** fts5yy_action[] A single table containing all actions. ** fts5yy_lookahead[] A table containing the lookahead for each entry in @@ -235316,66 +184586,64 @@ ** fts5yy_reduce_ofst[] For each state, the offset into fts5yy_action for ** shifting non-terminals after a reduce. ** fts5yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define fts5YY_ACTTAB_COUNT (105) +#define fts5YY_ACTTAB_COUNT (98) static const fts5YYACTIONTYPE fts5yy_action[] = { - /* 0 */ 81, 20, 96, 6, 28, 99, 98, 26, 26, 18, - /* 10 */ 96, 6, 28, 17, 98, 56, 26, 19, 96, 6, - /* 20 */ 28, 14, 98, 14, 26, 31, 92, 96, 6, 28, - /* 30 */ 108, 98, 25, 26, 21, 96, 6, 28, 78, 98, - /* 40 */ 58, 26, 29, 96, 6, 28, 107, 98, 22, 26, - /* 50 */ 24, 16, 12, 11, 1, 13, 13, 24, 16, 23, - /* 60 */ 11, 33, 34, 13, 97, 8, 27, 32, 98, 7, - /* 70 */ 26, 3, 4, 5, 3, 4, 5, 3, 83, 4, - /* 80 */ 5, 3, 63, 5, 3, 62, 12, 2, 86, 13, - /* 90 */ 9, 30, 10, 10, 54, 57, 75, 78, 78, 53, - /* 100 */ 57, 15, 82, 82, 71, + /* 0 */ 105, 19, 90, 6, 26, 93, 92, 24, 24, 17, + /* 10 */ 90, 6, 26, 16, 92, 54, 24, 18, 90, 6, + /* 20 */ 26, 10, 92, 12, 24, 75, 86, 90, 6, 26, + /* 30 */ 13, 92, 75, 24, 20, 90, 6, 26, 101, 92, + /* 40 */ 56, 24, 27, 90, 6, 26, 100, 92, 21, 24, + /* 50 */ 23, 15, 30, 11, 1, 91, 22, 25, 9, 92, + /* 60 */ 7, 24, 3, 4, 5, 3, 4, 5, 3, 77, + /* 70 */ 4, 5, 3, 61, 23, 15, 60, 11, 80, 12, + /* 80 */ 2, 13, 68, 10, 29, 52, 55, 75, 31, 32, + /* 90 */ 8, 28, 5, 3, 51, 55, 72, 14, }; static const fts5YYCODETYPE fts5yy_lookahead[] = { /* 0 */ 16, 17, 18, 19, 20, 22, 22, 24, 24, 17, /* 10 */ 18, 19, 20, 7, 22, 9, 24, 17, 18, 19, - /* 20 */ 20, 9, 22, 9, 24, 13, 17, 18, 19, 20, - /* 30 */ 26, 22, 24, 24, 17, 18, 19, 20, 15, 22, + /* 20 */ 20, 10, 22, 9, 24, 14, 17, 18, 19, 20, + /* 30 */ 9, 22, 14, 24, 17, 18, 19, 20, 26, 22, /* 40 */ 9, 24, 17, 18, 19, 20, 26, 22, 21, 24, - /* 50 */ 6, 7, 9, 9, 10, 12, 12, 6, 7, 21, - /* 60 */ 9, 24, 25, 12, 18, 5, 20, 14, 22, 5, - /* 70 */ 24, 3, 1, 2, 3, 1, 2, 3, 0, 1, - /* 80 */ 2, 3, 11, 2, 3, 11, 9, 10, 5, 12, - /* 90 */ 23, 24, 10, 10, 8, 9, 9, 15, 15, 8, - /* 100 */ 9, 9, 27, 27, 11, 27, 27, 27, 27, 27, - /* 110 */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - /* 120 */ 27, + /* 50 */ 6, 7, 13, 9, 10, 18, 21, 20, 5, 22, + /* 60 */ 5, 24, 3, 1, 2, 3, 1, 2, 3, 0, + /* 70 */ 1, 2, 3, 11, 6, 7, 11, 9, 5, 9, + /* 80 */ 10, 9, 11, 10, 12, 8, 9, 14, 24, 25, + /* 90 */ 23, 24, 2, 3, 8, 9, 9, 9, }; -#define fts5YY_SHIFT_COUNT (34) +#define fts5YY_SHIFT_USE_DFLT (98) +#define fts5YY_SHIFT_COUNT (32) #define fts5YY_SHIFT_MIN (0) -#define fts5YY_SHIFT_MAX (93) +#define fts5YY_SHIFT_MAX (90) static const unsigned char fts5yy_shift_ofst[] = { - /* 0 */ 44, 44, 44, 44, 44, 44, 51, 77, 43, 12, - /* 10 */ 14, 83, 82, 14, 23, 23, 31, 31, 71, 74, - /* 20 */ 78, 81, 86, 91, 6, 53, 53, 60, 64, 68, - /* 30 */ 53, 87, 92, 53, 93, + /* 0 */ 44, 44, 44, 44, 44, 44, 68, 70, 72, 14, + /* 10 */ 21, 73, 11, 18, 18, 31, 31, 62, 65, 69, + /* 20 */ 90, 77, 86, 6, 39, 53, 55, 59, 39, 87, + /* 30 */ 88, 39, 71, }; -#define fts5YY_REDUCE_COUNT (17) +#define fts5YY_REDUCE_USE_DFLT (-18) +#define fts5YY_REDUCE_COUNT (16) #define fts5YY_REDUCE_MIN (-17) #define fts5YY_REDUCE_MAX (67) static const signed char fts5yy_reduce_ofst[] = { - /* 0 */ -16, -8, 0, 9, 17, 25, 46, -17, -17, 37, - /* 10 */ 67, 4, 4, 8, 4, 20, 27, 38, + /* 0 */ -16, -8, 0, 9, 17, 25, 37, -17, 64, -17, + /* 10 */ 67, 12, 12, 12, 20, 27, 35, }; static const fts5YYACTIONTYPE fts5yy_default[] = { - /* 0 */ 80, 80, 80, 80, 80, 80, 95, 80, 80, 105, - /* 10 */ 80, 110, 110, 80, 110, 110, 80, 80, 80, 80, - /* 20 */ 80, 91, 80, 80, 80, 101, 100, 80, 80, 90, - /* 30 */ 103, 80, 80, 104, 80, + /* 0 */ 104, 104, 104, 104, 104, 104, 89, 104, 98, 104, + /* 10 */ 104, 103, 103, 103, 103, 104, 104, 104, 104, 104, + /* 20 */ 85, 104, 104, 104, 94, 104, 104, 84, 96, 104, + /* 30 */ 104, 97, 104, }; /********** End of lemon-generated parsing tables *****************************/ -/* The next table maps tokens (terminal symbols) into fallback tokens. +/* The next table maps tokens (terminal symbols) into fallback tokens. ** If a construct like the following: -** +** ** %fallback ID X Y Z. ** ** appears in the grammar, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and @@ -235424,29 +184692,32 @@ #endif #ifndef fts5YYNOERRORRECOVERY int fts5yyerrcnt; /* Shifts left before out of the error */ #endif sqlite3Fts5ParserARG_SDECL /* A place to hold %extra_argument */ - sqlite3Fts5ParserCTX_SDECL /* A place to hold %extra_context */ - fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ - fts5yyStackEntry *fts5yystack; /* The parser stack */ - fts5yyStackEntry fts5yystk0[fts5YYSTACKDEPTH]; /* Initial stack space */ +#if fts5YYSTACKDEPTH<=0 + int fts5yystksz; /* Current side of the stack */ + fts5yyStackEntry *fts5yystack; /* The parser's stack */ + fts5yyStackEntry fts5yystk0; /* First stack entry */ +#else + fts5yyStackEntry fts5yystack[fts5YYSTACKDEPTH]; /* The parser's stack */ + fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ +#endif }; typedef struct fts5yyParser fts5yyParser; -/* #include */ #ifndef NDEBUG /* #include */ static FILE *fts5yyTraceFILE = 0; static char *fts5yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG -/* +/* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL +** by making either argument NULL ** ** Inputs: **
                    **
                  • A FILE* to which trace output should be written. ** If NULL, then tracing is turned off. @@ -235464,43 +184735,23 @@ if( fts5yyTraceFILE==0 ) fts5yyTracePrompt = 0; else if( fts5yyTracePrompt==0 ) fts5yyTraceFILE = 0; } #endif /* NDEBUG */ -#if defined(fts5YYCOVERAGE) || !defined(NDEBUG) +#ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ -static const char *const fts5yyTokenName[] = { - /* 0 */ "$", - /* 1 */ "OR", - /* 2 */ "AND", - /* 3 */ "NOT", - /* 4 */ "TERM", - /* 5 */ "COLON", - /* 6 */ "MINUS", - /* 7 */ "LCP", - /* 8 */ "RCP", - /* 9 */ "STRING", - /* 10 */ "LP", - /* 11 */ "RP", - /* 12 */ "CARET", - /* 13 */ "COMMA", - /* 14 */ "PLUS", - /* 15 */ "STAR", - /* 16 */ "input", - /* 17 */ "expr", - /* 18 */ "cnearset", - /* 19 */ "exprlist", - /* 20 */ "colset", - /* 21 */ "colsetlist", - /* 22 */ "nearset", - /* 23 */ "nearphrases", - /* 24 */ "phrase", - /* 25 */ "neardist_opt", - /* 26 */ "star_opt", +static const char *const fts5yyTokenName[] = { + "$", "OR", "AND", "NOT", + "TERM", "COLON", "MINUS", "LCP", + "RCP", "STRING", "LP", "RP", + "COMMA", "PLUS", "STAR", "error", + "input", "expr", "cnearset", "exprlist", + "colset", "colsetlist", "nearset", "nearphrases", + "phrase", "neardist_opt", "star_opt", }; -#endif /* defined(fts5YYCOVERAGE) || !defined(NDEBUG) */ +#endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *const fts5yyRuleName[] = { @@ -235520,63 +184771,54 @@ /* 13 */ "exprlist ::= cnearset", /* 14 */ "exprlist ::= exprlist cnearset", /* 15 */ "cnearset ::= nearset", /* 16 */ "cnearset ::= colset COLON nearset", /* 17 */ "nearset ::= phrase", - /* 18 */ "nearset ::= CARET phrase", - /* 19 */ "nearset ::= STRING LP nearphrases neardist_opt RP", - /* 20 */ "nearphrases ::= phrase", - /* 21 */ "nearphrases ::= nearphrases phrase", - /* 22 */ "neardist_opt ::=", - /* 23 */ "neardist_opt ::= COMMA STRING", - /* 24 */ "phrase ::= phrase PLUS STRING star_opt", - /* 25 */ "phrase ::= STRING star_opt", - /* 26 */ "star_opt ::= STAR", - /* 27 */ "star_opt ::=", + /* 18 */ "nearset ::= STRING LP nearphrases neardist_opt RP", + /* 19 */ "nearphrases ::= phrase", + /* 20 */ "nearphrases ::= nearphrases phrase", + /* 21 */ "neardist_opt ::=", + /* 22 */ "neardist_opt ::= COMMA STRING", + /* 23 */ "phrase ::= phrase PLUS STRING star_opt", + /* 24 */ "phrase ::= STRING star_opt", + /* 25 */ "star_opt ::= STAR", + /* 26 */ "star_opt ::=", }; #endif /* NDEBUG */ -#if fts5YYGROWABLESTACK +#if fts5YYSTACKDEPTH<=0 /* ** Try to increase the size of the parser stack. Return the number ** of errors. Return 0 on success. */ static int fts5yyGrowStack(fts5yyParser *p){ - int oldSize = 1 + (int)(p->fts5yystackEnd - p->fts5yystack); int newSize; int idx; fts5yyStackEntry *pNew; - newSize = oldSize*2 + 100; - idx = (int)(p->fts5yytos - p->fts5yystack); - if( p->fts5yystack==p->fts5yystk0 ){ - pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0])); - if( pNew==0 ) return 1; - memcpy(pNew, p->fts5yystack, oldSize*sizeof(pNew[0])); + newSize = p->fts5yystksz*2 + 100; + idx = p->fts5yytos ? (int)(p->fts5yytos - p->fts5yystack) : 0; + if( p->fts5yystack==&p->fts5yystk0 ){ + pNew = malloc(newSize*sizeof(pNew[0])); + if( pNew ) pNew[0] = p->fts5yystk0; }else{ - pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0])); - if( pNew==0 ) return 1; + pNew = realloc(p->fts5yystack, newSize*sizeof(pNew[0])); } - p->fts5yystack = pNew; - p->fts5yytos = &p->fts5yystack[idx]; + if( pNew ){ + p->fts5yystack = pNew; + p->fts5yytos = &p->fts5yystack[idx]; #ifndef NDEBUG - if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE,"%sStack grows from %d to %d entries.\n", - fts5yyTracePrompt, oldSize, newSize); - } -#endif - p->fts5yystackEnd = &p->fts5yystack[newSize-1]; - return 0; -} -#endif /* fts5YYGROWABLESTACK */ - -#if !fts5YYGROWABLESTACK -/* For builds that do no have a growable stack, fts5yyGrowStack always -** returns an error. -*/ -# define fts5yyGrowStack(X) 1 + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sStack grows from %d to %d entries.\n", + fts5yyTracePrompt, p->fts5yystksz, newSize); + } +#endif + p->fts5yystksz = newSize; + } + return pNew==0; +} #endif /* Datatype of the argument to the memory allocated passed as the ** second argument to sqlite3Fts5ParserAlloc() below. This can be changed by ** putting an appropriate #define in the %include section of the input @@ -235586,28 +184828,37 @@ # define fts5YYMALLOCARGTYPE size_t #endif /* Initialize a new parser that has already been allocated. */ -static void sqlite3Fts5ParserInit(void *fts5yypRawParser sqlite3Fts5ParserCTX_PDECL){ - fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yypRawParser; - sqlite3Fts5ParserCTX_STORE +static void sqlite3Fts5ParserInit(void *fts5yypParser){ + fts5yyParser *pParser = (fts5yyParser*)fts5yypParser; #ifdef fts5YYTRACKMAXSTACKDEPTH - fts5yypParser->fts5yyhwm = 0; + pParser->fts5yyhwm = 0; #endif - fts5yypParser->fts5yystack = fts5yypParser->fts5yystk0; - fts5yypParser->fts5yystackEnd = &fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1]; +#if fts5YYSTACKDEPTH<=0 + pParser->fts5yytos = NULL; + pParser->fts5yystack = NULL; + pParser->fts5yystksz = 0; + if( fts5yyGrowStack(pParser) ){ + pParser->fts5yystack = &pParser->fts5yystk0; + pParser->fts5yystksz = 1; + } +#endif #ifndef fts5YYNOERRORRECOVERY - fts5yypParser->fts5yyerrcnt = -1; + pParser->fts5yyerrcnt = -1; #endif - fts5yypParser->fts5yytos = fts5yypParser->fts5yystack; - fts5yypParser->fts5yystack[0].stateno = 0; - fts5yypParser->fts5yystack[0].major = 0; + pParser->fts5yytos = pParser->fts5yystack; + pParser->fts5yystack[0].stateno = 0; + pParser->fts5yystack[0].major = 0; +#if fts5YYSTACKDEPTH>0 + pParser->fts5yystackEnd = &pParser->fts5yystack[fts5YYSTACKDEPTH-1]; +#endif } #ifndef sqlite3Fts5Parser_ENGINEALWAYSONSTACK -/* +/* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** ** Inputs: @@ -235615,75 +184866,71 @@ ** ** Outputs: ** A pointer to a parser. This pointer is used in subsequent calls ** to sqlite3Fts5Parser and sqlite3Fts5ParserFree. */ -static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE) sqlite3Fts5ParserCTX_PDECL){ - fts5yyParser *fts5yypParser; - fts5yypParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); - if( fts5yypParser ){ - sqlite3Fts5ParserCTX_STORE - sqlite3Fts5ParserInit(fts5yypParser sqlite3Fts5ParserCTX_PARAM); - } - return (void*)fts5yypParser; +static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE)){ + fts5yyParser *pParser; + pParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); + if( pParser ) sqlite3Fts5ParserInit(pParser); + return pParser; } #endif /* sqlite3Fts5Parser_ENGINEALWAYSONSTACK */ /* The following function deletes the "minor type" or semantic value ** associated with a symbol. The symbol can be either a terminal ** or nonterminal. "fts5yymajor" is the symbol code, and "fts5yypminor" is -** a pointer to the value to be deleted. The code used to do the +** a pointer to the value to be deleted. The code used to do the ** deletions is derived from the %destructor and/or %token_destructor ** directives of the input grammar. */ static void fts5yy_destructor( fts5yyParser *fts5yypParser, /* The parser */ fts5YYCODETYPE fts5yymajor, /* Type code for object to destroy */ fts5YYMINORTYPE *fts5yypminor /* The object to be destroyed */ ){ - sqlite3Fts5ParserARG_FETCH - sqlite3Fts5ParserCTX_FETCH + sqlite3Fts5ParserARG_FETCH; switch( fts5yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is + ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ /********* Begin destructor definitions ***************************************/ case 16: /* input */ { - (void)pParse; + (void)pParse; } break; case 17: /* expr */ case 18: /* cnearset */ case 19: /* exprlist */ { - sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy24)); + sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy24)); } break; case 20: /* colset */ case 21: /* colsetlist */ { - sqlite3_free((fts5yypminor->fts5yy11)); + sqlite3_free((fts5yypminor->fts5yy11)); } break; case 22: /* nearset */ case 23: /* nearphrases */ { - sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy46)); + sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy46)); } break; case 24: /* phrase */ { - sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy53)); + sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy53)); } break; /********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } @@ -235713,35 +184960,18 @@ /* ** Clear all secondary memory allocations from the parser */ static void sqlite3Fts5ParserFinalize(void *p){ fts5yyParser *pParser = (fts5yyParser*)p; - - /* In-lined version of calling fts5yy_pop_parser_stack() for each - ** element left in the stack */ - fts5yyStackEntry *fts5yytos = pParser->fts5yytos; - while( fts5yytos>pParser->fts5yystack ){ -#ifndef NDEBUG - if( fts5yyTraceFILE ){ - fprintf(fts5yyTraceFILE,"%sPopping %s\n", - fts5yyTracePrompt, - fts5yyTokenName[fts5yytos->major]); - } -#endif - if( fts5yytos->major>=fts5YY_MIN_DSTRCTR ){ - fts5yy_destructor(pParser, fts5yytos->major, &fts5yytos->minor); - } - fts5yytos--; - } - -#if fts5YYGROWABLESTACK - if( pParser->fts5yystack!=pParser->fts5yystk0 ) fts5YYFREE(pParser->fts5yystack); + while( pParser->fts5yytos>pParser->fts5yystack ) fts5yy_pop_parser_stack(pParser); +#if fts5YYSTACKDEPTH<=0 + if( pParser->fts5yystack!=&pParser->fts5yystk0 ) free(pParser->fts5yystack); #endif } #ifndef sqlite3Fts5Parser_ENGINEALWAYSONSTACK -/* +/* ** Deallocate and destroy a parser. Destructors are called for ** all stack elements before shutting the parser down. ** ** If the fts5YYPARSEFREENEVERNULL macro exists (for example because it ** is defined in a %include section of the input grammar) then it is @@ -235767,77 +184997,32 @@ fts5yyParser *pParser = (fts5yyParser*)p; return pParser->fts5yyhwm; } #endif -/* This array of booleans keeps track of the parser statement -** coverage. The element fts5yycoverage[X][Y] is set when the parser -** is in state X and has a lookahead token Y. In a well-tested -** systems, every element of this matrix should end up being set. -*/ -#if defined(fts5YYCOVERAGE) -static unsigned char fts5yycoverage[fts5YYNSTATE][fts5YYNFTS5TOKEN]; -#endif - -/* -** Write into out a description of every state/lookahead combination that -** -** (1) has not been used by the parser, and -** (2) is not a syntax error. -** -** Return the number of missed state/lookahead combinations. -*/ -#if defined(fts5YYCOVERAGE) -static int sqlite3Fts5ParserCoverage(FILE *out){ - int stateno, iLookAhead, i; - int nMissed = 0; - for(stateno=0; statenofts5YY_MAX_SHIFT ) return stateno; + int stateno = pParser->fts5yytos->stateno; + + if( stateno>=fts5YY_MIN_REDUCE ) return stateno; assert( stateno <= fts5YY_SHIFT_COUNT ); -#if defined(fts5YYCOVERAGE) - fts5yycoverage[stateno][iLookAhead] = 1; -#endif do{ i = fts5yy_shift_ofst[stateno]; - assert( i>=0 ); - assert( i<=fts5YY_ACTTAB_COUNT ); - assert( i+fts5YYNFTS5TOKEN<=(int)fts5YY_NLOOKAHEAD ); assert( iLookAhead!=fts5YYNOCODE ); - assert( iLookAhead < fts5YYNFTS5TOKEN ); i += iLookAhead; - assert( i<(int)fts5YY_NLOOKAHEAD ); - if( fts5yy_lookahead[i]!=iLookAhead ){ + if( i<0 || i>=fts5YY_ACTTAB_COUNT || fts5yy_lookahead[i]!=iLookAhead ){ #ifdef fts5YYFALLBACK fts5YYCODETYPE iFallback; /* Fallback token */ - assert( iLookAhead %s\n", fts5yyTracePrompt, fts5yyTokenName[iLookAhead], fts5yyTokenName[iFallback]); } @@ -235848,12 +185033,19 @@ } #endif #ifdef fts5YYWILDCARD { int j = i - iLookAhead + fts5YYWILDCARD; - assert( j<(int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])) ); - if( fts5yy_lookahead[j]==fts5YYWILDCARD && iLookAhead>0 ){ + if( +#if fts5YY_SHIFT_MIN+fts5YYWILDCARD<0 + j>=0 && +#endif +#if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT + j0 + ){ #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE, "%sWILDCARD %s => %s\n", fts5yyTracePrompt, fts5yyTokenName[iLookAhead], fts5yyTokenName[fts5YYWILDCARD]); @@ -235863,22 +185055,21 @@ } } #endif /* fts5YYWILDCARD */ return fts5yy_default[stateno]; }else{ - assert( i>=0 && i<(int)(sizeof(fts5yy_action)/sizeof(fts5yy_action[0])) ); return fts5yy_action[i]; } }while(1); } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. */ -static fts5YYACTIONTYPE fts5yy_find_reduce_action( - fts5YYACTIONTYPE stateno, /* Current state number */ +static int fts5yy_find_reduce_action( + int stateno, /* Current state number */ fts5YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; #ifdef fts5YYERRORSYMBOL if( stateno>fts5YY_REDUCE_COUNT ){ @@ -235886,10 +185077,11 @@ } #else assert( stateno<=fts5YY_REDUCE_COUNT ); #endif i = fts5yy_reduce_ofst[stateno]; + assert( i!=fts5YY_REDUCE_USE_DFLT ); assert( iLookAhead!=fts5YYNOCODE ); i += iLookAhead; #ifdef fts5YYERRORSYMBOL if( i<0 || i>=fts5YY_ACTTAB_COUNT || fts5yy_lookahead[i]!=iLookAhead ){ return fts5yy_default[stateno]; @@ -235903,12 +185095,11 @@ /* ** The following routine is called if the stack overflows. */ static void fts5yyStackOverflow(fts5yyParser *fts5yypParser){ - sqlite3Fts5ParserARG_FETCH - sqlite3Fts5ParserCTX_FETCH + sqlite3Fts5ParserARG_FETCH; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sStack Overflow!\n",fts5yyTracePrompt); } #endif @@ -235917,42 +185108,40 @@ ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); /******** End %stack_overflow code ********************************************/ - sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument var */ - sqlite3Fts5ParserCTX_STORE + sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ } /* ** Print tracing information for a SHIFT action */ #ifndef NDEBUG -static void fts5yyTraceShift(fts5yyParser *fts5yypParser, int fts5yyNewState, const char *zTag){ +static void fts5yyTraceShift(fts5yyParser *fts5yypParser, int fts5yyNewState){ if( fts5yyTraceFILE ){ if( fts5yyNewStatefts5yytos->major], + fprintf(fts5yyTraceFILE,"%sShift '%s', go to state %d\n", + fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major], fts5yyNewState); }else{ - fprintf(fts5yyTraceFILE,"%s%s '%s', pending reduce %d\n", - fts5yyTracePrompt, zTag, fts5yyTokenName[fts5yypParser->fts5yytos->major], - fts5yyNewState - fts5YY_MIN_REDUCE); + fprintf(fts5yyTraceFILE,"%sShift '%s'\n", + fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major]); } } } #else -# define fts5yyTraceShift(X,Y,Z) +# define fts5yyTraceShift(X,Y) #endif /* ** Perform a shift action. */ static void fts5yy_shift( fts5yyParser *fts5yypParser, /* The parser to be shifted */ - fts5YYACTIONTYPE fts5yyNewState, /* The new state to shift in */ - fts5YYCODETYPE fts5yyMajor, /* The major token to shift in */ + int fts5yyNewState, /* The new state to shift in */ + int fts5yyMajor, /* The major token to shift in */ sqlite3Fts5ParserFTS5TOKENTYPE fts5yyMinor /* The minor token to shift in */ ){ fts5yyStackEntry *fts5yytos; fts5yypParser->fts5yytos++; #ifdef fts5YYTRACKMAXSTACKDEPTH @@ -235959,122 +185148,120 @@ if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){ fts5yypParser->fts5yyhwm++; assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack) ); } #endif - fts5yytos = fts5yypParser->fts5yytos; - if( fts5yytos>fts5yypParser->fts5yystackEnd ){ +#if fts5YYSTACKDEPTH>0 + if( fts5yypParser->fts5yytos>fts5yypParser->fts5yystackEnd ){ + fts5yypParser->fts5yytos--; + fts5yyStackOverflow(fts5yypParser); + return; + } +#else + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz] ){ if( fts5yyGrowStack(fts5yypParser) ){ fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; } - fts5yytos = fts5yypParser->fts5yytos; - assert( fts5yytos <= fts5yypParser->fts5yystackEnd ); } +#endif if( fts5yyNewState > fts5YY_MAX_SHIFT ){ fts5yyNewState += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; } - fts5yytos->stateno = fts5yyNewState; - fts5yytos->major = fts5yyMajor; + fts5yytos = fts5yypParser->fts5yytos; + fts5yytos->stateno = (fts5YYACTIONTYPE)fts5yyNewState; + fts5yytos->major = (fts5YYCODETYPE)fts5yyMajor; fts5yytos->minor.fts5yy0 = fts5yyMinor; - fts5yyTraceShift(fts5yypParser, fts5yyNewState, "Shift"); -} - -/* For rule J, fts5yyRuleInfoLhs[J] contains the symbol on the left-hand side -** of that rule */ -static const fts5YYCODETYPE fts5yyRuleInfoLhs[] = { - 16, /* (0) input ::= expr */ - 20, /* (1) colset ::= MINUS LCP colsetlist RCP */ - 20, /* (2) colset ::= LCP colsetlist RCP */ - 20, /* (3) colset ::= STRING */ - 20, /* (4) colset ::= MINUS STRING */ - 21, /* (5) colsetlist ::= colsetlist STRING */ - 21, /* (6) colsetlist ::= STRING */ - 17, /* (7) expr ::= expr AND expr */ - 17, /* (8) expr ::= expr OR expr */ - 17, /* (9) expr ::= expr NOT expr */ - 17, /* (10) expr ::= colset COLON LP expr RP */ - 17, /* (11) expr ::= LP expr RP */ - 17, /* (12) expr ::= exprlist */ - 19, /* (13) exprlist ::= cnearset */ - 19, /* (14) exprlist ::= exprlist cnearset */ - 18, /* (15) cnearset ::= nearset */ - 18, /* (16) cnearset ::= colset COLON nearset */ - 22, /* (17) nearset ::= phrase */ - 22, /* (18) nearset ::= CARET phrase */ - 22, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */ - 23, /* (20) nearphrases ::= phrase */ - 23, /* (21) nearphrases ::= nearphrases phrase */ - 25, /* (22) neardist_opt ::= */ - 25, /* (23) neardist_opt ::= COMMA STRING */ - 24, /* (24) phrase ::= phrase PLUS STRING star_opt */ - 24, /* (25) phrase ::= STRING star_opt */ - 26, /* (26) star_opt ::= STAR */ - 26, /* (27) star_opt ::= */ -}; - -/* For rule J, fts5yyRuleInfoNRhs[J] contains the negative of the number -** of symbols on the right-hand side of that rule. */ -static const signed char fts5yyRuleInfoNRhs[] = { - -1, /* (0) input ::= expr */ - -4, /* (1) colset ::= MINUS LCP colsetlist RCP */ - -3, /* (2) colset ::= LCP colsetlist RCP */ - -1, /* (3) colset ::= STRING */ - -2, /* (4) colset ::= MINUS STRING */ - -2, /* (5) colsetlist ::= colsetlist STRING */ - -1, /* (6) colsetlist ::= STRING */ - -3, /* (7) expr ::= expr AND expr */ - -3, /* (8) expr ::= expr OR expr */ - -3, /* (9) expr ::= expr NOT expr */ - -5, /* (10) expr ::= colset COLON LP expr RP */ - -3, /* (11) expr ::= LP expr RP */ - -1, /* (12) expr ::= exprlist */ - -1, /* (13) exprlist ::= cnearset */ - -2, /* (14) exprlist ::= exprlist cnearset */ - -1, /* (15) cnearset ::= nearset */ - -3, /* (16) cnearset ::= colset COLON nearset */ - -1, /* (17) nearset ::= phrase */ - -2, /* (18) nearset ::= CARET phrase */ - -5, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */ - -1, /* (20) nearphrases ::= phrase */ - -2, /* (21) nearphrases ::= nearphrases phrase */ - 0, /* (22) neardist_opt ::= */ - -2, /* (23) neardist_opt ::= COMMA STRING */ - -4, /* (24) phrase ::= phrase PLUS STRING star_opt */ - -2, /* (25) phrase ::= STRING star_opt */ - -1, /* (26) star_opt ::= STAR */ - 0, /* (27) star_opt ::= */ + fts5yyTraceShift(fts5yypParser, fts5yyNewState); +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ +} fts5yyRuleInfo[] = { + { 16, -1 }, + { 20, -4 }, + { 20, -3 }, + { 20, -1 }, + { 20, -2 }, + { 21, -2 }, + { 21, -1 }, + { 17, -3 }, + { 17, -3 }, + { 17, -3 }, + { 17, -5 }, + { 17, -3 }, + { 17, -1 }, + { 19, -1 }, + { 19, -2 }, + { 18, -1 }, + { 18, -3 }, + { 22, -1 }, + { 22, -5 }, + { 23, -1 }, + { 23, -2 }, + { 25, 0 }, + { 25, -2 }, + { 24, -4 }, + { 24, -2 }, + { 26, -1 }, + { 26, 0 }, }; static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. -** -** The fts5yyLookahead and fts5yyLookaheadToken parameters provide reduce actions -** access to the lookahead token (if any). The fts5yyLookahead will be fts5YYNOCODE -** if the lookahead token has already been consumed. As this procedure is -** only called from one place, optimizing compilers will in-line it, which -** means that the extra parameters have no performance impact. */ -static fts5YYACTIONTYPE fts5yy_reduce( +static void fts5yy_reduce( fts5yyParser *fts5yypParser, /* The parser */ - unsigned int fts5yyruleno, /* Number of the rule by which to reduce */ - int fts5yyLookahead, /* Lookahead token, or fts5YYNOCODE if none */ - sqlite3Fts5ParserFTS5TOKENTYPE fts5yyLookaheadToken /* Value of the lookahead token */ - sqlite3Fts5ParserCTX_PDECL /* %extra_context */ + unsigned int fts5yyruleno /* Number of the rule by which to reduce */ ){ int fts5yygoto; /* The next state */ - fts5YYACTIONTYPE fts5yyact; /* The next action */ + int fts5yyact; /* The next action */ fts5yyStackEntry *fts5yymsp; /* The top of the parser's stack */ int fts5yysize; /* Amount to pop the stack */ - sqlite3Fts5ParserARG_FETCH - (void)fts5yyLookahead; - (void)fts5yyLookaheadToken; + sqlite3Fts5ParserARG_FETCH; fts5yymsp = fts5yypParser->fts5yytos; +#ifndef NDEBUG + if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){ + fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; + fprintf(fts5yyTraceFILE, "%sReduce [%s], go to state %d.\n", fts5yyTracePrompt, + fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno); + } +#endif /* NDEBUG */ + + /* Check that the stack is large enough to grow by a single entry + ** if the RHS of the rule is empty. This ensures that there is room + ** enough on the stack to push the LHS value */ + if( fts5yyRuleInfo[fts5yyruleno].nrhs==0 ){ +#ifdef fts5YYTRACKMAXSTACKDEPTH + if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){ + fts5yypParser->fts5yyhwm++; + assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)); + } +#endif +#if fts5YYSTACKDEPTH>0 + if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ + fts5yyStackOverflow(fts5yypParser); + return; + } +#else + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){ + if( fts5yyGrowStack(fts5yypParser) ){ + fts5yyStackOverflow(fts5yypParser); + return; + } + fts5yymsp = fts5yypParser->fts5yytos; + } +#endif + } switch( fts5yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: @@ -236087,11 +185274,11 @@ fts5YYMINORTYPE fts5yylhsminor; case 0: /* input ::= expr */ { sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy24); } break; case 1: /* colset ::= MINUS LCP colsetlist RCP */ -{ +{ fts5yymsp[-3].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); } break; case 2: /* colset ::= LCP colsetlist RCP */ { fts5yymsp[-2].minor.fts5yy11 = fts5yymsp[-1].minor.fts5yy11; } @@ -236107,17 +185294,17 @@ fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); } break; case 5: /* colsetlist ::= colsetlist STRING */ -{ +{ fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy11, &fts5yymsp[0].minor.fts5yy0); } fts5yymsp[-1].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; case 6: /* colsetlist ::= STRING */ -{ - fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); +{ + fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); } fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; break; case 7: /* expr ::= expr AND expr */ { @@ -236157,109 +185344,106 @@ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24); } fts5yymsp[-1].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 15: /* cnearset ::= nearset */ -{ - fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); +{ + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); } fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 16: /* cnearset ::= colset COLON nearset */ -{ - fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); +{ + fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); sqlite3Fts5ParseSetColset(pParse, fts5yylhsminor.fts5yy24, fts5yymsp[-2].minor.fts5yy11); } fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; break; case 17: /* nearset ::= phrase */ { fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 18: /* nearset ::= CARET phrase */ -{ - sqlite3Fts5ParseSetCaret(fts5yymsp[0].minor.fts5yy53); - fts5yymsp[-1].minor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); -} - break; - case 19: /* nearset ::= STRING LP nearphrases neardist_opt RP */ + case 18: /* nearset ::= STRING LP nearphrases neardist_opt RP */ { sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy46, &fts5yymsp[-1].minor.fts5yy0); fts5yylhsminor.fts5yy46 = fts5yymsp[-2].minor.fts5yy46; } fts5yymsp[-4].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 20: /* nearphrases ::= phrase */ -{ - fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); + case 19: /* nearphrases ::= phrase */ +{ + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 21: /* nearphrases ::= nearphrases phrase */ + case 20: /* nearphrases ::= nearphrases phrase */ { fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy46, fts5yymsp[0].minor.fts5yy53); } fts5yymsp[-1].minor.fts5yy46 = fts5yylhsminor.fts5yy46; break; - case 22: /* neardist_opt ::= */ + case 21: /* neardist_opt ::= */ { fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } break; - case 23: /* neardist_opt ::= COMMA STRING */ + case 22: /* neardist_opt ::= COMMA STRING */ { fts5yymsp[-1].minor.fts5yy0 = fts5yymsp[0].minor.fts5yy0; } break; - case 24: /* phrase ::= phrase PLUS STRING star_opt */ -{ + case 23: /* phrase ::= phrase PLUS STRING star_opt */ +{ fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy53, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); } fts5yymsp[-3].minor.fts5yy53 = fts5yylhsminor.fts5yy53; break; - case 25: /* phrase ::= STRING star_opt */ -{ + case 24: /* phrase ::= STRING star_opt */ +{ fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); } fts5yymsp[-1].minor.fts5yy53 = fts5yylhsminor.fts5yy53; break; - case 26: /* star_opt ::= STAR */ + case 25: /* star_opt ::= STAR */ { fts5yymsp[0].minor.fts5yy4 = 1; } break; - case 27: /* star_opt ::= */ + case 26: /* star_opt ::= */ { fts5yymsp[1].minor.fts5yy4 = 0; } break; default: break; /********** End reduce actions ************************************************/ }; - assert( fts5yyrulenofts5YY_MAX_SHIFT && fts5yyact<=fts5YY_MAX_SHIFTREDUCE) ); /* It is not possible for a REDUCE to be followed by an error */ assert( fts5yyact!=fts5YY_ERROR_ACTION ); - fts5yymsp += fts5yysize+1; - fts5yypParser->fts5yytos = fts5yymsp; - fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; - fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; - fts5yyTraceShift(fts5yypParser, fts5yyact, "... then shift"); - return fts5yyact; + if( fts5yyact==fts5YY_ACCEPT_ACTION ){ + fts5yypParser->fts5yytos += fts5yysize; + fts5yy_accept(fts5yypParser); + }else{ + fts5yymsp += fts5yysize+1; + fts5yypParser->fts5yytos = fts5yymsp; + fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; + fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; + fts5yyTraceShift(fts5yypParser, fts5yyact); + } } /* ** The following code executes when the parse fails */ #ifndef fts5YYNOERRORRECOVERY static void fts5yy_parse_failed( fts5yyParser *fts5yypParser /* The parser */ ){ - sqlite3Fts5ParserARG_FETCH - sqlite3Fts5ParserCTX_FETCH + sqlite3Fts5ParserARG_FETCH; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sFail!\n",fts5yyTracePrompt); } #endif @@ -236266,12 +185450,11 @@ while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ) fts5yy_pop_parser_stack(fts5yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ /************ Begin %parse_failure code ***************************************/ /************ End %parse_failure code *****************************************/ - sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3Fts5ParserCTX_STORE + sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* fts5YYNOERRORRECOVERY */ /* ** The following code executes when a syntax error first occurs. @@ -236279,32 +185462,29 @@ static void fts5yy_syntax_error( fts5yyParser *fts5yypParser, /* The parser */ int fts5yymajor, /* The major type of the error token */ sqlite3Fts5ParserFTS5TOKENTYPE fts5yyminor /* The minor type of the error token */ ){ - sqlite3Fts5ParserARG_FETCH - sqlite3Fts5ParserCTX_FETCH + sqlite3Fts5ParserARG_FETCH; #define FTS5TOKEN fts5yyminor /************ Begin %syntax_error code ****************************************/ UNUSED_PARAM(fts5yymajor); /* Silence a compiler warning */ sqlite3Fts5ParseError( pParse, "fts5: syntax error near \"%.*s\"",FTS5TOKEN.n,FTS5TOKEN.p ); /************ End %syntax_error code ******************************************/ - sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3Fts5ParserCTX_STORE + sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following is executed when the parser accepts */ static void fts5yy_accept( fts5yyParser *fts5yypParser /* The parser */ ){ - sqlite3Fts5ParserARG_FETCH - sqlite3Fts5ParserCTX_FETCH + sqlite3Fts5ParserARG_FETCH; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sAccept!\n",fts5yyTracePrompt); } #endif @@ -236314,12 +185494,11 @@ assert( fts5yypParser->fts5yytos==fts5yypParser->fts5yystack ); /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ /*********** End %parse_accept code *******************************************/ - sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ - sqlite3Fts5ParserCTX_STORE + sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* The main parser program. ** The first argument is a pointer to a structure obtained from ** "sqlite3Fts5ParserAlloc" which describes the current state of the parser. @@ -236344,92 +185523,42 @@ int fts5yymajor, /* The major token code number */ sqlite3Fts5ParserFTS5TOKENTYPE fts5yyminor /* The value for the token */ sqlite3Fts5ParserARG_PDECL /* Optional %extra_argument parameter */ ){ fts5YYMINORTYPE fts5yyminorunion; - fts5YYACTIONTYPE fts5yyact; /* The parser action. */ + unsigned int fts5yyact; /* The parser action. */ #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) int fts5yyendofinput; /* True if we are at the end of input */ #endif #ifdef fts5YYERRORSYMBOL int fts5yyerrorhit = 0; /* True if fts5yymajor has invoked an error */ #endif - fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yyp; /* The parser */ - sqlite3Fts5ParserCTX_FETCH - sqlite3Fts5ParserARG_STORE + fts5yyParser *fts5yypParser; /* The parser */ + fts5yypParser = (fts5yyParser*)fts5yyp; assert( fts5yypParser->fts5yytos!=0 ); #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) fts5yyendofinput = (fts5yymajor==0); #endif - - fts5yyact = fts5yypParser->fts5yytos->stateno; -#ifndef NDEBUG - if( fts5yyTraceFILE ){ - if( fts5yyact < fts5YY_MIN_REDUCE ){ - fprintf(fts5yyTraceFILE,"%sInput '%s' in state %d\n", - fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact); - }else{ - fprintf(fts5yyTraceFILE,"%sInput '%s' with pending reduce %d\n", - fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact-fts5YY_MIN_REDUCE); - } - } -#endif - - while(1){ /* Exit by "break" */ - assert( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystack ); - assert( fts5yyact==fts5yypParser->fts5yytos->stateno ); - fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact); - if( fts5yyact >= fts5YY_MIN_REDUCE ){ - unsigned int fts5yyruleno = fts5yyact - fts5YY_MIN_REDUCE; /* Reduce by this rule */ -#ifndef NDEBUG - assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ); - if( fts5yyTraceFILE ){ - int fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno]; - if( fts5yysize ){ - fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", - fts5yyTracePrompt, - fts5yyruleno, fts5yyRuleName[fts5yyruleno], - fts5yyrulenofts5yytos[fts5yysize].stateno); - }else{ - fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n", - fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno], - fts5yyrulenofts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){ - fts5yypParser->fts5yyhwm++; - assert( fts5yypParser->fts5yyhwm == - (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)); - } -#endif - if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ - if( fts5yyGrowStack(fts5yypParser) ){ - fts5yyStackOverflow(fts5yypParser); - break; - } - } - } - fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyruleno,fts5yymajor,fts5yyminor sqlite3Fts5ParserCTX_PARAM); - }else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ - fts5yy_shift(fts5yypParser,fts5yyact,(fts5YYCODETYPE)fts5yymajor,fts5yyminor); + sqlite3Fts5ParserARG_STORE; + +#ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sInput '%s'\n",fts5yyTracePrompt,fts5yyTokenName[fts5yymajor]); + } +#endif + + do{ + fts5yyact = fts5yy_find_shift_action(fts5yypParser,(fts5YYCODETYPE)fts5yymajor); + if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ + fts5yy_shift(fts5yypParser,fts5yyact,fts5yymajor,fts5yyminor); #ifndef fts5YYNOERRORRECOVERY fts5yypParser->fts5yyerrcnt--; #endif - break; - }else if( fts5yyact==fts5YY_ACCEPT_ACTION ){ - fts5yypParser->fts5yytos--; - fts5yy_accept(fts5yypParser); - return; + fts5yymajor = fts5YYNOCODE; + }else if( fts5yyact <= fts5YY_MAX_REDUCE ){ + fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE); }else{ assert( fts5yyact == fts5YY_ERROR_ACTION ); fts5yyminorunion.fts5yy0 = fts5yyminor; #ifdef fts5YYERRORSYMBOL int fts5yymx; @@ -236440,11 +185569,11 @@ } #endif #ifdef fts5YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". + ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** ** * Call the %syntax_error function. ** @@ -236471,17 +185600,19 @@ } #endif fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion); fts5yymajor = fts5YYNOCODE; }else{ - while( fts5yypParser->fts5yytos > fts5yypParser->fts5yystack ){ - fts5yyact = fts5yy_find_reduce_action(fts5yypParser->fts5yytos->stateno, - fts5YYERRORSYMBOL); - if( fts5yyact<=fts5YY_MAX_SHIFTREDUCE ) break; + while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack + && fts5yymx != fts5YYERRORSYMBOL + && (fts5yyact = fts5yy_find_reduce_action( + fts5yypParser->fts5yytos->stateno, + fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE + ){ fts5yy_pop_parser_stack(fts5yypParser); } - if( fts5yypParser->fts5yytos <= fts5yypParser->fts5yystack || fts5yymajor==0 ){ + if( fts5yypParser->fts5yytos < fts5yypParser->fts5yystack || fts5yymajor==0 ){ fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); fts5yy_parse_failed(fts5yypParser); #ifndef fts5YYNOERRORRECOVERY fts5yypParser->fts5yyerrcnt = -1; #endif @@ -236490,12 +185621,10 @@ fts5yy_shift(fts5yypParser,fts5yyact,fts5YYERRORSYMBOL,fts5yyminor); } } fts5yypParser->fts5yyerrcnt = 3; fts5yyerrorhit = 1; - if( fts5yymajor==fts5YYNOCODE ) break; - fts5yyact = fts5yypParser->fts5yytos->stateno; #elif defined(fts5YYNOERRORRECOVERY) /* If the fts5YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax ** error routine and continue going as if nothing had happened. ** @@ -236502,11 +185631,12 @@ ** Applications can set this macro (for example inside %include) if ** they intend to abandon the parse upon the first syntax error seen. */ fts5yy_syntax_error(fts5yypParser,fts5yymajor, fts5yyminor); fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); - break; + fts5yymajor = fts5YYNOCODE; + #else /* fts5YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** ** * Report an error message, and throw away the input token. ** @@ -236524,14 +185654,14 @@ fts5yy_parse_failed(fts5yypParser); #ifndef fts5YYNOERRORRECOVERY fts5yypParser->fts5yyerrcnt = -1; #endif } - break; + fts5yymajor = fts5YYNOCODE; #endif } - } + }while( fts5yymajor!=fts5YYNOCODE && fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); #ifndef NDEBUG if( fts5yyTraceFILE ){ fts5yyStackEntry *i; char cDiv = '['; fprintf(fts5yyTraceFILE,"%sReturn. Stack=",fts5yyTracePrompt); @@ -236543,24 +185673,10 @@ } #endif return; } -/* -** Return the fallback token corresponding to canonical token iToken, or -** 0 if iToken has no fallback. -*/ -static int sqlite3Fts5ParserFallback(int iToken){ -#ifdef fts5YYFALLBACK - assert( iToken<(int)(sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])) ); - return fts5yyFallback[iToken]; -#else - (void)iToken; - return 0; -#endif -} - /* ** 2014 May 31 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -236575,11 +185691,11 @@ /* #include "fts5Int.h" */ #include /* amalgamator: keep */ /* -** Object used to iterate through all "coalesced phrase instances" in +** Object used to iterate through all "coalesced phrase instances" in ** a single column of the current row. If the phrase instances in the ** column being considered do not overlap, this object simply iterates ** through them. Or, if they do overlap (share one or more tokens in ** common), each set of overlapping instances is treated as a single ** match. See documentation for the highlight() auxiliary function for @@ -236638,11 +185754,11 @@ return rc; } /* -** Initialize the iterator object indicated by the final parameter to +** Initialize the iterator object indicated by the final parameter to ** iterate through coalesced phrase instances in column iCol. */ static int fts5CInstIterInit( const Fts5ExtensionApi *pApi, Fts5Context *pFts, @@ -236669,41 +185785,37 @@ /************************************************************************* ** Start of highlight() implementation. */ typedef struct HighlightContext HighlightContext; struct HighlightContext { - /* Constant parameters to fts5HighlightCb() */ + CInstIter iter; /* Coalesced Instance Iterator */ + int iPos; /* Current token offset in zIn[] */ int iRangeStart; /* First token to include */ int iRangeEnd; /* If non-zero, last token to include */ const char *zOpen; /* Opening highlight */ const char *zClose; /* Closing highlight */ const char *zIn; /* Input text */ int nIn; /* Size of input text in bytes */ - - /* Variables modified by fts5HighlightCb() */ - CInstIter iter; /* Coalesced Instance Iterator */ - int iPos; /* Current token offset in zIn[] */ - int iOff; /* Have copied up to this offset in zIn[] */ - int bOpen; /* True if highlight is open */ + int iOff; /* Current offset within zIn[] */ char *zOut; /* Output value */ }; /* ** Append text to the HighlightContext output string - p->zOut. Argument -** z points to a buffer containing n bytes of text to append. If n is +** z points to a buffer containing n bytes of text to append. If n is ** negative, everything up until the first '\0' is appended to the output. ** -** If *pRc is set to any value other than SQLITE_OK when this function is -** called, it is a no-op. If an error (i.e. an OOM condition) is encountered, -** *pRc is set to an error code before returning. +** If *pRc is set to any value other than SQLITE_OK when this function is +** called, it is a no-op. If an error (i.e. an OOM condition) is encountered, +** *pRc is set to an error code before returning. */ static void fts5HighlightAppend( - int *pRc, - HighlightContext *p, + int *pRc, + HighlightContext *p, const char *z, int n ){ - if( *pRc==SQLITE_OK && z ){ + if( *pRc==SQLITE_OK ){ if( n<0 ) n = (int)strlen(z); p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z); if( p->zOut==0 ) *pRc = SQLITE_NOMEM; } } @@ -236714,12 +185826,12 @@ static int fts5HighlightCb( void *pContext, /* Pointer to HighlightContext object */ int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Buffer containing token */ int nToken, /* Size of token in bytes */ - int iStartOff, /* Start byte offset of token */ - int iEndOff /* End byte offset of token */ + int iStartOff, /* Start offset of token */ + int iEndOff /* End offset of token */ ){ HighlightContext *p = (HighlightContext*)pContext; int rc = SQLITE_OK; int iPos; @@ -236726,69 +185838,43 @@ UNUSED_PARAM2(pToken, nToken); if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK; iPos = p->iPos++; - if( p->iRangeEnd>=0 ){ + if( p->iRangeEnd>0 ){ if( iPosiRangeStart || iPos>p->iRangeEnd ) return SQLITE_OK; if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; } - /* If the parenthesis is open, and this token is not part of the current - ** phrase, and the starting byte offset of this token is past the point - ** that has currently been copied into the output buffer, close the - ** parenthesis. */ - if( p->bOpen - && (iPos<=p->iter.iStart || p->iter.iStart<0) - && iStartOff>p->iOff - ){ - fts5HighlightAppend(&rc, p, p->zClose, -1); - p->bOpen = 0; - } - - /* If this is the start of a new phrase, and the highlight is not open: - ** - ** * copy text from the input up to the start of the phrase, and - ** * open the highlight. - */ - if( iPos==p->iter.iStart && p->bOpen==0 ){ + if( iPos==p->iter.iStart ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff); fts5HighlightAppend(&rc, p, p->zOpen, -1); p->iOff = iStartOff; - p->bOpen = 1; } if( iPos==p->iter.iEnd ){ - if( p->bOpen==0 ){ - assert( p->iRangeEnd>=0 ); + if( p->iRangeEnd && p->iter.iStartiRangeStart ){ fts5HighlightAppend(&rc, p, p->zOpen, -1); - p->bOpen = 1; } fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + fts5HighlightAppend(&rc, p, p->zClose, -1); p->iOff = iEndOff; - if( rc==SQLITE_OK ){ rc = fts5CInstIterNext(&p->iter); } } - if( iPos==p->iRangeEnd ){ - if( p->bOpen ){ - if( p->iter.iStart>=0 && iPos>=p->iter.iStart ){ - fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); - p->iOff = iEndOff; - } - fts5HighlightAppend(&rc, p, p->zClose, -1); - p->bOpen = 0; - } - fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); - p->iOff = iEndOff; - } - - return rc; -} - + if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){ + fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + p->iOff = iEndOff; + if( iPos>=p->iter.iStart && iPositer.iEnd ){ + fts5HighlightAppend(&rc, p, p->zClose, -1); + } + } + + return rc; +} /* ** Implementation of highlight() function. */ static void fts5HighlightFunction( @@ -236810,32 +185896,19 @@ iCol = sqlite3_value_int(apVal[0]); memset(&ctx, 0, sizeof(HighlightContext)); ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); - ctx.iRangeEnd = -1; rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn); - if( rc==SQLITE_RANGE ){ - sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); - rc = SQLITE_OK; - }else if( ctx.zIn ){ - const char *pLoc = 0; /* Locale of column iCol */ - int nLoc = 0; /* Size of pLoc in bytes */ + + if( ctx.zIn ){ if( rc==SQLITE_OK ){ rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter); } if( rc==SQLITE_OK ){ - rc = pApi->xColumnLocale(pFts, iCol, &pLoc, &nLoc); - } - if( rc==SQLITE_OK ){ - rc = pApi->xTokenize_v2( - pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx, fts5HighlightCb - ); - } - if( ctx.bOpen ){ - fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); + rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); if( rc==SQLITE_OK ){ sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); @@ -236870,11 +185943,11 @@ static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){ if( p->nFirstAlloc==p->nFirst ){ int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64; int *aNew; - aNew = (int*)sqlite3_realloc64(p->aFirst, nNew*sizeof(int)); + aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int)); if( aNew==0 ) return SQLITE_NOMEM; p->aFirst = aNew; p->nFirstAlloc = nNew; } p->aFirst[p->nFirst++] = iAdd; @@ -236937,44 +186010,33 @@ int iOff = 0; int iFirst = -1; int nInst; int nScore = 0; int iLast = 0; - sqlite3_int64 iEnd = (sqlite3_int64)iPos + nToken; rc = pApi->xInstCount(pFts, &nInst); for(i=0; ixInst(pFts, i, &ip, &ic, &iOff); - if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff=iPos && iOff<(iPos+nToken) ){ nScore += (aSeen[ip] ? 1 : 1000); aSeen[ip] = 1; if( iFirst<0 ) iFirst = iOff; iLast = iOff + pApi->xPhraseSize(pFts, ip); } } *pnScore = nScore; if( piPos ){ - sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2; + int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2; if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken; if( iAdj<0 ) iAdj = 0; - *piPos = (int)iAdj; + *piPos = iAdj; } return rc; } -/* -** Return the value in pVal interpreted as utf-8 text. Except, if pVal -** contains a NULL value, return a pointer to a static string zero -** bytes in length instead of a NULL pointer. -*/ -static const char *fts5ValueToText(sqlite3_value *pVal){ - const char *zRet = (const char*)sqlite3_value_text(pVal); - return zRet ? zRet : ""; -} - /* ** Implementation of snippet() function. */ static void fts5SnippetFunction( const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ @@ -237006,14 +186068,13 @@ } nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); - ctx.zOpen = fts5ValueToText(apVal[1]); - ctx.zClose = fts5ValueToText(apVal[2]); - ctx.iRangeEnd = -1; - zEllips = fts5ValueToText(apVal[3]); + ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); + ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); + zEllips = (const char*)sqlite3_value_text(apVal[3]); nToken = sqlite3_value_int(apVal[4]); iBestCol = (iCol>=0 ? iCol : 0); nPhrase = pApi->xPhraseCount(pFts); aSeen = sqlite3_malloc(nPhrase); @@ -237025,23 +186086,19 @@ } memset(&sFinder, 0, sizeof(Fts5SFinder)); for(i=0; ixColumnText(pFts, i, &sFinder.zDoc, &nDoc); if( rc!=SQLITE_OK ) break; - rc = pApi->xColumnLocale(pFts, i, &pLoc, &nLoc); - if( rc!=SQLITE_OK ) break; - rc = pApi->xTokenize_v2(pFts, - sFinder.zDoc, nDoc, pLoc, nLoc, (void*)&sFinder, fts5SentenceFinderCb + rc = pApi->xTokenize(pFts, + sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb ); if( rc!=SQLITE_OK ) break; rc = pApi->xColumnSize(pFts, i, &nDocsize); if( rc!=SQLITE_OK ) break; @@ -237050,13 +186107,11 @@ int iAdj; int nScore; int jj; rc = pApi->xInst(pFts, ii, &ip, &ic, &io); - if( ic!=i ) continue; - if( io>nDocsize ) rc = FTS5_CORRUPT; - if( rc!=SQLITE_OK ) continue; + if( ic!=i || rc!=SQLITE_OK ) continue; memset(aSeen, 0, nPhrase); rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, io, nToken, &nScore, &iAdj ); if( rc==SQLITE_OK && nScore>nBestScore ){ @@ -237071,11 +186126,11 @@ if( sFinder.aFirst[jj+1]>io ) break; } if( sFinder.aFirst[jj]nBestScore ){ @@ -237095,13 +186150,10 @@ } if( rc==SQLITE_OK && nColSize==0 ){ rc = pApi->xColumnSize(pFts, iBestCol, &nColSize); } if( ctx.zIn ){ - const char *pLoc = 0; /* Locale of column iBestCol */ - int nLoc = 0; /* Bytes in pLoc */ - if( rc==SQLITE_OK ){ rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter); } ctx.iRangeStart = iBestStart; @@ -237116,19 +186168,11 @@ while( ctx.iter.iStart>=0 && ctx.iter.iStartxColumnLocale(pFts, iBestCol, &pLoc, &nLoc); - } - if( rc==SQLITE_OK ){ - rc = pApi->xTokenize_v2( - pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx,fts5HighlightCb - ); - } - if( ctx.bOpen ){ - fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); + rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } if( ctx.iRangeEnd>=(nColSize-1) ){ fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); }else{ fts5HighlightAppend(&rc, &ctx, zEllips, -1); @@ -237161,11 +186205,11 @@ /* ** Callback used by fts5Bm25GetData() to count the number of rows in the ** table matched by each individual phrase within the query. */ static int fts5CountCb( - const Fts5ExtensionApi *pApi, + const Fts5ExtensionApi *pApi, Fts5Context *pFts, void *pUserData /* Pointer to sqlite3_int64 variable */ ){ sqlite3_int64 *pn = (sqlite3_int64*)pUserData; UNUSED_PARAM2(pApi, pFts); @@ -237172,46 +186216,45 @@ (*pn)++; return SQLITE_OK; } /* -** Set *ppData to point to the Fts5Bm25Data object for the current query. +** Set *ppData to point to the Fts5Bm25Data object for the current query. ** If the object has not already been allocated, allocate and populate it ** now. */ static int fts5Bm25GetData( - const Fts5ExtensionApi *pApi, + const Fts5ExtensionApi *pApi, Fts5Context *pFts, Fts5Bm25Data **ppData /* OUT: bm25-data object for this query */ ){ int rc = SQLITE_OK; /* Return code */ Fts5Bm25Data *p; /* Object to return */ - p = (Fts5Bm25Data*)pApi->xGetAuxdata(pFts, 0); + p = pApi->xGetAuxdata(pFts, 0); if( p==0 ){ int nPhrase; /* Number of phrases in query */ sqlite3_int64 nRow = 0; /* Number of rows in table */ sqlite3_int64 nToken = 0; /* Number of tokens in table */ - sqlite3_int64 nByte; /* Bytes of space to allocate */ + int nByte; /* Bytes of space to allocate */ int i; /* Allocate the Fts5Bm25Data object */ nPhrase = pApi->xPhraseCount(pFts); nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double); - p = (Fts5Bm25Data*)sqlite3_malloc64(nByte); + p = (Fts5Bm25Data*)sqlite3_malloc(nByte); if( p==0 ){ rc = SQLITE_NOMEM; }else{ - memset(p, 0, (size_t)nByte); + memset(p, 0, nByte); p->nPhrase = nPhrase; p->aIDF = (double*)&p[1]; p->aFreq = &p->aIDF[nPhrase]; } /* Calculate the average document length for this FTS5 table */ if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow); - assert( rc!=SQLITE_OK || nRow>0 ); if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken); if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow; /* Calculate an IDF for each phrase in the query */ for(i=0; rc==SQLITE_OK && ixColumnSize(pFts, -1, &nTok); D = (double)nTok; } - /* Determine and return the BM25 score for the current row. Or, if an - ** error has occurred, throw an exception. */ + /* Determine the BM25 score for the current row. */ + for(i=0; rc==SQLITE_OK && inPhrase; i++){ + score += pData->aIDF[i] * ( + ( aFreq[i] * (k1 + 1.0) ) / + ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) ) + ); + } + + /* If no error has occurred, return the calculated score. Otherwise, + ** throw an SQL exception. */ if( rc==SQLITE_OK ){ - for(i=0; inPhrase; i++){ - score += pData->aIDF[i] * ( - ( aFreq[i] * (k1 + 1.0) ) / - ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) ) - ); - } sqlite3_result_double(pCtx, -1.0 * score); }else{ sqlite3_result_error_code(pCtx, rc); } } -/* -** Implementation of fts5_get_locale() function. -*/ -static void fts5GetLocaleFunction( - const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ - Fts5Context *pFts, /* First arg to pass to pApi functions */ - sqlite3_context *pCtx, /* Context for returning result/error */ - int nVal, /* Number of values in apVal[] array */ - sqlite3_value **apVal /* Array of trailing arguments */ -){ - int iCol = 0; - int eType = 0; - int rc = SQLITE_OK; - const char *zLocale = 0; - int nLocale = 0; - - /* xColumnLocale() must be available */ - assert( pApi->iVersion>=4 ); - - if( nVal!=1 ){ - const char *z = "wrong number of arguments to function fts5_get_locale()"; - sqlite3_result_error(pCtx, z, -1); - return; - } - - eType = sqlite3_value_numeric_type(apVal[0]); - if( eType!=SQLITE_INTEGER ){ - const char *z = "non-integer argument passed to function fts5_get_locale()"; - sqlite3_result_error(pCtx, z, -1); - return; - } - - iCol = sqlite3_value_int(apVal[0]); - if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){ - sqlite3_result_error_code(pCtx, SQLITE_RANGE); - return; - } - - rc = pApi->xColumnLocale(pFts, iCol, &zLocale, &nLocale); - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - return; - } - - sqlite3_result_text(pCtx, zLocale, nLocale, SQLITE_TRANSIENT); -} - static int sqlite3Fts5AuxInit(fts5_api *pApi){ struct Builtin { const char *zFunc; /* Function name (nul-terminated) */ void *pUserData; /* User-data pointer */ fts5_extension_function xFunc;/* Callback function */ void (*xDestroy)(void*); /* Destructor function */ } aBuiltin [] = { - { "snippet", 0, fts5SnippetFunction, 0 }, - { "highlight", 0, fts5HighlightFunction, 0 }, - { "bm25", 0, fts5Bm25Function, 0 }, - { "fts5_get_locale", 0, fts5GetLocaleFunction, 0 }, + { "snippet", 0, fts5SnippetFunction, 0 }, + { "highlight", 0, fts5HighlightFunction, 0 }, + { "bm25", 0, fts5Bm25Function, 0 }, }; int rc = SQLITE_OK; /* Return code */ int i; /* To iterate through builtin functions */ for(i=0; rc==SQLITE_OK && inSpacenSpace ? pBuf->nSpace : 64; + u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64; u8 *pNew; while( nNewp, nNew); + pNew = sqlite3_realloc(pBuf->p, nNew); if( pNew==0 ){ *pRc = SQLITE_NOMEM; return 1; }else{ - pBuf->nSpace = (int)nNew; + pBuf->nSpace = nNew; pBuf->p = pNew; } } return 0; } @@ -237433,40 +186432,40 @@ aBuf[2] = (iVal>> 8) & 0x00FF; aBuf[3] = (iVal>> 0) & 0x00FF; } static int sqlite3Fts5Get32(const u8 *aBuf){ - return (int)((((u32)aBuf[0])<<24) + (aBuf[1]<<16) + (aBuf[2]<<8) + aBuf[3]); + return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3]; } /* -** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set +** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set ** the error code in p. If an error has already occurred when this function ** is called, it is a no-op. */ static void sqlite3Fts5BufferAppendBlob( int *pRc, - Fts5Buffer *pBuf, - u32 nData, + Fts5Buffer *pBuf, + u32 nData, const u8 *pData ){ + assert_nc( *pRc || nData>=0 ); if( nData ){ if( fts5BufferGrow(pRc, pBuf, nData) ) return; - assert( pBuf->p!=0 ); memcpy(&pBuf->p[pBuf->n], pData, nData); pBuf->n += nData; } } /* ** Append the nul-terminated string zStr to the buffer pBuf. This function -** ensures that the byte following the buffer data is set to 0x00, even +** ensures that the byte following the buffer data is set to 0x00, even ** though this byte is not included in the pBuf->n count. */ static void sqlite3Fts5BufferAppendString( int *pRc, - Fts5Buffer *pBuf, + Fts5Buffer *pBuf, const char *zStr ){ int nStr = (int)strlen(zStr); sqlite3Fts5BufferAppendBlob(pRc, pBuf, nStr+1, (const u8*)zStr); pBuf->n--; @@ -237474,17 +186473,17 @@ /* ** Argument zFmt is a printf() style format string. This function performs ** the printf() style processing, then appends the results to buffer pBuf. ** -** Like sqlite3Fts5BufferAppendString(), this function ensures that the byte +** Like sqlite3Fts5BufferAppendString(), this function ensures that the byte ** following the buffer data is set to 0x00, even though this byte is not ** included in the pBuf->n count. -*/ +*/ static void sqlite3Fts5BufferAppendPrintf( int *pRc, - Fts5Buffer *pBuf, + Fts5Buffer *pBuf, char *zFmt, ... ){ if( *pRc==SQLITE_OK ){ char *zTmp; va_list ap; @@ -237507,16 +186506,16 @@ va_list ap; va_start(ap, zFmt); zRet = sqlite3_vmprintf(zFmt, ap); va_end(ap); if( zRet==0 ){ - *pRc = SQLITE_NOMEM; + *pRc = SQLITE_NOMEM; } } return zRet; } - + /* ** Free any buffer allocated by pBuf. Zero the structure before returning. */ static void sqlite3Fts5BufferFree(Fts5Buffer *pBuf){ @@ -237523,11 +186522,11 @@ sqlite3_free(pBuf->p); memset(pBuf, 0, sizeof(Fts5Buffer)); } /* -** Zero the contents of the buffer object. But do not free the associated +** Zero the contents of the buffer object. But do not free the associated ** memory allocation. */ static void sqlite3Fts5BufferZero(Fts5Buffer *pBuf){ pBuf->n = 0; } @@ -237537,12 +186536,12 @@ ** the error code in p. If an error has already occurred when this function ** is called, it is a no-op. */ static void sqlite3Fts5BufferSet( int *pRc, - Fts5Buffer *pBuf, - int nData, + Fts5Buffer *pBuf, + int nData, const u8 *pData ){ pBuf->n = 0; sqlite3Fts5BufferAppendBlob(pRc, pBuf, nData, pData); } @@ -237551,40 +186550,25 @@ const u8 *a, int n, /* Buffer containing poslist */ int *pi, /* IN/OUT: Offset within a[] */ i64 *piOff /* IN/OUT: Current offset */ ){ int i = *pi; - assert( a!=0 || i==0 ); if( i>=n ){ /* EOF */ *piOff = -1; - return 1; + return 1; }else{ i64 iOff = *piOff; - u32 iVal; - assert( a!=0 ); + int iVal; fts5FastGetVarint32(a, i, iVal); - if( iVal<=1 ){ - if( iVal==0 ){ - *pi = i; - return 0; - } + if( iVal==1 ){ fts5FastGetVarint32(a, i, iVal); iOff = ((i64)iVal) << 32; - assert( iOff>=0 ); fts5FastGetVarint32(a, i, iVal); - if( iVal<2 ){ - /* This is a corrupt record. So stop parsing it here. */ - *piOff = -1; - return 1; - } - *piOff = iOff + ((iVal-2) & 0x7FFFFFFF); - }else{ - *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF); - } - *pi = i; - assert_nc( *piOff>=iOff ); + } + *piOff = iOff + (iVal-2); + *pi = i; return 0; } } @@ -237615,45 +186599,43 @@ ** pBuf, which must be already be large enough to hold the new data. ** The previous position written to this list is *piPrev. *piPrev is set ** to iPos before returning. */ static void sqlite3Fts5PoslistSafeAppend( - Fts5Buffer *pBuf, - i64 *piPrev, + Fts5Buffer *pBuf, + i64 *piPrev, i64 iPos ){ - if( iPos>=*piPrev ){ - static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; - if( (iPos & colmask) != (*piPrev & colmask) ){ - pBuf->p[pBuf->n++] = 1; - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); - *piPrev = (iPos & colmask); - } - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); - *piPrev = iPos; - } + static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; + if( (iPos & colmask) != (*piPrev & colmask) ){ + pBuf->p[pBuf->n++] = 1; + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); + *piPrev = (iPos & colmask); + } + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); + *piPrev = iPos; } static int sqlite3Fts5PoslistWriterAppend( - Fts5Buffer *pBuf, + Fts5Buffer *pBuf, Fts5PoslistWriter *pWriter, i64 iPos ){ int rc = 0; /* Initialized only to suppress erroneous warning from Clang */ if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); return SQLITE_OK; } -static void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){ +static void *sqlite3Fts5MallocZero(int *pRc, int nByte){ void *pRet = 0; if( *pRc==SQLITE_OK ){ - pRet = sqlite3_malloc64(nByte); + pRet = sqlite3_malloc(nByte); if( pRet==0 ){ if( nByte>0 ) *pRc = SQLITE_NOMEM; }else{ - memset(pRet, 0, (size_t)nByte); + memset(pRet, 0, nByte); } } return pRet; } @@ -237661,11 +186643,11 @@ ** Return a nul-terminated copy of the string indicated by pIn. If nIn ** is non-negative, then it is the length of the string in bytes. Otherwise, ** the length of the string is determined using strlen(). ** ** It is the responsibility of the caller to eventually free the returned -** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned. +** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned. */ static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){ char *zRet = 0; if( *pRc==SQLITE_OK ){ if( nIn<0 ){ @@ -237728,13 +186710,13 @@ *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset)); return rc; } static int sqlite3Fts5TermsetAdd( - Fts5Termset *p, + Fts5Termset *p, int iIdx, - const char *pTerm, int nTerm, + const char *pTerm, int nTerm, int *pbPresent ){ int rc = SQLITE_OK; *pbPresent = 0; if( p ){ @@ -237751,13 +186733,13 @@ } hash = (hash << 3) ^ hash ^ iIdx; hash = hash % ArraySize(p->apHash); for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){ - if( pEntry->iIdx==iIdx - && pEntry->nTerm==nTerm - && memcmp(pEntry->pTerm, pTerm, nTerm)==0 + if( pEntry->iIdx==iIdx + && pEntry->nTerm==nTerm + && memcmp(pEntry->pTerm, pTerm, nTerm)==0 ){ *pbPresent = 1; break; } } @@ -237815,14 +186797,12 @@ #define FTS5_DEFAULT_AUTOMERGE 4 #define FTS5_DEFAULT_USERMERGE 4 #define FTS5_DEFAULT_CRISISMERGE 16 #define FTS5_DEFAULT_HASHSIZE (1024*1024) -#define FTS5_DEFAULT_DELETE_AUTOMERGE 10 /* default 10% */ - /* Maximum allowed page size */ -#define FTS5_MAX_PAGE_SIZE (64*1024) +#define FTS5_MAX_PAGE_SIZE (128*1024) static int fts5_iswhitespace(char x){ return (x==' '); } @@ -237829,12 +186809,12 @@ static int fts5_isopenquote(char x){ return (x=='"' || x=='\'' || x=='[' || x=='`'); } /* -** Argument pIn points to a character that is part of a nul-terminated -** string. Return a pointer to the first character following *pIn in +** Argument pIn points to a character that is part of a nul-terminated +** string. Return a pointer to the first character following *pIn in ** the string that is not a white-space character. */ static const char *fts5ConfigSkipWhitespace(const char *pIn){ const char *p = pIn; if( p ){ @@ -237842,12 +186822,12 @@ } return p; } /* -** Argument pIn points to a character that is part of a nul-terminated -** string. Return a pointer to the first character following *pIn in +** Argument pIn points to a character that is part of a nul-terminated +** string. Return a pointer to the first character following *pIn in ** the string that is not a "bareword" character. */ static const char *fts5ConfigSkipBareword(const char *pIn){ const char *p = pIn; while ( sqlite3Fts5IsBareword(*p) ) p++; @@ -237874,13 +186854,13 @@ case 'x': case 'X': p++; if( *p=='\'' ){ p++; - while( (*p>='a' && *p<='f') - || (*p>='A' && *p<='F') - || (*p>='0' && *p<='9') + while( (*p>='a' && *p<='f') + || (*p>='A' && *p<='F') + || (*p>='0' && *p<='9') ){ p++; } if( *p=='\'' && 0==((p-pIn)%2) ){ p++; @@ -237907,11 +186887,11 @@ default: /* maybe a number */ if( *p=='+' || *p=='-' ) p++; while( fts5_isdigit(*p) ) p++; - /* At this point, if the literal was an integer, the parse is + /* At this point, if the literal was an integer, the parse is ** finished. Or, if it is a floating point value, it may continue ** with either a decimal point or an 'E' character. */ if( *p=='.' && fts5_isdigit(p[1]) ){ p += 2; while( fts5_isdigit(*p) ) p++; @@ -237931,12 +186911,12 @@ ** This function searches for the corresponding close-quote character within ** the string and, if found, dequotes the string in place and adds a new ** nul-terminator byte. ** ** If the close-quote is found, the value returned is the byte offset of -** the character immediately following it. Or, if the close-quote is not -** found, -1 is returned. If -1 is returned, the buffer is left in an +** the character immediately following it. Or, if the close-quote is not +** found, -1 is returned. If -1 is returned, the buffer is left in an ** undefined state. */ static int fts5Dequote(char *z){ char q; int iIn = 1; @@ -237943,21 +186923,21 @@ int iOut = 0; q = z[0]; /* Set stack variable q to the close-quote character */ assert( q=='[' || q=='\'' || q=='"' || q=='`' ); - if( q=='[' ) q = ']'; + if( q=='[' ) q = ']'; - while( z[iIn] ){ + while( ALWAYS(z[iIn]) ){ if( z[iIn]==q ){ if( z[iIn+1]!=q ){ /* Character iIn was the close quote. */ iIn++; break; }else{ /* Character iIn and iIn+1 form an escaped quote character. Skip - ** the input cursor past both and copy a single quote character + ** the input cursor past both and copy a single quote character ** to the output buffer. */ iIn += 2; z[iOut++] = q; } }else{ @@ -237998,12 +186978,12 @@ int eVal; }; typedef struct Fts5Enum Fts5Enum; static int fts5ConfigSetEnum( - const Fts5Enum *aEnum, - const char *zEnum, + const Fts5Enum *aEnum, + const char *zEnum, int *peVal ){ int nEnum = (int)strlen(zEnum); int i; int iVal = -1; @@ -238027,18 +187007,18 @@ ** an error occurs, an SQLite error code is returned and an error message ** may be left in *pzErr. It is the responsibility of the caller to ** eventually free any such error message using sqlite3_free(). */ static int fts5ConfigParseSpecial( + Fts5Global *pGlobal, Fts5Config *pConfig, /* Configuration object to update */ const char *zCmd, /* Special command to parse */ const char *zArg, /* Argument to parse */ char **pzErr /* OUT: Error message */ ){ int rc = SQLITE_OK; int nCmd = (int)strlen(zCmd); - if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){ const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES; const char *p; int bFirst = 1; if( pConfig->aPrefix==0 ){ @@ -238090,16 +187070,17 @@ return rc; } if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){ const char *p = (const char*)zArg; - sqlite3_int64 nArg = strlen(zArg) + 1; - char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg); + int nArg = (int)strlen(zArg) + 1; + char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg); + char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2); + char *pSpace = pDel; - if( azArg ){ - char *pSpace = (char*)&azArg[nArg]; - if( pConfig->t.azArg ){ + if( azArg && pSpace ){ + if( pConfig->pTok ){ *pzErr = sqlite3_mprintf("multiple tokenize=... directives"); rc = SQLITE_ERROR; }else{ for(nArg=0; p && *p; nArg++){ const char *p2 = fts5ConfigSkipWhitespace(p); @@ -238118,18 +187099,20 @@ } if( p==0 ){ *pzErr = sqlite3_mprintf("parse error in tokenize directive"); rc = SQLITE_ERROR; }else{ - pConfig->t.azArg = (const char**)azArg; - pConfig->t.nArg = nArg; - azArg = 0; + rc = sqlite3Fts5GetTokenizer(pGlobal, + (const char**)azArg, nArg, &pConfig->pTok, &pConfig->pTokApi, + pzErr + ); } } } + sqlite3_free(azArg); - + sqlite3_free(pDel); return rc; } if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){ if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){ @@ -238141,30 +187124,10 @@ pConfig->zContent = sqlite3Fts5Mprintf(&rc, "%Q.%Q", pConfig->zDb,zArg); }else{ pConfig->eContent = FTS5_CONTENT_NONE; } } - return rc; - } - - if( sqlite3_strnicmp("contentless_delete", zCmd, nCmd)==0 ){ - if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ - *pzErr = sqlite3_mprintf("malformed contentless_delete=... directive"); - rc = SQLITE_ERROR; - }else{ - pConfig->bContentlessDelete = (zArg[0]=='1'); - } - return rc; - } - - if( sqlite3_strnicmp("contentless_unindexed", zCmd, nCmd)==0 ){ - if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ - *pzErr = sqlite3_mprintf("malformed contentless_delete=... directive"); - rc = SQLITE_ERROR; - }else{ - pConfig->bContentlessUnindexed = (zArg[0]=='1'); - } return rc; } if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){ if( pConfig->zContentRowid ){ @@ -238184,20 +187147,10 @@ pConfig->bColumnsize = (zArg[0]=='1'); } return rc; } - if( sqlite3_strnicmp("locale", zCmd, nCmd)==0 ){ - if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ - *pzErr = sqlite3_mprintf("malformed locale=... directive"); - rc = SQLITE_ERROR; - }else{ - pConfig->bLocale = (zArg[0]=='1'); - } - return rc; - } - if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){ const Fts5Enum aDetail[] = { { "none", FTS5_DETAIL_NONE }, { "full", FTS5_DETAIL_FULL }, { "columns", FTS5_DETAIL_COLUMNS }, @@ -238208,23 +187161,25 @@ *pzErr = sqlite3_mprintf("malformed detail=... directive"); } return rc; } - if( sqlite3_strnicmp("tokendata", zCmd, nCmd)==0 ){ - if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ - *pzErr = sqlite3_mprintf("malformed tokendata=... directive"); - rc = SQLITE_ERROR; - }else{ - pConfig->bTokendata = (zArg[0]=='1'); - } - return rc; - } - *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd); return SQLITE_ERROR; } + +/* +** Allocate an instance of the default tokenizer ("simple") at +** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error +** code if an error occurs. +*/ +static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){ + assert( pConfig->pTok==0 && pConfig->pTokApi==0 ); + return sqlite3Fts5GetTokenizer( + pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0 + ); +} /* ** Gobble up the first bareword or quoted word from the input buffer zIn. ** Return a pointer to the character immediately following the last in ** the gobbled word if successful, or a NULL pointer otherwise (failed @@ -238245,21 +187200,21 @@ char **pzOut, /* OUT: malloc'd buffer containing str/bw */ int *pbQuoted /* OUT: Set to true if dequoting required */ ){ const char *zRet = 0; - sqlite3_int64 nIn = strlen(zIn); - char *zOut = sqlite3_malloc64(nIn+1); + int nIn = (int)strlen(zIn); + char *zOut = sqlite3_malloc(nIn+1); assert( *pRc==SQLITE_OK ); *pbQuoted = 0; *pzOut = 0; if( zOut==0 ){ *pRc = SQLITE_NOMEM; }else{ - memcpy(zOut, zIn, (size_t)(nIn+1)); + memcpy(zOut, zIn, nIn+1); if( fts5_isopenquote(zOut[0]) ){ int ii = fts5Dequote(zOut); zRet = &zIn[ii]; *pbQuoted = 1; }else{ @@ -238278,26 +187233,24 @@ return zRet; } static int fts5ConfigParseColumn( - Fts5Config *p, - char *zCol, - char *zArg, - char **pzErr, - int *pbUnindexed + Fts5Config *p, + char *zCol, + char *zArg, + char **pzErr ){ int rc = SQLITE_OK; - if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME) - || 0==sqlite3_stricmp(zCol, FTS5_ROWID_NAME) + if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME) + || 0==sqlite3_stricmp(zCol, FTS5_ROWID_NAME) ){ *pzErr = sqlite3_mprintf("reserved fts5 column name: %s", zCol); rc = SQLITE_ERROR; }else if( zArg ){ if( 0==sqlite3_stricmp(zArg, "unindexed") ){ p->abUnindexed[p->nCol] = 1; - *pbUnindexed = 1; }else{ *pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg); rc = SQLITE_ERROR; } } @@ -238314,30 +187267,15 @@ int rc = SQLITE_OK; Fts5Buffer buf = {0, 0, 0}; sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid); if( p->eContent!=FTS5_CONTENT_NONE ){ - assert( p->eContent==FTS5_CONTENT_EXTERNAL - || p->eContent==FTS5_CONTENT_NORMAL - || p->eContent==FTS5_CONTENT_UNINDEXED - ); for(i=0; inCol; i++){ if( p->eContent==FTS5_CONTENT_EXTERNAL ){ sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]); - }else if( p->eContent==FTS5_CONTENT_NORMAL || p->abUnindexed[i] ){ - sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i); - }else{ - sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL"); - } - } - } - if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){ - for(i=0; inCol; i++){ - if( p->abUnindexed[i]==0 ){ - sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.l%d", i); - }else{ - sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL"); + }else{ + sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i); } } } assert( p->zContentExprlist==0 ); @@ -238345,18 +187283,18 @@ return rc; } /* ** Arguments nArg/azArg contain the string arguments passed to the xCreate -** or xConnect method of the virtual table. This function attempts to +** or xConnect method of the virtual table. This function attempts to ** allocate an instance of Fts5Config containing the results of parsing ** those arguments. ** ** If successful, SQLITE_OK is returned and *ppOut is set to point to the -** new Fts5Config object. If an error occurs, an SQLite error code is +** new Fts5Config object. If an error occurs, an SQLite error code is ** returned, *ppOut is set to NULL and an error message may be left in -** *pzErr. It is the responsibility of the caller to eventually free any +** *pzErr. It is the responsibility of the caller to eventually free any ** such error message using sqlite3_free(). */ static int sqlite3Fts5ConfigParse( Fts5Global *pGlobal, sqlite3 *db, @@ -238366,23 +187304,21 @@ char **pzErr /* OUT: Error message */ ){ int rc = SQLITE_OK; /* Return code */ Fts5Config *pRet; /* New object to return */ int i; - sqlite3_int64 nByte; - int bUnindexed = 0; /* True if there are one or more UNINDEXED */ + int nByte; *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config)); if( pRet==0 ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(Fts5Config)); - pRet->pGlobal = pGlobal; pRet->db = db; pRet->iCookie = -1; nByte = nArg * (sizeof(char*) + sizeof(u8)); pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte); - pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0; + pRet->abUnindexed = (u8*)&pRet->azCol[nArg]; pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1); pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1); pRet->bColumnsize = 1; pRet->eDetail = FTS5_DETAIL_FULL; #ifdef SQLITE_DEBUG @@ -238391,11 +187327,10 @@ if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){ *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName); rc = SQLITE_ERROR; } - assert( (pRet->abUnindexed && pRet->azCol) || rc!=SQLITE_OK ); for(i=3; rc==SQLITE_OK && ibContentlessDelete - && pRet->eContent!=FTS5_CONTENT_NONE - ){ - *pzErr = sqlite3_mprintf( - "contentless_delete=1 requires a contentless table" - ); - rc = SQLITE_ERROR; - } - - /* We only allow contentless_delete=1 if columnsize=0 is not present. - ** - ** This restriction may be removed at some point. - */ - if( rc==SQLITE_OK && pRet->bContentlessDelete && pRet->bColumnsize==0 ){ - *pzErr = sqlite3_mprintf( - "contentless_delete=1 is incompatible with columnsize=0" - ); - rc = SQLITE_ERROR; - } - - /* We only allow contentless_unindexed=1 if the table is actually a - ** contentless one. - */ - if( rc==SQLITE_OK - && pRet->bContentlessUnindexed - && pRet->eContent!=FTS5_CONTENT_NONE - ){ - *pzErr = sqlite3_mprintf( - "contentless_unindexed=1 requires a contentless table" - ); - rc = SQLITE_ERROR; + /* If a tokenizer= option was successfully parsed, the tokenizer has + ** already been allocated. Otherwise, allocate an instance of the default + ** tokenizer (unicode61) now. */ + if( rc==SQLITE_OK && pRet->pTok==0 ){ + rc = fts5ConfigDefaultTokenizer(pGlobal, pRet); } /* If no zContent option was specified, fill in the default values. */ if( rc==SQLITE_OK && pRet->zContent==0 ){ const char *zTail = 0; - assert( pRet->eContent==FTS5_CONTENT_NORMAL - || pRet->eContent==FTS5_CONTENT_NONE + assert( pRet->eContent==FTS5_CONTENT_NORMAL + || pRet->eContent==FTS5_CONTENT_NONE ); if( pRet->eContent==FTS5_CONTENT_NORMAL ){ zTail = "content"; - }else if( bUnindexed && pRet->bContentlessUnindexed ){ - pRet->eContent = FTS5_CONTENT_UNINDEXED; - zTail = "content"; }else if( pRet->bColumnsize ){ zTail = "docsize"; } if( zTail ){ @@ -238516,18 +187415,13 @@ ** Free the configuration object passed as the only argument. */ static void sqlite3Fts5ConfigFree(Fts5Config *pConfig){ if( pConfig ){ int i; - if( pConfig->t.pTok ){ - if( pConfig->t.pApi1 ){ - pConfig->t.pApi1->xDelete(pConfig->t.pTok); - }else{ - pConfig->t.pApi2->xDelete(pConfig->t.pTok); - } - } - sqlite3_free((char*)pConfig->t.azArg); + if( pConfig->pTok ){ + pConfig->pTokApi->xDelete(pConfig->pTok); + } sqlite3_free(pConfig->zDb); sqlite3_free(pConfig->zName); for(i=0; inCol; i++){ sqlite3_free(pConfig->azCol[i]); } @@ -238555,20 +187449,20 @@ zSql = sqlite3Fts5Mprintf(&rc, "CREATE TABLE x("); for(i=0; zSql && inCol; i++){ const char *zSep = (i==0?"":", "); zSql = sqlite3Fts5Mprintf(&rc, "%z%s%Q", zSql, zSep, pConfig->azCol[i]); } - zSql = sqlite3Fts5Mprintf(&rc, "%z, %Q HIDDEN, %s HIDDEN)", + zSql = sqlite3Fts5Mprintf(&rc, "%z, %Q HIDDEN, %s HIDDEN)", zSql, pConfig->zName, FTS5_RANK_NAME ); assert( zSql || rc==SQLITE_NOMEM ); if( zSql ){ rc = sqlite3_declare_vtab(pConfig->db, zSql); sqlite3_free(zSql); } - + return rc; } /* ** Tokenize the text passed via the second and third arguments. @@ -238582,11 +187476,11 @@ ** int iStart // Byte offset of start of token within input text ** int iEnd // Byte offset of end of token within input text ** int iPos // Position of token in input (first token is 0) ** ** If the callback returns a non-zero value the tokenization is abandoned -** and no further callbacks are issued. +** and no further callbacks are issued. ** ** This function returns SQLITE_OK if successful or an SQLite error code ** if an error occurs. If the tokenization was abandoned early because ** the callback returned SQLITE_DONE, this is not an error and this function ** still returns SQLITE_OK. Or, if the tokenization was abandoned early @@ -238598,28 +187492,14 @@ int flags, /* FTS5_TOKENIZE_* flags */ const char *pText, int nText, /* Text to tokenize */ void *pCtx, /* Context passed to xToken() */ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ ){ - int rc = SQLITE_OK; - if( pText ){ - if( pConfig->t.pTok==0 ){ - rc = sqlite3Fts5LoadTokenizer(pConfig); - } - if( rc==SQLITE_OK ){ - if( pConfig->t.pApi1 ){ - rc = pConfig->t.pApi1->xTokenize( - pConfig->t.pTok, pCtx, flags, pText, nText, xToken - ); - }else{ - rc = pConfig->t.pApi2->xTokenize(pConfig->t.pTok, pCtx, flags, - pText, nText, pConfig->t.pLocale, pConfig->t.nLocale, xToken - ); - } - } - } - return rc; + if( pText==0 ) return SQLITE_OK; + return pConfig->pTokApi->xTokenize( + pConfig->pTok, pCtx, flags, pText, nText, xToken + ); } /* ** Argument pIn points to the first character in what is expected to be ** a comma-separated list of SQL literals followed by a ')' character. @@ -238626,11 +187506,11 @@ ** If it actually is this, return a pointer to the ')'. Otherwise, return ** NULL to indicate a parse error. */ static const char *fts5ConfigSkipArgs(const char *pIn){ const char *p = pIn; - + while( 1 ){ p = fts5ConfigSkipWhitespace(p); p = fts5ConfigSkipLiteral(p); p = fts5ConfigSkipWhitespace(p); if( p==0 || *p==')' ) break; @@ -238643,11 +187523,11 @@ return p; } /* -** Parameter zIn contains a rank() function specification. The format of +** Parameter zIn contains a rank() function specification. The format of ** this is: ** ** + Bareword (function name) ** + Open parenthesis - "(" ** + Zero or more SQL literals in a comma separated list @@ -238685,11 +187565,11 @@ p = fts5ConfigSkipWhitespace(p); if( *p!='(' ) rc = SQLITE_ERROR; p++; } if( rc==SQLITE_OK ){ - const char *pArgs; + const char *pArgs; p = fts5ConfigSkipWhitespace(p); pArgs = p; if( *p!=')' ){ p = fts5ConfigSkipArgs(p); if( p==0 ){ @@ -238711,12 +187591,12 @@ } return rc; } static int sqlite3Fts5ConfigSetValue( - Fts5Config *pConfig, - const char *zKey, + Fts5Config *pConfig, + const char *zKey, sqlite3_value *pVal, int *pbBadkey ){ int rc = SQLITE_OK; @@ -238723,11 +187603,11 @@ if( 0==sqlite3_stricmp(zKey, "pgsz") ){ int pgsz = 0; if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ pgsz = sqlite3_value_int(pVal); } - if( pgsz<32 || pgsz>FTS5_MAX_PAGE_SIZE ){ + if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){ *pbBadkey = 1; }else{ pConfig->pgsz = pgsz; } } @@ -238776,27 +187656,14 @@ } if( nCrisisMerge<0 ){ *pbBadkey = 1; }else{ if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; - if( nCrisisMerge>=FTS5_MAX_SEGMENT ) nCrisisMerge = FTS5_MAX_SEGMENT-1; pConfig->nCrisisMerge = nCrisisMerge; } } - else if( 0==sqlite3_stricmp(zKey, "deletemerge") ){ - int nVal = -1; - if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ - nVal = sqlite3_value_int(pVal); - }else{ - *pbBadkey = 1; - } - if( nVal<0 ) nVal = FTS5_DEFAULT_DELETE_AUTOMERGE; - if( nVal>100 ) nVal = 0; - pConfig->nDeleteMerge = nVal; - } - else if( 0==sqlite3_stricmp(zKey, "rank") ){ const char *zIn = (const char*)sqlite3_value_text(pVal); char *zRank; char *zRankArgs; rc = sqlite3Fts5ConfigParseRank(zIn, &zRank, &zRankArgs); @@ -238807,35 +187674,10 @@ pConfig->zRankArgs = zRankArgs; }else if( rc==SQLITE_ERROR ){ rc = SQLITE_OK; *pbBadkey = 1; } - } - - else if( 0==sqlite3_stricmp(zKey, "secure-delete") ){ - int bVal = -1; - if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ - bVal = sqlite3_value_int(pVal); - } - if( bVal<0 ){ - *pbBadkey = 1; - }else{ - pConfig->bSecureDelete = (bVal ? 1 : 0); - } - } - - else if( 0==sqlite3_stricmp(zKey, "insttoken") ){ - int bVal = -1; - if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ - bVal = sqlite3_value_int(pVal); - } - if( bVal<0 ){ - *pbBadkey = 1; - }else{ - pConfig->bPrefixInsttoken = (bVal ? 1 : 0); - } - }else{ *pbBadkey = 1; } return rc; } @@ -238854,11 +187696,10 @@ pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE; pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE; pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE; pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE; - pConfig->nDeleteMerge = FTS5_DEFAULT_DELETE_AUTOMERGE; zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName); if( zSql ){ rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p, 0); sqlite3_free(zSql); @@ -238876,52 +187717,27 @@ sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, &bDummy); } } rc = sqlite3_finalize(p); } - - if( rc==SQLITE_OK - && iVersion!=FTS5_CURRENT_VERSION - && iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE - ){ + + if( rc==SQLITE_OK && iVersion!=FTS5_CURRENT_VERSION ){ rc = SQLITE_ERROR; - sqlite3Fts5ConfigErrmsg(pConfig, "invalid fts5 file format " - "(found %d, expected %d or %d) - run 'rebuild'", - iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE - ); - }else{ - pConfig->iVersion = iVersion; + if( pConfig->pzErrmsg ){ + assert( 0==*pConfig->pzErrmsg ); + *pConfig->pzErrmsg = sqlite3_mprintf( + "invalid fts5 file format (found %d, expected %d) - run 'rebuild'", + iVersion, FTS5_CURRENT_VERSION + ); + } } if( rc==SQLITE_OK ){ pConfig->iCookie = iCookie; } return rc; } - -/* -** Set (*pConfig->pzErrmsg) to point to an sqlite3_malloc()ed buffer -** containing the error message created using printf() style formatting -** string zFmt and its trailing arguments. -*/ -static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){ - va_list ap; /* ... printf arguments */ - char *zMsg = 0; - - va_start(ap, zFmt); - zMsg = sqlite3_vmprintf(zFmt, ap); - if( pConfig->pzErrmsg ){ - assert( *pConfig->pzErrmsg==0 ); - *pConfig->pzErrmsg = zMsg; - }else{ - sqlite3_free(zMsg); - } - - va_end(ap); -} - - /* ** 2014 May 31 ** ** The author disclaims copyright to this source code. In place of @@ -238938,14 +187754,10 @@ /* #include "fts5Int.h" */ /* #include "fts5parse.h" */ -#ifndef SQLITE_FTS5_MAX_EXPR_DEPTH -# define SQLITE_FTS5_MAX_EXPR_DEPTH 256 -#endif - /* ** All token types in the generated fts5parse.h file are greater than 0. */ #define FTS5_EOF 0 @@ -238961,11 +187773,10 @@ static void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*); #ifndef NDEBUG /* #include */ static void sqlite3Fts5ParserTrace(FILE*, char*); #endif -static int sqlite3Fts5ParserFallback(int); struct Fts5Expr { Fts5Index *pIndex; Fts5Config *pConfig; @@ -238975,40 +187786,30 @@ Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */ }; /* ** eType: -** Expression node type. Usually one of: +** Expression node type. Always one of: ** ** FTS5_AND (nChild, apChild valid) ** FTS5_OR (nChild, apChild valid) ** FTS5_NOT (nChild, apChild valid) ** FTS5_STRING (pNear valid) ** FTS5_TERM (pNear valid) -** -** An expression node with eType==0 may also exist. It always matches zero -** rows. This is created when a phrase containing no tokens is parsed. -** e.g. "". -** -** iHeight: -** Distance from this node to furthest leaf. This is always 0 for nodes -** of type FTS5_STRING and FTS5_TERM. For all other nodes it is one -** greater than the largest child value. */ struct Fts5ExprNode { int eType; /* Node type */ int bEof; /* True at EOF */ int bNomatch; /* True if entry is not a match */ - int iHeight; /* Distance to tree leaf nodes */ /* Next method for this node. */ int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64); i64 iRowid; /* Current rowid */ Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ - /* Child nodes. For a NOT node, this array always contains 2 entries. For + /* Child nodes. For a NOT node, this array always contains 2 entries. For ** AND or OR nodes, it contains 2 or more entries. */ int nChild; /* Number of child nodes */ Fts5ExprNode *apChild[1]; /* Array of child nodes */ }; @@ -239023,15 +187824,12 @@ /* ** An instance of the following structure represents a single search term ** or term prefix. */ struct Fts5ExprTerm { - u8 bPrefix; /* True for a prefix term */ - u8 bFirst; /* True if token must be first in column */ - char *pTerm; /* Term data */ - int nQueryTerm; /* Effective size of term in bytes */ - int nFullTerm; /* Size of term in bytes incl. tokendata */ + int bPrefix; /* True for a prefix term */ + char *zTerm; /* nul-terminated term */ Fts5IndexIter *pIter; /* Iterator for this term */ Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */ }; /* @@ -239065,43 +187863,16 @@ char *zErr; int rc; int nPhrase; /* Size of apPhrase array */ Fts5ExprPhrase **apPhrase; /* Array of all phrases */ Fts5ExprNode *pExpr; /* Result of a successful parse */ - int bPhraseToAnd; /* Convert "a+b" to "a AND b" */ }; -/* -** Check that the Fts5ExprNode.iHeight variables are set correctly in -** the expression tree passed as the only argument. -*/ -#ifndef NDEBUG -static void assert_expr_depth_ok(int rc, Fts5ExprNode *p){ - if( rc==SQLITE_OK ){ - if( p->eType==FTS5_TERM || p->eType==FTS5_STRING || p->eType==0 ){ - assert( p->iHeight==0 ); - }else{ - int ii; - int iMaxChild = 0; - for(ii=0; iinChild; ii++){ - Fts5ExprNode *pChild = p->apChild[ii]; - iMaxChild = MAX(iMaxChild, pChild->iHeight); - assert_expr_depth_ok(SQLITE_OK, pChild); - } - assert( p->iHeight==iMaxChild+1 ); - } - } -} -#else -# define assert_expr_depth_ok(rc, p) -#endif - static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){ va_list ap; va_start(ap, zFmt); if( pParse->rc==SQLITE_OK ){ - assert( pParse->zErr==0 ); pParse->zErr = sqlite3_vmprintf(zFmt, ap); pParse->rc = SQLITE_ERROR; } va_end(ap); } @@ -239112,11 +187883,11 @@ /* ** Read the first token from the nul-terminated string at *pz. */ static int fts5ExprGetToken( - Fts5Parse *pParse, + Fts5Parse *pParse, const char **pz, /* IN/OUT: Pointer into buffer */ Fts5Token *pToken ){ const char *z = *pz; int tok; @@ -239134,11 +187905,10 @@ case ':': tok = FTS5_COLON; break; case ',': tok = FTS5_COMMA; break; case '+': tok = FTS5_PLUS; break; case '*': tok = FTS5_STAR; break; case '-': tok = FTS5_MINUS; break; - case '^': tok = FTS5_CARET; break; case '\0': tok = FTS5_EOF; break; case '"': { const char *z2; tok = FTS5_STRING; @@ -239175,19 +187945,18 @@ *pz = &pToken->p[pToken->n]; return tok; } -static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);} +static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); } static void fts5ParseFree(void *p){ sqlite3_free(p); } static int sqlite3Fts5ExprNew( Fts5Config *pConfig, /* FTS5 Configuration */ - int bPhraseToAnd, int iCol, const char *zExpr, /* Expression text */ - Fts5Expr **ppNew, + Fts5Expr **ppNew, char **pzErr ){ Fts5Parse sParse; Fts5Token token; const char *z = zExpr; @@ -239196,11 +187965,10 @@ Fts5Expr *pNew; *ppNew = 0; *pzErr = 0; memset(&sParse, 0, sizeof(sParse)); - sParse.bPhraseToAnd = bPhraseToAnd; pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc); if( pEngine==0 ){ return SQLITE_NOMEM; } sParse.pConfig = pConfig; do { @@ -239207,16 +187975,13 @@ t = fts5ExprGetToken(&sParse, &z, &token); sqlite3Fts5Parser(pEngine, t, token, &sParse); }while( sParse.rc==SQLITE_OK && t!=FTS5_EOF ); sqlite3Fts5ParserFree(pEngine, fts5ParseFree); - assert( sParse.pExpr || sParse.rc!=SQLITE_OK ); - assert_expr_depth_ok(sParse.rc, sParse.pExpr); - /* If the LHS of the MATCH expression was a user column, apply the ** implicit column-filter. */ - if( sParse.rc==SQLITE_OK && iColnCol ){ + if( iColnCol && sParse.pExpr && sParse.rc==SQLITE_OK ){ int n = sizeof(Fts5Colset); Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n); if( pColset ){ pColset->nCol = 1; pColset->aiCol[0] = iCol; @@ -239229,120 +187994,34 @@ *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); if( pNew==0 ){ sParse.rc = SQLITE_NOMEM; sqlite3Fts5ParseNodeFree(sParse.pExpr); }else{ - pNew->pRoot = sParse.pExpr; + if( !sParse.pExpr ){ + const int nByte = sizeof(Fts5ExprNode); + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte); + if( pNew->pRoot ){ + pNew->pRoot->bEof = 1; + } + }else{ + pNew->pRoot = sParse.pExpr; + } pNew->pIndex = 0; pNew->pConfig = pConfig; pNew->apExprPhrase = sParse.apPhrase; pNew->nPhrase = sParse.nPhrase; - pNew->bDesc = 0; sParse.apPhrase = 0; } }else{ sqlite3Fts5ParseNodeFree(sParse.pExpr); } sqlite3_free(sParse.apPhrase); - if( 0==*pzErr ){ - *pzErr = sParse.zErr; - }else{ - sqlite3_free(sParse.zErr); - } + *pzErr = sParse.zErr; return sParse.rc; } -/* -** Assuming that buffer z is at least nByte bytes in size and contains a -** valid utf-8 string, return the number of characters in the string. -*/ -static int fts5ExprCountChar(const char *z, int nByte){ - int nRet = 0; - int ii; - for(ii=0; ii=3 ){ - int jj; - zExpr[iOut++] = '"'; - for(jj=iFirst; jj0 ){ - int bAnd = 0; - if( pConfig->eDetail!=FTS5_DETAIL_FULL ){ - bAnd = 1; - if( pConfig->eDetail==FTS5_DETAIL_NONE ){ - iCol = pConfig->nCol; - } - } - zExpr[iOut] = '\0'; - rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg); - }else{ - *pp = 0; - } - sqlite3_free(zExpr); - } - - return rc; -} - /* ** Free the expression node object passed as the only argument. */ static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){ if( p ){ @@ -239364,56 +188043,19 @@ sqlite3_free(p->apExprPhrase); sqlite3_free(p); } } -static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ - Fts5Parse sParse; - memset(&sParse, 0, sizeof(sParse)); - - if( *pp1 && p2 ){ - Fts5Expr *p1 = *pp1; - int nPhrase = p1->nPhrase + p2->nPhrase; - - p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0); - p2->pRoot = 0; - - if( sParse.rc==SQLITE_OK ){ - Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc( - p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*) - ); - if( ap==0 ){ - sParse.rc = SQLITE_NOMEM; - }else{ - int i; - memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*)); - for(i=0; inPhrase; i++){ - ap[i] = p2->apExprPhrase[i]; - } - p1->nPhrase = nPhrase; - p1->apExprPhrase = ap; - } - } - sqlite3_free(p2->apExprPhrase); - sqlite3_free(p2); - }else if( p2 ){ - *pp1 = p2; - } - - return sParse.rc; -} - /* ** Argument pTerm must be a synonym iterator. Return the current rowid ** that it points to. */ static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ i64 iRet = 0; int bRetValid = 0; Fts5ExprTerm *p; - assert( pTerm ); assert( pTerm->pSynonym ); assert( bDesc==0 || bDesc==1 ); for(p=pTerm; p; p=p->pSynonym){ if( 0==sqlite3Fts5IterEof(p->pIter) ){ i64 iRowid = p->pIter->iRowid; @@ -239430,11 +188072,11 @@ /* ** Argument pTerm must be a synonym iterator. */ static int fts5ExprSynonymList( - Fts5ExprTerm *pTerm, + Fts5ExprTerm *pTerm, i64 iRowid, Fts5Buffer *pBuf, /* Use this buffer for space if required */ u8 **pa, int *pn ){ Fts5PoslistReader aStatic[4]; @@ -239448,12 +188090,12 @@ for(p=pTerm; p; p=p->pSynonym){ Fts5IndexIter *pIter = p->pIter; if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){ if( pIter->nData==0 ) continue; if( nIter==nAlloc ){ - sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; - Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc64(nByte); + int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; + Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); if( aNew==0 ){ rc = SQLITE_NOMEM; goto synonym_poslist_out; } memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); @@ -239503,17 +188145,17 @@ } /* ** All individual term iterators in pPhrase are guaranteed to be valid and -** pointing to the same rowid when this function is called. This function +** pointing to the same rowid when this function is called. This function ** checks if the current rowid really is a match, and if so populates ** the pPhrase->poslist buffer accordingly. Output parameter *pbMatch ** is set to true if this is really a match, or false otherwise. ** -** SQLITE_OK is returned if an error occurs, or an SQLite error code -** otherwise. It is not considered an error code if the current rowid is +** SQLITE_OK is returned if an error occurs, or an SQLite error code +** otherwise. It is not considered an error code if the current rowid is ** not a match. */ static int fts5ExprPhraseIsMatch( Fts5ExprNode *pNode, /* Node pPhrase belongs to */ Fts5ExprPhrase *pPhrase, /* Phrase object to initialize */ @@ -239522,19 +188164,18 @@ Fts5PoslistWriter writer = {0}; Fts5PoslistReader aStatic[4]; Fts5PoslistReader *aIter = aStatic; int i; int rc = SQLITE_OK; - int bFirst = pPhrase->aTerm[0].bFirst; - + fts5BufferZero(&pPhrase->poslist); /* If the aStatic[] array is not large enough, allocate a large array ** using sqlite3_malloc(). This approach could be improved upon. */ if( pPhrase->nTerm>ArraySize(aStatic) ){ - sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; - aIter = (Fts5PoslistReader*)sqlite3_malloc64(nByte); + int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; + aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); if( !aIter ) return SQLITE_NOMEM; } memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm); /* Initialize a term iterator for each term in the phrase */ @@ -239577,14 +188218,12 @@ } } }while( bMatch==0 ); /* Append position iPos to the output */ - if( bFirst==0 || FTS5_POS2OFFSET(iPos)==0 ){ - rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); - if( rc!=SQLITE_OK ) goto ismatch_out; - } + rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); + if( rc!=SQLITE_OK ) goto ismatch_out; for(i=0; inTerm; i++){ if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; } } @@ -239645,11 +188284,11 @@ ** ** If in/out parameter (*pRc) is set to other than SQLITE_OK when this ** function is called, it is a no-op. Or, if an error (e.g. SQLITE_NOMEM) ** occurs within this function (*pRc) is set accordingly before returning. ** The return value is undefined in both these cases. -** +** ** If no error occurs and non-zero (a match) is returned, the position-list ** of each phrase object is edited to contain only those entries that ** meet the constraint before returning. */ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){ @@ -239664,11 +188303,11 @@ assert( pNear->nPhrase>1 ); /* If the aStatic[] array is not large enough, allocate a large array ** using sqlite3_malloc(). This approach could be improved upon. */ if( pNear->nPhrase>ArraySize(aStatic) ){ - sqlite3_int64 nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; + int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); }else{ memset(aStatic, 0, sizeof(aStatic)); } if( rc!=SQLITE_OK ){ @@ -239677,11 +188316,11 @@ } /* Initialize a lookahead iterator for each phrase. After passing the ** buffer and buffer size to the lookaside-reader init function, zero ** the phrase poslist buffer. The new poslist for the phrase (containing - ** the same entries as the original with some entries removed on account + ** the same entries as the original with some entries removed on account ** of the NEAR constraint) is written over the original even as it is ** being read. This is safe as the entries for the new poslist are a ** subset of the old, so it is not possible for data yet to be read to ** be overwritten. */ for(i=0; inPhrase; i++){ @@ -239834,13 +188473,11 @@ /* Check that each phrase in the nearset matches the current row. ** Populate the pPhrase->poslist buffers at the same time. If any ** phrase is not a match, break out of the loop early. */ for(i=0; rc==SQLITE_OK && inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym - || pNear->pColset || pPhrase->aTerm[0].bFirst - ){ + if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ int bMatch = 0; rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch); if( bMatch==0 ) break; }else{ Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; @@ -239891,11 +188528,11 @@ if( p->pIter ){ sqlite3Fts5IterClose(p->pIter); p->pIter = 0; } rc = sqlite3Fts5IndexQuery( - pExpr->pIndex, p->pTerm, p->nQueryTerm, + pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), pNear->pColset, &p->pIter ); @@ -239982,11 +188619,11 @@ ** rowids are considered larger. Or if it is the default DESC, numerically ** smaller rowids are larger. */ static int fts5NodeCompare( Fts5Expr *pExpr, - Fts5ExprNode *p1, + Fts5ExprNode *p1, Fts5ExprNode *p2 ){ if( p2->bEof ) return -1; if( p1->bEof ) return +1; return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); @@ -239997,11 +188634,11 @@ ** this function is called. This function checks if all term iterators ** point to the same rowid, and if not, advances them until they do. ** If an EOF is reached before this happens, *pbEof is set to true before ** returning. ** -** SQLITE_OK is returned if an error occurs, or an SQLite error code +** SQLITE_OK is returned if an error occurs, or an SQLite error code ** otherwise. It is not considered an error code if an iterator reaches ** EOF. */ static int fts5ExprNodeTest_STRING( Fts5Expr *pExpr, /* Expression pPhrase belongs to */ @@ -240014,14 +188651,13 @@ int i, j; /* Phrase and token index, respectively */ int bMatch; /* True if all terms are at the same rowid */ const int bDesc = pExpr->bDesc; /* Check that this node should not be FTS5_TERM */ - assert( pNear->nPhrase>1 - || pNear->apPhrase[0]->nTerm>1 + assert( pNear->nPhrase>1 + || pNear->apPhrase[0]->nTerm>1 || pNear->apPhrase[0]->aTerm[0].pSynonym - || pNear->apPhrase[0]->aTerm[0].bFirst ); /* Initialize iLast, the "lastest" rowid any iterator points to. If the ** iterator skips through rowids in the default ascending order, this means ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it @@ -240047,11 +188683,11 @@ pNode->bEof = 1; return rc; } }else{ Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; - if( pIter->iRowid==iLast ) continue; + if( pIter->iRowid==iLast || pIter->bEof ) continue; bMatch = 0; if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ return rc; } } @@ -240075,11 +188711,11 @@ */ static int fts5ExprNodeNext_STRING( Fts5Expr *pExpr, /* Expression pPhrase belongs to */ Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ int bFromValid, - i64 iFrom + i64 iFrom ){ Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; int rc = SQLITE_OK; pNode->bNomatch = 0; @@ -240093,12 +188729,12 @@ /* Advance each iterator that currently points to iRowid. Or, if iFrom ** is valid - each iterator that points to a rowid before iFrom. */ for(p=pTerm; p; p=p->pSynonym){ if( sqlite3Fts5IterEof(p->pIter)==0 ){ i64 ii = p->pIter->iRowid; - if( ii==iRowid - || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) + if( ii==iRowid + || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) ){ if( bFromValid ){ rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); }else{ rc = sqlite3Fts5IterNext(p->pIter); @@ -240140,13 +188776,13 @@ static int fts5ExprNodeTest_TERM( Fts5Expr *pExpr, /* Expression that pNear is a part of */ Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ ){ - /* As this "NEAR" object is actually a single phrase that consists + /* As this "NEAR" object is actually a single phrase that consists ** of a single term only, grab pointers into the poslist managed by the - ** fts5_index.c iterator object. This is much faster than synthesizing + ** fts5_index.c iterator object. This is much faster than synthesizing ** a new poslist the way we have to for more complicated phrase or NEAR ** expressions. */ Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; @@ -240165,11 +188801,11 @@ /* ** xNext() method for a node of type FTS5_TERM. */ static int fts5ExprNodeNext_TERM( - Fts5Expr *pExpr, + Fts5Expr *pExpr, Fts5ExprNode *pNode, int bFromValid, i64 iFrom ){ int rc; @@ -240208,11 +188844,11 @@ pNode->bEof = pNext->bEof; pNode->bNomatch = pNext->bNomatch; } static int fts5ExprNodeNext_OR( - Fts5Expr *pExpr, + Fts5Expr *pExpr, Fts5ExprNode *pNode, int bFromValid, i64 iFrom ){ int i; @@ -240220,11 +188856,11 @@ for(i=0; inChild; i++){ Fts5ExprNode *p1 = pNode->apChild[i]; assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); if( p1->bEof==0 ){ - if( (p1->iRowid==iLast) + if( (p1->iRowid==iLast) || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) ){ int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); if( rc!=SQLITE_OK ){ pNode->bNomatch = 0; @@ -240292,11 +188928,11 @@ pAnd->iRowid = iLast; return SQLITE_OK; } static int fts5ExprNodeNext_AND( - Fts5Expr *pExpr, + Fts5Expr *pExpr, Fts5ExprNode *pNode, int bFromValid, i64 iFrom ){ int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); @@ -240335,11 +188971,11 @@ } return rc; } static int fts5ExprNodeNext_NOT( - Fts5Expr *pExpr, + Fts5Expr *pExpr, Fts5ExprNode *pNode, int bFromValid, i64 iFrom ){ int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); @@ -240392,11 +189028,11 @@ } } return rc; } - + /* ** Set node pNode, which is part of expression pExpr, to point to the first ** match. If there are no matches, set the Node.bEof flag to indicate EOF. ** ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. @@ -240446,12 +189082,12 @@ } /* ** Begin iterating through the set of documents in index pIdx matched by -** the MATCH expression passed as the first argument. If the "bDesc" -** parameter is passed a non-zero value, iteration is in descending rowid +** the MATCH expression passed as the first argument. If the "bDesc" +** parameter is passed a non-zero value, iteration is in descending rowid ** order. Or, if it is zero, in ascending order. ** ** If iterating in ascending rowid order (bDesc==0), the first document ** visited is that with the smallest rowid that is larger than or equal ** to parameter iFirst. Or, if iterating in ascending order (bDesc==1), @@ -240469,27 +189105,27 @@ p->bDesc = bDesc; rc = fts5ExprNodeFirst(p, pRoot); /* If not at EOF but the current rowid occurs earlier than iFirst in ** the iteration order, move to document iFirst or later. */ - if( rc==SQLITE_OK - && 0==pRoot->bEof - && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 + if( rc==SQLITE_OK + && 0==pRoot->bEof + && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); } /* If the iterator is not at a real match, skip forward until it is. */ - while( pRoot->bNomatch && rc==SQLITE_OK ){ - assert( pRoot->bEof==0 ); + while( pRoot->bNomatch ){ + assert( pRoot->bEof==0 && rc==SQLITE_OK ); rc = fts5ExprNodeNext(p, pRoot, 0, 0); } return rc; } /* -** Move to the next document +** Move to the next document ** ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It ** is not considered an error if the query does not match any documents. */ static int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ @@ -240528,11 +189164,11 @@ int i; for(i=0; inTerm; i++){ Fts5ExprTerm *pSyn; Fts5ExprTerm *pNext; Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; - sqlite3_free(pTerm->pTerm); + sqlite3_free(pTerm->zTerm); sqlite3Fts5IterClose(pTerm->pIter); for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ pNext = pSyn->pSynonym; sqlite3Fts5IterClose(pSyn->pIter); fts5BufferFree((Fts5Buffer*)&pSyn[1]); @@ -240542,20 +189178,10 @@ if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist); sqlite3_free(pPhrase); } } -/* -** Set the "bFirst" flag on the first token of the phrase passed as the -** only argument. -*/ -static void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase *pPhrase){ - if( pPhrase && pPhrase->nTerm ){ - pPhrase->aTerm[0].bFirst = 1; - } -} - /* ** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated ** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is ** appended to it and the results returned. ** @@ -240569,25 +189195,26 @@ ){ const int SZALLOC = 8; Fts5ExprNearset *pRet = 0; if( pParse->rc==SQLITE_OK ){ + if( pPhrase==0 ){ + return pNear; + } if( pNear==0 ){ - sqlite3_int64 nByte; - nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*); - pRet = sqlite3_malloc64(nByte); + int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*); + pRet = sqlite3_malloc(nByte); if( pRet==0 ){ pParse->rc = SQLITE_NOMEM; }else{ - memset(pRet, 0, (size_t)nByte); + memset(pRet, 0, nByte); } }else if( (pNear->nPhrase % SZALLOC)==0 ){ int nNew = pNear->nPhrase + SZALLOC; - sqlite3_int64 nByte; + int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*); - nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*); - pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte); + pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte); if( pRet==0 ){ pParse->rc = SQLITE_NOMEM; } }else{ pRet = pNear; @@ -240599,13 +189226,10 @@ sqlite3Fts5ParseNearsetFree(pNear); sqlite3Fts5ParsePhraseFree(pPhrase); }else{ if( pRet->nPhrase>0 ){ Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1]; - assert( pParse!=0 ); - assert( pParse->apPhrase!=0 ); - assert( pParse->nPhrase>=2 ); assert( pLast==pParse->apPhrase[pParse->nPhrase-2] ); if( pPhrase->nTerm==0 ){ fts5ExprPhraseFree(pPhrase); pRet->nPhrase--; pParse->nPhrase--; @@ -240623,11 +189247,10 @@ } typedef struct TokenCtx TokenCtx; struct TokenCtx { Fts5ExprPhrase *pPhrase; - Fts5Config *pConfig; int rc; }; /* ** Callback for tokenizing terms used by ParseTerm(). @@ -240651,32 +189274,28 @@ if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){ Fts5ExprTerm *pSyn; - sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; - pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte); + int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; + pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); if( pSyn==0 ){ rc = SQLITE_NOMEM; }else{ - memset(pSyn, 0, (size_t)nByte); - pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); - pSyn->nFullTerm = pSyn->nQueryTerm = nToken; - if( pCtx->pConfig->bTokendata ){ - pSyn->nQueryTerm = (int)strlen(pSyn->pTerm); - } - memcpy(pSyn->pTerm, pToken, nToken); + memset(pSyn, 0, nByte); + pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); + memcpy(pSyn->zTerm, pToken, nToken); pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; } }else{ Fts5ExprTerm *pTerm; if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){ Fts5ExprPhrase *pNew; int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0); - pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase, + pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase, sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew ); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -240687,15 +189306,11 @@ } if( rc==SQLITE_OK ){ pTerm = &pPhrase->aTerm[pPhrase->nTerm++]; memset(pTerm, 0, sizeof(Fts5ExprTerm)); - pTerm->pTerm = sqlite3Fts5Strndup(&rc, pToken, nToken); - pTerm->nFullTerm = pTerm->nQueryTerm = nToken; - if( pCtx->pConfig->bTokendata && rc==SQLITE_OK ){ - pTerm->nQueryTerm = (int)strlen(pTerm->pTerm); - } + pTerm->zTerm = sqlite3Fts5Strndup(&rc, pToken, nToken); } } pCtx->rc = rc; return rc; @@ -240726,24 +189341,10 @@ static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){ assert( pParse->pExpr==0 ); pParse->pExpr = p; } -static int parseGrowPhraseArray(Fts5Parse *pParse){ - if( (pParse->nPhrase % 8)==0 ){ - sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8); - Fts5ExprPhrase **apNew; - apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte); - if( apNew==0 ){ - pParse->rc = SQLITE_NOMEM; - return SQLITE_NOMEM; - } - pParse->apPhrase = apNew; - } - return SQLITE_OK; -} - /* ** This function is called by the parser to process a string token. The ** string may or may not be quoted. In any case it is tokenized and a ** phrase object consisting of all tokens returned. */ @@ -240758,11 +189359,10 @@ int rc; /* Tokenize return code */ char *z = 0; memset(&sCtx, 0, sizeof(TokenCtx)); sCtx.pPhrase = pAppend; - sCtx.pConfig = pConfig; rc = fts5ParseStringFromToken(pToken, &z); if( rc==SQLITE_OK ){ int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0); int n; @@ -240776,25 +189376,31 @@ fts5ExprPhraseFree(sCtx.pPhrase); sCtx.pPhrase = 0; }else{ if( pAppend==0 ){ - if( parseGrowPhraseArray(pParse) ){ - fts5ExprPhraseFree(sCtx.pPhrase); - return 0; + if( (pParse->nPhrase % 8)==0 ){ + int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8); + Fts5ExprPhrase **apNew; + apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte); + if( apNew==0 ){ + pParse->rc = SQLITE_NOMEM; + fts5ExprPhraseFree(sCtx.pPhrase); + return 0; + } + pParse->apPhrase = apNew; } pParse->nPhrase++; } if( sCtx.pPhrase==0 ){ /* This happens when parsing a token or quoted phrase that contains ** no token characters at all. (e.g ... MATCH '""'). */ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase)); }else if( sCtx.pPhrase->nTerm ){ - sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix; + sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; } - assert( pParse->apPhrase!=0 ); pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; } return sCtx.pPhrase; } @@ -240802,87 +189408,77 @@ /* ** Create a new FTS5 expression by cloning phrase iPhrase of the ** expression passed as the second argument. */ static int sqlite3Fts5ExprClonePhrase( - Fts5Expr *pExpr, - int iPhrase, + Fts5Expr *pExpr, + int iPhrase, Fts5Expr **ppNew ){ int rc = SQLITE_OK; /* Return code */ - Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */ + Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ - TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */ - if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){ - rc = SQLITE_RANGE; - }else{ - pOrig = pExpr->apExprPhrase[iPhrase]; - pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); - } + TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ + + pOrig = pExpr->apExprPhrase[iPhrase]; + pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); if( rc==SQLITE_OK ){ - pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, + pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase*)); } if( rc==SQLITE_OK ){ - pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNode)); } if( rc==SQLITE_OK ){ - pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, + pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)); } - if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){ + if( rc==SQLITE_OK ){ Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; if( pColsetOrig ){ - sqlite3_int64 nByte; - Fts5Colset *pColset; - nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); - pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); - if( pColset ){ - memcpy(pColset, pColsetOrig, (size_t)nByte); + int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); + Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); + if( pColset ){ + memcpy(pColset, pColsetOrig, nByte); } pNew->pRoot->pNear->pColset = pColset; } } - if( rc==SQLITE_OK ){ - if( pOrig->nTerm ){ - int i; /* Used to iterate through phrase terms */ - sCtx.pConfig = pExpr->pConfig; - for(i=0; rc==SQLITE_OK && inTerm; i++){ - int tflags = 0; - Fts5ExprTerm *p; - for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ - rc = fts5ParseTokenize((void*)&sCtx,tflags,p->pTerm,p->nFullTerm,0,0); - tflags = FTS5_TOKEN_COLOCATED; - } - if( rc==SQLITE_OK ){ - sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; - sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; - } - } - }else{ - /* This happens when parsing a token or quoted phrase that contains - ** no token characters at all. (e.g ... MATCH '""'). */ - sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); - } - } - - if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){ + if( pOrig->nTerm ){ + int i; /* Used to iterate through phrase terms */ + for(i=0; rc==SQLITE_OK && inTerm; i++){ + int tflags = 0; + Fts5ExprTerm *p; + for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ + const char *zTerm = p->zTerm; + rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), + 0, 0); + tflags = FTS5_TOKEN_COLOCATED; + } + if( rc==SQLITE_OK ){ + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + } + } + }else{ + /* This happens when parsing a token or quoted phrase that contains + ** no token characters at all. (e.g ... MATCH '""'). */ + sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase)); + } + + if( rc==SQLITE_OK ){ /* All the allocations succeeded. Put the expression object together. */ pNew->pIndex = pExpr->pIndex; pNew->pConfig = pExpr->pConfig; pNew->nPhrase = 1; pNew->apExprPhrase[0] = sCtx.pPhrase; pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase; pNew->pRoot->pNear->nPhrase = 1; sCtx.pPhrase->pNode = pNew->pRoot; - if( pOrig->nTerm==1 - && pOrig->aTerm[0].pSynonym==0 - && pOrig->aTerm[0].bFirst==0 - ){ + if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ pNew->pRoot->eType = FTS5_TERM; pNew->pRoot->xNext = fts5ExprNodeNext_TERM; }else{ pNew->pRoot->eType = FTS5_STRING; pNew->pRoot->xNext = fts5ExprNodeNext_STRING; @@ -240910,11 +189506,11 @@ ); } } static void sqlite3Fts5ParseSetDistance( - Fts5Parse *pParse, + Fts5Parse *pParse, Fts5ExprNearset *pNear, Fts5Token *p ){ if( pNear ){ int nNear = 0; @@ -240939,11 +189535,11 @@ /* ** The second argument passed to this function may be NULL, or it may be ** an existing Fts5Colset object. This function returns a pointer to ** a new colset object containing the contents of (p) with new value column -** number iCol appended. +** number iCol appended. ** ** If an OOM error occurs, store an error code in pParse and return NULL. ** The old colset object (if any) is not freed in this case. */ static Fts5Colset *fts5ParseColset( @@ -240955,11 +189551,11 @@ Fts5Colset *pNew; /* New colset object to return */ assert( pParse->rc==SQLITE_OK ); assert( iCol>=0 && iColpConfig->nCol ); - pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol); + pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol); if( pNew==0 ){ pParse->rc = SQLITE_NOMEM; }else{ int *aiCol = pNew->aiCol; int i, j; @@ -240989,11 +189585,11 @@ */ static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){ Fts5Colset *pRet; int nCol = pParse->pConfig->nCol; - pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc, + pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5Colset) + sizeof(int)*nCol ); if( pRet ){ int i; int iOld = 0; @@ -241042,23 +189638,23 @@ return pRet; } /* ** If argument pOrig is NULL, or if (*pRc) is set to anything other than -** SQLITE_OK when this function is called, NULL is returned. +** SQLITE_OK when this function is called, NULL is returned. ** ** Otherwise, a copy of (*pOrig) is made into memory obtained from ** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation ** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned. */ static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){ Fts5Colset *pRet; if( pOrig ){ - sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int); + int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int); pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte); - if( pRet ){ - memcpy(pRet, pOrig, (size_t)nByte); + if( pRet ){ + memcpy(pRet, pOrig, nByte); } }else{ pRet = 0; } return pRet; @@ -241092,17 +189688,17 @@ ** its decendents. If (*ppFree) is not NULL, it contains a spare copy ** of pColset. This function may use the spare copy and set (*ppFree) to ** zero, or it may create copies of pColset using fts5CloneColset(). */ static void fts5ParseSetColset( - Fts5Parse *pParse, - Fts5ExprNode *pNode, + Fts5Parse *pParse, + Fts5ExprNode *pNode, Fts5Colset *pColset, Fts5Colset **ppFree ){ if( pParse->rc==SQLITE_OK ){ - assert( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING + assert( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING || pNode->eType==FTS5_AND || pNode->eType==FTS5_OR || pNode->eType==FTS5_NOT || pNode->eType==FTS5_EOF ); if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){ Fts5ExprNearset *pNear = pNode->pNear; @@ -241130,18 +189726,19 @@ /* ** Apply colset pColset to expression node pExpr and all of its descendents. */ static void sqlite3Fts5ParseSetColset( - Fts5Parse *pParse, - Fts5ExprNode *pExpr, - Fts5Colset *pColset + Fts5Parse *pParse, + Fts5ExprNode *pExpr, + Fts5Colset *pColset ){ Fts5Colset *pFree = pColset; if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){ - sqlite3Fts5ParseError(pParse, - "fts5: column queries are not supported (detail=none)" + pParse->rc = SQLITE_ERROR; + pParse->zErr = sqlite3_mprintf( + "fts5: column queries are not supported (detail=none)" ); }else{ fts5ParseSetColset(pParse, pExpr, pColset, &pFree); } sqlite3_free(pFree); @@ -241149,13 +189746,12 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ switch( pNode->eType ){ case FTS5_STRING: { Fts5ExprNearset *pNear = pNode->pNear; - if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 + if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 && pNear->apPhrase[0]->aTerm[0].pSynonym==0 - && pNear->apPhrase[0]->aTerm[0].bFirst==0 ){ pNode->eType = FTS5_TERM; pNode->xNext = fts5ExprNodeNext_TERM; }else{ pNode->xNext = fts5ExprNodeNext_STRING; @@ -241178,90 +189774,19 @@ break; }; } } -/* -** Add pSub as a child of p. -*/ static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ - int ii = p->nChild; if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; memcpy(&p->apChild[p->nChild], pSub->apChild, nByte); p->nChild += pSub->nChild; sqlite3_free(pSub); }else{ p->apChild[p->nChild++] = pSub; } - for( ; iinChild; ii++){ - p->iHeight = MAX(p->iHeight, p->apChild[ii]->iHeight + 1); - } -} - -/* -** This function is used when parsing LIKE or GLOB patterns against -** trigram indexes that specify either detail=column or detail=none. -** It converts a phrase: -** -** abc + def + ghi -** -** into an AND tree: -** -** abc AND def AND ghi -*/ -static Fts5ExprNode *fts5ParsePhraseToAnd( - Fts5Parse *pParse, - Fts5ExprNearset *pNear -){ - int nTerm = pNear->apPhrase[0]->nTerm; - int ii; - int nByte; - Fts5ExprNode *pRet; - - assert( pNear->nPhrase==1 ); - assert( pParse->bPhraseToAnd ); - - nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*); - pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); - if( pRet ){ - pRet->eType = FTS5_AND; - pRet->nChild = nTerm; - pRet->iHeight = 1; - fts5ExprAssignXNext(pRet); - pParse->nPhrase--; - for(ii=0; iirc, sizeof(Fts5ExprPhrase) - ); - if( pPhrase ){ - if( parseGrowPhraseArray(pParse) ){ - fts5ExprPhraseFree(pPhrase); - }else{ - Fts5ExprTerm *p = &pNear->apPhrase[0]->aTerm[ii]; - Fts5ExprTerm *pTo = &pPhrase->aTerm[0]; - pParse->apPhrase[pParse->nPhrase++] = pPhrase; - pPhrase->nTerm = 1; - pTo->pTerm = sqlite3Fts5Strndup(&pParse->rc, p->pTerm, p->nFullTerm); - pTo->nQueryTerm = p->nQueryTerm; - pTo->nFullTerm = p->nFullTerm; - pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING, - 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase) - ); - } - } - } - - if( pParse->rc ){ - sqlite3Fts5ParseNodeFree(pRet); - pRet = 0; - }else{ - sqlite3Fts5ParseNearsetFree(pNear); - } - } - - return pRet; } /* ** Allocate and return a new expression object. If anything goes wrong (i.e. ** OOM error), leave an error code in pParse and return NULL. @@ -241275,80 +189800,61 @@ ){ Fts5ExprNode *pRet = 0; if( pParse->rc==SQLITE_OK ){ int nChild = 0; /* Number of children of returned node */ - sqlite3_int64 nByte; /* Bytes of space to allocate for this node */ - + int nByte; /* Bytes of space to allocate for this node */ + assert( (eType!=FTS5_STRING && !pNear) || (eType==FTS5_STRING && !pLeft && !pRight) ); if( eType==FTS5_STRING && pNear==0 ) return 0; if( eType!=FTS5_STRING && pLeft==0 ) return pRight; if( eType!=FTS5_STRING && pRight==0 ) return pLeft; - if( eType==FTS5_STRING - && pParse->bPhraseToAnd - && pNear->apPhrase[0]->nTerm>1 - ){ - pRet = fts5ParsePhraseToAnd(pParse, pNear); - }else{ - if( eType==FTS5_NOT ){ - nChild = 2; - }else if( eType==FTS5_AND || eType==FTS5_OR ){ - nChild = 2; - if( pLeft->eType==eType ) nChild += pLeft->nChild-1; - if( pRight->eType==eType ) nChild += pRight->nChild-1; - } - - nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1); - pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); - - if( pRet ){ - pRet->eType = eType; - pRet->pNear = pNear; - fts5ExprAssignXNext(pRet); - if( eType==FTS5_STRING ){ - int iPhrase; - for(iPhrase=0; iPhrasenPhrase; iPhrase++){ - pNear->apPhrase[iPhrase]->pNode = pRet; - if( pNear->apPhrase[iPhrase]->nTerm==0 ){ - pRet->xNext = 0; - pRet->eType = FTS5_EOF; - } - } - - if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ - Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; - if( pNear->nPhrase!=1 - || pPhrase->nTerm>1 - || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst) - ){ - sqlite3Fts5ParseError(pParse, - "fts5: %s queries are not supported (detail!=full)", - pNear->nPhrase==1 ? "phrase": "NEAR" - ); - sqlite3Fts5ParseNodeFree(pRet); - pRet = 0; - pNear = 0; - assert( pLeft==0 && pRight==0 ); - } - } - }else{ - assert( pNear==0 ); - fts5ExprAddChildren(pRet, pLeft); - fts5ExprAddChildren(pRet, pRight); - pLeft = pRight = 0; - if( pRet->iHeight>SQLITE_FTS5_MAX_EXPR_DEPTH ){ - sqlite3Fts5ParseError(pParse, - "fts5 expression tree is too large (maximum depth %d)", - SQLITE_FTS5_MAX_EXPR_DEPTH - ); - sqlite3Fts5ParseNodeFree(pRet); - pRet = 0; - } - } + if( eType==FTS5_NOT ){ + nChild = 2; + }else if( eType==FTS5_AND || eType==FTS5_OR ){ + nChild = 2; + if( pLeft->eType==eType ) nChild += pLeft->nChild-1; + if( pRight->eType==eType ) nChild += pRight->nChild-1; + } + + nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1); + pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); + + if( pRet ){ + pRet->eType = eType; + pRet->pNear = pNear; + fts5ExprAssignXNext(pRet); + if( eType==FTS5_STRING ){ + int iPhrase; + for(iPhrase=0; iPhrasenPhrase; iPhrase++){ + pNear->apPhrase[iPhrase]->pNode = pRet; + if( pNear->apPhrase[iPhrase]->nTerm==0 ){ + pRet->xNext = 0; + pRet->eType = FTS5_EOF; + } + } + + if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL + && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1) + ){ + assert( pParse->rc==SQLITE_OK ); + pParse->rc = SQLITE_ERROR; + assert( pParse->zErr==0 ); + pParse->zErr = sqlite3_mprintf( + "fts5: %s queries are not supported (detail!=full)", + pNear->nPhrase==1 ? "phrase": "NEAR" + ); + sqlite3_free(pRet); + pRet = 0; + } + + }else{ + fts5ExprAddChildren(pRet, pLeft); + fts5ExprAddChildren(pRet, pRight); } } } if( pRet==0 ){ @@ -241371,34 +189877,31 @@ if( pParse->rc ){ sqlite3Fts5ParseNodeFree(pLeft); sqlite3Fts5ParseNodeFree(pRight); }else{ - assert( pLeft->eType==FTS5_STRING + assert( pLeft->eType==FTS5_STRING || pLeft->eType==FTS5_TERM || pLeft->eType==FTS5_EOF || pLeft->eType==FTS5_AND ); - assert( pRight->eType==FTS5_STRING - || pRight->eType==FTS5_TERM - || pRight->eType==FTS5_EOF - || (pRight->eType==FTS5_AND && pParse->bPhraseToAnd) + assert( pRight->eType==FTS5_STRING + || pRight->eType==FTS5_TERM + || pRight->eType==FTS5_EOF ); if( pLeft->eType==FTS5_AND ){ pPrev = pLeft->apChild[pLeft->nChild-1]; }else{ pPrev = pLeft; } - assert( pPrev->eType==FTS5_STRING - || pPrev->eType==FTS5_TERM - || pPrev->eType==FTS5_EOF + assert( pPrev->eType==FTS5_STRING + || pPrev->eType==FTS5_TERM + || pPrev->eType==FTS5_EOF ); if( pRight->eType==FTS5_EOF ){ - assert( pParse->apPhrase!=0 ); - assert( pParse->nPhrase>0 ); assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] ); sqlite3Fts5ParseNodeFree(pRight); pRet = pLeft; pParse->nPhrase--; } @@ -241425,29 +189928,27 @@ } return pRet; } -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){ - sqlite3_int64 nByte = 0; + int nByte = 0; Fts5ExprTerm *p; char *zQuoted; /* Determine the maximum amount of space required. */ for(p=pTerm; p; p=p->pSynonym){ - nByte += pTerm->nQueryTerm * 2 + 3 + 2; + nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2; } - zQuoted = sqlite3_malloc64(nByte); + zQuoted = sqlite3_malloc(nByte); if( zQuoted ){ int i = 0; for(p=pTerm; p; p=p->pSynonym){ - char *zIn = p->pTerm; - char *zEnd = &zIn[p->nQueryTerm]; + char *zIn = p->zTerm; zQuoted[i++] = '"'; - while( zInpSynonym ) zQuoted[i++] = '|'; @@ -241475,24 +189976,24 @@ sqlite3_free(zApp); return zNew; } /* -** Compose a tcl-readable representation of expression pExpr. Return a -** pointer to a buffer containing that representation. It is the -** responsibility of the caller to at some point free the buffer using +** Compose a tcl-readable representation of expression pExpr. Return a +** pointer to a buffer containing that representation. It is the +** responsibility of the caller to at some point free the buffer using ** sqlite3_free(). */ static char *fts5ExprPrintTcl( - Fts5Config *pConfig, + Fts5Config *pConfig, const char *zNearsetCmd, Fts5ExprNode *pExpr ){ char *zRet = 0; if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){ Fts5ExprNearset *pNear = pExpr->pNear; - int i; + int i; int iTerm; zRet = fts5PrintfAppend(zRet, "%s ", zNearsetCmd); if( zRet==0 ) return 0; if( pNear->pColset ){ @@ -241521,34 +190022,30 @@ for(i=0; inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; zRet = fts5PrintfAppend(zRet, " {"); for(iTerm=0; zRet && iTermnTerm; iTerm++){ - Fts5ExprTerm *p = &pPhrase->aTerm[iTerm]; - zRet = fts5PrintfAppend(zRet, "%s%.*s", iTerm==0?"":" ", - p->nQueryTerm, p->pTerm - ); + char *zTerm = pPhrase->aTerm[iTerm].zTerm; + zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm); if( pPhrase->aTerm[iTerm].bPrefix ){ zRet = fts5PrintfAppend(zRet, "*"); } } if( zRet ) zRet = fts5PrintfAppend(zRet, "}"); if( zRet==0 ) return 0; } - }else if( pExpr->eType==0 ){ - zRet = sqlite3_mprintf("{}"); }else{ char const *zOp = 0; int i; switch( pExpr->eType ){ case FTS5_AND: zOp = "AND"; break; case FTS5_NOT: zOp = "NOT"; break; - default: + default: assert( pExpr->eType==FTS5_OR ); - zOp = "OR"; + zOp = "OR"; break; } zRet = sqlite3_mprintf("%s", zOp); for(i=0; zRet && inChild; i++){ @@ -241570,25 +190067,16 @@ if( pExpr->eType==0 ){ return sqlite3_mprintf("\"\""); }else if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){ Fts5ExprNearset *pNear = pExpr->pNear; - int i; + int i; int iTerm; if( pNear->pColset ){ - int ii; - Fts5Colset *pColset = pNear->pColset; - if( pColset->nCol>1 ) zRet = fts5PrintfAppend(zRet, "{"); - for(ii=0; iinCol; ii++){ - zRet = fts5PrintfAppend(zRet, "%s%s", - pConfig->azCol[pColset->aiCol[ii]], ii==pColset->nCol-1 ? "" : " " - ); - } - if( zRet ){ - zRet = fts5PrintfAppend(zRet, "%s : ", pColset->nCol>1 ? "}" : ""); - } + int iCol = pNear->pColset->aiCol[0]; + zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]); if( zRet==0 ) return 0; } if( pNear->nPhrase>1 ){ zRet = fts5PrintfAppend(zRet, "NEAR("); @@ -241624,13 +190112,13 @@ int i; switch( pExpr->eType ){ case FTS5_AND: zOp = " AND "; break; case FTS5_NOT: zOp = " NOT "; break; - default: + default: assert( pExpr->eType==FTS5_OR ); - zOp = " OR "; + zOp = " OR "; break; } for(i=0; inChild; i++){ char *z = fts5ExprPrint(pConfig, pExpr->apChild[i]); @@ -241638,11 +190126,11 @@ sqlite3_free(zRet); zRet = 0; }else{ int e = pExpr->apChild[i]->eType; int b = (e!=FTS5_STRING && e!=FTS5_TERM && e!=FTS5_EOF); - zRet = fts5PrintfAppend(zRet, "%s%s%z%s", + zRet = fts5PrintfAppend(zRet, "%s%s%z%s", (i==0 ? "" : zOp), (b?"(":""), z, (b?")":"") ); } if( zRet==0 ) break; @@ -241689,29 +190177,27 @@ zNearsetCmd = (const char*)sqlite3_value_text(apVal[1]); iArg = 2; } nConfig = 3 + (nArg-iArg); - azConfig = (const char**)sqlite3_malloc64(sizeof(char*) * nConfig); + azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig); if( azConfig==0 ){ sqlite3_result_error_nomem(pCtx); return; } azConfig[0] = 0; azConfig[1] = "main"; azConfig[2] = "tbl"; for(i=3; iArgnCol, zExpr, &pExpr, &zErr); + rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr); } if( rc==SQLITE_OK ){ char *zText; if( pExpr->pRoot->xNext==0 ){ zText = sqlite3_mprintf(""); @@ -241756,41 +190242,36 @@ fts5ExprFunction(pCtx, nArg, apVal, 1); } /* ** The implementation of an SQLite user-defined-function that accepts a -** single integer as an argument. If the integer is an alpha-numeric +** single integer as an argument. If the integer is an alpha-numeric ** unicode code point, 1 is returned. Otherwise 0. */ static void fts5ExprIsAlnum( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apVal /* Function arguments */ ){ int iCode; - u8 aArr[32]; if( nArg!=1 ){ - sqlite3_result_error(pCtx, + sqlite3_result_error(pCtx, "wrong number of arguments to function fts5_isalnum", -1 ); return; } - memset(aArr, 0, sizeof(aArr)); - sqlite3Fts5UnicodeCatParse("L*", aArr); - sqlite3Fts5UnicodeCatParse("N*", aArr); - sqlite3Fts5UnicodeCatParse("Co", aArr); iCode = sqlite3_value_int(apVal[0]); - sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory((u32)iCode)]); + sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode)); } static void fts5ExprFold( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apVal /* Function arguments */ ){ if( nArg!=1 && nArg!=2 ){ - sqlite3_result_error(pCtx, + sqlite3_result_error(pCtx, "wrong number of arguments to function fts5_fold", -1 ); }else{ int iCode; int bRemoveDiacritics = 0; @@ -241797,18 +190278,16 @@ iCode = sqlite3_value_int(apVal[0]); if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]); sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics)); } } -#endif /* if SQLITE_TEST || SQLITE_FTS5_DEBUG */ /* ** This is called during initialization to register the fts5_expr() scalar ** UDF with the SQLite handle passed as the only argument. */ static int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) struct Fts5ExprFunc { const char *z; void (*x)(sqlite3_context*,int,sqlite3_value**); } aFunc[] = { { "fts5_expr", fts5ExprFunctionHr }, @@ -241822,21 +190301,15 @@ for(i=0; rc==SQLITE_OK && iz, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); } -#else - int rc = SQLITE_OK; - UNUSED_PARAM2(pGlobal,db); -#endif - /* Avoid warnings indicating that sqlite3Fts5ParserTrace() and - ** sqlite3Fts5ParserFallback() are unused */ + /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ #ifndef NDEBUG (void)sqlite3Fts5ParserTrace; #endif - (void)sqlite3Fts5ParserFallback; return rc; } /* @@ -241876,30 +190349,21 @@ Fts5PoslistWriter writer; int bOk; /* True if ok to populate */ int bMiss; }; -/* -** Clear the position lists associated with all phrases in the expression -** passed as the first argument. Argument bLive is true if the expression -** might be pointing to a real entry, otherwise it has just been reset. -** -** At present this function is only used for detail=col and detail=none -** fts5 tables. This implies that all phrases must be at most 1 token -** in size, as phrase matches are not supported without detail=full. -*/ static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){ Fts5PoslistPopulator *pRet; - pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase); + pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase); if( pRet ){ int i; memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase); for(i=0; inPhrase; i++){ Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist; Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode; - assert( pExpr->apExprPhrase[i]->nTerm<=1 ); - if( bLive && + assert( pExpr->apExprPhrase[i]->nTerm==1 ); + if( bLive && (pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof) ){ pRet[i].bMiss = 1; }else{ pBuf->n = 0; @@ -241925,21 +190389,10 @@ if( pColset->aiCol[i]==iCol ) return 1; } return 0; } -/* -** pToken is a buffer nToken bytes in size that may or may not contain -** an embedded 0x00 byte. If it does, return the number of bytes in -** the buffer before the 0x00. If it does not, return nToken. -*/ -static int fts5QueryTerm(const char *pToken, int nToken){ - int ii; - for(ii=0; iipExpr; int i; - int nQuery = nToken; - i64 iRowid = pExpr->pRoot->iRowid; UNUSED_PARAM2(iUnused1, iUnused2); - if( nQuery>FTS5_MAX_TOKEN_SIZE ) nQuery = FTS5_MAX_TOKEN_SIZE; - if( pExpr->pConfig->bTokendata ){ - nQuery = fts5QueryTerm(pToken, nQuery); - } + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE; if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; for(i=0; inPhrase; i++){ - Fts5ExprTerm *pT; + Fts5ExprTerm *pTerm; if( p->aPopulator[i].bOk==0 ) continue; - for(pT=&pExpr->apExprPhrase[i]->aTerm[0]; pT; pT=pT->pSynonym){ - if( (pT->nQueryTerm==nQuery || (pT->nQueryTermbPrefix)) - && memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0 + for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ + int nTerm = (int)strlen(pTerm->zTerm); + if( (nTerm==nToken || (nTermbPrefix)) + && memcmp(pTerm->zTerm, pToken, nTerm)==0 ){ int rc = sqlite3Fts5PoslistWriterAppend( &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff ); - if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){ - int iCol = p->iOff>>32; - int iTokOff = p->iOff & 0x7FFFFFFF; - rc = sqlite3Fts5IndexIterWriteTokendata( - pT->pIter, pToken, nToken, iRowid, iCol, iTokOff - ); - } if( rc ) return rc; break; } } } @@ -241984,13 +190426,13 @@ return SQLITE_OK; } static int sqlite3Fts5ExprPopulatePoslists( Fts5Config *pConfig, - Fts5Expr *pExpr, + Fts5Expr *pExpr, Fts5PoslistPopulator *aPopulator, - int iCol, + int iCol, const char *z, int n ){ int i; Fts5ExprCtx sCtx; sCtx.pExpr = pExpr; @@ -241998,20 +190440,20 @@ sCtx.iOff = (((i64)iCol) << 32) - 1; for(i=0; inPhrase; i++){ Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode; Fts5Colset *pColset = pNode->pNear->pColset; - if( (pColset && 0==fts5ExprColsetTest(pColset, iCol)) + if( (pColset && 0==fts5ExprColsetTest(pColset, iCol)) || aPopulator[i].bMiss ){ aPopulator[i].bOk = 0; }else{ aPopulator[i].bOk = 1; } } - return sqlite3Fts5Tokenize(pConfig, + return sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb ); } static void fts5ExprClearPoslists(Fts5ExprNode *pNode){ @@ -242027,11 +190469,10 @@ static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){ pNode->iRowid = iRowid; pNode->bEof = 0; switch( pNode->eType ){ - case 0: case FTS5_TERM: case FTS5_STRING: return (pNode->pNear->apPhrase[0]->poslist.n>0); case FTS5_AND: { @@ -242073,27 +190514,27 @@ static void sqlite3Fts5ExprCheckPoslists(Fts5Expr *pExpr, i64 iRowid){ fts5ExprCheckPoslists(pExpr->pRoot, iRowid); } /* -** This function is only called for detail=columns tables. +** This function is only called for detail=columns tables. */ static int sqlite3Fts5ExprPhraseCollist( - Fts5Expr *pExpr, - int iPhrase, - const u8 **ppCollist, + Fts5Expr *pExpr, + int iPhrase, + const u8 **ppCollist, int *pnCollist ){ Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; Fts5ExprNode *pNode = pPhrase->pNode; int rc = SQLITE_OK; assert( iPhrase>=0 && iPhrasenPhrase ); assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); - if( pNode->bEof==0 - && pNode->iRowid==pExpr->pRoot->iRowid + if( pNode->bEof==0 + && pNode->iRowid==pExpr->pRoot->iRowid && pPhrase->poslist.n>0 ){ Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; if( pTerm->pSynonym ){ Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; @@ -242110,85 +190551,10 @@ } return rc; } -/* -** Does the work of the fts5_api.xQueryToken() API method. -*/ -static int sqlite3Fts5ExprQueryToken( - Fts5Expr *pExpr, - int iPhrase, - int iToken, - const char **ppOut, - int *pnOut -){ - Fts5ExprPhrase *pPhrase = 0; - - if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){ - return SQLITE_RANGE; - } - pPhrase = pExpr->apExprPhrase[iPhrase]; - if( iToken<0 || iToken>=pPhrase->nTerm ){ - return SQLITE_RANGE; - } - - *ppOut = pPhrase->aTerm[iToken].pTerm; - *pnOut = pPhrase->aTerm[iToken].nFullTerm; - return SQLITE_OK; -} - -/* -** Does the work of the fts5_api.xInstToken() API method. -*/ -static int sqlite3Fts5ExprInstToken( - Fts5Expr *pExpr, - i64 iRowid, - int iPhrase, - int iCol, - int iOff, - int iToken, - const char **ppOut, - int *pnOut -){ - Fts5ExprPhrase *pPhrase = 0; - Fts5ExprTerm *pTerm = 0; - int rc = SQLITE_OK; - - if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){ - return SQLITE_RANGE; - } - pPhrase = pExpr->apExprPhrase[iPhrase]; - if( iToken<0 || iToken>=pPhrase->nTerm ){ - return SQLITE_RANGE; - } - pTerm = &pPhrase->aTerm[iToken]; - if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){ - rc = sqlite3Fts5IterToken( - pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm, - iRowid, iCol, iOff+iToken, ppOut, pnOut - ); - }else{ - *ppOut = pTerm->pTerm; - *pnOut = pTerm->nFullTerm; - } - return rc; -} - -/* -** Clear the token mappings for all Fts5IndexIter objects mannaged by -** the expression passed as the only argument. -*/ -static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){ - int ii; - for(ii=0; iinPhrase; ii++){ - Fts5ExprTerm *pT; - for(pT=&pExpr->apExprPhrase[ii]->aTerm[0]; pT; pT=pT->pSynonym){ - sqlite3Fts5IndexIterClearTokendata(pT->pIter); - } - } -} /* ** 2014 August 11 ** ** The author disclaims copyright to this source code. In place of @@ -242223,20 +190589,15 @@ Fts5HashEntry *pScan; /* Current ordered scan item */ Fts5HashEntry **aSlot; /* Array of hash slots */ }; /* -** Each entry in the hash table is represented by an object of the -** following type. Each object, its key, and its current data are stored -** in a single memory allocation. The key immediately follows the object -** in memory. The position list data immediately follows the key data -** in memory. -** -** The key is Fts5HashEntry.nKey bytes in size. It consists of a single -** byte identifying the index (either the main term index or a prefix-index), -** followed by the term data. For example: "0token". There is no -** nul-terminator - in this case nKey=6. +** Each entry in the hash table is represented by an object of the +** following type. Each object, its key (a nul-terminated string) and +** its current data are stored in a single memory allocation. The +** key immediately follows the object in memory. The position list +** data immediately follows the key data in memory. ** ** The data that follows the key is in a similar, but not identical format ** to the doclist data stored in the database. It is: ** ** * Rowid, as a varint @@ -242252,11 +190613,11 @@ ** Bytes of data written since iRowidOff. */ struct Fts5HashEntry { Fts5HashEntry *pHashNext; /* Next hash entry with same hash-key */ Fts5HashEntry *pScanNext; /* Next entry in sorted order */ - + int nAlloc; /* Total size of allocation */ int iSzPoslist; /* Offset of space for 4-byte poslist size */ int nData; /* Total bytes of data (incl. structure) */ int nKey; /* Length of key in bytes */ u8 bDel; /* Set delete-flag @ iSzPoslist */ @@ -242283,24 +190644,24 @@ *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash)); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ - sqlite3_int64 nByte; + int nByte; memset(pNew, 0, sizeof(Fts5Hash)); pNew->pnByte = pnByte; pNew->eDetail = pConfig->eDetail; pNew->nSlot = 1024; nByte = sizeof(Fts5HashEntry*) * pNew->nSlot; - pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc64(nByte); + pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte); if( pNew->aSlot==0 ){ sqlite3_free(pNew); *ppNew = 0; rc = SQLITE_NOMEM; }else{ - memset(pNew->aSlot, 0, (size_t)nByte); + memset(pNew->aSlot, 0, nByte); } } return rc; } @@ -242358,20 +190719,21 @@ int nNew = pHash->nSlot*2; int i; Fts5HashEntry **apNew; Fts5HashEntry **apOld = pHash->aSlot; - apNew = (Fts5HashEntry**)sqlite3_malloc64(nNew*sizeof(Fts5HashEntry*)); + apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*)); if( !apNew ) return SQLITE_NOMEM; memset(apNew, 0, nNew*sizeof(Fts5HashEntry*)); for(i=0; inSlot; i++){ while( apOld[i] ){ unsigned int iHash; Fts5HashEntry *p = apOld[i]; apOld[i] = p->pHashNext; - iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), p->nKey); + iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), + (int)strlen(fts5EntryKey(p))); p->pHashNext = apNew[iHash]; apNew[iHash] = p; } } @@ -242379,51 +190741,40 @@ pHash->nSlot = nNew; pHash->aSlot = apNew; return SQLITE_OK; } -static int fts5HashAddPoslistSize( - Fts5Hash *pHash, - Fts5HashEntry *p, - Fts5HashEntry *p2 -){ - int nRet = 0; +static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){ if( p->iSzPoslist ){ - u8 *pPtr = p2 ? (u8*)p2 : (u8*)p; - int nData = p->nData; + u8 *pPtr = (u8*)p; if( pHash->eDetail==FTS5_DETAIL_NONE ){ - assert( nData==p->iSzPoslist ); + assert( p->nData==p->iSzPoslist ); if( p->bDel ){ - pPtr[nData++] = 0x00; + pPtr[p->nData++] = 0x00; if( p->bContent ){ - pPtr[nData++] = 0x00; + pPtr[p->nData++] = 0x00; } } }else{ - int nSz = (nData - p->iSzPoslist - 1); /* Size in bytes */ + int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */ int nPos = nSz*2 + p->bDel; /* Value of nPos field */ assert( p->bDel==0 || p->bDel==1 ); if( nPos<=127 ){ pPtr[p->iSzPoslist] = (u8)nPos; }else{ int nByte = sqlite3Fts5GetVarintLen((u32)nPos); memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz); sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos); - nData += (nByte-1); + p->nData += (nByte-1); } } - nRet = nData - p->nData; - if( p2==0 ){ - p->iSzPoslist = 0; - p->bDel = 0; - p->bContent = 0; - p->nData = nData; - } - } - return nRet; + p->iSzPoslist = 0; + p->bDel = 0; + p->bContent = 0; + } } /* ** Add an entry to the in-memory hash table. The key is the concatenation ** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos). @@ -242443,30 +190794,30 @@ unsigned int iHash; Fts5HashEntry *p; u8 *pPtr; int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */ int bNew; /* If non-delete entry should be written */ - + bNew = (pHash->eDetail==FTS5_DETAIL_FULL); /* Attempt to locate an existing hash entry */ iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ char *zKey = fts5EntryKey(p); - if( zKey[0]==bByte - && p->nKey==nToken+1 - && memcmp(&zKey[1], pToken, nToken)==0 + if( zKey[0]==bByte + && p->nKey==nToken + && memcmp(&zKey[1], pToken, nToken)==0 ){ break; } } /* If an existing hash entry cannot be found, create a new one. */ if( p==0 ){ /* Figure out how much space to allocate */ char *zKey; - sqlite3_int64 nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64; + int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64; if( nByte<128 ) nByte = 128; /* Grow the Fts5Hash.aSlot[] array if necessary. */ if( (pHash->nEntry*2)>=pHash->nSlot ){ int rc = fts5HashResize(pHash); @@ -242473,21 +190824,21 @@ if( rc!=SQLITE_OK ) return rc; iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); } /* Allocate new Fts5HashEntry and add it to the hash table. */ - p = (Fts5HashEntry*)sqlite3_malloc64(nByte); + p = (Fts5HashEntry*)sqlite3_malloc(nByte); if( !p ) return SQLITE_NOMEM; memset(p, 0, sizeof(Fts5HashEntry)); - p->nAlloc = (int)nByte; + p->nAlloc = nByte; zKey = fts5EntryKey(p); zKey[0] = bByte; memcpy(&zKey[1], pToken, nToken); assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) ); - p->nKey = nToken+1; + p->nKey = nToken; zKey[nToken+1] = '\0'; - p->nData = nToken+1 + sizeof(Fts5HashEntry); + p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry); p->pHashNext = pHash->aSlot[iHash]; pHash->aSlot[iHash] = p; pHash->nEntry++; /* Add the first rowid field to the hash-entry */ @@ -242498,29 +190849,30 @@ if( pHash->eDetail!=FTS5_DETAIL_NONE ){ p->nData += 1; p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1); } + nIncr += p->nData; }else{ - /* Appending to an existing hash-entry. Check that there is enough - ** space to append the largest possible new entry. Worst case scenario + /* Appending to an existing hash-entry. Check that there is enough + ** space to append the largest possible new entry. Worst case scenario ** is: ** ** + 9 bytes for a new rowid, ** + 4 byte reserved for the "poslist size" varint. ** + 1 byte for a "new column" byte, ** + 3 bytes for a new column number (16-bit max) as a varint, ** + 5 bytes for the new position offset (32-bit max). */ if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){ - sqlite3_int64 nNew = p->nAlloc * 2; + int nNew = p->nAlloc * 2; Fts5HashEntry *pNew; Fts5HashEntry **pp; - pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew); + pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew); if( pNew==0 ) return SQLITE_NOMEM; - pNew->nAlloc = (int)nNew; + pNew->nAlloc = nNew; for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext); *pp = pNew; p = pNew; } nIncr -= p->nData; @@ -242530,13 +190882,12 @@ pPtr = (u8*)p; /* If this is a new rowid, append the 4-byte size field for the previous ** entry, and the new rowid for this entry. */ if( iRowid!=p->iRowid ){ - u64 iDiff = (u64)iRowid - (u64)p->iRowid; - fts5HashAddPoslistSize(pHash, p, 0); - p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff); + fts5HashAddPoslistSize(pHash, p); + p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid); p->iRowid = iRowid; bNew = 1; p->iSzPoslist = p->nData; if( pHash->eDetail!=FTS5_DETAIL_NONE ){ p->nData += 1; @@ -242548,11 +190899,11 @@ if( iCol>=0 ){ if( pHash->eDetail==FTS5_DETAIL_NONE ){ p->bContent = 1; }else{ /* Append a new column value, if necessary */ - assert_nc( iCol>=p->iCol ); + assert( iCol>=p->iCol ); if( iCol!=p->iCol ){ if( pHash->eDetail==FTS5_DETAIL_FULL ){ pPtr[p->nData++] = 0x01; p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol); p->iCol = (i16)iCol; @@ -242600,21 +190951,16 @@ p2 = 0; }else if( p2==0 ){ *ppOut = p1; p1 = 0; }else{ + int i = 0; char *zKey1 = fts5EntryKey(p1); char *zKey2 = fts5EntryKey(p2); - int nMin = MIN(p1->nKey, p2->nKey); - - int cmp = memcmp(zKey1, zKey2, nMin); - if( cmp==0 ){ - cmp = p1->nKey - p2->nKey; - } - assert( cmp!=0 ); - - if( cmp>0 ){ + while( zKey1[i]==zKey2[i] ) i++; + + if( ((u8)zKey1[i])>((u8)zKey2[i]) ){ /* p2 is smaller */ *ppOut = p2; ppOut = &p2->pScanNext; p2 = p2->pScanNext; }else{ @@ -242629,15 +190975,17 @@ return pRet; } /* -** Link all tokens from hash table iHash into a list in sorted order. The -** tokens are not removed from the hash table. +** Extract all tokens from hash table iHash and link them into a list +** in sorted order. The hash table is cleared before returning. It is +** the responsibility of the caller to free the elements of the returned +** list. */ static int fts5HashEntrySort( - Fts5Hash *pHash, + Fts5Hash *pHash, const char *pTerm, int nTerm, /* Query prefix, if any */ Fts5HashEntry **ppSorted ){ const int nMergeSlot = 32; Fts5HashEntry **ap; @@ -242644,20 +190992,18 @@ Fts5HashEntry *pList; int iSlot; int i; *ppSorted = 0; - ap = sqlite3_malloc64(sizeof(Fts5HashEntry*) * nMergeSlot); + ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot); if( !ap ) return SQLITE_NOMEM; memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot); for(iSlot=0; iSlotnSlot; iSlot++){ Fts5HashEntry *pIter; for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){ - if( pTerm==0 - || (pIter->nKey>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) - ){ + if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){ Fts5HashEntry *pEntry = pIter; pEntry->pScanNext = 0; for(i=0; ap[i]; i++){ pEntry = fts5HashEntryMerge(pEntry, ap[i]); ap[i] = 0; @@ -242670,10 +191016,11 @@ pList = 0; for(i=0; inEntry = 0; sqlite3_free(ap); *ppSorted = pList; return SQLITE_OK; } @@ -242680,39 +191027,29 @@ /* ** Query the hash table for a doclist associated with term pTerm/nTerm. */ static int sqlite3Fts5HashQuery( Fts5Hash *pHash, /* Hash table to query */ - int nPre, const char *pTerm, int nTerm, /* Query term */ - void **ppOut, /* OUT: Pointer to new object */ + const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ int *pnDoclist /* OUT: Size of doclist in bytes */ ){ unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm); char *zKey = 0; Fts5HashEntry *p; for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ zKey = fts5EntryKey(p); - if( nTerm==p->nKey && memcmp(zKey, pTerm, nTerm)==0 ) break; + if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break; } if( p ){ - int nHashPre = sizeof(Fts5HashEntry) + nTerm; - int nList = p->nData - nHashPre; - u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10)); - if( pRet ){ - Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre]; - memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList); - nList += fts5HashAddPoslistSize(pHash, p, pFaux); - *pnDoclist = nList; - }else{ - *pnDoclist = 0; - return SQLITE_NOMEM; - } - }else{ - *ppOut = 0; + fts5HashAddPoslistSize(pHash, p); + *ppDoclist = (const u8*)&zKey[nTerm+1]; + *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); + }else{ + *ppDoclist = 0; *pnDoclist = 0; } return SQLITE_OK; } @@ -242722,32 +191059,10 @@ const char *pTerm, int nTerm /* Query prefix */ ){ return fts5HashEntrySort(p, pTerm, nTerm, &p->pScan); } -#ifdef SQLITE_DEBUG -static int fts5HashCount(Fts5Hash *pHash){ - int nEntry = 0; - int ii; - for(ii=0; iinSlot; ii++){ - Fts5HashEntry *p = 0; - for(p=pHash->aSlot[ii]; p; p=p->pHashNext){ - nEntry++; - } - } - return nEntry; -} -#endif - -/* -** Return true if the hash table is empty, false otherwise. -*/ -static int sqlite3Fts5HashIsEmpty(Fts5Hash *pHash){ - assert( pHash->nEntry==fts5HashCount(pHash) ); - return pHash->nEntry==0; -} - static void sqlite3Fts5HashScanNext(Fts5Hash *p){ assert( !sqlite3Fts5HashScanEof(p) ); p->pScan = p->pScan->pScanNext; } @@ -242756,30 +191071,28 @@ } static void sqlite3Fts5HashScanEntry( Fts5Hash *pHash, const char **pzTerm, /* OUT: term (nul-terminated) */ - int *pnTerm, /* OUT: Size of term in bytes */ const u8 **ppDoclist, /* OUT: pointer to doclist */ int *pnDoclist /* OUT: size of doclist in bytes */ ){ Fts5HashEntry *p; if( (p = pHash->pScan) ){ char *zKey = fts5EntryKey(p); - int nTerm = p->nKey; - fts5HashAddPoslistSize(pHash, p, 0); + int nTerm = (int)strlen(zKey); + fts5HashAddPoslistSize(pHash, p); *pzTerm = zKey; - *pnTerm = nTerm; - *ppDoclist = (const u8*)&zKey[nTerm]; - *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm); + *ppDoclist = (const u8*)&zKey[nTerm+1]; + *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); }else{ *pzTerm = 0; - *pnTerm = 0; *ppDoclist = 0; *pnDoclist = 0; } } + /* ** 2014 May 31 ** ** The author disclaims copyright to this source code. In place of @@ -242789,11 +191102,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** -** Low level access to the FTS index stored in the database file. The +** Low level access to the FTS index stored in the database file. The ** routines in this file file implement all read and write access to the ** %_data table. Other parts of the system access this functionality via ** the interface defined in fts5Int.h. */ @@ -242805,14 +191118,14 @@ ** ** The %_data table contains all the FTS indexes for an FTS5 virtual table. ** As well as the main term index, there may be up to 31 prefix indexes. ** The format is similar to FTS3/4, except that: ** -** * all segment b-tree leaf data is stored in fixed size page records -** (e.g. 1000 bytes). A single doclist may span multiple pages. Care is -** taken to ensure it is possible to iterate in either direction through -** the entries in a doclist, or to seek to a specific entry within a +** * all segment b-tree leaf data is stored in fixed size page records +** (e.g. 1000 bytes). A single doclist may span multiple pages. Care is +** taken to ensure it is possible to iterate in either direction through +** the entries in a doclist, or to seek to a specific entry within a ** doclist, without loading it into memory. ** ** * large doclists that span many pages have associated "doclist index" ** records that contain a copy of the first rowid on each page spanned by ** the doclist. This is used to speed up seek operations, and merges of @@ -242833,52 +191146,32 @@ #if FTS5_MAX_PREFIX_INDEXES > 31 # error "FTS5_MAX_PREFIX_INDEXES is too large" #endif -#define FTS5_MAX_LEVEL 64 - -/* -** There are two versions of the format used for the structure record: -** -** 1. the legacy format, that may be read by all fts5 versions, and -** -** 2. the V2 format, which is used by contentless_delete=1 databases. -** -** Both begin with a 4-byte "configuration cookie" value. Then, a legacy -** format structure record contains a varint - the number of levels in -** the structure. Whereas a V2 structure record contains the constant -** 4 bytes [0xff 0x00 0x00 0x01]. This is unambiguous as the value of a -** varint has to be at least 16256 to begin with "0xFF". And the default -** maximum number of levels is 64. -** -** See below for more on structure record formats. -*/ -#define FTS5_STRUCTURE_V2 "\xFF\x00\x00\x01" - /* ** Details: ** ** The %_data table managed by this module, ** ** CREATE TABLE %_data(id INTEGER PRIMARY KEY, block BLOB); ** -** , contains the following 6 types of records. See the comments surrounding -** the FTS5_*_ROWID macros below for a description of how %_data rowids are +** , contains the following 5 types of records. See the comments surrounding +** the FTS5_*_ROWID macros below for a description of how %_data rowids are ** assigned to each fo them. ** ** 1. Structure Records: ** ** The set of segments that make up an index - the index structure - are ** recorded in a single record within the %_data table. The record consists -** of a single 32-bit configuration cookie value followed by a list of -** SQLite varints. +** of a single 32-bit configuration cookie value followed by a list of +** SQLite varints. If the FTS table features more than one index (because +** there are one or more prefix indexes), it is guaranteed that all share +** the same cookie value. ** -** If the structure record is a V2 record, the configuration cookie is -** followed by the following 4 bytes: [0xFF 0x00 0x00 0x01]. -** -** Next, the record continues with three varints: +** Immediately following the configuration cookie, the record begins with +** three varints: ** ** + number of levels, ** + total number of segments on all levels, ** + value of write counter. ** @@ -242889,16 +191182,10 @@ ** + for each segment from oldest to newest: ** + segment id (always > 0) ** + first leaf page number (often 1, always greater than 0) ** + final leaf page number ** -** Then, for V2 structures only: -** -** + lower origin counter value, -** + upper origin counter value, -** + the number of tombstone hash pages. -** ** 2. The Averages Record: ** ** A single record within the %_data table. The data is a list of varints. ** The first value is the number of rows in the index. Then, for each column ** from left to right, the total number of tokens in the column for all @@ -242906,11 +191193,11 @@ ** ** 3. Segment leaves: ** ** TERM/DOCLIST FORMAT: ** -** Most of each segment leaf is taken up by term/doclist data. The +** Most of each segment leaf is taken up by term/doclist data. The ** general format of term/doclist, starting with the first term ** on the leaf page, is: ** ** varint : size of first term ** blob: first term data @@ -242949,11 +191236,11 @@ ** varint: offset delta + 2 ** } ** ** PAGE FORMAT ** -** Each leaf page begins with a 4-byte header containing 2 16-bit +** Each leaf page begins with a 4-byte header containing 2 16-bit ** unsigned integer fields in big-endian format. They are: ** ** * The byte offset of the first rowid on the page, if it exists ** and occurs before the first term (otherwise 0). ** @@ -242984,22 +191271,22 @@ ** blob: first term data ** ** 5. Segment doclist indexes: ** ** Doclist indexes are themselves b-trees, however they usually consist of -** a single leaf record only. The format of each doclist index leaf page +** a single leaf record only. The format of each doclist index leaf page ** is: ** ** * Flags byte. Bits are: ** 0x01: Clear if leaf is also the root page, otherwise set. ** ** * Page number of fts index leaf page. As a varint. ** ** * First rowid on page indicated by previous field. As a varint. ** -** * A list of varints, one for each subsequent termless page. A -** positive delta if the termless page contains at least one rowid, +** * A list of varints, one for each subsequent termless page. A +** positive delta if the termless page contains at least one rowid, ** or an 0x00 byte otherwise. ** ** Internal doclist index nodes are: ** ** * Flags byte. Bits are: @@ -243008,44 +191295,12 @@ ** * Page number of first child page. As a varint. ** ** * Copy of first rowid on page indicated by previous field. As a varint. ** ** * A list of delta-encoded varints - the first rowid on each subsequent -** child page. -** -** 6. Tombstone Hash Page -** -** These records are only ever present in contentless_delete=1 tables. -** There are zero or more of these associated with each segment. They -** are used to store the tombstone rowids for rows contained in the -** associated segments. -** -** The set of nHashPg tombstone hash pages associated with a single -** segment together form a single hash table containing tombstone rowids. -** To find the page of the hash on which a key might be stored: -** -** iPg = (rowid % nHashPg) -** -** Then, within page iPg, which has nSlot slots: -** -** iSlot = (rowid / nHashPg) % nSlot -** -** Each tombstone hash page begins with an 8 byte header: -** -** 1-byte: Key-size (the size in bytes of each slot). Either 4 or 8. -** 1-byte: rowid-0-tombstone flag. This flag is only valid on the -** first tombstone hash page for each segment (iPg=0). If set, -** the hash table contains rowid 0. If clear, it does not. -** Rowid 0 is handled specially. -** 2-bytes: unused. -** 4-bytes: Big-endian integer containing number of entries on page. -** -** Following this are nSlot 4 or 8 byte slots (depending on the key-size -** in the first byte of the page header). The number of slots may be -** determined based on the size of the page record and the key-size: -** -** nSlot = (nByte - 8) / key-size +** child page. +** */ /* ** Rowids for the averages and structure records in the %_data table. */ @@ -243057,11 +191312,11 @@ ** and nodes. All nodes and leaves are stored in the %_data table with large ** positive rowids. ** ** Each segment has a unique non-zero 16-bit id. ** -** The rowid for each segment leaf is found by passing the segment id and +** The rowid for each segment leaf is found by passing the segment id and ** the leaf page number to the FTS5_SEGMENT_ROWID macro. Leaves are numbered ** sequentially starting from 1. */ #define FTS5_DATA_ID_B 16 /* Max seg id number 65535 */ #define FTS5_DATA_DLI_B 1 /* Doclist-index flag (1 bit) */ @@ -243075,11 +191330,15 @@ ((i64)(pgno)) \ ) #define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno) #define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno) -#define FTS5_TOMBSTONE_ROWID(segid,ipg) fts5_dri(segid+(1<<16), 0, 0, ipg) + +/* +** Maximum segments permitted in a single index +*/ +#define FTS5_MAX_SEGMENT 2000 #ifdef SQLITE_DEBUG static int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; } #endif @@ -243102,28 +191361,19 @@ typedef struct Fts5DoclistIter Fts5DoclistIter; typedef struct Fts5SegWriter Fts5SegWriter; typedef struct Fts5Structure Fts5Structure; typedef struct Fts5StructureLevel Fts5StructureLevel; typedef struct Fts5StructureSegment Fts5StructureSegment; -typedef struct Fts5TokenDataIter Fts5TokenDataIter; -typedef struct Fts5TokenDataMap Fts5TokenDataMap; -typedef struct Fts5TombstoneArray Fts5TombstoneArray; struct Fts5Data { u8 *p; /* Pointer to buffer containing record */ int nn; /* Size of record in bytes */ int szLeaf; /* Size of leaf without page-index */ }; /* ** One object per %_data table. -** -** nContentlessDelete: -** The number of contentless delete operations since the most recent -** call to fts5IndexFlush() or fts5IndexDiscardData(). This is tracked -** so that extra auto-merge work can be done by fts5IndexFlush() to -** account for the delete operations. */ struct Fts5Index { Fts5Config *pConfig; /* Virtual table configuration */ char *zDataTbl; /* Name of %_data table */ int nWorkUnit; /* Leaf pages in a "unit" of work */ @@ -243134,29 +191384,23 @@ */ Fts5Hash *pHash; /* Hash table for in-memory data */ int nPendingData; /* Current bytes of pending data */ i64 iWriteRowid; /* Rowid for current doc being written */ int bDelete; /* Current write is a delete */ - int nContentlessDelete; /* Number of contentless delete ops */ - int nPendingRow; /* Number of INSERT in hash table */ /* Error state. */ int rc; /* Current error code */ - int flushRc; /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ - sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ + sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */ sqlite3_stmt *pIdxSelect; - sqlite3_stmt *pIdxNextSelect; int nRead; /* Total number of blocks read */ - sqlite3_stmt *pDeleteFromIdx; - sqlite3_stmt *pDataVersion; i64 iStructVersion; /* data_version when pStruct read */ Fts5Structure *pStruct; /* Current db structure (or NULL) */ }; @@ -243170,39 +191414,26 @@ int nSize; }; /* ** The contents of the "structure" record for each index are represented -** using an Fts5Structure record in memory. Which uses instances of the +** using an Fts5Structure record in memory. Which uses instances of the ** other Fts5StructureXXX types as components. -** -** nOriginCntr: -** This value is set to non-zero for structure records created for -** contentlessdelete=1 tables only. In that case it represents the -** origin value to apply to the next top-level segment created. */ struct Fts5StructureSegment { int iSegid; /* Segment id */ int pgnoFirst; /* First leaf page number in segment */ int pgnoLast; /* Last leaf page number in segment */ - - /* contentlessdelete=1 tables only: */ - u64 iOrigin1; - u64 iOrigin2; - int nPgTombstone; /* Number of tombstone hash table pages */ - u64 nEntryTombstone; /* Number of tombstone entries that "count" */ - u64 nEntry; /* Number of rows in this segment */ }; struct Fts5StructureLevel { int nMerge; /* Number of segments in incr-merge */ int nSeg; /* Total number of segments on level */ Fts5StructureSegment *aSeg; /* Array of segments. aSeg[0] is oldest. */ }; struct Fts5Structure { int nRef; /* Object reference count */ u64 nWriteCounter; /* Total leaves written to level 0 */ - u64 nOriginCntr; /* Origin value for next top-level segment */ int nSegment; /* Total segments in this structure */ int nLevel; /* Number of levels in this index */ Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */ }; @@ -243256,12 +191487,15 @@ ** ** iLeafPgno: ** Current leaf page number within segment. ** ** iLeafOffset: -** Byte offset within the current leaf that is the first byte of the +** Byte offset within the current leaf that is the first byte of the ** position list data (one byte passed the position-list size field). +** rowid field of the current entry. Usually this is the size field of the +** position list data. The exception is if the rowid for the current entry +** is the last thing on the leaf page. ** ** pLeaf: ** Buffer containing current leaf page data. Set to NULL at EOF. ** ** iTermLeafPgno, iTermLeafOffset: @@ -243270,11 +191504,11 @@ ** ** flags: ** Mask of FTS5_SEGITER_XXX values. Interpreted as follows: ** ** FTS5_SEGITER_ONETERM: -** If set, set the iterator to point to EOF after the current doclist +** If set, set the iterator to point to EOF after the current doclist ** has been exhausted. Do not proceed to the next term in the segment. ** ** FTS5_SEGITER_REVERSE: ** This flag is only ever set if FTS5_SEGITER_ONETERM is also set. If ** it is set, iterate through rowid in descending order instead of the @@ -243287,31 +191521,23 @@ ** corresponding aRowidOffset[] entry is set to the byte offset of the ** start of the "position-list-size" field within the page. ** ** iTermIdx: ** Index of current term on iTermLeafPgno. -** -** apTombstone/nTombstone: -** These are used for contentless_delete=1 tables only. When the cursor -** is first allocated, the apTombstone[] array is allocated so that it -** is large enough for all tombstones hash pages associated with the -** segment. The pages themselves are loaded lazily from the database as -** they are required. */ struct Fts5SegIter { Fts5StructureSegment *pSeg; /* Segment to iterate through */ int flags; /* Mask of configuration flags */ int iLeafPgno; /* Current leaf page number */ Fts5Data *pLeaf; /* Current leaf data */ Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */ - i64 iLeafOffset; /* Byte offset within current leaf */ - Fts5TombstoneArray *pTombArray; /* Array of tombstone pages */ + int iLeafOffset; /* Byte offset within current leaf */ /* Next method */ void (*xNext)(Fts5Index*, Fts5SegIter*, int*); - /* The page and offset from which the current term was read. The offset + /* The page and offset from which the current term was read. The offset ** is the offset of the first rowid in the current doclist. */ int iTermLeafPgno; int iTermLeafOffset; int iPgidxOff; /* Next offset in pgidx */ @@ -243330,30 +191556,21 @@ int nPos; /* Number of bytes in current position list */ u8 bDel; /* True if the delete flag is set */ }; /* -** Array of tombstone pages. Reference counted. -*/ -struct Fts5TombstoneArray { - int nRef; /* Number of pointers to this object */ - int nTombstone; - Fts5Data *apTombstone[1]; /* Array of tombstone pages */ -}; - -/* -** Argument is a pointer to an Fts5Data structure that contains a +** Argument is a pointer to an Fts5Data structure that contains a ** leaf page. */ #define ASSERT_SZLEAF_OK(x) assert( \ (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \ ) #define FTS5_SEGITER_ONETERM 0x01 #define FTS5_SEGITER_REVERSE 0x02 -/* +/* ** Argument is a pointer to an Fts5Data structure that contains a leaf ** page. This macro evaluates to true if the leaf contains no terms, or ** false if it contains at least one term. */ #define fts5LeafIsTermless(x) ((x)->szLeaf >= (x)->nn) @@ -243371,33 +191588,27 @@ ** aFirst[] arrays are sized at nSeg entries. The aSeg[] array is padded ** with zeroed objects - these are handled as if they were iterators opened ** on empty segments. ** ** The results of comparing segments aSeg[N] and aSeg[N+1], where N is an -** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the +** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the ** comparison in this context is the index of the iterator that currently ** points to the smaller term/rowid combination. Iterators at EOF are ** considered to be greater than all other iterators. ** ** aFirst[1] contains the index in aSeg[] of the iterator that points to -** the smallest key overall. aFirst[0] is unused. +** the smallest key overall. aFirst[0] is unused. ** ** poslist: ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. ** There is no way to tell if this is populated or not. -** -** pColset: -** If not NULL, points to an object containing a set of column indices. -** Only matches that occur in one of these columns will be returned. -** The Fts5Iter does not own the Fts5Colset object, and so it is not -** freed when the iterator is closed - it is owned by the upper layer. */ struct Fts5Iter { Fts5IndexIter base; /* Base class containing output vars */ - Fts5TokenDataIter *pTokenDataIter; Fts5Index *pIndex; /* Index that owns this iterator */ + Fts5Structure *pStruct; /* Database structure for this iterator */ Fts5Buffer poslist; /* Buffer containing current poslist */ Fts5Colset *pColset; /* Restrict matches to these columns */ /* Invoked to set output variables. */ void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*); @@ -243408,10 +191619,11 @@ i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ Fts5CResult *aFirst; /* Current merge state (see above) */ Fts5SegIter aSeg[1]; /* Array of segment iterators */ }; + /* ** An instance of the following type is used to iterate through the contents ** of a doclist-index record. ** @@ -243445,73 +191657,19 @@ aOut[1] = (iVal&0xFF); } static u16 fts5GetU16(const u8 *aIn){ return ((u16)aIn[0] << 8) + aIn[1]; -} - -/* -** The only argument points to a buffer at least 8 bytes in size. This -** function interprets the first 8 bytes of the buffer as a 64-bit big-endian -** unsigned integer and returns the result. -*/ -static u64 fts5GetU64(u8 *a){ - return ((u64)a[0] << 56) - + ((u64)a[1] << 48) - + ((u64)a[2] << 40) - + ((u64)a[3] << 32) - + ((u64)a[4] << 24) - + ((u64)a[5] << 16) - + ((u64)a[6] << 8) - + ((u64)a[7] << 0); -} - -/* -** The only argument points to a buffer at least 4 bytes in size. This -** function interprets the first 4 bytes of the buffer as a 32-bit big-endian -** unsigned integer and returns the result. -*/ -static u32 fts5GetU32(const u8 *a){ - return ((u32)a[0] << 24) - + ((u32)a[1] << 16) - + ((u32)a[2] << 8) - + ((u32)a[3] << 0); -} - -/* -** Write iVal, formated as a 64-bit big-endian unsigned integer, to the -** buffer indicated by the first argument. -*/ -static void fts5PutU64(u8 *a, u64 iVal){ - a[0] = ((iVal >> 56) & 0xFF); - a[1] = ((iVal >> 48) & 0xFF); - a[2] = ((iVal >> 40) & 0xFF); - a[3] = ((iVal >> 32) & 0xFF); - a[4] = ((iVal >> 24) & 0xFF); - a[5] = ((iVal >> 16) & 0xFF); - a[6] = ((iVal >> 8) & 0xFF); - a[7] = ((iVal >> 0) & 0xFF); -} - -/* -** Write iVal, formated as a 32-bit big-endian unsigned integer, to the -** buffer indicated by the first argument. -*/ -static void fts5PutU32(u8 *a, u32 iVal){ - a[0] = ((iVal >> 24) & 0xFF); - a[1] = ((iVal >> 16) & 0xFF); - a[2] = ((iVal >> 8) & 0xFF); - a[3] = ((iVal >> 0) & 0xFF); -} +} /* ** Allocate and return a buffer at least nByte bytes in size. ** ** If an OOM error is encountered, return NULL and set the error code in ** the Fts5Index handle passed as the first argument. */ -static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){ +static void *fts5IdxMalloc(Fts5Index *p, int nByte){ return sqlite3Fts5MallocZero(&p->rc, nByte); } /* ** Compare the contents of the pLeft buffer with the pRight/nRight blob. @@ -243540,15 +191698,12 @@ ** +ve if pRight is smaller than pLeft. In other words: ** ** res = *pLeft - *pRight */ static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){ - int nCmp, res; - nCmp = MIN(pLeft->n, pRight->n); - assert( nCmp<=0 || pLeft->p!=0 ); - assert( nCmp<=0 || pRight->p!=0 ); - res = fts5Memcmp(pLeft->p, pRight->p, nCmp); + int nCmp = MIN(pLeft->n, pRight->n); + int res = memcmp(pLeft->p, pRight->p, nCmp); return (res==0 ? (pLeft->n - pRight->n) : res); } static int fts5LeafFirstTermOff(Fts5Data *pLeaf){ int ret; @@ -243557,24 +191712,22 @@ } /* ** Close the read-only blob handle, if it is open. */ -static void fts5IndexCloseReader(Fts5Index *p){ +static void fts5CloseReader(Fts5Index *p){ if( p->pReader ){ - int rc; sqlite3_blob *pReader = p->pReader; p->pReader = 0; - rc = sqlite3_blob_close(pReader); - if( p->rc==SQLITE_OK ) p->rc = rc; + sqlite3_blob_close(pReader); } } /* ** Retrieve a record from the %_data table. ** -** If an error occurs, NULL is returned and an error left in the +** If an error occurs, NULL is returned and an error left in the ** Fts5Index object. */ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = 0; if( p->rc==SQLITE_OK ){ @@ -243588,40 +191741,39 @@ p->pReader = 0; rc = sqlite3_blob_reopen(pBlob, iRowid); assert( p->pReader==0 ); p->pReader = pBlob; if( rc!=SQLITE_OK ){ - fts5IndexCloseReader(p); + fts5CloseReader(p); } if( rc==SQLITE_ABORT ) rc = SQLITE_OK; } - /* If the blob handle is not open at this point, open it and seek + /* If the blob handle is not open at this point, open it and seek ** to the requested entry. */ if( p->pReader==0 && rc==SQLITE_OK ){ Fts5Config *pConfig = p->pConfig; - rc = sqlite3_blob_open(pConfig->db, + rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader ); } /* If either of the sqlite3_blob_open() or sqlite3_blob_reopen() calls ** above returned SQLITE_ERROR, return SQLITE_CORRUPT_VTAB instead. ** All the reasons those functions might return SQLITE_ERROR - missing - ** table, missing row, non-blob/text in block column - indicate + ** table, missing row, non-blob/text in block column - indicate ** backing store corruption. */ if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT; if( rc==SQLITE_OK ){ u8 *aOut = 0; /* Read blob data into this buffer */ int nByte = sqlite3_blob_bytes(p->pReader); - int szData = (sizeof(Fts5Data) + 7) & ~7; - sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING; - pRet = (Fts5Data*)sqlite3_malloc64(nAlloc); + int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING; + pRet = (Fts5Data*)sqlite3_malloc(nAlloc); if( pRet ){ pRet->nn = nByte; - aOut = pRet->p = (u8*)pRet + szData; + aOut = pRet->p = (u8*)&pRet[1]; }else{ rc = SQLITE_NOMEM; } if( rc==SQLITE_OK ){ @@ -243630,24 +191782,20 @@ if( rc!=SQLITE_OK ){ sqlite3_free(pRet); pRet = 0; }else{ /* TODO1: Fix this */ - pRet->p[nByte] = 0x00; - pRet->p[nByte+1] = 0x00; pRet->szLeaf = fts5GetU16(&pRet->p[2]); } } p->rc = rc; p->nRead++; } assert( (pRet==0)==(p->rc!=SQLITE_OK) ); - assert( pRet==0 || EIGHT_BYTE_ALIGNMENT( pRet->p ) ); return pRet; } - /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). */ @@ -243656,11 +191804,11 @@ } static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = fts5DataRead(p, iRowid); if( pRet ){ - if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){ + if( pRet->szLeaf>pRet->nn ){ p->rc = FTS5_CORRUPT; fts5DataRelease(pRet); pRet = 0; } } @@ -243672,17 +191820,12 @@ sqlite3_stmt **ppStmt, char *zSql ){ if( p->rc==SQLITE_OK ){ if( zSql ){ - int rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1, - SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB, - ppStmt, 0); - /* If this prepare() call fails with SQLITE_ERROR, then one of the - ** %_idx or %_data tables has been removed or modified. Call this - ** corruption. */ - p->rc = (rc==SQLITE_ERROR ? SQLITE_CORRUPT : rc); + p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, ppStmt, 0); }else{ p->rc = SQLITE_NOMEM; } } sqlite3_free(zSql); @@ -243697,21 +191840,20 @@ if( p->rc!=SQLITE_OK ) return; if( p->pWriter==0 ){ Fts5Config *pConfig = p->pConfig; fts5IndexPrepareStmt(p, &p->pWriter, sqlite3_mprintf( - "REPLACE INTO '%q'.'%q_data'(id, block) VALUES(?,?)", + "REPLACE INTO '%q'.'%q_data'(id, block) VALUES(?,?)", pConfig->zDb, pConfig->zName )); if( p->rc ) return; } sqlite3_bind_int64(p->pWriter, 1, iRowid); sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC); sqlite3_step(p->pWriter); p->rc = sqlite3_reset(p->pWriter); - sqlite3_bind_null(p->pWriter, 2); } /* ** Execute the following SQL: ** @@ -243719,16 +191861,27 @@ */ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){ if( p->rc!=SQLITE_OK ) return; if( p->pDeleter==0 ){ + int rc; Fts5Config *pConfig = p->pConfig; char *zSql = sqlite3_mprintf( - "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?", + "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?", pConfig->zDb, pConfig->zName ); - if( fts5IndexPrepareStmt(p, &p->pDeleter, zSql) ) return; + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0); + sqlite3_free(zSql); + } + if( rc!=SQLITE_OK ){ + p->rc = rc; + return; + } } sqlite3_bind_int64(p->pDeleter, 1, iFirst); sqlite3_bind_int64(p->pDeleter, 2, iLast); sqlite3_step(p->pDeleter); @@ -243736,21 +191889,14 @@ } /* ** Remove all records associated with segment iSegid. */ -static void fts5DataRemoveSegment(Fts5Index *p, Fts5StructureSegment *pSeg){ - int iSegid = pSeg->iSegid; +static void fts5DataRemoveSegment(Fts5Index *p, int iSegid){ i64 iFirst = FTS5_SEGMENT_ROWID(iSegid, 0); i64 iLast = FTS5_SEGMENT_ROWID(iSegid+1, 0)-1; fts5DataDelete(p, iFirst, iLast); - - if( pSeg->nPgTombstone ){ - i64 iTomb1 = FTS5_TOMBSTONE_ROWID(iSegid, 0); - i64 iTomb2 = FTS5_TOMBSTONE_ROWID(iSegid, pSeg->nPgTombstone-1); - fts5DataDelete(p, iTomb1, iTomb2); - } if( p->pIdxDeleter==0 ){ Fts5Config *pConfig = p->pConfig; fts5IndexPrepareStmt(p, &p->pIdxDeleter, sqlite3_mprintf( "DELETE FROM '%q'.'%q_idx' WHERE segid=?", pConfig->zDb, pConfig->zName @@ -243762,11 +191908,11 @@ p->rc = sqlite3_reset(p->pIdxDeleter); } } /* -** Release a reference to an Fts5Structure object returned by an earlier +** Release a reference to an Fts5Structure object returned by an earlier ** call to fts5StructureRead() or fts5StructureDecode(). */ static void fts5StructureRelease(Fts5Structure *pStruct){ if( pStruct && 0>=(--pStruct->nRef) ){ int i; @@ -243780,62 +191926,10 @@ static void fts5StructureRef(Fts5Structure *pStruct){ pStruct->nRef++; } -static void *sqlite3Fts5StructureRef(Fts5Index *p){ - fts5StructureRef(p->pStruct); - return (void*)p->pStruct; -} -static void sqlite3Fts5StructureRelease(void *p){ - if( p ){ - fts5StructureRelease((Fts5Structure*)p); - } -} -static int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){ - if( p->pStruct!=(Fts5Structure*)pStruct ){ - return SQLITE_ABORT; - } - return SQLITE_OK; -} - -/* -** Ensure that structure object (*pp) is writable. -** -** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If -** an error occurs, (*pRc) is set to an SQLite error code before returning. -*/ -static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){ - Fts5Structure *p = *pp; - if( *pRc==SQLITE_OK && p->nRef>1 ){ - i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel); - Fts5Structure *pNew; - pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte); - if( pNew ){ - int i; - memcpy(pNew, p, nByte); - for(i=0; inLevel; i++) pNew->aLevel[i].aSeg = 0; - for(i=0; inLevel; i++){ - Fts5StructureLevel *pLvl = &pNew->aLevel[i]; - nByte = sizeof(Fts5StructureSegment) * pNew->aLevel[i].nSeg; - pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(pRc, nByte); - if( pLvl->aSeg==0 ){ - for(i=0; inLevel; i++){ - sqlite3_free(pNew->aLevel[i].aSeg); - } - sqlite3_free(pNew); - return; - } - memcpy(pLvl->aSeg, p->aLevel[i].aSeg, nByte); - } - p->nRef--; - pNew->nRef = 1; - } - *pp = pNew; - } -} - /* ** Deserialize and return the structure record currently stored in serialized ** form within buffer pData/nData. ** ** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array @@ -243855,34 +191949,21 @@ int rc = SQLITE_OK; int i = 0; int iLvl; int nLevel = 0; int nSegment = 0; - sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */ + int nByte; /* Bytes of space to allocate at pRet */ Fts5Structure *pRet = 0; /* Structure object to return */ - int bStructureV2 = 0; /* True for FTS5_STRUCTURE_V2 */ - u64 nOriginCntr = 0; /* Largest origin value seen so far */ /* Grab the cookie value */ if( piCookie ) *piCookie = sqlite3Fts5Get32(pData); i = 4; - /* Check if this is a V2 structure record. Set bStructureV2 if it is. */ - if( 0==memcmp(&pData[i], FTS5_STRUCTURE_V2, 4) ){ - i += 4; - bStructureV2 = 1; - } - /* Read the total number of levels and segments from the start of the ** structure record. */ i += fts5GetVarint32(&pData[i], nLevel); i += fts5GetVarint32(&pData[i], nSegment); - if( nLevel>FTS5_MAX_SEGMENT || nLevel<0 - || nSegment>FTS5_MAX_SEGMENT || nSegment<0 - ){ - return FTS5_CORRUPT; - } nByte = ( sizeof(Fts5Structure) + /* Main structure */ sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */ ); pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte); @@ -243901,51 +191982,29 @@ if( i>=nData ){ rc = FTS5_CORRUPT; }else{ i += fts5GetVarint32(&pData[i], pLvl->nMerge); i += fts5GetVarint32(&pData[i], nTotal); - if( nTotalnMerge ) rc = FTS5_CORRUPT; - pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, + assert( nTotal>=pLvl->nMerge ); + pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, nTotal * sizeof(Fts5StructureSegment) ); - nSegment -= nTotal; } if( rc==SQLITE_OK ){ pLvl->nSeg = nTotal; for(iSeg=0; iSegaSeg[iSeg]; if( i>=nData ){ rc = FTS5_CORRUPT; break; } - assert( pSeg!=0 ); - i += fts5GetVarint32(&pData[i], pSeg->iSegid); - i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst); - i += fts5GetVarint32(&pData[i], pSeg->pgnoLast); - if( bStructureV2 ){ - i += fts5GetVarint(&pData[i], &pSeg->iOrigin1); - i += fts5GetVarint(&pData[i], &pSeg->iOrigin2); - i += fts5GetVarint32(&pData[i], pSeg->nPgTombstone); - i += fts5GetVarint(&pData[i], &pSeg->nEntryTombstone); - i += fts5GetVarint(&pData[i], &pSeg->nEntry); - nOriginCntr = MAX(nOriginCntr, pSeg->iOrigin2); - } - if( pSeg->pgnoLastpgnoFirst ){ - rc = FTS5_CORRUPT; - break; - } - } - if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT; - if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT; - } - } - if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT; - if( bStructureV2 ){ - pRet->nOriginCntr = nOriginCntr+1; - } - + i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid); + i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst); + i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast); + } + } + } if( rc!=SQLITE_OK ){ fts5StructureRelease(pRet); pRet = 0; } } @@ -243953,25 +192012,22 @@ *ppOut = pRet; return rc; } /* -** Add a level to the Fts5Structure.aLevel[] array of structure object -** (*ppStruct). +** */ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ - fts5StructureMakeWritable(pRc, ppStruct); - assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK ); if( *pRc==SQLITE_OK ){ Fts5Structure *pStruct = *ppStruct; int nLevel = pStruct->nLevel; - sqlite3_int64 nByte = ( + int nByte = ( sizeof(Fts5Structure) + /* Main structure */ sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */ ); - pStruct = sqlite3_realloc64(pStruct, nByte); + pStruct = sqlite3_realloc(pStruct, nByte); if( pStruct ){ memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel)); pStruct->nLevel++; *ppStruct = pStruct; }else{ @@ -243983,23 +192039,23 @@ /* ** Extend level iLvl so that there is room for at least nExtra more ** segments. */ static void fts5StructureExtendLevel( - int *pRc, - Fts5Structure *pStruct, - int iLvl, - int nExtra, + int *pRc, + Fts5Structure *pStruct, + int iLvl, + int nExtra, int bInsert ){ if( *pRc==SQLITE_OK ){ Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; Fts5StructureSegment *aNew; - sqlite3_int64 nByte; + int nByte; nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment); - aNew = sqlite3_realloc64(pLvl->aSeg, nByte); + aNew = sqlite3_realloc(pLvl->aSeg, nByte); if( aNew ){ if( bInsert==0 ){ memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra); }else{ int nMove = pLvl->nSeg * sizeof(Fts5StructureSegment); @@ -244022,11 +192078,11 @@ pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID); if( p->rc==SQLITE_OK ){ /* TODO: Do we need this if the leaf-index is appended? Probably... */ memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); - if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ + if( p->rc==SQLITE_OK && pConfig->iCookie!=iCookie ){ p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); } fts5DataRelease(pData); if( p->rc!=SQLITE_OK ){ fts5StructureRelease(pRet); @@ -244040,11 +192096,11 @@ static i64 fts5IndexDataVersion(Fts5Index *p){ i64 iVersion = 0; if( p->rc==SQLITE_OK ){ if( p->pDataVersion==0 ){ - p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion, + p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion, sqlite3_mprintf("PRAGMA %Q.data_version", p->pConfig->zDb) ); if( p->rc ) return 0; } @@ -244059,11 +192115,11 @@ /* ** Read, deserialize and return the structure record. ** ** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array -** are over-allocated as described for function fts5StructureDecode() +** are over-allocated as described for function fts5StructureDecode() ** above. ** ** If an error occurs, NULL is returned and an error code left in the ** Fts5Index handle. If an error has already occurred when this function ** is called, it is a no-op. @@ -244153,25 +192209,21 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ if( p->rc==SQLITE_OK ){ Fts5Buffer buf; /* Buffer to serialize record into */ int iLvl; /* Used to iterate through levels */ int iCookie; /* Cookie value to store */ - int nHdr = (pStruct->nOriginCntr>0 ? (4+4+9+9+9) : (4+9+9)); assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); memset(&buf, 0, sizeof(Fts5Buffer)); /* Append the current configuration cookie */ iCookie = p->pConfig->iCookie; if( iCookie<0 ) iCookie = 0; - if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, nHdr) ){ + if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, 4+9+9+9) ){ sqlite3Fts5Put32(buf.p, iCookie); buf.n = 4; - if( pStruct->nOriginCntr>0 ){ - fts5BufferSafeAppendBlob(&buf, FTS5_STRUCTURE_V2, 4); - } fts5BufferSafeAppendVarint(&buf, pStruct->nLevel); fts5BufferSafeAppendVarint(&buf, pStruct->nSegment); fts5BufferSafeAppendVarint(&buf, (i64)pStruct->nWriteCounter); } @@ -244181,21 +192233,13 @@ fts5BufferAppendVarint(&p->rc, &buf, pLvl->nMerge); fts5BufferAppendVarint(&p->rc, &buf, pLvl->nSeg); assert( pLvl->nMerge<=pLvl->nSeg ); for(iSeg=0; iSegnSeg; iSeg++){ - Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; - fts5BufferAppendVarint(&p->rc, &buf, pSeg->iSegid); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->pgnoFirst); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->pgnoLast); - if( pStruct->nOriginCntr>0 ){ - fts5BufferAppendVarint(&p->rc, &buf, pSeg->iOrigin1); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->iOrigin2); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->nPgTombstone); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->nEntryTombstone); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->nEntry); - } + fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].iSegid); + fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoFirst); + fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoLast); } } fts5DataWrite(p, FTS5_STRUCTURE_ROWID, buf.p, buf.n); fts5BufferFree(&buf); @@ -244220,12 +192264,12 @@ static int fts5SegmentSize(Fts5StructureSegment *pSeg){ return 1 + pSeg->pgnoLast - pSeg->pgnoFirst; } /* -** Return a copy of index structure pStruct. Except, promote as many -** segments as possible to level iPromote. If an OOM occurs, NULL is +** Return a copy of index structure pStruct. Except, promote as many +** segments as possible to level iPromote. If an OOM occurs, NULL is ** returned. */ static void fts5StructurePromoteTo( Fts5Index *p, int iPromote, @@ -244261,12 +192305,12 @@ ** within the previous populated level, it is promoted to the previous ** populated level. ** ** b) If the segment just written is larger than the newest segment on ** the next populated level, then that segment, and any other adjacent -** segments that are also smaller than the one just written, are -** promoted. +** segments that are also smaller than the one just written, are +** promoted. ** ** If one or more segments are promoted, the structure object is updated ** to reflect this. */ static void fts5StructurePromote( @@ -244296,11 +192340,11 @@ for(i=0; inSeg; i++){ int sz = pTst->aSeg[i].pgnoLast - pTst->aSeg[i].pgnoFirst + 1; if( sz>szMax ) szMax = sz; } if( szMax>=szSeg ){ - /* Condition (a) is true. Promote the newest segment on level + /* Condition (a) is true. Promote the newest segment on level ** iLvl to level iTst. */ iPromote = iTst; szPromote = szMax; } } @@ -244315,11 +192359,11 @@ } } /* -** Advance the iterator passed as the only argument. If the end of the +** Advance the iterator passed as the only argument. If the end of the ** doclist-index page is reached, return non-zero. */ static int fts5DlidxLvlNext(Fts5DlidxLvl *pLvl){ Fts5Data *pData = pLvl->pData; @@ -244330,17 +192374,17 @@ pLvl->iOff += fts5GetVarint(&pData->p[pLvl->iOff], (u64*)&pLvl->iRowid); pLvl->iFirstOff = pLvl->iOff; }else{ int iOff; for(iOff=pLvl->iOff; iOffnn; iOff++){ - if( pData->p[iOff] ) break; + if( pData->p[iOff] ) break; } if( iOffnn ){ - u64 iVal; + i64 iVal; pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1; - iOff += fts5GetVarint(&pData->p[iOff], &iVal); + iOff += fts5GetVarint(&pData->p[iOff], (u64*)&iVal); pLvl->iRowid += iVal; pLvl->iOff = iOff; }else{ pLvl->bEof = 1; } @@ -244360,11 +192404,11 @@ if( (iLvl+1) < pIter->nLvl ){ fts5DlidxIterNextR(p, pIter, iLvl+1); if( pLvl[1].bEof==0 ){ fts5DataRelease(pLvl->pData); memset(pLvl, 0, sizeof(Fts5DlidxLvl)); - pLvl->pData = fts5DataRead(p, + pLvl->pData = fts5DataRead(p, FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno) ); if( pLvl->pData ) fts5DlidxLvlNext(pLvl); } } @@ -244380,11 +192424,11 @@ ** The iterator passed as the first argument has the following fields set ** as follows. This function sets up the rest of the iterator so that it ** points to the first rowid in the doclist-index. ** ** pData: -** pointer to doclist-index record, +** pointer to doclist-index record, ** ** When this function is called pIter->iLeafPgno is the page number the ** doclist is associated with (the one featuring the term). */ static int fts5DlidxIterFirst(Fts5DlidxIter *pIter){ @@ -244411,11 +192455,11 @@ if( i>0 ){ Fts5DlidxLvl *pChild = &pLvl[-1]; fts5DataRelease(pChild->pData); memset(pChild, 0, sizeof(Fts5DlidxLvl)); - pChild->pData = fts5DataRead(p, + pChild->pData = fts5DataRead(p, FTS5_DLIDX_ROWID(pIter->iSegid, i-1, pLvl->iLeafPgno) ); } } } @@ -244429,29 +192473,46 @@ assert( pLvl->bEof==0 ); if( iOff<=pLvl->iFirstOff ){ pLvl->bEof = 1; }else{ u8 *a = pLvl->pData->p; - - pLvl->iOff = 0; - fts5DlidxLvlNext(pLvl); - while( 1 ){ - int nZero = 0; - int ii = pLvl->iOff; - u64 delta = 0; - - while( a[ii]==0 ){ - nZero++; - ii++; - } - ii += sqlite3Fts5GetVarint(&a[ii], &delta); - - if( ii>=iOff ) break; - pLvl->iLeafPgno += nZero+1; - pLvl->iRowid += delta; - pLvl->iOff = ii; - } + i64 iVal; + int iLimit; + int ii; + int nZero = 0; + + /* Currently iOff points to the first byte of a varint. This block + ** decrements iOff until it points to the first byte of the previous + ** varint. Taking care not to read any memory locations that occur + ** before the buffer in memory. */ + iLimit = (iOff>9 ? iOff-9 : 0); + for(iOff--; iOff>iLimit; iOff--){ + if( (a[iOff-1] & 0x80)==0 ) break; + } + + fts5GetVarint(&a[iOff], (u64*)&iVal); + pLvl->iRowid -= iVal; + pLvl->iLeafPgno--; + + /* Skip backwards past any 0x00 varints. */ + for(ii=iOff-1; ii>=pLvl->iFirstOff && a[ii]==0x00; ii--){ + nZero++; + } + if( ii>=pLvl->iFirstOff && (a[ii] & 0x80) ){ + /* The byte immediately before the last 0x00 byte has the 0x80 bit + ** set. So the last 0x00 is only a varint 0 if there are 8 more 0x80 + ** bytes before a[ii]. */ + int bZero = 0; /* True if last 0x00 counts */ + if( (ii-8)>=pLvl->iFirstOff ){ + int j; + for(j=1; j<=8 && (a[ii-j] & 0x80); j++); + bZero = (j>8); + } + if( bZero==0 ) nZero--; + } + pLvl->iLeafPgno -= nZero; + pLvl->iOff = iOff - nZero; } return pLvl->bEof; } @@ -244463,11 +192524,11 @@ if( (iLvl+1) < pIter->nLvl ){ fts5DlidxIterPrevR(p, pIter, iLvl+1); if( pLvl[1].bEof==0 ){ fts5DataRelease(pLvl->pData); memset(pLvl, 0, sizeof(Fts5DlidxLvl)); - pLvl->pData = fts5DataRead(p, + pLvl->pData = fts5DataRead(p, FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno) ); if( pLvl->pData ){ while( fts5DlidxLvlNext(pLvl)==0 ); pLvl->bEof = 0; @@ -244504,14 +192565,14 @@ Fts5DlidxIter *pIter = 0; int i; int bDone = 0; for(i=0; p->rc==SQLITE_OK && bDone==0; i++){ - sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl); + int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl); Fts5DlidxIter *pNew; - pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte); + pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte); if( pNew==0 ){ p->rc = SQLITE_NOMEM; }else{ i64 iRowid = FTS5_DLIDX_ROWID(iSegid, i, iLeafPg); Fts5DlidxLvl *pLvl = &pNew->aLvl[i]; @@ -244562,11 +192623,11 @@ pIter->iLeafPgno++; if( pIter->pNextLeaf ){ pIter->pLeaf = pIter->pNextLeaf; pIter->pNextLeaf = 0; }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){ - pIter->pLeaf = fts5LeafRead(p, + pIter->pLeaf = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno) ); }else{ pIter->pLeaf = 0; } @@ -244606,11 +192667,11 @@ ** in the following variables: ** ** Fts5SegIter.nPos ** Fts5SegIter.bDel ** -** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the +** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the ** position list content (if any). */ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){ if( p->rc==SQLITE_OK ){ int iOff = pIter->iLeafOffset; /* Offset to read at */ @@ -244640,14 +192701,14 @@ } } static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ - i64 iOff = pIter->iLeafOffset; + int iOff = pIter->iLeafOffset; ASSERT_SZLEAF_OK(pIter->pLeaf); - while( iOff>=pIter->pLeaf->szLeaf ){ + if( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; return; } @@ -244657,11 +192718,11 @@ iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; } /* -** Fts5SegIter.iLeafOffset currently points to the first byte of the +** Fts5SegIter.iLeafOffset currently points to the first byte of the ** "nSuffix" field of a term. Function parameter nKeep contains the value ** of the "nPrefix" field (if there was one - it is passed 0 if this is ** the first term in the segment). ** ** This function populates: @@ -244668,26 +192729,25 @@ ** ** Fts5SegIter.term ** Fts5SegIter.rowid ** ** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of -** the first position list. The position list belonging to document +** the first position list. The position list belonging to document ** (Fts5SegIter.iRowid). */ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ - i64 iOff = pIter->iLeafOffset; /* Offset to read at */ + int iOff = pIter->iLeafOffset; /* Offset to read at */ int nNew; /* Bytes of new data */ iOff += fts5GetVarint32(&a[iOff], nNew); - if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){ + if( iOff+nNew>pIter->pLeaf->nn ){ p->rc = FTS5_CORRUPT; return; } pIter->term.n = nKeep; fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]); - assert( pIter->term.n<=pIter->term.nSpace ); iOff += nNew; pIter->iTermLeafOffset = iOff; pIter->iTermLeafPgno = pIter->iLeafPgno; pIter->iLeafOffset = iOff; @@ -244714,35 +192774,16 @@ }else{ pIter->xNext = fts5SegIterNext; } } -/* -** Allocate a tombstone hash page array object (pIter->pTombArray) for -** the iterator passed as the second argument. If an OOM error occurs, -** leave an error in the Fts5Index object. -*/ -static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){ - const int nTomb = pIter->pSeg->nPgTombstone; - if( nTomb>0 ){ - int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray); - Fts5TombstoneArray *pNew; - pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte); - if( pNew ){ - pNew->nTombstone = nTomb; - pNew->nRef = 1; - pIter->pTombArray = pNew; - } - } -} - /* ** Initialize the iterator object pIter to iterate through the entries in -** segment pSeg. The iterator is left pointing to the first entry when +** segment pSeg. The iterator is left pointing to the first entry when ** this function returns. ** -** If an error occurs, Fts5Index.rc is set to an appropriate error code. If +** If an error occurs, Fts5Index.rc is set to an appropriate error code. If ** an error has already occurred when this function is called, it is a no-op. */ static void fts5SegIterInit( Fts5Index *p, /* FTS index object */ Fts5StructureSegment *pSeg, /* Description of segment */ @@ -244761,24 +192802,20 @@ if( p->rc==SQLITE_OK ){ memset(pIter, 0, sizeof(*pIter)); fts5SegIterSetNext(p, pIter); pIter->pSeg = pSeg; pIter->iLeafPgno = pSeg->pgnoFirst-1; - do { - fts5SegIterNextPage(p, pIter); - }while( p->rc==SQLITE_OK && pIter->pLeaf && pIter->pLeaf->nn==4 ); + fts5SegIterNextPage(p, pIter); } - if( p->rc==SQLITE_OK && pIter->pLeaf ){ + if( p->rc==SQLITE_OK ){ pIter->iLeafOffset = 4; - assert( pIter->pLeaf!=0 ); assert_nc( pIter->pLeaf->nn>4 ); - assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 ); + assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 ); pIter->iPgidxOff = pIter->pLeaf->szLeaf+1; fts5SegIterLoadTerm(p, pIter, 0); fts5SegIterLoadNPos(p, pIter); - fts5SegIterAllocTombstone(p, pIter); } } /* ** This function is only ever called on iterators created by calls to @@ -244787,12 +192824,12 @@ ** The iterator is in an unusual state when this function is called: the ** Fts5SegIter.iLeafOffset variable is set to the offset of the start of ** the position-list size field for the first relevant rowid on the page. ** Fts5SegIter.rowid is set, but nPos and bDel are not. ** -** This function advances the iterator so that it points to the last -** relevant rowid on the page and, if necessary, initializes the +** This function advances the iterator so that it points to the last +** relevant rowid on the page and, if necessary, initializes the ** aRowidOffset[] and iRowidOffset variables. At this point the iterator ** is in its regular state - Fts5SegIter.iLeafOffset points to the first ** byte of the position list content associated with said rowid. */ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){ @@ -244806,11 +192843,11 @@ n = pIter->iEndofDoclist; } ASSERT_SZLEAF_OK(pIter->pLeaf); while( 1 ){ - u64 iDelta = 0; + i64 iDelta = 0; if( eDetail==FTS5_DETAIL_NONE ){ /* todo */ if( i=n ) break; - i += fts5GetVarint(&a[i], &iDelta); + i += fts5GetVarint(&a[i], (u64*)&iDelta); pIter->iRowid += iDelta; /* If necessary, grow the pIter->aRowidOffset[] array. */ if( iRowidOffset>=pIter->nRowidOffset ){ int nNew = pIter->nRowidOffset + 8; - int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int)); + int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int)); if( aNew==0 ){ p->rc = SQLITE_NOMEM; break; } pIter->aRowidOffset = aNew; @@ -244872,16 +192909,12 @@ } }else{ int iRowidOff; iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ - if( iRowidOff>=pNew->szLeaf ){ - p->rc = FTS5_CORRUPT; - }else{ - pIter->pLeaf = pNew; - pIter->iLeafOffset = iRowidOff; - } + pIter->pLeaf = pNew; + pIter->iLeafOffset = iRowidOff; } } if( pIter->pLeaf ){ u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset]; @@ -244924,20 +192957,20 @@ UNUSED_PARAM(pbUnused); if( pIter->iRowidOffset>0 ){ u8 *a = pIter->pLeaf->p; int iOff; - u64 iDelta; + i64 iDelta; pIter->iRowidOffset--; pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset]; fts5SegIterLoadNPos(p, pIter); iOff = pIter->iLeafOffset; if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){ iOff += pIter->nPos; } - fts5GetVarint(&a[iOff], &iDelta); + fts5GetVarint(&a[iOff], (u64*)&iDelta); pIter->iRowid -= iDelta; }else{ fts5SegIterReverseNewPage(p, pIter); } } @@ -244961,20 +192994,20 @@ ASSERT_SZLEAF_OK(pIter->pLeaf); iOff = pIter->iLeafOffset; /* Next entry is on the next page */ - while( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){ + if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( p->rc || pIter->pLeaf==0 ) return; pIter->iRowid = 0; iOff = 4; } if( iOffiEndofDoclist ){ /* Next entry is on the current page */ - u64 iDelta; + i64 iDelta; iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta); pIter->iLeafOffset = iOff; pIter->iRowid += iDelta; }else if( (pIter->flags & FTS5_SEGITER_ONETERM)==0 ){ if( pIter->pSeg ){ @@ -244985,20 +193018,19 @@ pIter->iLeafOffset = iOff; fts5SegIterLoadTerm(p, pIter, nKeep); }else{ const u8 *pList = 0; const char *zTerm = 0; - int nTerm = 0; int nList; sqlite3Fts5HashScanNext(p->pHash); - sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList); + sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); if( pList==0 ) goto next_none_eof; pIter->pLeaf->p = (u8*)pList; pIter->pLeaf->nn = nList; pIter->pLeaf->szLeaf = nList; pIter->iEndofDoclist = nList; - sqlite3Fts5BufferSet(&p->rc,&pIter->term, nTerm, (u8*)zTerm); + sqlite3Fts5BufferSet(&p->rc,&pIter->term, (int)strlen(zTerm), (u8*)zTerm); pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid); } if( pbNewTerm ) *pbNewTerm = 1; }else{ @@ -245013,14 +193045,14 @@ pIter->pLeaf = 0; } /* -** Advance iterator pIter to the next entry. +** Advance iterator pIter to the next entry. ** -** If an error occurs, Fts5Index.rc is set to an appropriate error code. It -** is not considered an error if the iterator reaches EOF. If an error has +** If an error occurs, Fts5Index.rc is set to an appropriate error code. It +** is not considered an error if the iterator reaches EOF. If an error has ** already occurred when this function is called, it is a no-op. */ static void fts5SegIterNext( Fts5Index *p, /* FTS5 backend object */ Fts5SegIter *pIter, /* Iterator to advance */ @@ -245060,26 +193092,26 @@ pIter->iLeafOffset = iOff; }else if( pIter->pSeg==0 ){ const u8 *pList = 0; const char *zTerm = 0; - int nTerm = 0; int nList = 0; assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm ); if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){ sqlite3Fts5HashScanNext(p->pHash); - sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList); + sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); } if( pList==0 ){ fts5DataRelease(pIter->pLeaf); pIter->pLeaf = 0; }else{ pIter->pLeaf->p = (u8*)pList; pIter->pLeaf->nn = nList; pIter->pLeaf->szLeaf = nList; pIter->iEndofDoclist = nList+1; - sqlite3Fts5BufferSet(&p->rc, &pIter->term, nTerm, (u8*)zTerm); + sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm), + (u8*)zTerm); pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid); *pbNewTerm = 1; } }else{ iOff = 0; @@ -245127,13 +193159,18 @@ if( pbNewTerm ) *pbNewTerm = 1; } }else{ /* The following could be done by calling fts5SegIterLoadNPos(). But ** this block is particularly performance critical, so equivalent - ** code is inlined. */ + ** code is inlined. + ** + ** Later: Switched back to fts5SegIterLoadNPos() because it supports + ** detail=none mode. Not ideal. + */ int nSz; - assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn ); + assert( p->rc==SQLITE_OK ); + assert( pIter->iLeafOffset<=pIter->pLeaf->nn ); fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; assert_nc( pIter->nPos>=0 ); } @@ -245155,14 +193192,14 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ Fts5DlidxIter *pDlidx = pIter->pDlidx; Fts5Data *pLast = 0; int pgnoLast = 0; - if( pDlidx && p->pConfig->iVersion==FTS5_CURRENT_VERSION ){ + if( pDlidx ){ int iSegid = pIter->pSeg->iSegid; pgnoLast = fts5DlidxIterPgno(pDlidx); - pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast)); + pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast)); }else{ Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */ /* Currently, Fts5SegIter.iLeafOffset points to the first byte of ** position-list content for the current rowid. Back it up so that it @@ -245185,11 +193222,11 @@ /* The last rowid in the doclist may not be on the current page. Search ** forward to find the page containing the last rowid. */ for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){ i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno); - Fts5Data *pNew = fts5LeafRead(p, iAbs); + Fts5Data *pNew = fts5DataRead(p, iAbs); if( pNew ){ int iRowid, bTermless; iRowid = fts5LeafFirstRowidOff(pNew); bTermless = fts5LeafIsTermless(pNew); if( iRowid ){ @@ -245202,11 +193239,11 @@ } } } /* If pLast is NULL at this point, then the last rowid for this doclist - ** lies on the page currently indicated by the iterator. In this case + ** lies on the page currently indicated by the iterator. In this case ** pIter->iLeafOffset is already set to point to the position-list size ** field associated with the first relevant rowid on the page. ** ** Or, if pLast is non-NULL, then it is the page that contains the last ** rowid. In this case configure the iterator so that it points to the @@ -245216,31 +193253,28 @@ int iOff; fts5DataRelease(pIter->pLeaf); pIter->pLeaf = pLast; pIter->iLeafPgno = pgnoLast; iOff = fts5LeafFirstRowidOff(pLast); - if( iOff>pLast->szLeaf ){ - p->rc = FTS5_CORRUPT; - return; - } iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; if( fts5LeafIsTermless(pLast) ){ pIter->iEndofDoclist = pLast->nn+1; }else{ pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast); } + } fts5SegIterReverseInitPage(p, pIter); } /* ** Iterator pIter currently points to the first rowid of a doclist. -** There is a doclist-index associated with the final term on the current -** page. If the current term is the last term on the page, load the +** There is a doclist-index associated with the final term on the current +** page. If the current term is the last term on the page, load the ** doclist-index from disk and initialize an iterator at (pIter->pDlidx). */ static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){ int iSeg = pIter->pSeg->iSegid; int bRev = (pIter->flags & FTS5_SEGITER_REVERSE); @@ -245250,12 +193284,12 @@ assert( pIter->pDlidx==0 ); /* Check if the current doclist ends on this page. If it does, return ** early without loading the doclist-index (as it belongs to a different ** term. */ - if( pIter->iTermLeafPgno==pIter->iLeafPgno - && pIter->iEndofDoclistszLeaf + if( pIter->iTermLeafPgno==pIter->iLeafPgno + && pIter->iEndofDoclistszLeaf ){ return; } pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno); @@ -245279,24 +193313,25 @@ Fts5Index *p, /* Leave any error code here */ int bGe, /* True for a >= search */ Fts5SegIter *pIter, /* Iterator to seek */ const u8 *pTerm, int nTerm /* Term to search for */ ){ - u32 iOff; + int iOff; const u8 *a = pIter->pLeaf->p; - u32 n = (u32)pIter->pLeaf->nn; + int szLeaf = pIter->pLeaf->szLeaf; + int n = pIter->pLeaf->nn; - u32 nMatch = 0; - u32 nKeep = 0; - u32 nNew = 0; - u32 iTermOff; - u32 iPgidx; /* Current offset in pgidx */ + int nMatch = 0; + int nKeep = 0; + int nNew = 0; + int iTermOff; + int iPgidx; /* Current offset in pgidx */ int bEndOfPage = 0; assert( p->rc==SQLITE_OK ); - iPgidx = (u32)pIter->pLeaf->szLeaf; + iPgidx = szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; if( iOff>n ){ p->rc = FTS5_CORRUPT; return; @@ -245310,19 +193345,19 @@ goto search_failed; } assert( nKeep>=nMatch ); if( nKeep==nMatch ){ - u32 nCmp; - u32 i; - nCmp = (u32)MIN(nNew, nTerm-nMatch); + int nCmp; + int i; + nCmp = MIN(nNew, nTerm-nMatch); for(i=0; ipLeaf==0 ) return; a = pIter->pLeaf->p; if( fts5LeafIsTermless(pIter->pLeaf)==0 ){ - iPgidx = (u32)pIter->pLeaf->szLeaf; + iPgidx = pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); - if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){ + if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; - return; }else{ nKeep = 0; iTermOff = iOff; - n = (u32)pIter->pLeaf->nn; + n = pIter->pLeaf->nn; iOff += fts5GetVarint32(&a[iOff], nNew); break; } } }while( 1 ); } search_success: - if( (i64)iOff+nNew>n || nNew<1 ){ - p->rc = FTS5_CORRUPT; - return; - } + pIter->iLeafOffset = iOff + nNew; pIter->iTermLeafOffset = pIter->iLeafOffset; pIter->iTermLeafPgno = pIter->iLeafPgno; fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm); @@ -245415,11 +193446,11 @@ /* ** Initialize the object pIter to point to term pTerm/nTerm within segment ** pSeg. If there is no such term in the index, the iterator is set to EOF. ** -** If an error occurs, Fts5Index.rc is set to an appropriate error code. If +** If an error occurs, Fts5Index.rc is set to an appropriate error code. If ** an error has already occurred when this function is called, it is a no-op. */ static void fts5SegIterSeekInit( Fts5Index *p, /* FTS5 backend */ const u8 *pTerm, int nTerm, /* Term to seek to */ @@ -245447,11 +193478,10 @@ i64 val = sqlite3_column_int(pIdxSelect, 0); iPg = (int)(val>>1); bDlidx = (val & 0x0001); } p->rc = sqlite3_reset(pIdxSelect); - sqlite3_bind_null(pIdxSelect, 2); if( iPgpgnoFirst ){ iPg = pSeg->pgnoFirst; bDlidx = 0; } @@ -245461,11 +193491,11 @@ if( pIter->pLeaf ){ fts5LeafSeek(p, bGe, pIter, pTerm, nTerm); } - if( p->rc==SQLITE_OK && (bGe==0 || (flags & FTS5INDEX_QUERY_SCANONETERM)) ){ + if( p->rc==SQLITE_OK && bGe==0 ){ pIter->flags |= FTS5_SEGITER_ONETERM; if( pIter->pLeaf ){ if( flags & FTS5INDEX_QUERY_DESC ){ pIter->flags |= FTS5_SEGITER_REVERSE; } @@ -245477,157 +193507,65 @@ } } } fts5SegIterSetNext(p, pIter); - if( 0==(flags & FTS5INDEX_QUERY_SCANONETERM) ){ - fts5SegIterAllocTombstone(p, pIter); - } /* Either: ** ** 1) an error has occurred, or ** 2) the iterator points to EOF, or ** 3) the iterator points to an entry with term (pTerm/nTerm), or ** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points ** to an entry with a term greater than or equal to (pTerm/nTerm). */ - assert_nc( p->rc!=SQLITE_OK /* 1 */ + assert( p->rc!=SQLITE_OK /* 1 */ || pIter->pLeaf==0 /* 2 */ || fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */ || (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */ ); } - -/* -** SQL used by fts5SegIterNextInit() to find the page to open. -*/ -static sqlite3_stmt *fts5IdxNextStmt(Fts5Index *p){ - if( p->pIdxNextSelect==0 ){ - Fts5Config *pConfig = p->pConfig; - fts5IndexPrepareStmt(p, &p->pIdxNextSelect, sqlite3_mprintf( - "SELECT pgno FROM '%q'.'%q_idx' WHERE " - "segid=? AND term>? ORDER BY term ASC LIMIT 1", - pConfig->zDb, pConfig->zName - )); - - } - return p->pIdxNextSelect; -} - -/* -** This is similar to fts5SegIterSeekInit(), except that it initializes -** the segment iterator to point to the first term following the page -** with pToken/nToken on it. -*/ -static void fts5SegIterNextInit( - Fts5Index *p, - const char *pTerm, int nTerm, - Fts5StructureSegment *pSeg, /* Description of segment */ - Fts5SegIter *pIter /* Object to populate */ -){ - int iPg = -1; /* Page of segment to open */ - int bDlidx = 0; - sqlite3_stmt *pSel = 0; /* SELECT to find iPg */ - - pSel = fts5IdxNextStmt(p); - if( pSel ){ - assert( p->rc==SQLITE_OK ); - sqlite3_bind_int(pSel, 1, pSeg->iSegid); - sqlite3_bind_blob(pSel, 2, pTerm, nTerm, SQLITE_STATIC); - - if( sqlite3_step(pSel)==SQLITE_ROW ){ - i64 val = sqlite3_column_int64(pSel, 0); - iPg = (int)(val>>1); - bDlidx = (val & 0x0001); - } - p->rc = sqlite3_reset(pSel); - sqlite3_bind_null(pSel, 2); - if( p->rc ) return; - } - - memset(pIter, 0, sizeof(*pIter)); - pIter->pSeg = pSeg; - pIter->flags |= FTS5_SEGITER_ONETERM; - if( iPg>=0 ){ - pIter->iLeafPgno = iPg - 1; - fts5SegIterNextPage(p, pIter); - fts5SegIterSetNext(p, pIter); - } - if( pIter->pLeaf ){ - const u8 *a = pIter->pLeaf->p; - int iTermOff = 0; - - pIter->iPgidxOff = pIter->pLeaf->szLeaf; - pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff); - pIter->iLeafOffset = iTermOff; - fts5SegIterLoadTerm(p, pIter, 0); - fts5SegIterLoadNPos(p, pIter); - if( bDlidx ) fts5SegIterLoadDlidx(p, pIter); - - assert( p->rc!=SQLITE_OK || - fts5BufferCompareBlob(&pIter->term, (const u8*)pTerm, nTerm)>0 - ); - } -} - /* ** Initialize the object pIter to point to term pTerm/nTerm within the -** in-memory hash table. If there is no such term in the hash-table, the +** in-memory hash table. If there is no such term in the hash-table, the ** iterator is set to EOF. ** -** If an error occurs, Fts5Index.rc is set to an appropriate error code. If +** If an error occurs, Fts5Index.rc is set to an appropriate error code. If ** an error has already occurred when this function is called, it is a no-op. */ static void fts5SegIterHashInit( Fts5Index *p, /* FTS5 backend */ const u8 *pTerm, int nTerm, /* Term to seek to */ int flags, /* Mask of FTS5INDEX_XXX flags */ Fts5SegIter *pIter /* Object to populate */ ){ + const u8 *pList = 0; int nList = 0; const u8 *z = 0; int n = 0; - Fts5Data *pLeaf = 0; assert( p->pHash ); assert( p->rc==SQLITE_OK ); if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){ - const u8 *pList = 0; - p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm); - sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &n, &pList, &nList); - if( pList ){ - pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); - if( pLeaf ){ - pLeaf->p = (u8*)pList; - } - } - - /* The call to sqlite3Fts5HashScanInit() causes the hash table to - ** fill the size field of all existing position lists. This means they - ** can no longer be appended to. Since the only scenario in which they - ** can be appended to is if the previous operation on this table was - ** a DELETE, by clearing the Fts5Index.bDelete flag we can avoid this - ** possibility altogether. */ - p->bDelete = 0; + sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList); + n = (z ? (int)strlen((const char*)z) : 0); }else{ - p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), - (const char*)pTerm, nTerm, (void**)&pLeaf, &nList - ); - if( pLeaf ){ - pLeaf->p = (u8*)&pLeaf[1]; - } + pIter->flags |= FTS5_SEGITER_ONETERM; + sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList); z = pTerm; n = nTerm; - pIter->flags |= FTS5_SEGITER_ONETERM; } - if( pLeaf ){ + if( pList ){ + Fts5Data *pLeaf; sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z); + pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); + if( pLeaf==0 ) return; + pLeaf->p = (u8*)pList; pLeaf->nn = pLeaf->szLeaf = nList; pIter->pLeaf = pLeaf; pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid); pIter->iEndofDoclist = pLeaf->nn; @@ -245640,49 +193578,17 @@ } fts5SegIterSetNext(p, pIter); } -/* -** Array ap[] contains n elements. Release each of these elements using -** fts5DataRelease(). Then free the array itself using sqlite3_free(). -*/ -static void fts5IndexFreeArray(Fts5Data **ap, int n){ - if( ap ){ - int ii; - for(ii=0; iinRef--; - if( p->nRef<=0 ){ - int ii; - for(ii=0; iinTombstone; ii++){ - fts5DataRelease(p->apTombstone[ii]); - } - sqlite3_free(p); - } - } -} - /* ** Zero the iterator passed as the only argument. */ static void fts5SegIterClear(Fts5SegIter *pIter){ fts5BufferFree(&pIter->term); fts5DataRelease(pIter->pLeaf); fts5DataRelease(pIter->pNextLeaf); - fts5TombstoneArrayDelete(pIter->pTombArray); fts5DlidxIterFree(pIter->pDlidx); sqlite3_free(pIter->aRowidOffset); memset(pIter, 0, sizeof(Fts5SegIter)); } @@ -245693,11 +193599,11 @@ ** fts5AssertMultiIterSetup(). It ensures that the result currently stored ** in *pRes is the correct result of comparing the current positions of the ** two iterators. */ static void fts5AssertComparisonResult( - Fts5Iter *pIter, + Fts5Iter *pIter, Fts5SegIter *p1, Fts5SegIter *p2, Fts5CResult *pRes ){ int i1 = p1 - pIter->aSeg; @@ -245708,11 +193614,11 @@ assert( pRes->iFirst==i2 ); }else if( p2->pLeaf==0 ){ assert( pRes->iFirst==i1 ); }else{ int nMin = MIN(p1->term.n, p2->term.n); - int res = fts5Memcmp(p1->term.p, p2->term.p, nMin); + int res = memcmp(p1->term.p, p2->term.p, nMin); if( res==0 ) res = p1->term.n - p2->term.n; if( res==0 ){ assert( pRes->bTermEq==1 ); assert( p1->iRowid!=p2->iRowid ); @@ -245730,11 +193636,11 @@ } } /* ** This function is a no-op unless SQLITE_DEBUG is defined when this module -** is compiled. In that case, this function is essentially an assert() +** is compiled. In that case, this function is essentially an assert() ** statement used to verify that the contents of the pIter->aFirst[] array ** are correct. */ static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ if( p->rc==SQLITE_OK ){ @@ -245744,13 +193650,13 @@ assert( (pFirst->pLeaf==0)==pIter->base.bEof ); /* Check that pIter->iSwitchRowid is set correctly. */ for(i=0; inSeg; i++){ Fts5SegIter *p1 = &pIter->aSeg[i]; - assert( p1==pFirst - || p1->pLeaf==0 - || fts5BufferCompare(&pFirst->term, &p1->term) + assert( p1==pFirst + || p1->pLeaf==0 + || fts5BufferCompare(&pFirst->term, &p1->term) || p1->iRowid==pIter->iSwitchRowid || (p1->iRowidiSwitchRowid)==pIter->bRev ); } @@ -245776,11 +193682,11 @@ /* ** Do the comparison necessary to populate pIter->aFirst[iOut]. ** ** If the returned value is non-zero, then it is the index of an entry ** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing -** to a key that is a duplicate of another, higher priority, +** to a key that is a duplicate of another, higher priority, ** segment-iterator in the pSeg->aSeg[] array. */ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ int i1; /* Index of left-hand Fts5SegIter */ int i2; /* Index of right-hand Fts5SegIter */ @@ -245808,14 +193714,15 @@ }else if( p2->pLeaf==0 ){ /* If p2 is at EOF */ iRes = i1; }else{ int res = fts5BufferCompare(&p1->term, &p2->term); if( res==0 ){ - assert_nc( i2>i1 ); - assert_nc( i2!=0 ); + assert( i2>i1 ); + assert( i2!=0 ); pRes->bTermEq = 1; if( p1->iRowid==p2->iRowid ){ + p1->bDel = p2->bDel; return i2; } res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1; } assert( res!=0 ); @@ -245830,12 +193737,11 @@ return 0; } /* ** Move the seg-iter so that it points to the first rowid on page iLeafPgno. -** It is an error if leaf iLeafPgno does not exist. Unless the db is -** a 'secure-delete' db, if it contains no rowids then this is also an error. +** It is an error if leaf iLeafPgno does not exist or contains no rowids. */ static void fts5SegIterGotoPage( Fts5Index *p, /* FTS5 backend object */ Fts5SegIter *pIter, /* Iterator to advance */ int iLeafPgno @@ -245846,34 +193752,32 @@ p->rc = FTS5_CORRUPT; }else{ fts5DataRelease(pIter->pNextLeaf); pIter->pNextLeaf = 0; pIter->iLeafPgno = iLeafPgno-1; + fts5SegIterNextPage(p, pIter); + assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno ); - while( p->rc==SQLITE_OK ){ + if( p->rc==SQLITE_OK ){ int iOff; - fts5SegIterNextPage(p, pIter); - if( pIter->pLeaf==0 ) break; + u8 *a = pIter->pLeaf->p; + int n = pIter->pLeaf->szLeaf; + iOff = fts5LeafFirstRowidOff(pIter->pLeaf); - if( iOff>0 ){ - u8 *a = pIter->pLeaf->p; - int n = pIter->pLeaf->szLeaf; - if( iOff<4 || iOff>=n ){ - p->rc = FTS5_CORRUPT; - }else{ - iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); - pIter->iLeafOffset = iOff; - fts5SegIterLoadNPos(p, pIter); - } - break; + if( iOff<4 || iOff>=n ){ + p->rc = FTS5_CORRUPT; + }else{ + iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; + fts5SegIterLoadNPos(p, pIter); } } } } /* -** Advance the iterator passed as the second argument until it is at or +** Advance the iterator passed as the second argument until it is at or ** past rowid iFrom. Regardless of the value of iFrom, the iterator is ** always advanced at least once. */ static void fts5SegIterNextFrom( Fts5Index *p, /* FTS5 backend object */ @@ -245922,10 +193826,11 @@ if( bRev==0 && pIter->iRowid>=iMatch ) break; if( bRev!=0 && pIter->iRowid<=iMatch ) break; bMove = 1; }while( p->rc==SQLITE_OK ); } + /* ** Free the iterator object passed as the second argument. */ static void fts5MultiIterFree(Fts5Iter *pIter){ @@ -245932,10 +193837,11 @@ if( pIter ){ int i; for(i=0; inSeg; i++){ fts5SegIterClear(&pIter->aSeg[i]); } + fts5StructureRelease(pIter->pStruct); fts5BufferFree(&pIter->poslist); sqlite3_free(pIter); } } @@ -245964,11 +193870,11 @@ ** If it does so successfully, 0 is returned. Otherwise 1. ** ** If non-zero is returned, the caller should call fts5MultiIterAdvanced() ** on the iterator instead. That function does the same as this one, except ** that it deals with more complicated cases as well. -*/ +*/ static int fts5MultiIterAdvanceRowid( Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ int iChanged, /* Index of sub-iterator just advanced */ Fts5SegIter **ppFirst ){ @@ -246015,97 +193921,18 @@ pIter->base.bEof = pSeg->pLeaf==0; pIter->iSwitchRowid = pSeg->iRowid; } /* -** The argument to this macro must be an Fts5Data structure containing a -** tombstone hash page. This macro returns the key-size of the hash-page. -*/ -#define TOMBSTONE_KEYSIZE(pPg) (pPg->p[0]==4 ? 4 : 8) - -#define TOMBSTONE_NSLOT(pPg) \ - ((pPg->nn > 16) ? ((pPg->nn-8) / TOMBSTONE_KEYSIZE(pPg)) : 1) - -/* -** Query a single tombstone hash table for rowid iRowid. Return true if -** it is found or false otherwise. The tombstone hash table is one of -** nHashTable tables. -*/ -static int fts5IndexTombstoneQuery( - Fts5Data *pHash, /* Hash table page to query */ - int nHashTable, /* Number of pages attached to segment */ - u64 iRowid /* Rowid to query hash for */ -){ - const int szKey = TOMBSTONE_KEYSIZE(pHash); - const int nSlot = TOMBSTONE_NSLOT(pHash); - int iSlot = (iRowid / nHashTable) % nSlot; - int nCollide = nSlot; - - if( iRowid==0 ){ - return pHash->p[1]; - }else if( szKey==4 ){ - u32 *aSlot = (u32*)&pHash->p[8]; - while( aSlot[iSlot] ){ - if( fts5GetU32((u8*)&aSlot[iSlot])==iRowid ) return 1; - if( nCollide--==0 ) break; - iSlot = (iSlot+1)%nSlot; - } - }else{ - u64 *aSlot = (u64*)&pHash->p[8]; - while( aSlot[iSlot] ){ - if( fts5GetU64((u8*)&aSlot[iSlot])==iRowid ) return 1; - if( nCollide--==0 ) break; - iSlot = (iSlot+1)%nSlot; - } - } - - return 0; -} - -/* -** Return true if the iterator passed as the only argument points -** to an segment entry for which there is a tombstone. Return false -** if there is no tombstone or if the iterator is already at EOF. -*/ -static int fts5MultiIterIsDeleted(Fts5Iter *pIter){ - int iFirst = pIter->aFirst[1].iFirst; - Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; - Fts5TombstoneArray *pArray = pSeg->pTombArray; - - if( pSeg->pLeaf && pArray ){ - /* Figure out which page the rowid might be present on. */ - int iPg = ((u64)pSeg->iRowid) % pArray->nTombstone; - assert( iPg>=0 ); - - /* If tombstone hash page iPg has not yet been loaded from the - ** database, load it now. */ - if( pArray->apTombstone[iPg]==0 ){ - pArray->apTombstone[iPg] = fts5DataRead(pIter->pIndex, - FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg) - ); - if( pArray->apTombstone[iPg]==0 ) return 0; - } - - return fts5IndexTombstoneQuery( - pArray->apTombstone[iPg], - pArray->nTombstone, - pSeg->iRowid - ); - } - - return 0; -} - -/* -** Move the iterator to the next entry. +** Move the iterator to the next entry. ** -** If an error occurs, an error code is left in Fts5Index.rc. It is not -** considered an error if the iterator reaches EOF, or if it is already at +** If an error occurs, an error code is left in Fts5Index.rc. It is not +** considered an error if the iterator reaches EOF, or if it is already at ** EOF when this function is called. */ static void fts5MultiIterNext( - Fts5Index *p, + Fts5Index *p, Fts5Iter *pIter, int bFrom, /* True if argument iFrom is valid */ i64 iFrom /* Advance at least as far as this */ ){ int bUseFrom = bFrom; @@ -246119,11 +193946,11 @@ fts5SegIterNextFrom(p, pSeg, iFrom); }else{ pSeg->xNext(p, pSeg, &bNewTerm); } - if( pSeg->pLeaf==0 || bNewTerm + if( pSeg->pLeaf==0 || bNewTerm || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) ){ fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterSetEof(pIter); pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; @@ -246130,22 +193957,20 @@ if( pSeg->pLeaf==0 ) return; } fts5AssertMultiIterSetup(p, pIter); assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); - if( (pIter->bSkipEmpty==0 || pSeg->nPos) - && 0==fts5MultiIterIsDeleted(pIter) - ){ + if( pIter->bSkipEmpty==0 || pSeg->nPos ){ pIter->xSetOutputs(pIter, pSeg); return; } bUseFrom = 0; } } static void fts5MultiIterNext2( - Fts5Index *p, + Fts5Index *p, Fts5Iter *pIter, int *pbNewTerm /* OUT: True if *might* be new term */ ){ assert( pIter->bSkipEmpty ); if( p->rc==SQLITE_OK ){ @@ -246155,22 +193980,20 @@ Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; int bNewTerm = 0; assert( p->rc==SQLITE_OK ); pSeg->xNext(p, pSeg, &bNewTerm); - if( pSeg->pLeaf==0 || bNewTerm + if( pSeg->pLeaf==0 || bNewTerm || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) ){ fts5MultiIterAdvanced(p, pIter, iFirst, 1); fts5MultiIterSetEof(pIter); *pbNewTerm = 1; } fts5AssertMultiIterSetup(p, pIter); - }while( (fts5MultiIterIsEmpty(p, pIter) || fts5MultiIterIsDeleted(pIter)) - && (p->rc==SQLITE_OK) - ); + }while( fts5MultiIterIsEmpty(p, pIter) ); } } static void fts5IterSetOutputs_Noop(Fts5Iter *pUnused1, Fts5SegIter *pUnused2){ UNUSED_PARAM2(pUnused1, pUnused2); @@ -246179,14 +194002,14 @@ static Fts5Iter *fts5MultiIterAlloc( Fts5Index *p, /* FTS5 backend to iterate within */ int nSeg ){ Fts5Iter *pNew; - i64 nSlot; /* Power of two >= nSeg */ + int nSlot; /* Power of two >= nSeg */ for(nSlot=2; nSlotaSeg[] */ sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ ); if( pNew ){ @@ -246197,12 +194020,12 @@ } return pNew; } static void fts5PoslistCallback( - Fts5Index *pUnused, - void *pContext, + Fts5Index *pUnused, + void *pContext, const u8 *pChunk, int nChunk ){ UNUSED_PARAM(pUnused); assert_nc( nChunk>=0 ); if( nChunk>0 ){ @@ -246235,12 +194058,12 @@ } return 0; } static void fts5PoslistOffsetsCallback( - Fts5Index *pUnused, - void *pContext, + Fts5Index *pUnused, + void *pContext, const u8 *pChunk, int nChunk ){ PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; UNUSED_PARAM(pUnused); assert_nc( nChunk>=0 ); @@ -246259,11 +194082,11 @@ } } static void fts5PoslistFilterCallback( Fts5Index *pUnused, - void *pContext, + void *pContext, const u8 *pChunk, int nChunk ){ PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; UNUSED_PARAM(pUnused); assert_nc( nChunk>=0 ); @@ -246322,11 +194145,11 @@ u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset]; int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset); int pgno = pSeg->iLeafPgno; int pgnoSave = 0; - /* This function does not work with detail=none databases. */ + /* This function does notmwork with detail=none databases. */ assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE ); if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){ pgnoSave = pgno+1; } @@ -246335,13 +194158,10 @@ xChunk(p, pCtx, pChunk, nChunk); nRem -= nChunk; fts5DataRelease(pData); if( nRem<=0 ){ break; - }else if( pSeg->pSeg==0 ){ - p->rc = FTS5_CORRUPT; - return; }else{ pgno++; pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); if( pData==0 ) break; pChunk = &pData->p[4]; @@ -246365,16 +194185,11 @@ Fts5Index *p, Fts5SegIter *pSeg, Fts5Colset *pColset, Fts5Buffer *pBuf ){ - assert( pBuf!=0 ); - assert( pSeg!=0 ); - if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){ - assert( pBuf->p!=0 ); - assert( pBuf->nSpace >= pBuf->n+pSeg->nPos+FTS5_DATA_ZERO_PADDING ); - memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING); + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ if( pColset==0 ){ fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); }else{ if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ PoslistCallbackCtx sCtx; @@ -246393,76 +194208,70 @@ } } } /* -** Parameter pPos points to a buffer containing a position list, size nPos. -** This function filters it according to pColset (which must be non-NULL) -** and sets pIter->base.pData/nData to point to the new position list. -** If memory is required for the new position list, use buffer pIter->poslist. -** Or, if the new position list is a contiguous subset of the input, set -** pIter->base.pData/nData to point directly to it. -** -** This function is a no-op if *pRc is other than SQLITE_OK when it is -** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM -** before returning. +** IN/OUT parameter (*pa) points to a position list n bytes in size. If +** the position list contains entries for column iCol, then (*pa) is set +** to point to the sub-position-list for that column and the number of +** bytes in it returned. Or, if the argument position list does not +** contain any entries for column iCol, return 0. */ +static int fts5IndexExtractCol( + const u8 **pa, /* IN/OUT: Pointer to poslist */ + int n, /* IN: Size of poslist in bytes */ + int iCol /* Column to extract from poslist */ +){ + int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ + const u8 *p = *pa; + const u8 *pEnd = &p[n]; /* One byte past end of position list */ + + while( iCol>iCurrent ){ + /* Advance pointer p until it points to pEnd or an 0x01 byte that is + ** not part of a varint. Note that it is not possible for a negative + ** or extremely large varint to occur within an uncorrupted position + ** list. So the last byte of each varint may be assumed to have a clear + ** 0x80 bit. */ + while( *p!=0x01 ){ + while( *p++ & 0x80 ); + if( p>=pEnd ) return 0; + } + *pa = p++; + iCurrent = *p++; + if( iCurrent & 0x80 ){ + p--; + p += fts5GetVarint32(p, iCurrent); + } + } + if( iCol!=iCurrent ) return 0; + + /* Advance pointer p until it points to pEnd or an 0x01 byte that is + ** not part of a varint */ + while( pnCol>1 && sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){ - return; - } - - while( 1 ){ - while( pColset->aiCol[i]nCol ){ - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; - return; - } - } - - /* Advance pointer p until it points to pEnd or an 0x01 byte that is - ** not part of a varint */ - while( paiCol[i]==iCurrent ){ - if( pColset->nCol==1 ){ - pIter->base.pData = aCopy; - pIter->base.nData = p-aCopy; - return; - } - fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy); - } - if( p>=pEnd ){ - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; - return; - } - aCopy = p++; - iCurrent = *p++; - if( iCurrent & 0x80 ){ - p--; - p += fts5GetVarint32(p, iCurrent); - } - } - } - + int i; + fts5BufferZero(pBuf); + for(i=0; inCol; i++){ + const u8 *pSub = pPos; + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); + if( nSub ){ + fts5BufferAppendBlob(pRc, pBuf, nSub, pSub); + } + } + } } /* ** xSetOutputs callback used by detail=none tables. */ @@ -246482,11 +194291,11 @@ assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); assert( pIter->pColset==0 ); if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ - /* All data is stored on the current page. Populate the output + /* All data is stored on the current page. Populate the output ** variables to point into the body of the page object. */ pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; }else{ /* The data is distributed over two or more pages. Copy it into the ** Fts5Iter.poslist buffer and then set the output pointer to point @@ -246518,17 +194327,17 @@ pIter->base.pData = pIter->poslist.p; pIter->base.nData = pIter->poslist.n; } /* -** xSetOutputs callback used when: +** xSetOutputs callback used when: ** ** * detail=col, ** * there is a column filter, and -** * the table contains 100 or fewer columns. +** * the table contains 100 or fewer columns. ** -** The last point is to ensure all column numbers are stored as +** The last point is to ensure all column numbers are stored as ** single-byte varints. */ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); @@ -246536,11 +194345,11 @@ if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ fts5IterSetOutputs_Col(pIter, pSeg); }else{ u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; - u8 *pEnd = (u8*)&a[pSeg->nPos]; + u8 *pEnd = (u8*)&a[pSeg->nPos]; int iPrev = 0; int *aiCol = pIter->pColset->aiCol; int *aiColEnd = &aiCol[pIter->pColset->nCol]; u8 *aOut = pIter->poslist.p; @@ -246575,16 +194384,23 @@ assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); assert( pColset ); if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ - /* All data is stored on the current page. Populate the output + /* All data is stored on the current page. Populate the output ** variables to point into the body of the page object. */ const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; - int *pRc = &pIter->pIndex->rc; - fts5BufferZero(&pIter->poslist); - fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter); + if( pColset->nCol==1 ){ + pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); + pIter->base.pData = a; + }else{ + int *pRc = &pIter->pIndex->rc; + fts5BufferZero(&pIter->poslist); + fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } }else{ /* The data is distributed over two or more pages. Copy it into the ** Fts5Iter.poslist buffer and then set the output pointer to point ** to this buffer. */ fts5BufferZero(&pIter->poslist); @@ -246593,11 +194409,10 @@ pIter->base.nData = pIter->poslist.n; } } static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ - assert( pIter!=0 || (*pRc)!=SQLITE_OK ); if( *pRc==SQLITE_OK ){ Fts5Config *pConfig = pIter->pIndex->pConfig; if( pConfig->eDetail==FTS5_DETAIL_NONE ){ pIter->xSetOutputs = fts5IterSetOutputs_None; } @@ -246624,46 +194439,20 @@ } } } } -/* -** All the component segment-iterators of pIter have been set up. This -** functions finishes setup for iterator pIter itself. -*/ -static void fts5MultiIterFinishSetup(Fts5Index *p, Fts5Iter *pIter){ - int iIter; - for(iIter=pIter->nSeg-1; iIter>0; iIter--){ - int iEq; - if( (iEq = fts5MultiIterDoCompare(pIter, iIter)) ){ - Fts5SegIter *pSeg = &pIter->aSeg[iEq]; - if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); - fts5MultiIterAdvanced(p, pIter, iEq, iIter); - } - } - fts5MultiIterSetEof(pIter); - fts5AssertMultiIterSetup(p, pIter); - - if( (pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter)) - || fts5MultiIterIsDeleted(pIter) - ){ - fts5MultiIterNext(p, pIter, 0, 0); - }else if( pIter->base.bEof==0 ){ - Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; - pIter->xSetOutputs(pIter, pSeg); - } -} /* ** Allocate a new Fts5Iter object. ** ** The new object will be used to iterate through data in structure pStruct. ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel ** is zero or greater, data from the first nSegment segments on level iLevel ** is merged. ** -** The iterator initially points to the first term/rowid entry in the +** The iterator initially points to the first term/rowid entry in the ** iterated data. */ static void fts5MultiIterNew( Fts5Index *p, /* FTS5 backend to iterate within */ Fts5Structure *pStruct, /* Structure of specific index */ @@ -246685,32 +194474,31 @@ /* Allocate space for the new multi-seg-iterator. */ if( p->rc==SQLITE_OK ){ if( iLevel<0 ){ assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); nSeg = pStruct->nSegment; - nSeg += (p->pHash && 0==(flags & FTS5INDEX_QUERY_SKIPHASH)); + nSeg += (p->pHash ? 1 : 0); }else{ nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); } } *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); - if( pNew==0 ){ - assert( p->rc!=SQLITE_OK ); - goto fts5MultiIterNew_post_check; - } + if( pNew==0 ) return; pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); + pNew->pStruct = pStruct; pNew->pColset = pColset; + fts5StructureRef(pStruct); if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ fts5IterSetOutputCb(&p->rc, pNew); } /* Initialize each of the component segment iterators. */ if( p->rc==SQLITE_OK ){ if( iLevel<0 ){ Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; - if( p->pHash && 0==(flags & FTS5INDEX_QUERY_SKIPHASH) ){ + if( p->pHash ){ /* Add a segment iterator for the current contents of the hash table. */ Fts5SegIter *pIter = &pNew->aSeg[iIter++]; fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); } for(pLvl=&pStruct->aLevel[0]; pLvlrc==SQLITE_OK ){ - fts5MultiIterFinishSetup(p, pNew); + for(iIter=pNew->nSeg-1; iIter>0; iIter--){ + int iEq; + if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ + Fts5SegIter *pSeg = &pNew->aSeg[iEq]; + if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); + fts5MultiIterAdvanced(p, pNew, iEq, iIter); + } + } + fts5MultiIterSetEof(pNew); + fts5AssertMultiIterSetup(p, pNew); + + if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ + fts5MultiIterNext(p, pNew, 0, 0); + }else if( pNew->base.bEof==0 ){ + Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; + pNew->xSetOutputs(pNew, pSeg); + } + }else{ fts5MultiIterFree(pNew); *ppOut = 0; } - -fts5MultiIterNew_post_check: - assert( (*ppOut)!=0 || p->rc!=SQLITE_OK ); - return; } /* ** Create an Fts5Iter that iterates through the doclist provided ** as the second argument. @@ -246761,10 +194562,11 @@ ){ Fts5Iter *pNew; pNew = fts5MultiIterAlloc(p, 2); if( pNew ){ Fts5SegIter *pIter = &pNew->aSeg[1]; + pIter->flags = FTS5_SEGITER_ONETERM; if( pData->szLeaf>0 ){ pIter->pLeaf = pData; pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); pIter->iEndofDoclist = pData->nn; @@ -246787,17 +194589,16 @@ fts5DataRelease(pData); } /* -** Return true if the iterator is at EOF or if an error has occurred. +** Return true if the iterator is at EOF or if an error has occurred. ** False otherwise. */ static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ - assert( pIter!=0 || p->rc!=SQLITE_OK ); - assert( p->rc!=SQLITE_OK - || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof + assert( p->rc + || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof ); return (p->rc || pIter->base.bEof); } /* @@ -246812,12 +194613,12 @@ /* ** Move the iterator to the next entry at or following iMatch. */ static void fts5MultiIterNextFrom( - Fts5Index *p, - Fts5Iter *pIter, + Fts5Index *p, + Fts5Iter *pIter, i64 iMatch ){ while( 1 ){ i64 iRowid; fts5MultiIterNext(p, pIter, 1, iMatch); @@ -246827,11 +194628,11 @@ if( pIter->bRev!=0 && iRowid<=iMatch ) break; } } /* -** Return a pointer to a buffer containing the term associated with the +** Return a pointer to a buffer containing the term associated with the ** entry that the iterator currently points to. */ static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; *pn = p->term.n; @@ -246838,15 +194639,15 @@ return p->term.p; } /* ** Allocate a new segment-id for the structure pStruct. The new segment -** id must be between 1 and 65335 inclusive, and must not be used by +** id must be between 1 and 65335 inclusive, and must not be used by ** any currently existing segment. If a free segment id cannot be found, ** SQLITE_FULL is returned. ** -** If an error has already occurred, this function is a no-op. 0 is +** If an error has already occurred, this function is a no-op. 0 is ** returned in this case. */ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ int iSegid = 0; @@ -246862,38 +194663,37 @@ u32 mask; memset(aUsed, 0, sizeof(aUsed)); for(iLvl=0; iLvlnLevel; iLvl++){ for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid; - if( iId<=FTS5_MAX_SEGMENT && iId>0 ){ - aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32); + if( iId<=FTS5_MAX_SEGMENT ){ + aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32); } } } for(i=0; aUsed[i]==0xFFFFFFFF; i++); mask = aUsed[i]; - for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++); + for(iSegid=0; mask & (1 << iSegid); iSegid++); iSegid += 1 + i*32; #ifdef SQLITE_DEBUG for(iLvl=0; iLvlnLevel; iLvl++){ for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ - assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ); + assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ); } } - assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT ); + assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT ); { sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p); if( p->rc==SQLITE_OK ){ u8 aBlob[2] = {0xff, 0xff}; sqlite3_bind_int(pIdxSelect, 1, iSegid); sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC); - assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW ); + assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW ); p->rc = sqlite3_reset(pIdxSelect); - sqlite3_bind_null(pIdxSelect, 2); } } #endif } } @@ -246907,21 +194707,18 @@ static void fts5IndexDiscardData(Fts5Index *p){ assert( p->pHash || p->nPendingData==0 ); if( p->pHash ){ sqlite3Fts5HashClear(p->pHash); p->nPendingData = 0; - p->nPendingRow = 0; - p->flushRc = SQLITE_OK; } - p->nContentlessDelete = 0; } /* -** Return the size of the prefix, in bytes, that buffer +** Return the size of the prefix, in bytes, that buffer ** (pNew/) shares with buffer (pOld/nOld). ** -** Buffer (pNew/) is guaranteed to be greater +** Buffer (pNew/) is guaranteed to be greater ** than buffer (pOld/nOld). */ static int fts5PrefixCompress(int nOld, const u8 *pOld, const u8 *pNew){ int i; for(i=0; inDlidx>0 && pWriter->aDlidx[0].buf.n>0) ); @@ -246940,11 +194737,11 @@ for(i=0; inDlidx; i++){ Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i]; if( pDlidx->buf.n==0 ) break; if( bFlush ){ assert( pDlidx->pgno!=0 ); - fts5DataWrite(p, + fts5DataWrite(p, FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno), pDlidx->buf.p, pDlidx->buf.n ); } sqlite3Fts5BufferZero(&pDlidx->buf); @@ -246960,17 +194757,17 @@ Fts5Index *p, Fts5SegWriter *pWriter, int nLvl ){ if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){ - Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64( + Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc( pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl ); if( aDlidx==0 ){ p->rc = SQLITE_NOMEM; }else{ - size_t nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx); + int nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx); memset(&aDlidx[pWriter->nDlidx], 0, nByte); pWriter->aDlidx = aDlidx; pWriter->nDlidx = nLvl; } } @@ -246994,12 +194791,12 @@ pWriter->nEmpty = 0; return bFlag; } /* -** This function is called whenever processing of the doclist for the -** last term on leaf page (pWriter->iBtPage) is completed. +** This function is called whenever processing of the doclist for the +** last term on leaf page (pWriter->iBtPage) is completed. ** ** The doclist-index for that term is currently stored in-memory within the ** Fts5SegWriter.aDlidx[] array. If it is large enough, this function ** writes it out to disk. Or, if it is too small to bother with, discards ** it. @@ -247019,11 +194816,10 @@ /* sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid); */ sqlite3_bind_blob(p->pIdxWriter, 2, z, pWriter->btterm.n, SQLITE_STATIC); sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1)); sqlite3_step(p->pIdxWriter); p->rc = sqlite3_reset(p->pIdxWriter); - sqlite3_bind_null(p->pIdxWriter, 2); } pWriter->iBtPage = 0; } /* @@ -247039,14 +194835,12 @@ Fts5Index *p, /* FTS5 backend object */ Fts5SegWriter *pWriter, /* Writer object */ int nTerm, const u8 *pTerm /* First term on new page */ ){ fts5WriteFlushBtree(p, pWriter); - if( p->rc==SQLITE_OK ){ - fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm); - pWriter->iBtPage = pWriter->writer.pgno; - } + fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm); + pWriter->iBtPage = pWriter->writer.pgno; } /* ** This function is called when flushing a leaf page that contains no ** terms at all to disk. @@ -247080,12 +194874,12 @@ ** Rowid iRowid has just been appended to the current leaf page. It is the ** first on the page. This function appends an appropriate entry to the current ** doclist-index. */ static void fts5WriteDlidxAppend( - Fts5Index *p, - Fts5SegWriter *pWriter, + Fts5Index *p, + Fts5SegWriter *pWriter, i64 iRowid ){ int i; int bDone = 0; @@ -247094,15 +194888,15 @@ Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i]; if( pDlidx->buf.n>=p->pConfig->pgsz ){ /* The current doclist-index page is full. Write it to disk and push ** a copy of iRowid (which will become the first rowid on the next - ** doclist-index leaf page) up into the next level of the b-tree + ** doclist-index leaf page) up into the next level of the b-tree ** hierarchy. If the node being flushed is currently the root node, ** also push its first rowid upwards. */ pDlidx->buf.p[0] = 0x01; /* Not the root node */ - fts5DataWrite(p, + fts5DataWrite(p, FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno), pDlidx->buf.p, pDlidx->buf.n ); fts5WriteDlidxGrow(p, pWriter, i+2); pDlidx = &pWriter->aDlidx[i]; @@ -247124,11 +194918,11 @@ }else{ bDone = 1; } if( pDlidx->bPrevValid ){ - iVal = (u64)iRowid - (u64)pDlidx->iPrev; + iVal = iRowid - pDlidx->iPrev; }else{ i64 iPgno = (i==0 ? pWriter->writer.pgno : pDlidx[-1].pgno); assert( pDlidx->buf.n==0 ); sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, !bDone); sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iPgno); @@ -247182,36 +194976,34 @@ /* ** Append term pTerm/nTerm to the segment being written by the writer passed ** as the second argument. ** -** If an error occurs, set the Fts5Index.rc error code. If an error has +** If an error occurs, set the Fts5Index.rc error code. If an error has ** already occurred, this function is a no-op. */ static void fts5WriteAppendTerm( - Fts5Index *p, + Fts5Index *p, Fts5SegWriter *pWriter, - int nTerm, const u8 *pTerm + int nTerm, const u8 *pTerm ){ int nPrefix; /* Bytes of prefix compression for term */ Fts5PageWriter *pPage = &pWriter->writer; Fts5Buffer *pPgidx = &pWriter->writer.pgidx; - int nMin = MIN(pPage->term.n, nTerm); assert( p->rc==SQLITE_OK ); assert( pPage->buf.n>=4 ); assert( pPage->buf.n>4 || pWriter->bFirstTermInPage ); /* If the current leaf page is full, flush it to disk. */ if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){ if( pPage->buf.n>4 ){ fts5WriteFlushLeaf(p, pWriter); - if( p->rc!=SQLITE_OK ) return; } fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING); } - + /* TODO1: Updating pgidx here. */ pPgidx->n += sqlite3Fts5PutVarint( &pPgidx->p[pPgidx->n], pPage->buf.n - pPage->iPrevPgidx ); pPage->iPrevPgidx = pPage->buf.n; @@ -247223,31 +195015,30 @@ if( pWriter->bFirstTermInPage ){ nPrefix = 0; if( pPage->pgno!=1 ){ /* This is the first term on a leaf that is not the leftmost leaf in ** the segment b-tree. In this case it is necessary to add a term to - ** the b-tree hierarchy that is (a) larger than the largest term + ** the b-tree hierarchy that is (a) larger than the largest term ** already written to the segment and (b) smaller than or equal to ** this term. In other words, a prefix of (pTerm/nTerm) that is one ** byte longer than the longest prefix (pTerm/nTerm) shares with the - ** previous term. + ** previous term. ** ** Usually, the previous term is available in pPage->term. The exception ** is if this is the first term written in an incremental-merge step. ** In this case the previous term is not available, so just write a ** copy of (pTerm/nTerm) into the parent node. This is slightly ** inefficient, but still correct. */ int n = nTerm; if( pPage->term.n ){ - n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm); + n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); } fts5WriteBtreeTerm(p, pWriter, n, pTerm); - if( p->rc!=SQLITE_OK ) return; pPage = &pWriter->writer; } }else{ - nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm); + nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix); } /* Append the number of bytes of new data, then the term data itself ** to the page. */ @@ -247264,14 +195055,14 @@ assert( p->rc || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n==0) ); pWriter->aDlidx[0].pgno = pPage->pgno; } /* -** Append a rowid and position-list size field to the writers output. +** Append a rowid and position-list size field to the writers output. */ static void fts5WriteAppendRowid( - Fts5Index *p, + Fts5Index *p, Fts5SegWriter *pWriter, i64 iRowid ){ if( p->rc==SQLITE_OK ){ Fts5PageWriter *pPage = &pWriter->writer; @@ -247278,11 +195069,11 @@ if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){ fts5WriteFlushLeaf(p, pWriter); } - /* If this is to be the first rowid written to the page, set the + /* If this is to be the first rowid written to the page, set the ** rowid-pointer in the page-header. Also append a value to the dlidx ** buffer, in case a doclist-index is required. */ if( pWriter->bFirstRowidInPage ){ fts5PutU16(pPage->buf.p, (u16)pPage->buf.n); fts5WriteDlidxAppend(p, pWriter, iRowid); @@ -247290,34 +195081,32 @@ /* Write the rowid. */ if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){ fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid); }else{ - assert_nc( p->rc || iRowid>pWriter->iPrevRowid ); - fts5BufferAppendVarint(&p->rc, &pPage->buf, - (u64)iRowid - (u64)pWriter->iPrevRowid - ); + assert( p->rc || iRowid>pWriter->iPrevRowid ); + fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid); } pWriter->iPrevRowid = iRowid; pWriter->bFirstRowidInDoclist = 0; pWriter->bFirstRowidInPage = 0; } } static void fts5WriteAppendPoslistData( - Fts5Index *p, - Fts5SegWriter *pWriter, - const u8 *aData, + Fts5Index *p, + Fts5SegWriter *pWriter, + const u8 *aData, int nData ){ Fts5PageWriter *pPage = &pWriter->writer; const u8 *a = aData; int n = nData; - - assert( p->pConfig->pgsz>0 || p->rc!=SQLITE_OK ); - while( p->rc==SQLITE_OK - && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz + + assert( p->pConfig->pgsz>0 ); + while( p->rc==SQLITE_OK + && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz ){ int nReq = p->pConfig->pgsz - pPage->buf.n - pPage->pgidx.n; int nCopy = 0; while( nCopywriter; @@ -247364,12 +195153,12 @@ } sqlite3_free(pWriter->aDlidx); } static void fts5WriteInit( - Fts5Index *p, - Fts5SegWriter *pWriter, + Fts5Index *p, + Fts5SegWriter *pWriter, int iSegid ){ const int nBuffer = p->pConfig->pgsz + FTS5_DATA_PADDING; memset(pWriter, 0, sizeof(Fts5SegWriter)); @@ -247388,11 +195177,11 @@ sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.buf, nBuffer); if( p->pIdxWriter==0 ){ Fts5Config *pConfig = p->pConfig; fts5IndexPrepareStmt(p, &p->pIdxWriter, sqlite3_mprintf( - "INSERT INTO '%q'.'%q_idx'(segid,term,pgno) VALUES(?,?,?)", + "INSERT INTO '%q'.'%q_idx'(segid,term,pgno) VALUES(?,?,?)", pConfig->zDb, pConfig->zName )); } if( p->rc==SQLITE_OK ){ @@ -247414,11 +195203,11 @@ */ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ int i; Fts5Buffer buf; memset(&buf, 0, sizeof(Fts5Buffer)); - for(i=0; inSeg && p->rc==SQLITE_OK; i++){ + for(i=0; inSeg; i++){ Fts5SegIter *pSeg = &pIter->aSeg[i]; if( pSeg->pSeg==0 ){ /* no-op */ }else if( pSeg->pLeaf==0 ){ /* All keys from this input segment have been transfered to the output. @@ -247432,57 +195221,48 @@ Fts5Data *pData; int iId = pSeg->pSeg->iSegid; u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00}; iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno); - pData = fts5LeafRead(p, iLeafRowid); + pData = fts5DataRead(p, iLeafRowid); if( pData ){ - if( iOff>pData->szLeaf ){ - /* This can occur if the pages that the segments occupy overlap - if - ** a single page has been assigned to more than one segment. In - ** this case a prior iteration of this loop may have corrupted the - ** segment currently being trimmed. */ - p->rc = FTS5_CORRUPT; - }else{ - fts5BufferZero(&buf); - fts5BufferGrow(&p->rc, &buf, pData->nn); - fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr); - fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n); - fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p); - fts5BufferAppendBlob(&p->rc, &buf,pData->szLeaf-iOff,&pData->p[iOff]); - if( p->rc==SQLITE_OK ){ - /* Set the szLeaf field */ - fts5PutU16(&buf.p[2], (u16)buf.n); - } - - /* Set up the new page-index array */ - fts5BufferAppendVarint(&p->rc, &buf, 4); - if( pSeg->iLeafPgno==pSeg->iTermLeafPgno - && pSeg->iEndofDoclistszLeaf - && pSeg->iPgidxOff<=pData->nn - ){ - int nDiff = pData->szLeaf - pSeg->iEndofDoclist; - fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4); - fts5BufferAppendBlob(&p->rc, &buf, - pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff] - ); - } - - pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno; - fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid); - fts5DataWrite(p, iLeafRowid, buf.p, buf.n); - } + fts5BufferZero(&buf); + fts5BufferGrow(&p->rc, &buf, pData->nn); + fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n); + fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p); + fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]); + if( p->rc==SQLITE_OK ){ + /* Set the szLeaf field */ + fts5PutU16(&buf.p[2], (u16)buf.n); + } + + /* Set up the new page-index array */ + fts5BufferAppendVarint(&p->rc, &buf, 4); + if( pSeg->iLeafPgno==pSeg->iTermLeafPgno + && pSeg->iEndofDoclistszLeaf + ){ + int nDiff = pData->szLeaf - pSeg->iEndofDoclist; + fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4); + fts5BufferAppendBlob(&p->rc, &buf, + pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff] + ); + } + fts5DataRelease(pData); + pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno; + fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid); + fts5DataWrite(p, iLeafRowid, buf.p, buf.n); } } } fts5BufferFree(&buf); } static void fts5MergeChunkCallback( - Fts5Index *p, - void *pCtx, + Fts5Index *p, + void *pCtx, const u8 *pChunk, int nChunk ){ Fts5SegWriter *pWriter = (Fts5SegWriter*)pCtx; fts5WriteAppendPoslistData(p, pWriter, pChunk, nChunk); } @@ -247547,16 +195327,10 @@ pSeg->iSegid = iSegid; pStruct->nSegment++; /* Read input from all segments in the input level */ nInput = pLvl->nSeg; - - /* Set the range of origins that will go into the output segment. */ - if( pStruct->nOriginCntr>0 ){ - pSeg->iOrigin1 = pLvl->aSeg[0].iOrigin1; - pSeg->iOrigin2 = pLvl->aSeg[pLvl->nSeg-1].iOrigin2; - } } bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); assert( iLvl>=0 ); for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter); @@ -247567,11 +195341,11 @@ int nPos; /* position-list size field value */ int nTerm; const u8 *pTerm; pTerm = fts5MultiIterTerm(pIter, &nTerm); - if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){ + if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){ if( pnRem && writer.nLeafWritten>nRem ){ break; } fts5BufferSet(&p->rc, &term, nTerm, pTerm); bTermWritten =0; @@ -247607,20 +195381,16 @@ /* Flush the last leaf page to disk. Set the output segment b-tree height ** and last leaf page number at the same time. */ fts5WriteFinish(p, &writer, &pSeg->pgnoLast); - assert( pIter!=0 || p->rc!=SQLITE_OK ); if( fts5MultiIterEof(p, pIter) ){ int i; /* Remove the redundant segments from the %_data table */ - assert( pSeg->nEntry==0 ); for(i=0; iaSeg[i]; - pSeg->nEntry += (pOld->nEntry - pOld->nEntryTombstone); - fts5DataRemoveSegment(p, pOld); + fts5DataRemoveSegment(p, pLvl->aSeg[i].iSegid); } /* Remove the redundant segments from the input level */ if( pLvl->nSeg!=nInput ){ int nMove = (pLvl->nSeg - nInput) * sizeof(Fts5StructureSegment); @@ -247642,52 +195412,10 @@ fts5MultiIterFree(pIter); fts5BufferFree(&term); if( pnRem ) *pnRem -= writer.nLeafWritten; } -/* -** If this is not a contentless_delete=1 table, or if the 'deletemerge' -** configuration option is set to 0, then this function always returns -1. -** Otherwise, it searches the structure object passed as the second argument -** for a level suitable for merging due to having a large number of -** tombstones in the tombstone hash. If one is found, its index is returned. -** Otherwise, if there is no suitable level, -1. -*/ -static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){ - Fts5Config *pConfig = p->pConfig; - int iRet = -1; - if( pConfig->bContentlessDelete && pConfig->nDeleteMerge>0 ){ - int ii; - int nBest = 0; - - for(ii=0; iinLevel; ii++){ - Fts5StructureLevel *pLvl = &pStruct->aLevel[ii]; - i64 nEntry = 0; - i64 nTomb = 0; - int iSeg; - for(iSeg=0; iSegnSeg; iSeg++){ - nEntry += pLvl->aSeg[iSeg].nEntry; - nTomb += pLvl->aSeg[iSeg].nEntryTombstone; - } - assert_nc( nEntry>0 || pLvl->nSeg==0 ); - if( nEntry>0 ){ - int nPercent = (nTomb * 100) / nEntry; - if( nPercent>=pConfig->nDeleteMerge && nPercent>nBest ){ - iRet = ii; - nBest = nPercent; - } - } - - /* If pLvl is already the input level to an ongoing merge, look no - ** further for a merge candidate. The caller should be allowed to - ** continue merging from pLvl first. */ - if( pLvl->nMerge ) break; - } - } - return iRet; -} - /* ** Do up to nPg pages of automerge work on the index. ** ** Return true if any changes were actually made, or false otherwise. */ @@ -247703,39 +195431,42 @@ while( nRem>0 && p->rc==SQLITE_OK ){ int iLvl; /* To iterate through levels */ int iBestLvl = 0; /* Level offering the most input segments */ int nBest = 0; /* Number of input segments on best level */ - /* Set iBestLvl to the level to read input segments from. Or to -1 if - ** there is no level suitable to merge segments from. */ + /* Set iBestLvl to the level to read input segments from. */ assert( pStruct->nLevel>0 ); for(iLvl=0; iLvlnLevel; iLvl++){ Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; if( pLvl->nMerge ){ if( pLvl->nMerge>nBest ){ iBestLvl = iLvl; - nBest = nMin; + nBest = pLvl->nMerge; } break; } if( pLvl->nSeg>nBest ){ nBest = pLvl->nSeg; iBestLvl = iLvl; } } - if( nBestnLevel; iLvl++){ + assert( pStruct->aLevel[iLvl].nSeg==0 ); } +#endif - if( iBestLvl<0 ) break; + if( nBestaLevel[iBestLvl].nMerge==0 ){ + break; + } bRet = 1; fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem); if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){ fts5StructurePromote(p, iBestLvl+1, pStruct); } - - if( nMin==1 ) nMin = 2; } *ppStruct = pStruct; return bRet; } @@ -247742,19 +195473,19 @@ /* ** A total of nLeaf leaf pages of data has just been flushed to a level-0 ** segment. This function updates the write-counter accordingly and, if ** necessary, performs incremental merge work. ** -** If an error occurs, set the Fts5Index.rc error code. If an error has +** If an error occurs, set the Fts5Index.rc error code. If an error has ** already occurred, this function is a no-op. */ static void fts5IndexAutomerge( Fts5Index *p, /* FTS5 backend object */ Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */ int nLeaf /* Number of output leaves just written */ ){ - if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 && ALWAYS((*ppStruct)!=0) ){ + if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){ Fts5Structure *pStruct = *ppStruct; u64 nWrite; /* Initial value of write-counter */ int nWork; /* Number of work-quanta to perform */ int nRem; /* Number of leaf pages left to write */ @@ -247772,45 +195503,37 @@ Fts5Index *p, /* FTS5 backend object */ Fts5Structure **ppStruct /* IN/OUT: Current structure of index */ ){ const int nCrisis = p->pConfig->nCrisisMerge; Fts5Structure *pStruct = *ppStruct; - if( pStruct && pStruct->nLevel>0 ){ - int iLvl = 0; - while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){ - fts5IndexMergeLevel(p, &pStruct, iLvl, 0); - assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) ); - fts5StructurePromote(p, iLvl+1, pStruct); - iLvl++; - } - *ppStruct = pStruct; - } + int iLvl = 0; + + assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 ); + while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){ + fts5IndexMergeLevel(p, &pStruct, iLvl, 0); + assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) ); + fts5StructurePromote(p, iLvl+1, pStruct); + iLvl++; + } + *ppStruct = pStruct; } static int fts5IndexReturn(Fts5Index *p){ int rc = p->rc; p->rc = SQLITE_OK; return rc; } -/* -** Close the read-only blob handle, if it is open. -*/ -static void sqlite3Fts5IndexCloseReader(Fts5Index *p){ - fts5IndexCloseReader(p); - fts5IndexReturn(p); -} - typedef struct Fts5FlushCtx Fts5FlushCtx; struct Fts5FlushCtx { Fts5Index *pIdx; - Fts5SegWriter writer; + Fts5SegWriter writer; }; /* ** Buffer aBuf[] contains a list of varints, all small enough to fit -** in a 32-bit integer. Return the size of the largest prefix of this +** in a 32-bit integer. Return the size of the largest prefix of this ** list nMax bytes or less in size. */ static int fts5PoslistPrefix(const u8 *aBuf, int nMax){ int ret; u32 dummy; @@ -247824,495 +195547,14 @@ } return ret; } /* -** Execute the SQL statement: -** -** DELETE FROM %_idx WHERE (segid, (pgno/2)) = ($iSegid, $iPgno); -** -** This is used when a secure-delete operation removes the last term -** from a segment leaf page. In that case the %_idx entry is removed -** too. This is done to ensure that if all instances of a token are -** removed from an fts5 database in secure-delete mode, no trace of -** the token itself remains in the database. -*/ -static void fts5SecureDeleteIdxEntry( - Fts5Index *p, /* FTS5 backend object */ - int iSegid, /* Id of segment to delete entry for */ - int iPgno /* Page number within segment */ -){ - if( iPgno!=1 ){ - assert( p->pConfig->iVersion==FTS5_CURRENT_VERSION_SECUREDELETE ); - if( p->pDeleteFromIdx==0 ){ - fts5IndexPrepareStmt(p, &p->pDeleteFromIdx, sqlite3_mprintf( - "DELETE FROM '%q'.'%q_idx' WHERE (segid, (pgno/2)) = (?1, ?2)", - p->pConfig->zDb, p->pConfig->zName - )); - } - if( p->rc==SQLITE_OK ){ - sqlite3_bind_int(p->pDeleteFromIdx, 1, iSegid); - sqlite3_bind_int(p->pDeleteFromIdx, 2, iPgno); - sqlite3_step(p->pDeleteFromIdx); - p->rc = sqlite3_reset(p->pDeleteFromIdx); - } - } -} - -/* -** This is called when a secure-delete operation removes a position-list -** that overflows onto segment page iPgno of segment pSeg. This function -** rewrites node iPgno, and possibly one or more of its right-hand peers, -** to remove this portion of the position list. -** -** Output variable (*pbLastInDoclist) is set to true if the position-list -** removed is followed by a new term or the end-of-segment, or false if -** it is followed by another rowid/position list. -*/ -static void fts5SecureDeleteOverflow( - Fts5Index *p, - Fts5StructureSegment *pSeg, - int iPgno, - int *pbLastInDoclist -){ - const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE); - int pgno; - Fts5Data *pLeaf = 0; - assert( iPgno!=1 ); - - *pbLastInDoclist = 1; - for(pgno=iPgno; p->rc==SQLITE_OK && pgno<=pSeg->pgnoLast; pgno++){ - i64 iRowid = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno); - int iNext = 0; - u8 *aPg = 0; - - pLeaf = fts5DataRead(p, iRowid); - if( pLeaf==0 ) break; - aPg = pLeaf->p; - - iNext = fts5GetU16(&aPg[0]); - if( iNext!=0 ){ - *pbLastInDoclist = 0; - } - if( iNext==0 && pLeaf->szLeaf!=pLeaf->nn ){ - fts5GetVarint32(&aPg[pLeaf->szLeaf], iNext); - } - - if( iNext==0 ){ - /* The page contains no terms or rowids. Replace it with an empty - ** page and move on to the right-hand peer. */ - const u8 aEmpty[] = {0x00, 0x00, 0x00, 0x04}; - assert_nc( bDetailNone==0 || pLeaf->nn==4 ); - if( bDetailNone==0 ) fts5DataWrite(p, iRowid, aEmpty, sizeof(aEmpty)); - fts5DataRelease(pLeaf); - pLeaf = 0; - }else if( bDetailNone ){ - break; - }else if( iNext>=pLeaf->szLeaf || pLeaf->nnszLeaf || iNext<4 ){ - p->rc = FTS5_CORRUPT; - break; - }else{ - int nShift = iNext - 4; - int nPg; - - int nIdx = 0; - u8 *aIdx = 0; - - /* Unless the current page footer is 0 bytes in size (in which case - ** the new page footer will be as well), allocate and populate a - ** buffer containing the new page footer. Set stack variables aIdx - ** and nIdx accordingly. */ - if( pLeaf->nn>pLeaf->szLeaf ){ - int iFirst = 0; - int i1 = pLeaf->szLeaf; - int i2 = 0; - - i1 += fts5GetVarint32(&aPg[i1], iFirst); - if( iFirstrc = FTS5_CORRUPT; - break; - } - aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2); - if( aIdx==0 ) break; - i2 = sqlite3Fts5PutVarint(aIdx, iFirst-nShift); - if( i1nn ){ - memcpy(&aIdx[i2], &aPg[i1], pLeaf->nn-i1); - i2 += (pLeaf->nn-i1); - } - nIdx = i2; - } - - /* Modify the contents of buffer aPg[]. Set nPg to the new size - ** in bytes. The new page is always smaller than the old. */ - nPg = pLeaf->szLeaf - nShift; - memmove(&aPg[4], &aPg[4+nShift], nPg-4); - fts5PutU16(&aPg[2], nPg); - if( fts5GetU16(&aPg[0]) ) fts5PutU16(&aPg[0], 4); - if( nIdx>0 ){ - memcpy(&aPg[nPg], aIdx, nIdx); - nPg += nIdx; - } - sqlite3_free(aIdx); - - /* Write the new page to disk and exit the loop */ - assert( nPg>4 || fts5GetU16(aPg)==0 ); - fts5DataWrite(p, iRowid, aPg, nPg); - break; - } - } - fts5DataRelease(pLeaf); -} - -/* -** Completely remove the entry that pSeg currently points to from -** the database. -*/ -static void fts5DoSecureDelete( - Fts5Index *p, - Fts5SegIter *pSeg -){ - const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE); - int iSegid = pSeg->pSeg->iSegid; - u8 *aPg = pSeg->pLeaf->p; - int nPg = pSeg->pLeaf->nn; - int iPgIdx = pSeg->pLeaf->szLeaf; - - u64 iDelta = 0; - int iNextOff = 0; - int iOff = 0; - int nIdx = 0; - u8 *aIdx = 0; - int bLastInDoclist = 0; - int iIdx = 0; - int iStart = 0; - int iDelKeyOff = 0; /* Offset of deleted key, if any */ - - nIdx = nPg-iPgIdx; - aIdx = sqlite3Fts5MallocZero(&p->rc, nIdx+16); - if( p->rc ) return; - memcpy(aIdx, &aPg[iPgIdx], nIdx); - - /* At this point segment iterator pSeg points to the entry - ** this function should remove from the b-tree segment. - ** - ** In detail=full or detail=column mode, pSeg->iLeafOffset is the - ** offset of the first byte in the position-list for the entry to - ** remove. Immediately before this comes two varints that will also - ** need to be removed: - ** - ** + the rowid or delta rowid value for the entry, and - ** + the size of the position list in bytes. - ** - ** Or, in detail=none mode, there is a single varint prior to - ** pSeg->iLeafOffset - the rowid or delta rowid value. - ** - ** This block sets the following variables: - ** - ** iStart: - ** The offset of the first byte of the rowid or delta-rowid - ** value for the doclist entry being removed. - ** - ** iDelta: - ** The value of the rowid or delta-rowid value for the doclist - ** entry being removed. - ** - ** iNextOff: - ** The offset of the next entry following the position list - ** for the one being removed. If the position list for this - ** entry overflows onto the next leaf page, this value will be - ** greater than pLeaf->szLeaf. - */ - { - int iSOP; /* Start-Of-Position-list */ - if( pSeg->iLeafPgno==pSeg->iTermLeafPgno ){ - iStart = pSeg->iTermLeafOffset; - }else{ - iStart = fts5GetU16(&aPg[0]); - } - - iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta); - assert_nc( iSOP<=pSeg->iLeafOffset ); - - if( bDetailNone ){ - while( iSOPiLeafOffset ){ - if( aPg[iSOP]==0x00 ) iSOP++; - if( aPg[iSOP]==0x00 ) iSOP++; - iStart = iSOP; - iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta); - } - - iNextOff = iSOP; - if( iNextOffiEndofDoclist && aPg[iNextOff]==0x00 ) iNextOff++; - if( iNextOffiEndofDoclist && aPg[iNextOff]==0x00 ) iNextOff++; - - }else{ - int nPos = 0; - iSOP += fts5GetVarint32(&aPg[iSOP], nPos); - while( iSOPiLeafOffset ){ - iStart = iSOP + (nPos/2); - iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta); - iSOP += fts5GetVarint32(&aPg[iSOP], nPos); - } - assert_nc( iSOP==pSeg->iLeafOffset ); - iNextOff = pSeg->iLeafOffset + pSeg->nPos; - } - } - - iOff = iStart; - - /* If the position-list for the entry being removed flows over past - ** the end of this page, delete the portion of the position-list on the - ** next page and beyond. - ** - ** Set variable bLastInDoclist to true if this entry happens - ** to be the last rowid in the doclist for its term. */ - if( iNextOff>=iPgIdx ){ - int pgno = pSeg->iLeafPgno+1; - fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist); - iNextOff = iPgIdx; - } - - if( pSeg->bDel==0 ){ - if( iNextOff!=iPgIdx ){ - /* Loop through the page-footer. If iNextOff (offset of the - ** entry following the one we are removing) is equal to the - ** offset of a key on this page, then the entry is the last - ** in its doclist. */ - int iKeyOff = 0; - for(iIdx=0; iIdxbDel ){ - iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta); - aPg[iOff++] = 0x01; - }else if( bLastInDoclist==0 ){ - if( iNextOff!=iPgIdx ){ - u64 iNextDelta = 0; - iNextOff += fts5GetVarint(&aPg[iNextOff], &iNextDelta); - iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta + iNextDelta); - } - }else if( - pSeg->iLeafPgno==pSeg->iTermLeafPgno - && iStart==pSeg->iTermLeafOffset - ){ - /* The entry being removed was the only position list in its - ** doclist. Therefore the term needs to be removed as well. */ - int iKey = 0; - int iKeyOff = 0; - - /* Set iKeyOff to the offset of the term that will be removed - the - ** last offset in the footer that is not greater than iStart. */ - for(iIdx=0; iIdx(u32)iStart ) break; - iKeyOff += iVal; - } - assert_nc( iKey>=1 ); - - /* Set iDelKeyOff to the value of the footer entry to remove from - ** the page. */ - iDelKeyOff = iOff = iKeyOff; - - if( iNextOff!=iPgIdx ){ - /* This is the only position-list associated with the term, and there - ** is another term following it on this page. So the subsequent term - ** needs to be moved to replace the term associated with the entry - ** being removed. */ - int nPrefix = 0; - int nSuffix = 0; - int nPrefix2 = 0; - int nSuffix2 = 0; - - iDelKeyOff = iNextOff; - iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2); - iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2); - - if( iKey!=1 ){ - iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix); - } - iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix); - - nPrefix = MIN(nPrefix, nPrefix2); - nSuffix = (nPrefix2 + nSuffix2) - nPrefix; - - if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ - p->rc = FTS5_CORRUPT; - }else{ - if( iKey!=1 ){ - iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); - } - iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); - if( nPrefix2>pSeg->term.n ){ - p->rc = FTS5_CORRUPT; - }else if( nPrefix2>nPrefix ){ - memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); - iOff += (nPrefix2-nPrefix); - } - memmove(&aPg[iOff], &aPg[iNextOff], nSuffix2); - iOff += nSuffix2; - iNextOff += nSuffix2; - } - } - }else if( iStart==4 ){ - int iPgno; - - assert_nc( pSeg->iLeafPgno>pSeg->iTermLeafPgno ); - /* The entry being removed may be the only position list in - ** its doclist. */ - for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){ - Fts5Data *pPg = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno)); - int bEmpty = (pPg && pPg->nn==4); - fts5DataRelease(pPg); - if( bEmpty==0 ) break; - } - - if( iPgno==pSeg->iTermLeafPgno ){ - i64 iId = FTS5_SEGMENT_ROWID(iSegid, pSeg->iTermLeafPgno); - Fts5Data *pTerm = fts5DataRead(p, iId); - if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){ - u8 *aTermIdx = &pTerm->p[pTerm->szLeaf]; - int nTermIdx = pTerm->nn - pTerm->szLeaf; - int iTermIdx = 0; - int iTermOff = 0; - - while( 1 ){ - u32 iVal = 0; - int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal); - iTermOff += iVal; - if( (iTermIdx+nByte)>=nTermIdx ) break; - iTermIdx += nByte; - } - nTermIdx = iTermIdx; - - memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx); - fts5PutU16(&pTerm->p[2], iTermOff); - - fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx); - if( nTermIdx==0 ){ - fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno); - } - } - fts5DataRelease(pTerm); - } - } - - /* Assuming no error has occurred, this block does final edits to the - ** leaf page before writing it back to disk. Input variables are: - ** - ** nPg: Total initial size of leaf page. - ** iPgIdx: Initial offset of page footer. - ** - ** iOff: Offset to move data to - ** iNextOff: Offset to move data from - */ - if( p->rc==SQLITE_OK ){ - const int nMove = nPg - iNextOff; /* Number of bytes to move */ - int nShift = iNextOff - iOff; /* Distance to move them */ - - int iPrevKeyOut = 0; - int iKeyIn = 0; - - memmove(&aPg[iOff], &aPg[iNextOff], nMove); - iPgIdx -= nShift; - nPg = iPgIdx; - fts5PutU16(&aPg[2], iPgIdx); - - for(iIdx=0; iIdxiOff ? nShift : 0)); - nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOut - iPrevKeyOut); - iPrevKeyOut = iKeyOut; - } - } - - if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){ - fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno); - } - - assert_nc( nPg>4 || fts5GetU16(aPg)==0 ); - fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg, nPg); - } - sqlite3_free(aIdx); -} - -/* -** This is called as part of flushing a delete to disk in 'secure-delete' -** mode. It edits the segments within the database described by argument -** pStruct to remove the entries for term zTerm, rowid iRowid. -*/ -static void fts5FlushSecureDelete( - Fts5Index *p, - Fts5Structure *pStruct, - const char *zTerm, - int nTerm, - i64 iRowid -){ - const int f = FTS5INDEX_QUERY_SKIPHASH; - Fts5Iter *pIter = 0; /* Used to find term instance */ - - /* If the version number has not been set to SECUREDELETE, do so now. */ - if( p->pConfig->iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE ){ - Fts5Config *pConfig = p->pConfig; - sqlite3_stmt *pStmt = 0; - fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf( - "REPLACE INTO %Q.'%q_config' VALUES ('version', %d)", - pConfig->zDb, pConfig->zName, FTS5_CURRENT_VERSION_SECUREDELETE - )); - if( p->rc==SQLITE_OK ){ - int rc; - sqlite3_step(pStmt); - rc = sqlite3_finalize(pStmt); - if( p->rc==SQLITE_OK ) p->rc = rc; - pConfig->iCookie++; - pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE; - } - } - - fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter); - if( fts5MultiIterEof(p, pIter)==0 ){ - i64 iThis = fts5MultiIterRowid(pIter); - if( iThisrc==SQLITE_OK - && fts5MultiIterEof(p, pIter)==0 - && iRowid==fts5MultiIterRowid(pIter) - ){ - Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; - fts5DoSecureDelete(p, pSeg); - } - } - - fts5MultiIterFree(pIter); -} - - -/* -** Flush the contents of in-memory hash table iHash to a new level-0 +** Flush the contents of in-memory hash table iHash to a new level-0 ** segment on disk. Also update the corresponding structure record. ** -** If an error occurs, set the Fts5Index.rc error code. If an error has +** If an error occurs, set the Fts5Index.rc error code. If an error has ** already occurred, this function is a no-op. */ static void fts5FlushOneHash(Fts5Index *p){ Fts5Hash *pHash = p->pHash; Fts5Structure *pStruct; @@ -248320,201 +195562,145 @@ int pgnoLast = 0; /* Last leaf page number in segment */ /* Obtain a reference to the index structure and allocate a new segment-id ** for the new level-0 segment. */ pStruct = fts5StructureRead(p); - fts5StructureInvalidate(p); - - if( sqlite3Fts5HashIsEmpty(pHash)==0 ){ - iSegid = fts5AllocateSegid(p, pStruct); - if( iSegid ){ - const int pgsz = p->pConfig->pgsz; - int eDetail = p->pConfig->eDetail; - int bSecureDelete = p->pConfig->bSecureDelete; - Fts5StructureSegment *pSeg; /* New segment within pStruct */ - Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */ - Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */ - - Fts5SegWriter writer; - fts5WriteInit(p, &writer, iSegid); - - pBuf = &writer.writer.buf; - pPgidx = &writer.writer.pgidx; - - /* fts5WriteInit() should have initialized the buffers to (most likely) - ** the maximum space required. */ - assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) ); - assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) ); - - /* Begin scanning through hash table entries. This loop runs once for each - ** term/doclist currently stored within the hash table. */ - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); - } - while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ - const char *zTerm; /* Buffer containing term */ - int nTerm; /* Size of zTerm in bytes */ - const u8 *pDoclist; /* Pointer to doclist for this term */ - int nDoclist; /* Size of doclist in bytes */ - - /* Get the term and doclist for this entry. */ - sqlite3Fts5HashScanEntry(pHash, &zTerm, &nTerm, &pDoclist, &nDoclist); - if( bSecureDelete==0 ){ - fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); - if( p->rc!=SQLITE_OK ) break; - assert( writer.bFirstRowidInPage==0 ); - } - - if( !bSecureDelete && pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){ - /* The entire doclist will fit on the current leaf. */ - fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist); - }else{ - int bTermWritten = !bSecureDelete; - i64 iRowid = 0; - i64 iPrev = 0; - int iOff = 0; - - /* The entire doclist will not fit on this leaf. The following - ** loop iterates through the poslists that make up the current - ** doclist. */ - while( p->rc==SQLITE_OK && iOffrc!=SQLITE_OK || pDoclist[iOff]==0x01 ){ - iOff++; - continue; - } - } - } - - if( p->rc==SQLITE_OK && bTermWritten==0 ){ - fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); - bTermWritten = 1; - assert( p->rc!=SQLITE_OK || writer.bFirstRowidInPage==0 ); - } - - if( writer.bFirstRowidInPage ){ - fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */ - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid); - writer.bFirstRowidInPage = 0; - fts5WriteDlidxAppend(p, &writer, iRowid); - }else{ - u64 iRowidDelta = (u64)iRowid - (u64)iPrev; - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowidDelta); - } - if( p->rc!=SQLITE_OK ) break; - assert( pBuf->n<=pBuf->nSpace ); - iPrev = iRowid; - - if( eDetail==FTS5_DETAIL_NONE ){ - if( iOffp[pBuf->n++] = 0; - iOff++; - if( iOffp[pBuf->n++] = 0; - iOff++; - } - } - if( (pBuf->n + pPgidx->n)>=pgsz ){ - fts5WriteFlushLeaf(p, &writer); - } - }else{ - int bDel = 0; - int nPos = 0; - int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDel); - if( bDel && bSecureDelete ){ - fts5BufferAppendVarint(&p->rc, pBuf, nPos*2); - iOff += nCopy; - nCopy = nPos; - }else{ - nCopy += nPos; - } - if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ - /* The entire poslist will fit on the current leaf. So copy - ** it in one go. */ - fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); - }else{ - /* The entire poslist will not fit on this leaf. So it needs - ** to be broken into sections. The only qualification being - ** that each varint must be stored contiguously. */ - const u8 *pPoslist = &pDoclist[iOff]; - int iPos = 0; - while( p->rc==SQLITE_OK ){ - int nSpace = pgsz - pBuf->n - pPgidx->n; - int n = 0; - if( (nCopy - iPos)<=nSpace ){ - n = nCopy - iPos; - }else{ - n = fts5PoslistPrefix(&pPoslist[iPos], nSpace); - } - assert( n>0 ); - fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n); - iPos += n; - if( (pBuf->n + pPgidx->n)>=pgsz ){ - fts5WriteFlushLeaf(p, &writer); - } - if( iPos>=nCopy ) break; - } - } - iOff += nCopy; - } - } - } - - /* TODO2: Doclist terminator written here. */ - /* pBuf->p[pBuf->n++] = '\0'; */ - assert( pBuf->n<=pBuf->nSpace ); - if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); - } - fts5WriteFinish(p, &writer, &pgnoLast); - - assert( p->rc!=SQLITE_OK || bSecureDelete || pgnoLast>0 ); - if( pgnoLast>0 ){ - /* Update the Fts5Structure. It is written back to the database by the - ** fts5StructureRelease() call below. */ - if( pStruct->nLevel==0 ){ - fts5StructureAddLevel(&p->rc, &pStruct); - } - fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0); - if( p->rc==SQLITE_OK ){ - pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ]; - pSeg->iSegid = iSegid; - pSeg->pgnoFirst = 1; - pSeg->pgnoLast = pgnoLast; - if( pStruct->nOriginCntr>0 ){ - pSeg->iOrigin1 = pStruct->nOriginCntr; - pSeg->iOrigin2 = pStruct->nOriginCntr; - pSeg->nEntry = p->nPendingRow; - pStruct->nOriginCntr++; - } - pStruct->nSegment++; - } - fts5StructurePromote(p, 0, pStruct); - } - } - } - - fts5IndexAutomerge(p, &pStruct, pgnoLast + p->nContentlessDelete); + iSegid = fts5AllocateSegid(p, pStruct); + fts5StructureInvalidate(p); + + if( iSegid ){ + const int pgsz = p->pConfig->pgsz; + int eDetail = p->pConfig->eDetail; + Fts5StructureSegment *pSeg; /* New segment within pStruct */ + Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */ + Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */ + + Fts5SegWriter writer; + fts5WriteInit(p, &writer, iSegid); + + pBuf = &writer.writer.buf; + pPgidx = &writer.writer.pgidx; + + /* fts5WriteInit() should have initialized the buffers to (most likely) + ** the maximum space required. */ + assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) ); + assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) ); + + /* Begin scanning through hash table entries. This loop runs once for each + ** term/doclist currently stored within the hash table. */ + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); + } + while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ + const char *zTerm; /* Buffer containing term */ + const u8 *pDoclist; /* Pointer to doclist for this term */ + int nDoclist; /* Size of doclist in bytes */ + + /* Write the term for this entry to disk. */ + sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist); + fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm); + + assert( writer.bFirstRowidInPage==0 ); + if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){ + /* The entire doclist will fit on the current leaf. */ + fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist); + }else{ + i64 iRowid = 0; + i64 iDelta = 0; + int iOff = 0; + + /* The entire doclist will not fit on this leaf. The following + ** loop iterates through the poslists that make up the current + ** doclist. */ + while( p->rc==SQLITE_OK && iOffp[0], (u16)pBuf->n); /* first rowid on page */ + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid); + writer.bFirstRowidInPage = 0; + fts5WriteDlidxAppend(p, &writer, iRowid); + }else{ + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta); + } + assert( pBuf->n<=pBuf->nSpace ); + + if( eDetail==FTS5_DETAIL_NONE ){ + if( iOffp[pBuf->n++] = 0; + iOff++; + if( iOffp[pBuf->n++] = 0; + iOff++; + } + } + if( (pBuf->n + pPgidx->n)>=pgsz ){ + fts5WriteFlushLeaf(p, &writer); + } + }else{ + int bDummy; + int nPos; + int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy); + nCopy += nPos; + if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ + /* The entire poslist will fit on the current leaf. So copy + ** it in one go. */ + fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); + }else{ + /* The entire poslist will not fit on this leaf. So it needs + ** to be broken into sections. The only qualification being + ** that each varint must be stored contiguously. */ + const u8 *pPoslist = &pDoclist[iOff]; + int iPos = 0; + while( p->rc==SQLITE_OK ){ + int nSpace = pgsz - pBuf->n - pPgidx->n; + int n = 0; + if( (nCopy - iPos)<=nSpace ){ + n = nCopy - iPos; + }else{ + n = fts5PoslistPrefix(&pPoslist[iPos], nSpace); + } + assert( n>0 ); + fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n); + iPos += n; + if( (pBuf->n + pPgidx->n)>=pgsz ){ + fts5WriteFlushLeaf(p, &writer); + } + if( iPos>=nCopy ) break; + } + } + iOff += nCopy; + } + } + } + + /* TODO2: Doclist terminator written here. */ + /* pBuf->p[pBuf->n++] = '\0'; */ + assert( pBuf->n<=pBuf->nSpace ); + sqlite3Fts5HashScanNext(pHash); + } + sqlite3Fts5HashClear(pHash); + fts5WriteFinish(p, &writer, &pgnoLast); + + /* Update the Fts5Structure. It is written back to the database by the + ** fts5StructureRelease() call below. */ + if( pStruct->nLevel==0 ){ + fts5StructureAddLevel(&p->rc, &pStruct); + } + fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0); + if( p->rc==SQLITE_OK ){ + pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ]; + pSeg->iSegid = iSegid; + pSeg->pgnoFirst = 1; + pSeg->pgnoLast = pgnoLast; + pStruct->nSegment++; + } + fts5StructurePromote(p, 0, pStruct); + } + + fts5IndexAutomerge(p, &pStruct, pgnoLast); fts5IndexCrisismerge(p, &pStruct); fts5StructureWrite(p, pStruct); fts5StructureRelease(pStruct); } @@ -248521,56 +195707,40 @@ /* ** Flush any data stored in the in-memory hash tables to the database. */ static void fts5IndexFlush(Fts5Index *p){ /* Unless it is empty, flush the hash table to disk */ - if( p->flushRc ){ - p->rc = p->flushRc; - return; - } - if( p->nPendingData || p->nContentlessDelete ){ + if( p->nPendingData ){ assert( p->pHash ); + p->nPendingData = 0; fts5FlushOneHash(p); - if( p->rc==SQLITE_OK ){ - sqlite3Fts5HashClear(p->pHash); - p->nPendingData = 0; - p->nPendingRow = 0; - p->nContentlessDelete = 0; - }else if( p->nPendingData || p->nContentlessDelete ){ - p->flushRc = p->rc; - } } } static Fts5Structure *fts5IndexOptimizeStruct( - Fts5Index *p, + Fts5Index *p, Fts5Structure *pStruct ){ Fts5Structure *pNew = 0; - sqlite3_int64 nByte = sizeof(Fts5Structure); + int nByte = sizeof(Fts5Structure); int nSeg = pStruct->nSegment; int i; /* Figure out if this structure requires optimization. A structure does ** not require optimization if either: ** - ** 1. it consists of fewer than two segments, or - ** 2. all segments are on the same level, or - ** 3. all segments except one are currently inputs to a merge operation. + ** + it consists of fewer than two segments, or + ** + all segments are on the same level, or + ** + all segments except one are currently inputs to a merge operation. ** - ** In the first case, if there are no tombstone hash pages, return NULL. In - ** the second, increment the ref-count on *pStruct and return a copy of the - ** pointer to it. + ** In the first case, return NULL. In the second, increment the ref-count + ** on *pStruct and return a copy of the pointer to it. */ - if( nSeg==0 ) return 0; + if( nSeg<2 ) return 0; for(i=0; inLevel; i++){ int nThis = pStruct->aLevel[i].nSeg; - int nMerge = pStruct->aLevel[i].nMerge; - if( nThis>0 && (nThis==nSeg || (nThis==nSeg-1 && nMerge==nThis)) ){ - if( nSeg==1 && nThis==1 && pStruct->aLevel[i].aSeg[0].nPgTombstone==0 ){ - return 0; - } + if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){ fts5StructureRef(pStruct); return pStruct; } assert( pStruct->aLevel[i].nMerge<=nThis ); } @@ -248579,15 +195749,14 @@ pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ Fts5StructureLevel *pLvl; nByte = nSeg * sizeof(Fts5StructureSegment); - pNew->nLevel = MIN(pStruct->nLevel+1, FTS5_MAX_LEVEL); + pNew->nLevel = pStruct->nLevel+1; pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; - pNew->nOriginCntr = pStruct->nOriginCntr; - pLvl = &pNew->aLevel[pNew->nLevel-1]; + pLvl = &pNew->aLevel[pStruct->nLevel]; pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pLvl->aSeg ){ int iLvl, iSeg; int iSegOut = 0; /* Iterate through all segments, from oldest to newest. Add them to @@ -248613,13 +195782,11 @@ Fts5Structure *pStruct; Fts5Structure *pNew = 0; assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); - assert( p->rc!=SQLITE_OK || p->nContentlessDelete==0 ); pStruct = fts5StructureRead(p); - assert( p->rc!=SQLITE_OK || pStruct!=0 ); fts5StructureInvalidate(p); if( pStruct ){ pNew = fts5IndexOptimizeStruct(p, pStruct); } @@ -248636,30 +195803,27 @@ fts5StructureWrite(p, pNew); fts5StructureRelease(pNew); } - return fts5IndexReturn(p); + return fts5IndexReturn(p); } /* ** This is called to implement the special "VALUES('merge', $nMerge)" ** INSERT command. */ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ - Fts5Structure *pStruct = 0; - - fts5IndexFlush(p); - pStruct = fts5StructureRead(p); + Fts5Structure *pStruct = fts5StructureRead(p); if( pStruct ){ int nMin = p->pConfig->nUsermerge; fts5StructureInvalidate(p); if( nMerge<0 ){ Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct); fts5StructureRelease(pStruct); pStruct = pNew; - nMin = 1; + nMin = 2; nMerge = nMerge*-1; } if( pStruct && pStruct->nLevel ){ if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){ fts5StructureWrite(p, pStruct); @@ -248670,40 +195834,38 @@ return fts5IndexReturn(p); } static void fts5AppendRowid( Fts5Index *p, - u64 iDelta, + i64 iDelta, Fts5Iter *pUnused, Fts5Buffer *pBuf ){ UNUSED_PARAM(pUnused); fts5BufferAppendVarint(&p->rc, pBuf, iDelta); } static void fts5AppendPoslist( Fts5Index *p, - u64 iDelta, + i64 iDelta, Fts5Iter *pMulti, Fts5Buffer *pBuf ){ int nData = pMulti->base.nData; - int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING; assert( nData>0 ); - if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){ + if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){ fts5BufferSafeAppendVarint(pBuf, iDelta); fts5BufferSafeAppendVarint(pBuf, nData*2); fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData); - memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING); } } static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist; - assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) ); + assert( pIter->aPoslist ); if( p>=pIter->aEof ){ pIter->aPoslist = 0; }else{ i64 iDelta; @@ -248719,26 +195881,21 @@ pIter->nPoslist = ((int)(p[0])) >> 1; pIter->nSize = 1; } pIter->aPoslist = p; - if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){ - pIter->aPoslist = 0; - } } } static void fts5DoclistIterInit( - Fts5Buffer *pBuf, + Fts5Buffer *pBuf, Fts5DoclistIter *pIter ){ memset(pIter, 0, sizeof(*pIter)); - if( pBuf->n>0 ){ - pIter->aPoslist = pBuf->p; - pIter->aEof = &pBuf->p[pBuf->n]; - fts5DoclistIterNext(pIter); - } + pIter->aPoslist = pBuf->p; + pIter->aEof = &pBuf->p[pBuf->n]; + fts5DoclistIterNext(pIter); } #if 0 /* ** Append a doclist to buffer pBuf. @@ -248755,14 +195912,14 @@ fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid); *piLastRowid = iRowid; } #endif -#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \ - assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \ - fts5BufferSafeAppendVarint((pBuf), (u64)(iRowid) - (u64)(iLastRowid)); \ - (iLastRowid) = (iRowid); \ +#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \ + assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \ + fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \ + (iLastRowid) = (iRowid); \ } /* ** Swap the contents of buffer *p1 with that of *p2. */ @@ -248788,24 +195945,20 @@ ** In this case the buffers consist of a delta-encoded list of rowids only. */ static void fts5MergeRowidLists( Fts5Index *p, /* FTS5 backend object */ Fts5Buffer *p1, /* First list to merge */ - int nBuf, /* Number of entries in apBuf[] */ - Fts5Buffer *aBuf /* Array of other lists to merge into p1 */ + Fts5Buffer *p2 /* Second list to merge */ ){ int i1 = 0; int i2 = 0; i64 iRowid1 = 0; i64 iRowid2 = 0; i64 iOut = 0; - Fts5Buffer *p2 = &aBuf[0]; + Fts5Buffer out; - - (void)nBuf; memset(&out, 0, sizeof(out)); - assert( nBuf==1 ); sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); if( p->rc ) return; fts5NextRowid(p1, &i1, &iRowid1); fts5NextRowid(p2, &i2, &iRowid2); @@ -248827,665 +195980,225 @@ } fts5BufferSwap(&out, p1); fts5BufferFree(&out); } - -typedef struct PrefixMerger PrefixMerger; -struct PrefixMerger { - Fts5DoclistIter iter; /* Doclist iterator */ - i64 iPos; /* For iterating through a position list */ - int iOff; - u8 *aPos; - PrefixMerger *pNext; /* Next in docid/poslist order */ -}; - -static void fts5PrefixMergerInsertByRowid( - PrefixMerger **ppHead, - PrefixMerger *p -){ - if( p->iter.aPoslist ){ - PrefixMerger **pp = ppHead; - while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){ - pp = &(*pp)->pNext; - } - p->pNext = *pp; - *pp = p; - } -} - -static void fts5PrefixMergerInsertByPosition( - PrefixMerger **ppHead, - PrefixMerger *p -){ - if( p->iPos>=0 ){ - PrefixMerger **pp = ppHead; - while( *pp && p->iPos>(*pp)->iPos ){ - pp = &(*pp)->pNext; - } - p->pNext = *pp; - *pp = p; - } -} - /* -** Array aBuf[] contains nBuf doclists. These are all merged in with the -** doclist in buffer p1. +** Buffers p1 and p2 contain doclists. This function merges the content +** of the two doclists together and sets buffer p1 to the result before +** returning. +** +** If an error occurs, an error code is left in p->rc. If an error has +** already occurred, this function is a no-op. */ static void fts5MergePrefixLists( Fts5Index *p, /* FTS5 backend object */ Fts5Buffer *p1, /* First list to merge */ - int nBuf, /* Number of buffers in array aBuf[] */ - Fts5Buffer *aBuf /* Other lists to merge in */ -){ -#define fts5PrefixMergerNextPosition(p) \ - sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos) -#define FTS5_MERGE_NLIST 16 - PrefixMerger aMerger[FTS5_MERGE_NLIST]; - PrefixMerger *pHead = 0; - int i; - int nOut = 0; - Fts5Buffer out = {0, 0, 0}; - Fts5Buffer tmp = {0, 0, 0}; - i64 iLastRowid = 0; - - /* Initialize a doclist-iterator for each input buffer. Arrange them in - ** a linked-list starting at pHead in ascending order of rowid. Avoid - ** linking any iterators already at EOF into the linked list at all. */ - assert( nBuf+1<=(int)(sizeof(aMerger)/sizeof(aMerger[0])) ); - memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1)); - pHead = &aMerger[nBuf]; - fts5DoclistIterInit(p1, &pHead->iter); - for(i=0; in + 9 + 10*nBuf; - - /* The maximum size of the output is equal to the sum of the - ** input sizes + 1 varint (9 bytes). The extra varint is because if the - ** first rowid in one input is a large negative number, and the first in - ** the other a non-negative number, the delta for the non-negative - ** number will be larger on disk than the literal integer value - ** was. - ** - ** Or, if the input position-lists are corrupt, then the output might - ** include up to (nBuf+1) extra 10-byte positions created by interpreting -1 - ** (the value PoslistNext64() uses for EOF) as a position and appending - ** it to the output. This can happen at most once for each input - ** position-list, hence (nBuf+1) 10 byte paddings. */ - if( sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return; - - while( pHead ){ - fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid); - - if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){ - /* Merge data from two or more poslists */ - i64 iPrev = 0; - int nTmp = FTS5_DATA_ZERO_PADDING; - int nMerge = 0; - PrefixMerger *pSave = pHead; - PrefixMerger *pThis = 0; - int nTail = 0; - - pHead = 0; - while( pSave && pSave->iter.iRowid==iLastRowid ){ - PrefixMerger *pNext = pSave->pNext; - pSave->iOff = 0; - pSave->iPos = 0; - pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize]; - fts5PrefixMergerNextPosition(pSave); - nTmp += pSave->iter.nPoslist + 10; - nMerge++; - fts5PrefixMergerInsertByPosition(&pHead, pSave); - pSave = pNext; - } - - if( pHead==0 || pHead->pNext==0 ){ - p->rc = FTS5_CORRUPT; - break; - } - - /* See the earlier comment in this function for an explanation of why - ** corrupt input position lists might cause the output to consume - ** at most nMerge*10 bytes of unexpected space. */ - if( sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){ - break; - } - fts5BufferZero(&tmp); - - pThis = pHead; - pHead = pThis->pNext; - sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos); - fts5PrefixMergerNextPosition(pThis); - fts5PrefixMergerInsertByPosition(&pHead, pThis); - - while( pHead->pNext ){ - pThis = pHead; - if( pThis->iPos!=iPrev ){ - sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos); - } - fts5PrefixMergerNextPosition(pThis); - pHead = pThis->pNext; - fts5PrefixMergerInsertByPosition(&pHead, pThis); - } - - if( pHead->iPos!=iPrev ){ - sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos); - } - nTail = pHead->iter.nPoslist - pHead->iOff; - - /* WRITEPOSLISTSIZE */ - assert_nc( tmp.n+nTail<=nTmp ); - assert( tmp.n+nTail<=nTmp+nMerge*10 ); - if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){ - if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; - break; - } - fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2); - fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); - if( nTail>0 ){ - fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail); - } - - pHead = pSave; - for(i=0; iiter.aPoslist && pX->iter.iRowid==iLastRowid ){ - fts5DoclistIterNext(&pX->iter); - fts5PrefixMergerInsertByRowid(&pHead, pX); - } - } - - }else{ - /* Copy poslist from pHead to output */ - PrefixMerger *pThis = pHead; - Fts5DoclistIter *pI = &pThis->iter; - fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize); - fts5DoclistIterNext(pI); - pHead = pThis->pNext; - fts5PrefixMergerInsertByRowid(&pHead, pThis); - } - } - - fts5BufferFree(p1); - fts5BufferFree(&tmp); - memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING); - *p1 = out; -} - - -/* -** Iterate through a range of entries in the FTS index, invoking the xVisit -** callback for each of them. -** -** Parameter pToken points to an nToken buffer containing an FTS index term -** (i.e. a document term with the preceding 1 byte index identifier - -** FTS5_MAIN_PREFIX or similar). If bPrefix is true, then the call visits -** all entries for terms that have pToken/nToken as a prefix. If bPrefix -** is false, then only entries with pToken/nToken as the entire key are -** visited. -** -** If the current table is a tokendata=1 table, then if bPrefix is true then -** each index term is treated separately. However, if bPrefix is false, then -** all index terms corresponding to pToken/nToken are collapsed into a single -** term before the callback is invoked. -** -** The callback invoked for each entry visited is specified by paramter xVisit. -** Each time it is invoked, it is passed a pointer to the Fts5Index object, -** a copy of the 7th paramter to this function (pCtx) and a pointer to the -** iterator that indicates the current entry. If the current entry is the -** first with a new term (i.e. different from that of the previous entry, -** including the very first term), then the final two parameters are passed -** a pointer to the term and its size in bytes, respectively. If the current -** entry is not the first associated with its term, these two parameters -** are passed 0. -** -** If parameter pColset is not NULL, then it is used to filter entries before -** the callback is invoked. -*/ -static int fts5VisitEntries( - Fts5Index *p, /* Fts5 index object */ - Fts5Colset *pColset, /* Columns filter to apply, or NULL */ - u8 *pToken, /* Buffer containing token */ - int nToken, /* Size of buffer pToken in bytes */ - int bPrefix, /* True for a prefix scan */ - void (*xVisit)(Fts5Index*, void *pCtx, Fts5Iter *pIter, const u8*, int), - void *pCtx /* Passed as second argument to xVisit() */ -){ - const int flags = (bPrefix ? FTS5INDEX_QUERY_SCAN : 0) - | FTS5INDEX_QUERY_SKIPEMPTY - | FTS5INDEX_QUERY_NOOUTPUT; - Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ - int bNewTerm = 1; - Fts5Structure *pStruct = fts5StructureRead(p); - - fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); - fts5IterSetOutputCb(&p->rc, p1); - for( /* no-op */ ; - fts5MultiIterEof(p, p1)==0; - fts5MultiIterNext2(p, p1, &bNewTerm) - ){ - Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; - int nNew = 0; - const u8 *pNew = 0; - - p1->xSetOutputs(p1, pSeg); - if( p->rc ) break; - - if( bNewTerm ){ - nNew = pSeg->term.n; - pNew = pSeg->term.p; - if( nNewrc; -} - - -/* -** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an -** array of these for each row it visits (so all iRowid fields are the same). -** Or, for an iterator used by an "ORDER BY rank" query, it accumulates an -** array of these for the entire query (in which case iRowid fields may take -** a variety of values). -** -** Each instance in the array indicates the iterator (and therefore term) -** associated with position iPos of rowid iRowid. This is used by the -** xInstToken() API. -** -** iRowid: -** Rowid for the current entry. -** -** iPos: -** Position of current entry within row. In the usual ((iCol<<32)+iOff) -** format (e.g. see macros FTS5_POS2COLUMN() and FTS5_POS2OFFSET()). -** -** iIter: -** If the Fts5TokenDataIter iterator that the entry is part of is -** actually an iterator (i.e. with nIter>0, not just a container for -** Fts5TokenDataMap structures), then this variable is an index into -** the apIter[] array. The corresponding term is that which the iterator -** at apIter[iIter] currently points to. -** -** Or, if the Fts5TokenDataIter iterator is just a container object -** (nIter==0), then iIter is an index into the term.p[] buffer where -** the term is stored. -** -** nByte: -** In the case where iIter is an index into term.p[], this variable -** is the size of the term in bytes. If iIter is an index into apIter[], -** this variable is unused. -*/ -struct Fts5TokenDataMap { - i64 iRowid; /* Row this token is located in */ - i64 iPos; /* Position of token */ - int iIter; /* Iterator token was read from */ - int nByte; /* Length of token in bytes (or 0) */ -}; - -/* -** An object used to supplement Fts5Iter for tokendata=1 iterators. -** -** This object serves two purposes. The first is as a container for an array -** of Fts5TokenDataMap structures, which are used to find the token required -** when the xInstToken() API is used. This is done by the nMapAlloc, nMap and -** aMap[] variables. -*/ -struct Fts5TokenDataIter { - int nMapAlloc; /* Allocated size of aMap[] in entries */ - int nMap; /* Number of valid entries in aMap[] */ - Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */ - - /* The following are used for prefix-queries only. */ - Fts5Buffer terms; - - /* The following are used for other full-token tokendata queries only. */ - int nIter; - int nIterAlloc; - Fts5PoslistReader *aPoslistReader; - int *aPoslistToIter; - Fts5Iter *apIter[1]; -}; - -/* -** The two input arrays - a1[] and a2[] - are in sorted order. This function -** merges the two arrays together and writes the result to output array -** aOut[]. aOut[] is guaranteed to be large enough to hold the result. -** -** Duplicate entries are copied into the output. So the size of the output -** array is always (n1+n2) entries. -*/ -static void fts5TokendataMerge( - Fts5TokenDataMap *a1, int n1, /* Input array 1 */ - Fts5TokenDataMap *a2, int n2, /* Input array 2 */ - Fts5TokenDataMap *aOut /* Output array */ -){ - int i1 = 0; - int i2 = 0; - - assert( n1>=0 && n2>=0 ); - while( i1=n2 || (i1rc==SQLITE_OK ){ - if( pT->nMap==pT->nMapAlloc ){ - int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64; - int nAlloc = nNew * sizeof(Fts5TokenDataMap); - Fts5TokenDataMap *aNew; - - aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc); - if( aNew==0 ){ - p->rc = SQLITE_NOMEM; - return; - } - - pT->aMap = aNew; - pT->nMapAlloc = nNew; - } - - pT->aMap[pT->nMap].iRowid = iRowid; - pT->aMap[pT->nMap].iPos = iPos; - pT->aMap[pT->nMap].iIter = iIter; - pT->aMap[pT->nMap].nByte = nByte; - pT->nMap++; - } -} - -/* -** Sort the contents of the pT->aMap[] array. -** -** The sorting algorithm requries a malloc(). If this fails, an error code -** is left in Fts5Index.rc before returning. -*/ -static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){ - Fts5TokenDataMap *aTmp = 0; - int nByte = pT->nMap * sizeof(Fts5TokenDataMap); - - aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte); - if( aTmp ){ - Fts5TokenDataMap *a1 = pT->aMap; - Fts5TokenDataMap *a2 = aTmp; - i64 nHalf; - - for(nHalf=1; nHalfnMap; nHalf=nHalf*2){ - int i1; - for(i1=0; i1nMap; i1+=(nHalf*2)){ - int n1 = MIN(nHalf, pT->nMap-i1); - int n2 = MIN(nHalf, pT->nMap-i1-n1); - fts5TokendataMerge(&a1[i1], n1, &a1[i1+n1], n2, &a2[i1]); - } - SWAPVAL(Fts5TokenDataMap*, a1, a2); - } - - if( a1!=pT->aMap ){ - memcpy(pT->aMap, a1, pT->nMap*sizeof(Fts5TokenDataMap)); - } - sqlite3_free(aTmp); - -#ifdef SQLITE_DEBUG - { - int ii; - for(ii=1; iinMap; ii++){ - Fts5TokenDataMap *p1 = &pT->aMap[ii-1]; - Fts5TokenDataMap *p2 = &pT->aMap[ii]; - assert( p1->iRowidiRowid - || (p1->iRowid==p2->iRowid && p1->iPos<=p2->iPos) - ); - } - } -#endif - } -} - -/* -** Delete an Fts5TokenDataIter structure and its contents. -*/ -static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){ - if( pSet ){ - int ii; - for(ii=0; iinIter; ii++){ - fts5MultiIterFree(pSet->apIter[ii]); - } - fts5BufferFree(&pSet->terms); - sqlite3_free(pSet->aPoslistReader); - sqlite3_free(pSet->aMap); - sqlite3_free(pSet); - } -} - - -/* -** fts5VisitEntries() context object used by fts5SetupPrefixIterTokendata() -** to pass data to prefixIterSetupTokendataCb(). -*/ -typedef struct TokendataSetupCtx TokendataSetupCtx; -struct TokendataSetupCtx { - Fts5TokenDataIter *pT; /* Object being populated with mappings */ - int iTermOff; /* Offset of current term in terms.p[] */ - int nTermByte; /* Size of current term in bytes */ -}; - -/* -** fts5VisitEntries() callback used by fts5SetupPrefixIterTokendata(). This -** callback adds an entry to the Fts5TokenDataIter.aMap[] array for each -** position in the current position-list. It doesn't matter that some of -** these may be out of order - they will be sorted later. -*/ -static void prefixIterSetupTokendataCb( - Fts5Index *p, - void *pCtx, - Fts5Iter *p1, - const u8 *pNew, - int nNew -){ - TokendataSetupCtx *pSetup = (TokendataSetupCtx*)pCtx; - int iPosOff = 0; - i64 iPos = 0; - - if( pNew ){ - pSetup->nTermByte = nNew-1; - pSetup->iTermOff = pSetup->pT->terms.n; - fts5BufferAppendBlob(&p->rc, &pSetup->pT->terms, nNew-1, pNew+1); - } - - while( 0==sqlite3Fts5PoslistNext64( - p1->base.pData, p1->base.nData, &iPosOff, &iPos - ) ){ - fts5TokendataIterAppendMap(p, - pSetup->pT, pSetup->iTermOff, pSetup->nTermByte, p1->base.iRowid, iPos - ); - } -} - - -/* -** Context object passed by fts5SetupPrefixIter() to fts5VisitEntries(). -*/ -typedef struct PrefixSetupCtx PrefixSetupCtx; -struct PrefixSetupCtx { - void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*); - void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*); - i64 iLastRowid; - int nMerge; - Fts5Buffer *aBuf; - int nBuf; - Fts5Buffer doclist; - TokendataSetupCtx *pTokendata; -}; - -/* -** fts5VisitEntries() callback used by fts5SetupPrefixIter() -*/ -static void prefixIterSetupCb( - Fts5Index *p, - void *pCtx, - Fts5Iter *p1, - const u8 *pNew, - int nNew -){ - PrefixSetupCtx *pSetup = (PrefixSetupCtx*)pCtx; - const int nMerge = pSetup->nMerge; - - if( p1->base.nData>0 ){ - if( p1->base.iRowid<=pSetup->iLastRowid && pSetup->doclist.n>0 ){ - int i; - for(i=0; p->rc==SQLITE_OK && pSetup->doclist.n; i++){ - int i1 = i*nMerge; - int iStore; - assert( i1+nMerge<=pSetup->nBuf ); - for(iStore=i1; iStoreaBuf[iStore].n==0 ){ - fts5BufferSwap(&pSetup->doclist, &pSetup->aBuf[iStore]); - fts5BufferZero(&pSetup->doclist); - break; - } - } - if( iStore==i1+nMerge ){ - pSetup->xMerge(p, &pSetup->doclist, nMerge, &pSetup->aBuf[i1]); - for(iStore=i1; iStoreaBuf[iStore]); - } - } - } - pSetup->iLastRowid = 0; - } - - pSetup->xAppend( - p, (u64)p1->base.iRowid-(u64)pSetup->iLastRowid, p1, &pSetup->doclist - ); - pSetup->iLastRowid = p1->base.iRowid; - } - - if( pSetup->pTokendata ){ - prefixIterSetupTokendataCb(p, (void*)pSetup->pTokendata, p1, pNew, nNew); + Fts5Buffer *p2 /* Second list to merge */ +){ + if( p2->n ){ + i64 iLastRowid = 0; + Fts5DoclistIter i1; + Fts5DoclistIter i2; + Fts5Buffer out = {0, 0, 0}; + Fts5Buffer tmp = {0, 0, 0}; + + if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; + fts5DoclistIterInit(p1, &i1); + fts5DoclistIterInit(p2, &i2); + + while( 1 ){ + if( i1.iRowidrc, &tmp, i1.nPoslist + i2.nPoslist); + if( p->rc ) break; + + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); + assert( iPos1>=0 && iPos2>=0 ); + + if( iPos1=0 && iPos2>=0 ){ + while( 1 ){ + if( iPos1=0 ){ + if( iPos1!=iPrev ){ + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); + } + fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); + }else{ + assert( iPos2>=0 && iPos2!=iPrev ); + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); + fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); + } + + /* WRITEPOSLISTSIZE */ + fts5BufferSafeAppendVarint(&out, tmp.n * 2); + fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); + fts5DoclistIterNext(&i1); + fts5DoclistIterNext(&i2); + if( i1.aPoslist==0 || i2.aPoslist==0 ) break; + } + } + + if( i1.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); + fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); + } + else if( i2.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); + } + + fts5BufferSet(&p->rc, p1, out.n, out.p); + fts5BufferFree(&tmp); + fts5BufferFree(&out); } } static void fts5SetupPrefixIter( Fts5Index *p, /* Index to read from */ int bDesc, /* True for "ORDER BY rowid DESC" */ - int iIdx, /* Index to scan for data */ - u8 *pToken, /* Buffer containing prefix to match */ + const u8 *pToken, /* Buffer containing prefix to match */ int nToken, /* Size of buffer pToken in bytes */ Fts5Colset *pColset, /* Restrict matches to these columns */ - Fts5Iter **ppIter /* OUT: New iterator */ + Fts5Iter **ppIter /* OUT: New iterator */ ){ Fts5Structure *pStruct; - PrefixSetupCtx s; - TokendataSetupCtx s2; - - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - - s.nMerge = 1; - s.iLastRowid = 0; - s.nBuf = 32; - if( iIdx==0 - && p->pConfig->eDetail==FTS5_DETAIL_FULL - && p->pConfig->bPrefixInsttoken - ){ - s.pTokendata = &s2; - s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT)); - } - + Fts5Buffer *aBuf; + const int nBuf = 32; + + void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); + void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*); if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ - s.xMerge = fts5MergeRowidLists; - s.xAppend = fts5AppendRowid; + xMerge = fts5MergeRowidLists; + xAppend = fts5AppendRowid; }else{ - s.nMerge = FTS5_MERGE_NLIST-1; - s.nBuf = s.nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */ - s.xMerge = fts5MergePrefixLists; - s.xAppend = fts5AppendPoslist; + xMerge = fts5MergePrefixLists; + xAppend = fts5AppendPoslist; } - s.aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*s.nBuf); + aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); pStruct = fts5StructureRead(p); - assert( p->rc!=SQLITE_OK || (s.aBuf && pStruct) ); - if( p->rc==SQLITE_OK ){ - void *pCtx = (void*)&s; + if( aBuf && pStruct ){ + const int flags = FTS5INDEX_QUERY_SCAN + | FTS5INDEX_QUERY_SKIPEMPTY + | FTS5INDEX_QUERY_NOOUTPUT; int i; + i64 iLastRowid = 0; + Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ Fts5Data *pData; - - /* If iIdx is non-zero, then it is the number of a prefix-index for - ** prefixes 1 character longer than the prefix being queried for. That - ** index contains all the doclists required, except for the one - ** corresponding to the prefix itself. That one is extracted from the - ** main term index here. */ - if( iIdx!=0 ){ - pToken[0] = FTS5_MAIN_PREFIX; - fts5VisitEntries(p, pColset, pToken, nToken, 0, prefixIterSetupCb, pCtx); - } - - pToken[0] = FTS5_MAIN_PREFIX + iIdx; - fts5VisitEntries(p, pColset, pToken, nToken, 1, prefixIterSetupCb, pCtx); - - assert( (s.nBuf%s.nMerge)==0 ); - for(i=0; irc, p1); + for( /* no-op */ ; + fts5MultiIterEof(p, p1)==0; + fts5MultiIterNext2(p, p1, &bNewTerm) + ){ + Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; + int nTerm = pSeg->term.n; + const u8 *pTerm = pSeg->term.p; + p1->xSetOutputs(p1, pSeg); + + assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); + if( bNewTerm ){ + if( nTermbase.nData==0 ) continue; + + if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ + for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ + assert( ibase.iRowid-iLastRowid, p1, &doclist); + iLastRowid = p1->base.iRowid; + } + + for(i=0; irc==SQLITE_OK ){ - s.xMerge(p, &s.doclist, s.nMerge, &s.aBuf[i]); - } - for(iFree=i; iFreerc!=SQLITE_OK ); + xMerge(p, &doclist, &aBuf[i]); + } + fts5BufferFree(&aBuf[i]); + } + fts5MultiIterFree(p1); + + pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n); if( pData ){ pData->p = (u8*)&pData[1]; - pData->nn = pData->szLeaf = s.doclist.n; - if( s.doclist.n ) memcpy(pData->p, s.doclist.p, s.doclist.n); + pData->nn = pData->szLeaf = doclist.n; + if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n); fts5MultiIterNew2(p, pData, bDesc, ppIter); } - - assert( (*ppIter)!=0 || p->rc!=SQLITE_OK ); - if( p->rc==SQLITE_OK && s.pTokendata ){ - fts5TokendataIterSortMap(p, s2.pT); - (*ppIter)->pTokenDataIter = s2.pT; - s2.pT = 0; - } + fts5BufferFree(&doclist); } - fts5TokendataIterDelete(s2.pT); - fts5BufferFree(&s.doclist); fts5StructureRelease(pStruct); - sqlite3_free(s.aBuf); + sqlite3_free(aBuf); } /* ** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain @@ -249498,46 +196211,44 @@ if( p->pHash==0 ){ p->rc = sqlite3Fts5HashNew(p->pConfig, &p->pHash, &p->nPendingData); } /* Flush the hash table to disk if required */ - if( iRowidiWriteRowid + if( iRowidiWriteRowid || (iRowid==p->iWriteRowid && p->bDelete==0) - || (p->nPendingData > p->pConfig->nHashSize) + || (p->nPendingData > p->pConfig->nHashSize) ){ fts5IndexFlush(p); } p->iWriteRowid = iRowid; p->bDelete = bDelete; - if( bDelete==0 ){ - p->nPendingRow++; - } return fts5IndexReturn(p); } /* ** Commit data to disk. */ static int sqlite3Fts5IndexSync(Fts5Index *p){ assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); - fts5IndexCloseReader(p); + fts5CloseReader(p); return fts5IndexReturn(p); } /* ** Discard any data stored in the in-memory hash tables. Do not write it ** to the database. Additionally, assume that the contents of the %_data -** table may have changed on disk. So any in-memory caches of %_data +** table may have changed on disk. So any in-memory caches of %_data ** records must be invalidated. */ static int sqlite3Fts5IndexRollback(Fts5Index *p){ - fts5IndexCloseReader(p); + fts5CloseReader(p); fts5IndexDiscardData(p); fts5StructureInvalidate(p); - return fts5IndexReturn(p); + /* assert( p->rc==SQLITE_OK ); */ + return SQLITE_OK; } /* ** The %_data table is completely empty when this function is called. This ** function populates it with the initial structure objects for each index, @@ -249544,15 +196255,11 @@ ** and the initial version of the "averages" record (a zero-byte blob). */ static int sqlite3Fts5IndexReinit(Fts5Index *p){ Fts5Structure s; fts5StructureInvalidate(p); - fts5IndexDiscardData(p); memset(&s, 0, sizeof(Fts5Structure)); - if( p->pConfig->bContentlessDelete ){ - s.nOriginCntr = 1; - } fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0); fts5StructureWrite(p, &s); return fts5IndexReturn(p); } @@ -249562,12 +196269,12 @@ ** ** If successful, set *pp to point to the new object and return SQLITE_OK. ** Otherwise, set *pp to NULL and return an SQLite error code. */ static int sqlite3Fts5IndexOpen( - Fts5Config *pConfig, - int bCreate, + Fts5Config *pConfig, + int bCreate, Fts5Index **pp, char **pzErr ){ int rc = SQLITE_OK; Fts5Index *p; /* New object */ @@ -249580,12 +196287,12 @@ if( p->zDataTbl && bCreate ){ rc = sqlite3Fts5CreateTable( pConfig, "data", "id INTEGER PRIMARY KEY, block BLOB", 0, pzErr ); if( rc==SQLITE_OK ){ - rc = sqlite3Fts5CreateTable(pConfig, "idx", - "segid, term, pgno, PRIMARY KEY(segid, term)", + rc = sqlite3Fts5CreateTable(pConfig, "idx", + "segid, term, pgno, PRIMARY KEY(segid, term)", 1, pzErr ); } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IndexReinit(p); @@ -249612,43 +196319,34 @@ sqlite3_finalize(p->pWriter); sqlite3_finalize(p->pDeleter); sqlite3_finalize(p->pIdxWriter); sqlite3_finalize(p->pIdxDeleter); sqlite3_finalize(p->pIdxSelect); - sqlite3_finalize(p->pIdxNextSelect); sqlite3_finalize(p->pDataVersion); - sqlite3_finalize(p->pDeleteFromIdx); sqlite3Fts5HashFree(p->pHash); sqlite3_free(p->zDataTbl); sqlite3_free(p); } return rc; } /* -** Argument p points to a buffer containing utf-8 text that is n bytes in +** Argument p points to a buffer containing utf-8 text that is n bytes in ** size. Return the number of bytes in the nChar character prefix of the ** buffer, or 0 if there are less than nChar characters in total. */ static int sqlite3Fts5IndexCharlenToBytelen( - const char *p, - int nByte, + const char *p, + int nByte, int nChar ){ int n = 0; int i; for(i=0; i=nByte ) return 0; /* Input contains fewer than nChar chars */ if( (unsigned char)p[n++]>=0xc0 ){ - if( n>=nByte ) return 0; - while( (p[n] & 0xc0)==0x80 ){ - n++; - if( n>=nByte ){ - if( i+1==nChar ) break; - return 0; - } - } + while( (p[n] & 0xc0)==0x80 ) n++; } } return n; } @@ -249655,11 +196353,11 @@ /* ** pIn is a UTF-8 encoded string, nIn bytes in size. Return the number of ** unicode characters in the string. */ static int fts5IndexCharlen(const char *pIn, int nIn){ - int nChar = 0; + int nChar = 0; int i = 0; while( i=0xc0 ){ while( inPrefix && rc==SQLITE_OK; i++){ const int nChar = pConfig->aPrefix[i]; int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar); if( nByte ){ - rc = sqlite3Fts5HashWrite(p->pHash, + rc = sqlite3Fts5HashWrite(p->pHash, p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken, nByte ); } } @@ -249709,392 +196407,11 @@ return rc; } /* -** pToken points to a buffer of size nToken bytes containing a search -** term, including the index number at the start, used on a tokendata=1 -** table. This function returns true if the term in buffer pBuf matches -** token pToken/nToken. -*/ -static int fts5IsTokendataPrefix( - Fts5Buffer *pBuf, - const u8 *pToken, - int nToken -){ - return ( - pBuf->n>=nToken - && 0==memcmp(pBuf->p, pToken, nToken) - && (pBuf->n==nToken || pBuf->p[nToken]==0x00) - ); -} - -/* -** Ensure the segment-iterator passed as the only argument points to EOF. -*/ -static void fts5SegIterSetEOF(Fts5SegIter *pSeg){ - fts5DataRelease(pSeg->pLeaf); - pSeg->pLeaf = 0; -} - -static void fts5IterClose(Fts5IndexIter *pIndexIter){ - if( pIndexIter ){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - Fts5Index *pIndex = pIter->pIndex; - fts5TokendataIterDelete(pIter->pTokenDataIter); - fts5MultiIterFree(pIter); - fts5IndexCloseReader(pIndex); - } -} - -/* -** This function appends iterator pAppend to Fts5TokenDataIter pIn and -** returns the result. -*/ -static Fts5TokenDataIter *fts5AppendTokendataIter( - Fts5Index *p, /* Index object (for error code) */ - Fts5TokenDataIter *pIn, /* Current Fts5TokenDataIter struct */ - Fts5Iter *pAppend /* Append this iterator */ -){ - Fts5TokenDataIter *pRet = pIn; - - if( p->rc==SQLITE_OK ){ - if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){ - int nAlloc = pIn ? pIn->nIterAlloc*2 : 16; - int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter); - Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte); - - if( pNew==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - if( pIn==0 ) memset(pNew, 0, nByte); - pRet = pNew; - pNew->nIterAlloc = nAlloc; - } - } - } - if( p->rc ){ - fts5IterClose((Fts5IndexIter*)pAppend); - }else{ - pRet->apIter[pRet->nIter++] = pAppend; - } - assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc ); - - return pRet; -} - -/* -** The iterator passed as the only argument must be a tokendata=1 iterator -** (pIter->pTokenDataIter!=0). This function sets the iterator output -** variables (pIter->base.*) according to the contents of the current -** row. -*/ -static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){ - int ii; - int nHit = 0; - i64 iRowid = SMALLEST_INT64; - int iMin = 0; - - Fts5TokenDataIter *pT = pIter->pTokenDataIter; - - pIter->base.nData = 0; - pIter->base.pData = 0; - - for(ii=0; iinIter; ii++){ - Fts5Iter *p = pT->apIter[ii]; - if( p->base.bEof==0 ){ - if( nHit==0 || p->base.iRowidbase.iRowid; - nHit = 1; - pIter->base.pData = p->base.pData; - pIter->base.nData = p->base.nData; - iMin = ii; - }else if( p->base.iRowid==iRowid ){ - nHit++; - } - } - } - - if( nHit==0 ){ - pIter->base.bEof = 1; - }else{ - int eDetail = pIter->pIndex->pConfig->eDetail; - pIter->base.bEof = 0; - pIter->base.iRowid = iRowid; - - if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){ - fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, 0, iRowid, -1); - }else - if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){ - int nReader = 0; - int nByte = 0; - i64 iPrev = 0; - - /* Allocate array of iterators if they are not already allocated. */ - if( pT->aPoslistReader==0 ){ - pT->aPoslistReader = (Fts5PoslistReader*)sqlite3Fts5MallocZero( - &pIter->pIndex->rc, - pT->nIter * (sizeof(Fts5PoslistReader) + sizeof(int)) - ); - if( pT->aPoslistReader==0 ) return; - pT->aPoslistToIter = (int*)&pT->aPoslistReader[pT->nIter]; - } - - /* Populate an iterator for each poslist that will be merged */ - for(ii=0; iinIter; ii++){ - Fts5Iter *p = pT->apIter[ii]; - if( iRowid==p->base.iRowid ){ - pT->aPoslistToIter[nReader] = ii; - sqlite3Fts5PoslistReaderInit( - p->base.pData, p->base.nData, &pT->aPoslistReader[nReader++] - ); - nByte += p->base.nData; - } - } - - /* Ensure the output buffer is large enough */ - if( fts5BufferGrow(&pIter->pIndex->rc, &pIter->poslist, nByte+nHit*10) ){ - return; - } - - /* Ensure the token-mapping is large enough */ - if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){ - int nNew = (pT->nMapAlloc + nByte) * 2; - Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc( - pT->aMap, nNew*sizeof(Fts5TokenDataMap) - ); - if( aNew==0 ){ - pIter->pIndex->rc = SQLITE_NOMEM; - return; - } - pT->aMap = aNew; - pT->nMapAlloc = nNew; - } - - pIter->poslist.n = 0; - - while( 1 ){ - i64 iMinPos = LARGEST_INT64; - - /* Find smallest position */ - iMin = 0; - for(ii=0; iiaPoslistReader[ii]; - if( pReader->bEof==0 ){ - if( pReader->iPosiPos; - iMin = ii; - } - } - } - - /* If all readers were at EOF, break out of the loop. */ - if( iMinPos==LARGEST_INT64 ) break; - - sqlite3Fts5PoslistSafeAppend(&pIter->poslist, &iPrev, iMinPos); - sqlite3Fts5PoslistReaderNext(&pT->aPoslistReader[iMin]); - - if( eDetail==FTS5_DETAIL_FULL ){ - pT->aMap[pT->nMap].iPos = iMinPos; - pT->aMap[pT->nMap].iIter = pT->aPoslistToIter[iMin]; - pT->aMap[pT->nMap].iRowid = iRowid; - pT->nMap++; - } - } - - pIter->base.pData = pIter->poslist.p; - pIter->base.nData = pIter->poslist.n; - } - } -} - -/* -** The iterator passed as the only argument must be a tokendata=1 iterator -** (pIter->pTokenDataIter!=0). This function advances the iterator. If -** argument bFrom is false, then the iterator is advanced to the next -** entry. Or, if bFrom is true, it is advanced to the first entry with -** a rowid of iFrom or greater. -*/ -static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){ - int ii; - Fts5TokenDataIter *pT = pIter->pTokenDataIter; - Fts5Index *pIndex = pIter->pIndex; - - for(ii=0; iinIter; ii++){ - Fts5Iter *p = pT->apIter[ii]; - if( p->base.bEof==0 - && (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowidbase.bEof==0 - && p->base.iRowidrc==SQLITE_OK - ){ - fts5MultiIterNext(pIndex, p, 0, 0); - } - } - } - - if( pIndex->rc==SQLITE_OK ){ - fts5IterSetOutputsTokendata(pIter); - } -} - -/* -** If the segment-iterator passed as the first argument is at EOF, then -** set pIter->term to a copy of buffer pTerm. -*/ -static void fts5TokendataSetTermIfEof(Fts5Iter *pIter, Fts5Buffer *pTerm){ - if( pIter && pIter->aSeg[0].pLeaf==0 ){ - fts5BufferSet(&pIter->pIndex->rc, &pIter->aSeg[0].term, pTerm->n, pTerm->p); - } -} - -/* -** This function sets up an iterator to use for a non-prefix query on a -** tokendata=1 table. -*/ -static Fts5Iter *fts5SetupTokendataIter( - Fts5Index *p, /* FTS index to query */ - const u8 *pToken, /* Buffer containing query term */ - int nToken, /* Size of buffer pToken in bytes */ - Fts5Colset *pColset /* Colset to filter on */ -){ - Fts5Iter *pRet = 0; - Fts5TokenDataIter *pSet = 0; - Fts5Structure *pStruct = 0; - const int flags = FTS5INDEX_QUERY_SCANONETERM | FTS5INDEX_QUERY_SCAN; - - Fts5Buffer bSeek = {0, 0, 0}; - Fts5Buffer *pSmall = 0; - - fts5IndexFlush(p); - pStruct = fts5StructureRead(p); - - while( p->rc==SQLITE_OK ){ - Fts5Iter *pPrev = pSet ? pSet->apIter[pSet->nIter-1] : 0; - Fts5Iter *pNew = 0; - Fts5SegIter *pNewIter = 0; - Fts5SegIter *pPrevIter = 0; - - int iLvl, iSeg, ii; - - pNew = fts5MultiIterAlloc(p, pStruct->nSegment); - if( pSmall ){ - fts5BufferSet(&p->rc, &bSeek, pSmall->n, pSmall->p); - fts5BufferAppendBlob(&p->rc, &bSeek, 1, (const u8*)"\0"); - }else{ - fts5BufferSet(&p->rc, &bSeek, nToken, pToken); - } - if( p->rc ){ - fts5IterClose((Fts5IndexIter*)pNew); - break; - } - - pNewIter = &pNew->aSeg[0]; - pPrevIter = (pPrev ? &pPrev->aSeg[0] : 0); - for(iLvl=0; iLvlnLevel; iLvl++){ - for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){ - Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; - int bDone = 0; - - if( pPrevIter ){ - if( fts5BufferCompare(pSmall, &pPrevIter->term) ){ - memcpy(pNewIter, pPrevIter, sizeof(Fts5SegIter)); - memset(pPrevIter, 0, sizeof(Fts5SegIter)); - bDone = 1; - }else if( pPrevIter->iEndofDoclist>pPrevIter->pLeaf->szLeaf ){ - fts5SegIterNextInit(p,(const char*)bSeek.p,bSeek.n-1,pSeg,pNewIter); - bDone = 1; - } - } - - if( bDone==0 ){ - fts5SegIterSeekInit(p, bSeek.p, bSeek.n, flags, pSeg, pNewIter); - } - - if( pPrevIter ){ - if( pPrevIter->pTombArray ){ - pNewIter->pTombArray = pPrevIter->pTombArray; - pNewIter->pTombArray->nRef++; - } - }else{ - fts5SegIterAllocTombstone(p, pNewIter); - } - - pNewIter++; - if( pPrevIter ) pPrevIter++; - if( p->rc ) break; - } - } - fts5TokendataSetTermIfEof(pPrev, pSmall); - - pNew->bSkipEmpty = 1; - pNew->pColset = pColset; - fts5IterSetOutputCb(&p->rc, pNew); - - /* Loop through all segments in the new iterator. Find the smallest - ** term that any segment-iterator points to. Iterator pNew will be - ** used for this term. Also, set any iterator that points to a term that - ** does not match pToken/nToken to point to EOF */ - pSmall = 0; - for(ii=0; iinSeg; ii++){ - Fts5SegIter *pII = &pNew->aSeg[ii]; - if( 0==fts5IsTokendataPrefix(&pII->term, pToken, nToken) ){ - fts5SegIterSetEOF(pII); - } - if( pII->pLeaf && (!pSmall || fts5BufferCompare(pSmall, &pII->term)>0) ){ - pSmall = &pII->term; - } - } - - /* If pSmall is still NULL at this point, then the new iterator does - ** not point to any terms that match the query. So delete it and break - ** out of the loop - all required iterators have been collected. */ - if( pSmall==0 ){ - fts5IterClose((Fts5IndexIter*)pNew); - break; - } - - /* Append this iterator to the set and continue. */ - pSet = fts5AppendTokendataIter(p, pSet, pNew); - } - - if( p->rc==SQLITE_OK && pSet ){ - int ii; - for(ii=0; iinIter; ii++){ - Fts5Iter *pIter = pSet->apIter[ii]; - int iSeg; - for(iSeg=0; iSegnSeg; iSeg++){ - pIter->aSeg[iSeg].flags |= FTS5_SEGITER_ONETERM; - } - fts5MultiIterFinishSetup(p, pIter); - } - } - - if( p->rc==SQLITE_OK ){ - pRet = fts5MultiIterAlloc(p, 0); - } - if( pRet ){ - pRet->nSeg = 0; - pRet->pTokenDataIter = pSet; - if( pSet ){ - fts5IterSetOutputsTokendata(pRet); - }else{ - pRet->base.bEof = 1; - } - }else{ - fts5TokendataIterDelete(pSet); - } - - fts5StructureRelease(pStruct); - fts5BufferFree(&bSeek); - return pRet; -} - -/* -** Open a new iterator to iterate though all rowid that match the +** Open a new iterator to iterate though all rowid that match the ** specified token or token prefix. */ static int sqlite3Fts5IndexQuery( Fts5Index *p, /* FTS index to query */ const char *pToken, int nToken, /* Token (or prefix) to query for */ @@ -250109,33 +196426,21 @@ /* If the QUERY_SCAN flag is set, all other flags must be clear. */ assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ int iIdx = 0; /* Index to search */ - int iPrefixIdx = 0; /* +1 prefix index */ - int bTokendata = pConfig->bTokendata; - assert( buf.p!=0 ); - if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken); - - /* The NOTOKENDATA flag is set when each token in a tokendata=1 table - ** should be treated individually, instead of merging all those with - ** a common prefix into a single entry. This is used, for example, by - ** queries performed as part of an integrity-check, or by the fts5vocab - ** module. */ - if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){ - bTokendata = 0; - } + if( nToken ) memcpy(&buf.p[1], pToken, nToken); /* Figure out which index to search and set iIdx accordingly. If this ** is a prefix query for which there is no prefix index, set iIdx to ** greater than pConfig->nPrefix to indicate that the query will be ** satisfied by scanning multiple terms in the main index. ** ** If the QUERY_TEST_NOIDX flag was specified, then this must be a - ** prefix-query. Instead of using a prefix-index (if one exists), + ** prefix-query. Instead of using a prefix-index (if one exists), ** evaluate the prefix query using the main FTS index. This is used - ** for internal sanity checking by the integrity-check in debug + ** for internal sanity checking by the integrity-check in debug ** mode only. */ #ifdef SQLITE_DEBUG if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ assert( flags & FTS5INDEX_QUERY_PREFIX ); iIdx = 1+pConfig->nPrefix; @@ -250142,72 +196447,59 @@ }else #endif if( flags & FTS5INDEX_QUERY_PREFIX ){ int nChar = fts5IndexCharlen(pToken, nToken); for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){ - int nIdxChar = pConfig->aPrefix[iIdx-1]; - if( nIdxChar==nChar ) break; - if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx; + if( pConfig->aPrefix[iIdx-1]==nChar ) break; } } - if( bTokendata && iIdx==0 ){ - buf.p[0] = FTS5_MAIN_PREFIX; - pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset); - }else if( iIdx<=pConfig->nPrefix ){ + if( iIdx<=pConfig->nPrefix ){ /* Straight index lookup */ Fts5Structure *pStruct = fts5StructureRead(p); buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); if( pStruct ){ - fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, + fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, pColset, buf.p, nToken+1, -1, 0, &pRet ); fts5StructureRelease(pStruct); } }else{ - /* Scan multiple terms in the main index for a prefix query. */ + /* Scan multiple terms in the main index */ int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; - fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet); - if( pRet==0 ){ - assert( p->rc!=SQLITE_OK ); - }else{ - assert( pRet->pColset==0 ); - fts5IterSetOutputCb(&p->rc, pRet); - if( p->rc==SQLITE_OK ){ - Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; - if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); - } + buf.p[0] = FTS5_MAIN_PREFIX; + fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); + assert( p->rc!=SQLITE_OK || pRet->pColset==0 ); + fts5IterSetOutputCb(&p->rc, pRet); + if( p->rc==SQLITE_OK ){ + Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; + if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); } } if( p->rc ){ - fts5IterClose((Fts5IndexIter*)pRet); + sqlite3Fts5IterClose((Fts5IndexIter*)pRet); pRet = 0; - fts5IndexCloseReader(p); + fts5CloseReader(p); } - *ppIter = (Fts5IndexIter*)pRet; + *ppIter = &pRet->base; sqlite3Fts5BufferFree(&buf); } return fts5IndexReturn(p); } /* ** Return true if the iterator passed as the only argument is at EOF. */ /* -** Move to the next matching rowid. +** Move to the next matching rowid. */ static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; assert( pIter->pIndex->rc==SQLITE_OK ); - if( pIter->nSeg==0 ){ - assert( pIter->pTokenDataIter ); - fts5TokendataIterNext(pIter, 0, 0); - }else{ - fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); - } + fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); return fts5IndexReturn(pIter->pIndex); } /* ** Move to the next matching term/rowid. Used by the fts5vocab module. @@ -250236,212 +196528,38 @@ ** definition of "at or after" depends on whether this iterator iterates ** in ascending or descending rowid order. */ static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - if( pIter->nSeg==0 ){ - assert( pIter->pTokenDataIter ); - fts5TokendataIterNext(pIter, 1, iMatch); - }else{ - fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); - } + fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); return fts5IndexReturn(pIter->pIndex); } /* ** Return the current term. */ static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ int n; const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n); - assert_nc( z || n<=1 ); *pn = n-1; - return (z ? &z[1] : 0); -} - -/* -** pIter is a prefix query. This function populates pIter->pTokenDataIter -** with an Fts5TokenDataIter object containing mappings for all rows -** matched by the query. -*/ -static int fts5SetupPrefixIterTokendata( - Fts5Iter *pIter, - const char *pToken, /* Token prefix to search for */ - int nToken /* Size of pToken in bytes */ -){ - Fts5Index *p = pIter->pIndex; - Fts5Buffer token = {0, 0, 0}; - TokendataSetupCtx ctx; - - memset(&ctx, 0, sizeof(ctx)); - - fts5BufferGrow(&p->rc, &token, nToken+1); - assert( token.p!=0 || p->rc!=SQLITE_OK ); - ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT)); - - if( p->rc==SQLITE_OK ){ - - /* Fill in the token prefix to search for */ - token.p[0] = FTS5_MAIN_PREFIX; - memcpy(&token.p[1], pToken, nToken); - token.n = nToken+1; - - fts5VisitEntries( - p, 0, token.p, token.n, 1, prefixIterSetupTokendataCb, (void*)&ctx - ); - - fts5TokendataIterSortMap(p, ctx.pT); - } - - if( p->rc==SQLITE_OK ){ - pIter->pTokenDataIter = ctx.pT; - }else{ - fts5TokendataIterDelete(ctx.pT); - } - fts5BufferFree(&token); - - return fts5IndexReturn(p); -} - -/* -** This is used by xInstToken() to access the token at offset iOff, column -** iCol of row iRowid. The token is returned via output variables *ppOut -** and *pnOut. The iterator passed as the first argument must be a tokendata=1 -** iterator (pIter->pTokenDataIter!=0). -** -** pToken/nToken: -*/ -static int sqlite3Fts5IterToken( - Fts5IndexIter *pIndexIter, - const char *pToken, int nToken, - i64 iRowid, - int iCol, - int iOff, - const char **ppOut, int *pnOut -){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - Fts5TokenDataIter *pT = pIter->pTokenDataIter; - i64 iPos = (((i64)iCol)<<32) + iOff; - Fts5TokenDataMap *aMap = 0; - int i1 = 0; - int i2 = 0; - int iTest = 0; - - assert( pT || (pToken && pIter->nSeg>0) ); - if( pT==0 ){ - int rc = fts5SetupPrefixIterTokendata(pIter, pToken, nToken); - if( rc!=SQLITE_OK ) return rc; - pT = pIter->pTokenDataIter; - } - - i2 = pT->nMap; - aMap = pT->aMap; - - while( i2>i1 ){ - iTest = (i1 + i2) / 2; - - if( aMap[iTest].iRowidiRowid ){ - i2 = iTest; - }else{ - if( aMap[iTest].iPosiPos ){ - i2 = iTest; - }else{ - break; - } - } - } - - if( i2>i1 ){ - if( pIter->nSeg==0 ){ - Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter]; - *ppOut = (const char*)pMap->aSeg[0].term.p+1; - *pnOut = pMap->aSeg[0].term.n-1; - }else{ - Fts5TokenDataMap *p = &aMap[iTest]; - *ppOut = (const char*)&pT->terms.p[p->iIter]; - *pnOut = aMap[iTest].nByte; - } - } - - return SQLITE_OK; -} - -/* -** Clear any existing entries from the token-map associated with the -** iterator passed as the only argument. -*/ -static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - if( pIter && pIter->pTokenDataIter - && (pIter->nSeg==0 || pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_FULL) - ){ - pIter->pTokenDataIter->nMap = 0; - } -} - -/* -** Set a token-mapping for the iterator passed as the first argument. This -** is used in detail=column or detail=none mode when a token is requested -** using the xInstToken() API. In this case the caller tokenizers the -** current row and configures the token-mapping via multiple calls to this -** function. -*/ -static int sqlite3Fts5IndexIterWriteTokendata( - Fts5IndexIter *pIndexIter, - const char *pToken, int nToken, - i64 iRowid, int iCol, int iOff -){ - Fts5Iter *pIter = (Fts5Iter*)pIndexIter; - Fts5TokenDataIter *pT = pIter->pTokenDataIter; - Fts5Index *p = pIter->pIndex; - i64 iPos = (((i64)iCol)<<32) + iOff; - - assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL ); - assert( pIter->pTokenDataIter || pIter->nSeg>0 ); - if( pIter->nSeg>0 ){ - /* This is a prefix term iterator. */ - if( pT==0 ){ - pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT)); - pIter->pTokenDataIter = pT; - } - if( pT ){ - fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos); - fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken); - } - }else{ - int ii; - for(ii=0; iinIter; ii++){ - Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term; - if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break; - } - if( iinIter ){ - fts5TokendataIterAppendMap(p, pT, ii, 0, iRowid, iPos); - } - } - return fts5IndexReturn(p); + return &z[1]; } /* ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). */ static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ if( pIndexIter ){ - Fts5Index *pIndex = ((Fts5Iter*)pIndexIter)->pIndex; - fts5IterClose(pIndexIter); - fts5IndexReturn(pIndex); + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + Fts5Index *pIndex = pIter->pIndex; + fts5MultiIterFree(pIter); + fts5CloseReader(pIndex); } } /* -** Read and decode the "averages" record from the database. +** Read and decode the "averages" record from the database. ** ** Parameter anSize must point to an array of size nCol, where nCol is ** the number of user defined columns in the FTS table. */ static int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize){ @@ -250463,11 +196581,11 @@ fts5DataRelease(pData); return fts5IndexReturn(p); } /* -** Replace the current "averages" record with the contents of the buffer +** Replace the current "averages" record with the contents of the buffer ** supplied as the second argument. */ static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8 *pData, int nData){ assert( p->rc==SQLITE_OK ); fts5DataWrite(p, FTS5_AVERAGES_ROWID, pData, nData); @@ -250481,11 +196599,11 @@ static int sqlite3Fts5IndexReads(Fts5Index *p){ return p->nRead; } /* -** Set the 32-bit cookie value stored at the start of all structure +** Set the 32-bit cookie value stored at the start of all structure ** records to the value passed as the second argument. ** ** Return SQLITE_OK if successful, or an SQLite error code if an error ** occurs. */ @@ -250496,11 +196614,11 @@ sqlite3_blob *pBlob = 0; assert( p->rc==SQLITE_OK ); sqlite3Fts5Put32(aCookie, iNew); - rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl, + rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl, "block", FTS5_STRUCTURE_ROWID, 1, &pBlob ); if( rc==SQLITE_OK ){ sqlite3_blob_write(pBlob, aCookie, 4, 0); rc = sqlite3_blob_close(pBlob); @@ -250514,365 +196632,24 @@ pStruct = fts5StructureRead(p); fts5StructureRelease(pStruct); return fts5IndexReturn(p); } -/* -** Retrieve the origin value that will be used for the segment currently -** being accumulated in the in-memory hash table when it is flushed to -** disk. If successful, SQLITE_OK is returned and (*piOrigin) set to -** the queried value. Or, if an error occurs, an error code is returned -** and the final value of (*piOrigin) is undefined. -*/ -static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin){ - Fts5Structure *pStruct; - pStruct = fts5StructureRead(p); - if( pStruct ){ - *piOrigin = pStruct->nOriginCntr; - fts5StructureRelease(pStruct); - } - return fts5IndexReturn(p); -} - -/* -** Buffer pPg contains a page of a tombstone hash table - one of nPg pages -** associated with the same segment. This function adds rowid iRowid to -** the hash table. The caller is required to guarantee that there is at -** least one free slot on the page. -** -** If parameter bForce is false and the hash table is deemed to be full -** (more than half of the slots are occupied), then non-zero is returned -** and iRowid not inserted. Or, if bForce is true or if the hash table page -** is not full, iRowid is inserted and zero returned. -*/ -static int fts5IndexTombstoneAddToPage( - Fts5Data *pPg, - int bForce, - int nPg, - u64 iRowid -){ - const int szKey = TOMBSTONE_KEYSIZE(pPg); - const int nSlot = TOMBSTONE_NSLOT(pPg); - const int nElem = fts5GetU32(&pPg->p[4]); - int iSlot = (iRowid / nPg) % nSlot; - int nCollide = nSlot; - - if( szKey==4 && iRowid>0xFFFFFFFF ) return 2; - if( iRowid==0 ){ - pPg->p[1] = 0x01; - return 0; - } - - if( bForce==0 && nElem>=(nSlot/2) ){ - return 1; - } - - fts5PutU32(&pPg->p[4], nElem+1); - if( szKey==4 ){ - u32 *aSlot = (u32*)&pPg->p[8]; - while( aSlot[iSlot] ){ - iSlot = (iSlot + 1) % nSlot; - if( nCollide--==0 ) return 0; - } - fts5PutU32((u8*)&aSlot[iSlot], (u32)iRowid); - }else{ - u64 *aSlot = (u64*)&pPg->p[8]; - while( aSlot[iSlot] ){ - iSlot = (iSlot + 1) % nSlot; - if( nCollide--==0 ) return 0; - } - fts5PutU64((u8*)&aSlot[iSlot], iRowid); - } - - return 0; -} - -/* -** This function attempts to build a new hash containing all the keys -** currently in the tombstone hash table for segment pSeg. The new -** hash will be stored in the nOut buffers passed in array apOut[]. -** All pages of the new hash use key-size szKey (4 or 8). -** -** Return 0 if the hash is successfully rebuilt into the nOut pages. -** Or non-zero if it is not (because one page became overfull). In this -** case the caller should retry with a larger nOut parameter. -** -** Parameter pData1 is page iPg1 of the hash table being rebuilt. -*/ -static int fts5IndexTombstoneRehash( - Fts5Index *p, - Fts5StructureSegment *pSeg, /* Segment to rebuild hash of */ - Fts5Data *pData1, /* One page of current hash - or NULL */ - int iPg1, /* Which page of the current hash is pData1 */ - int szKey, /* 4 or 8, the keysize */ - int nOut, /* Number of output pages */ - Fts5Data **apOut /* Array of output hash pages */ -){ - int ii; - int res = 0; - - /* Initialize the headers of all the output pages */ - for(ii=0; iip[0] = szKey; - fts5PutU32(&apOut[ii]->p[4], 0); - } - - /* Loop through the current pages of the hash table. */ - for(ii=0; res==0 && iinPgTombstone; ii++){ - Fts5Data *pData = 0; /* Page ii of the current hash table */ - Fts5Data *pFree = 0; /* Free this at the end of the loop */ - - if( iPg1==ii ){ - pData = pData1; - }else{ - pFree = pData = fts5DataRead(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid, ii)); - } - - if( pData ){ - int szKeyIn = TOMBSTONE_KEYSIZE(pData); - int nSlotIn = (pData->nn - 8) / szKeyIn; - int iIn; - for(iIn=0; iInp[8]; - if( aSlot[iIn] ) iVal = fts5GetU32((u8*)&aSlot[iIn]); - }else{ - u64 *aSlot = (u64*)&pData->p[8]; - if( aSlot[iIn] ) iVal = fts5GetU64((u8*)&aSlot[iIn]); - } - - /* If iVal is not 0 at this point, insert it into the new hash table */ - if( iVal ){ - Fts5Data *pPg = apOut[(iVal % nOut)]; - res = fts5IndexTombstoneAddToPage(pPg, 0, nOut, iVal); - if( res ) break; - } - } - - /* If this is page 0 of the old hash, copy the rowid-0-flag from the - ** old hash to the new. */ - if( ii==0 ){ - apOut[0]->p[1] = pData->p[1]; - } - } - fts5DataRelease(pFree); - } - - return res; -} - -/* -** This is called to rebuild the hash table belonging to segment pSeg. -** If parameter pData1 is not NULL, then one page of the existing hash table -** has already been loaded - pData1, which is page iPg1. The key-size for -** the new hash table is szKey (4 or 8). -** -** If successful, the new hash table is not written to disk. Instead, -** output parameter (*pnOut) is set to the number of pages in the new -** hash table, and (*papOut) to point to an array of buffers containing -** the new page data. -** -** If an error occurs, an error code is left in the Fts5Index object and -** both output parameters set to 0 before returning. -*/ -static void fts5IndexTombstoneRebuild( - Fts5Index *p, - Fts5StructureSegment *pSeg, /* Segment to rebuild hash of */ - Fts5Data *pData1, /* One page of current hash - or NULL */ - int iPg1, /* Which page of the current hash is pData1 */ - int szKey, /* 4 or 8, the keysize */ - int *pnOut, /* OUT: Number of output pages */ - Fts5Data ***papOut /* OUT: Output hash pages */ -){ - const int MINSLOT = 32; - int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey); - int nSlot = 0; /* Number of slots in each output page */ - int nOut = 0; - - /* Figure out how many output pages (nOut) and how many slots per - ** page (nSlot). There are three possibilities: - ** - ** 1. The hash table does not yet exist. In this case the new hash - ** table will consist of a single page with MINSLOT slots. - ** - ** 2. The hash table exists but is currently a single page. In this - ** case an attempt is made to grow the page to accommodate the new - ** entry. The page is allowed to grow up to nSlotPerPage (see above) - ** slots. - ** - ** 3. The hash table already consists of more than one page, or of - ** a single page already so large that it cannot be grown. In this - ** case the new hash consists of (nPg*2+1) pages of nSlotPerPage - ** slots each, where nPg is the current number of pages in the - ** hash table. - */ - if( pSeg->nPgTombstone==0 ){ - /* Case 1. */ - nOut = 1; - nSlot = MINSLOT; - }else if( pSeg->nPgTombstone==1 ){ - /* Case 2. */ - int nElem = (int)fts5GetU32(&pData1->p[4]); - assert( pData1 && iPg1==0 ); - nOut = 1; - nSlot = MAX(nElem*4, MINSLOT); - if( nSlot>nSlotPerPage ) nOut = 0; - } - if( nOut==0 ){ - /* Case 3. */ - nOut = (pSeg->nPgTombstone * 2 + 1); - nSlot = nSlotPerPage; - } - - /* Allocate the required array and output pages */ - while( 1 ){ - int res = 0; - int ii = 0; - int szPage = 0; - Fts5Data **apOut = 0; - - /* Allocate space for the new hash table */ - assert( nSlot>=MINSLOT ); - apOut = (Fts5Data**)sqlite3Fts5MallocZero(&p->rc, sizeof(Fts5Data*) * nOut); - szPage = 8 + nSlot*szKey; - for(ii=0; iirc, - sizeof(Fts5Data)+szPage - ); - if( pNew ){ - pNew->nn = szPage; - pNew->p = (u8*)&pNew[1]; - apOut[ii] = pNew; - } - } - - /* Rebuild the hash table. */ - if( p->rc==SQLITE_OK ){ - res = fts5IndexTombstoneRehash(p, pSeg, pData1, iPg1, szKey, nOut, apOut); - } - if( res==0 ){ - if( p->rc ){ - fts5IndexFreeArray(apOut, nOut); - apOut = 0; - nOut = 0; - } - *pnOut = nOut; - *papOut = apOut; - break; - } - - /* If control flows to here, it was not possible to rebuild the hash - ** table. Free all buffers and then try again with more pages. */ - assert( p->rc==SQLITE_OK ); - fts5IndexFreeArray(apOut, nOut); - nSlot = nSlotPerPage; - nOut = nOut*2 + 1; - } -} - - -/* -** Add a tombstone for rowid iRowid to segment pSeg. -*/ -static void fts5IndexTombstoneAdd( - Fts5Index *p, - Fts5StructureSegment *pSeg, - u64 iRowid -){ - Fts5Data *pPg = 0; - int iPg = -1; - int szKey = 0; - int nHash = 0; - Fts5Data **apHash = 0; - - p->nContentlessDelete++; - - if( pSeg->nPgTombstone>0 ){ - iPg = iRowid % pSeg->nPgTombstone; - pPg = fts5DataRead(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid,iPg)); - if( pPg==0 ){ - assert( p->rc!=SQLITE_OK ); - return; - } - - if( 0==fts5IndexTombstoneAddToPage(pPg, 0, pSeg->nPgTombstone, iRowid) ){ - fts5DataWrite(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid,iPg), pPg->p, pPg->nn); - fts5DataRelease(pPg); - return; - } - } - - /* Have to rebuild the hash table. First figure out the key-size (4 or 8). */ - szKey = pPg ? TOMBSTONE_KEYSIZE(pPg) : 4; - if( iRowid>0xFFFFFFFF ) szKey = 8; - - /* Rebuild the hash table */ - fts5IndexTombstoneRebuild(p, pSeg, pPg, iPg, szKey, &nHash, &apHash); - assert( p->rc==SQLITE_OK || (nHash==0 && apHash==0) ); - - /* If all has succeeded, write the new rowid into one of the new hash - ** table pages, then write them all out to disk. */ - if( nHash ){ - int ii = 0; - fts5IndexTombstoneAddToPage(apHash[iRowid % nHash], 1, nHash, iRowid); - for(ii=0; iiiSegid, ii); - fts5DataWrite(p, iTombstoneRowid, apHash[ii]->p, apHash[ii]->nn); - } - pSeg->nPgTombstone = nHash; - fts5StructureWrite(p, p->pStruct); - } - - fts5DataRelease(pPg); - fts5IndexFreeArray(apHash, nHash); -} - -/* -** Add iRowid to the tombstone list of the segment or segments that contain -** rows from origin iOrigin. Return SQLITE_OK if successful, or an SQLite -** error code otherwise. -*/ -static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid){ - Fts5Structure *pStruct; - pStruct = fts5StructureRead(p); - if( pStruct ){ - int bFound = 0; /* True after pSeg->nEntryTombstone incr. */ - int iLvl; - for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){ - int iSeg; - for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){ - Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; - if( pSeg->iOrigin1<=(u64)iOrigin && pSeg->iOrigin2>=(u64)iOrigin ){ - if( bFound==0 ){ - pSeg->nEntryTombstone++; - bFound = 1; - } - fts5IndexTombstoneAdd(p, pSeg, iRowid); - } - } - } - fts5StructureRelease(pStruct); - } - return fts5IndexReturn(p); -} /************************************************************************* ************************************************************************** -** Below this point is the implementation of the integrity-check +** Below this point is the implementation of the integrity-check ** functionality. */ /* ** Return a simple checksum value based on the arguments. */ static u64 sqlite3Fts5IndexEntryCksum( - i64 iRowid, - int iCol, - int iPos, + i64 iRowid, + int iCol, + int iPos, int iIdx, const char *pTerm, int nTerm ){ int i; @@ -250884,19 +196661,19 @@ return ret; } #ifdef SQLITE_DEBUG /* -** This function is purely an internal test. It does not contribute to +** This function is purely an internal test. It does not contribute to ** FTS functionality, or even the integrity-check, in any way. ** -** Instead, it tests that the same set of pgno/rowid combinations are +** Instead, it tests that the same set of pgno/rowid combinations are ** visited regardless of whether the doclist-index identified by parameters ** iSegid/iLeaf is iterated in forwards or reverse order. */ static void fts5TestDlidxReverse( - Fts5Index *p, + Fts5Index *p, int iSegid, /* Segment id to load from */ int iLeaf /* Load doclist-index for this leaf */ ){ Fts5DlidxIter *pDlidx = 0; u64 cksum1 = 13; @@ -250938,15 +196715,13 @@ u64 *pCksum /* IN/OUT: Checksum value */ ){ int eDetail = p->pConfig->eDetail; u64 cksum = *pCksum; Fts5IndexIter *pIter = 0; - int rc = sqlite3Fts5IndexQuery( - p, z, n, (flags | FTS5INDEX_QUERY_NOTOKENDATA), 0, &pIter - ); + int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); - while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){ + while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ i64 rowid = pIter->iRowid; if( eDetail==FTS5_DETAIL_NONE ){ cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); }else{ @@ -250962,54 +196737,23 @@ } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IterNext(pIter); } } - fts5IterClose(pIter); + sqlite3Fts5IterClose(pIter); *pCksum = cksum; return rc; } -/* -** Check if buffer z[], size n bytes, contains as series of valid utf-8 -** encoded codepoints. If so, return 0. Otherwise, if the buffer does not -** contain valid utf-8, return non-zero. -*/ -static int fts5TestUtf8(const char *z, int n){ - int i = 0; - assert_nc( n>0 ); - while( i=n || (z[i+1] & 0xC0)!=0x80 ) return 1; - i += 2; - }else - if( (z[i] & 0xF0)==0xE0 ){ - if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1; - i += 3; - }else - if( (z[i] & 0xF8)==0xF0 ){ - if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1; - if( (z[i+2] & 0xC0)!=0x80 ) return 1; - i += 3; - }else{ - return 1; - } - } - - return 0; -} - -/* -** This function is also purely an internal test. It does not contribute to + +/* +** This function is also purely an internal test. It does not contribute to ** FTS functionality, or even the integrity-check, in any way. */ static void fts5TestTerm( - Fts5Index *p, + Fts5Index *p, Fts5Buffer *pPrev, /* Previous term */ const char *z, int n, /* Possibly new term to test */ u64 expected, u64 *pCksum ){ @@ -251034,23 +196778,17 @@ rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2); } if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT; /* If this is a prefix query, check that the results returned if the - ** the index is disabled are the same. In both ASC and DESC order. + ** the index is disabled are the same. In both ASC and DESC order. ** ** This check may only be performed if the hash table is empty. This ** is because the hash table only supports a single scan query at ** a time, and the multi-iter loop from which this function is called - ** is already performing such a scan. - ** - ** Also only do this if buffer zTerm contains nTerm bytes of valid - ** utf-8. Otherwise, the last part of the buffer contents might contain - ** a non-utf-8 sequence that happens to be a prefix of a valid utf-8 - ** character stored in the main fts index, which will cause the - ** test to fail. */ - if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){ + ** is already performing such a scan. */ + if( p->nPendingData==0 ){ if( iIdx>0 && rc==SQLITE_OK ){ int f = flags|FTS5INDEX_QUERY_TEST_NOIDX; ck2 = 0; rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2); if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT; @@ -251071,11 +196809,11 @@ } *pCksum = cksum3; } p->rc = rc; } - + #else # define fts5TestDlidxReverse(x,y,z) # define fts5TestTerm(u,v,w,x,y,z) #endif @@ -251107,20 +196845,20 @@ fts5DataRelease(pLeaf); } } static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ - i64 iTermOff = 0; + int iTermOff = 0; int ii; Fts5Buffer buf1 = {0,0,0}; Fts5Buffer buf2 = {0,0,0}; ii = pLeaf->szLeaf; while( iinn && p->rc==SQLITE_OK ){ int res; - i64 iOff; + int iOff; int nIncr; ii += fts5GetVarint32(&pLeaf->p[ii], nIncr); iTermOff += nIncr; iOff = iTermOff; @@ -251161,35 +196899,33 @@ static void fts5IndexIntegrityCheckSegment( Fts5Index *p, /* FTS5 backend object */ Fts5StructureSegment *pSeg /* Segment to check internal consistency */ ){ Fts5Config *pConfig = p->pConfig; - int bSecureDelete = (pConfig->iVersion==FTS5_CURRENT_VERSION_SECUREDELETE); sqlite3_stmt *pStmt = 0; int rc2; int iIdxPrevLeaf = pSeg->pgnoFirst-1; int iDlidxPrevLeaf = pSeg->pgnoLast; if( pSeg->pgnoFirst==0 ) return; fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf( - "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d " - "ORDER BY 1, 2", + "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d", pConfig->zDb, pConfig->zName, pSeg->iSegid )); /* Iterate through the b-tree hierarchy. */ while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ i64 iRow; /* Rowid for this leaf */ Fts5Data *pLeaf; /* Data for this leaf */ - const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1); int nIdxTerm = sqlite3_column_bytes(pStmt, 1); + const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1); int iIdxLeaf = sqlite3_column_int(pStmt, 2); int bIdxDlidx = sqlite3_column_int(pStmt, 3); - /* If the leaf in question has already been trimmed from the segment, + /* If the leaf in question has already been trimmed from the segment, ** ignore this b-tree entry. Otherwise, load it into memory. */ if( iIdxLeafpgnoFirst ) continue; iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf); pLeaf = fts5LeafRead(p, iRow); if( pLeaf==0 ) break; @@ -251197,36 +196933,24 @@ /* Check that the leaf contains at least one term, and that it is equal ** to or larger than the split-key in zIdxTerm. Also check that if there ** is also a rowid pointer within the leaf page header, it points to a ** location before the term. */ if( pLeaf->nn<=pLeaf->szLeaf ){ - - if( nIdxTerm==0 - && pConfig->iVersion==FTS5_CURRENT_VERSION_SECUREDELETE - && pLeaf->nn==pLeaf->szLeaf - && pLeaf->nn==4 - ){ - /* special case - the very first page in a segment keeps its %_idx - ** entry even if all the terms are removed from it by secure-delete - ** operations. */ - }else{ - p->rc = FTS5_CORRUPT; - } - + p->rc = FTS5_CORRUPT; }else{ int iOff; /* Offset of first term on leaf */ int iRowidOff; /* Offset of first rowid on leaf */ int nTerm; /* Size of term on leaf in bytes */ int res; /* Comparison of term and split-key */ iOff = fts5LeafFirstTermOff(pLeaf); iRowidOff = fts5LeafFirstRowidOff(pLeaf); - if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){ + if( iRowidOff>=iOff ){ p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); - res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); + res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); if( res==0 ) res = nTerm - nIdxTerm; if( res<0 ) p->rc = FTS5_CORRUPT; } fts5IntegrityCheckPgidx(p, pLeaf); @@ -251273,16 +196997,13 @@ i64 iRowid; int iRowidOff = fts5LeafFirstRowidOff(pLeaf); ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; - }else if( bSecureDelete==0 || iRowidOff>0 ){ - i64 iDlRowid = fts5DlidxIterRowid(pDlidx); + }else{ fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); - if( iRowidrc = FTS5_CORRUPT; - } + if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT; } fts5DataRelease(pLeaf); } } @@ -251308,46 +197029,44 @@ #endif } /* -** Run internal checks to ensure that the FTS index (a) is internally +** Run internal checks to ensure that the FTS index (a) is internally ** consistent and (b) contains entries for which the XOR of the checksums ** as calculated by sqlite3Fts5IndexEntryCksum() is cksum. ** ** Return SQLITE_CORRUPT if any of the internal checks fail, or if the ** checksum does not match. Return SQLITE_OK if all checks pass without ** error, or some other SQLite error code if another error (e.g. OOM) ** occurs. */ -static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){ +static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ int eDetail = p->pConfig->eDetail; u64 cksum2 = 0; /* Checksum based on contents of indexes */ Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ Fts5Iter *pIter; /* Used to iterate through entire index */ Fts5Structure *pStruct; /* Index structure */ - int iLvl, iSeg; #ifdef SQLITE_DEBUG /* Used by extra internal tests only run if NDEBUG is not defined */ u64 cksum3 = 0; /* Checksum based on contents of indexes */ Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ #endif const int flags = FTS5INDEX_QUERY_NOOUTPUT; - + /* Load the FTS index structure */ pStruct = fts5StructureRead(p); - if( pStruct==0 ){ - assert( p->rc!=SQLITE_OK ); - return fts5IndexReturn(p); - } /* Check that the internal nodes of each segment match the leaves */ - for(iLvl=0; iLvlnLevel; iLvl++){ - for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ - Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; - fts5IndexIntegrityCheckSegment(p, pSeg); + if( pStruct ){ + int iLvl, iSeg; + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ + Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; + fts5IndexIntegrityCheckSegment(p, pSeg); + } } } /* The cksum argument passed to this function is a checksum calculated ** based on all expected entries in the FTS index (including prefix index @@ -251354,11 +197073,11 @@ ** entries). This block checks that a checksum calculated based on the ** actual contents of FTS index is identical. ** ** Two versions of the same checksum are calculated. The first (stack ** variable cksum2) based on entries extracted from the full-text index - ** while doing a linear scan of each individual index in turn. + ** while doing a linear scan of each individual index in turn. ** ** As each term visited by the linear scans, a separate query for the ** same term is performed. cksum3 is calculated based on the entries ** extracted by these queries. */ @@ -251372,20 +197091,18 @@ i64 iRowid = fts5MultiIterRowid(pIter); char *z = (char*)fts5MultiIterTerm(pIter, &n); /* If this is a new term, query for it. Update cksum3 with the results. */ fts5TestTerm(p, &term, z, n, cksum2, &cksum3); - if( p->rc ) break; if( eDetail==FTS5_DETAIL_NONE ){ if( 0==fts5MultiIterIsEmpty(p, pIter) ){ cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n); } }else{ poslist.n = 0; fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist); - fts5BufferAppendBlob(&p->rc, &poslist, 4, (const u8*)"\0\0\0\0"); while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){ int iCol = FTS5_POS2COLUMN(iPos); int iTokOff = FTS5_POS2OFFSET(iPos); cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n); } @@ -251392,11 +197109,11 @@ } } fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); fts5MultiIterFree(pIter); - if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; + if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; fts5StructureRelease(pStruct); #ifdef SQLITE_DEBUG fts5BufferFree(&term); #endif @@ -251408,18 +197125,16 @@ ************************************************************************** ** Below this point is the implementation of the fts5_decode() scalar ** function only. */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** Decode a segment-data rowid from the %_data table. This function is ** the opposite of macro FTS5_SEGMENT_ROWID(). */ static void fts5DecodeRowid( i64 iRowid, /* Rowid from %_data table */ - int *pbTombstone, /* OUT: Tombstone hash flag */ int *piSegid, /* OUT: Segment id */ int *pbDlidx, /* OUT: Dlidx flag */ int *piHeight, /* OUT: Height */ int *piPgno /* OUT: Page number */ ){ @@ -251431,75 +197146,58 @@ *pbDlidx = (int)(iRowid & 0x0001); iRowid >>= FTS5_DATA_DLI_B; *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1)); - iRowid >>= FTS5_DATA_ID_B; +} - *pbTombstone = (int)(iRowid & 0x0001); -} -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ - -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){ - int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */ - fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno); + int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */ + fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno); if( iSegid==0 ){ if( iKey==FTS5_AVERAGES_ROWID ){ sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} "); }else{ sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}"); } } else{ - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%s%ssegid=%d h=%d pgno=%d}", - bDlidx ? "dlidx " : "", - bTomb ? "tombstone " : "", - iSegid, iHeight, iPgno + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}", + bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno ); } } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static void fts5DebugStructure( int *pRc, /* IN/OUT: error code */ Fts5Buffer *pBuf, Fts5Structure *p ){ int iLvl, iSeg; /* Iterate through levels, segments */ for(iLvl=0; iLvlnLevel; iLvl++){ Fts5StructureLevel *pLvl = &p->aLevel[iLvl]; - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {lvl=%d nMerge=%d nSeg=%d", iLvl, pLvl->nMerge, pLvl->nSeg ); for(iSeg=0; iSegnSeg; iSeg++){ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d", + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}", pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast ); - if( pSeg->iOrigin1>0 ){ - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " origin=%lld..%lld", - pSeg->iOrigin1, pSeg->iOrigin2 - ); - } - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}"); } sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}"); } } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This is part of the fts5_decode() debugging aid. ** ** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This ** function appends a human-readable representation of the same object -** to the buffer passed as the second argument. +** to the buffer passed as the second argument. */ static void fts5DecodeStructure( int *pRc, /* IN/OUT: error code */ Fts5Buffer *pBuf, const u8 *pBlob, int nBlob @@ -251514,19 +197212,17 @@ } fts5DebugStructure(pRc, pBuf, p); fts5StructureRelease(p); } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This is part of the fts5_decode() debugging aid. ** -** Arguments pBlob/nBlob contain an "averages" record. This function -** appends a human-readable representation of record to the buffer passed -** as the second argument. +** Arguments pBlob/nBlob contain an "averages" record. This function +** appends a human-readable representation of record to the buffer passed +** as the second argument. */ static void fts5DecodeAverages( int *pRc, /* IN/OUT: error code */ Fts5Buffer *pBuf, const u8 *pBlob, int nBlob @@ -251539,13 +197235,11 @@ i += sqlite3Fts5GetVarint(&pBlob[i], &iVal); sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal); zSpace = " "; } } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** Buffer (a/n) is assumed to contain a list of serialized varints. Read ** each varint and append its string representation to buffer pBuf. Return ** after either the input buffer is exhausted or a 0 value is read. ** @@ -251558,18 +197252,16 @@ iOff += fts5GetVarint32(&a[iOff], iVal); sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal); } return iOff; } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** The start of buffer (a/n) contains the start of a doclist. The doclist ** may or may not finish within the buffer. This function appends a text ** representation of the part of the doclist that is present to buffer -** pBuf. +** pBuf. ** ** The return value is the number of bytes read from the input buffer. */ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){ i64 iDocid = 0; @@ -251593,15 +197285,13 @@ } } return iOff; } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* -** This function is part of the fts5_decode() debugging function. It is +** This function is part of the fts5_decode() debugging function. It is ** only ever used with detail=none tables. ** ** Buffer (pData/nData) contains a doclist in the format used by detail=none ** tables. This function appends a human-readable version of that list to ** buffer pBuf. @@ -251636,31 +197326,11 @@ } sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp); } } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ - -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) -static void fts5BufferAppendTerm(int *pRc, Fts5Buffer *pBuf, Fts5Buffer *pTerm){ - int ii; - fts5BufferGrow(pRc, pBuf, pTerm->n*2 + 1); - if( *pRc==SQLITE_OK ){ - for(ii=0; iin; ii++){ - if( pTerm->p[ii]==0x00 ){ - pBuf->p[pBuf->n++] = '\\'; - pBuf->p[pBuf->n++] = '0'; - }else{ - pBuf->p[pBuf->n++] = pTerm->p[ii]; - } - } - pBuf->p[pBuf->n] = 0x00; - } -} -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ - -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) + /* ** The implementation of user-defined scalar function fts5_decode(). */ static void fts5DecodeFunction( sqlite3_context *pCtx, /* Function call context */ @@ -251667,16 +197337,15 @@ int nArg, /* Number of args (always 2) */ sqlite3_value **apVal /* Function arguments */ ){ i64 iRowid; /* Rowid for record being decoded */ int iSegid,iHeight,iPgno,bDlidx;/* Rowid components */ - int bTomb; const u8 *aBlob; int n; /* Record to decode */ u8 *a = 0; Fts5Buffer s; /* Build up text to return here */ int rc = SQLITE_OK; /* Return code */ - sqlite3_int64 nSpace = 0; + int nSpace = 0; int eDetailNone = (sqlite3_user_data(pCtx)!=0); assert( nArg==2 ); UNUSED_PARAM(nArg); memset(&s, 0, sizeof(Fts5Buffer)); @@ -251688,13 +197357,14 @@ n = sqlite3_value_bytes(apVal[1]); aBlob = sqlite3_value_blob(apVal[1]); nSpace = n + FTS5_DATA_ZERO_PADDING; a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace); if( a==0 ) goto decode_out; - if( n>0 ) memcpy(a, aBlob, n); + memcpy(a, aBlob, n); - fts5DecodeRowid(iRowid, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno); + + fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno); fts5DebugRowid(&rc, &s, iRowid); if( bDlidx ){ Fts5Data dlidx; Fts5DlidxLvl lvl; @@ -251705,36 +197375,14 @@ memset(&lvl, 0, sizeof(Fts5DlidxLvl)); lvl.pData = &dlidx; lvl.iLeafPgno = iPgno; for(fts5DlidxLvlNext(&lvl); lvl.bEof==0; fts5DlidxLvlNext(&lvl)){ - sqlite3Fts5BufferAppendPrintf(&rc, &s, + sqlite3Fts5BufferAppendPrintf(&rc, &s, " %d(%lld)", lvl.iLeafPgno, lvl.iRowid ); } - }else if( bTomb ){ - u32 nElem = fts5GetU32(&a[4]); - int szKey = (aBlob[0]==4 || aBlob[0]==8) ? aBlob[0] : 8; - int nSlot = (n - 8) / szKey; - int ii; - sqlite3Fts5BufferAppendPrintf(&rc, &s, " nElem=%d", (int)nElem); - if( aBlob[1] ){ - sqlite3Fts5BufferAppendPrintf(&rc, &s, " 0"); - } - for(ii=0; iiszLeaf ){ - rc = FTS5_CORRUPT; - }else{ - fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff); - } + + fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff); iOff = iTermOff; if( iOffn ){ - rc = FTS5_CORRUPT; - goto decode_out; } } /* Decode the position list tail at the start of the page */ if( iRowidOff!=0 ){ @@ -251821,30 +197464,22 @@ }else if( iTermOff!=0 ){ iOff = iTermOff; }else{ iOff = szLeaf; } - if( iOff>n ){ - rc = FTS5_CORRUPT; - goto decode_out; - } fts5DecodePoslist(&rc, &s, &a[4], iOff-4); /* Decode any more doclist data that appears on the page before the ** first term. */ nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff; - if( nDoclist+iOff>n ){ - rc = FTS5_CORRUPT; - goto decode_out; - } fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist); - while( iPgidxOffszLeaf ){ - rc = FTS5_CORRUPT; - break; - } if( bFirst==0 ){ iOff += fts5GetVarint32(&a[iOff], nByte); - if( nByte>term.n ){ - rc = FTS5_CORRUPT; - break; - } term.n = nByte; } iOff += fts5GetVarint32(&a[iOff], nByte); - if( iOff+nByte>n ){ - rc = FTS5_CORRUPT; - break; - } fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]); iOff += nByte; - sqlite3Fts5BufferAppendPrintf(&rc, &s, " term="); - fts5BufferAppendTerm(&rc, &s, &term); + sqlite3Fts5BufferAppendPrintf( + &rc, &s, " term=%.*s", term.n, (const char*)term.p + ); iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff); } fts5BufferFree(&term); } - + decode_out: sqlite3_free(a); if( rc==SQLITE_OK ){ sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT); }else{ sqlite3_result_error_code(pCtx, rc); } fts5BufferFree(&s); } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** The implementation of user-defined scalar function fts5_rowid(). */ static void fts5RowidFunction( sqlite3_context *pCtx, /* Function call context */ @@ -251909,255 +197531,26 @@ zArg = (const char*)sqlite3_value_text(apVal[0]); if( 0==sqlite3_stricmp(zArg, "segment") ){ i64 iRowid; int segid, pgno; if( nArg!=3 ){ - sqlite3_result_error(pCtx, + sqlite3_result_error(pCtx, "should be: fts5_rowid('segment', segid, pgno))", -1 ); }else{ segid = sqlite3_value_int(apVal[1]); pgno = sqlite3_value_int(apVal[2]); iRowid = FTS5_SEGMENT_ROWID(segid, pgno); sqlite3_result_int64(pCtx, iRowid); } }else{ - sqlite3_result_error(pCtx, + sqlite3_result_error(pCtx, "first arg to fts5_rowid() must be 'segment'" , -1 ); } } } -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ - -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) - -typedef struct Fts5StructVtab Fts5StructVtab; -struct Fts5StructVtab { - sqlite3_vtab base; -}; - -typedef struct Fts5StructVcsr Fts5StructVcsr; -struct Fts5StructVcsr { - sqlite3_vtab_cursor base; - Fts5Structure *pStruct; - int iLevel; - int iSeg; - int iRowid; -}; - -/* -** Create a new fts5_structure() table-valued function. -*/ -static int fts5structConnectMethod( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - Fts5StructVtab *pNew = 0; - int rc = SQLITE_OK; - - rc = sqlite3_declare_vtab(db, - "CREATE TABLE xyz(" - "level, segment, merge, segid, leaf1, leaf2, loc1, loc2, " - "npgtombstone, nentrytombstone, nentry, struct HIDDEN);" - ); - if( rc==SQLITE_OK ){ - pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew)); - } - - *ppVtab = (sqlite3_vtab*)pNew; - return rc; -} - -/* -** We must have a single struct=? constraint that will be passed through -** into the xFilter method. If there is no valid struct=? constraint, -** then return an SQLITE_CONSTRAINT error. -*/ -static int fts5structBestIndexMethod( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo -){ - int i; - int rc = SQLITE_CONSTRAINT; - struct sqlite3_index_constraint *p; - pIdxInfo->estimatedCost = (double)100; - pIdxInfo->estimatedRows = 100; - pIdxInfo->idxNum = 0; - for(i=0, p=pIdxInfo->aConstraint; inConstraint; i++, p++){ - if( p->usable==0 ) continue; - if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==11 ){ - rc = SQLITE_OK; - pIdxInfo->aConstraintUsage[i].omit = 1; - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - break; - } - } - return rc; -} - -/* -** This method is the destructor for bytecodevtab objects. -*/ -static int fts5structDisconnectMethod(sqlite3_vtab *pVtab){ - Fts5StructVtab *p = (Fts5StructVtab*)pVtab; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Constructor for a new bytecodevtab_cursor object. -*/ -static int fts5structOpenMethod(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){ - int rc = SQLITE_OK; - Fts5StructVcsr *pNew = 0; - - pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew)); - *ppCsr = (sqlite3_vtab_cursor*)pNew; - - return SQLITE_OK; -} - -/* -** Destructor for a bytecodevtab_cursor. -*/ -static int fts5structCloseMethod(sqlite3_vtab_cursor *cur){ - Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; - fts5StructureRelease(pCsr->pStruct); - sqlite3_free(pCsr); - return SQLITE_OK; -} - - -/* -** Advance a bytecodevtab_cursor to its next row of output. -*/ -static int fts5structNextMethod(sqlite3_vtab_cursor *cur){ - Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; - Fts5Structure *p = pCsr->pStruct; - - assert( pCsr->pStruct ); - pCsr->iSeg++; - pCsr->iRowid++; - while( pCsr->iLevelnLevel && pCsr->iSeg>=p->aLevel[pCsr->iLevel].nSeg ){ - pCsr->iLevel++; - pCsr->iSeg = 0; - } - if( pCsr->iLevel>=p->nLevel ){ - fts5StructureRelease(pCsr->pStruct); - pCsr->pStruct = 0; - } - return SQLITE_OK; -} - -/* -** Return TRUE if the cursor has been moved off of the last -** row of output. -*/ -static int fts5structEofMethod(sqlite3_vtab_cursor *cur){ - Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; - return pCsr->pStruct==0; -} - -static int fts5structRowidMethod( - sqlite3_vtab_cursor *cur, - sqlite_int64 *piRowid -){ - Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; - *piRowid = pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Return values of columns for the row at which the bytecodevtab_cursor -** is currently pointing. -*/ -static int fts5structColumnMethod( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ -){ - Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; - Fts5Structure *p = pCsr->pStruct; - Fts5StructureSegment *pSeg = &p->aLevel[pCsr->iLevel].aSeg[pCsr->iSeg]; - - switch( i ){ - case 0: /* level */ - sqlite3_result_int(ctx, pCsr->iLevel); - break; - case 1: /* segment */ - sqlite3_result_int(ctx, pCsr->iSeg); - break; - case 2: /* merge */ - sqlite3_result_int(ctx, pCsr->iSeg < p->aLevel[pCsr->iLevel].nMerge); - break; - case 3: /* segid */ - sqlite3_result_int(ctx, pSeg->iSegid); - break; - case 4: /* leaf1 */ - sqlite3_result_int(ctx, pSeg->pgnoFirst); - break; - case 5: /* leaf2 */ - sqlite3_result_int(ctx, pSeg->pgnoLast); - break; - case 6: /* origin1 */ - sqlite3_result_int64(ctx, pSeg->iOrigin1); - break; - case 7: /* origin2 */ - sqlite3_result_int64(ctx, pSeg->iOrigin2); - break; - case 8: /* npgtombstone */ - sqlite3_result_int(ctx, pSeg->nPgTombstone); - break; - case 9: /* nentrytombstone */ - sqlite3_result_int64(ctx, pSeg->nEntryTombstone); - break; - case 10: /* nentry */ - sqlite3_result_int64(ctx, pSeg->nEntry); - break; - } - return SQLITE_OK; -} - -/* -** Initialize a cursor. -** -** idxNum==0 means show all subprograms -** idxNum==1 means show only the main bytecode and omit subprograms. -*/ -static int fts5structFilterMethod( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - Fts5StructVcsr *pCsr = (Fts5StructVcsr *)pVtabCursor; - int rc = SQLITE_OK; - - const u8 *aBlob = 0; - int nBlob = 0; - - assert( argc==1 ); - fts5StructureRelease(pCsr->pStruct); - pCsr->pStruct = 0; - - nBlob = sqlite3_value_bytes(argv[0]); - aBlob = (const u8*)sqlite3_value_blob(argv[0]); - rc = fts5StructureDecode(aBlob, nBlob, 0, &pCsr->pStruct); - if( rc==SQLITE_OK ){ - pCsr->iLevel = 0; - pCsr->iRowid = 0; - pCsr->iSeg = -1; - rc = fts5structNextMethod(pVtabCursor); - } - - return rc; -} - -#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ /* ** This is called as part of registering the FTS5 module with database ** connection db. It registers several user-defined scalar functions useful ** with FTS5. @@ -252164,63 +197557,27 @@ ** ** If successful, SQLITE_OK is returned. If an error occurs, some other ** SQLite error code is returned instead. */ static int sqlite3Fts5IndexInit(sqlite3 *db){ -#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) int rc = sqlite3_create_function( db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0 ); if( rc==SQLITE_OK ){ rc = sqlite3_create_function( - db, "fts5_decode_none", 2, + db, "fts5_decode_none", 2, SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0 ); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function( db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0 ); } - - if( rc==SQLITE_OK ){ - static const sqlite3_module fts5structure_module = { - 0, /* iVersion */ - 0, /* xCreate */ - fts5structConnectMethod, /* xConnect */ - fts5structBestIndexMethod, /* xBestIndex */ - fts5structDisconnectMethod, /* xDisconnect */ - 0, /* xDestroy */ - fts5structOpenMethod, /* xOpen */ - fts5structCloseMethod, /* xClose */ - fts5structFilterMethod, /* xFilter */ - fts5structNextMethod, /* xNext */ - fts5structEofMethod, /* xEof */ - fts5structColumnMethod, /* xColumn */ - fts5structRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ - }; - rc = sqlite3_create_module(db, "fts5_structure", &fts5structure_module, 0); - } return rc; -#else - return SQLITE_OK; - UNUSED_PARAM(db); -#endif } static int sqlite3Fts5IndexReset(Fts5Index *p){ assert( p->pStruct==0 || p->iStructVersion!=0 ); @@ -252252,46 +197609,44 @@ ** This variable is set to false when running tests for which the on disk ** structures should not be corrupt. Otherwise, true. If it is false, extra ** assert() conditions in the fts5 code are activated - conditions that are ** only true if it is guaranteed that the fts5 database is not corrupt. */ -#ifdef SQLITE_DEBUG SQLITE_API int sqlite3_fts5_may_be_corrupt = 1; -#endif typedef struct Fts5Auxdata Fts5Auxdata; typedef struct Fts5Auxiliary Fts5Auxiliary; typedef struct Fts5Cursor Fts5Cursor; -typedef struct Fts5FullTable Fts5FullTable; typedef struct Fts5Sorter Fts5Sorter; +typedef struct Fts5Table Fts5Table; typedef struct Fts5TokenizerModule Fts5TokenizerModule; /* -** NOTES ON TRANSACTIONS: +** NOTES ON TRANSACTIONS: ** -** SQLite invokes the following virtual table methods as transactions are +** SQLite invokes the following virtual table methods as transactions are ** opened and closed by the user: ** ** xBegin(): Start of a new transaction. ** xSync(): Initial part of two-phase commit. ** xCommit(): Final part of two-phase commit. ** xRollback(): Rollback the transaction. ** ** Anything that is required as part of a commit that may fail is performed -** in the xSync() callback. Current versions of SQLite ignore any errors +** in the xSync() callback. Current versions of SQLite ignore any errors ** returned by xCommit(). ** ** And as sub-transactions are opened/closed: ** ** xSavepoint(int S): Open savepoint S. ** xRelease(int S): Commit and close savepoint S. ** xRollbackTo(int S): Rollback to start of savepoint S. ** -** During a write-transaction the fts5_index.c module may cache some data +** During a write-transaction the fts5_index.c module may cache some data ** in-memory. It is flushed to disk whenever xSync(), xRelease() or -** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo() +** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo() ** is called. ** ** Additionally, if SQLITE_DEBUG is defined, an instance of the following ** structure is used to record the current transaction state. This information ** is not required, but it is used in the assert() statements executed by @@ -252301,34 +197656,24 @@ int eState; /* 0==closed, 1==open, 2==synced */ int iSavepoint; /* Number of open savepoints (0 -> none) */ }; /* -** A single object of this type is allocated when the FTS5 module is +** A single object of this type is allocated when the FTS5 module is ** registered with a database handle. It is used to store pointers to ** all registered FTS5 extensions - tokenizers and auxiliary functions. */ struct Fts5Global { fts5_api api; /* User visible part of object (see fts5.h) */ - sqlite3 *db; /* Associated database connection */ + sqlite3 *db; /* Associated database connection */ i64 iNextId; /* Used to allocate unique cursor ids */ Fts5Auxiliary *pAux; /* First in list of all aux. functions */ Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */ Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */ Fts5Cursor *pCsr; /* First in list of all open cursors */ - u32 aLocaleHdr[4]; }; -/* -** Size of header on fts5_locale() values. And macro to access a buffer -** containing a copy of the header from an Fts5Config pointer. -*/ -#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr )) -#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr)) - -#define FTS5_INSTTOKEN_SUBTYPE 73 - /* ** Each auxiliary function registered with the FTS5 module is represented ** by an object of the following type. All such objects are stored as part ** of the Fts5Global.pAux list. */ @@ -252343,43 +197688,29 @@ /* ** Each tokenizer module registered with the FTS5 module is represented ** by an object of the following type. All such objects are stored as part ** of the Fts5Global.pTok list. -** -** bV2Native: -** True if the tokenizer was registered using xCreateTokenizer_v2(), false -** for xCreateTokenizer(). If this variable is true, then x2 is populated -** with the routines as supplied by the caller and x1 contains synthesized -** wrapper routines. In this case the user-data pointer passed to -** x1.xCreate should be a pointer to the Fts5TokenizerModule structure, -** not a copy of pUserData. -** -** Of course, if bV2Native is false, then x1 contains the real routines and -** x2 the synthesized ones. In this case a pointer to the Fts5TokenizerModule -** object should be passed to x2.xCreate. -** -** The synthesized wrapper routines are necessary for xFindTokenizer(_v2) -** calls. */ struct Fts5TokenizerModule { char *zName; /* Name of tokenizer */ void *pUserData; /* User pointer passed to xCreate() */ - int bV2Native; /* True if v2 native tokenizer */ - fts5_tokenizer x1; /* Tokenizer functions */ - fts5_tokenizer_v2 x2; /* V2 tokenizer functions */ + fts5_tokenizer x; /* Tokenizer functions */ void (*xDestroy)(void*); /* Destructor function */ Fts5TokenizerModule *pNext; /* Next registered tokenizer module */ }; -struct Fts5FullTable { - Fts5Table p; /* Public class members from fts5Int.h */ +/* +** Virtual-table object. +*/ +struct Fts5Table { + sqlite3_vtab base; /* Base class used by SQLite core */ + Fts5Config *pConfig; /* Virtual table configuration */ + Fts5Index *pIndex; /* Full-text index */ Fts5Storage *pStorage; /* Document store */ Fts5Global *pGlobal; /* Global (connection wide) data */ Fts5Cursor *pSortCsr; /* Sort data from this cursor */ - int iSavepoint; /* Successful xSavepoint()+1 */ - #ifdef SQLITE_DEBUG struct Fts5TransactionState ts; #endif }; @@ -252392,11 +197723,11 @@ ** pStmt: ** SELECT rowid, FROM ORDER BY +rank; ** ** aIdx[]: ** There is one entry in the aIdx[] array for each phrase in the query, -** the value of which is the offset within aPoslist[] following the last +** the value of which is the offset within aPoslist[] following the last ** byte of the position list for the corresponding phrase. */ struct Fts5Sorter { sqlite3_stmt *pStmt; i64 iRowid; /* Current rowid */ @@ -252408,12 +197739,12 @@ /* ** Virtual-table cursor object. ** ** iSpecial: -** If this is a 'special' query (refer to function fts5SpecialMatch()), -** then this variable contains the result of the query. +** If this is a 'special' query (refer to function fts5SpecialMatch()), +** then this variable contains the result of the query. ** ** iFirstRowid, iLastRowid: ** These variables are only used for FTS5_PLAN_MATCH cursors. Assuming the ** cursor iterates in ascending order of rowids, iFirstRowid is the lower ** limit of rowids to return, and iLastRowid the upper. In other words, the @@ -252452,19 +197783,19 @@ /* Auxiliary data storage */ Fts5Auxiliary *pAux; /* Currently executing extension function */ Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */ - /* Cache used by auxiliary API functions xInst() and xInstCount() */ + /* Cache used by auxiliary functions xInst() and xInstCount() */ Fts5PoslistReader *aInstIter; /* One for each phrase */ int nInstAlloc; /* Size of aInst[] array (entries / 3) */ int nInstCount; /* Number of phrase instances */ int *aInst; /* 3 integers per phrase instance */ }; /* -** Bits that make up the "idxNum" parameter passed indirectly by +** Bits that make up the "idxNum" parameter passed indirectly by ** xBestIndex() to xFilter(). */ #define FTS5_BI_MATCH 0x0001 /* MATCH ? */ #define FTS5_BI_RANK 0x0002 /* rank MATCH ? */ #define FTS5_BI_ROWID_EQ 0x0004 /* rowid == ? */ @@ -252510,20 +197841,20 @@ #define FTS5_COMMIT 3 #define FTS5_ROLLBACK 4 #define FTS5_SAVEPOINT 5 #define FTS5_RELEASE 6 #define FTS5_ROLLBACKTO 7 -static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){ +static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){ switch( op ){ case FTS5_BEGIN: assert( p->ts.eState==0 ); p->ts.eState = 1; p->ts.iSavepoint = -1; break; case FTS5_SYNC: - assert( p->ts.eState==1 || p->ts.eState==2 ); + assert( p->ts.eState==1 ); p->ts.eState = 2; break; case FTS5_COMMIT: assert( p->ts.eState==2 ); @@ -252534,68 +197865,59 @@ assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 ); p->ts.eState = 0; break; case FTS5_SAVEPOINT: - assert( p->ts.eState>=1 ); + assert( p->ts.eState==1 ); assert( iSavepoint>=0 ); - assert( iSavepoint>=p->ts.iSavepoint ); + assert( iSavepoint>p->ts.iSavepoint ); p->ts.iSavepoint = iSavepoint; break; - + case FTS5_RELEASE: - assert( p->ts.eState>=1 ); + assert( p->ts.eState==1 ); assert( iSavepoint>=0 ); assert( iSavepoint<=p->ts.iSavepoint ); p->ts.iSavepoint = iSavepoint-1; break; case FTS5_ROLLBACKTO: - assert( p->ts.eState>=1 ); - assert( iSavepoint>=-1 ); - /* The following assert() can fail if another vtab strikes an error - ** within an xSavepoint() call then SQLite calls xRollbackTo() - without - ** having called xSavepoint() on this vtab. */ - /* assert( iSavepoint<=p->ts.iSavepoint ); */ + assert( p->ts.eState==1 ); + assert( iSavepoint>=0 ); + assert( iSavepoint<=p->ts.iSavepoint ); p->ts.iSavepoint = iSavepoint; break; } } #else # define fts5CheckTransactionState(x,y,z) #endif /* -** Return true if pTab is a contentless table. If parameter bIncludeUnindexed -** is true, this includes contentless tables that store UNINDEXED columns -** only. +** Return true if pTab is a contentless table. */ -static int fts5IsContentless(Fts5FullTable *pTab, int bIncludeUnindexed){ - int eContent = pTab->p.pConfig->eContent; - return ( - eContent==FTS5_CONTENT_NONE - || (bIncludeUnindexed && eContent==FTS5_CONTENT_UNINDEXED) - ); +static int fts5IsContentless(Fts5Table *pTab){ + return pTab->pConfig->eContent==FTS5_CONTENT_NONE; } /* -** Delete a virtual table handle allocated by fts5InitVtab(). +** Delete a virtual table handle allocated by fts5InitVtab(). */ -static void fts5FreeVtab(Fts5FullTable *pTab){ +static void fts5FreeVtab(Fts5Table *pTab){ if( pTab ){ - sqlite3Fts5IndexClose(pTab->p.pIndex); + sqlite3Fts5IndexClose(pTab->pIndex); sqlite3Fts5StorageClose(pTab->pStorage); - sqlite3Fts5ConfigFree(pTab->p.pConfig); + sqlite3Fts5ConfigFree(pTab->pConfig); sqlite3_free(pTab); } } /* ** The xDisconnect() virtual table method. */ static int fts5DisconnectMethod(sqlite3_vtab *pVtab){ - fts5FreeVtab((Fts5FullTable*)pVtab); + fts5FreeVtab((Fts5Table*)pVtab); return SQLITE_OK; } /* ** The xDestroy() virtual table method. @@ -252602,11 +197924,11 @@ */ static int fts5DestroyMethod(sqlite3_vtab *pVtab){ Fts5Table *pTab = (Fts5Table*)pVtab; int rc = sqlite3Fts5DropAll(pTab->pConfig); if( rc==SQLITE_OK ){ - fts5FreeVtab((Fts5FullTable*)pVtab); + fts5FreeVtab((Fts5Table*)pVtab); } return rc; } /* @@ -252631,36 +197953,32 @@ ){ Fts5Global *pGlobal = (Fts5Global*)pAux; const char **azConfig = (const char**)argv; int rc = SQLITE_OK; /* Return code */ Fts5Config *pConfig = 0; /* Results of parsing argc/argv */ - Fts5FullTable *pTab = 0; /* New virtual table object */ + Fts5Table *pTab = 0; /* New virtual table object */ /* Allocate the new vtab object and parse the configuration */ - pTab = (Fts5FullTable*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5FullTable)); + pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table)); if( rc==SQLITE_OK ){ rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr); assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 ); } if( rc==SQLITE_OK ){ - pConfig->pzErrmsg = pzErr; - pTab->p.pConfig = pConfig; + pTab->pConfig = pConfig; pTab->pGlobal = pGlobal; - if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){ - rc = sqlite3Fts5LoadTokenizer(pConfig); - } } /* Open the index sub-system */ if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr); + rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr); } /* Open the storage sub-system */ if( rc==SQLITE_OK ){ rc = sqlite3Fts5StorageOpen( - pConfig, pTab->p.pIndex, bCreate, &pTab->pStorage, pzErr + pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr ); } /* Call sqlite3_declare_vtab() */ if( rc==SQLITE_OK ){ @@ -252667,21 +197985,17 @@ rc = sqlite3Fts5ConfigDeclareVtab(pConfig); } /* Load the initial configuration */ if( rc==SQLITE_OK ){ - rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1); + assert( pConfig->pzErrmsg==0 ); + pConfig->pzErrmsg = pzErr; + rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex); + sqlite3Fts5IndexRollback(pTab->pIndex); + pConfig->pzErrmsg = 0; } - if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ - rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - } - - if( pConfig ) pConfig->pzErrmsg = 0; if( rc!=SQLITE_OK ){ fts5FreeVtab(pTab); pTab = 0; }else if( bCreate ){ fts5CheckTransactionState(pTab, FTS5_BEGIN, 0); @@ -252739,70 +198053,29 @@ pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; } #endif } -static int fts5UsePatternMatch( - Fts5Config *pConfig, - struct sqlite3_index_constraint *p -){ - assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB ); - assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE ); - if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){ - return 1; - } - if( pConfig->t.ePattern==FTS5_PATTERN_LIKE - && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB) - ){ - return 1; - } - return 0; -} - /* -** Implementation of the xBestIndex method for FTS5 tables. Within the +** Implementation of the xBestIndex method for FTS5 tables. Within the ** WHERE constraint, it searches for the following: ** -** 1. A MATCH constraint against the table column. +** 1. A MATCH constraint against the special column. ** 2. A MATCH constraint against the "rank" column. -** 3. A MATCH constraint against some other column. -** 4. An == constraint against the rowid column. -** 5. A < or <= constraint against the rowid column. -** 6. A > or >= constraint against the rowid column. +** 3. An == constraint against the rowid column. +** 4. A < or <= constraint against the rowid column. +** 5. A > or >= constraint against the rowid column. ** -** Within the ORDER BY, the following are supported: +** Within the ORDER BY, either: ** ** 5. ORDER BY rank [ASC|DESC] ** 6. ORDER BY rowid [ASC|DESC] ** -** Information for the xFilter call is passed via both the idxNum and -** idxStr variables. Specifically, idxNum is a bitmask of the following -** flags used to encode the ORDER BY clause: -** -** FTS5_BI_ORDER_RANK -** FTS5_BI_ORDER_ROWID -** FTS5_BI_ORDER_DESC -** -** idxStr is used to encode data from the WHERE clause. For each argument -** passed to the xFilter method, the following is appended to idxStr: -** -** Match against table column: "m" -** Match against rank column: "r" -** Match against other column: "M" -** LIKE against other column: "L" -** GLOB against other column: "G" -** Equality constraint against the rowid: "=" -** A < or <= against the rowid: "<" -** A > or >= against the rowid: ">" -** -** This function ensures that there is at most one "r" or "=". And that if -** there exists an "=" then there is no "<" or ">". -** -** If an unusable MATCH operator is present in the WHERE clause, then -** SQLITE_CONSTRAINT is returned. -** ** Costs are assigned as follows: +** +** a) If an unusable MATCH operator is present in the WHERE clause, the +** cost is unconditionally set to 1e50 (a really big number). ** ** a) If a MATCH operator is present, the cost depends on the other ** constraints also present. As follows: ** ** * No other constraints: cost=1000.0 @@ -252822,116 +198095,73 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts5Table *pTab = (Fts5Table*)pVTab; Fts5Config *pConfig = pTab->pConfig; const int nCol = pConfig->nCol; int idxFlags = 0; /* Parameter passed through to xFilter() */ + int bHasMatch; + int iNext; int i; - char *idxStr; - int iIdxStr = 0; - int iCons = 0; - - int bSeenEq = 0; - int bSeenGt = 0; - int bSeenLt = 0; - int nSeenMatch = 0; - int bSeenRank = 0; - - - assert( SQLITE_INDEX_CONSTRAINT_EQbLock ){ - pTab->base.zErrMsg = sqlite3_mprintf( - "recursively defined fts5 content table" - ); - return SQLITE_ERROR; - } - - idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1); - if( idxStr==0 ) return SQLITE_NOMEM; - pInfo->idxStr = idxStr; - pInfo->needToFreeIdxStr = 1; - + struct Constraint { + int op; /* Mask against sqlite3_index_constraint.op */ + int fts5op; /* FTS5 mask for idxFlags */ + int iCol; /* 0==rowid, 1==tbl, 2==rank */ + int omit; /* True to omit this if found */ + int iConsIndex; /* Index in pInfo->aConstraint[] */ + } aConstraint[] = { + {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, + FTS5_BI_MATCH, 1, 1, -1}, + {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, + FTS5_BI_RANK, 2, 1, -1}, + {SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1}, + {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, + FTS5_BI_ROWID_LE, 0, 0, -1}, + {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, + FTS5_BI_ROWID_GE, 0, 0, -1}, + }; + + int aColMap[3]; + aColMap[0] = -1; + aColMap[1] = nCol; + aColMap[2] = nCol+1; + + /* Set idxFlags flags for all WHERE clause terms that will be used. */ for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; int iCol = p->iColumn; - if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH - || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol) + + if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol) + || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol) ){ /* A MATCH operator or equivalent */ - if( p->usable==0 || iCol<0 ){ - /* As there exists an unusable MATCH constraint this is an - ** unusable plan. Return SQLITE_CONSTRAINT. */ - idxStr[iIdxStr] = 0; - return SQLITE_CONSTRAINT; - }else{ - if( iCol==nCol+1 ){ - if( bSeenRank ) continue; - idxStr[iIdxStr++] = 'r'; - bSeenRank = 1; - }else{ - nSeenMatch++; - idxStr[iIdxStr++] = 'M'; - sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol); - idxStr += strlen(&idxStr[iIdxStr]); - assert( idxStr[iIdxStr]=='\0' ); - } - pInfo->aConstraintUsage[i].argvIndex = ++iCons; - pInfo->aConstraintUsage[i].omit = 1; - } - }else if( p->usable ){ - if( iCol>=0 && iColop==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB ); - idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G'; - sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol); - idxStr += strlen(&idxStr[iIdxStr]); - pInfo->aConstraintUsage[i].argvIndex = ++iCons; - assert( idxStr[iIdxStr]=='\0' ); - nSeenMatch++; - }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){ - idxStr[iIdxStr++] = '='; - bSeenEq = 1; - pInfo->aConstraintUsage[i].argvIndex = ++iCons; - } - } - } - - if( bSeenEq==0 ){ - for(i=0; inConstraint; i++){ - struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; - if( p->iColumn<0 && p->usable ){ - int op = p->op; - if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){ - if( bSeenLt ) continue; - idxStr[iIdxStr++] = '<'; - pInfo->aConstraintUsage[i].argvIndex = ++iCons; - bSeenLt = 1; - }else - if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){ - if( bSeenGt ) continue; - idxStr[iIdxStr++] = '>'; - pInfo->aConstraintUsage[i].argvIndex = ++iCons; - bSeenGt = 1; - } - } - } - } - idxStr[iIdxStr] = '\0'; - - /* Set idxFlags flags for the ORDER BY clause - ** - ** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC". - */ + if( p->usable ){ + idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16); + aConstraint[0].iConsIndex = i; + }else{ + /* As there exists an unusable MATCH constraint this is an + ** unusable plan. Set a prohibitively high cost. */ + pInfo->estimatedCost = 1e50; + return SQLITE_OK; + } + }else{ + int j; + for(j=1; jiCol] && p->op & pC->op && p->usable ){ + pC->iConsIndex = i; + idxFlags |= pC->fts5op; + } + } + } + } + + /* Set idxFlags flags for the ORDER BY clause */ if( pInfo->nOrderBy==1 ){ int iSort = pInfo->aOrderBy[0].iColumn; - if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){ + if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){ idxFlags |= FTS5_BI_ORDER_RANK; - }else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){ + }else if( iSort==-1 ){ idxFlags |= FTS5_BI_ORDER_ROWID; } if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){ pInfo->orderByConsumed = 1; if( pInfo->aOrderBy[0].desc ){ @@ -252939,29 +198169,37 @@ } } } /* Calculate the estimated cost based on the flags set in idxFlags. */ - if( bSeenEq ){ - pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0; - if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo); - }else if( bSeenLt && bSeenGt ){ - pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0; - }else if( bSeenLt || bSeenGt ){ - pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0; + bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH); + if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){ + pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0; + if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo); + }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ + pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0; + }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ + pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0; }else{ - pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0; + pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; } - for(i=1; iestimatedCost *= 0.4; + + /* Assign argvIndex values to each constraint in use. */ + iNext = 1; + for(i=0; iiConsIndex>=0 ){ + pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; + pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; + } } pInfo->idxNum = idxFlags; return SQLITE_OK; } -static int fts5NewTransaction(Fts5FullTable *pTab){ +static int fts5NewTransaction(Fts5Table *pTab){ Fts5Cursor *pCsr; for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){ if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK; } return sqlite3Fts5StorageReset(pTab->pStorage); @@ -252969,23 +198207,23 @@ /* ** Implementation of xOpen method. */ static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts5FullTable *pTab = (Fts5FullTable*)pVTab; - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Table *pTab = (Fts5Table*)pVTab; + Fts5Config *pConfig = pTab->pConfig; Fts5Cursor *pCsr = 0; /* New cursor object */ - sqlite3_int64 nByte; /* Bytes of space to allocate */ + int nByte; /* Bytes of space to allocate */ int rc; /* Return code */ rc = fts5NewTransaction(pTab); if( rc==SQLITE_OK ){ nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int); - pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte); + pCsr = (Fts5Cursor*)sqlite3_malloc(nByte); if( pCsr ){ Fts5Global *pGlobal = pTab->pGlobal; - memset(pCsr, 0, (size_t)nByte); + memset(pCsr, 0, nByte); pCsr->aColumnSize = (int*)&pCsr[1]; pCsr->pNext = pGlobal->pCsr; pGlobal->pCsr = pCsr; pCsr->iCsrId = ++pGlobal->iNextId; }else{ @@ -253003,24 +198241,24 @@ return FTS5_STMT_LOOKUP; } /* ** This function is called after the cursor passed as the only argument -** is moved to point at a different row. It clears all cached data +** is moved to point at a different row. It clears all cached data ** specific to the previous row stored by the cursor object. */ static void fts5CsrNewrow(Fts5Cursor *pCsr){ - CsrFlagSet(pCsr, - FTS5CSR_REQUIRE_CONTENT - | FTS5CSR_REQUIRE_DOCSIZE - | FTS5CSR_REQUIRE_INST - | FTS5CSR_REQUIRE_POSLIST + CsrFlagSet(pCsr, + FTS5CSR_REQUIRE_CONTENT + | FTS5CSR_REQUIRE_DOCSIZE + | FTS5CSR_REQUIRE_INST + | FTS5CSR_REQUIRE_POSLIST ); } static void fts5FreeCursorComponents(Fts5Cursor *pCsr){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); Fts5Auxdata *pData; Fts5Auxdata *pNext; sqlite3_free(pCsr->aInstIter); sqlite3_free(pCsr->aInst); @@ -253050,11 +198288,10 @@ if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){ sqlite3_free(pCsr->zRank); sqlite3_free(pCsr->zRankArgs); } - sqlite3Fts5IndexCloseReader(pTab->p.pIndex); memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr)); } /* @@ -253061,11 +198298,11 @@ ** Close the cursor. For additional information see the documentation ** on the xClose method of the virtual table interface. */ static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){ if( pCursor ){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab); + Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; Fts5Cursor **pp; fts5FreeCursorComponents(pCsr); /* Remove the cursor from the Fts5Global.pCsr list */ @@ -253082,11 +198319,11 @@ int rc; rc = sqlite3_step(pSorter->pStmt); if( rc==SQLITE_DONE ){ rc = SQLITE_OK; - CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT); + CsrFlagSet(pCsr, FTS5CSR_EOF); }else if( rc==SQLITE_ROW ){ const u8 *a; const u8 *aBlob; int nBlob; int i; @@ -253115,45 +198352,45 @@ return rc; } /* -** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors +** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors ** open on table pTab. */ -static void fts5TripCursors(Fts5FullTable *pTab){ +static void fts5TripCursors(Fts5Table *pTab){ Fts5Cursor *pCsr; for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){ if( pCsr->ePlan==FTS5_PLAN_MATCH - && pCsr->base.pVtab==(sqlite3_vtab*)pTab + && pCsr->base.pVtab==(sqlite3_vtab*)pTab ){ CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK); } } } /* ** If the REQUIRE_RESEEK flag is set on the cursor passed as the first -** argument, close and reopen all Fts5IndexIter iterators that the cursor +** argument, close and reopen all Fts5IndexIter iterators that the cursor ** is using. Then attempt to move the cursor to a rowid equal to or laster -** (in the cursors sort order - ASC or DESC) than the current rowid. +** (in the cursors sort order - ASC or DESC) than the current rowid. ** ** If the new rowid is not equal to the old, set output parameter *pbSkip ** to 1 before returning. Otherwise, leave it unchanged. ** -** Return SQLITE_OK if successful or if no reseek was required, or an +** Return SQLITE_OK if successful or if no reseek was required, or an ** error code if an error occurred. */ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ int rc = SQLITE_OK; assert( *pbSkip==0 ); if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); int bDesc = pCsr->bDesc; i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); - rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc); + rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ *pbSkip = 1; } CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); @@ -253166,11 +198403,11 @@ return rc; } /* -** Advance the cursor to the next row in the table that matches the +** Advance the cursor to the next row in the table that matches the ** search criteria. ** ** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned ** even if we reach end-of-file. The fts5EofMethod() will be called ** subsequently to determine whether or not an EOF was hit. @@ -253178,24 +198415,14 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; int rc; assert( (pCsr->ePlan<3)== - (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) + (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) ); assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); - /* If this cursor uses FTS5_PLAN_MATCH and this is a tokendata=1 table, - ** clear any token mappings accumulated at the fts5_index.c level. In - ** other cases, specifically FTS5_PLAN_SOURCE and FTS5_PLAN_SORTED_MATCH, - ** we need to retain the mappings for the entire query. */ - if( pCsr->ePlan==FTS5_PLAN_MATCH - && ((Fts5Table*)pCursor->pVtab)->pConfig->bTokendata - ){ - sqlite3Fts5ExprClearTokens(pCsr->pExpr); - } - if( pCsr->ePlan<3 ){ int bSkip = 0; if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr)); @@ -253205,45 +198432,35 @@ case FTS5_PLAN_SPECIAL: { CsrFlagSet(pCsr, FTS5CSR_EOF); rc = SQLITE_OK; break; } - + case FTS5_PLAN_SORTED_MATCH: { rc = fts5SorterNext(pCsr); break; } - - default: { - Fts5Config *pConfig = ((Fts5Table*)pCursor->pVtab)->pConfig; - pConfig->bLock++; + + default: rc = sqlite3_step(pCsr->pStmt); - pConfig->bLock--; if( rc!=SQLITE_ROW ){ CsrFlagSet(pCsr, FTS5CSR_EOF); rc = sqlite3_reset(pCsr->pStmt); - if( rc!=SQLITE_OK ){ - pCursor->pVtab->zErrMsg = sqlite3_mprintf( - "%s", sqlite3_errmsg(pConfig->db) - ); - } }else{ rc = SQLITE_OK; - CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE); } break; - } } } - + return rc; } static int fts5PrepareStatement( sqlite3_stmt **ppStmt, - Fts5Config *pConfig, + Fts5Config *pConfig, const char *zFmt, ... ){ sqlite3_stmt *pRet = 0; int rc; @@ -253251,54 +198468,50 @@ va_list ap; va_start(ap, zFmt); zSql = sqlite3_vmprintf(zFmt, ap); if( zSql==0 ){ - rc = SQLITE_NOMEM; + rc = SQLITE_NOMEM; }else{ - rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, + rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, SQLITE_PREPARE_PERSISTENT, &pRet, 0); if( rc!=SQLITE_OK ){ - sqlite3Fts5ConfigErrmsg(pConfig, "%s", sqlite3_errmsg(pConfig->db)); + *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db)); } sqlite3_free(zSql); } va_end(ap); *ppStmt = pRet; return rc; -} - -static int fts5CursorFirstSorted( - Fts5FullTable *pTab, - Fts5Cursor *pCsr, - int bDesc -){ - Fts5Config *pConfig = pTab->p.pConfig; +} + +static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ + Fts5Config *pConfig = pTab->pConfig; Fts5Sorter *pSorter; int nPhrase; - sqlite3_int64 nByte; + int nByte; int rc; const char *zRank = pCsr->zRank; const char *zRankArgs = pCsr->zRankArgs; - + nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1); - pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte); + pSorter = (Fts5Sorter*)sqlite3_malloc(nByte); if( pSorter==0 ) return SQLITE_NOMEM; - memset(pSorter, 0, (size_t)nByte); + memset(pSorter, 0, nByte); pSorter->nIdx = nPhrase; /* TODO: It would be better to have some system for reusing statement ** handles here, rather than preparing a new one for each query. But that ** is not possible as SQLite reference counts the virtual table objects. - ** And since the statement required here reads from this very virtual + ** And since the statement required here reads from this very virtual ** table, saving it creates a circular reference. ** ** If SQLite a built-in statement cache, this wouldn't be a problem. */ rc = fts5PrepareStatement(&pSorter->pStmt, pConfig, - "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s", + "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", pConfig->zDb, pConfig->zName, zRank, pConfig->zName, (zRankArgs ? ", " : ""), (zRankArgs ? zRankArgs : ""), bDesc ? "DESC" : "ASC" ); @@ -253318,14 +198531,14 @@ } return rc; } -static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){ +static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ int rc; Fts5Expr *pExpr = pCsr->pExpr; - rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc); + rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc); if( sqlite3Fts5ExprEof(pExpr) ){ CsrFlagSet(pCsr, FTS5CSR_EOF); } fts5CsrNewrow(pCsr); return rc; @@ -253336,33 +198549,33 @@ ** MATCH expression that begins with a '*' character. The remainder of ** the text passed to the MATCH operator are used as the special query ** parameters. */ static int fts5SpecialMatch( - Fts5FullTable *pTab, - Fts5Cursor *pCsr, + Fts5Table *pTab, + Fts5Cursor *pCsr, const char *zQuery ){ int rc = SQLITE_OK; /* Return code */ const char *z = zQuery; /* Special query text */ int n; /* Number of bytes in text at z */ while( z[0]==' ' ) z++; for(n=0; z[n] && z[n]!=' '; n++); - assert( pTab->p.base.zErrMsg==0 ); + assert( pTab->base.zErrMsg==0 ); pCsr->ePlan = FTS5_PLAN_SPECIAL; - if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){ - pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex); + if( 0==sqlite3_strnicmp("reads", z, n) ){ + pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex); } - else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){ + else if( 0==sqlite3_strnicmp("id", z, n) ){ pCsr->iSpecial = pCsr->iCsrId; } else{ /* An unrecognized directive. Return an error message. */ - pTab->p.base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z); + pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z); rc = SQLITE_ERROR; } return rc; } @@ -253370,11 +198583,11 @@ /* ** Search for an auxiliary function named zName that can be used with table ** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary ** structure. Otherwise, if no such function exists, return NULL. */ -static Fts5Auxiliary *fts5FindAuxiliary(Fts5FullTable *pTab, const char *zName){ +static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){ Fts5Auxiliary *pAux; for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){ if( sqlite3_stricmp(zName, pAux->zFunc)==0 ) return pAux; } @@ -253383,12 +198596,12 @@ return 0; } static int fts5FindRankFunction(Fts5Cursor *pCsr){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + Fts5Config *pConfig = pTab->pConfig; int rc = SQLITE_OK; Fts5Auxiliary *pAux = 0; const char *zRank = pCsr->zRank; const char *zRankArgs = pCsr->zRankArgs; @@ -253400,11 +198613,11 @@ SQLITE_PREPARE_PERSISTENT, &pStmt, 0); sqlite3_free(zSql); assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 ); if( rc==SQLITE_OK ){ if( SQLITE_ROW==sqlite3_step(pStmt) ){ - sqlite3_int64 nByte; + int nByte; pCsr->nRankArg = sqlite3_column_count(pStmt); nByte = sizeof(sqlite3_value*)*pCsr->nRankArg; pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte); if( rc==SQLITE_OK ){ int i; @@ -253422,12 +198635,12 @@ } if( rc==SQLITE_OK ){ pAux = fts5FindAuxiliary(pTab, zRank); if( pAux==0 ){ - assert( pTab->p.base.zErrMsg==0 ); - pTab->p.base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank); + assert( pTab->base.zErrMsg==0 ); + pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank); rc = SQLITE_ERROR; } } pCsr->pRank = pAux; @@ -253435,11 +198648,11 @@ } static int fts5CursorParseRank( Fts5Config *pConfig, - Fts5Cursor *pCsr, + Fts5Cursor *pCsr, sqlite3_value *pRank ){ int rc = SQLITE_OK; if( pRank ){ const char *z = (const char*)sqlite3_value_text(pRank); @@ -253479,186 +198692,47 @@ return sqlite3_value_int64(pVal); } } return iDefault; } - -/* -** Set the error message on the virtual table passed as the first argument. -*/ -static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){ - va_list ap; /* ... printf arguments */ - va_start(ap, zFormat); - sqlite3_free(p->p.base.zErrMsg); - p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap); - va_end(ap); -} - -/* -** Arrange for subsequent calls to sqlite3Fts5Tokenize() to use the locale -** specified by pLocale/nLocale. The buffer indicated by pLocale must remain -** valid until after the final call to sqlite3Fts5Tokenize() that will use -** the locale. -*/ -static void sqlite3Fts5SetLocale( - Fts5Config *pConfig, - const char *zLocale, - int nLocale -){ - Fts5TokenizerConfig *pT = &pConfig->t; - pT->pLocale = zLocale; - pT->nLocale = nLocale; -} - -/* -** Clear any locale configured by an earlier call to sqlite3Fts5SetLocale(). -*/ -static void sqlite3Fts5ClearLocale(Fts5Config *pConfig){ - sqlite3Fts5SetLocale(pConfig, 0, 0); -} - -/* -** Return true if the value passed as the only argument is an -** fts5_locale() value. -*/ -static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal){ - int ret = 0; - if( sqlite3_value_type(pVal)==SQLITE_BLOB ){ - /* Call sqlite3_value_bytes() after sqlite3_value_blob() in this case. - ** If the blob was created using zeroblob(), then sqlite3_value_blob() - ** may call malloc(). If this malloc() fails, then the values returned - ** by both value_blob() and value_bytes() will be 0. If value_bytes() were - ** called first, then the NULL pointer returned by value_blob() might - ** be dereferenced. */ - const u8 *pBlob = sqlite3_value_blob(pVal); - int nBlob = sqlite3_value_bytes(pVal); - if( nBlob>FTS5_LOCALE_HDR_SIZE - && 0==memcmp(pBlob, FTS5_LOCALE_HDR(pConfig), FTS5_LOCALE_HDR_SIZE) - ){ - ret = 1; - } - } - return ret; -} - -/* -** Value pVal is guaranteed to be an fts5_locale() value, according to -** sqlite3Fts5IsLocaleValue(). This function extracts the text and locale -** from the value and returns them separately. -** -** If successful, SQLITE_OK is returned and (*ppText) and (*ppLoc) set -** to point to buffers containing the text and locale, as utf-8, -** respectively. In this case output parameters (*pnText) and (*pnLoc) are -** set to the sizes in bytes of these two buffers. -** -** Or, if an error occurs, then an SQLite error code is returned. The final -** value of the four output parameters is undefined in this case. -*/ -static int sqlite3Fts5DecodeLocaleValue( - sqlite3_value *pVal, - const char **ppText, - int *pnText, - const char **ppLoc, - int *pnLoc -){ - const char *p = sqlite3_value_blob(pVal); - int n = sqlite3_value_bytes(pVal); - int nLoc = 0; - - assert( sqlite3_value_type(pVal)==SQLITE_BLOB ); - assert( n>FTS5_LOCALE_HDR_SIZE ); - - for(nLoc=FTS5_LOCALE_HDR_SIZE; p[nLoc]; nLoc++){ - if( nLoc==(n-1) ){ - return SQLITE_MISMATCH; - } - } - *ppLoc = &p[FTS5_LOCALE_HDR_SIZE]; - *pnLoc = nLoc - FTS5_LOCALE_HDR_SIZE; - - *ppText = &p[nLoc+1]; - *pnText = n - nLoc - 1; - return SQLITE_OK; -} - -/* -** Argument pVal is the text of a full-text search expression. It may or -** may not have been wrapped by fts5_locale(). This function extracts -** the text of the expression, and sets output variable (*pzText) to -** point to a nul-terminated buffer containing the expression. -** -** If pVal was an fts5_locale() value, then sqlite3Fts5SetLocale() is called -** to set the tokenizer to use the specified locale. -** -** If output variable (*pbFreeAndReset) is set to true, then the caller -** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer -** locale, and (b) call sqlite3_free() to free (*pzText). -*/ -static int fts5ExtractExprText( - Fts5Config *pConfig, /* Fts5 configuration */ - sqlite3_value *pVal, /* Value to extract expression text from */ - char **pzText, /* OUT: nul-terminated buffer of text */ - int *pbFreeAndReset /* OUT: Free (*pzText) and clear locale */ -){ - int rc = SQLITE_OK; - - if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ - const char *pText = 0; - int nText = 0; - const char *pLoc = 0; - int nLoc = 0; - rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); - *pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, pText); - if( rc==SQLITE_OK ){ - sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); - } - *pbFreeAndReset = 1; - }else{ - *pzText = (char*)sqlite3_value_text(pVal); - *pbFreeAndReset = 0; - } - - return rc; -} - /* ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. -** +** ** There are three possible query strategies: ** ** 1. Full-text search using a MATCH operator. ** 2. A by-rowid lookup. ** 3. A full-table scan. */ static int fts5FilterMethod( sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ + const char *zUnused, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab); - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); + Fts5Config *pConfig = pTab->pConfig; Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; int rc = SQLITE_OK; /* Error code */ + int iVal = 0; /* Counter for apVal[] */ int bDesc; /* True if ORDER BY [rank|rowid] DESC */ int bOrderByRank; /* True if ORDER BY rank */ + sqlite3_value *pMatch = 0; /* MATCH ? expression (or NULL) */ sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */ sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */ sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */ sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ int iCol; /* Column on LHS of MATCH operator */ char **pzErrmsg = pConfig->pzErrmsg; - int bPrefixInsttoken = pConfig->bPrefixInsttoken; - int i; - int iIdxStr = 0; - Fts5Expr *pExpr = 0; - assert( pConfig->bLock==0 ); + UNUSED_PARAM(zUnused); + UNUSED_PARAM(nVal); + if( pCsr->ePlan ){ fts5FreeCursorComponents(pCsr); memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr)); } @@ -253666,97 +198740,31 @@ assert( pCsr->pExpr==0 ); assert( pCsr->csrflags==0 ); assert( pCsr->pRank==0 ); assert( pCsr->zRank==0 ); assert( pCsr->zRankArgs==0 ); - assert( pTab->pSortCsr==0 || nVal==0 ); - - assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg ); - pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - - /* Decode the arguments passed through to this function. */ - for(i=0; ibPrefixInsttoken = 1; - } - - iCol = 0; - do{ - iCol = iCol*10 + (idxStr[iIdxStr]-'0'); - iIdxStr++; - }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ); - - if( zText[0]=='*' ){ - /* The user has issued a query of the form "MATCH '*...'". This - ** indicates that the MATCH expression is not a full text query, - ** but a request for an internal parameter. */ - rc = fts5SpecialMatch(pTab, pCsr, &zText[1]); - bInternal = 1; - }else{ - char **pzErr = &pTab->p.base.zErrMsg; - rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr); - pExpr = 0; - } - } - - if( bFreeAndReset ){ - sqlite3_free(zText); - sqlite3Fts5ClearLocale(pConfig); - } - - if( bInternal || rc!=SQLITE_OK ) goto filter_out; - - break; - } - case 'L': - case 'G': { - int bGlob = (idxStr[iIdxStr-1]=='G'); - const char *zText = (const char*)sqlite3_value_text(apVal[i]); - iCol = 0; - do{ - iCol = iCol*10 + (idxStr[iIdxStr]-'0'); - iIdxStr++; - }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ); - if( zText ){ - rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr); - pExpr = 0; - } - if( rc!=SQLITE_OK ) goto filter_out; - break; - } - case '=': - pRowidEq = apVal[i]; - break; - case '<': - pRowidLe = apVal[i]; - break; - default: assert( idxStr[iIdxStr-1]=='>' ); - pRowidGe = apVal[i]; - break; - } - } + + assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg ); + pConfig->pzErrmsg = &pTab->base.zErrMsg; + + /* Decode the arguments passed through to this function. + ** + ** Note: The following set of if(...) statements must be in the same + ** order as the corresponding entries in the struct at the top of + ** fts5BestIndexMethod(). */ + if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++]; + iCol = (idxNum>>16); + assert( iCol>=0 && iCol<=pConfig->nCol ); + assert( iVal==nVal ); bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0); pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0); - /* Set the cursor upper and lower rowid limits. Only some strategies + /* Set the cursor upper and lower rowid limits. Only some strategies ** actually use them. This is ok, as the xBestIndex() method leaves the ** sqlite3_index_constraint.omit flag clear for range constraints ** on the rowid field. */ if( pRowidEq ){ pRowidLe = pRowidGe = pRowidEq; @@ -253767,77 +198775,78 @@ }else{ pCsr->iLastRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64); pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64); } - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); - if( rc!=SQLITE_OK ) goto filter_out; - if( pTab->pSortCsr ){ - /* If pSortCsr is non-NULL, then this call is being made as part of + /* If pSortCsr is non-NULL, then this call is being made as part of ** processing for a "... MATCH ORDER BY rank" query (ePlan is ** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will - ** return results to the user for this query. The current cursor - ** (pCursor) is used to execute the query issued by function + ** return results to the user for this query. The current cursor + ** (pCursor) is used to execute the query issued by function ** fts5CursorFirstSorted() above. */ assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 ); - assert( nVal==0 && bOrderByRank==0 && bDesc==0 ); + assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 ); assert( pCsr->iLastRowid==LARGEST_INT64 ); assert( pCsr->iFirstRowid==SMALLEST_INT64 ); - if( pTab->pSortCsr->bDesc ){ - pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid; - pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid; - }else{ - pCsr->iLastRowid = pTab->pSortCsr->iLastRowid; - pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid; - } pCsr->ePlan = FTS5_PLAN_SOURCE; pCsr->pExpr = pTab->pSortCsr->pExpr; rc = fts5CursorFirst(pTab, pCsr, bDesc); - }else if( pCsr->pExpr ){ - assert( rc==SQLITE_OK ); + }else if( pMatch ){ + const char *zExpr = (const char*)sqlite3_value_text(apVal[0]); + if( zExpr==0 ) zExpr = ""; + rc = fts5CursorParseRank(pConfig, pCsr, pRank); if( rc==SQLITE_OK ){ - if( bOrderByRank ){ - pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; - rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); + if( zExpr[0]=='*' ){ + /* The user has issued a query of the form "MATCH '*...'". This + ** indicates that the MATCH expression is not a full text query, + ** but a request for an internal parameter. */ + rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]); }else{ - pCsr->ePlan = FTS5_PLAN_MATCH; - rc = fts5CursorFirst(pTab, pCsr, bDesc); + char **pzErr = &pTab->base.zErrMsg; + rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr); + if( rc==SQLITE_OK ){ + if( bOrderByRank ){ + pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; + rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); + }else{ + pCsr->ePlan = FTS5_PLAN_MATCH; + rc = fts5CursorFirst(pTab, pCsr, bDesc); + } + } } } }else if( pConfig->zContent==0 ){ - fts5SetVtabError(pTab,"%s: table does not support scanning",pConfig->zName); + *pConfig->pzErrmsg = sqlite3_mprintf( + "%s: table does not support scanning", pConfig->zName + ); rc = SQLITE_ERROR; }else{ /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup ** by rowid (ePlan==FTS5_PLAN_ROWID). */ pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN); rc = sqlite3Fts5StorageStmt( - pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg + pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg ); if( rc==SQLITE_OK ){ - if( pRowidEq!=0 ){ - assert( pCsr->ePlan==FTS5_PLAN_ROWID ); - sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq); + if( pCsr->ePlan==FTS5_PLAN_ROWID ){ + sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); }else{ sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid); sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid); } rc = fts5NextMethod(pCursor); } } - filter_out: - sqlite3Fts5ExprFree(pExpr); pConfig->pzErrmsg = pzErrmsg; - pConfig->bPrefixInsttoken = bPrefixInsttoken; return rc; } -/* -** This is the xEof method of the virtual table. SQLite calls this +/* +** This is the xEof method of the virtual table. SQLite calls this ** routine to find out if it has reached the end of a result set. */ static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){ Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0); @@ -253845,45 +198854,50 @@ /* ** Return the rowid that the cursor currently points to. */ static i64 fts5CursorRowid(Fts5Cursor *pCsr){ - assert( pCsr->ePlan==FTS5_PLAN_MATCH - || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH - || pCsr->ePlan==FTS5_PLAN_SOURCE - || pCsr->ePlan==FTS5_PLAN_SCAN - || pCsr->ePlan==FTS5_PLAN_ROWID + assert( pCsr->ePlan==FTS5_PLAN_MATCH + || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH + || pCsr->ePlan==FTS5_PLAN_SOURCE ); if( pCsr->pSorter ){ return pCsr->pSorter->iRowid; - }else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){ - return sqlite3_column_int64(pCsr->pStmt, 0); }else{ return sqlite3Fts5ExprRowid(pCsr->pExpr); } } -/* +/* ** This is the xRowid method. The SQLite core calls this routine to ** retrieve the rowid for the current row of the result set. fts5 ** exposes %_content.rowid as the rowid for the virtual table. The ** rowid should be written to *pRowid. */ static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; int ePlan = pCsr->ePlan; - + assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 ); - if( ePlan==FTS5_PLAN_SPECIAL ){ - *pRowid = 0; - }else{ - *pRowid = fts5CursorRowid(pCsr); + switch( ePlan ){ + case FTS5_PLAN_SPECIAL: + *pRowid = 0; + break; + + case FTS5_PLAN_SOURCE: + case FTS5_PLAN_MATCH: + case FTS5_PLAN_SORTED_MATCH: + *pRowid = fts5CursorRowid(pCsr); + break; + + default: + *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); + break; } return SQLITE_OK; } - /* ** If the cursor requires seeking (bSeekRequired flag is set), seek it. ** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise. ** @@ -253891,233 +198905,153 @@ ** be left in sqlite3_vtab.zErrMsg. */ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){ int rc = SQLITE_OK; - /* If the cursor does not yet have a statement handle, obtain one now. */ + /* If the cursor does not yet have a statement handle, obtain one now. */ if( pCsr->pStmt==0 ){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); int eStmt = fts5StmtType(pCsr); rc = sqlite3Fts5StorageStmt( - pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0) + pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0) ); - assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 ); + assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 ); assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ); } if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){ - Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); assert( pCsr->pExpr ); sqlite3_reset(pCsr->pStmt); sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr)); - pTab->pConfig->bLock++; rc = sqlite3_step(pCsr->pStmt); - pTab->pConfig->bLock--; if( rc==SQLITE_ROW ){ rc = SQLITE_OK; CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT); }else{ rc = sqlite3_reset(pCsr->pStmt); if( rc==SQLITE_OK ){ rc = FTS5_CORRUPT; - fts5SetVtabError((Fts5FullTable*)pTab, - "fts5: missing row %lld from content table %s", - fts5CursorRowid(pCsr), - pTab->pConfig->zContent - ); - }else if( pTab->pConfig->pzErrmsg ){ - fts5SetVtabError((Fts5FullTable*)pTab, - "%s", sqlite3_errmsg(pTab->pConfig->db) - ); } } } return rc; } + +static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){ + va_list ap; /* ... printf arguments */ + va_start(ap, zFormat); + assert( p->base.zErrMsg==0 ); + p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap); + va_end(ap); +} /* ** This function is called to handle an FTS INSERT command. In other words, ** an INSERT statement of the form: ** ** INSERT INTO fts(fts) VALUES($pCmd) ** INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal) ** -** Argument pVal is the value assigned to column "fts" by the INSERT +** Argument pVal is the value assigned to column "fts" by the INSERT ** statement. This function returns SQLITE_OK if successful, or an SQLite ** error code if an error occurs. ** ** The commands implemented by this function are documented in the "Special ** INSERT Directives" section of the documentation. It should be updated if ** more commands are added to this function. */ static int fts5SpecialInsert( - Fts5FullTable *pTab, /* Fts5 table object */ + Fts5Table *pTab, /* Fts5 table object */ const char *zCmd, /* Text inserted into table-name column */ sqlite3_value *pVal /* Value inserted into rank column */ ){ - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Config *pConfig = pTab->pConfig; int rc = SQLITE_OK; int bError = 0; - int bLoadConfig = 0; if( 0==sqlite3_stricmp("delete-all", zCmd) ){ if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ - fts5SetVtabError(pTab, + fts5SetVtabError(pTab, "'delete-all' may only be used with a " "contentless or external content fts5 table" ); rc = SQLITE_ERROR; }else{ rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage); } - bLoadConfig = 1; }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){ - if( fts5IsContentless(pTab, 1) ){ - fts5SetVtabError(pTab, + if( pConfig->eContent==FTS5_CONTENT_NONE ){ + fts5SetVtabError(pTab, "'rebuild' may not be used with a contentless fts5 table" ); rc = SQLITE_ERROR; }else{ rc = sqlite3Fts5StorageRebuild(pTab->pStorage); } - bLoadConfig = 1; }else if( 0==sqlite3_stricmp("optimize", zCmd) ){ rc = sqlite3Fts5StorageOptimize(pTab->pStorage); }else if( 0==sqlite3_stricmp("merge", zCmd) ){ int nMerge = sqlite3_value_int(pVal); rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge); }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){ - int iArg = sqlite3_value_int(pVal); - rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg); + rc = sqlite3Fts5StorageIntegrity(pTab->pStorage); #ifdef SQLITE_DEBUG }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){ pConfig->bPrefixIndex = sqlite3_value_int(pVal); #endif - }else if( 0==sqlite3_stricmp("flush", zCmd) ){ - rc = sqlite3Fts5FlushToDisk(&pTab->p); - }else{ - rc = sqlite3Fts5FlushToDisk(&pTab->p); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError); + }else{ + rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError); } if( rc==SQLITE_OK ){ if( bError ){ rc = SQLITE_ERROR; }else{ rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0); } } } - - if( rc==SQLITE_OK && bLoadConfig ){ - pTab->p.pConfig->iCookie--; - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); - } - return rc; } static int fts5SpecialDelete( - Fts5FullTable *pTab, + Fts5Table *pTab, sqlite3_value **apVal ){ int rc = SQLITE_OK; int eType1 = sqlite3_value_type(apVal[1]); if( eType1==SQLITE_INTEGER ){ sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]); - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2], 0); + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]); } return rc; } static void fts5StorageInsert( - int *pRc, - Fts5FullTable *pTab, - sqlite3_value **apVal, + int *pRc, + Fts5Table *pTab, + sqlite3_value **apVal, i64 *piRowid ){ int rc = *pRc; if( rc==SQLITE_OK ){ - rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, 0, apVal, piRowid); + rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid); } if( rc==SQLITE_OK ){ rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid); } *pRc = rc; } -/* -** -** This function is called when the user attempts an UPDATE on a contentless -** table. Parameter bRowidModified is true if the UPDATE statement modifies -** the rowid value. Parameter apVal[] contains the new values for each user -** defined column of the fts5 table. pConfig is the configuration object of the -** table being updated (guaranteed to be contentless). The contentless_delete=1 -** and contentless_unindexed=1 options may or may not be set. -** -** This function returns SQLITE_OK if the UPDATE can go ahead, or an SQLite -** error code if it cannot. In this case an error message is also loaded into -** pConfig. Output parameter (*pbContent) is set to true if the caller should -** update the %_content table only - not the FTS index or any other shadow -** table. This occurs when an UPDATE modifies only UNINDEXED columns of the -** table. -** -** An UPDATE may proceed if: -** -** * The only columns modified are UNINDEXED columns, or -** -** * The contentless_delete=1 option was specified and all of the indexed -** columns (not a subset) have been modified. -*/ -static int fts5ContentlessUpdate( - Fts5Config *pConfig, - sqlite3_value **apVal, - int bRowidModified, - int *pbContent -){ - int ii; - int bSeenIndex = 0; /* Have seen modified indexed column */ - int bSeenIndexNC = 0; /* Have seen unmodified indexed column */ - int rc = SQLITE_OK; - - for(ii=0; iinCol; ii++){ - if( pConfig->abUnindexed[ii]==0 ){ - if( sqlite3_value_nochange(apVal[ii]) ){ - bSeenIndexNC++; - }else{ - bSeenIndex++; - } - } - } - - if( bSeenIndex==0 && bRowidModified==0 ){ - *pbContent = 1; - }else{ - if( bSeenIndexNC || pConfig->bContentlessDelete==0 ){ - rc = SQLITE_ERROR; - sqlite3Fts5ConfigErrmsg(pConfig, - (pConfig->bContentlessDelete ? - "%s a subset of columns on fts5 contentless-delete table: %s" : - "%s contentless fts5 table: %s") - , "cannot UPDATE", pConfig->zName - ); - } - } - - return rc; -} - -/* -** This function is the implementation of the xUpdate callback used by +/* +** This function is the implementation of the xUpdate callback used by ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be ** inserted, updated or deleted. ** ** A delete specifies a single argument - the rowid of the row to remove. -** +** ** Update and insert operations pass: ** ** 1. The "old" rowid, or NULL. ** 2. The "new" rowid. ** 3. Values for each of the nCol matchable columns. @@ -254127,57 +199061,46 @@ sqlite3_vtab *pVtab, /* Virtual table handle */ int nArg, /* Size of argument array */ sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Table *pTab = (Fts5Table*)pVtab; + Fts5Config *pConfig = pTab->pConfig; int eType0; /* value_type() of apVal[0] */ int rc = SQLITE_OK; /* Return code */ /* A transaction must be open when this is called. */ - assert( pTab->ts.eState==1 || pTab->ts.eState==2 ); + assert( pTab->ts.eState==1 ); assert( pVtab->zErrMsg==0 ); assert( nArg==1 || nArg==(2+pConfig->nCol+2) ); - assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER - || sqlite3_value_type(apVal[0])==SQLITE_NULL + assert( nArg==1 + || sqlite3_value_type(apVal[1])==SQLITE_INTEGER + || sqlite3_value_type(apVal[1])==SQLITE_NULL ); - assert( pTab->p.pConfig->pzErrmsg==0 ); - if( pConfig->pgsz==0 ){ - rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie); - if( rc!=SQLITE_OK ) return rc; - } - - pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; + assert( pTab->pConfig->pzErrmsg==0 ); + pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg; /* Put any active cursors into REQUIRE_SEEK state. */ fts5TripCursors(pTab); eType0 = sqlite3_value_type(apVal[0]); - if( eType0==SQLITE_NULL - && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL + if( eType0==SQLITE_NULL + && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL ){ /* A "special" INSERT op. These are handled separately. */ const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]); - if( pConfig->eContent!=FTS5_CONTENT_NORMAL - && 0==sqlite3_stricmp("delete", z) + if( pConfig->eContent!=FTS5_CONTENT_NORMAL + && 0==sqlite3_stricmp("delete", z) ){ - if( pConfig->bContentlessDelete ){ - fts5SetVtabError(pTab, - "'delete' may not be used with a contentless_delete=1 table" - ); - rc = SQLITE_ERROR; - }else{ - rc = fts5SpecialDelete(pTab, apVal); - } + rc = fts5SpecialDelete(pTab, apVal); }else{ rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); } }else{ /* A regular INSERT, UPDATE or DELETE statement. The trick here is that - ** any conflict on the rowid value must be detected before any + ** any conflict on the rowid value must be detected before any ** modifications are made to the database file. There are 4 cases: ** ** 1) DELETE ** 2) UPDATE (rowid not modified) ** 3) UPDATE (rowid modified) @@ -254184,164 +199107,119 @@ ** 4) INSERT ** ** Cases 3 and 4 may violate the rowid constraint. */ int eConflict = SQLITE_ABORT; - if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->bContentlessDelete ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ eConflict = sqlite3_vtab_on_conflict(pConfig->db); } assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL ); assert( nArg!=1 || eType0==SQLITE_INTEGER ); - /* DELETE */ - if( nArg==1 ){ - /* It is only possible to DELETE from a contentless table if the - ** contentless_delete=1 flag is set. */ - if( fts5IsContentless(pTab, 1) && pConfig->bContentlessDelete==0 ){ - fts5SetVtabError(pTab, - "cannot DELETE from contentless fts5 table: %s", pConfig->zName - ); - rc = SQLITE_ERROR; - }else{ - i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0); - } - } - - /* INSERT or UPDATE */ - else{ - int eType1 = sqlite3_value_numeric_type(apVal[1]); - - /* It is an error to write an fts5_locale() value to a table without - ** the locale=1 option. */ - if( pConfig->bLocale==0 ){ - int ii; - for(ii=0; iinCol; ii++){ - sqlite3_value *pVal = apVal[ii+2]; - if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ - fts5SetVtabError(pTab, "fts5_locale() requires locale=1"); - rc = SQLITE_MISMATCH; - goto update_out; - } - } - } - - if( eType0!=SQLITE_INTEGER ){ - /* An INSERT statement. If the conflict-mode is REPLACE, first remove - ** the current entry (if any). */ - if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){ - i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ - rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0); - } - fts5StorageInsert(&rc, pTab, apVal, pRowid); - } - - /* UPDATE */ - else{ - Fts5Storage *pStorage = pTab->pStorage; - i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ - i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ - int bContent = 0; /* Content only update */ - - /* If this is a contentless table (including contentless_unindexed=1 - ** tables), check if the UPDATE may proceed. */ - if( fts5IsContentless(pTab, 1) ){ - rc = fts5ContentlessUpdate(pConfig, &apVal[2], iOld!=iNew, &bContent); - if( rc!=SQLITE_OK ) goto update_out; - } - - if( eType1!=SQLITE_INTEGER ){ - rc = SQLITE_MISMATCH; - }else if( iOld!=iNew ){ - assert( bContent==0 ); - if( eConflict==SQLITE_REPLACE ){ - rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5StorageDelete(pStorage, iNew, 0, 0); - } - fts5StorageInsert(&rc, pTab, apVal, pRowid); - }else{ - rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5StorageContentInsert(pStorage, 0, apVal, pRowid); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5StorageIndexInsert(pStorage, apVal, *pRowid); - } - } - }else if( bContent ){ - /* This occurs when an UPDATE on a contentless table affects *only* - ** UNINDEXED columns. This is a no-op for contentless_unindexed=0 - ** tables, or a write to the %_content table only for =1 tables. */ - assert( fts5IsContentless(pTab, 1) ); - rc = sqlite3Fts5StorageFindDeleteRow(pStorage, iOld); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid); - } - }else{ - rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1); - fts5StorageInsert(&rc, pTab, apVal, pRowid); - } - sqlite3Fts5StorageReleaseDeleteRow(pStorage); - } - } - } - - update_out: - pTab->p.pConfig->pzErrmsg = 0; - return rc; -} - -/* -** Implementation of xSync() method. + /* Filter out attempts to run UPDATE or DELETE on contentless tables. + ** This is not suported. */ + if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){ + pTab->base.zErrMsg = sqlite3_mprintf( + "cannot %s contentless fts5 table: %s", + (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName + ); + rc = SQLITE_ERROR; + } + + /* DELETE */ + else if( nArg==1 ){ + i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0); + } + + /* INSERT */ + else if( eType0!=SQLITE_INTEGER ){ + /* If this is a REPLACE, first remove the current entry (if any) */ + if( eConflict==SQLITE_REPLACE + && sqlite3_value_type(apVal[1])==SQLITE_INTEGER + ){ + i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0); + } + fts5StorageInsert(&rc, pTab, apVal, pRowid); + } + + /* UPDATE */ + else{ + i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ + i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ + if( iOld!=iNew ){ + if( eConflict==SQLITE_REPLACE ){ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0); + } + fts5StorageInsert(&rc, pTab, apVal, pRowid); + }else{ + rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid); + } + } + }else{ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); + fts5StorageInsert(&rc, pTab, apVal, pRowid); + } + } + } + + pTab->pConfig->pzErrmsg = 0; + return rc; +} + +/* +** Implementation of xSync() method. */ static int fts5SyncMethod(sqlite3_vtab *pVtab){ int rc; - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + Fts5Table *pTab = (Fts5Table*)pVtab; fts5CheckTransactionState(pTab, FTS5_SYNC, 0); - pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - rc = sqlite3Fts5FlushToDisk(&pTab->p); - pTab->p.pConfig->pzErrmsg = 0; + pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg; + fts5TripCursors(pTab); + rc = sqlite3Fts5StorageSync(pTab->pStorage); + pTab->pConfig->pzErrmsg = 0; return rc; } /* -** Implementation of xBegin() method. +** Implementation of xBegin() method. */ static int fts5BeginMethod(sqlite3_vtab *pVtab){ - int rc = fts5NewTransaction((Fts5FullTable*)pVtab); - if( rc==SQLITE_OK ){ - fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0); - } - return rc; + fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); + fts5NewTransaction((Fts5Table*)pVtab); + return SQLITE_OK; } /* ** Implementation of xCommit() method. This is a no-op. The contents of ** the pending-terms hash-table have already been flushed into the database ** by fts5SyncMethod(). */ static int fts5CommitMethod(sqlite3_vtab *pVtab){ UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ - fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_COMMIT, 0); + fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0); return SQLITE_OK; } /* ** Implementation of xRollback(). Discard the contents of the pending-terms ** hash-table. Any changes made to the database are reverted by SQLite. */ static int fts5RollbackMethod(sqlite3_vtab *pVtab){ int rc; - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + Fts5Table *pTab = (Fts5Table*)pVtab; fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0); rc = sqlite3Fts5StorageRollback(pTab->pStorage); - pTab->p.pConfig->pgsz = 0; return rc; } static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*); @@ -254354,59 +199232,36 @@ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol; } static int fts5ApiColumnTotalSize( - Fts5Context *pCtx, - int iCol, + Fts5Context *pCtx, + int iCol, sqlite3_int64 *pnToken ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken); } static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow); } -/* -** Implementation of xTokenize_v2() API. -*/ -static int fts5ApiTokenize_v2( - Fts5Context *pCtx, - const char *pText, int nText, - const char *pLoc, int nLoc, +static int fts5ApiTokenize( + Fts5Context *pCtx, + const char *pText, int nText, void *pUserData, int (*xToken)(void*, int, const char*, int, int, int) ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); - int rc = SQLITE_OK; - - sqlite3Fts5SetLocale(pTab->pConfig, pLoc, nLoc); - rc = sqlite3Fts5Tokenize(pTab->pConfig, - FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken + return sqlite3Fts5Tokenize( + pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken ); - sqlite3Fts5SetLocale(pTab->pConfig, 0, 0); - - return rc; -} - -/* -** Implementation of xTokenize() API. This is just xTokenize_v2() with NULL/0 -** passed as the locale. -*/ -static int fts5ApiTokenize( - Fts5Context *pCtx, - const char *pText, int nText, - void *pUserData, - int (*xToken)(void*, int, const char*, int, int, int) -){ - return fts5ApiTokenize_v2(pCtx, pText, nText, 0, 0, pUserData, xToken); } static int fts5ApiPhraseCount(Fts5Context *pCtx){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; return sqlite3Fts5ExprPhraseCount(pCsr->pExpr); @@ -254415,124 +199270,56 @@ static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase); } -/* -** Argument pStmt is an SQL statement of the type used by Fts5Cursor. This -** function extracts the text value of column iCol of the current row. -** Additionally, if there is an associated locale, it invokes -** sqlite3Fts5SetLocale() to configure the tokenizer. In all cases the caller -** should invoke sqlite3Fts5ClearLocale() to clear the locale at some point -** after this function returns. -** -** If successful, (*ppText) is set to point to a buffer containing the text -** value as utf-8 and SQLITE_OK returned. (*pnText) is set to the size of that -** buffer in bytes. It is not guaranteed to be nul-terminated. If an error -** occurs, an SQLite error code is returned. The final values of the two -** output parameters are undefined in this case. -*/ -static int fts5TextFromStmt( - Fts5Config *pConfig, - sqlite3_stmt *pStmt, - int iCol, - const char **ppText, - int *pnText -){ - sqlite3_value *pVal = sqlite3_column_value(pStmt, iCol+1); - const char *pLoc = 0; - int nLoc = 0; - int rc = SQLITE_OK; - - if( pConfig->bLocale - && pConfig->eContent==FTS5_CONTENT_EXTERNAL - && sqlite3Fts5IsLocaleValue(pConfig, pVal) - ){ - rc = sqlite3Fts5DecodeLocaleValue(pVal, ppText, pnText, &pLoc, &nLoc); - }else{ - *ppText = (const char*)sqlite3_value_text(pVal); - *pnText = sqlite3_value_bytes(pVal); - if( pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){ - pLoc = (const char*)sqlite3_column_text(pStmt, iCol+1+pConfig->nCol); - nLoc = sqlite3_column_bytes(pStmt, iCol+1+pConfig->nCol); - } - } - sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); - return rc; -} - static int fts5ApiColumnText( - Fts5Context *pCtx, - int iCol, - const char **pz, + Fts5Context *pCtx, + int iCol, + const char **pz, int *pn ){ int rc = SQLITE_OK; Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); - - assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL ); - if( iCol<0 || iCol>=pTab->pConfig->nCol ){ - rc = SQLITE_RANGE; - }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab), 0) ){ + if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){ *pz = 0; *pn = 0; }else{ rc = fts5SeekCursor(pCsr, 0); if( rc==SQLITE_OK ){ - rc = fts5TextFromStmt(pTab->pConfig, pCsr->pStmt, iCol, pz, pn); - sqlite3Fts5ClearLocale(pTab->pConfig); + *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1); + *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1); } } return rc; } -/* -** This is called by various API functions - xInst, xPhraseFirst, -** xPhraseFirstColumn etc. - to obtain the position list for phrase iPhrase -** of the current row. This function works for both detail=full tables (in -** which case the position-list was read from the fts index) or for other -** detail= modes if the row content is available. -*/ static int fts5CsrPoslist( - Fts5Cursor *pCsr, /* Fts5 cursor object */ - int iPhrase, /* Phrase to find position list for */ - const u8 **pa, /* OUT: Pointer to position list buffer */ - int *pn /* OUT: Size of (*pa) in bytes */ + Fts5Cursor *pCsr, + int iPhrase, + const u8 **pa, + int *pn ){ Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; int rc = SQLITE_OK; int bLive = (pCsr->pSorter==0); - if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){ - rc = SQLITE_RANGE; - }else if( pConfig->eDetail!=FTS5_DETAIL_FULL - && fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1) - ){ - *pa = 0; - *pn = 0; - return SQLITE_OK; - }else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ + if( pConfig->eDetail!=FTS5_DETAIL_FULL ){ Fts5PoslistPopulator *aPopulator; int i; - aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive); if( aPopulator==0 ) rc = SQLITE_NOMEM; - if( rc==SQLITE_OK ){ - rc = fts5SeekCursor(pCsr, 0); - } for(i=0; inCol && rc==SQLITE_OK; i++){ - const char *z = 0; - int n = 0; - rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n); + int n; const char *z; + rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n); if( rc==SQLITE_OK ){ rc = sqlite3Fts5ExprPopulatePoslists( pConfig, pCsr->pExpr, aPopulator, i, z, n ); } - sqlite3Fts5ClearLocale(pConfig); } sqlite3_free(aPopulator); if( pCsr->pSorter ){ sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid); @@ -254539,22 +199326,17 @@ } } CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST); } - if( rc==SQLITE_OK ){ - if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ - Fts5Sorter *pSorter = pCsr->pSorter; - int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); - *pn = pSorter->aIdx[iPhrase] - i1; - *pa = &pSorter->aPoslist[i1]; - }else{ - *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); - } - }else{ - *pa = 0; - *pn = 0; + if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ + Fts5Sorter *pSorter = pCsr->pSorter; + int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); + *pn = pSorter->aIdx[iPhrase] - i1; + *pa = &pSorter->aPoslist[i1]; + }else{ + *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); } return rc; } @@ -254565,15 +199347,14 @@ */ static int fts5CacheInstArray(Fts5Cursor *pCsr){ int rc = SQLITE_OK; Fts5PoslistReader *aIter; /* One iterator for each phrase */ int nIter; /* Number of iterators/phrases */ - int nCol = ((Fts5Table*)pCsr->base.pVtab)->pConfig->nCol; - + nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); if( pCsr->aInstIter==0 ){ - sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nIter; + int nByte = sizeof(Fts5PoslistReader) * nIter; pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte); } aIter = pCsr->aInstIter; if( aIter ){ @@ -254581,11 +199362,11 @@ int i; /* Initialize all iterators */ for(i=0; i=pCsr->nInstAlloc ){ - int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32; - aInst = (int*)sqlite3_realloc64( - pCsr->aInst, nNewSize*sizeof(int)*3 + pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32; + aInst = (int*)sqlite3_realloc( + pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3 ); if( aInst ){ pCsr->aInst = aInst; - pCsr->nInstAlloc = nNewSize; }else{ - nInst--; rc = SQLITE_NOMEM; break; } } aInst = &pCsr->aInst[3 * (nInst-1)]; aInst[0] = iBest; aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos); aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos); - assert( aInst[1]>=0 ); - if( aInst[1]>=nCol ){ - rc = FTS5_CORRUPT; - break; - } sqlite3Fts5PoslistReaderNext(&aIter[iBest]); } } pCsr->nInstCount = nInst; @@ -254639,31 +199413,37 @@ } static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; int rc = SQLITE_OK; - if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){ *pnInst = pCsr->nInstCount; } return rc; } static int fts5ApiInst( - Fts5Context *pCtx, - int iIdx, - int *piPhrase, - int *piCol, + Fts5Context *pCtx, + int iIdx, + int *piPhrase, + int *piCol, int *piOff ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; int rc = SQLITE_OK; - if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 - || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 + || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){ if( iIdx<0 || iIdx>=pCsr->nInstCount ){ rc = SQLITE_RANGE; +#if 0 + }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){ + *piPhrase = pCsr->aInst[iIdx*3]; + *piCol = pCsr->aInst[iIdx*3 + 2]; + *piOff = -1; +#endif }else{ *piPhrase = pCsr->aInst[iIdx*3]; *piCol = pCsr->aInst[iIdx*3 + 1]; *piOff = pCsr->aInst[iIdx*3 + 2]; } @@ -254692,40 +199472,38 @@ return SQLITE_OK; } static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + Fts5Config *pConfig = pTab->pConfig; int rc = SQLITE_OK; if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){ if( pConfig->bColumnsize ){ i64 iRowid = fts5CursorRowid(pCsr); rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize); - }else if( !pConfig->zContent || pConfig->eContent==FTS5_CONTENT_UNINDEXED ){ + }else if( pConfig->zContent==0 ){ int i; for(i=0; inCol; i++){ if( pConfig->abUnindexed[i]==0 ){ pCsr->aColumnSize[i] = -1; } } }else{ int i; - rc = fts5SeekCursor(pCsr, 0); for(i=0; rc==SQLITE_OK && inCol; i++){ if( pConfig->abUnindexed[i]==0 ){ - const char *z = 0; - int n = 0; + const char *z; int n; + void *p = (void*)(&pCsr->aColumnSize[i]); pCsr->aColumnSize[i] = 0; - rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n); + rc = fts5ApiColumnText(pCtx, i, &z, &n); if( rc==SQLITE_OK ){ - rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX, - z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb + rc = sqlite3Fts5Tokenize( + pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb ); } - sqlite3Fts5ClearLocale(pConfig); } } } CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE); } @@ -254801,56 +199579,52 @@ return pRet; } static void fts5ApiPhraseNext( - Fts5Context *pCtx, - Fts5PhraseIter *pIter, + Fts5Context *pUnused, + Fts5PhraseIter *pIter, int *piCol, int *piOff ){ + UNUSED_PARAM(pUnused); if( pIter->a>=pIter->b ){ *piCol = -1; *piOff = -1; }else{ int iVal; pIter->a += fts5GetVarint32(pIter->a, iVal); if( iVal==1 ){ - /* Avoid returning a (*piCol) value that is too large for the table, - ** even if the position-list is corrupt. The caller might not be - ** expecting it. */ - int nCol = ((Fts5Table*)(((Fts5Cursor*)pCtx)->base.pVtab))->pConfig->nCol; pIter->a += fts5GetVarint32(pIter->a, iVal); - *piCol = (iVal>=nCol ? nCol-1 : iVal); + *piCol = iVal; *piOff = 0; pIter->a += fts5GetVarint32(pIter->a, iVal); } *piOff += (iVal-2); } } static int fts5ApiPhraseFirst( - Fts5Context *pCtx, - int iPhrase, - Fts5PhraseIter *pIter, + Fts5Context *pCtx, + int iPhrase, + Fts5PhraseIter *pIter, int *piCol, int *piOff ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; int n; int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n); if( rc==SQLITE_OK ){ - assert( pIter->a || n==0 ); - pIter->b = (pIter->a ? &pIter->a[n] : 0); + pIter->b = &pIter->a[n]; *piCol = 0; *piOff = 0; fts5ApiPhraseNext(pCtx, pIter, piCol, piOff); } return rc; } static void fts5ApiPhraseNextColumn( - Fts5Context *pCtx, - Fts5PhraseIter *pIter, + Fts5Context *pCtx, + Fts5PhraseIter *pIter, int *piCol ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; @@ -254875,13 +199649,13 @@ pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol); } } static int fts5ApiPhraseFirstColumn( - Fts5Context *pCtx, - int iPhrase, - Fts5PhraseIter *pIter, + Fts5Context *pCtx, + int iPhrase, + Fts5PhraseIter *pIter, int *piCol ){ int rc = SQLITE_OK; Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; @@ -254895,21 +199669,19 @@ pIter->a = &pSorter->aPoslist[i1]; }else{ rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n); } if( rc==SQLITE_OK ){ - assert( pIter->a || n==0 ); - pIter->b = (pIter->a ? &pIter->a[n] : 0); + pIter->b = &pIter->a[n]; *piCol = 0; fts5ApiPhraseNextColumn(pCtx, pIter, piCol); } }else{ int n; rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n); if( rc==SQLITE_OK ){ - assert( pIter->a || n==0 ); - pIter->b = (pIter->a ? &pIter->a[n] : 0); + pIter->b = &pIter->a[n]; if( n<=0 ){ *piCol = -1; }else if( pIter->a[0]==0x01 ){ pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol); }else{ @@ -254919,100 +199691,17 @@ } return rc; } -/* -** xQueryToken() API implemenetation. -*/ -static int fts5ApiQueryToken( - Fts5Context* pCtx, - int iPhrase, - int iToken, - const char **ppOut, - int *pnOut -){ - Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - return sqlite3Fts5ExprQueryToken(pCsr->pExpr, iPhrase, iToken, ppOut, pnOut); -} - -/* -** xInstToken() API implemenetation. -*/ -static int fts5ApiInstToken( - Fts5Context *pCtx, - int iIdx, - int iToken, - const char **ppOut, int *pnOut -){ - Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - int rc = SQLITE_OK; - if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 - || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) - ){ - if( iIdx<0 || iIdx>=pCsr->nInstCount ){ - rc = SQLITE_RANGE; - }else{ - int iPhrase = pCsr->aInst[iIdx*3]; - int iCol = pCsr->aInst[iIdx*3 + 1]; - int iOff = pCsr->aInst[iIdx*3 + 2]; - i64 iRowid = fts5CursorRowid(pCsr); - rc = sqlite3Fts5ExprInstToken( - pCsr->pExpr, iRowid, iPhrase, iCol, iOff, iToken, ppOut, pnOut - ); - } - } - return rc; -} - - -static int fts5ApiQueryPhrase(Fts5Context*, int, void*, + +static int fts5ApiQueryPhrase(Fts5Context*, int, void*, int(*)(const Fts5ExtensionApi*, Fts5Context*, void*) ); -/* -** The xColumnLocale() API. -*/ -static int fts5ApiColumnLocale( - Fts5Context *pCtx, - int iCol, - const char **pzLocale, - int *pnLocale -){ - int rc = SQLITE_OK; - Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; - - *pzLocale = 0; - *pnLocale = 0; - - assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL ); - if( iCol<0 || iCol>=pConfig->nCol ){ - rc = SQLITE_RANGE; - }else if( - pConfig->abUnindexed[iCol]==0 - && 0==fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1) - && pConfig->bLocale - ){ - rc = fts5SeekCursor(pCsr, 0); - if( rc==SQLITE_OK ){ - const char *zDummy = 0; - int nDummy = 0; - rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &zDummy, &nDummy); - if( rc==SQLITE_OK ){ - *pzLocale = pConfig->t.pLocale; - *pnLocale = pConfig->t.nLocale; - } - sqlite3Fts5ClearLocale(pConfig); - } - } - - return rc; -} - static const Fts5ExtensionApi sFts5Api = { - 4, /* iVersion */ + 2, /* iVersion */ fts5ApiUserData, fts5ApiColumnCount, fts5ApiRowCount, fts5ApiColumnTotalSize, fts5ApiTokenize, @@ -255028,27 +199717,23 @@ fts5ApiGetAuxdata, fts5ApiPhraseFirst, fts5ApiPhraseNext, fts5ApiPhraseFirstColumn, fts5ApiPhraseNextColumn, - fts5ApiQueryToken, - fts5ApiInstToken, - fts5ApiColumnLocale, - fts5ApiTokenize_v2 }; /* ** Implementation of API function xQueryPhrase(). */ static int fts5ApiQueryPhrase( - Fts5Context *pCtx, - int iPhrase, + Fts5Context *pCtx, + int iPhrase, void *pUserData, int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*) ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); int rc; Fts5Cursor *pNew = 0; rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew); if( rc==SQLITE_OK ){ @@ -255082,11 +199767,10 @@ sqlite3_context *context, int argc, sqlite3_value **argv ){ assert( pCsr->pAux==0 ); - assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL ); pCsr->pAux = pAux; pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv); pCsr->pAux = 0; } @@ -255096,25 +199780,10 @@ if( pCsr->iCsrId==iCsrId ) break; } return pCsr; } -/* -** Parameter zFmt is a printf() style formatting string. This function -** formats it using the trailing arguments and returns the result as -** an error message to the context passed as the first argument. -*/ -static void fts5ResultError(sqlite3_context *pCtx, const char *zFmt, ...){ - char *zErr = 0; - va_list ap; - va_start(ap, zFmt); - zErr = sqlite3_vmprintf(zFmt, ap); - sqlite3_result_error(pCtx, zErr, -1); - sqlite3_free(zErr); - va_end(ap); -} - static void fts5ApiCallback( sqlite3_context *context, int argc, sqlite3_value **argv ){ @@ -255126,35 +199795,40 @@ assert( argc>=1 ); pAux = (Fts5Auxiliary*)sqlite3_user_data(context); iCsrId = sqlite3_value_int64(argv[0]); pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId); - if( pCsr==0 || (pCsr->ePlan==0 || pCsr->ePlan==FTS5_PLAN_SPECIAL) ){ - fts5ResultError(context, "no such cursor: %lld", iCsrId); + if( pCsr==0 ){ + char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); }else{ - sqlite3_vtab *pTab = pCsr->base.pVtab; fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]); - sqlite3_free(pTab->zErrMsg); - pTab->zErrMsg = 0; } } /* -** Given cursor id iId, return a pointer to the corresponding Fts5Table +** Given cursor id iId, return a pointer to the corresponding Fts5Index ** object. Or NULL If the cursor id does not exist. +** +** If successful, set *ppConfig to point to the associated config object +** before returning. */ -static Fts5Table *sqlite3Fts5TableFromCsrid( +static Fts5Index *sqlite3Fts5IndexFromCsrid( Fts5Global *pGlobal, /* FTS5 global context for db handle */ - i64 iCsrId /* Id of cursor to find */ + i64 iCsrId, /* Id of cursor to find */ + Fts5Config **ppConfig /* OUT: Configuration object */ ){ Fts5Cursor *pCsr; + Fts5Table *pTab; + pCsr = fts5CursorFromCsrid(pGlobal, iCsrId); - if( pCsr ){ - return (Fts5Table*)pCsr->base.pVtab; - } - return 0; + pTab = (Fts5Table*)pCsr->base.pVtab; + *ppConfig = pTab->pConfig; + + return pTab->pIndex; } /* ** Return a "position-list blob" corresponding to the current position of ** cursor pCsr via sqlite3_result_blob(). A position-list blob contains @@ -255221,24 +199895,24 @@ sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free); return rc; } -/* +/* ** This is the xColumn method, called by SQLite to request a value from ** the row that the supplied cursor currently points to. */ static int fts5ColumnMethod( sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ int iCol /* Index of column to read value from */ ){ - Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab); - Fts5Config *pConfig = pTab->p.pConfig; + Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); + Fts5Config *pConfig = pTab->pConfig; Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; int rc = SQLITE_OK; - + assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 ); if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){ if( iCol==pConfig->nCol ){ sqlite3_result_int64(pCtx, pCsr->iSpecial); @@ -255250,48 +199924,28 @@ ** as the table. Return the cursor integer id number. This value is only ** useful in that it may be passed as the first argument to an FTS5 ** auxiliary function. */ sqlite3_result_int64(pCtx, pCsr->iCsrId); }else if( iCol==pConfig->nCol+1 ){ + /* The value of the "rank" column. */ - if( pCsr->ePlan==FTS5_PLAN_SOURCE ){ fts5PoslistBlob(pCtx, pCsr); - }else if( + }else if( pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH ){ if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){ fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg); } } - }else{ - if( !sqlite3_vtab_nochange(pCtx) && pConfig->eContent!=FTS5_CONTENT_NONE ){ - pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - rc = fts5SeekCursor(pCsr, 1); - if( rc==SQLITE_OK ){ - sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1); - if( pConfig->bLocale - && pConfig->eContent==FTS5_CONTENT_EXTERNAL - && sqlite3Fts5IsLocaleValue(pConfig, pVal) - ){ - const char *z = 0; - int n = 0; - rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &z, &n); - if( rc==SQLITE_OK ){ - sqlite3_result_text(pCtx, z, n, SQLITE_TRANSIENT); - } - sqlite3Fts5ClearLocale(pConfig); - }else{ - sqlite3_result_value(pCtx, pVal); - } - } - - pConfig->pzErrmsg = 0; - } - } - + }else if( !fts5IsContentless(pTab) ){ + rc = fts5SeekCursor(pCsr, 1); + if( rc==SQLITE_OK ){ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); + } + } return rc; } /* @@ -255303,11 +199957,11 @@ int nUnused, /* Number of SQL function arguments */ const char *zName, /* Name of SQL function */ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ void **ppArg /* OUT: User data for *pxFunc */ ){ - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + Fts5Table *pTab = (Fts5Table*)pVtab; Fts5Auxiliary *pAux; UNUSED_PARAM(nUnused); pAux = fts5FindAuxiliary(pTab, zName); if( pAux ){ @@ -255325,71 +199979,51 @@ */ static int fts5RenameMethod( sqlite3_vtab *pVtab, /* Virtual table handle */ const char *zName /* New name of table */ ){ - int rc; - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - rc = sqlite3Fts5StorageRename(pTab->pStorage, zName); - return rc; -} - -static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){ - fts5TripCursors((Fts5FullTable*)pTab); - return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage); + Fts5Table *pTab = (Fts5Table*)pVtab; + return sqlite3Fts5StorageRename(pTab->pStorage, zName); } /* ** The xSavepoint() method. ** ** Flush the contents of the pending-terms table to disk. */ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - int rc = SQLITE_OK; - + Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); - rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); - if( rc==SQLITE_OK ){ - pTab->iSavepoint = iSavepoint+1; - } - return rc; + fts5TripCursors(pTab); + return sqlite3Fts5StorageSync(pTab->pStorage); } /* ** The xRelease() method. ** ** This is a no-op. */ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - int rc = SQLITE_OK; + Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); - if( (iSavepoint+1)iSavepoint ){ - rc = sqlite3Fts5FlushToDisk(&pTab->p); - if( rc==SQLITE_OK ){ - pTab->iSavepoint = iSavepoint; - } - } - return rc; + fts5TripCursors(pTab); + return sqlite3Fts5StorageSync(pTab->pStorage); } /* ** The xRollbackTo() method. ** ** Discard the contents of the pending terms table. */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - int rc = SQLITE_OK; + Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); - if( (iSavepoint+1)<=pTab->iSavepoint ){ - pTab->p.pConfig->pgsz = 0; - rc = sqlite3Fts5StorageRollback(pTab->pStorage); - } - return rc; + return sqlite3Fts5StorageRollback(pTab->pStorage); } /* ** Register a new auxiliary function with global context pGlobal. */ @@ -255402,18 +200036,18 @@ ){ Fts5Global *pGlobal = (Fts5Global*)pApi; int rc = sqlite3_overload_function(pGlobal->db, zName, -1); if( rc==SQLITE_OK ){ Fts5Auxiliary *pAux; - sqlite3_int64 nName; /* Size of zName in bytes, including \0 */ - sqlite3_int64 nByte; /* Bytes of space to allocate */ + int nName; /* Size of zName in bytes, including \0 */ + int nByte; /* Bytes of space to allocate */ - nName = strlen(zName) + 1; + nName = (int)strlen(zName) + 1; nByte = sizeof(Fts5Auxiliary) + nName; - pAux = (Fts5Auxiliary*)sqlite3_malloc64(nByte); + pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte); if( pAux ){ - memset(pAux, 0, (size_t)nByte); + memset(pAux, 0, nByte); pAux->zFunc = (char*)&pAux[1]; memcpy(pAux->zFunc, zName, nName); pAux->pGlobal = pGlobal; pAux->pUserData = pUserData; pAux->xFunc = xFunc; @@ -255427,214 +200061,51 @@ return rc; } /* -** This function is used by xCreateTokenizer_v2() and xCreateTokenizer(). -** It allocates and partially populates a new Fts5TokenizerModule object. -** The new object is already linked into the Fts5Global context before -** returning. -** -** If successful, SQLITE_OK is returned and a pointer to the new -** Fts5TokenizerModule object returned via output parameter (*ppNew). All -** that is required is for the caller to fill in the methods in -** Fts5TokenizerModule.x1 and x2, and to set Fts5TokenizerModule.bV2Native -** as appropriate. -** -** If an error occurs, an SQLite error code is returned and the final value -** of (*ppNew) undefined. -*/ -static int fts5NewTokenizerModule( - Fts5Global *pGlobal, /* Global context (one per db handle) */ - const char *zName, /* Name of new function */ - void *pUserData, /* User data for aux. function */ - void(*xDestroy)(void*), /* Destructor for pUserData */ - Fts5TokenizerModule **ppNew -){ - int rc = SQLITE_OK; - Fts5TokenizerModule *pNew; - sqlite3_int64 nName; /* Size of zName and its \0 terminator */ - sqlite3_int64 nByte; /* Bytes of space to allocate */ - - nName = strlen(zName) + 1; - nByte = sizeof(Fts5TokenizerModule) + nName; - *ppNew = pNew = (Fts5TokenizerModule*)sqlite3Fts5MallocZero(&rc, nByte); - if( pNew ){ - pNew->zName = (char*)&pNew[1]; - memcpy(pNew->zName, zName, nName); - pNew->pUserData = pUserData; - pNew->xDestroy = xDestroy; - pNew->pNext = pGlobal->pTok; - pGlobal->pTok = pNew; - if( pNew->pNext==0 ){ - pGlobal->pDfltTok = pNew; - } - } - - return rc; -} - -/* -** An instance of this type is used as the Fts5Tokenizer object for -** wrapper tokenizers - those that provide access to a v1 tokenizer via -** the fts5_tokenizer_v2 API, and those that provide access to a v2 tokenizer -** via the fts5_tokenizer API. -*/ -typedef struct Fts5VtoVTokenizer Fts5VtoVTokenizer; -struct Fts5VtoVTokenizer { - int bV2Native; /* True if v2 native tokenizer */ - fts5_tokenizer x1; /* Tokenizer functions */ - fts5_tokenizer_v2 x2; /* V2 tokenizer functions */ - Fts5Tokenizer *pReal; -}; - -/* -** Create a wrapper tokenizer. The context argument pCtx points to the -** Fts5TokenizerModule object. -*/ -static int fts5VtoVCreate( - void *pCtx, - const char **azArg, - int nArg, - Fts5Tokenizer **ppOut -){ - Fts5TokenizerModule *pMod = (Fts5TokenizerModule*)pCtx; - Fts5VtoVTokenizer *pNew = 0; - int rc = SQLITE_OK; - - pNew = (Fts5VtoVTokenizer*)sqlite3Fts5MallocZero(&rc, sizeof(*pNew)); - if( rc==SQLITE_OK ){ - pNew->x1 = pMod->x1; - pNew->x2 = pMod->x2; - pNew->bV2Native = pMod->bV2Native; - if( pMod->bV2Native ){ - rc = pMod->x2.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal); - }else{ - rc = pMod->x1.xCreate(pMod->pUserData, azArg, nArg, &pNew->pReal); - } - if( rc!=SQLITE_OK ){ - sqlite3_free(pNew); - pNew = 0; - } - } - - *ppOut = (Fts5Tokenizer*)pNew; - return rc; -} - -/* -** Delete an Fts5VtoVTokenizer wrapper tokenizer. -*/ -static void fts5VtoVDelete(Fts5Tokenizer *pTok){ - Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok; - if( p ){ - if( p->bV2Native ){ - p->x2.xDelete(p->pReal); - }else{ - p->x1.xDelete(p->pReal); - } - sqlite3_free(p); - } -} - - -/* -** xTokenizer method for a wrapper tokenizer that offers the v1 interface -** (no support for locales). -*/ -static int fts5V1toV2Tokenize( - Fts5Tokenizer *pTok, - void *pCtx, int flags, - const char *pText, int nText, - int (*xToken)(void*, int, const char*, int, int, int) -){ - Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok; - assert( p->bV2Native ); - return p->x2.xTokenize(p->pReal, pCtx, flags, pText, nText, 0, 0, xToken); -} - -/* -** xTokenizer method for a wrapper tokenizer that offers the v2 interface -** (with locale support). -*/ -static int fts5V2toV1Tokenize( - Fts5Tokenizer *pTok, - void *pCtx, int flags, - const char *pText, int nText, - const char *pLocale, int nLocale, - int (*xToken)(void*, int, const char*, int, int, int) -){ - Fts5VtoVTokenizer *p = (Fts5VtoVTokenizer*)pTok; - assert( p->bV2Native==0 ); - UNUSED_PARAM2(pLocale,nLocale); - return p->x1.xTokenize(p->pReal, pCtx, flags, pText, nText, xToken); -} - -/* -** Register a new tokenizer. This is the implementation of the -** fts5_api.xCreateTokenizer_v2() method. -*/ -static int fts5CreateTokenizer_v2( - fts5_api *pApi, /* Global context (one per db handle) */ - const char *zName, /* Name of new function */ - void *pUserData, /* User data for aux. function */ - fts5_tokenizer_v2 *pTokenizer, /* Tokenizer implementation */ - void(*xDestroy)(void*) /* Destructor for pUserData */ -){ - Fts5Global *pGlobal = (Fts5Global*)pApi; - int rc = SQLITE_OK; - - if( pTokenizer->iVersion>2 ){ - rc = SQLITE_ERROR; - }else{ - Fts5TokenizerModule *pNew = 0; - rc = fts5NewTokenizerModule(pGlobal, zName, pUserData, xDestroy, &pNew); - if( pNew ){ - pNew->x2 = *pTokenizer; - pNew->bV2Native = 1; - pNew->x1.xCreate = fts5VtoVCreate; - pNew->x1.xTokenize = fts5V1toV2Tokenize; - pNew->x1.xDelete = fts5VtoVDelete; - } - } - - return rc; -} - -/* -** The fts5_api.xCreateTokenizer() method. +** Register a new tokenizer. This is the implementation of the +** fts5_api.xCreateTokenizer() method. */ static int fts5CreateTokenizer( fts5_api *pApi, /* Global context (one per db handle) */ const char *zName, /* Name of new function */ void *pUserData, /* User data for aux. function */ fts5_tokenizer *pTokenizer, /* Tokenizer implementation */ void(*xDestroy)(void*) /* Destructor for pUserData */ ){ - Fts5TokenizerModule *pNew = 0; + Fts5Global *pGlobal = (Fts5Global*)pApi; + Fts5TokenizerModule *pNew; + int nName; /* Size of zName and its \0 terminator */ + int nByte; /* Bytes of space to allocate */ int rc = SQLITE_OK; - rc = fts5NewTokenizerModule( - (Fts5Global*)pApi, zName, pUserData, xDestroy, &pNew - ); + nName = (int)strlen(zName) + 1; + nByte = sizeof(Fts5TokenizerModule) + nName; + pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte); if( pNew ){ - pNew->x1 = *pTokenizer; - pNew->x2.xCreate = fts5VtoVCreate; - pNew->x2.xTokenize = fts5V2toV1Tokenize; - pNew->x2.xDelete = fts5VtoVDelete; + memset(pNew, 0, nByte); + pNew->zName = (char*)&pNew[1]; + memcpy(pNew->zName, zName, nName); + pNew->pUserData = pUserData; + pNew->x = *pTokenizer; + pNew->xDestroy = xDestroy; + pNew->pNext = pGlobal->pTok; + pGlobal->pTok = pNew; + if( pNew->pNext==0 ){ + pGlobal->pDfltTok = pNew; + } + }else{ + rc = SQLITE_NOMEM; } + return rc; } -/* -** Search the global context passed as the first argument for a tokenizer -** module named zName. If found, return a pointer to the Fts5TokenizerModule -** object. Otherwise, return NULL. -*/ static Fts5TokenizerModule *fts5LocateTokenizer( - Fts5Global *pGlobal, /* Global (one per db handle) object */ - const char *zName /* Name of tokenizer module to find */ + Fts5Global *pGlobal, + const char *zName ){ Fts5TokenizerModule *pMod = 0; if( zName==0 ){ pMod = pGlobal->pDfltTok; @@ -255646,41 +200117,11 @@ return pMod; } /* -** Find a tokenizer. This is the implementation of the -** fts5_api.xFindTokenizer_v2() method. -*/ -static int fts5FindTokenizer_v2( - fts5_api *pApi, /* Global context (one per db handle) */ - const char *zName, /* Name of tokenizer */ - void **ppUserData, - fts5_tokenizer_v2 **ppTokenizer /* Populate this object */ -){ - int rc = SQLITE_OK; - Fts5TokenizerModule *pMod; - - pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName); - if( pMod ){ - if( pMod->bV2Native ){ - *ppUserData = pMod->pUserData; - }else{ - *ppUserData = (void*)pMod; - } - *ppTokenizer = &pMod->x2; - }else{ - *ppTokenizer = 0; - *ppUserData = 0; - rc = SQLITE_ERROR; - } - - return rc; -} - -/* -** Find a tokenizer. This is the implementation of the +** Find a tokenizer. This is the implementation of the ** fts5_api.xFindTokenizer() method. */ static int fts5FindTokenizer( fts5_api *pApi, /* Global context (one per db handle) */ const char *zName, /* Name of new function */ @@ -255690,79 +200131,52 @@ int rc = SQLITE_OK; Fts5TokenizerModule *pMod; pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName); if( pMod ){ - if( pMod->bV2Native==0 ){ - *ppUserData = pMod->pUserData; - }else{ - *ppUserData = (void*)pMod; - } - *pTokenizer = pMod->x1; - }else{ - memset(pTokenizer, 0, sizeof(*pTokenizer)); - *ppUserData = 0; - rc = SQLITE_ERROR; - } - - return rc; -} - -/* -** Attempt to instantiate the tokenizer. -*/ -static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){ - const char **azArg = pConfig->t.azArg; - const int nArg = pConfig->t.nArg; - Fts5TokenizerModule *pMod = 0; - int rc = SQLITE_OK; - - pMod = fts5LocateTokenizer(pConfig->pGlobal, nArg==0 ? 0 : azArg[0]); - if( pMod==0 ){ - assert( nArg>0 ); - rc = SQLITE_ERROR; - sqlite3Fts5ConfigErrmsg(pConfig, "no such tokenizer: %s", azArg[0]); - }else{ - int (*xCreate)(void*, const char**, int, Fts5Tokenizer**) = 0; - if( pMod->bV2Native ){ - xCreate = pMod->x2.xCreate; - pConfig->t.pApi2 = &pMod->x2; - }else{ - pConfig->t.pApi1 = &pMod->x1; - xCreate = pMod->x1.xCreate; - } - - rc = xCreate(pMod->pUserData, - (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok - ); - - if( rc!=SQLITE_OK ){ - if( rc!=SQLITE_NOMEM ){ - sqlite3Fts5ConfigErrmsg(pConfig, "error in tokenizer constructor"); - } - }else if( pMod->bV2Native==0 ){ - pConfig->t.ePattern = sqlite3Fts5TokenizerPattern( - pMod->x1.xCreate, pConfig->t.pTok - ); - } - } - - if( rc!=SQLITE_OK ){ - pConfig->t.pApi1 = 0; - pConfig->t.pApi2 = 0; - pConfig->t.pTok = 0; - } - - return rc; -} - - -/* -** xDestroy callback passed to sqlite3_create_module(). This is invoked -** when the db handle is being closed. Free memory associated with -** tokenizers and aux functions registered with this db handle. -*/ + *pTokenizer = pMod->x; + *ppUserData = pMod->pUserData; + }else{ + memset(pTokenizer, 0, sizeof(fts5_tokenizer)); + rc = SQLITE_ERROR; + } + + return rc; +} + +static int sqlite3Fts5GetTokenizer( + Fts5Global *pGlobal, + const char **azArg, + int nArg, + Fts5Tokenizer **ppTok, + fts5_tokenizer **ppTokApi, + char **pzErr +){ + Fts5TokenizerModule *pMod; + int rc = SQLITE_OK; + + pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]); + if( pMod==0 ){ + assert( nArg>0 ); + rc = SQLITE_ERROR; + *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]); + }else{ + rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok); + *ppTokApi = &pMod->x; + if( rc!=SQLITE_OK && pzErr ){ + *pzErr = sqlite3_mprintf("error in tokenizer constructor"); + } + } + + if( rc!=SQLITE_OK ){ + *ppTokApi = 0; + *ppTok = 0; + } + + return rc; +} + static void fts5ModuleDestroy(void *pCtx){ Fts5TokenizerModule *pTok, *pNextTok; Fts5Auxiliary *pAux, *pNextAux; Fts5Global *pGlobal = (Fts5Global*)pCtx; @@ -255779,25 +200193,22 @@ } sqlite3_free(pGlobal); } -/* -** Implementation of the fts5() function used by clients to obtain the -** API pointer. -*/ static void fts5Fts5Func( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ - sqlite3_value **apArg /* Function arguments */ + sqlite3_value **apUnused /* Function arguments */ ){ Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); - fts5_api **ppApi; - UNUSED_PARAM(nArg); - assert( nArg==1 ); - ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr"); - if( ppApi ) *ppApi = &pGlobal->api; + char buf[8]; + UNUSED_PARAM2(nArg, apUnused); + assert( nArg==0 ); + assert( sizeof(buf)>=sizeof(pGlobal) ); + memcpy(buf, (void*)&pGlobal, sizeof(pGlobal)); + sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT); } /* ** Implementation of fts5_source_id() function. */ @@ -255806,144 +200217,16 @@ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2025-02-02 18:01:32 602d4dd69ec9a724c69cb41ab15376ec731bfd4894fac0a2b25076b857786c6d", -1, SQLITE_TRANSIENT); -} - -/* -** Implementation of fts5_locale(LOCALE, TEXT) function. -** -** If parameter LOCALE is NULL, or a zero-length string, then a copy of -** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as -** text, and the value returned is a blob consisting of: -** -** * The 4 bytes 0x00, 0xE0, 0xB2, 0xEb (FTS5_LOCALE_HEADER). -** * The LOCALE, as utf-8 text, followed by -** * 0x00, followed by -** * The TEXT, as utf-8 text. -** -** There is no final nul-terminator following the TEXT value. -*/ -static void fts5LocaleFunc( - sqlite3_context *pCtx, /* Function call context */ - int nArg, /* Number of args */ - sqlite3_value **apArg /* Function arguments */ -){ - const char *zLocale = 0; - int nLocale = 0; - const char *zText = 0; - int nText = 0; - - assert( nArg==2 ); - UNUSED_PARAM(nArg); - - zLocale = (const char*)sqlite3_value_text(apArg[0]); - nLocale = sqlite3_value_bytes(apArg[0]); - - zText = (const char*)sqlite3_value_text(apArg[1]); - nText = sqlite3_value_bytes(apArg[1]); - - if( zLocale==0 || zLocale[0]=='\0' ){ - sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT); - }else{ - Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx); - u8 *pBlob = 0; - u8 *pCsr = 0; - int nBlob = 0; - - nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText; - pBlob = (u8*)sqlite3_malloc(nBlob); - if( pBlob==0 ){ - sqlite3_result_error_nomem(pCtx); - return; - } - - pCsr = pBlob; - memcpy(pCsr, (const u8*)p->aLocaleHdr, FTS5_LOCALE_HDR_SIZE); - pCsr += FTS5_LOCALE_HDR_SIZE; - memcpy(pCsr, zLocale, nLocale); - pCsr += nLocale; - (*pCsr++) = 0x00; - if( zText ) memcpy(pCsr, zText, nText); - assert( &pCsr[nText]==&pBlob[nBlob] ); - - sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free); - } -} - -/* -** Implementation of fts5_insttoken() function. -*/ -static void fts5InsttokenFunc( - sqlite3_context *pCtx, /* Function call context */ - int nArg, /* Number of args */ - sqlite3_value **apArg /* Function arguments */ -){ - assert( nArg==1 ); - (void)nArg; - sqlite3_result_value(pCtx, apArg[0]); - sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE); -} - -/* -** Return true if zName is the extension on one of the shadow tables used -** by this module. -*/ -static int fts5ShadowName(const char *zName){ - static const char *azName[] = { - "config", "content", "data", "docsize", "idx" - }; - unsigned int i; - for(i=0; ip.pConfig->pzErrmsg==0 ); - pTab->p.pConfig->pzErrmsg = pzErr; - rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0); - if( *pzErr==0 && rc!=SQLITE_OK ){ - if( (rc&0xff)==SQLITE_CORRUPT ){ - *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s", - zSchema, zTabname); - rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM; - }else{ - *pzErr = sqlite3_mprintf("unable to validate the inverted index for" - " FTS5 table %s.%s: %s", - zSchema, zTabname, sqlite3_errstr(rc)); - } - } - - sqlite3Fts5IndexCloseReader(pTab->p.pIndex); - pTab->p.pConfig->pzErrmsg = 0; - - return rc; + sqlite3_result_text(pCtx, "fts5: 2017-07-15 13:49:56 47cf83a0682b7b3219cf255457f5fbe05f3c1f46be42f6bbab33b78a57a252f6", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { - /* iVersion */ 4, + /* iVersion */ 2, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, /* xBestIndex */ fts5BestIndexMethod, /* xDisconnect */ fts5DisconnectMethod, /* xDestroy */ fts5DestroyMethod, @@ -255962,12 +200245,10 @@ /* xFindFunction */ fts5FindFunctionMethod, /* xRename */ fts5RenameMethod, /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, - /* xShadowName */ fts5ShadowName, - /* xIntegrity */ fts5IntegrityMethod }; int rc; Fts5Global *pGlobal = 0; @@ -255976,56 +200257,28 @@ rc = SQLITE_NOMEM; }else{ void *p = (void*)pGlobal; memset(pGlobal, 0, sizeof(Fts5Global)); pGlobal->db = db; - pGlobal->api.iVersion = 3; + pGlobal->api.iVersion = 2; pGlobal->api.xCreateFunction = fts5CreateAux; pGlobal->api.xCreateTokenizer = fts5CreateTokenizer; pGlobal->api.xFindTokenizer = fts5FindTokenizer; - pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2; - pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2; - - /* Initialize pGlobal->aLocaleHdr[] to a 128-bit pseudo-random vector. - ** The constants below were generated randomly. */ - sqlite3_randomness(sizeof(pGlobal->aLocaleHdr), pGlobal->aLocaleHdr); - pGlobal->aLocaleHdr[0] ^= 0xF924976D; - pGlobal->aLocaleHdr[1] ^= 0x16596E13; - pGlobal->aLocaleHdr[2] ^= 0x7C80BEAA; - pGlobal->aLocaleHdr[3] ^= 0x9B03A67F; - assert( sizeof(pGlobal->aLocaleHdr)==16 ); - rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy); if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db); if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db); if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api); if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api); if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db); if( rc==SQLITE_OK ){ rc = sqlite3_create_function( - db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 + db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 ); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function( - db, "fts5_source_id", 0, - SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, - p, fts5SourceIdFunc, 0, 0 - ); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function( - db, "fts5_locale", 2, - SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE, - p, fts5LocaleFunc, 0, 0 - ); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function( - db, "fts5_insttoken", 1, - SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE, - p, fts5InsttokenFunc, 0, 0 + db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0 ); } } /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file @@ -256044,11 +200297,11 @@ /* ** The following functions are used to register the module with SQLite. If ** this module is being built as part of the SQLite core (SQLITE_CORE is ** defined), then sqlite3_open() will call sqlite3Fts5Init() directly. ** -** Or, if this module is being built as a loadable extension, +** Or, if this module is being built as a loadable extension, ** sqlite3Fts5Init() is omitted and the two standard entry points ** sqlite3_fts_init() and sqlite3_fts5_init() defined instead. */ #ifndef SQLITE_CORE #ifdef _WIN32 @@ -256098,66 +200351,38 @@ /* #include "fts5Int.h" */ -/* -** pSavedRow: -** SQL statement FTS5_STMT_LOOKUP2 is a copy of FTS5_STMT_LOOKUP, it -** does a by-rowid lookup to retrieve a single row from the %_content -** table or equivalent external-content table/view. -** -** However, FTS5_STMT_LOOKUP2 is only used when retrieving the original -** values for a row being UPDATEd. In that case, the SQL statement is -** not reset and pSavedRow is set to point at it. This is so that the -** insert operation that follows the delete may access the original -** row values for any new values for which sqlite3_value_nochange() returns -** true. i.e. if the user executes: -** -** CREATE VIRTUAL TABLE ft USING fts5(a, b, c, locale=1); -** ... -** UPDATE fts SET a=?, b=? WHERE rowid=?; -** -** then the value passed to the xUpdate() method of this table as the -** new.c value is an sqlite3_value_nochange() value. So in this case it -** must be read from the saved row stored in Fts5Storage.pSavedRow. -** -** This is necessary - using sqlite3_value_nochange() instead of just having -** SQLite pass the original value back via xUpdate() - so as not to discard -** any locale information associated with such values. -** -*/ struct Fts5Storage { Fts5Config *pConfig; Fts5Index *pIndex; int bTotalsValid; /* True if nTotalRow/aTotalSize[] are valid */ i64 nTotalRow; /* Total number of rows in FTS table */ - i64 *aTotalSize; /* Total sizes of each column */ - sqlite3_stmt *pSavedRow; - sqlite3_stmt *aStmt[12]; + i64 *aTotalSize; /* Total sizes of each column */ + sqlite3_stmt *aStmt[11]; }; -#if FTS5_STMT_SCAN_ASC!=0 -# error "FTS5_STMT_SCAN_ASC mismatch" +#if FTS5_STMT_SCAN_ASC!=0 +# error "FTS5_STMT_SCAN_ASC mismatch" #endif -#if FTS5_STMT_SCAN_DESC!=1 -# error "FTS5_STMT_SCAN_DESC mismatch" +#if FTS5_STMT_SCAN_DESC!=1 +# error "FTS5_STMT_SCAN_DESC mismatch" #endif #if FTS5_STMT_LOOKUP!=2 -# error "FTS5_STMT_LOOKUP mismatch" +# error "FTS5_STMT_LOOKUP mismatch" #endif -#define FTS5_STMT_LOOKUP2 3 -#define FTS5_STMT_INSERT_CONTENT 4 -#define FTS5_STMT_REPLACE_CONTENT 5 -#define FTS5_STMT_DELETE_CONTENT 6 -#define FTS5_STMT_REPLACE_DOCSIZE 7 -#define FTS5_STMT_DELETE_DOCSIZE 8 -#define FTS5_STMT_LOOKUP_DOCSIZE 9 -#define FTS5_STMT_REPLACE_CONFIG 10 -#define FTS5_STMT_SCAN 11 +#define FTS5_STMT_INSERT_CONTENT 3 +#define FTS5_STMT_REPLACE_CONTENT 4 +#define FTS5_STMT_DELETE_CONTENT 5 +#define FTS5_STMT_REPLACE_DOCSIZE 6 +#define FTS5_STMT_DELETE_DOCSIZE 7 +#define FTS5_STMT_LOOKUP_DOCSIZE 8 +#define FTS5_STMT_REPLACE_CONFIG 9 +#define FTS5_STMT_SCAN 10 /* ** Prepare the two insert statements - Fts5Storage.pInsertContent and ** Fts5Storage.pInsertDocsize - if they have not already been prepared. ** Return SQLITE_OK if successful, or an SQLite error code if an error @@ -256169,133 +200394,93 @@ sqlite3_stmt **ppStmt, /* OUT: Prepared statement handle */ char **pzErrMsg /* OUT: Error message (if any) */ ){ int rc = SQLITE_OK; - /* If there is no %_docsize table, there should be no requests for + /* If there is no %_docsize table, there should be no requests for ** statements to operate on it. */ assert( p->pConfig->bColumnsize || ( - eStmt!=FTS5_STMT_REPLACE_DOCSIZE - && eStmt!=FTS5_STMT_DELETE_DOCSIZE - && eStmt!=FTS5_STMT_LOOKUP_DOCSIZE + eStmt!=FTS5_STMT_REPLACE_DOCSIZE + && eStmt!=FTS5_STMT_DELETE_DOCSIZE + && eStmt!=FTS5_STMT_LOOKUP_DOCSIZE )); assert( eStmt>=0 && eStmtaStmt) ); if( p->aStmt[eStmt]==0 ){ const char *azStmt[] = { "SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC", "SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC", "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP */ - "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP2 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */ "REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */ "DELETE FROM %Q.'%q_content' WHERE id=?", /* DELETE_CONTENT */ - "REPLACE INTO %Q.'%q_docsize' VALUES(?,?%s)", /* REPLACE_DOCSIZE */ + "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", /* REPLACE_DOCSIZE */ "DELETE FROM %Q.'%q_docsize' WHERE id=?", /* DELETE_DOCSIZE */ - "SELECT sz%s FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ + "SELECT sz FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ "REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */ "SELECT %s FROM %s AS T", /* SCAN */ }; Fts5Config *pC = p->pConfig; char *zSql = 0; - assert( ArraySize(azStmt)==ArraySize(p->aStmt) ); - switch( eStmt ){ case FTS5_STMT_SCAN: - zSql = sqlite3_mprintf(azStmt[eStmt], + zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist, pC->zContent ); break; case FTS5_STMT_SCAN_ASC: case FTS5_STMT_SCAN_DESC: - zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist, + zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist, pC->zContent, pC->zContentRowid, pC->zContentRowid, pC->zContentRowid ); break; case FTS5_STMT_LOOKUP: - case FTS5_STMT_LOOKUP2: - zSql = sqlite3_mprintf(azStmt[eStmt], + zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist, pC->zContent, pC->zContentRowid ); break; - case FTS5_STMT_INSERT_CONTENT: + case FTS5_STMT_INSERT_CONTENT: case FTS5_STMT_REPLACE_CONTENT: { - char *zBind = 0; + int nCol = pC->nCol + 1; + char *zBind; int i; - assert( pC->eContent==FTS5_CONTENT_NORMAL - || pC->eContent==FTS5_CONTENT_UNINDEXED - ); - - /* Add bindings for the "c*" columns - those that store the actual - ** table content. If eContent==NORMAL, then there is one binding - ** for each column. Or, if eContent==UNINDEXED, then there are only - ** bindings for the UNINDEXED columns. */ - for(i=0; rc==SQLITE_OK && i<(pC->nCol+1); i++){ - if( !i || pC->eContent==FTS5_CONTENT_NORMAL || pC->abUnindexed[i-1] ){ - zBind = sqlite3Fts5Mprintf(&rc, "%z%s?%d", zBind, zBind?",":"",i+1); - } - } - - /* Add bindings for any "l*" columns. Only non-UNINDEXED columns - ** require these. */ - if( pC->bLocale && pC->eContent==FTS5_CONTENT_NORMAL ){ - for(i=0; rc==SQLITE_OK && inCol; i++){ - if( pC->abUnindexed[i]==0 ){ - zBind = sqlite3Fts5Mprintf(&rc, "%z,?%d", zBind, pC->nCol+i+2); - } - } - } - - zSql = sqlite3Fts5Mprintf(&rc, azStmt[eStmt], pC->zDb, pC->zName,zBind); - sqlite3_free(zBind); - break; - } - - case FTS5_STMT_REPLACE_DOCSIZE: - zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, - (pC->bContentlessDelete ? ",?" : "") - ); - break; - - case FTS5_STMT_LOOKUP_DOCSIZE: - zSql = sqlite3_mprintf(azStmt[eStmt], - (pC->bContentlessDelete ? ",origin" : ""), - pC->zDb, pC->zName - ); - break; + zBind = sqlite3_malloc(1 + nCol*2); + if( zBind ){ + for(i=0; izDb, pC->zName, zBind); + sqlite3_free(zBind); + } + break; + } default: zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName); break; } if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ - int f = SQLITE_PREPARE_PERSISTENT; - if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB; - p->pConfig->bLock++; - rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0); - p->pConfig->bLock--; + rc = sqlite3_prepare_v3(pC->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0); sqlite3_free(zSql); if( rc!=SQLITE_OK && pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); } - if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmtaStmt[eStmt]; sqlite3_reset(*ppStmt); @@ -256330,26 +200515,26 @@ /* ** Drop all shadow tables. Return SQLITE_OK if successful or an SQLite error ** code otherwise. */ static int sqlite3Fts5DropAll(Fts5Config *pConfig){ - int rc = fts5ExecPrintf(pConfig->db, 0, + int rc = fts5ExecPrintf(pConfig->db, 0, "DROP TABLE IF EXISTS %Q.'%q_data';" "DROP TABLE IF EXISTS %Q.'%q_idx';" "DROP TABLE IF EXISTS %Q.'%q_config';", pConfig->zDb, pConfig->zName, pConfig->zDb, pConfig->zName, pConfig->zDb, pConfig->zName ); if( rc==SQLITE_OK && pConfig->bColumnsize ){ - rc = fts5ExecPrintf(pConfig->db, 0, + rc = fts5ExecPrintf(pConfig->db, 0, "DROP TABLE IF EXISTS %Q.'%q_docsize';", pConfig->zDb, pConfig->zName ); } if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ - rc = fts5ExecPrintf(pConfig->db, 0, + rc = fts5ExecPrintf(pConfig->db, 0, "DROP TABLE IF EXISTS %Q.'%q_content';", pConfig->zDb, pConfig->zName ); } return rc; @@ -256360,11 +200545,11 @@ int *pRc, /* IN/OUT: Error code */ const char *zTail, /* Tail of table name e.g. "data", "config" */ const char *zName /* New name of FTS5 table */ ){ if( *pRc==SQLITE_OK ){ - *pRc = fts5ExecPrintf(pConfig->db, 0, + *pRc = fts5ExecPrintf(pConfig->db, 0, "ALTER TABLE %Q.'%q_%s' RENAME TO '%q_%s';", pConfig->zDb, pConfig->zName, zTail, zName, zTail ); } } @@ -256398,19 +200583,19 @@ ){ int rc; char *zErr = 0; rc = fts5ExecPrintf(pConfig->db, &zErr, "CREATE TABLE %Q.'%q_%q'(%s)%s", - pConfig->zDb, pConfig->zName, zPost, zDefn, + pConfig->zDb, pConfig->zName, zPost, zDefn, #ifndef SQLITE_FTS5_NO_WITHOUT_ROWID bWithout?" WITHOUT ROWID": #endif "" ); if( zErr ){ *pzErr = sqlite3_mprintf( - "fts5: error creating shadow table %q_%s: %s", + "fts5: error creating shadow table %q_%s: %s", pConfig->zName, zPost, zErr ); sqlite3_free(zErr); } @@ -256417,76 +200602,60 @@ return rc; } /* ** Open a new Fts5Index handle. If the bCreate argument is true, create -** and initialize the underlying tables +** and initialize the underlying tables ** ** If successful, set *pp to point to the new object and return SQLITE_OK. ** Otherwise, set *pp to NULL and return an SQLite error code. */ static int sqlite3Fts5StorageOpen( - Fts5Config *pConfig, - Fts5Index *pIndex, - int bCreate, + Fts5Config *pConfig, + Fts5Index *pIndex, + int bCreate, Fts5Storage **pp, char **pzErr /* OUT: Error message */ ){ int rc = SQLITE_OK; Fts5Storage *p; /* New object */ - sqlite3_int64 nByte; /* Bytes of space to allocate */ + int nByte; /* Bytes of space to allocate */ nByte = sizeof(Fts5Storage) /* Fts5Storage object */ + pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */ - *pp = p = (Fts5Storage*)sqlite3_malloc64(nByte); + *pp = p = (Fts5Storage*)sqlite3_malloc(nByte); if( !p ) return SQLITE_NOMEM; - memset(p, 0, (size_t)nByte); + memset(p, 0, nByte); p->aTotalSize = (i64*)&p[1]; p->pConfig = pConfig; p->pIndex = pIndex; if( bCreate ){ - if( pConfig->eContent==FTS5_CONTENT_NORMAL - || pConfig->eContent==FTS5_CONTENT_UNINDEXED - ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ int nDefn = 32 + pConfig->nCol*10; - char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20); + char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10); if( zDefn==0 ){ rc = SQLITE_NOMEM; }else{ int i; int iOff; sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY"); iOff = (int)strlen(zDefn); for(i=0; inCol; i++){ - if( pConfig->eContent==FTS5_CONTENT_NORMAL - || pConfig->abUnindexed[i] - ){ - sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i); - iOff += (int)strlen(&zDefn[iOff]); - } - } - if( pConfig->bLocale ){ - for(i=0; inCol; i++){ - if( pConfig->abUnindexed[i]==0 ){ - sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i); - iOff += (int)strlen(&zDefn[iOff]); - } - } + sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i); + iOff += (int)strlen(&zDefn[iOff]); } rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr); } sqlite3_free(zDefn); } if( rc==SQLITE_OK && pConfig->bColumnsize ){ - const char *zCols = "id INTEGER PRIMARY KEY, sz BLOB"; - if( pConfig->bContentlessDelete ){ - zCols = "id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER"; - } - rc = sqlite3Fts5CreateTable(pConfig, "docsize", zCols, 0, pzErr); + rc = sqlite3Fts5CreateTable( + pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr + ); } if( rc==SQLITE_OK ){ rc = sqlite3Fts5CreateTable( pConfig, "config", "k PRIMARY KEY, v", 1, pzErr ); @@ -256547,184 +200716,64 @@ pCtx->szCol++; } return sqlite3Fts5IndexWrite(pIdx, pCtx->iCol, pCtx->szCol-1, pToken, nToken); } -/* -** This function is used as part of an UPDATE statement that modifies the -** rowid of a row. In that case, this function is called first to set -** Fts5Storage.pSavedRow to point to a statement that may be used to -** access the original values of the row being deleted - iDel. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -** It is not considered an error if row iDel does not exist. In this case -** pSavedRow is not set and SQLITE_OK returned. -*/ -static int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel){ - int rc = SQLITE_OK; - sqlite3_stmt *pSeek = 0; - - assert( p->pSavedRow==0 ); - rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+1, &pSeek, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pSeek, 1, iDel); - if( sqlite3_step(pSeek)!=SQLITE_ROW ){ - rc = sqlite3_reset(pSeek); - }else{ - p->pSavedRow = pSeek; - } - } - - return rc; -} - /* ** If a row with rowid iDel is present in the %_content table, add the ** delete-markers to the FTS index necessary to delete it. Do not actually ** remove the %_content row at this time though. -** -** If parameter bSaveRow is true, then Fts5Storage.pSavedRow is left -** pointing to a statement (FTS5_STMT_LOOKUP2) that may be used to access -** the original values of the row being deleted. This is used by UPDATE -** statements. */ static int fts5StorageDeleteFromIndex( - Fts5Storage *p, - i64 iDel, - sqlite3_value **apVal, - int bSaveRow /* True to set pSavedRow */ + Fts5Storage *p, + i64 iDel, + sqlite3_value **apVal ){ Fts5Config *pConfig = p->pConfig; sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */ - int rc = SQLITE_OK; /* Return code */ + int rc; /* Return code */ int rc2; /* sqlite3_reset() return code */ int iCol; Fts5InsertCtx ctx; - assert( bSaveRow==0 || apVal==0 ); - assert( bSaveRow==0 || bSaveRow==1 ); - assert( FTS5_STMT_LOOKUP2==FTS5_STMT_LOOKUP+1 ); - if( apVal==0 ){ - if( p->pSavedRow && bSaveRow ){ - pSeek = p->pSavedRow; - p->pSavedRow = 0; - }else{ - rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+bSaveRow, &pSeek, 0); - if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int64(pSeek, 1, iDel); - if( sqlite3_step(pSeek)!=SQLITE_ROW ){ - return sqlite3_reset(pSeek); - } + rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0); + if( rc!=SQLITE_OK ) return rc; + sqlite3_bind_int64(pSeek, 1, iDel); + if( sqlite3_step(pSeek)!=SQLITE_ROW ){ + return sqlite3_reset(pSeek); } } ctx.pStorage = p; ctx.iCol = -1; + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel); for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){ if( pConfig->abUnindexed[iCol-1]==0 ){ - sqlite3_value *pVal = 0; - const char *pText = 0; - int nText = 0; - const char *pLoc = 0; - int nLoc = 0; - - assert( pSeek==0 || apVal==0 ); - assert( pSeek!=0 || apVal!=0 ); + const char *zText; + int nText; if( pSeek ){ - pVal = sqlite3_column_value(pSeek, iCol); - }else{ - pVal = apVal[iCol-1]; - } - - if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ - rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); - }else{ - pText = (const char*)sqlite3_value_text(pVal); - nText = sqlite3_value_bytes(pVal); - if( pConfig->bLocale && pSeek ){ - pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol); - nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol); - } - } - - if( rc==SQLITE_OK ){ - sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); - ctx.szCol = 0; - rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT, - pText, nText, (void*)&ctx, fts5StorageInsertCallback - ); - p->aTotalSize[iCol-1] -= (i64)ctx.szCol; - if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){ - rc = FTS5_CORRUPT; - } - sqlite3Fts5ClearLocale(pConfig); - } - } - } - if( rc==SQLITE_OK && p->nTotalRow<1 ){ - rc = FTS5_CORRUPT; - }else{ - p->nTotalRow--; - } - - if( rc==SQLITE_OK && bSaveRow ){ - assert( p->pSavedRow==0 ); - p->pSavedRow = pSeek; - }else{ - rc2 = sqlite3_reset(pSeek); - if( rc==SQLITE_OK ) rc = rc2; - } - return rc; -} - -/* -** Reset any saved statement pSavedRow. Zero pSavedRow as well. This -** should be called by the xUpdate() method of the fts5 table before -** returning from any operation that may have set Fts5Storage.pSavedRow. -*/ -static void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage *pStorage){ - assert( pStorage->pSavedRow==0 - || pStorage->pSavedRow==pStorage->aStmt[FTS5_STMT_LOOKUP2] - ); - sqlite3_reset(pStorage->pSavedRow); - pStorage->pSavedRow = 0; -} - -/* -** This function is called to process a DELETE on a contentless_delete=1 -** table. It adds the tombstone required to delete the entry with rowid -** iDel. If successful, SQLITE_OK is returned. Or, if an error occurs, -** an SQLite error code. -*/ -static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){ - i64 iOrigin = 0; - sqlite3_stmt *pLookup = 0; - int rc = SQLITE_OK; - - assert( p->pConfig->bContentlessDelete ); - assert( p->pConfig->eContent==FTS5_CONTENT_NONE - || p->pConfig->eContent==FTS5_CONTENT_UNINDEXED - ); - - /* Look up the origin of the document in the %_docsize table. Store - ** this in stack variable iOrigin. */ - rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pLookup, 1, iDel); - if( SQLITE_ROW==sqlite3_step(pLookup) ){ - iOrigin = sqlite3_column_int64(pLookup, 1); - } - rc = sqlite3_reset(pLookup); - } - - if( rc==SQLITE_OK && iOrigin!=0 ){ - rc = sqlite3Fts5IndexContentlessDelete(p->pIndex, iOrigin, iDel); - } - - return rc; -} + zText = (const char*)sqlite3_column_text(pSeek, iCol); + nText = sqlite3_column_bytes(pSeek, iCol); + }else{ + zText = (const char*)sqlite3_value_text(apVal[iCol-1]); + nText = sqlite3_value_bytes(apVal[iCol-1]); + } + ctx.szCol = 0; + rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT, + zText, nText, (void*)&ctx, fts5StorageInsertCallback + ); + p->aTotalSize[iCol-1] -= (i64)ctx.szCol; + } + } + p->nTotalRow--; + + rc2 = sqlite3_reset(pSeek); + if( rc==SQLITE_OK ) rc = rc2; + return rc; +} + /* ** Insert a record into the %_docsize table. Specifically, do: ** ** INSERT OR REPLACE INTO %_docsize(id, sz) VALUES(iRowid, pBuf); @@ -256741,28 +200790,20 @@ if( p->pConfig->bColumnsize ){ sqlite3_stmt *pReplace = 0; rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0); if( rc==SQLITE_OK ){ sqlite3_bind_int64(pReplace, 1, iRowid); - if( p->pConfig->bContentlessDelete ){ - i64 iOrigin = 0; - rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin); - sqlite3_bind_int64(pReplace, 3, iOrigin); - } - } - if( rc==SQLITE_OK ){ sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 2); } } return rc; } /* -** Load the contents of the "averages" record from disk into the +** Load the contents of the "averages" record from disk into the ** p->nTotalRow and p->aTotalSize[] variables. If successful, and if ** argument bCache is true, set the p->bTotalsValid flag to indicate ** that the contents of aTotalSize[] and nTotalRow are valid until ** further notice. ** @@ -256777,11 +200818,11 @@ } return rc; } /* -** Store the current contents of the p->nTotalRow and p->aTotalSize[] +** Store the current contents of the p->nTotalRow and p->aTotalSize[] ** variables in the "averages" record on disk. ** ** Return SQLITE_OK if successful, or an SQLite error code if an error ** occurs. */ @@ -256805,40 +200846,21 @@ } /* ** Remove a row from the FTS table. */ -static int sqlite3Fts5StorageDelete( - Fts5Storage *p, /* Storage object */ - i64 iDel, /* Rowid to delete from table */ - sqlite3_value **apVal, /* Optional - values to remove from index */ - int bSaveRow /* If true, set pSavedRow for deleted row */ -){ +static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){ Fts5Config *pConfig = p->pConfig; int rc; sqlite3_stmt *pDel = 0; assert( pConfig->eContent!=FTS5_CONTENT_NORMAL || apVal==0 ); rc = fts5StorageLoadTotals(p, 1); /* Delete the index records */ if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel); - } - - if( rc==SQLITE_OK ){ - if( p->pConfig->bContentlessDelete ){ - rc = fts5StorageContentlessDelete(p, iDel); - if( rc==SQLITE_OK - && bSaveRow - && p->pConfig->eContent==FTS5_CONTENT_UNINDEXED - ){ - rc = sqlite3Fts5StorageFindDeleteRow(p, iDel); - } - }else{ - rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow); - } + rc = fts5StorageDeleteFromIndex(p, iDel, apVal); } /* Delete the %_docsize record */ if( rc==SQLITE_OK && pConfig->bColumnsize ){ rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0); @@ -256848,13 +200870,11 @@ rc = sqlite3_reset(pDel); } } /* Delete the %_content record */ - if( pConfig->eContent==FTS5_CONTENT_NORMAL - || pConfig->eContent==FTS5_CONTENT_UNINDEXED - ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ if( rc==SQLITE_OK ){ rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0); } if( rc==SQLITE_OK ){ sqlite3_bind_int64(pDel, 1, iDel); @@ -256871,28 +200891,21 @@ */ static int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){ Fts5Config *pConfig = p->pConfig; int rc; - p->bTotalsValid = 0; - /* Delete the contents of the %_data and %_docsize tables. */ rc = fts5ExecPrintf(pConfig->db, 0, - "DELETE FROM %Q.'%q_data';" + "DELETE FROM %Q.'%q_data';" "DELETE FROM %Q.'%q_idx';", pConfig->zDb, pConfig->zName, pConfig->zDb, pConfig->zName ); if( rc==SQLITE_OK && pConfig->bColumnsize ){ rc = fts5ExecPrintf(pConfig->db, 0, - "DELETE FROM %Q.'%q_docsize';", pConfig->zDb, pConfig->zName - ); - } - - if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_UNINDEXED ){ - rc = fts5ExecPrintf(pConfig->db, 0, - "DELETE FROM %Q.'%q_content';", pConfig->zDb, pConfig->zName + "DELETE FROM %Q.'%q_docsize';", + pConfig->zDb, pConfig->zName ); } /* Reinitialize the %_data table. This call creates the initial structure ** and averages records. */ @@ -256908,21 +200921,21 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){ Fts5Buffer buf = {0,0,0}; Fts5Config *pConfig = p->pConfig; sqlite3_stmt *pScan = 0; Fts5InsertCtx ctx; - int rc, rc2; + int rc; memset(&ctx, 0, sizeof(Fts5InsertCtx)); ctx.pStorage = p; rc = sqlite3Fts5StorageDeleteAll(p); if( rc==SQLITE_OK ){ rc = fts5StorageLoadTotals(p, 1); } if( rc==SQLITE_OK ){ - rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, pConfig->pzErrmsg); + rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){ i64 iRowid = sqlite3_column_int64(pScan, 0); @@ -256929,40 +200942,17 @@ sqlite3Fts5BufferZero(&buf); rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid); for(ctx.iCol=0; rc==SQLITE_OK && ctx.iColnCol; ctx.iCol++){ ctx.szCol = 0; if( pConfig->abUnindexed[ctx.iCol]==0 ){ - int nText = 0; /* Size of pText in bytes */ - const char *pText = 0; /* Pointer to buffer containing text value */ - int nLoc = 0; /* Size of pLoc in bytes */ - const char *pLoc = 0; /* Pointer to buffer containing text value */ - - sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1); - if( pConfig->eContent==FTS5_CONTENT_EXTERNAL - && sqlite3Fts5IsLocaleValue(pConfig, pVal) - ){ - rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); - }else{ - pText = (const char*)sqlite3_value_text(pVal); - nText = sqlite3_value_bytes(pVal); - if( pConfig->bLocale ){ - int iCol = ctx.iCol + 1 + pConfig->nCol; - pLoc = (const char*)sqlite3_column_text(pScan, iCol); - nLoc = sqlite3_column_bytes(pScan, iCol); - } - } - - if( rc==SQLITE_OK ){ - sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); - rc = sqlite3Fts5Tokenize(pConfig, - FTS5_TOKENIZE_DOCUMENT, - pText, nText, - (void*)&ctx, - fts5StorageInsertCallback - ); - sqlite3Fts5ClearLocale(pConfig); - } + rc = sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, + (const char*)sqlite3_column_text(pScan, ctx.iCol+1), + sqlite3_column_bytes(pScan, ctx.iCol+1), + (void*)&ctx, + fts5StorageInsertCallback + ); } sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol); p->aTotalSize[ctx.iCol] += (i64)ctx.szCol; } p->nTotalRow++; @@ -256970,12 +200960,10 @@ if( rc==SQLITE_OK ){ rc = fts5StorageInsertDocsize(p, iRowid, &buf); } } sqlite3_free(buf.p); - rc2 = sqlite3_reset(pScan); - if( rc==SQLITE_OK ) rc = rc2; /* Write the averages record */ if( rc==SQLITE_OK ){ rc = fts5StorageSaveTotals(p); } @@ -257023,76 +201011,30 @@ /* ** Insert a new row into the FTS content table. */ static int sqlite3Fts5StorageContentInsert( - Fts5Storage *p, - int bReplace, /* True to use REPLACE instead of INSERT */ - sqlite3_value **apVal, + Fts5Storage *p, + sqlite3_value **apVal, i64 *piRowid ){ Fts5Config *pConfig = p->pConfig; int rc = SQLITE_OK; /* Insert the new row into the %_content table. */ - if( pConfig->eContent!=FTS5_CONTENT_NORMAL - && pConfig->eContent!=FTS5_CONTENT_UNINDEXED - ){ + if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){ if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){ *piRowid = sqlite3_value_int64(apVal[1]); }else{ rc = fts5StorageNewRowid(p, piRowid); } }else{ sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */ int i; /* Counter variable */ - - assert( FTS5_STMT_INSERT_CONTENT+1==FTS5_STMT_REPLACE_CONTENT ); - assert( bReplace==0 || bReplace==1 ); - rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT+bReplace, &pInsert, 0); - if( pInsert ) sqlite3_clear_bindings(pInsert); - - /* Bind the rowid value */ - sqlite3_bind_value(pInsert, 1, apVal[1]); - - /* Loop through values for user-defined columns. i=2 is the leftmost - ** user-defined column. As is column 1 of pSavedRow. */ - for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){ - int bUnindexed = pConfig->abUnindexed[i-2]; - if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){ - sqlite3_value *pVal = apVal[i]; - - if( sqlite3_value_nochange(pVal) && p->pSavedRow ){ - /* This is an UPDATE statement, and user-defined column (i-2) was not - ** modified. Retrieve the value from Fts5Storage.pSavedRow. */ - pVal = sqlite3_column_value(p->pSavedRow, i-1); - if( pConfig->bLocale && bUnindexed==0 ){ - sqlite3_bind_value(pInsert, pConfig->nCol + i, - sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1) - ); - } - }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ - const char *pText = 0; - const char *pLoc = 0; - int nText = 0; - int nLoc = 0; - assert( pConfig->bLocale ); - - rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); - if( rc==SQLITE_OK ){ - sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT); - if( bUnindexed==0 ){ - int iLoc = pConfig->nCol + i; - sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT); - } - } - - continue; - } - - rc = sqlite3_bind_value(pInsert, i, pVal); - } + rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0); + for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){ + rc = sqlite3_bind_value(pInsert, i, apVal[i]); } if( rc==SQLITE_OK ){ sqlite3_step(pInsert); rc = sqlite3_reset(pInsert); } @@ -257104,12 +201046,12 @@ /* ** Insert new entries into the FTS index and %_docsize table. */ static int sqlite3Fts5StorageIndexInsert( - Fts5Storage *p, - sqlite3_value **apVal, + Fts5Storage *p, + sqlite3_value **apVal, i64 iRowid ){ Fts5Config *pConfig = p->pConfig; int rc = SQLITE_OK; /* Return code */ Fts5InsertCtx ctx; /* Tokenization callback context object */ @@ -257123,42 +201065,17 @@ rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid); } for(ctx.iCol=0; rc==SQLITE_OK && ctx.iColnCol; ctx.iCol++){ ctx.szCol = 0; if( pConfig->abUnindexed[ctx.iCol]==0 ){ - int nText = 0; /* Size of pText in bytes */ - const char *pText = 0; /* Pointer to buffer containing text value */ - int nLoc = 0; /* Size of pText in bytes */ - const char *pLoc = 0; /* Pointer to buffer containing text value */ - - sqlite3_value *pVal = apVal[ctx.iCol+2]; - if( p->pSavedRow && sqlite3_value_nochange(pVal) ){ - pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1); - if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){ - int iCol = ctx.iCol + 1 + pConfig->nCol; - pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol); - nLoc = sqlite3_column_bytes(p->pSavedRow, iCol); - } - }else{ - pVal = apVal[ctx.iCol+2]; - } - - if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ - rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); - }else{ - pText = (const char*)sqlite3_value_text(pVal); - nText = sqlite3_value_bytes(pVal); - } - - if( rc==SQLITE_OK ){ - sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); - rc = sqlite3Fts5Tokenize(pConfig, - FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx, - fts5StorageInsertCallback - ); - sqlite3Fts5ClearLocale(pConfig); - } + rc = sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, + (const char*)sqlite3_value_text(apVal[ctx.iCol+2]), + sqlite3_value_bytes(apVal[ctx.iCol+2]), + (void*)&ctx, + fts5StorageInsertCallback + ); } sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol); p->aTotalSize[ctx.iCol] += (i64)ctx.szCol; } p->nTotalRow++; @@ -257175,11 +201092,11 @@ static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){ Fts5Config *pConfig = p->pConfig; char *zSql; int rc; - zSql = sqlite3_mprintf("SELECT count(*) FROM %Q.'%q_%s'", + zSql = sqlite3_mprintf("SELECT count(*) FROM %Q.'%q_%s'", pConfig->zDb, pConfig->zName, zSuffix ); if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ @@ -257282,140 +201199,101 @@ ** Check that the contents of the FTS index match that of the %_content ** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return ** some other SQLite error code if an error occurs while attempting to ** determine this. */ -static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){ +static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){ Fts5Config *pConfig = p->pConfig; - int rc = SQLITE_OK; /* Return code */ + int rc; /* Return code */ int *aColSize; /* Array of size pConfig->nCol */ i64 *aTotalSize; /* Array of size pConfig->nCol */ Fts5IntegrityCtx ctx; sqlite3_stmt *pScan; - int bUseCksum; memset(&ctx, 0, sizeof(Fts5IntegrityCtx)); ctx.pConfig = p->pConfig; - aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64))); + aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64))); if( !aTotalSize ) return SQLITE_NOMEM; aColSize = (int*)&aTotalSize[pConfig->nCol]; memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol); - bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL - || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg) - ); - if( bUseCksum ){ - /* Generate the expected index checksum based on the contents of the - ** %_content table. This block stores the checksum in ctx.cksum. */ - rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); - if( rc==SQLITE_OK ){ - int rc2; - while( SQLITE_ROW==sqlite3_step(pScan) ){ - int i; - ctx.iRowid = sqlite3_column_int64(pScan, 0); - ctx.szCol = 0; - if( pConfig->bColumnsize ){ - rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize); - } - if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){ - rc = sqlite3Fts5TermsetNew(&ctx.pTermset); - } - for(i=0; rc==SQLITE_OK && inCol; i++){ - if( pConfig->abUnindexed[i]==0 ){ - const char *pText = 0; - int nText = 0; - const char *pLoc = 0; - int nLoc = 0; - sqlite3_value *pVal = sqlite3_column_value(pScan, i+1); - - if( pConfig->eContent==FTS5_CONTENT_EXTERNAL - && sqlite3Fts5IsLocaleValue(pConfig, pVal) - ){ - rc = sqlite3Fts5DecodeLocaleValue( - pVal, &pText, &nText, &pLoc, &nLoc - ); - }else{ - if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){ - int iCol = i + 1 + pConfig->nCol; - pLoc = (const char*)sqlite3_column_text(pScan, iCol); - nLoc = sqlite3_column_bytes(pScan, iCol); - } - pText = (const char*)sqlite3_value_text(pVal); - nText = sqlite3_value_bytes(pVal); - } - - ctx.iCol = i; - ctx.szCol = 0; - - if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ - rc = sqlite3Fts5TermsetNew(&ctx.pTermset); - } - - if( rc==SQLITE_OK ){ - sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); - rc = sqlite3Fts5Tokenize(pConfig, - FTS5_TOKENIZE_DOCUMENT, - pText, nText, - (void*)&ctx, - fts5StorageIntegrityCallback - ); - sqlite3Fts5ClearLocale(pConfig); - } - - /* If this is not a columnsize=0 database, check that the number - ** of tokens in the value matches the aColSize[] value read from - ** the %_docsize table. */ - if( rc==SQLITE_OK - && pConfig->bColumnsize - && ctx.szCol!=aColSize[i] - ){ - rc = FTS5_CORRUPT; - } - aTotalSize[i] += ctx.szCol; - if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ - sqlite3Fts5TermsetFree(ctx.pTermset); - ctx.pTermset = 0; - } - } - } - sqlite3Fts5TermsetFree(ctx.pTermset); - ctx.pTermset = 0; - - if( rc!=SQLITE_OK ) break; - } - rc2 = sqlite3_reset(pScan); - if( rc==SQLITE_OK ) rc = rc2; - } - - /* Test that the "totals" (sometimes called "averages") record looks Ok */ - if( rc==SQLITE_OK ){ - int i; - rc = fts5StorageLoadTotals(p, 0); - for(i=0; rc==SQLITE_OK && inCol; i++){ - if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT; - } - } - - /* Check that the %_docsize and %_content tables contain the expected - ** number of rows. */ - if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ - i64 nRow = 0; - rc = fts5StorageCount(p, "content", &nRow); - if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; - } - if( rc==SQLITE_OK && pConfig->bColumnsize ){ - i64 nRow = 0; - rc = fts5StorageCount(p, "docsize", &nRow); - if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; - } + /* Generate the expected index checksum based on the contents of the + ** %_content table. This block stores the checksum in ctx.cksum. */ + rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); + if( rc==SQLITE_OK ){ + int rc2; + while( SQLITE_ROW==sqlite3_step(pScan) ){ + int i; + ctx.iRowid = sqlite3_column_int64(pScan, 0); + ctx.szCol = 0; + if( pConfig->bColumnsize ){ + rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize); + } + if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){ + rc = sqlite3Fts5TermsetNew(&ctx.pTermset); + } + for(i=0; rc==SQLITE_OK && inCol; i++){ + if( pConfig->abUnindexed[i] ) continue; + ctx.iCol = i; + ctx.szCol = 0; + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ + rc = sqlite3Fts5TermsetNew(&ctx.pTermset); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, + (const char*)sqlite3_column_text(pScan, i+1), + sqlite3_column_bytes(pScan, i+1), + (void*)&ctx, + fts5StorageIntegrityCallback + ); + } + if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){ + rc = FTS5_CORRUPT; + } + aTotalSize[i] += ctx.szCol; + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ + sqlite3Fts5TermsetFree(ctx.pTermset); + ctx.pTermset = 0; + } + } + sqlite3Fts5TermsetFree(ctx.pTermset); + ctx.pTermset = 0; + + if( rc!=SQLITE_OK ) break; + } + rc2 = sqlite3_reset(pScan); + if( rc==SQLITE_OK ) rc = rc2; + } + + /* Test that the "totals" (sometimes called "averages") record looks Ok */ + if( rc==SQLITE_OK ){ + int i; + rc = fts5StorageLoadTotals(p, 0); + for(i=0; rc==SQLITE_OK && inCol; i++){ + if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT; + } + } + + /* Check that the %_docsize and %_content tables contain the expected + ** number of rows. */ + if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ + i64 nRow = 0; + rc = fts5StorageCount(p, "content", &nRow); + if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; + } + if( rc==SQLITE_OK && pConfig->bColumnsize ){ + i64 nRow = 0; + rc = fts5StorageCount(p, "docsize", &nRow); + if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; } /* Pass the expected checksum down to the FTS index module. It will ** verify, amongst other things, that it matches the checksum generated by ** inspecting the index itself. */ if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum); + rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum); } sqlite3_free(aTotalSize); return rc; } @@ -257423,17 +201301,17 @@ /* ** Obtain an SQLite statement handle that may be used to read data from the ** %_content table. */ static int sqlite3Fts5StorageStmt( - Fts5Storage *p, - int eStmt, - sqlite3_stmt **pp, + Fts5Storage *p, + int eStmt, + sqlite3_stmt **pp, char **pzErrMsg ){ int rc; - assert( eStmt==FTS5_STMT_SCAN_ASC + assert( eStmt==FTS5_STMT_SCAN_ASC || eStmt==FTS5_STMT_SCAN_DESC || eStmt==FTS5_STMT_LOOKUP ); rc = fts5StorageGetStmt(p, eStmt, pp, pzErrMsg); if( rc==SQLITE_OK ){ @@ -257447,12 +201325,12 @@ ** Release an SQLite statement handle obtained via an earlier call to ** sqlite3Fts5StorageStmt(). The eStmt parameter passed to this function ** must match that passed to the sqlite3Fts5StorageStmt() call. */ static void sqlite3Fts5StorageStmtRelease( - Fts5Storage *p, - int eStmt, + Fts5Storage *p, + int eStmt, sqlite3_stmt *pStmt ){ assert( eStmt==FTS5_STMT_SCAN_ASC || eStmt==FTS5_STMT_SCAN_DESC || eStmt==FTS5_STMT_LOOKUP @@ -257491,13 +201369,12 @@ sqlite3_stmt *pLookup = 0; /* Statement to query %_docsize */ int rc; /* Return Code */ assert( p->pConfig->bColumnsize ); rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0); - if( pLookup ){ + if( rc==SQLITE_OK ){ int bCorrupt = 1; - assert( rc==SQLITE_OK ); sqlite3_bind_int64(pLookup, 1, iRowid); if( SQLITE_ROW==sqlite3_step(pLookup) ){ const u8 *aBlob = sqlite3_column_blob(pLookup, 0); int nBlob = sqlite3_column_bytes(pLookup, 0); if( 0==fts5StorageDecodeSizeArray(aCol, nCol, aBlob, nBlob) ){ @@ -257506,12 +201383,10 @@ } rc = sqlite3_reset(pLookup); if( bCorrupt && rc==SQLITE_OK ){ rc = FTS5_CORRUPT; } - }else{ - assert( rc!=SQLITE_OK ); } return rc; } @@ -257534,17 +201409,11 @@ } static int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){ int rc = fts5StorageLoadTotals(p, 0); if( rc==SQLITE_OK ){ - /* nTotalRow being zero does not necessarily indicate a corrupt - ** database - it might be that the FTS5 table really does contain zero - ** rows. However this function is only called from the xRowCount() API, - ** and there is no way for that API to be invoked if the table contains - ** no rows. Hence the FTS5_CORRUPT return. */ *pnRow = p->nTotalRow; - if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT; } return rc; } /* @@ -257553,13 +201422,11 @@ static int sqlite3Fts5StorageSync(Fts5Storage *p){ int rc = SQLITE_OK; i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); if( p->bTotalsValid ){ rc = fts5StorageSaveTotals(p); - if( rc==SQLITE_OK ){ - p->bTotalsValid = 0; - } + p->bTotalsValid = 0; } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IndexSync(p->pIndex); } sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid); @@ -257570,11 +201437,11 @@ p->bTotalsValid = 0; return sqlite3Fts5IndexRollback(p->pIndex); } static int sqlite3Fts5StorageConfigValue( - Fts5Storage *p, + Fts5Storage *p, const char *z, sqlite3_value *pVal, int iVal ){ sqlite3_stmt *pReplace = 0; @@ -257586,11 +201453,10 @@ }else{ sqlite3_bind_int(pReplace, 2, iVal); } sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 1); } if( rc==SQLITE_OK && pVal ){ int iNew = p->pConfig->iCookie + 1; rc = sqlite3Fts5IndexSetCookie(p->pIndex, iNew); if( rc==SQLITE_OK ){ @@ -257620,11 +201486,11 @@ ** Start of ascii tokenizer implementation. */ /* ** For tokenizers with no "unicode" modifier, the set of token characters -** is the same as the set of ASCII range alphanumeric characters. +** is the same as the set of ASCII range alphanumeric characters. */ static unsigned char aAsciiTokenChar[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00..0x0F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10..0x1F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20..0x2F */ @@ -257639,12 +201505,12 @@ struct AsciiTokenizer { unsigned char aTokenChar[128]; }; static void fts5AsciiAddExceptions( - AsciiTokenizer *p, - const char *zArg, + AsciiTokenizer *p, + const char *zArg, int bTokenChars ){ int i; for(i=0; zArg[i]; i++){ if( (zArg[i] & 0x80)==0 ){ @@ -257662,11 +201528,11 @@ /* ** Create an "ascii" tokenizer. */ static int fts5AsciiCreate( - void *pUnused, + void *pUnused, const char **azArg, int nArg, Fts5Tokenizer **ppOut ){ int rc = SQLITE_OK; AsciiTokenizer *p = 0; @@ -257752,11 +201618,11 @@ /* Fold to lower case */ nByte = ie-is; if( nByte>nFold ){ if( pFold!=aFold ) sqlite3_free(pFold); - pFold = sqlite3_malloc64((sqlite3_int64)nByte*2); + pFold = sqlite3_malloc(nByte*2); if( pFold==0 ){ rc = SQLITE_NOMEM; break; } nFold = nByte*2; @@ -257765,11 +201631,11 @@ /* Invoke the token callback */ rc = xToken(pCtx, 0, pFold, nByte, is, ie); is = ie+1; } - + if( pFold!=aFold ) sqlite3_free(pFold); if( rc==SQLITE_DONE ) rc = SQLITE_OK; return rc; } @@ -257798,11 +201664,11 @@ #define READ_UTF8(zIn, zTerm, c) \ c = *(zIn++); \ if( c>=0xc0 ){ \ c = sqlite3Utf8Trans1[c-0xc0]; \ - while( zIn=0xc0 ){ \ - while( (((unsigned char)*zIn) & 0xc0)==0x80 ){ zIn++; } \ - } \ -} - typedef struct Unicode61Tokenizer Unicode61Tokenizer; struct Unicode61Tokenizer { unsigned char aTokenChar[128]; /* ASCII range token characters */ char *aFold; /* Buffer to fold text into */ int nFold; /* Size of aFold[] in bytes */ - int eRemoveDiacritic; /* True if remove_diacritics=1 is set */ + int bRemoveDiacritic; /* True if remove_diacritics=1 is set */ int nException; int *aiException; - - unsigned char aCategory[32]; /* True for token char categories */ }; -/* Values for eRemoveDiacritic (must match internals of fts5_unicode2.c) */ -#define FTS5_REMOVE_DIACRITICS_NONE 0 -#define FTS5_REMOVE_DIACRITICS_SIMPLE 1 -#define FTS5_REMOVE_DIACRITICS_COMPLEX 2 - static int fts5UnicodeAddExceptions( Unicode61Tokenizer *p, /* Tokenizer object */ const char *z, /* Characters to treat as exceptions */ int bTokenChars /* 1 for 'tokenchars', 0 for 'separators' */ ){ @@ -257862,30 +201715,29 @@ int rc = SQLITE_OK; int n = (int)strlen(z); int *aNew; if( n>0 ){ - aNew = (int*)sqlite3_realloc64(p->aiException, - (n+p->nException)*sizeof(int)); + aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int)); if( aNew ){ int nNew = p->nException; const unsigned char *zCsr = (const unsigned char*)z; const unsigned char *zTerm = (const unsigned char*)&z[n]; while( zCsraTokenChar[iCode] = (unsigned char)bTokenChars; }else{ - bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]; - assert( (bToken==0 || bToken==1) ); + bToken = sqlite3Fts5UnicodeIsalnum(iCode); + assert( (bToken==0 || bToken==1) ); assert( (bTokenChars==0 || bTokenChars==1) ); if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){ int i; for(i=0; iiCode ) break; + if( aNew[i]>iCode ) break; } memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int)); aNew[i] = iCode; nNew++; } @@ -257936,85 +201788,50 @@ sqlite3_free(p); } return; } -static int unicodeSetCategories(Unicode61Tokenizer *p, const char *zCat){ - const char *z = zCat; - - while( *z ){ - while( *z==' ' || *z=='\t' ) z++; - if( *z && sqlite3Fts5UnicodeCatParse(z, p->aCategory) ){ - return SQLITE_ERROR; - } - while( *z!=' ' && *z!='\t' && *z!='\0' ) z++; - } - - sqlite3Fts5UnicodeAscii(p->aCategory, p->aTokenChar); - return SQLITE_OK; -} - /* ** Create a "unicode61" tokenizer. */ static int fts5UnicodeCreate( - void *pUnused, + void *pUnused, const char **azArg, int nArg, Fts5Tokenizer **ppOut ){ int rc = SQLITE_OK; /* Return code */ - Unicode61Tokenizer *p = 0; /* New tokenizer object */ + Unicode61Tokenizer *p = 0; /* New tokenizer object */ UNUSED_PARAM(pUnused); if( nArg%2 ){ rc = SQLITE_ERROR; }else{ p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); if( p ){ - const char *zCat = "L* N* Co"; int i; memset(p, 0, sizeof(Unicode61Tokenizer)); - - p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE; + memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar)); + p->bRemoveDiacritic = 1; p->nFold = 64; - p->aFold = sqlite3_malloc64(p->nFold * sizeof(char)); + p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); if( p->aFold==0 ){ rc = SQLITE_NOMEM; } - - /* Search for a "categories" argument */ - for(i=0; rc==SQLITE_OK && ieRemoveDiacritic = (zArg[0] - '0'); - assert( p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_NONE - || p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_SIMPLE - || p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_COMPLEX - ); } + p->bRemoveDiacritic = (zArg[0]=='1'); }else if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){ rc = fts5UnicodeAddExceptions(p, zArg, 1); }else if( 0==sqlite3_stricmp(azArg[i], "separators") ){ rc = fts5UnicodeAddExceptions(p, zArg, 0); - }else - if( 0==sqlite3_stricmp(azArg[i], "categories") ){ - /* no-op */ }else{ rc = SQLITE_ERROR; } } }else{ @@ -258029,18 +201846,16 @@ return rc; } /* ** Return true if, for the purposes of tokenizing with the tokenizer -** passed as the first argument, codepoint iCode is considered a token +** passed as the first argument, codepoint iCode is considered a token ** character (not a separator). */ static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){ - return ( - p->aCategory[sqlite3Fts5UnicodeCategory((u32)iCode)] - ^ fts5UnicodeIsException(p, iCode) - ); + assert( (sqlite3Fts5UnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); + return sqlite3Fts5UnicodeIsalnum(iCode) ^ fts5UnicodeIsException(p, iCode); } static int fts5UnicodeTokenize( Fts5Tokenizer *pTokenizer, void *pCtx, @@ -258063,11 +201878,11 @@ UNUSED_PARAM(iUnused); /* Each iteration of this loop gobbles up a contiguous run of separators, ** then the next token. */ while( rc==SQLITE_OK ){ - u32 iCode; /* non-ASCII codepoint read from input */ + int iCode; /* non-ASCII codepoint read from input */ char *zOut = aFold; int is; int ie; /* Skip any separator characters. */ @@ -258095,11 +201910,11 @@ while( zCsrpEnd ){ - aFold = sqlite3_malloc64((sqlite3_int64)nFold*2); + aFold = sqlite3_malloc(nFold*2); if( aFold==0 ){ rc = SQLITE_NOMEM; goto tokenize_done; } zOut = &aFold[zOut - p->aFold]; @@ -258114,18 +201929,18 @@ /* An non-ascii-range character. Fold it into the output buffer if ** it is a token character, or break out of the loop if it is not. */ READ_UTF8(zCsr, zTerm, iCode); if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){ non_ascii_tokenchar: - iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic); + iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic); if( iCode ) WRITE_UTF8(zOut, iCode); }else{ break; } }else if( a[*zCsr]==0 ){ /* An ascii-range separator character. End of token. */ - break; + break; }else{ ascii_tokenchar: if( *zCsr>='A' && *zCsr<='Z' ){ *zOut++ = *zCsr + 32; }else{ @@ -258135,13 +201950,13 @@ } ie = zCsr - (unsigned char*)pText; } /* Invoke the token callback */ - rc = xToken(pCtx, 0, aFold, zOut-aFold, is, ie); + rc = xToken(pCtx, 0, aFold, zOut-aFold, is, ie); } - + tokenize_done: if( rc==SQLITE_DONE ) rc = SQLITE_OK; return rc; } @@ -258153,11 +201968,11 @@ ** stemming. */ #define FTS5_PORTER_MAX_TOKEN 64 typedef struct PorterTokenizer PorterTokenizer; struct PorterTokenizer { - fts5_tokenizer_v2 tokenizer_v2; /* Parent tokenizer module */ + fts5_tokenizer tokenizer; /* Parent tokenizer module */ Fts5Tokenizer *pTokenizer; /* Parent tokenizer instance */ char aBuf[FTS5_PORTER_MAX_TOKEN + 64]; }; /* @@ -258165,47 +201980,45 @@ */ static void fts5PorterDelete(Fts5Tokenizer *pTok){ if( pTok ){ PorterTokenizer *p = (PorterTokenizer*)pTok; if( p->pTokenizer ){ - p->tokenizer_v2.xDelete(p->pTokenizer); + p->tokenizer.xDelete(p->pTokenizer); } sqlite3_free(p); } } /* ** Create a "porter" tokenizer. */ static int fts5PorterCreate( - void *pCtx, + void *pCtx, const char **azArg, int nArg, Fts5Tokenizer **ppOut ){ fts5_api *pApi = (fts5_api*)pCtx; int rc = SQLITE_OK; PorterTokenizer *pRet; void *pUserdata = 0; const char *zBase = "unicode61"; - fts5_tokenizer_v2 *pV2 = 0; if( nArg>0 ){ zBase = azArg[0]; } pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer)); if( pRet ){ memset(pRet, 0, sizeof(PorterTokenizer)); - rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2); + rc = pApi->xFindTokenizer(pApi, zBase, &pUserdata, &pRet->tokenizer); }else{ rc = SQLITE_NOMEM; } if( rc==SQLITE_OK ){ int nArg2 = (nArg>0 ? nArg-1 : 0); - const char **az2 = (nArg2 ? &azArg[1] : 0); - memcpy(&pRet->tokenizer_v2, pV2, sizeof(fts5_tokenizer_v2)); - rc = pRet->tokenizer_v2.xCreate(pUserdata, az2, nArg2, &pRet->pTokenizer); + const char **azArg2 = (nArg2 ? &azArg[1] : 0); + rc = pRet->tokenizer.xCreate(pUserdata, azArg2, nArg2, &pRet->pTokenizer); } if( rc!=SQLITE_OK ){ fts5PorterDelete((Fts5Tokenizer*)pRet); pRet = 0; @@ -258321,11 +202134,11 @@ } /* porter rule condition: (m > 1 and (*S or *T)) */ static int fts5Porter_MGt1_and_S_or_T(char *zStem, int nStem){ assert( nStem>0 ); - return (zStem[nStem-1]=='s' || zStem[nStem-1]=='t') + return (zStem[nStem-1]=='s' || zStem[nStem-1]=='t') && fts5Porter_MGt1(zStem, nStem); } /* porter rule condition: (*v*) */ static int fts5Porter_Vowel(char *zStem, int nStem){ @@ -258346,20 +202159,20 @@ static int fts5PorterStep4(char *aBuf, int *pnBuf){ int ret = 0; int nBuf = *pnBuf; switch( aBuf[nBuf-2] ){ - - case 'a': + + case 'a': if( nBuf>2 && 0==memcmp("al", &aBuf[nBuf-2], 2) ){ if( fts5Porter_MGt1(aBuf, nBuf-2) ){ *pnBuf = nBuf - 2; } } break; - - case 'c': + + case 'c': if( nBuf>4 && 0==memcmp("ance", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt1(aBuf, nBuf-4) ){ *pnBuf = nBuf - 4; } }else if( nBuf>4 && 0==memcmp("ence", &aBuf[nBuf-4], 4) ){ @@ -258366,28 +202179,28 @@ if( fts5Porter_MGt1(aBuf, nBuf-4) ){ *pnBuf = nBuf - 4; } } break; - - case 'e': + + case 'e': if( nBuf>2 && 0==memcmp("er", &aBuf[nBuf-2], 2) ){ if( fts5Porter_MGt1(aBuf, nBuf-2) ){ *pnBuf = nBuf - 2; } } break; - - case 'i': + + case 'i': if( nBuf>2 && 0==memcmp("ic", &aBuf[nBuf-2], 2) ){ if( fts5Porter_MGt1(aBuf, nBuf-2) ){ *pnBuf = nBuf - 2; } } break; - - case 'l': + + case 'l': if( nBuf>4 && 0==memcmp("able", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt1(aBuf, nBuf-4) ){ *pnBuf = nBuf - 4; } }else if( nBuf>4 && 0==memcmp("ible", &aBuf[nBuf-4], 4) ){ @@ -258394,12 +202207,12 @@ if( fts5Porter_MGt1(aBuf, nBuf-4) ){ *pnBuf = nBuf - 4; } } break; - - case 'n': + + case 'n': if( nBuf>3 && 0==memcmp("ant", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } }else if( nBuf>5 && 0==memcmp("ement", &aBuf[nBuf-5], 5) ){ @@ -258414,12 +202227,12 @@ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - - case 'o': + + case 'o': if( nBuf>3 && 0==memcmp("ion", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1_and_S_or_T(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } }else if( nBuf>2 && 0==memcmp("ou", &aBuf[nBuf-2], 2) ){ @@ -258426,20 +202239,20 @@ if( fts5Porter_MGt1(aBuf, nBuf-2) ){ *pnBuf = nBuf - 2; } } break; - - case 's': + + case 's': if( nBuf>3 && 0==memcmp("ism", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - - case 't': + + case 't': if( nBuf>3 && 0==memcmp("ate", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } }else if( nBuf>3 && 0==memcmp("iti", &aBuf[nBuf-3], 3) ){ @@ -258446,80 +202259,80 @@ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - - case 'u': + + case 'u': if( nBuf>3 && 0==memcmp("ous", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - - case 'v': + + case 'v': if( nBuf>3 && 0==memcmp("ive", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - - case 'z': + + case 'z': if( nBuf>3 && 0==memcmp("ize", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt1(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - + } return ret; } - + static int fts5PorterStep1B2(char *aBuf, int *pnBuf){ int ret = 0; int nBuf = *pnBuf; switch( aBuf[nBuf-2] ){ - - case 'a': + + case 'a': if( nBuf>2 && 0==memcmp("at", &aBuf[nBuf-2], 2) ){ memcpy(&aBuf[nBuf-2], "ate", 3); *pnBuf = nBuf - 2 + 3; ret = 1; } break; - - case 'b': + + case 'b': if( nBuf>2 && 0==memcmp("bl", &aBuf[nBuf-2], 2) ){ memcpy(&aBuf[nBuf-2], "ble", 3); *pnBuf = nBuf - 2 + 3; ret = 1; } break; - - case 'i': + + case 'i': if( nBuf>2 && 0==memcmp("iz", &aBuf[nBuf-2], 2) ){ memcpy(&aBuf[nBuf-2], "ize", 3); *pnBuf = nBuf - 2 + 3; ret = 1; } break; - + } return ret; } - + static int fts5PorterStep2(char *aBuf, int *pnBuf){ int ret = 0; int nBuf = *pnBuf; switch( aBuf[nBuf-2] ){ - - case 'a': + + case 'a': if( nBuf>7 && 0==memcmp("ational", &aBuf[nBuf-7], 7) ){ if( fts5Porter_MGt0(aBuf, nBuf-7) ){ memcpy(&aBuf[nBuf-7], "ate", 3); *pnBuf = nBuf - 7 + 3; } @@ -258528,12 +202341,12 @@ memcpy(&aBuf[nBuf-6], "tion", 4); *pnBuf = nBuf - 6 + 4; } } break; - - case 'c': + + case 'c': if( nBuf>4 && 0==memcmp("enci", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt0(aBuf, nBuf-4) ){ memcpy(&aBuf[nBuf-4], "ence", 4); *pnBuf = nBuf - 4 + 4; } @@ -258542,30 +202355,30 @@ memcpy(&aBuf[nBuf-4], "ance", 4); *pnBuf = nBuf - 4 + 4; } } break; - - case 'e': + + case 'e': if( nBuf>4 && 0==memcmp("izer", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt0(aBuf, nBuf-4) ){ memcpy(&aBuf[nBuf-4], "ize", 3); *pnBuf = nBuf - 4 + 3; } } break; - - case 'g': + + case 'g': if( nBuf>4 && 0==memcmp("logi", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt0(aBuf, nBuf-4) ){ memcpy(&aBuf[nBuf-4], "log", 3); *pnBuf = nBuf - 4 + 3; } } break; - - case 'l': + + case 'l': if( nBuf>3 && 0==memcmp("bli", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt0(aBuf, nBuf-3) ){ memcpy(&aBuf[nBuf-3], "ble", 3); *pnBuf = nBuf - 3 + 3; } @@ -258589,12 +202402,12 @@ memcpy(&aBuf[nBuf-5], "ous", 3); *pnBuf = nBuf - 5 + 3; } } break; - - case 'o': + + case 'o': if( nBuf>7 && 0==memcmp("ization", &aBuf[nBuf-7], 7) ){ if( fts5Porter_MGt0(aBuf, nBuf-7) ){ memcpy(&aBuf[nBuf-7], "ize", 3); *pnBuf = nBuf - 7 + 3; } @@ -258608,12 +202421,12 @@ memcpy(&aBuf[nBuf-4], "ate", 3); *pnBuf = nBuf - 4 + 3; } } break; - - case 's': + + case 's': if( nBuf>5 && 0==memcmp("alism", &aBuf[nBuf-5], 5) ){ if( fts5Porter_MGt0(aBuf, nBuf-5) ){ memcpy(&aBuf[nBuf-5], "al", 2); *pnBuf = nBuf - 5 + 2; } @@ -258632,12 +202445,12 @@ memcpy(&aBuf[nBuf-7], "ous", 3); *pnBuf = nBuf - 7 + 3; } } break; - - case 't': + + case 't': if( nBuf>5 && 0==memcmp("aliti", &aBuf[nBuf-5], 5) ){ if( fts5Porter_MGt0(aBuf, nBuf-5) ){ memcpy(&aBuf[nBuf-5], "al", 2); *pnBuf = nBuf - 5 + 2; } @@ -258651,39 +202464,39 @@ memcpy(&aBuf[nBuf-6], "ble", 3); *pnBuf = nBuf - 6 + 3; } } break; - + } return ret; } - + static int fts5PorterStep3(char *aBuf, int *pnBuf){ int ret = 0; int nBuf = *pnBuf; switch( aBuf[nBuf-2] ){ - - case 'a': + + case 'a': if( nBuf>4 && 0==memcmp("ical", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt0(aBuf, nBuf-4) ){ memcpy(&aBuf[nBuf-4], "ic", 2); *pnBuf = nBuf - 4 + 2; } } break; - - case 's': + + case 's': if( nBuf>4 && 0==memcmp("ness", &aBuf[nBuf-4], 4) ){ if( fts5Porter_MGt0(aBuf, nBuf-4) ){ *pnBuf = nBuf - 4; } } break; - - case 't': + + case 't': if( nBuf>5 && 0==memcmp("icate", &aBuf[nBuf-5], 5) ){ if( fts5Porter_MGt0(aBuf, nBuf-5) ){ memcpy(&aBuf[nBuf-5], "ic", 2); *pnBuf = nBuf - 5 + 2; } @@ -258692,47 +202505,47 @@ memcpy(&aBuf[nBuf-5], "ic", 2); *pnBuf = nBuf - 5 + 2; } } break; - - case 'u': + + case 'u': if( nBuf>3 && 0==memcmp("ful", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt0(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; } } break; - - case 'v': + + case 'v': if( nBuf>5 && 0==memcmp("ative", &aBuf[nBuf-5], 5) ){ if( fts5Porter_MGt0(aBuf, nBuf-5) ){ *pnBuf = nBuf - 5; } } break; - - case 'z': + + case 'z': if( nBuf>5 && 0==memcmp("alize", &aBuf[nBuf-5], 5) ){ if( fts5Porter_MGt0(aBuf, nBuf-5) ){ memcpy(&aBuf[nBuf-5], "al", 2); *pnBuf = nBuf - 5 + 2; } } break; - + } return ret; } - + static int fts5PorterStep1B(char *aBuf, int *pnBuf){ int ret = 0; int nBuf = *pnBuf; switch( aBuf[nBuf-2] ){ - - case 'e': + + case 'e': if( nBuf>3 && 0==memcmp("eed", &aBuf[nBuf-3], 3) ){ if( fts5Porter_MGt0(aBuf, nBuf-3) ){ memcpy(&aBuf[nBuf-3], "ee", 2); *pnBuf = nBuf - 3 + 2; } @@ -258741,34 +202554,34 @@ *pnBuf = nBuf - 2; ret = 1; } } break; - - case 'n': + + case 'n': if( nBuf>3 && 0==memcmp("ing", &aBuf[nBuf-3], 3) ){ if( fts5Porter_Vowel(aBuf, nBuf-3) ){ *pnBuf = nBuf - 3; ret = 1; } } break; - + } return ret; } - -/* + +/* ** GENERATED CODE ENDS HERE (mkportersteps.tcl) *************************************************************************** **************************************************************************/ static void fts5PorterStep1A(char *aBuf, int *pnBuf){ int nBuf = *pnBuf; if( aBuf[nBuf-1]=='s' ){ if( aBuf[nBuf-2]=='e' ){ - if( (nBuf>4 && aBuf[nBuf-4]=='s' && aBuf[nBuf-3]=='s') + if( (nBuf>4 && aBuf[nBuf-4]=='s' && aBuf[nBuf-3]=='s') || (nBuf>3 && aBuf[nBuf-3]=='i' ) ){ *pnBuf = nBuf-2; }else{ *pnBuf = nBuf-1; @@ -258779,15 +202592,15 @@ } } } static int fts5PorterCb( - void *pCtx, + void *pCtx, int tflags, - const char *pToken, - int nToken, - int iStart, + const char *pToken, + int nToken, + int iStart, int iEnd ){ PorterContext *p = (PorterContext*)pCtx; char *aBuf; @@ -258801,12 +202614,12 @@ /* Step 1. */ fts5PorterStep1A(aBuf, &nBuf); if( fts5PorterStep1B(aBuf, &nBuf) ){ if( fts5PorterStep1B2(aBuf, &nBuf)==0 ){ char c = aBuf[nBuf-1]; - if( fts5PorterIsVowel(c, 0)==0 - && c!='l' && c!='s' && c!='z' && c==aBuf[nBuf-2] + if( fts5PorterIsVowel(c, 0)==0 + && c!='l' && c!='s' && c!='z' && c==aBuf[nBuf-2] ){ nBuf--; }else if( fts5Porter_MEq1(aBuf, nBuf) && fts5Porter_Ostar(aBuf, nBuf) ){ aBuf[nBuf++] = 'e'; } @@ -258824,20 +202637,20 @@ fts5PorterStep4(aBuf, &nBuf); /* Step 5a. */ assert( nBuf>0 ); if( aBuf[nBuf-1]=='e' ){ - if( fts5Porter_MGt1(aBuf, nBuf-1) + if( fts5Porter_MGt1(aBuf, nBuf-1) || (fts5Porter_MEq1(aBuf, nBuf-1) && !fts5Porter_Ostar(aBuf, nBuf-1)) ){ nBuf--; } } /* Step 5b. */ - if( nBuf>1 && aBuf[nBuf-1]=='l' - && aBuf[nBuf-2]=='l' && fts5Porter_MGt1(aBuf, nBuf-1) + if( nBuf>1 && aBuf[nBuf-1]=='l' + && aBuf[nBuf-2]=='l' && fts5Porter_MGt1(aBuf, nBuf-1) ){ nBuf--; } return p->xToken(p->pCtx, tflags, aBuf, nBuf, iStart, iEnd); @@ -258852,205 +202665,21 @@ static int fts5PorterTokenize( Fts5Tokenizer *pTokenizer, void *pCtx, int flags, const char *pText, int nText, - const char *pLoc, int nLoc, int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) ){ PorterTokenizer *p = (PorterTokenizer*)pTokenizer; PorterContext sCtx; sCtx.xToken = xToken; sCtx.pCtx = pCtx; sCtx.aBuf = p->aBuf; - return p->tokenizer_v2.xTokenize( - p->pTokenizer, (void*)&sCtx, flags, pText, nText, pLoc, nLoc, fts5PorterCb + return p->tokenizer.xTokenize( + p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb ); } - -/************************************************************************** -** Start of trigram implementation. -*/ -typedef struct TrigramTokenizer TrigramTokenizer; -struct TrigramTokenizer { - int bFold; /* True to fold to lower-case */ - int iFoldParam; /* Parameter to pass to Fts5UnicodeFold() */ -}; - -/* -** Free a trigram tokenizer. -*/ -static void fts5TriDelete(Fts5Tokenizer *p){ - sqlite3_free(p); -} - -/* -** Allocate a trigram tokenizer. -*/ -static int fts5TriCreate( - void *pUnused, - const char **azArg, - int nArg, - Fts5Tokenizer **ppOut -){ - int rc = SQLITE_OK; - TrigramTokenizer *pNew = 0; - UNUSED_PARAM(pUnused); - if( nArg%2 ){ - rc = SQLITE_ERROR; - }else{ - int i; - pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew)); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - pNew->bFold = 1; - pNew->iFoldParam = 0; - - for(i=0; rc==SQLITE_OK && ibFold = (zArg[0]=='0'); - } - }else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){ - if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){ - rc = SQLITE_ERROR; - }else{ - pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0; - } - }else{ - rc = SQLITE_ERROR; - } - } - - if( pNew->iFoldParam!=0 && pNew->bFold==0 ){ - rc = SQLITE_ERROR; - } - - if( rc!=SQLITE_OK ){ - fts5TriDelete((Fts5Tokenizer*)pNew); - pNew = 0; - } - } - } - *ppOut = (Fts5Tokenizer*)pNew; - return rc; -} - -/* -** Trigram tokenizer tokenize routine. -*/ -static int fts5TriTokenize( - Fts5Tokenizer *pTok, - void *pCtx, - int unusedFlags, - const char *pText, int nText, - int (*xToken)(void*, int, const char*, int, int, int) -){ - TrigramTokenizer *p = (TrigramTokenizer*)pTok; - int rc = SQLITE_OK; - char aBuf[32]; - char *zOut = aBuf; - int ii; - const unsigned char *zIn = (const unsigned char*)pText; - const unsigned char *zEof = (zIn ? &zIn[nText] : 0); - u32 iCode = 0; - int aStart[3]; /* Input offset of each character in aBuf[] */ - - UNUSED_PARAM(unusedFlags); - - /* Populate aBuf[] with the characters for the first trigram. */ - for(ii=0; ii<3; ii++){ - do { - aStart[ii] = zIn - (const unsigned char*)pText; - if( zIn>=zEof ) return SQLITE_OK; - READ_UTF8(zIn, zEof, iCode); - if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam); - }while( iCode==0 ); - WRITE_UTF8(zOut, iCode); - } - - /* At the start of each iteration of this loop: - ** - ** aBuf: Contains 3 characters. The 3 characters of the next trigram. - ** zOut: Points to the byte following the last character in aBuf. - ** aStart[3]: Contains the byte offset in the input text corresponding - ** to the start of each of the three characters in the buffer. - */ - assert( zIn<=zEof ); - while( 1 ){ - int iNext; /* Start of character following current tri */ - const char *z1; - - /* Read characters from the input up until the first non-diacritic */ - do { - iNext = zIn - (const unsigned char*)pText; - if( zIn>=zEof ){ - iCode = 0; - break; - } - READ_UTF8(zIn, zEof, iCode); - if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam); - }while( iCode==0 ); - - /* Pass the current trigram back to fts5 */ - rc = xToken(pCtx, 0, aBuf, zOut-aBuf, aStart[0], iNext); - if( iCode==0 || rc!=SQLITE_OK ) break; - - /* Remove the first character from buffer aBuf[]. Append the character - ** with codepoint iCode. */ - z1 = aBuf; - FTS5_SKIP_UTF8(z1); - memmove(aBuf, z1, zOut - z1); - zOut -= (z1 - aBuf); - WRITE_UTF8(zOut, iCode); - - /* Update the aStart[] array */ - aStart[0] = aStart[1]; - aStart[1] = aStart[2]; - aStart[2] = iNext; - } - - return rc; -} - -/* -** Argument xCreate is a pointer to a constructor function for a tokenizer. -** pTok is a tokenizer previously created using the same method. This function -** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB -** indicating the style of pattern matching that the tokenizer can support. -** In practice, this is: -** -** "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB -** "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE -** all other tokenizers - FTS5_PATTERN_NONE -*/ -static int sqlite3Fts5TokenizerPattern( - int (*xCreate)(void*, const char**, int, Fts5Tokenizer**), - Fts5Tokenizer *pTok -){ - if( xCreate==fts5TriCreate ){ - TrigramTokenizer *p = (TrigramTokenizer*)pTok; - if( p->iFoldParam==0 ){ - return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB; - } - } - return FTS5_PATTERN_NONE; -} - -/* -** Return true if the tokenizer described by p->azArg[] is the trigram -** tokenizer. This tokenizer needs to be loaded before xBestIndex is -** called for the first time in order to correctly handle LIKE/GLOB. -*/ -static int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){ - return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram")); -} - /* ** Register all built-in tokenizers with FTS5. */ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){ @@ -259058,13 +202687,13 @@ const char *zName; fts5_tokenizer x; } aBuiltin[] = { { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}}, { "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }}, - { "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}}, + { "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }}, }; - + int rc = SQLITE_OK; /* Return code */ int i; /* To iterate through builtin functions */ for(i=0; rc==SQLITE_OK && ixCreateTokenizer(pApi, @@ -259072,29 +202701,18 @@ (void*)pApi, &aBuiltin[i].x, 0 ); } - if( rc==SQLITE_OK ){ - fts5_tokenizer_v2 sPorter = { - 2, - fts5PorterCreate, - fts5PorterDelete, - fts5PorterTokenize - }; - rc = pApi->xCreateTokenizer_v2(pApi, - "porter", - (void*)pApi, - &sPorter, - 0 - ); - } + return rc; } + + /* -** 2012-05-25 +** 2012 May 25 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. @@ -259109,10 +202727,139 @@ */ /* #include */ +/* +** Return true if the argument corresponds to a unicode codepoint +** classified as either a letter or a number. Otherwise false. +** +** The results are undefined if the value passed to this function +** is less than zero. +*/ +static int sqlite3Fts5UnicodeIsalnum(int c){ + /* Each unsigned integer in the following array corresponds to a contiguous + ** range of unicode codepoints that are not either letters or numbers (i.e. + ** codepoints for which this function should return 0). + ** + ** The most significant 22 bits in each 32-bit value contain the first + ** codepoint in the range. The least significant 10 bits are used to store + ** the size of the range (always at least 1). In other words, the value + ** ((C<<22) + N) represents a range of N codepoints starting with codepoint + ** C. It is not possible to represent a range larger than 1023 codepoints + ** using this format. + */ + static const unsigned int aEntry[] = { + 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, + 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, + 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, + 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, + 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, + 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, + 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, + 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, + 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, + 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, + 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, + 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, + 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, + 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, + 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, + 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, + 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, + 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, + 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, + 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, + 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, + 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, + 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, + 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, + 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, + 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, + 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, + 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, + 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, + 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, + 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, + 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, + 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, + 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, + 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, + 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, + 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, + 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, + 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, + 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, + 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, + 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, + 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, + 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, + 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, + 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, + 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, + 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, + 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, + 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, + 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, + 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, + 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, + 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, + 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, + 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, + 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, + 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, + 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, + 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, + 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, + 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, + 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, + 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, + 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, + 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, + 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, + 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, + 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, + 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, + 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, + 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, + 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, + 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, + 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, + 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, + 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, + 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, + 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, + 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, + 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, + 0x380400F0, + }; + static const unsigned int aAscii[4] = { + 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, + }; + + if( (unsigned int)c<128 ){ + return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); + }else if( (unsigned int)c<(1<<22) ){ + unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; + int iRes = 0; + int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; + int iLo = 0; + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( key >= aEntry[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + assert( aEntry[0]=aEntry[iRes] ); + return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); + } + return 1; +} /* ** If the argument is a codepoint corresponding to a lowercase letter ** in the ASCII range with a diacritic added, return the codepoint @@ -259119,52 +202866,36 @@ ** of the ASCII letter only. For example, if passed 235 - "LATIN ** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER ** E"). The resuls of passing a codepoint that corresponds to an ** uppercase letter are undefined. */ -static int fts5_remove_diacritic(int c, int bComplex){ +static int fts5_remove_diacritic(int c){ unsigned short aDia[] = { - 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, - 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, - 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, - 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, - 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896, - 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106, - 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344, - 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198, - 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468, - 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704, - 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914, - 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218, - 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554, - 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766, - 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118, - 63182, 63242, 63274, 63310, 63368, 63390, + 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, + 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, + 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, + 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, + 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928, + 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234, + 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504, + 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529, + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, + 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, + 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, + 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, + 62924, 63050, 63082, 63274, 63390, }; -#define HIBIT ((unsigned char)0x80) - unsigned char aChar[] = { - '\0', 'a', 'c', 'e', 'i', 'n', - 'o', 'u', 'y', 'y', 'a', 'c', - 'd', 'e', 'e', 'g', 'h', 'i', - 'j', 'k', 'l', 'n', 'o', 'r', - 's', 't', 'u', 'u', 'w', 'y', - 'z', 'o', 'u', 'a', 'i', 'o', - 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o', - 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a', - 'e', 'i', 'o', 'r', 'u', 's', - 't', 'h', 'a', 'e', 'o'|HIBIT, 'o', - 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', 'a', 'b', - 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT, - 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT, - 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n', - 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's', - 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w', - 'w', 'x', 'y', 'z', 'h', 't', - 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT, - 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT, - 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y', + char aChar[] = { + '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c', + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', + 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', + 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', + 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', + 'e', 'i', 'o', 'u', 'y', }; unsigned int key = (((unsigned int)c)<<3) | 0x00000007; int iRes = 0; int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; @@ -259177,12 +202908,11 @@ }else{ iHi = iTest-1; } } assert( key>=aDia[iRes] ); - if( bComplex==0 && (aChar[iRes] & 0x80) ) return c; - return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F); + return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]); } /* ** Return true if the argument interpreted as a unicode codepoint @@ -259191,12 +202921,12 @@ static int sqlite3Fts5UnicodeIsdiacritic(int c){ unsigned int mask0 = 0x08029FDF; unsigned int mask1 = 0x000361F8; if( c<768 || c>817 ) return 0; return (c < 768+32) ? - (mask0 & ((unsigned int)1 << (c-768))) : - (mask1 & ((unsigned int)1 << (c-768-32))); + (mask0 & (1 << (c-768))) : + (mask1 & (1 << (c-768-32))); } /* ** Interpret the argument as a unicode codepoint. If the codepoint @@ -259205,11 +202935,11 @@ ** Otherwise, return a copy of the argument. ** ** The results are undefined if the value passed to this function ** is less than zero. */ -static int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){ +static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){ /* Each entry in the following array defines a rule for folding a range ** of codepoints to lower case. The rule applies to a range of nRange ** codepoints starting at codepoint iCode. ** ** If the least significant bit in flags is clear, then the rule applies @@ -259282,23 +203012,23 @@ {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, - {65313, 14, 26}, + {65313, 14, 26}, }; static const unsigned short aiOff[] = { - 1, 2, 8, 15, 16, 26, 28, 32, - 37, 38, 40, 48, 63, 64, 69, 71, - 79, 80, 116, 202, 203, 205, 206, 207, - 209, 210, 211, 213, 214, 217, 218, 219, - 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, - 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, - 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, - 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, - 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, - 65514, 65521, 65527, 65528, 65529, + 1, 2, 8, 15, 16, 26, 28, 32, + 37, 38, 40, 48, 63, 64, 69, 71, + 79, 80, 116, 202, 203, 205, 206, 207, + 209, 210, 211, 213, 214, 217, 218, 219, + 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, + 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, + 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, + 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, + 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, + 65514, 65521, 65527, 65528, 65529, }; int ret = c; assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); @@ -259328,552 +203058,19 @@ if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; assert( ret>0 ); } - if( eRemoveDiacritic ){ - ret = fts5_remove_diacritic(ret, eRemoveDiacritic==2); - } + if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret); } - + else if( c>=66560 && c<66600 ){ ret = c + 40; } return ret; } - - -static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ - aArray[0] = 1; - switch( zCat[0] ){ - case 'C': - switch( zCat[1] ){ - case 'c': aArray[1] = 1; break; - case 'f': aArray[2] = 1; break; - case 'n': aArray[3] = 1; break; - case 's': aArray[4] = 1; break; - case 'o': aArray[31] = 1; break; - case '*': - aArray[1] = 1; - aArray[2] = 1; - aArray[3] = 1; - aArray[4] = 1; - aArray[31] = 1; - break; - default: return 1; } - break; - - case 'L': - switch( zCat[1] ){ - case 'l': aArray[5] = 1; break; - case 'm': aArray[6] = 1; break; - case 'o': aArray[7] = 1; break; - case 't': aArray[8] = 1; break; - case 'u': aArray[9] = 1; break; - case 'C': aArray[30] = 1; break; - case '*': - aArray[5] = 1; - aArray[6] = 1; - aArray[7] = 1; - aArray[8] = 1; - aArray[9] = 1; - aArray[30] = 1; - break; - default: return 1; } - break; - - case 'M': - switch( zCat[1] ){ - case 'c': aArray[10] = 1; break; - case 'e': aArray[11] = 1; break; - case 'n': aArray[12] = 1; break; - case '*': - aArray[10] = 1; - aArray[11] = 1; - aArray[12] = 1; - break; - default: return 1; } - break; - - case 'N': - switch( zCat[1] ){ - case 'd': aArray[13] = 1; break; - case 'l': aArray[14] = 1; break; - case 'o': aArray[15] = 1; break; - case '*': - aArray[13] = 1; - aArray[14] = 1; - aArray[15] = 1; - break; - default: return 1; } - break; - - case 'P': - switch( zCat[1] ){ - case 'c': aArray[16] = 1; break; - case 'd': aArray[17] = 1; break; - case 'e': aArray[18] = 1; break; - case 'f': aArray[19] = 1; break; - case 'i': aArray[20] = 1; break; - case 'o': aArray[21] = 1; break; - case 's': aArray[22] = 1; break; - case '*': - aArray[16] = 1; - aArray[17] = 1; - aArray[18] = 1; - aArray[19] = 1; - aArray[20] = 1; - aArray[21] = 1; - aArray[22] = 1; - break; - default: return 1; } - break; - - case 'S': - switch( zCat[1] ){ - case 'c': aArray[23] = 1; break; - case 'k': aArray[24] = 1; break; - case 'm': aArray[25] = 1; break; - case 'o': aArray[26] = 1; break; - case '*': - aArray[23] = 1; - aArray[24] = 1; - aArray[25] = 1; - aArray[26] = 1; - break; - default: return 1; } - break; - - case 'Z': - switch( zCat[1] ){ - case 'l': aArray[27] = 1; break; - case 'p': aArray[28] = 1; break; - case 's': aArray[29] = 1; break; - case '*': - aArray[27] = 1; - aArray[28] = 1; - aArray[29] = 1; - break; - default: return 1; } - break; - - - default: - return 1; - } - return 0; -} - -static u16 aFts5UnicodeBlock[] = { - 0, 1471, 1753, 1760, 1760, 1760, 1760, 1760, 1760, 1760, - 1760, 1760, 1760, 1760, 1760, 1763, 1765, - }; -static u16 aFts5UnicodeMap[] = { - 0, 32, 33, 36, 37, 40, 41, 42, 43, 44, - 45, 46, 48, 58, 60, 63, 65, 91, 92, 93, - 94, 95, 96, 97, 123, 124, 125, 126, 127, 160, - 161, 162, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 180, 181, 182, 184, 185, - 186, 187, 188, 191, 192, 215, 216, 223, 247, 248, - 256, 312, 313, 329, 330, 377, 383, 385, 387, 388, - 391, 394, 396, 398, 402, 403, 405, 406, 409, 412, - 414, 415, 417, 418, 423, 427, 428, 431, 434, 436, - 437, 440, 442, 443, 444, 446, 448, 452, 453, 454, - 455, 456, 457, 458, 459, 460, 461, 477, 478, 496, - 497, 498, 499, 500, 503, 505, 506, 564, 570, 572, - 573, 575, 577, 580, 583, 584, 592, 660, 661, 688, - 706, 710, 722, 736, 741, 748, 749, 750, 751, 768, - 880, 884, 885, 886, 890, 891, 894, 900, 902, 903, - 904, 908, 910, 912, 913, 931, 940, 975, 977, 978, - 981, 984, 1008, 1012, 1014, 1015, 1018, 1020, 1021, 1072, - 1120, 1154, 1155, 1160, 1162, 1217, 1231, 1232, 1329, 1369, - 1370, 1377, 1417, 1418, 1423, 1425, 1470, 1471, 1472, 1473, - 1475, 1476, 1478, 1479, 1488, 1520, 1523, 1536, 1542, 1545, - 1547, 1548, 1550, 1552, 1563, 1566, 1568, 1600, 1601, 1611, - 1632, 1642, 1646, 1648, 1649, 1748, 1749, 1750, 1757, 1758, - 1759, 1765, 1767, 1769, 1770, 1774, 1776, 1786, 1789, 1791, - 1792, 1807, 1808, 1809, 1810, 1840, 1869, 1958, 1969, 1984, - 1994, 2027, 2036, 2038, 2039, 2042, 2048, 2070, 2074, 2075, - 2084, 2085, 2088, 2089, 2096, 2112, 2137, 2142, 2208, 2210, - 2276, 2304, 2307, 2308, 2362, 2363, 2364, 2365, 2366, 2369, - 2377, 2381, 2382, 2384, 2385, 2392, 2402, 2404, 2406, 2416, - 2417, 2418, 2425, 2433, 2434, 2437, 2447, 2451, 2474, 2482, - 2486, 2492, 2493, 2494, 2497, 2503, 2507, 2509, 2510, 2519, - 2524, 2527, 2530, 2534, 2544, 2546, 2548, 2554, 2555, 2561, - 2563, 2565, 2575, 2579, 2602, 2610, 2613, 2616, 2620, 2622, - 2625, 2631, 2635, 2641, 2649, 2654, 2662, 2672, 2674, 2677, - 2689, 2691, 2693, 2703, 2707, 2730, 2738, 2741, 2748, 2749, - 2750, 2753, 2759, 2761, 2763, 2765, 2768, 2784, 2786, 2790, - 2800, 2801, 2817, 2818, 2821, 2831, 2835, 2858, 2866, 2869, - 2876, 2877, 2878, 2879, 2880, 2881, 2887, 2891, 2893, 2902, - 2903, 2908, 2911, 2914, 2918, 2928, 2929, 2930, 2946, 2947, - 2949, 2958, 2962, 2969, 2972, 2974, 2979, 2984, 2990, 3006, - 3008, 3009, 3014, 3018, 3021, 3024, 3031, 3046, 3056, 3059, - 3065, 3066, 3073, 3077, 3086, 3090, 3114, 3125, 3133, 3134, - 3137, 3142, 3146, 3157, 3160, 3168, 3170, 3174, 3192, 3199, - 3202, 3205, 3214, 3218, 3242, 3253, 3260, 3261, 3262, 3263, - 3264, 3270, 3271, 3274, 3276, 3285, 3294, 3296, 3298, 3302, - 3313, 3330, 3333, 3342, 3346, 3389, 3390, 3393, 3398, 3402, - 3405, 3406, 3415, 3424, 3426, 3430, 3440, 3449, 3450, 3458, - 3461, 3482, 3507, 3517, 3520, 3530, 3535, 3538, 3542, 3544, - 3570, 3572, 3585, 3633, 3634, 3636, 3647, 3648, 3654, 3655, - 3663, 3664, 3674, 3713, 3716, 3719, 3722, 3725, 3732, 3737, - 3745, 3749, 3751, 3754, 3757, 3761, 3762, 3764, 3771, 3773, - 3776, 3782, 3784, 3792, 3804, 3840, 3841, 3844, 3859, 3860, - 3861, 3864, 3866, 3872, 3882, 3892, 3893, 3894, 3895, 3896, - 3897, 3898, 3899, 3900, 3901, 3902, 3904, 3913, 3953, 3967, - 3968, 3973, 3974, 3976, 3981, 3993, 4030, 4038, 4039, 4046, - 4048, 4053, 4057, 4096, 4139, 4141, 4145, 4146, 4152, 4153, - 4155, 4157, 4159, 4160, 4170, 4176, 4182, 4184, 4186, 4190, - 4193, 4194, 4197, 4199, 4206, 4209, 4213, 4226, 4227, 4229, - 4231, 4237, 4238, 4239, 4240, 4250, 4253, 4254, 4256, 4295, - 4301, 4304, 4347, 4348, 4349, 4682, 4688, 4696, 4698, 4704, - 4746, 4752, 4786, 4792, 4800, 4802, 4808, 4824, 4882, 4888, - 4957, 4960, 4969, 4992, 5008, 5024, 5120, 5121, 5741, 5743, - 5760, 5761, 5787, 5788, 5792, 5867, 5870, 5888, 5902, 5906, - 5920, 5938, 5941, 5952, 5970, 5984, 5998, 6002, 6016, 6068, - 6070, 6071, 6078, 6086, 6087, 6089, 6100, 6103, 6104, 6107, - 6108, 6109, 6112, 6128, 6144, 6150, 6151, 6155, 6158, 6160, - 6176, 6211, 6212, 6272, 6313, 6314, 6320, 6400, 6432, 6435, - 6439, 6441, 6448, 6450, 6451, 6457, 6464, 6468, 6470, 6480, - 6512, 6528, 6576, 6593, 6600, 6608, 6618, 6622, 6656, 6679, - 6681, 6686, 6688, 6741, 6742, 6743, 6744, 6752, 6753, 6754, - 6755, 6757, 6765, 6771, 6783, 6784, 6800, 6816, 6823, 6824, - 6912, 6916, 6917, 6964, 6965, 6966, 6971, 6972, 6973, 6978, - 6979, 6981, 6992, 7002, 7009, 7019, 7028, 7040, 7042, 7043, - 7073, 7074, 7078, 7080, 7082, 7083, 7084, 7086, 7088, 7098, - 7142, 7143, 7144, 7146, 7149, 7150, 7151, 7154, 7164, 7168, - 7204, 7212, 7220, 7222, 7227, 7232, 7245, 7248, 7258, 7288, - 7294, 7360, 7376, 7379, 7380, 7393, 7394, 7401, 7405, 7406, - 7410, 7412, 7413, 7424, 7468, 7531, 7544, 7545, 7579, 7616, - 7676, 7680, 7830, 7838, 7936, 7944, 7952, 7960, 7968, 7976, - 7984, 7992, 8000, 8008, 8016, 8025, 8027, 8029, 8031, 8033, - 8040, 8048, 8064, 8072, 8080, 8088, 8096, 8104, 8112, 8118, - 8120, 8124, 8125, 8126, 8127, 8130, 8134, 8136, 8140, 8141, - 8144, 8150, 8152, 8157, 8160, 8168, 8173, 8178, 8182, 8184, - 8188, 8189, 8192, 8203, 8208, 8214, 8216, 8217, 8218, 8219, - 8221, 8222, 8223, 8224, 8232, 8233, 8234, 8239, 8240, 8249, - 8250, 8251, 8255, 8257, 8260, 8261, 8262, 8263, 8274, 8275, - 8276, 8277, 8287, 8288, 8298, 8304, 8305, 8308, 8314, 8317, - 8318, 8319, 8320, 8330, 8333, 8334, 8336, 8352, 8400, 8413, - 8417, 8418, 8421, 8448, 8450, 8451, 8455, 8456, 8458, 8459, - 8462, 8464, 8467, 8468, 8469, 8470, 8472, 8473, 8478, 8484, - 8485, 8486, 8487, 8488, 8489, 8490, 8494, 8495, 8496, 8500, - 8501, 8505, 8506, 8508, 8510, 8512, 8517, 8519, 8522, 8523, - 8524, 8526, 8527, 8528, 8544, 8579, 8581, 8585, 8592, 8597, - 8602, 8604, 8608, 8609, 8611, 8612, 8614, 8615, 8622, 8623, - 8654, 8656, 8658, 8659, 8660, 8661, 8692, 8960, 8968, 8972, - 8992, 8994, 9001, 9002, 9003, 9084, 9085, 9115, 9140, 9180, - 9186, 9216, 9280, 9312, 9372, 9450, 9472, 9655, 9656, 9665, - 9666, 9720, 9728, 9839, 9840, 9985, 10088, 10089, 10090, 10091, - 10092, 10093, 10094, 10095, 10096, 10097, 10098, 10099, 10100, 10101, - 10102, 10132, 10176, 10181, 10182, 10183, 10214, 10215, 10216, 10217, - 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10240, 10496, 10627, - 10628, 10629, 10630, 10631, 10632, 10633, 10634, 10635, 10636, 10637, - 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647, - 10648, 10649, 10712, 10713, 10714, 10715, 10716, 10748, 10749, 10750, - 11008, 11056, 11077, 11079, 11088, 11264, 11312, 11360, 11363, 11365, - 11367, 11374, 11377, 11378, 11380, 11381, 11383, 11388, 11390, 11393, - 11394, 11492, 11493, 11499, 11503, 11506, 11513, 11517, 11518, 11520, - 11559, 11565, 11568, 11631, 11632, 11647, 11648, 11680, 11688, 11696, - 11704, 11712, 11720, 11728, 11736, 11744, 11776, 11778, 11779, 11780, - 11781, 11782, 11785, 11786, 11787, 11788, 11789, 11790, 11799, 11800, - 11802, 11803, 11804, 11805, 11806, 11808, 11809, 11810, 11811, 11812, - 11813, 11814, 11815, 11816, 11817, 11818, 11823, 11824, 11834, 11904, - 11931, 12032, 12272, 12288, 12289, 12292, 12293, 12294, 12295, 12296, - 12297, 12298, 12299, 12300, 12301, 12302, 12303, 12304, 12305, 12306, - 12308, 12309, 12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317, - 12318, 12320, 12321, 12330, 12334, 12336, 12337, 12342, 12344, 12347, - 12348, 12349, 12350, 12353, 12441, 12443, 12445, 12447, 12448, 12449, - 12539, 12540, 12543, 12549, 12593, 12688, 12690, 12694, 12704, 12736, - 12784, 12800, 12832, 12842, 12872, 12880, 12881, 12896, 12928, 12938, - 12977, 12992, 13056, 13312, 19893, 19904, 19968, 40908, 40960, 40981, - 40982, 42128, 42192, 42232, 42238, 42240, 42508, 42509, 42512, 42528, - 42538, 42560, 42606, 42607, 42608, 42611, 42612, 42622, 42623, 42624, - 42655, 42656, 42726, 42736, 42738, 42752, 42775, 42784, 42786, 42800, - 42802, 42864, 42865, 42873, 42878, 42888, 42889, 42891, 42896, 42912, - 43000, 43002, 43003, 43010, 43011, 43014, 43015, 43019, 43020, 43043, - 43045, 43047, 43048, 43056, 43062, 43064, 43065, 43072, 43124, 43136, - 43138, 43188, 43204, 43214, 43216, 43232, 43250, 43256, 43259, 43264, - 43274, 43302, 43310, 43312, 43335, 43346, 43359, 43360, 43392, 43395, - 43396, 43443, 43444, 43446, 43450, 43452, 43453, 43457, 43471, 43472, - 43486, 43520, 43561, 43567, 43569, 43571, 43573, 43584, 43587, 43588, - 43596, 43597, 43600, 43612, 43616, 43632, 43633, 43639, 43642, 43643, - 43648, 43696, 43697, 43698, 43701, 43703, 43705, 43710, 43712, 43713, - 43714, 43739, 43741, 43742, 43744, 43755, 43756, 43758, 43760, 43762, - 43763, 43765, 43766, 43777, 43785, 43793, 43808, 43816, 43968, 44003, - 44005, 44006, 44008, 44009, 44011, 44012, 44013, 44016, 44032, 55203, - 55216, 55243, 55296, 56191, 56319, 57343, 57344, 63743, 63744, 64112, - 64256, 64275, 64285, 64286, 64287, 64297, 64298, 64312, 64318, 64320, - 64323, 64326, 64434, 64467, 64830, 64831, 64848, 64914, 65008, 65020, - 65021, 65024, 65040, 65047, 65048, 65049, 65056, 65072, 65073, 65075, - 65077, 65078, 65079, 65080, 65081, 65082, 65083, 65084, 65085, 65086, - 65087, 65088, 65089, 65090, 65091, 65092, 65093, 65095, 65096, 65097, - 65101, 65104, 65108, 65112, 65113, 65114, 65115, 65116, 65117, 65118, - 65119, 65122, 65123, 65124, 65128, 65129, 65130, 65136, 65142, 65279, - 65281, 65284, 65285, 65288, 65289, 65290, 65291, 65292, 65293, 65294, - 65296, 65306, 65308, 65311, 65313, 65339, 65340, 65341, 65342, 65343, - 65344, 65345, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378, - 65379, 65380, 65382, 65392, 65393, 65438, 65440, 65474, 65482, 65490, - 65498, 65504, 65506, 65507, 65508, 65509, 65512, 65513, 65517, 65529, - 65532, 0, 13, 40, 60, 63, 80, 128, 256, 263, - 311, 320, 373, 377, 394, 400, 464, 509, 640, 672, - 768, 800, 816, 833, 834, 842, 896, 927, 928, 968, - 976, 977, 1024, 1064, 1104, 1184, 2048, 2056, 2058, 2103, - 2108, 2111, 2135, 2136, 2304, 2326, 2335, 2336, 2367, 2432, - 2494, 2560, 2561, 2565, 2572, 2576, 2581, 2585, 2616, 2623, - 2624, 2640, 2656, 2685, 2687, 2816, 2873, 2880, 2904, 2912, - 2936, 3072, 3680, 4096, 4097, 4098, 4099, 4152, 4167, 4178, - 4198, 4224, 4226, 4227, 4272, 4275, 4279, 4281, 4283, 4285, - 4286, 4304, 4336, 4352, 4355, 4391, 4396, 4397, 4406, 4416, - 4480, 4482, 4483, 4531, 4534, 4543, 4545, 4549, 4560, 5760, - 5803, 5804, 5805, 5806, 5808, 5814, 5815, 5824, 8192, 9216, - 9328, 12288, 26624, 28416, 28496, 28497, 28559, 28563, 45056, 53248, - 53504, 53545, 53605, 53607, 53610, 53613, 53619, 53627, 53635, 53637, - 53644, 53674, 53678, 53760, 53826, 53829, 54016, 54112, 54272, 54298, - 54324, 54350, 54358, 54376, 54402, 54428, 54430, 54434, 54437, 54441, - 54446, 54454, 54459, 54461, 54469, 54480, 54506, 54532, 54535, 54541, - 54550, 54558, 54584, 54587, 54592, 54598, 54602, 54610, 54636, 54662, - 54688, 54714, 54740, 54766, 54792, 54818, 54844, 54870, 54896, 54922, - 54952, 54977, 54978, 55003, 55004, 55010, 55035, 55036, 55061, 55062, - 55068, 55093, 55094, 55119, 55120, 55126, 55151, 55152, 55177, 55178, - 55184, 55209, 55210, 55235, 55236, 55242, 55246, 60928, 60933, 60961, - 60964, 60967, 60969, 60980, 60985, 60987, 60994, 60999, 61001, 61003, - 61005, 61009, 61012, 61015, 61017, 61019, 61021, 61023, 61025, 61028, - 61031, 61036, 61044, 61049, 61054, 61056, 61067, 61089, 61093, 61099, - 61168, 61440, 61488, 61600, 61617, 61633, 61649, 61696, 61712, 61744, - 61808, 61926, 61968, 62016, 62032, 62208, 62256, 62263, 62336, 62368, - 62406, 62432, 62464, 62528, 62530, 62713, 62720, 62784, 62800, 62971, - 63045, 63104, 63232, 0, 42710, 42752, 46900, 46912, 47133, 63488, - 1, 32, 256, 0, 65533, - }; -static u16 aFts5UnicodeData[] = { - 1025, 61, 117, 55, 117, 54, 50, 53, 57, 53, - 49, 85, 333, 85, 121, 85, 841, 54, 53, 50, - 56, 48, 56, 837, 54, 57, 50, 57, 1057, 61, - 53, 151, 58, 53, 56, 58, 39, 52, 57, 34, - 58, 56, 58, 57, 79, 56, 37, 85, 56, 47, - 39, 51, 111, 53, 745, 57, 233, 773, 57, 261, - 1822, 37, 542, 37, 1534, 222, 69, 73, 37, 126, - 126, 73, 69, 137, 37, 73, 37, 105, 101, 73, - 37, 73, 37, 190, 158, 37, 126, 126, 73, 37, - 126, 94, 37, 39, 94, 69, 135, 41, 40, 37, - 41, 40, 37, 41, 40, 37, 542, 37, 606, 37, - 41, 40, 37, 126, 73, 37, 1886, 197, 73, 37, - 73, 69, 126, 105, 37, 286, 2181, 39, 869, 582, - 152, 390, 472, 166, 248, 38, 56, 38, 568, 3596, - 158, 38, 56, 94, 38, 101, 53, 88, 41, 53, - 105, 41, 73, 37, 553, 297, 1125, 94, 37, 105, - 101, 798, 133, 94, 57, 126, 94, 37, 1641, 1541, - 1118, 58, 172, 75, 1790, 478, 37, 2846, 1225, 38, - 213, 1253, 53, 49, 55, 1452, 49, 44, 53, 76, - 53, 76, 53, 44, 871, 103, 85, 162, 121, 85, - 55, 85, 90, 364, 53, 85, 1031, 38, 327, 684, - 333, 149, 71, 44, 3175, 53, 39, 236, 34, 58, - 204, 70, 76, 58, 140, 71, 333, 103, 90, 39, - 469, 34, 39, 44, 967, 876, 2855, 364, 39, 333, - 1063, 300, 70, 58, 117, 38, 711, 140, 38, 300, - 38, 108, 38, 172, 501, 807, 108, 53, 39, 359, - 876, 108, 42, 1735, 44, 42, 44, 39, 106, 268, - 138, 44, 74, 39, 236, 327, 76, 85, 333, 53, - 38, 199, 231, 44, 74, 263, 71, 711, 231, 39, - 135, 44, 39, 106, 140, 74, 74, 44, 39, 42, - 71, 103, 76, 333, 71, 87, 207, 58, 55, 76, - 42, 199, 71, 711, 231, 71, 71, 71, 44, 106, - 76, 76, 108, 44, 135, 39, 333, 76, 103, 44, - 76, 42, 295, 103, 711, 231, 71, 167, 44, 39, - 106, 172, 76, 42, 74, 44, 39, 71, 76, 333, - 53, 55, 44, 74, 263, 71, 711, 231, 71, 167, - 44, 39, 42, 44, 42, 140, 74, 74, 44, 44, - 42, 71, 103, 76, 333, 58, 39, 207, 44, 39, - 199, 103, 135, 71, 39, 71, 71, 103, 391, 74, - 44, 74, 106, 106, 44, 39, 42, 333, 111, 218, - 55, 58, 106, 263, 103, 743, 327, 167, 39, 108, - 138, 108, 140, 76, 71, 71, 76, 333, 239, 58, - 74, 263, 103, 743, 327, 167, 44, 39, 42, 44, - 170, 44, 74, 74, 76, 74, 39, 71, 76, 333, - 71, 74, 263, 103, 1319, 39, 106, 140, 106, 106, - 44, 39, 42, 71, 76, 333, 207, 58, 199, 74, - 583, 775, 295, 39, 231, 44, 106, 108, 44, 266, - 74, 53, 1543, 44, 71, 236, 55, 199, 38, 268, - 53, 333, 85, 71, 39, 71, 39, 39, 135, 231, - 103, 39, 39, 71, 135, 44, 71, 204, 76, 39, - 167, 38, 204, 333, 135, 39, 122, 501, 58, 53, - 122, 76, 218, 333, 335, 58, 44, 58, 44, 58, - 44, 54, 50, 54, 50, 74, 263, 1159, 460, 42, - 172, 53, 76, 167, 364, 1164, 282, 44, 218, 90, - 181, 154, 85, 1383, 74, 140, 42, 204, 42, 76, - 74, 76, 39, 333, 213, 199, 74, 76, 135, 108, - 39, 106, 71, 234, 103, 140, 423, 44, 74, 76, - 202, 44, 39, 42, 333, 106, 44, 90, 1225, 41, - 41, 1383, 53, 38, 10631, 135, 231, 39, 135, 1319, - 135, 1063, 135, 231, 39, 135, 487, 1831, 135, 2151, - 108, 309, 655, 519, 346, 2727, 49, 19847, 85, 551, - 61, 839, 54, 50, 2407, 117, 110, 423, 135, 108, - 583, 108, 85, 583, 76, 423, 103, 76, 1671, 76, - 42, 236, 266, 44, 74, 364, 117, 38, 117, 55, - 39, 44, 333, 335, 213, 49, 149, 108, 61, 333, - 1127, 38, 1671, 1319, 44, 39, 2247, 935, 108, 138, - 76, 106, 74, 44, 202, 108, 58, 85, 333, 967, - 167, 1415, 554, 231, 74, 333, 47, 1114, 743, 76, - 106, 85, 1703, 42, 44, 42, 236, 44, 42, 44, - 74, 268, 202, 332, 44, 333, 333, 245, 38, 213, - 140, 42, 1511, 44, 42, 172, 42, 44, 170, 44, - 74, 231, 333, 245, 346, 300, 314, 76, 42, 967, - 42, 140, 74, 76, 42, 44, 74, 71, 333, 1415, - 44, 42, 76, 106, 44, 42, 108, 74, 149, 1159, - 266, 268, 74, 76, 181, 333, 103, 333, 967, 198, - 85, 277, 108, 53, 428, 42, 236, 135, 44, 135, - 74, 44, 71, 1413, 2022, 421, 38, 1093, 1190, 1260, - 140, 4830, 261, 3166, 261, 265, 197, 201, 261, 265, - 261, 265, 197, 201, 261, 41, 41, 41, 94, 229, - 265, 453, 261, 264, 261, 264, 261, 264, 165, 69, - 137, 40, 56, 37, 120, 101, 69, 137, 40, 120, - 133, 69, 137, 120, 261, 169, 120, 101, 69, 137, - 40, 88, 381, 162, 209, 85, 52, 51, 54, 84, - 51, 54, 52, 277, 59, 60, 162, 61, 309, 52, - 51, 149, 80, 117, 57, 54, 50, 373, 57, 53, - 48, 341, 61, 162, 194, 47, 38, 207, 121, 54, - 50, 38, 335, 121, 54, 50, 422, 855, 428, 139, - 44, 107, 396, 90, 41, 154, 41, 90, 37, 105, - 69, 105, 37, 58, 41, 90, 57, 169, 218, 41, - 58, 41, 58, 41, 58, 137, 58, 37, 137, 37, - 135, 37, 90, 69, 73, 185, 94, 101, 58, 57, - 90, 37, 58, 527, 1134, 94, 142, 47, 185, 186, - 89, 154, 57, 90, 57, 90, 57, 250, 57, 1018, - 89, 90, 57, 58, 57, 1018, 8601, 282, 153, 666, - 89, 250, 54, 50, 2618, 57, 986, 825, 1306, 217, - 602, 1274, 378, 1935, 2522, 719, 5882, 57, 314, 57, - 1754, 281, 3578, 57, 4634, 3322, 54, 50, 54, 50, - 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, - 975, 1434, 185, 54, 50, 1017, 54, 50, 54, 50, - 54, 50, 54, 50, 54, 50, 537, 8218, 4217, 54, - 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, - 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, - 50, 2041, 54, 50, 54, 50, 1049, 54, 50, 8281, - 1562, 697, 90, 217, 346, 1513, 1509, 126, 73, 69, - 254, 105, 37, 94, 37, 94, 165, 70, 105, 37, - 3166, 37, 218, 158, 108, 94, 149, 47, 85, 1221, - 37, 37, 1799, 38, 53, 44, 743, 231, 231, 231, - 231, 231, 231, 231, 231, 1036, 85, 52, 51, 52, - 51, 117, 52, 51, 53, 52, 51, 309, 49, 85, - 49, 53, 52, 51, 85, 52, 51, 54, 50, 54, - 50, 54, 50, 54, 50, 181, 38, 341, 81, 858, - 2874, 6874, 410, 61, 117, 58, 38, 39, 46, 54, - 50, 54, 50, 54, 50, 54, 50, 54, 50, 90, - 54, 50, 54, 50, 54, 50, 54, 50, 49, 54, - 82, 58, 302, 140, 74, 49, 166, 90, 110, 38, - 39, 53, 90, 2759, 76, 88, 70, 39, 49, 2887, - 53, 102, 39, 1319, 3015, 90, 143, 346, 871, 1178, - 519, 1018, 335, 986, 271, 58, 495, 1050, 335, 1274, - 495, 2042, 8218, 39, 39, 2074, 39, 39, 679, 38, - 36583, 1786, 1287, 198, 85, 8583, 38, 117, 519, 333, - 71, 1502, 39, 44, 107, 53, 332, 53, 38, 798, - 44, 2247, 334, 76, 213, 760, 294, 88, 478, 69, - 2014, 38, 261, 190, 350, 38, 88, 158, 158, 382, - 70, 37, 231, 44, 103, 44, 135, 44, 743, 74, - 76, 42, 154, 207, 90, 55, 58, 1671, 149, 74, - 1607, 522, 44, 85, 333, 588, 199, 117, 39, 333, - 903, 268, 85, 743, 364, 74, 53, 935, 108, 42, - 1511, 44, 74, 140, 74, 44, 138, 437, 38, 333, - 85, 1319, 204, 74, 76, 74, 76, 103, 44, 263, - 44, 42, 333, 149, 519, 38, 199, 122, 39, 42, - 1543, 44, 39, 108, 71, 76, 167, 76, 39, 44, - 39, 71, 38, 85, 359, 42, 76, 74, 85, 39, - 70, 42, 44, 199, 199, 199, 231, 231, 1127, 74, - 44, 74, 44, 74, 53, 42, 44, 333, 39, 39, - 743, 1575, 36, 68, 68, 36, 63, 63, 11719, 3399, - 229, 165, 39, 44, 327, 57, 423, 167, 39, 71, - 71, 3463, 536, 11623, 54, 50, 2055, 1735, 391, 55, - 58, 524, 245, 54, 50, 53, 236, 53, 81, 80, - 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, - 54, 50, 54, 50, 54, 50, 85, 54, 50, 149, - 112, 117, 149, 49, 54, 50, 54, 50, 54, 50, - 117, 57, 49, 121, 53, 55, 85, 167, 4327, 34, - 117, 55, 117, 54, 50, 53, 57, 53, 49, 85, - 333, 85, 121, 85, 841, 54, 53, 50, 56, 48, - 56, 837, 54, 57, 50, 57, 54, 50, 53, 54, - 50, 85, 327, 38, 1447, 70, 999, 199, 199, 199, - 103, 87, 57, 56, 58, 87, 58, 153, 90, 98, - 90, 391, 839, 615, 71, 487, 455, 3943, 117, 1455, - 314, 1710, 143, 570, 47, 410, 1466, 44, 935, 1575, - 999, 143, 551, 46, 263, 46, 967, 53, 1159, 263, - 53, 174, 1289, 1285, 2503, 333, 199, 39, 1415, 71, - 39, 743, 53, 271, 711, 207, 53, 839, 53, 1799, - 71, 39, 108, 76, 140, 135, 103, 871, 108, 44, - 271, 309, 935, 79, 53, 1735, 245, 711, 271, 615, - 271, 2343, 1007, 42, 44, 42, 1703, 492, 245, 655, - 333, 76, 42, 1447, 106, 140, 74, 76, 85, 34, - 149, 807, 333, 108, 1159, 172, 42, 268, 333, 149, - 76, 42, 1543, 106, 300, 74, 135, 149, 333, 1383, - 44, 42, 44, 74, 204, 42, 44, 333, 28135, 3182, - 149, 34279, 18215, 2215, 39, 1482, 140, 422, 71, 7898, - 1274, 1946, 74, 108, 122, 202, 258, 268, 90, 236, - 986, 140, 1562, 2138, 108, 58, 2810, 591, 841, 837, - 841, 229, 581, 841, 837, 41, 73, 41, 73, 137, - 265, 133, 37, 229, 357, 841, 837, 73, 137, 265, - 233, 837, 73, 137, 169, 41, 233, 837, 841, 837, - 841, 837, 841, 837, 841, 837, 841, 837, 841, 901, - 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, - 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, - 809, 57, 805, 57, 197, 94, 1613, 135, 871, 71, - 39, 39, 327, 135, 39, 39, 39, 39, 39, 39, - 103, 71, 39, 39, 39, 39, 39, 39, 71, 39, - 135, 231, 135, 135, 39, 327, 551, 103, 167, 551, - 89, 1434, 3226, 506, 474, 506, 506, 367, 1018, 1946, - 1402, 954, 1402, 314, 90, 1082, 218, 2266, 666, 1210, - 186, 570, 2042, 58, 5850, 154, 2010, 154, 794, 2266, - 378, 2266, 3738, 39, 39, 39, 39, 39, 39, 17351, - 34, 3074, 7692, 63, 63, - }; - -static int sqlite3Fts5UnicodeCategory(u32 iCode) { - int iRes = -1; - int iHi; - int iLo; - int ret; - u16 iKey; - - if( iCode>=(1<<20) ){ - return 0; - } - iLo = aFts5UnicodeBlock[(iCode>>16)]; - iHi = aFts5UnicodeBlock[1+(iCode>>16)]; - iKey = (iCode & 0xFFFF); - while( iHi>iLo ){ - int iTest = (iHi + iLo) / 2; - assert( iTest>=iLo && iTest=aFts5UnicodeMap[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest; - } - } - - if( iRes<0 ) return 0; - if( iKey>=(aFts5UnicodeMap[iRes]+(aFts5UnicodeData[iRes]>>5)) ) return 0; - ret = aFts5UnicodeData[iRes] & 0x1F; - if( ret!=30 ) return ret; - return ((iKey - aFts5UnicodeMap[iRes]) & 0x01) ? 5 : 9; -} - -static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ - int i = 0; - int iTbl = 0; - while( i<128 ){ - int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; - int n = (aFts5UnicodeData[iTbl] >> 5) + i; - for(; i<128 && i3 && n<=9 ); return n; } } @@ -260177,11 +203374,11 @@ for(i=7; i>=0; i--){ p[i] = (u8)((v & 0x7f) | 0x80); v >>= 7; } return 9; - } + } n = 0; do{ buf[n++] = (u8)((v & 0x7f) | 0x80); v >>= 7; }while( v!=0 ); @@ -260215,10 +203412,11 @@ if( iVal<(1 << 14) ) return 2; if( iVal<(1 << 21) ) return 3; if( iVal<(1 << 28) ) return 4; return 5; } + /* ** 2015 May 08 ** ** The author disclaims copyright to this source code. In place of @@ -260229,33 +203427,28 @@ ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This is an SQLite virtual table module implementing direct access to an -** existing FTS5 index. The module may create several different types of +** existing FTS5 index. The module may create several different types of ** tables: ** ** col: ** CREATE TABLE vocab(term, col, doc, cnt, PRIMARY KEY(term, col)); ** ** One row for each term/column combination. The value of $doc is set to ** the number of fts5 rows that contain at least one instance of term -** $term within column $col. Field $cnt is set to the total number of -** instances of term $term in column $col (in any row of the fts5 table). +** $term within column $col. Field $cnt is set to the total number of +** instances of term $term in column $col (in any row of the fts5 table). ** ** row: ** CREATE TABLE vocab(term, doc, cnt, PRIMARY KEY(term)); ** ** One row for each term in the database. The value of $doc is set to ** the number of fts5 rows that contain at least one instance of term -** $term. Field $cnt is set to the total number of instances of term +** $term. Field $cnt is set to the total number of instances of term ** $term in the database. -** -** instance: -** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY()); -** -** One row for each term instance in the database. */ /* #include "fts5Int.h" */ @@ -260267,61 +203460,51 @@ sqlite3_vtab base; char *zFts5Tbl; /* Name of fts5 table */ char *zFts5Db; /* Db containing fts5 table */ sqlite3 *db; /* Database handle */ Fts5Global *pGlobal; /* FTS5 global object for this database */ - int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */ - unsigned bBusy; /* True if busy */ + int eType; /* FTS5_VOCAB_COL or ROW */ }; struct Fts5VocabCursor { sqlite3_vtab_cursor base; sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */ - Fts5Table *pFts5; /* Associated FTS5 table */ + Fts5Index *pIndex; /* Associated FTS5 index */ int bEof; /* True if this cursor is at EOF */ Fts5IndexIter *pIter; /* Term/rowid iterator object */ - void *pStruct; /* From sqlite3Fts5StructureRef() */ int nLeTerm; /* Size of zLeTerm in bytes */ char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */ - int colUsed; /* Copy of sqlite3_index_info.colUsed */ /* These are used by 'col' tables only */ + Fts5Config *pConfig; /* Fts5 table configuration */ int iCol; i64 *aCnt; i64 *aDoc; - /* Output values used by all tables. */ + /* Output values used by 'row' and 'col' tables */ i64 rowid; /* This table's current rowid value */ Fts5Buffer term; /* Current value of 'term' column */ - - /* Output values Used by 'instance' tables only */ - i64 iInstPos; - int iInstOff; }; -#define FTS5_VOCAB_COL 0 -#define FTS5_VOCAB_ROW 1 -#define FTS5_VOCAB_INSTANCE 2 +#define FTS5_VOCAB_COL 0 +#define FTS5_VOCAB_ROW 1 #define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt" #define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt" -#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset" /* ** Bits for the mask used as the idxNum value by xBestIndex/xFilter. */ -#define FTS5_VOCAB_TERM_EQ 0x0100 -#define FTS5_VOCAB_TERM_GE 0x0200 -#define FTS5_VOCAB_TERM_LE 0x0400 - -#define FTS5_VOCAB_COLUSED_MASK 0xFF +#define FTS5_VOCAB_TERM_EQ 0x01 +#define FTS5_VOCAB_TERM_GE 0x02 +#define FTS5_VOCAB_TERM_LE 0x04 /* -** Translate a string containing an fts5vocab table type to an +** Translate a string containing an fts5vocab table type to an ** FTS5_VOCAB_XXX constant. If successful, set *peType to the output ** value and return SQLITE_OK. Otherwise, set *pzErr to an error message ** and return SQLITE_ERROR. */ static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){ @@ -260334,13 +203517,10 @@ }else if( sqlite3_stricmp(zCopy, "row")==0 ){ *peType = FTS5_VOCAB_ROW; }else - if( sqlite3_stricmp(zCopy, "instance")==0 ){ - *peType = FTS5_VOCAB_INSTANCE; - }else { *pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy); rc = SQLITE_ERROR; } sqlite3_free(zCopy); @@ -260395,14 +203575,13 @@ int argc, /* Number of elements in argv array */ const char * const *argv, /* xCreate/xConnect argument array */ sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ char **pzErr /* Write any error message here */ ){ - const char *azSchema[] = { - "CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")", - "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")", - "CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")" + const char *azSchema[] = { + "CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")", + "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")" }; Fts5VocabTable *pRet = 0; int rc = SQLITE_OK; /* Return code */ int bDb; @@ -260415,14 +203594,14 @@ }else{ int nByte; /* Bytes of space to allocate */ const char *zDb = bDb ? argv[3] : argv[1]; const char *zTab = bDb ? argv[4] : argv[3]; const char *zType = bDb ? argv[5] : argv[4]; - int nDb = (int)strlen(zDb)+1; + int nDb = (int)strlen(zDb)+1; int nTab = (int)strlen(zTab)+1; int eType = 0; - + rc = fts5VocabTableType(zType, pzErr, &eType); if( rc==SQLITE_OK ){ assert( eType>=0 && eType= ? -** -** are interpreted. Less-than and less-than-or-equal are treated -** identically, as are greater-than and greater-than-or-equal. */ static int fts5VocabBestIndexMethod( sqlite3_vtab *pUnused, sqlite3_index_info *pInfo ){ int i; int iTermEq = -1; int iTermGe = -1; int iTermLe = -1; - int idxNum = (int)pInfo->colUsed; + int idxNum = 0; int nArg = 0; UNUSED_PARAM(pUnused); - assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed ); - for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; if( p->usable==0 ) continue; if( p->iColumn==0 ){ /* term column */ if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i; @@ -260532,12 +203700,12 @@ /* This virtual table always delivers results in ascending order of ** the "term" column (column 0). So if the user has requested this ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the ** sqlite3_index_info.orderByConsumed flag to tell the core the results ** are already in sorted order. */ - if( pInfo->nOrderBy==1 - && pInfo->aOrderBy[0].iColumn==0 + if( pInfo->nOrderBy==1 + && pInfo->aOrderBy[0].iColumn==0 && pInfo->aOrderBy[0].desc==0 ){ pInfo->orderByConsumed = 1; } @@ -260547,26 +203715,21 @@ /* ** Implementation of xOpen method. */ static int fts5VocabOpenMethod( - sqlite3_vtab *pVTab, + sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr ){ Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab; - Fts5Table *pFts5 = 0; + Fts5Index *pIndex = 0; + Fts5Config *pConfig = 0; Fts5VocabCursor *pCsr = 0; int rc = SQLITE_OK; sqlite3_stmt *pStmt = 0; char *zSql = 0; - if( pTab->bBusy ){ - pVTab->zErrMsg = sqlite3_mprintf( - "recursive definition for %s.%s", pTab->zFts5Db, pTab->zFts5Tbl - ); - return SQLITE_ERROR; - } zSql = sqlite3Fts5Mprintf(&rc, "SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'", pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl ); if( zSql ){ @@ -260574,42 +203737,37 @@ } sqlite3_free(zSql); assert( rc==SQLITE_OK || pStmt==0 ); if( rc==SQLITE_ERROR ) rc = SQLITE_OK; - pTab->bBusy = 1; - if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ - i64 iId = sqlite3_column_int64(pStmt, 0); - pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId); - } - pTab->bBusy = 0; - - if( rc==SQLITE_OK ){ - if( pFts5==0 ){ - rc = sqlite3_finalize(pStmt); - pStmt = 0; - if( rc==SQLITE_OK ){ - pVTab->zErrMsg = sqlite3_mprintf( - "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl - ); - rc = SQLITE_ERROR; - } - }else{ - rc = sqlite3Fts5FlushToDisk(pFts5); - } - } - - if( rc==SQLITE_OK ){ - i64 nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor); - pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte); - } - - if( pCsr ){ - pCsr->pFts5 = pFts5; - pCsr->pStmt = pStmt; - pCsr->aCnt = (i64*)&pCsr[1]; - pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol]; + if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ + i64 iId = sqlite3_column_int64(pStmt, 0); + pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig); + } + + if( rc==SQLITE_OK && pIndex==0 ){ + rc = sqlite3_finalize(pStmt); + pStmt = 0; + if( rc==SQLITE_OK ){ + pVTab->zErrMsg = sqlite3_mprintf( + "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl + ); + rc = SQLITE_ERROR; + } + } + + if( rc==SQLITE_OK ){ + int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor); + pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte); + } + + if( pCsr ){ + pCsr->pIndex = pIndex; + pCsr->pStmt = pStmt; + pCsr->pConfig = pConfig; + pCsr->aCnt = (i64*)&pCsr[1]; + pCsr->aDoc = &pCsr->aCnt[pConfig->nCol]; }else{ sqlite3_finalize(pStmt); } *ppCsr = (sqlite3_vtab_cursor*)pCsr; @@ -260617,17 +203775,14 @@ } static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){ pCsr->rowid = 0; sqlite3Fts5IterClose(pCsr->pIter); - sqlite3Fts5StructureRelease(pCsr->pStruct); - pCsr->pStruct = 0; pCsr->pIter = 0; sqlite3_free(pCsr->zLeTerm); pCsr->nLeTerm = -1; pCsr->zLeTerm = 0; - pCsr->bEof = 0; } /* ** Close the cursor. For additional information see the documentation ** on the xClose method of the virtual table interface. @@ -260639,93 +203794,36 @@ sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr); return SQLITE_OK; } -static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){ - int rc = SQLITE_OK; - - if( sqlite3Fts5IterEof(pCsr->pIter) ){ - pCsr->bEof = 1; - }else{ - const char *zTerm; - int nTerm; - zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); - if( pCsr->nLeTerm>=0 ){ - int nCmp = MIN(nTerm, pCsr->nLeTerm); - int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); - if( bCmp<0 || (bCmp==0 && pCsr->nLeTermbEof = 1; - } - } - - sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); - } - return rc; -} - -static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){ - int eDetail = pCsr->pFts5->pConfig->eDetail; - int rc = SQLITE_OK; - Fts5IndexIter *pIter = pCsr->pIter; - i64 *pp = &pCsr->iInstPos; - int *po = &pCsr->iInstOff; - - assert( sqlite3Fts5IterEof(pIter)==0 ); - assert( pCsr->bEof==0 ); - while( eDetail==FTS5_DETAIL_NONE - || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) - ){ - pCsr->iInstPos = 0; - pCsr->iInstOff = 0; - - rc = sqlite3Fts5IterNextScan(pCsr->pIter); - if( rc==SQLITE_OK ){ - rc = fts5VocabInstanceNewTerm(pCsr); - if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break; - } - if( rc ){ - pCsr->bEof = 1; - break; - } - } - - return rc; -} /* ** Advance the cursor to the next row in the table. */ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; - int nCol = pCsr->pFts5->pConfig->nCol; - int rc; - - rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct); - if( rc!=SQLITE_OK ) return rc; - pCsr->rowid++; - - if( pTab->eType==FTS5_VOCAB_INSTANCE ){ - return fts5VocabInstanceNext(pCsr); - } + int rc = SQLITE_OK; + int nCol = pCsr->pConfig->nCol; + + pCsr->rowid++; if( pTab->eType==FTS5_VOCAB_COL ){ for(pCsr->iCol++; pCsr->iColiCol++){ if( pCsr->aDoc[pCsr->iCol] ) break; } } - if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){ + if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){ if( sqlite3Fts5IterEof(pCsr->pIter) ){ pCsr->bEof = 1; }else{ const char *zTerm; int nTerm; zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); - assert( nTerm>=0 ); if( pCsr->nLeTerm>=0 ){ int nCmp = MIN(nTerm, pCsr->nLeTerm); int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); if( bCmp<0 || (bCmp==0 && pCsr->nLeTermbEof = 1; @@ -260738,96 +203836,81 @@ memset(pCsr->aDoc, 0, nCol * sizeof(i64)); pCsr->iCol = 0; assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); while( rc==SQLITE_OK ){ - int eDetail = pCsr->pFts5->pConfig->eDetail; const u8 *pPos; int nPos; /* Position list */ i64 iPos = 0; /* 64-bit position read from poslist */ int iOff = 0; /* Current offset within position list */ pPos = pCsr->pIter->pData; nPos = pCsr->pIter->nData; - - switch( pTab->eType ){ - case FTS5_VOCAB_ROW: - /* Do not bother counting the number of instances if the "cnt" - ** column is not being read (according to colUsed). */ - if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){ - while( iPosaCnt[] */ - pCsr->aCnt[0]++; - } - } - } - pCsr->aDoc[0]++; - break; - - case FTS5_VOCAB_COL: - if( eDetail==FTS5_DETAIL_FULL ){ + switch( pCsr->pConfig->eDetail ){ + case FTS5_DETAIL_FULL: + pPos = pCsr->pIter->pData; + nPos = pCsr->pIter->nData; + if( pTab->eType==FTS5_VOCAB_ROW ){ + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + pCsr->aCnt[0]++; + } + pCsr->aDoc[0]++; + }else{ int iCol = -1; while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ int ii = FTS5_POS2COLUMN(iPos); + pCsr->aCnt[ii]++; if( iCol!=ii ){ if( ii>=nCol ){ rc = FTS5_CORRUPT; break; } pCsr->aDoc[ii]++; iCol = ii; } - pCsr->aCnt[ii]++; } - }else if( eDetail==FTS5_DETAIL_COLUMNS ){ + } + break; + + case FTS5_DETAIL_COLUMNS: + if( pTab->eType==FTS5_VOCAB_ROW ){ + pCsr->aDoc[0]++; + }else{ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ assert_nc( iPos>=0 && iPos=nCol ){ rc = FTS5_CORRUPT; break; } pCsr->aDoc[iPos]++; } - }else{ - assert( eDetail==FTS5_DETAIL_NONE ); - pCsr->aDoc[0]++; } break; - default: - assert( pTab->eType==FTS5_VOCAB_INSTANCE ); + default: + assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); + pCsr->aDoc[0]++; break; } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IterNextScan(pCsr->pIter); } - if( pTab->eType==FTS5_VOCAB_INSTANCE ) break; if( rc==SQLITE_OK ){ zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); - if( nTerm!=pCsr->term.n - || (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm)) - ){ + if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){ break; } if( sqlite3Fts5IterEof(pCsr->pIter) ) break; } } } } if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ - for(/* noop */; pCsr->iColaDoc[pCsr->iCol]==0; pCsr->iCol++); - if( pCsr->iCol==nCol ){ - rc = FTS5_CORRUPT; - } + while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++; + assert( pCsr->iColpConfig->nCol ); } return rc; } /* @@ -260838,13 +203921,11 @@ int idxNum, /* Strategy index */ const char *zUnused, /* Unused */ int nUnused, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ - Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; - int eType = pTab->eType; int rc = SQLITE_OK; int iVal = 0; int f = FTS5INDEX_QUERY_SCAN; const char *zTerm = 0; @@ -260858,24 +203939,22 @@ fts5VocabResetCursor(pCsr); if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++]; - pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK); if( pEq ){ zTerm = (const char *)sqlite3_value_text(pEq); nTerm = sqlite3_value_bytes(pEq); - f = FTS5INDEX_QUERY_NOTOKENDATA; + f = 0; }else{ if( pGe ){ zTerm = (const char *)sqlite3_value_text(pGe); nTerm = sqlite3_value_bytes(pGe); } if( pLe ){ const char *zCopy = (const char *)sqlite3_value_text(pLe); - if( zCopy==0 ) zCopy = ""; pCsr->nLeTerm = sqlite3_value_bytes(pLe); pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1); if( pCsr->zLeTerm==0 ){ rc = SQLITE_NOMEM; }else{ @@ -260882,32 +203961,23 @@ memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1); } } } - if( rc==SQLITE_OK ){ - Fts5Index *pIndex = pCsr->pFts5->pIndex; - rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); - if( rc==SQLITE_OK ){ - pCsr->pStruct = sqlite3Fts5StructureRef(pIndex); - } - } - if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){ - rc = fts5VocabInstanceNewTerm(pCsr); - } - if( rc==SQLITE_OK && !pCsr->bEof - && (eType!=FTS5_VOCAB_INSTANCE - || pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE) - ){ + + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); + } + if( rc==SQLITE_OK ){ rc = fts5VocabNextMethod(pCursor); } return rc; } -/* -** This is the xEof method of the virtual table. SQLite calls this +/* +** This is the xEof method of the virtual table. SQLite calls this ** routine to find out if it has reached the end of a result set. */ static int fts5VocabEofMethod(sqlite3_vtab_cursor *pCursor){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; return pCsr->bEof; @@ -260917,11 +203987,11 @@ sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ int iCol /* Index of column to read value from */ ){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; - int eDetail = pCsr->pFts5->pConfig->eDetail; + int eDetail = pCsr->pConfig->eDetail; int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType; i64 iVal = 0; if( iCol==0 ){ sqlite3_result_text( @@ -260929,66 +203999,38 @@ ); }else if( eType==FTS5_VOCAB_COL ){ assert( iCol==1 || iCol==2 || iCol==3 ); if( iCol==1 ){ if( eDetail!=FTS5_DETAIL_NONE ){ - const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol]; + const char *z = pCsr->pConfig->azCol[pCsr->iCol]; sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); } }else if( iCol==2 ){ iVal = pCsr->aDoc[pCsr->iCol]; }else{ iVal = pCsr->aCnt[pCsr->iCol]; } - }else if( eType==FTS5_VOCAB_ROW ){ + }else{ assert( iCol==1 || iCol==2 ); if( iCol==1 ){ iVal = pCsr->aDoc[0]; }else{ iVal = pCsr->aCnt[0]; } - }else{ - assert( eType==FTS5_VOCAB_INSTANCE ); - switch( iCol ){ - case 1: - sqlite3_result_int64(pCtx, pCsr->pIter->iRowid); - break; - case 2: { - int ii = -1; - if( eDetail==FTS5_DETAIL_FULL ){ - ii = FTS5_POS2COLUMN(pCsr->iInstPos); - }else if( eDetail==FTS5_DETAIL_COLUMNS ){ - ii = (int)pCsr->iInstPos; - } - if( ii>=0 && iipFts5->pConfig->nCol ){ - const char *z = pCsr->pFts5->pConfig->azCol[ii]; - sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); - } - break; - } - default: { - assert( iCol==3 ); - if( eDetail==FTS5_DETAIL_FULL ){ - int ii = FTS5_POS2OFFSET(pCsr->iInstPos); - sqlite3_result_int(pCtx, ii); - } - break; - } - } } if( iVal>0 ) sqlite3_result_int64(pCtx, iVal); return SQLITE_OK; } -/* +/* ** This is the xRowid method. The SQLite core calls this routine to ** retrieve the rowid for the current row of the result set. The ** rowid should be written to *pRowid. */ static int fts5VocabRowidMethod( - sqlite3_vtab_cursor *pCursor, + sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid ){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; *pRowid = pCsr->rowid; return SQLITE_OK; @@ -261017,20 +204059,20 @@ /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, - /* xShadowName */ 0, - /* xIntegrity */ 0 }; void *p = (void*)pGlobal; return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); } -/* Here ends the fts5.c composite file. */ + + + #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */ /************** End of fts5.c ************************************************/ /************** Begin file stmt.c ********************************************/ /* @@ -261063,20 +204105,10 @@ /* #include */ /* #include */ #ifndef SQLITE_OMIT_VIRTUALTABLE - -#define STMT_NUM_INTEGER_COLUMN 10 -typedef struct StmtRow StmtRow; -struct StmtRow { - sqlite3_int64 iRowid; /* Rowid value */ - char *zSql; /* column "sql" */ - int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */ - StmtRow *pNext; /* Next row to return */ -}; - /* stmt_vtab is a subclass of sqlite3_vtab which will ** serve as the underlying representation of a stmt virtual table */ typedef struct stmt_vtab stmt_vtab; struct stmt_vtab { @@ -261090,11 +204122,12 @@ */ typedef struct stmt_cursor stmt_cursor; struct stmt_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3 *db; /* Database connection for this cursor */ - StmtRow *pRow; /* Current row */ + sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */ + sqlite3_int64 iRowid; /* The rowid */ }; /* ** The stmtConnect() method is invoked to create a new ** stmt_vtab that describes the stmt virtual table. @@ -261130,19 +204163,15 @@ #define STMT_COLUMN_REPREP 8 /* SQLITE_STMTSTATUS_REPREPARE */ #define STMT_COLUMN_RUN 9 /* SQLITE_STMTSTATUS_RUN */ #define STMT_COLUMN_MEM 10 /* SQLITE_STMTSTATUS_MEMUSED */ - (void)pAux; - (void)argc; - (void)argv; - (void)pzErr; rc = sqlite3_declare_vtab(db, "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep," "reprep,run,mem)"); if( rc==SQLITE_OK ){ - pNew = sqlite3_malloc64( sizeof(*pNew) ); + pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); pNew->db = db; } @@ -261160,33 +204189,22 @@ /* ** Constructor for a new stmt_cursor object. */ static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ stmt_cursor *pCur; - pCur = sqlite3_malloc64( sizeof(*pCur) ); + pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); pCur->db = ((stmt_vtab*)p)->db; *ppCursor = &pCur->base; return SQLITE_OK; } -static void stmtCsrReset(stmt_cursor *pCur){ - StmtRow *pRow = 0; - StmtRow *pNext = 0; - for(pRow=pCur->pRow; pRow; pRow=pNext){ - pNext = pRow->pNext; - sqlite3_free(pRow); - } - pCur->pRow = 0; -} - /* ** Destructor for a stmt_cursor. */ static int stmtClose(sqlite3_vtab_cursor *cur){ - stmtCsrReset((stmt_cursor*)cur); sqlite3_free(cur); return SQLITE_OK; } @@ -261193,13 +204211,12 @@ /* ** Advance a stmt_cursor to its next row of output. */ static int stmtNext(sqlite3_vtab_cursor *cur){ stmt_cursor *pCur = (stmt_cursor*)cur; - StmtRow *pNext = pCur->pRow->pNext; - sqlite3_free(pCur->pRow); - pCur->pRow = pNext; + pCur->iRowid++; + pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt); return SQLITE_OK; } /* ** Return values of columns for the row at which the stmt_cursor @@ -261209,15 +204226,42 @@ sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ int i /* Which column to return */ ){ stmt_cursor *pCur = (stmt_cursor*)cur; - StmtRow *pRow = pCur->pRow; - if( i==STMT_COLUMN_SQL ){ - sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT); - }else{ - sqlite3_result_int(ctx, pRow->aCol[i]); + switch( i ){ + case STMT_COLUMN_SQL: { + sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT); + break; + } + case STMT_COLUMN_NCOL: { + sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt)); + break; + } + case STMT_COLUMN_RO: { + sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt)); + break; + } + case STMT_COLUMN_BUSY: { + sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt)); + break; + } + case STMT_COLUMN_MEM: { + i = SQLITE_STMTSTATUS_MEMUSED + + STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP; + /* Fall thru */ + } + case STMT_COLUMN_NSCAN: + case STMT_COLUMN_NSORT: + case STMT_COLUMN_NAIDX: + case STMT_COLUMN_NSTEP: + case STMT_COLUMN_REPREP: + case STMT_COLUMN_RUN: { + sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt, + i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0)); + break; + } } return SQLITE_OK; } /* @@ -261224,86 +204268,38 @@ ** Return the rowid for the current row. In this implementation, the ** rowid is the same as the output value. */ static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ stmt_cursor *pCur = (stmt_cursor*)cur; - *pRowid = pCur->pRow->iRowid; + *pRowid = pCur->iRowid; return SQLITE_OK; } /* ** Return TRUE if the cursor has been moved off of the last ** row of output. */ static int stmtEof(sqlite3_vtab_cursor *cur){ stmt_cursor *pCur = (stmt_cursor*)cur; - return pCur->pRow==0; + return pCur->pStmt==0; } /* ** This method is called to "rewind" the stmt_cursor object back ** to the first row of output. This method is always called at least -** once prior to any call to stmtColumn() or stmtRowid() or +** once prior to any call to stmtColumn() or stmtRowid() or ** stmtEof(). */ static int stmtFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ stmt_cursor *pCur = (stmt_cursor *)pVtabCursor; - sqlite3_stmt *p = 0; - sqlite3_int64 iRowid = 1; - StmtRow **ppRow = 0; - - (void)idxNum; - (void)idxStr; - (void)argc; - (void)argv; - stmtCsrReset(pCur); - ppRow = &pCur->pRow; - for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){ - const char *zSql = sqlite3_sql(p); - sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0; - StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql); - - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(StmtRow)); - if( zSql ){ - pNew->zSql = (char*)&pNew[1]; - memcpy(pNew->zSql, zSql, nSql); - } - pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p); - pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p); - pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p); - pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0 - ); - pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_SORT, 0 - ); - pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_AUTOINDEX, 0 - ); - pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_VM_STEP, 0 - ); - pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_REPREPARE, 0 - ); - pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_RUN, 0 - ); - pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status( - p, SQLITE_STMTSTATUS_MEMUSED, 0 - ); - pNew->iRowid = iRowid++; - *ppRow = pNew; - ppRow = &pNew->pNext; - } - - return SQLITE_OK; + pCur->pStmt = 0; + pCur->iRowid = 0; + return stmtNext(pVtabCursor); } /* ** SQLite will invoke this method one or more times while planning a query ** that uses the stmt virtual table. This routine needs to create @@ -261312,18 +204308,17 @@ */ static int stmtBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ - (void)tab; pIdxInfo->estimatedCost = (double)500; pIdxInfo->estimatedRows = 500; return SQLITE_OK; } /* -** This following structure defines all the methods for the +** This following structure defines all the methods for the ** stmt virtual table. */ static sqlite3_module stmtModule = { 0, /* iVersion */ 0, /* xCreate */ @@ -261346,12 +204341,10 @@ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0, /* xShadowName */ - 0 /* xIntegrity */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3 *db){ @@ -261365,12 +204358,12 @@ #ifndef SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif SQLITE_API int sqlite3_stmt_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -261380,9 +204373,5 @@ } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -/* Return the source-id for this library */ -SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } -#endif /* SQLITE_AMALGAMATION */ -/************************** End of sqlite3.c ******************************/ Index: src/sqlite3.h ================================================================== --- src/sqlite3.h +++ src/sqlite3.h @@ -41,34 +41,11 @@ extern "C" { #endif /* -** Facilitate override of interface linkage and calling conventions. -** Be aware that these macros may not be used within this particular -** translation of the amalgamation and its associated header file. -** -** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the -** compiler that the target identifier should have external linkage. -** -** The SQLITE_CDECL macro is used to set the calling convention for -** public functions that accept a variable number of arguments. -** -** The SQLITE_APICALL macro is used to set the calling convention for -** public functions that accept a fixed number of arguments. -** -** The SQLITE_STDCALL macro is no longer used and is now deprecated. -** -** The SQLITE_CALLBACK macro is used to set the calling convention for -** function pointers. -** -** The SQLITE_SYSAPI macro is used to set the calling convention for -** functions provided by the operating system. -** -** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and -** SQLITE_SYSAPI macros are used only when building for environments -** that require non-default calling conventions. +** Provide the ability to override linkage features of the interface. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif #ifndef SQLITE_API @@ -129,28 +106,26 @@ ** The SQLITE_VERSION_NUMBER for any given release of SQLite will also ** be larger than the release from which it is derived. Either Y will ** be held constant and Z will be incremented or else Y will be incremented ** and Z will be reset to zero. ** -** Since [version 3.6.18] ([dateof:3.6.18]), +** Since [version 3.6.18] ([dateof:3.6.18]), ** SQLite source code has been stored in the ** Fossil configuration management ** 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 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. +** or SHA3-256 hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.49.0" -#define SQLITE_VERSION_NUMBER 3049000 -#define SQLITE_SOURCE_ID "2025-02-02 18:01:32 602d4dd69ec9a724c69cb41ab15376ec731bfd4894fac0a2b25076b857786c6d" +#define SQLITE_VERSION "3.20.0" +#define SQLITE_VERSION_NUMBER 3020000 +#define SQLITE_SOURCE_ID "2017-07-15 13:49:56 47cf83a0682b7b3219cf255457f5fbe05f3c1f46be42f6bbab33b78a57a252f6" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** @@ -162,25 +137,23 @@ ** the header, and thus ensure that the application is ** compiled with matching library and header files. ** **
                     ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
                    -** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
                    +** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
                     ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
                     ** 
                    )^ ** ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] ** macro. ^The sqlite3_libversion() function returns a pointer to the ** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to -** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns -** a pointer to a string constant whose value is the same as the -** [SQLITE_SOURCE_ID] C preprocessor macro. 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].)^ +** [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. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; SQLITE_API const char *sqlite3_libversion(void); @@ -188,35 +161,32 @@ SQLITE_API int sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics ** -** ^The sqlite3_compileoption_used() function returns 0 or 1 -** indicating whether the specified option was defined at -** compile time. ^The SQLITE_ prefix may be omitted from the -** option name passed to sqlite3_compileoption_used(). +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). ** ** ^The sqlite3_compileoption_get() function allows iterating ** over the list of options that were defined at compile time by ** returning the N-th compile time option string. ^If N is out of range, -** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ -** prefix is omitted from any strings returned by +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by ** sqlite3_compileoption_get(). ** ** ^Support for the diagnostic functions sqlite3_compileoption_used() -** and sqlite3_compileoption_get() may be omitted by specifying the +** and sqlite3_compileoption_get() may be omitted by specifying the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_API int sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *sqlite3_compileoption_get(int N); -#else -# define sqlite3_compileoption_used(X) 0 -# define sqlite3_compileoption_get(X) ((void*)0) #endif /* ** CAPI3REF: Test To See If The Library Is Threadsafe ** @@ -225,11 +195,11 @@ ** [SQLITE_THREADSAFE] compile-time option being set to 0. ** ** SQLite can be compiled with or without mutexes. When ** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes ** are enabled and SQLite is threadsafe. When the -** [SQLITE_THREADSAFE] macro is 0, +** [SQLITE_THREADSAFE] macro is 0, ** the mutexes are omitted. Without the mutexes, it is not safe ** to use SQLite concurrently from more than one thread. ** ** Enabling mutexes incurs a measurable performance penalty. ** So if speed is of utmost importance, it makes sense to disable @@ -282,18 +252,18 @@ ** The sqlite_int64 and sqlite_uint64 types are supported for backwards ** compatibility only. ** ** ^The sqlite3_int64 and sqlite_int64 types can store integer values ** between -9223372036854775808 and +9223372036854775807 inclusive. ^The -** sqlite3_uint64 and sqlite_uint64 types can store integer values +** sqlite3_uint64 and sqlite_uint64 types can store integer values ** between 0 and +18446744073709551615 inclusive. */ #ifdef SQLITE_INT64_TYPE typedef SQLITE_INT64_TYPE sqlite_int64; # ifdef SQLITE_UINT64_TYPE typedef SQLITE_UINT64_TYPE sqlite_uint64; -# else +# else typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; # endif #elif defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; @@ -320,26 +290,30 @@ ** for the [sqlite3] object. ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if ** the [sqlite3] object is successfully destroyed and all associated ** resources are deallocated. ** -** Ideally, applications should [sqlite3_finalize | finalize] all -** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and -** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated -** with the [sqlite3] object prior to attempting to close the object. ** ^If the database connection is associated with unfinalized prepared -** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then -** sqlite3_close() will leave the database connection open and return -** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared -** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups, -** it returns [SQLITE_OK] regardless, but instead of deallocating the database -** connection immediately, it marks the database connection as an unusable -** "zombie" and makes arrangements to automatically deallocate the database -** connection after all prepared statements are finalized, all BLOB handles -** are closed, and all backups have finished. The sqlite3_close_v2() interface -** is intended for use with host languages that are garbage collected, and -** where the order in which destructors are called is arbitrary. +** statements or unfinished sqlite3_backup objects then sqlite3_close() +** will leave the database connection open and return [SQLITE_BUSY]. +** ^If sqlite3_close_v2() is called with unfinalized prepared statements +** and/or unfinished sqlite3_backups, then the database connection becomes +** an unusable "zombie" which will automatically be deallocated when the +** last prepared statement is finalized or the last sqlite3_backup is +** finished. The sqlite3_close_v2() interface is intended for use with +** host languages that are garbage collected, and where the order in which +** destructors are called is arbitrary. +** +** Applications should [sqlite3_finalize | finalize] all [prepared statements], +** [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated +** with the [sqlite3] object prior to attempting to close the object. ^If +** sqlite3_close_v2() is called on a [database connection] that still has +** outstanding [prepared statements], [BLOB handles], and/or +** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation +** of resources is deferred until all [prepared statements], [BLOB handles], +** and [sqlite3_backup] objects are also destroyed. ** ** ^If an [sqlite3] object is destroyed while a transaction is open, ** the transaction is automatically rolled back. ** ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] @@ -365,11 +339,11 @@ ** METHOD: sqlite3 ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], ** that allows an application to run multiple statements of SQL -** without having to use a lot of C code. +** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, ** semicolon-separate SQL statements passed into its 2nd argument, ** in the context of the [database connection] passed in as its 1st ** argument. ^If the callback function of the 3rd argument to @@ -405,11 +379,11 @@ ** sqlite3_exec() callback is an array of pointers to strings where each ** entry represents the name of corresponding result column as obtained ** from [sqlite3_column_name()]. ** ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer -** to an empty string, or a pointer that contains only whitespace and/or +** to an empty string, or a pointer that contains only whitespace and/or ** SQL comments, then no SQL statements are evaluated and the database ** is not changed. ** ** Restrictions: ** @@ -418,12 +392,10 @@ ** is a valid and open [database connection]. **
                  • The application must not close the [database connection] specified by ** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. **
                  • The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. -**
                  • The application must not dereference the arrays or string pointers -** passed as the 3rd and 4th callback parameters after it returns. **
                  */ SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ @@ -458,11 +430,11 @@ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ #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 /* Internal use only */ +#define SQLITE_EMPTY 16 /* Not used */ #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 */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ @@ -492,13 +464,10 @@ ** on a per database connection basis using the ** [sqlite3_extended_result_codes()] API. Or, the extended code for ** 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_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<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)) #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) #define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) @@ -523,36 +492,22 @@ #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) #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_IOERR_DATA (SQLITE_IOERR | (32<<8)) -#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) -#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) -#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) -#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) -#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ -#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) -#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) -#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #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)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) @@ -560,39 +515,22 @@ #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) -#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8)) -#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) -#define SQLITE_NOTICE_RBU (SQLITE_NOTICE | (3<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) -#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. -** -** Only those flags marked as "Ok for sqlite3_open_v2()" may be -** used as the third argument to the [sqlite3_open_v2()] interface. -** The other flags have historically been ignored by sqlite3_open_v2(), -** though future versions of SQLite might change so that an error is -** raised if any of the disallowed bits are passed into sqlite3_open_v2(). -** Applications should not depend on the historical behavior. -** -** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into -** [sqlite3_open_v2()] does *not* cause the underlying database file -** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into -** [sqlite3_open_v2()] has historically be a no-op and might become an -** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ @@ -604,23 +542,18 @@ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ -#define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ -#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ /* Reserved: 0x00F00000 */ -/* Legacy compatibility: */ -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ - /* ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods] @@ -645,22 +578,10 @@ ** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN ** 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]. -** -** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read -** from the database file in amounts that are not a multiple of the -** page size and that do not begin at a page boundary. Without this -** property, SQLite is careful to only do full-page reads and write -** on aligned pages, with the one exception that it will do a sub-page -** read of the first page to access the database header. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC1K 0x00000004 #define SQLITE_IOCAP_ATOMIC2K 0x00000008 @@ -672,29 +593,23 @@ #define SQLITE_IOCAP_SAFE_APPEND 0x00000200 #define SQLITE_IOCAP_SEQUENTIAL 0x00000400 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_IMMUTABLE 0x00002000 -#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 -#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000 /* ** CAPI3REF: File Locking Levels ** ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. These values are ordered from -** lest restrictive to most restrictive. -** -** The argument to xLock() is always SHARED or higher. The argument to -** xUnlock is either SHARED or NONE. +** of an [sqlite3_io_methods] object. */ -#define SQLITE_LOCK_NONE 0 /* xUnlock() only */ -#define SQLITE_LOCK_SHARED 1 /* xLock() or xUnlock() */ -#define SQLITE_LOCK_RESERVED 2 /* xLock() only */ -#define SQLITE_LOCK_PENDING 3 /* xLock() only */ -#define SQLITE_LOCK_EXCLUSIVE 4 /* xLock() only */ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 /* ** CAPI3REF: Synchronization Type Flags ** ** When SQLite invokes the xSync() method of an @@ -725,11 +640,11 @@ #define SQLITE_SYNC_DATAONLY 0x00010 /* ** CAPI3REF: OS Interface Open File Handle ** -** An [sqlite3_file] object represents an open file in the +** An [sqlite3_file] object represents an open file in the ** [sqlite3_vfs | OS interface layer]. Individual OS interface ** implementations will ** want to subclass this object by appending additional fields ** for their own use. The pMethods entry is a pointer to an ** [sqlite3_io_methods] object that defines methods for performing @@ -747,11 +662,11 @@ ** [sqlite3_file] object (or, more commonly, a subclass of the ** [sqlite3_file] object) with a pointer to an instance of this object. ** This object defines the methods used to perform various operations ** against the open file represented by the [sqlite3_file] object. ** -** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method ** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The ** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] ** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element ** to NULL. @@ -768,22 +683,15 @@ **
                2. [SQLITE_LOCK_SHARED], **
                3. [SQLITE_LOCK_RESERVED], **
                4. [SQLITE_LOCK_PENDING], or **
                5. [SQLITE_LOCK_EXCLUSIVE]. ** -** xLock() upgrades the database file lock. In other words, xLock() moves the -** database file lock in the direction NONE toward EXCLUSIVE. The argument to -** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never -** SQLITE_LOCK_NONE. If the database file lock is already at or above the -** requested lock, then the call to xLock() is a no-op. -** xUnlock() downgrades the database file lock to either SHARED or NONE. -** If the lock is already at or below the requested lock state, then the call -** to xUnlock() is a no-op. +** xLock() increases the lock. xUnlock() decreases the lock. ** The xCheckReservedLock() method checks whether any database connection, ** either in this process or in some other process, is holding a RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns, via its output -** pointer parameter, true if such a lock exists and false otherwise. +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. ** ** The xFileControl() method is a generic interface that allows custom ** VFS implementations to directly control an open file using the ** [sqlite3_file_control()] interface. The second "op" argument is an ** integer opcode. The third argument is a generic pointer intended to @@ -819,12 +727,10 @@ **
                6. [SQLITE_IOCAP_SAFE_APPEND] **
                7. [SQLITE_IOCAP_SEQUENTIAL] **
                8. [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] **
                9. [SQLITE_IOCAP_POWERSAFE_OVERWRITE] **
                10. [SQLITE_IOCAP_IMMUTABLE] -**
                11. [SQLITE_IOCAP_BATCH_ATOMIC] -**
                12. [SQLITE_IOCAP_SUBPAGE_READ] ** ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and @@ -881,34 +787,26 @@ **
                13. [[SQLITE_FCNTL_LOCKSTATE]] ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. -** This capability is only available if SQLite is compiled with [SQLITE_DEBUG]. +** into an integer that the pArg argument points to. This capability +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. ** **
                14. [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the ** current transaction. This hint is not guaranteed to be accurate but it ** is often close. The underlying VFS might choose to preallocate database ** file space based on this hint in order to help writes to the database ** file run faster. ** -**
                15. [[SQLITE_FCNTL_SIZE_LIMIT]] -** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that -** implements [sqlite3_deserialize()] to set an upper bound on the size -** of the in-memory database. The argument is a pointer to a [sqlite3_int64]. -** If the integer pointed to is negative, then it is filled in with the -** current limit. Otherwise the limit is set to the larger of the value -** of the integer pointed to and the current database size. The integer -** pointed to is set to the new limit. -** **
                16. [[SQLITE_FCNTL_CHUNK_SIZE]] ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS ** extends and truncates the database file in chunks of a size specified -** by the user. The fourth argument to [sqlite3_file_control()] should +** by the user. The fourth argument to [sqlite3_file_control()] should ** point to an integer (type int) containing the new chunk-size to use ** for the nominated database. Allocating database file space in large ** chunks (say 1MB at a time), may reduce file-system fragmentation and ** improve performance on some systems. ** @@ -927,28 +825,28 @@ ** No longer in use. ** **
                17. [[SQLITE_FCNTL_SYNC]] ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and ** sent to the VFS immediately before the xSync method is invoked on a -** database file descriptor. Or, if the xSync method is not invoked -** because the user has configured SQLite with -** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place ** of the xSync method. In most cases, the pointer argument passed with ** this file-control is NULL. However, if the database file is being synced ** as part of a multi-database commit, the argument points to a nul-terminated -** string containing the transactions super-journal file name. VFSes that -** do not need this signal should silently ignore this opcode. Applications -** should not call [sqlite3_file_control()] with this opcode as doing so may -** disrupt the operation of the specialized VFSes that do require it. +** string containing the transactions master-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. ** **
                18. [[SQLITE_FCNTL_COMMIT_PHASETWO]] ** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite ** and sent to the VFS after a transaction has been committed immediately ** but before the database is unlocked. VFSes that do not need this signal ** should silently ignore this opcode. Applications should not call -** [sqlite3_file_control()] with this opcode as doing so may disrupt the -** operation of the specialized VFSes that do require it. +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. ** **
                19. [[SQLITE_FCNTL_WIN32_AV_RETRY]] ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic ** retry counts and intervals for certain disk I/O operations for the ** windows [VFS] in order to provide robustness in the presence of @@ -966,12 +864,11 @@ ** interrogated. The zDbName parameter is ignored. ** **
                20. [[SQLITE_FCNTL_PERSIST_WAL]] ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary -** write ahead log ([WAL file]) and shared memory -** files used for transaction control +** write ahead log and shared memory files used for transaction control ** are automatically deleted when the latest connection to the database ** closes. Setting persistent WAL mode causes those files to persist after ** close. Persisting the files is useful when other processes that do not ** have write permission on the directory containing the database file want ** to read the database file, as the WAL and shared memory files must exist @@ -992,17 +889,17 @@ ** zero-damage mode setting. ** **
                21. [[SQLITE_FCNTL_OVERWRITE]] ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening ** a write transaction to indicate that, unless it is rolled back for some -** reason, the entire database file will be overwritten by the current +** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. ** **
                22. [[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of ** all [VFSes] in the VFS stack. The names are of all VFS shims and the -** final bottom-level VFS are written into memory obtained from +** final bottom-level VFS are written into memory obtained from ** [sqlite3_malloc()] and the result is stored in the char* variable ** that the fourth parameter of [sqlite3_file_control()] points to. ** The caller is responsible for freeing the memory when done. As with ** all file-control actions, there is no guarantee that this will actually ** do anything. Callers should initialize the char* variable to a NULL @@ -1017,11 +914,11 @@ ** to a pointer to the top-level VFS.)^ ** ^When there are multiple VFS shims in the stack, this opcode finds the ** upper-most shim only. ** **
                23. [[SQLITE_FCNTL_PRAGMA]] -** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] ** file control is sent to the open [sqlite3_file] object corresponding ** to the database file to which the pragma statement refers. ^The argument ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of ** pointers to strings (char**) in which the second element of the array ** is the name of the pragma and the third element is the argument to the @@ -1028,11 +925,11 @@ ** pragma or NULL if the pragma has no argument. ^The handler for an ** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element ** of the char** argument point to a string obtained from [sqlite3_mprintf()] ** or the equivalent and that string will become the result of the pragma or ** the error message if the pragma fails. ^If the -** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] ** file control returns [SQLITE_OK], then the parser assumes that the ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement if result string is NULL, or that returns a copy ** of the result string if the string is non-NULL. @@ -1045,20 +942,20 @@ ** **
                24. [[SQLITE_FCNTL_BUSYHANDLER]] ** ^The [SQLITE_FCNTL_BUSYHANDLER] ** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access -** to the connection's busy-handler callback. The argument is of type (void**) +** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points -** to a function of type (int (*)(void *)). In order to invoke the connection's +** to a function of type (int (*)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. ** **
                25. [[SQLITE_FCNTL_TEMPFILENAME]] -** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control ** to have SQLite generate a ** temporary filename using the same algorithm that is followed to generate ** temporary filenames for TEMP tables and other internal uses. The ** argument should be a char** which will be filled with the filename ** written into memory obtained from [sqlite3_malloc()]. The caller should @@ -1068,11 +965,11 @@ ** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the ** maximum number of bytes that will be used for memory-mapped I/O. ** The argument is a pointer to a value of type sqlite3_int64 that ** is an advisory maximum number of bytes in the file to memory map. The ** pointer is overwritten with the old value. The limit is not changed if -** the value originally pointed to is negative, and so the current limit +** the value originally pointed to is negative, and so the current limit ** can be queried by passing in a pointer to a negative number. This ** file-control is used internally to implement [PRAGMA mmap_size]. ** **
                26. [[SQLITE_FCNTL_TRACE]] ** The [SQLITE_FCNTL_TRACE] file control provides advisory information @@ -1098,15 +995,10 @@ ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This ** opcode causes the xFileControl method to swap the file handle with the one ** pointed to by the pArg argument. This capability is used during testing ** and only needs to be supported when SQLITE_TEST is defined. ** -**
                27. [[SQLITE_FCNTL_NULL_IO]] -** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor -** or file handle for the [sqlite3_file] object such that it will no longer -** read or write to the database file. -** **
                28. [[SQLITE_FCNTL_WAL_BLOCK]] ** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might ** be advantageous to block on the next WAL lock if the lock is not immediately ** available. The WAL subsystem issues this signal during rare ** circumstances in order to fix a problem with priority inversion. @@ -1117,106 +1009,11 @@ ** VFS should return SQLITE_NOTFOUND for this opcode. ** **
                29. [[SQLITE_FCNTL_RBU]] ** 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. -** -**
                30. [[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]. -** -**
                31. [[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]. -** -**
                32. [[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]. -** -**
                33. [[SQLITE_FCNTL_LOCK_TIMEOUT]] -** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS -** to block for up to M milliseconds before failing when attempting to -** obtain a file lock using the xLock or xShmLock methods of the VFS. -** The parameter is a pointer to a 32-bit signed integer that contains -** the value that M is to be set to. Before returning, the 32-bit signed -** integer is overwritten with the previous value of M. -** -**
                34. [[SQLITE_FCNTL_DATA_VERSION]] -** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to -** a database file. The argument is a pointer to a 32-bit unsigned integer. -** The "data version" for the pager is written into the pointer. The -** "data version" changes whenever any change occurs to the corresponding -** database file, either through SQL statements on the same database -** connection or through transactions committed by separate database -** connections possibly in other processes. The [sqlite3_total_changes()] -** interface can be used to find if any database on the connection has changed, -** but that interface responds to changes on TEMP as well as MAIN and does -** not provide a mechanism to detect changes to MAIN only. Also, the -** [sqlite3_total_changes()] interface responds to internal changes only and -** omits changes made by other database connections. The -** [PRAGMA data_version] command provides a mechanism to detect changes to -** a single attached database that occur due to other database connections, -** but omits changes implemented by the database connection on which it is -** called. This file control is the only mechanism to detect changes that -** happen either internally or externally and that are associated with -** a particular attached database. -** -**
                35. [[SQLITE_FCNTL_CKPT_START]] -** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint -** in wal mode before the client starts to copy pages from the wal -** file to the database file. -** -**
                36. [[SQLITE_FCNTL_CKPT_DONE]] -** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint -** in wal mode after the client has finished copying pages from the wal -** file to the database file, but before the *-shm file is updated to -** record the fact that the pages have been checkpointed. -** -**
                37. [[SQLITE_FCNTL_EXTERNAL_READER]] -** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect -** whether or not there is a database client in another process with a wal-mode -** transaction open on the database or not. It is only available on unix.The -** (void*) argument passed with this file-control should be a pointer to a -** value of type (int). The integer value is set to 1 if the database is a wal -** mode database and there exists at least one client in another process that -** currently has an SQL transaction open on the database. It is set to 0 if -** the database is not a wal-mode db, or if there is no such connection in any -** other process. This opcode cannot be used to detect transactions opened -** by clients within the current process, only within other processes. -** -**
                38. [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the -** [checksum VFS shim] only. -** -**
                39. [[SQLITE_FCNTL_RESET_CACHE]] -** If there is currently no transaction open on the database, and the -** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control -** purges the contents of the in-memory page cache. If there is an open -** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. +** this opcode. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 @@ -1244,23 +1041,10 @@ #define SQLITE_FCNTL_RBU 26 #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 -#define SQLITE_FCNTL_LOCK_TIMEOUT 34 -#define SQLITE_FCNTL_DATA_VERSION 35 -#define SQLITE_FCNTL_SIZE_LIMIT 36 -#define SQLITE_FCNTL_CKPT_DONE 37 -#define SQLITE_FCNTL_RESERVE_BYTES 38 -#define SQLITE_FCNTL_CKPT_START 39 -#define SQLITE_FCNTL_EXTERNAL_READER 40 -#define SQLITE_FCNTL_CKSM_FILE 41 -#define SQLITE_FCNTL_RESET_CACHE 42 -#define SQLITE_FCNTL_NULL_IO 43 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO @@ -1286,50 +1070,24 @@ ** structure must be typedefed in order to work around compiler warnings ** on some platforms. */ typedef struct sqlite3_api_routines sqlite3_api_routines; -/* -** CAPI3REF: File Name -** -** Type [sqlite3_filename] is used by SQLite to pass filenames to the -** xOpen method of a [VFS]. It may be cast to (const char*) and treated -** as a normal, nul-terminated, UTF-8 buffer containing the filename, but -** may also be passed to special APIs such as: -** -**
                    -**
                  • sqlite3_filename_database() -**
                  • sqlite3_filename_journal() -**
                  • sqlite3_filename_wal() -**
                  • sqlite3_uri_parameter() -**
                  • sqlite3_uri_boolean() -**
                  • sqlite3_uri_int64() -**
                  • sqlite3_uri_key() -**
                  -*/ -typedef const char *sqlite3_filename; - /* ** CAPI3REF: OS Interface Object ** ** An instance of the sqlite3_vfs object defines the interface between ** the SQLite core and the underlying operating system. The "vfs" ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. ** -** 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 due to an oversight, the structure -** of the sqlite3_vfs object changed 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 increased. +** 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 szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of ** a pathname in this VFS. ** @@ -1360,18 +1118,18 @@ ** the string will be valid and unchanged until xClose() is ** called. Because of the previous sentence, ** the [sqlite3_file] can safely store a pointer to the ** filename if it needs to remember the filename for some reason. ** If the zFilename parameter to xOpen is a NULL pointer then xOpen -** must invent its own temporary name for the file. ^Whenever the +** must invent its own temporary name for the file. ^Whenever the ** xFilename parameter is NULL it will also be the case that the ** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. ** ** The flags argument to xOpen() includes all bits set in ** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] ** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. ** If xOpen() opens a file read-only then it sets *pOutFlags to ** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. ** ** ^(SQLite will also add one of the following flags to the xOpen() ** call, depending on the object being opened: @@ -1381,11 +1139,11 @@ **
                40. [SQLITE_OPEN_MAIN_JOURNAL] **
                41. [SQLITE_OPEN_TEMP_DB] **
                42. [SQLITE_OPEN_TEMP_JOURNAL] **
                43. [SQLITE_OPEN_TRANSIENT_DB] **
                44. [SQLITE_OPEN_SUBJOURNAL] -**
                45. [SQLITE_OPEN_SUPER_JOURNAL] +**
                46. [SQLITE_OPEN_MASTER_JOURNAL] **
                47. [SQLITE_OPEN_WAL] ** )^ ** ** The file I/O implementation can use the object type flags to ** change the way it deals with files. For example, an application @@ -1409,18 +1167,18 @@ ** databases, and subjournals. ** ** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction ** with the [SQLITE_OPEN_CREATE] flag, which are both directly ** analogous to the O_EXCL and O_CREAT flags of the POSIX open() -** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the ** SQLITE_OPEN_CREATE, is used to indicate that file should always ** be created, and that it is an error if it already exists. -** It is not used to indicate the file should be opened +** It is not used to indicate the file should be opened ** for exclusive access. ** ** ^At least szOsFile bytes of memory are allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third +** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to ** allocate the structure; it should just fill it in. Note that ** the xOpen method must set the sqlite3_file.pMethods to either ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods @@ -1429,18 +1187,12 @@ ** ** [[sqlite3_vfs.xAccess]] ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test whether a file is at least readable. The SQLITE_ACCESS_READ -** flag is never actually used and is not implemented in the built-in -** VFSes of SQLite. The file is named by the second argument and can be a -** directory. The xAccess method returns [SQLITE_OK] on success or some -** non-zero error code if there is an I/O error or if the name of -** the file given in the second argument is illegal. If SQLITE_OK -** is returned, then non-zero or zero is written into *pResOut to indicate -** whether or not the file is accessible. +** to test whether a file is at least readable. The file can be a +** directory. ** ** ^SQLite will always allocate at least mxPathname+1 bytes for the ** output buffer xFullPathname. The exact size of the output buffer ** is also passed as a parameter to both methods. If the output buffer ** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is @@ -1456,20 +1208,20 @@ ** The xSleep() method causes the calling thread to sleep for at ** least the number of microseconds given. ^The xCurrentTime() ** method returns a Julian Day Number for the current date and time as ** a floating point value. ** ^The xCurrentTimeInt64() method returns, as an integer, the Julian -** Day Number multiplied by 86400000 (the number of milliseconds in -** a 24-hour day). +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). ** ^SQLite will use the xCurrentTimeInt64() method to get the current -** date and time if that method is available (if iVersion is 2 or +** date and time if that method is available (if iVersion is 2 or ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** ** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided -** by some VFSes to facilitate testing of the VFS code. By overriding +** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can ** simulate faults and error conditions that would otherwise be difficult ** or impossible to induce. The set of system calls that can be overridden ** varies from one VFS to another, and from one version of the same VFS to the ** next. Applications that use these interfaces must be prepared for any @@ -1484,11 +1236,11 @@ int szOsFile; /* Size of subclassed sqlite3_file */ int mxPathname; /* Maximum file pathname length */ sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*, + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); @@ -1512,11 +1264,11 @@ sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. ** New fields may be appended in future versions. The iVersion - ** value will increment whenever this happens. + ** value will increment whenever this happens. */ }; /* ** CAPI3REF: Flags for the xAccess VFS method @@ -1556,11 +1308,11 @@ **
                48. SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED **
                49. SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE ** ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as -** was given on the corresponding lock. +** was given on the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED ** and EXCLUSIVE. */ @@ -1671,27 +1423,24 @@ ** ** The sqlite3_config() interface is not threadsafe. The application ** must ensure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running. ** +** The sqlite3_config() interface +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** ** The first argument to sqlite3_config() is an integer ** [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** -** For most configuration options, the sqlite3_config() interface -** may only be invoked prior to library initialization using -** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. -** The exceptional configuration options that may be invoked at any time -** are called "anytime configuration options". -** ^If sqlite3_config() is called after [sqlite3_initialize()] and before -** [sqlite3_shutdown()] with a first argument that is not an anytime -** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE. -** Note, however, that ^sqlite3_config() can be called as part of the -** implementation of an application-defined [sqlite3_os_init()]. -** ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ SQLITE_API int sqlite3_config(int, ...); @@ -1704,11 +1453,11 @@ ** changes to a [database connection]. The interface is similar to ** [sqlite3_config()] except that the changes apply to a single ** [database connection] (specified in the first argument). ** ** The second argument to sqlite3_db_config(D,V,...) is the -** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code ** that indicates what aspect of the [database connection] is being configured. ** Subsequent arguments vary depending on the configuration verb. ** ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. @@ -1722,11 +1471,11 @@ ** and low-level memory allocation routines. ** ** This object is used in only one place in the SQLite interface. ** A pointer to an instance of this object is the argument to ** [sqlite3_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. ** By creating an instance of this object ** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) ** during configuration, an application can specify an alternative ** memory allocation subsystem for SQLite to use for all of its ** dynamic memory needs. @@ -1752,21 +1501,21 @@ ** The xRoundup method returns what would be the allocated size of ** a memory allocation given a particular requested size. Most memory ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. ** Every memory allocation request coming in through [sqlite3_malloc()] -** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, ** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. For example, -** it might allocate any required mutexes or initialize internal data +** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. ** -** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes ** the xInit method, so the xInit method need not be threadsafe. The ** xShutdown method is only called from [sqlite3_shutdown()] so it does ** not need to be threadsafe either. For all other methods, SQLite ** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the ** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which @@ -1795,27 +1544,10 @@ ** KEYWORDS: {configuration option} ** ** These constants are the available integer configuration options that ** can be passed as the first argument to the [sqlite3_config()] interface. ** -** Most of the configuration options for sqlite3_config() -** will only work if invoked prior to [sqlite3_initialize()] or after -** [sqlite3_shutdown()]. The few exceptions to this rule are called -** "anytime configuration options". -** ^Calling [sqlite3_config()] with a first argument that is not an -** anytime configuration option in between calls to [sqlite3_initialize()] and -** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE. -** -** The set of anytime configuration options can change (by insertions -** and/or deletions) from one release of SQLite to the next. -** As of SQLite version 3.42.0, the complete set of anytime configuration -** options is: -**
                    -**
                  • SQLITE_CONFIG_LOG -**
                  • SQLITE_CONFIG_PCACHE_HDRSZ -**
                  -** ** New configuration options may be added in future releases of SQLite. ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_config()] to make sure that ** the call worked. The [sqlite3_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option @@ -1827,11 +1559,11 @@ ** [threading mode] to Single-thread. In other words, it disables ** all mutexing and puts SQLite into a mode where it can only be used ** by a single thread. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** it is not possible to change the [threading mode] from its default -** value of Single-thread and so [sqlite3_config()] will return +** value of Single-thread and so [sqlite3_config()] will return ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD ** configuration option. ** ** [[SQLITE_CONFIG_MULTITHREAD]]
                  SQLITE_CONFIG_MULTITHREAD
                  **
                  There are no arguments to this option. ^This option sets the @@ -1862,11 +1594,11 @@ ** it is not possible to set the Serialized [threading mode] and ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the ** SQLITE_CONFIG_SERIALIZED configuration option.
                  ** ** [[SQLITE_CONFIG_MALLOC]]
                  SQLITE_CONFIG_MALLOC
                  -**
                  ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is +**
                  ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is ** a pointer to an instance of the [sqlite3_mem_methods] structure. ** The argument specifies ** alternative low-level memory allocation routines to be used in place of ** the memory allocation routines built into SQLite.)^ ^SQLite makes ** its own private copy of the content of the [sqlite3_mem_methods] structure @@ -1879,27 +1611,16 @@ ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation ** 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 ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: **
                    -**
                  • [sqlite3_hard_heap_limit64()] **
                  • [sqlite3_memory_used()] **
                  • [sqlite3_memory_highwater()] **
                  • [sqlite3_soft_heap_limit64()] **
                  • [sqlite3_status64()] **
                  )^ @@ -1907,18 +1628,36 @@ ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory ** allocation statistics are disabled by default. **
                  ** ** [[SQLITE_CONFIG_SCRATCH]]
                  SQLITE_CONFIG_SCRATCH
                  -**
                  The SQLITE_CONFIG_SCRATCH option is no longer used. +**
                  ^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. **

                  ** ** [[SQLITE_CONFIG_PAGECACHE]]
                  SQLITE_CONFIG_PAGECACHE
                  **
                  ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool ** that SQLite can use for the database page cache with the default page -** cache implementation. -** This configuration option is a no-op if an application-defined page +** cache implementation. +** This configuration option is a no-op if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to ** 8-byte aligned memory (pMem), the size of each page cache line (sz), ** and the number of cache lines (N). ** The sz argument should be the size of the largest database page @@ -1941,13 +1680,14 @@ ** page cache memory is needed beyond what is provided by the initial ** allocation, then SQLite goes to [sqlite3_malloc()] separately for each ** additional cache line.
                  ** ** [[SQLITE_CONFIG_HEAP]]
                  SQLITE_CONFIG_HEAP
                  -**
                  ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer +**
                  ^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_PAGECACHE]. +** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and +** [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. ** ^There are three arguments to SQLITE_CONFIG_HEAP: ** An 8-byte aligned pointer to the memory, @@ -1996,11 +1736,11 @@ ** sets the default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] ** option to [sqlite3_db_config()] can be used to change the lookaside ** configuration on individual connections.)^
                  ** ** [[SQLITE_CONFIG_PCACHE2]]
                  SQLITE_CONFIG_PCACHE2
                  -**
                  ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is +**
                  ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.
                  ** ** [[SQLITE_CONFIG_GETPCACHE2]]
                  SQLITE_CONFIG_GETPCACHE2
                  @@ -2010,11 +1750,11 @@ ** ** [[SQLITE_CONFIG_LOG]]
                  SQLITE_CONFIG_LOG
                  **
                  The SQLITE_CONFIG_LOG option is used to configure the SQLite ** global [error log]. ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,int,const char*), +** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger @@ -2119,95 +1859,48 @@ ** [PRAGMA cache_size] setting and this value. ** ** [[SQLITE_CONFIG_STMTJRNL_SPILL]] **
                  SQLITE_CONFIG_STMTJRNL_SPILL **
                  ^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which -** becomes the [statement journal] spill-to-disk threshold. +** becomes the [statement journal] spill-to-disk threshold. ** [Statement journals] are held in memory until their size (in bytes) ** exceeds this threshold, at which point they are written to disk. ** Or if the threshold is -1, statement journals are always held ** exclusively in memory. ** Since many statement journals never become large, setting the spill ** threshold to a value such as 64KiB can greatly reduce the amount of ** I/O required to support statement rollback. ** The default value for this setting is controlled by the ** [SQLITE_STMTJRNL_SPILL] compile-time option. -** -** [[SQLITE_CONFIG_SORTERREF_SIZE]] -**
                  SQLITE_CONFIG_SORTERREF_SIZE -**
                  The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter -** of type (int) - the new value of the sorter-reference size threshold. -** Usually, when SQLite uses an external sort to order records according -** to an ORDER BY clause, all fields required by the caller are present in the -** sorted records. However, if SQLite determines based on the declared type -** of a table column that its values are likely to be very large - larger -** than the configured sorter-reference size threshold - then a reference -** is stored in each sorted record and the required column values loaded -** from the database as records are returned in sorted order. The default -** value for this option is to never use this optimization. Specifying a -** negative value for this option restores the default behavior. -** This option is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. -** -** [[SQLITE_CONFIG_MEMDB_MAXSIZE]] -**
                  SQLITE_CONFIG_MEMDB_MAXSIZE -**
                  The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter -** [sqlite3_int64] parameter which is the default maximum size for an in-memory -** database created using [sqlite3_deserialize()]. This default maximum -** size can be adjusted up or down for individual databases using the -** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this -** configuration setting is never used, then the default maximum is determined -** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that -** compile-time option is not set, then the default maximum is 1073741824. -** -** [[SQLITE_CONFIG_ROWID_IN_VIEW]] -**
                  SQLITE_CONFIG_ROWID_IN_VIEW -**
                  The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability -** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is -** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability -** defaults to on. This configuration option queries the current setting or -** changes the setting to off or on. The argument is a pointer to an integer. -** If that integer initially holds a value of 1, then the ability for VIEWs to -** have ROWIDs is activated. If the integer initially holds zero, then the -** ability is deactivated. Any other initial value for the integer leaves the -** setting unchanged. After changes, if any, the integer is written with -** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite -** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and -** recommended case) then the integer is always filled with zero, regardless -** if its initial value. ** */ -#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ -#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ -#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 /* 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 */ -#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ -#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ -/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ -#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ -#define SQLITE_CONFIG_PCACHE 14 /* no-op */ -#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ -#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ -#define SQLITE_CONFIG_URI 17 /* int */ -#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ -#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#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_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ -#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ -#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ +#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #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 */ -#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ -#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ -#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that @@ -2219,18 +1912,13 @@ ** the call worked. ^The [sqlite3_db_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** **
                  -** [[SQLITE_DBCONFIG_LOOKASIDE]] **
                  SQLITE_DBCONFIG_LOOKASIDE
                  -**
                  The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the -** configuration of the lookaside memory allocator within a database -** connection. -** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are not -** in the [DBCONFIG arguments|usual format]. -** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two. +**
                  ^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. ** ^The first argument (the third parameter to [sqlite3_db_config()] is a ** pointer to a memory buffer to use for lookaside memory. ** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb ** may be NULL in which case SQLite will allocate the ** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the @@ -2241,82 +1929,54 @@ ** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally ** rounded down to the next smaller multiple of 8. ^(The lookaside memory ** configuration for a database connection can only be changed when that ** connection is not currently using lookaside memory, or in other words ** when the "current value" returned by -** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero. +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. ** Any attempt to change the lookaside memory configuration when lookaside -** memory is in use leaves the configuration unchanged and returns +** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^
                  ** -** [[SQLITE_DBCONFIG_ENABLE_FKEY]] **
                  SQLITE_DBCONFIG_ENABLE_FKEY
                  **
                  ^This option is used to enable or disable the enforcement of -** [foreign key constraints]. This is the same setting that is -** enabled or disabled by the [PRAGMA foreign_keys] statement. +** [foreign key constraints]. There should be two additional arguments. ** The first argument is an integer which is 0 to disable FK enforcement, ** positive to enable FK enforcement or negative to leave FK enforcement ** unchanged. The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether FK enforcement is off or on ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back.
                  ** -** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] **
                  SQLITE_DBCONFIG_ENABLE_TRIGGER
                  **
                  ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in -** which case the trigger setting is not reported back. -** -**

                  Originally this option disabled all triggers. ^(However, since -** SQLite version 3.35.0, TEMP triggers are still allowed even if -** this option is off. So, in other words, this option now only disables -** triggers in the main database schema or in the schemas of [ATTACH]-ed -** databases.)^

                  -** -** [[SQLITE_DBCONFIG_ENABLE_VIEW]] -**
                  SQLITE_DBCONFIG_ENABLE_VIEW
                  -**
                  ^This option is used to enable or disable [CREATE VIEW | views]. -** There must be two additional arguments. -** The first argument is an integer which is 0 to disable views, -** positive to enable views or negative to leave the setting unchanged. -** The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether views are disabled or enabled -** following this call. The second parameter may be a NULL pointer, in -** which case the view setting is not reported back. -** -**

                  Originally this option disabled all views. ^(However, since -** SQLite version 3.35.0, TEMP views are still allowed even if -** this option is off. So, in other words, this option now only disables -** views in the main database schema or in the schemas of ATTACH-ed -** databases.)^

                  -** -** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] +** which case the trigger setting is not reported back.
                  +** **
                  SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
                  -**
                  ^This option is used to enable or disable the -** [fts3_tokenizer()] function which is part of the +**
                  ^This option is used to enable or disable the two-argument +** version of the [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. -** There must be two additional arguments. +** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or ** positive to enable fts3_tokenizer() or negative to leave the setting ** unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back.
                  ** -** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] **
                  SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
                  **
                  ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. -** There must be two additional arguments. +** There should be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. ** If the first argument is -1, then no changes are made to state of either the ** C-API or the SQL function. @@ -2324,310 +1984,53 @@ ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may ** be a NULL pointer, in which case the new setting is not reported back. **
                  ** -** [[SQLITE_DBCONFIG_MAINDBNAME]]
                  SQLITE_DBCONFIG_MAINDBNAME
                  +**
                  SQLITE_DBCONFIG_MAINDBNAME
                  **
                  ^This option is used to change the name of the "main" database -** schema. This option does not follow the -** [DBCONFIG arguments|usual SQLITE_DBCONFIG argument format]. -** This option takes exactly one argument, which ust be a pointer -** to a constant UTF8 string which will become the new schema name -** in place of "main". ^SQLite does not make a copy of the new main -** schema name string, so the application must ensure that the argument -** passed into SQLITE_DBCONFIG MAINDBNAME is unchanged +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged ** until after the database connection closes. **
                  ** -** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] **
                  SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
                  -**
                  Usually, when a database in [WAL mode] is closed or detached from a -** database handle, SQLite checks if if there are other connections to the -** same database, and if there are no other database connection (if the -** connection being closed is the last open connection to the database), -** then SQLite performs a [checkpoint] before closing the connection and -** deletes the WAL file. The SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE option can -** be used to override that behavior. The first parameter passed to this -** operation is an integer - positive to disable checkpoints-on-close, or -** zero (the default) to enable them, and negative to leave the setting unchanged. -** The second parameter is a pointer to an integer +**
                  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]]
                  SQLITE_DBCONFIG_ENABLE_QPSG
                  +**
                  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. -** The first argument to this setting is an integer which is 0 to disable -** the QPSG, positive to enable QPSG, or negative to leave the setting -** unchanged. The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether the QPSG is disabled or enabled -** following this call. -**
                  -** -** [[SQLITE_DBCONFIG_TRIGGER_EQP]]
                  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 - -** positive to enable output for trigger programs, or zero to disable it, -** or negative to leave the setting unchanged. -** 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. -**
                  -** -** [[SQLITE_DBCONFIG_RESET_DATABASE]]
                  SQLITE_DBCONFIG_RESET_DATABASE
                  -**
                  Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run -** [VACUUM] in order to reset a database back to an empty database -** with no schema and no content. The following process works even for -** a badly corrupted database file: -**
                    -**
                  1. If the database connection is newly opened, make sure it has read the -** database schema by preparing then discarding some query against the -** database, or calling sqlite3_table_column_metadata(), ignoring any -** errors. This step is only necessary if the application desires to keep -** the database in WAL mode after the reset if it was in WAL mode before -** the reset. -**
                  2. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); -**
                  3. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); -**
                  4. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); -**
                  -** Because resetting a database is destructive and irreversible, the -** process requires the use of this obscure API and multiple steps to -** help ensure that it does not happen by accident. Because this -** feature must be capable of resetting corrupt databases, and -** shutting down virtual tables may require access to that corrupt -** storage, the library must abandon any installed virtual tables -** without calling their xDestroy() methods. -** -** [[SQLITE_DBCONFIG_DEFENSIVE]]
                  SQLITE_DBCONFIG_DEFENSIVE
                  -**
                  The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the -** "defensive" flag for a database connection. When the defensive -** flag is enabled, language features that allow ordinary SQL to -** deliberately corrupt the database file are disabled. The disabled -** features include but are not limited to the following: -**
                    -**
                  • The [PRAGMA writable_schema=ON] statement. -**
                  • The [PRAGMA journal_mode=OFF] statement. -**
                  • The [PRAGMA schema_version=N] statement. -**
                  • Writes to the [sqlite_dbpage] virtual table. -**
                  • Direct writes to [shadow tables]. -**
                  -**
                  -** -** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]]
                  SQLITE_DBCONFIG_WRITABLE_SCHEMA
                  -**
                  The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the -** "writable_schema" flag. This has the same effect and is logically equivalent -** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF]. -** The first argument to this setting is an integer which is 0 to disable -** the writable_schema, positive to enable writable_schema, or negative to -** leave the setting unchanged. The second parameter is a pointer to an -** integer into which is written 0 or 1 to indicate whether the writable_schema -** is enabled or disabled following this call. -**
                  -** -** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] -**
                  SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
                  -**
                  The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates -** the legacy behavior of the [ALTER TABLE RENAME] command such it -** behaves as it did prior to [version 3.24.0] (2018-06-04). See the -** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for -** additional information. This feature can also be turned on and off -** using the [PRAGMA legacy_alter_table] statement. -**
                  -** -** [[SQLITE_DBCONFIG_DQS_DML]] -**
                  SQLITE_DBCONFIG_DQS_DML
                  -**
                  The SQLITE_DBCONFIG_DQS_DML option activates or deactivates -** the legacy [double-quoted string literal] misfeature for DML statements -** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The -** default value of this setting is determined by the [-DSQLITE_DQS] -** compile-time option. -**
                  -** -** [[SQLITE_DBCONFIG_DQS_DDL]] -**
                  SQLITE_DBCONFIG_DQS_DDL
                  -**
                  The SQLITE_DBCONFIG_DQS option activates or deactivates -** the legacy [double-quoted string literal] misfeature for DDL statements, -** such as CREATE TABLE and CREATE INDEX. The -** default value of this setting is determined by the [-DSQLITE_DQS] -** compile-time option. -**
                  -** -** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] -**
                  SQLITE_DBCONFIG_TRUSTED_SCHEMA
                  -**
                  The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to -** assume that database schemas are untainted by malicious content. -** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite -** takes additional defensive steps to protect the application from harm -** including: -**
                    -**
                  • Prohibit the use of SQL functions inside triggers, views, -** CHECK constraints, DEFAULT clauses, expression indexes, -** partial indexes, or generated columns -** unless those functions are tagged with [SQLITE_INNOCUOUS]. -**
                  • Prohibit the use of virtual tables inside of triggers or views -** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS]. -**
                  -** This setting defaults to "on" for legacy compatibility, however -** all applications are advised to turn it off if possible. This setting -** can also be controlled using the [PRAGMA trusted_schema] statement. -**
                  -** -** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] -**
                  SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
                  -**
                  The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates -** the legacy file format flag. When activated, this flag causes all newly -** created database file to have a schema format version number (the 4-byte -** integer found at offset 44 into the database header) of 1. This in turn -** means that the resulting database file will be readable and writable by -** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, -** newly created databases are generally not understandable by SQLite versions -** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there -** is now scarcely any need to generate database files that are compatible -** all the way back to version 3.0.0, and so this setting is of little -** practical use, but is provided so that SQLite can continue to claim the -** ability to generate new database files that are compatible with version -** 3.0.0. -**

                  Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on, -** the [VACUUM] command will fail with an obscure error when attempting to -** process a table with generated columns and a descending index. This is -** not considered a bug since SQLite versions 3.3.0 and earlier do not support -** either generated columns or descending indexes. -**

                  -** -** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] -**
                  SQLITE_DBCONFIG_STMT_SCANSTATUS
                  -**
                  The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears -** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() -** statistics. For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is prepared and when it -** is stepped. The flag is set (collection of statistics is enabled) -** by default.

                  This option takes two arguments: an integer and a pointer to -** an integer.. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the statement scanstatus option. If the second argument -** is not NULL, then the value of the statement scanstatus setting after -** processing the first argument is written into the integer that the second -** argument points to. -**

                  -** -** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]] -**
                  SQLITE_DBCONFIG_REVERSE_SCANORDER
                  -**
                  The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order -** in which tables and indexes are scanned so that the scans start at the end -** and work toward the beginning rather than starting at the beginning and -** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the -** same as setting [PRAGMA reverse_unordered_selects].

                  This option takes -** two arguments which are an integer and a pointer to an integer. The first -** argument is 1, 0, or -1 to enable, disable, or leave unchanged the -** reverse scan order flag, respectively. If the second argument is not NULL, -** then 0 or 1 is written into the integer that the second argument points to -** depending on if the reverse scan order flag is set after processing the -** first argument. -**

                  -** -** [[SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]] -**
                  SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE
                  -**
                  The SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE option enables or disables -** the ability of the [ATTACH DATABASE] SQL command to create a new database -** file if the database filed named in the ATTACH command does not already -** exist. This ability of ATTACH to create a new database is enabled by -** default. Applications can disable or reenable the ability for ATTACH to -** create new database files using this DBCONFIG option.

                  -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the attach-create flag, respectively. If the second -** argument is not NULL, then 0 or 1 is written into the integer that the -** second argument points to depending on if the attach-create flag is set -** after processing the first argument. -**

                  -** -** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]] -**
                  SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE
                  -**
                  The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the -** ability of the [ATTACH DATABASE] SQL command to open a database for writing. -** This capability is enabled by default. Applications can disable or -** reenable this capability using the current DBCONFIG option. If the -** the this capability is disabled, the [ATTACH] command will still work, -** but the database will be opened read-only. If this option is disabled, -** then the ability to create a new database using [ATTACH] is also disabled, -** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE] -** option.

                  -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the ability to ATTACH another database for writing, -** respectively. If the second argument is not NULL, then 0 or 1 is written -** into the integer to which the second argument points, depending on whether -** the ability to ATTACH a read/write database is enabled or disabled -** after processing the first argument. -**

                  -** -** [[SQLITE_DBCONFIG_ENABLE_COMMENTS]] -**
                  SQLITE_DBCONFIG_ENABLE_COMMENTS
                  -**
                  The SQLITE_DBCONFIG_ENABLE_COMMENTS option enables or disables the -** ability to include comments in SQL text. Comments are enabled by default. -** An application can disable or reenable comments in SQL text using this -** DBCONFIG option.

                  -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is 1, 0, or -1 to enable, disable, or -** leave unchanged the ability to use comments in SQL text, -** respectively. If the second argument is not NULL, then 0 or 1 is written -** into the integer that the second argument points to depending on if -** comments are allowed in SQL text after processing the first argument. **

                  ** ** -** -** [[DBCONFIG arguments]]

                  Arguments To SQLITE_DBCONFIG Options

                  -** -**

                  Most of the SQLITE_DBCONFIG options take two arguments: an integer -** and a pointer to an integer. If the first integer argument is 1, then -** the option becomes enabled. If the first integer argument is 0, then the -** option is disabled. If the first argument is -1, then the option setting -** is unchanged. The second argument, the pointer to an integer, may be NULL. -** If the second argument is not NULL, then a value of 0 or 1 is written into -** the integer to which the second argument points, depending on whether the -** setting is disabled or enabled after applying any changes specified by -** the first argument. -** -**

                  While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] -** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the -** documentation of those exceptional options for details. */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #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_RESET_DATABASE 1009 /* int int* */ -#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ -#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ -#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ -#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ -#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ -#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ -#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */ -#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */ -#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ + /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 ** @@ -2650,30 +2053,30 @@ ** is another alias for the rowid. ** ** ^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 +** 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 +** 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 +** 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 +** ^(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 ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, @@ -2702,122 +2105,91 @@ /* ** 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 +** 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 ** -** ^These functions return the number of rows modified, inserted or +** ^This function returns the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE ** statement on the database connection specified by the only parameter. -** The two functions are identical except for the type of the return value -** and that if the number of rows modified by the most recent INSERT, UPDATE, -** or DELETE is greater than the maximum value supported by type "int", then -** the return value of sqlite3_changes() is undefined. ^Executing any other -** type of SQL statement does not modify the value returned by these functions. -** For the purposes of this interface, a CREATE TABLE AS SELECT statement -** does not count as an INSERT, UPDATE or DELETE statement and hence the rows -** added to the new table by the CREATE TABLE AS SELECT statement are not -** counted. +** ^Executing any other type of SQL statement does not modify the value +** returned by this function. ** ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are -** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], +** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], ** [foreign key actions] or [REPLACE] constraint resolution are not counted. -** -** Changes to a view that are intercepted by -** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value -** returned by sqlite3_changes() immediately after an INSERT, UPDATE or -** DELETE statement run on a view is always zero. Only changes made to real +** +** Changes to a view that are intercepted by +** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value +** returned by sqlite3_changes() immediately after an INSERT, UPDATE or +** DELETE statement run on a view is always zero. Only changes made to real ** tables are counted. ** ** Things are more complicated if the sqlite3_changes() function is ** executed while a trigger program is running. This may happen if the ** program uses the [changes() SQL function], or if some other callback ** function invokes sqlite3_changes() directly. Essentially: -** +** **

                    **
                  • ^(Before entering a trigger program the value returned by -** sqlite3_changes() function is saved. After the trigger program +** sqlite3_changes() function is saved. After the trigger program ** has finished, the original value is restored.)^ -** -**
                  • ^(Within a trigger program each INSERT, UPDATE and DELETE -** statement sets the value returned by sqlite3_changes() -** upon completion as normal. Of course, this value will not include -** any changes performed by sub-triggers, as the sqlite3_changes() +** +**
                  • ^(Within a trigger program each INSERT, UPDATE and DELETE +** statement sets the value returned by sqlite3_changes() +** upon completion as normal. Of course, this value will not include +** any changes performed by sub-triggers, as the sqlite3_changes() ** value will be saved and restored after each sub-trigger has run.)^ **
                  -** +** ** ^This means that if the changes() SQL function (or similar) is used -** by the first INSERT, UPDATE or DELETE statement within a trigger, it +** by the first INSERT, UPDATE or DELETE statement within a trigger, it ** returns the value as set when the calling statement began executing. -** ^If it is used by the second or subsequent such statement within a trigger -** program, the value returned reflects the number of rows modified by the +** ^If it is used by the second or subsequent such statement within a trigger +** program, the value returned reflects the number of rows modified by the ** previous INSERT, UPDATE or DELETE statement within the same trigger. ** +** See also the [sqlite3_total_changes()] interface, the +** [count_changes pragma], and the [changes() SQL function]. +** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. -** -** See also: -**
                    -**
                  • the [sqlite3_total_changes()] interface -**
                  • the [count_changes pragma] -**
                  • the [changes() SQL function] -**
                  • the [data_version pragma] -**
                  */ SQLITE_API int sqlite3_changes(sqlite3*); -SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** -** ^These functions return the total number of rows inserted, modified or +** ^This function returns the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed ** since the database connection was opened, including those executed as -** part of trigger programs. The two functions are identical except for the -** type of the return value and that if the number of rows modified by the -** connection exceeds the maximum value supported by type "int", then -** the return value of sqlite3_total_changes() is undefined. ^Executing -** any other type of SQL statement does not affect the value returned by -** sqlite3_total_changes(). -** +** part of trigger programs. ^Executing any other type of SQL statement +** does not affect the value returned by sqlite3_total_changes(). +** ** ^Changes made as part of [foreign key actions] are included in the ** count, but those made as part of REPLACE constraint resolution are -** not. ^Changes to a view that are intercepted by INSTEAD OF triggers +** not. ^Changes to a view that are intercepted by INSTEAD OF triggers ** are not counted. -** -** The [sqlite3_total_changes(D)] interface only reports the number -** of rows that changed due to SQL statement run against database -** connection D. Any changes by other database connections are ignored. -** To detect changes against a database file from other database -** connections use the [PRAGMA data_version] command or the -** [SQLITE_FCNTL_DATA_VERSION] [file control]. +** +** See also the [sqlite3_changes()] interface, the +** [count_changes pragma], and the [total_changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. -** -** See also: -**
                    -**
                  • the [sqlite3_changes()] interface -**
                  • the [count_changes pragma] -**
                  • the [changes() SQL function] -**
                  • the [data_version pragma] -**
                  • the [SQLITE_FCNTL_DATA_VERSION] [file control] -**
                  */ SQLITE_API int sqlite3_total_changes(sqlite3*); -SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** @@ -2841,25 +2213,20 @@ ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** ** ^The sqlite3_interrupt(D) call is in effect until all currently running ** SQL statements on [database connection] D complete. ^Any new SQL statements -** that are started after the sqlite3_interrupt() call and before the -** running statement count reaches zero are interrupted as if they had been +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^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. -** -** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether -** or not an interrupt is currently in effect for [database connection] D. -** It returns 1 if an interrupt is currently in effect, or 0 otherwise. */ SQLITE_API void sqlite3_interrupt(sqlite3*); -SQLITE_API int sqlite3_is_interrupted(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete ** ** These routines are useful during command-line input to determine if the @@ -2878,11 +2245,11 @@ ** memory allocation fails, then SQLITE_NOMEM is returned. ** ** ^These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. ** -** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked ** automatically by sqlite3_complete16(). If that initialization fails, ** then the return value from sqlite3_complete16() will be non-zero ** regardless of whether or not the input SQL is complete.)^ ** @@ -2923,11 +2290,11 @@ ** is made to access the database and the cycle repeats. ** ** The presence of a busy handler does not guarantee that it will be invoked ** when there is lock contention. ^If SQLite determines that invoking the busy ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] -** to the application instead of invoking the +** to the application instead of invoking the ** busy handler. ** Consider a scenario where one process is holding a read lock that ** it is trying to promote to a reserved lock and ** a second process is holding a reserved lock that it is trying ** to promote to an exclusive lock. The first process cannot proceed @@ -2948,11 +2315,11 @@ ** ** The busy callback should not take any actions which modify the ** database connection that invoked the busy handler. In other words, ** the busy handler is not reentrant. Any such actions ** result in undefined behavior. -** +** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); @@ -3015,13 +2382,13 @@ ** Alice | 43 ** Bob | 28 ** Cindy | 21 ** ** -** There are two columns (M==2) and three rows (N==3). Thus the +** There are two column (M==2) and three rows (N==3). Thus the ** result table has 8 entries. Suppose the result table is stored -** in an array named azResult. Then azResult holds this content: +** in an array names azResult. Then azResult holds this content: ** **
                   **        azResult[0] = "Name";
                   **        azResult[1] = "Age";
                   **        azResult[2] = "Alice";
                  @@ -3065,20 +2432,20 @@
                   /*
                   ** CAPI3REF: Formatted String Printing Functions
                   **
                   ** These routines are work-alikes of the "printf()" family of functions
                   ** from the standard C library.
                  -** These routines understand most of the common formatting options from
                  -** the standard library printf()
                  -** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
                  -** See the [built-in printf()] documentation for details.
                  +** These routines understand most of the common K&R formatting options,
                  +** plus some additional non-standard formats, detailed below.
                  +** Note that some of the more obscure formatting options from recent
                  +** C-library standards are omitted from this implementation.
                   **
                   ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
                  -** results into memory obtained from [sqlite3_malloc64()].
                  +** results into memory obtained from [sqlite3_malloc()].
                   ** The strings returned by these two routines should be
                   ** released by [sqlite3_free()].  ^Both routines return a
                  -** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
                  +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
                   ** memory to hold the resulting string.
                   **
                   ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
                   ** the standard C library.  The result is written into the
                   ** buffer supplied as the second parameter whose size is given by
                  @@ -3098,11 +2465,75 @@
                   ** the zero terminator.  So the longest string that can be completely
                   ** written will be n-1 characters.
                   **
                   ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
                   **
                  -** See also:  [built-in printf()], [printf() SQL function]
                  +** These routines all implement some additional formatting
                  +** options that are useful for constructing SQL statements.
                  +** All of the usual printf() formatting options apply.  In addition, there
                  +** is are "%q", "%Q", "%w" and "%z" options.
                  +**
                  +** ^(The %q option works like %s in that it substitutes a nul-terminated
                  +** string from the argument list.  But %q also doubles every '\'' character.
                  +** %q is designed for use inside a string literal.)^  By doubling each '\''
                  +** character it escapes that character and allows it to be inserted into
                  +** the string.
                  +**
                  +** For example, assume the string variable zText contains text as follows:
                  +**
                  +** 
                  +**  char *zText = "It's a happy day!";
                  +** 
                  +** +** One can use this text in an SQL statement as follows: +** +**
                  +**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
                  +**  sqlite3_exec(db, zSQL, 0, 0, 0);
                  +**  sqlite3_free(zSQL);
                  +** 
                  +** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
                  +**  INSERT INTO table1 VALUES('It''s a happy day!')
                  +** 
                  +** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
                  +**  INSERT INTO table1 VALUES('It's a happy day!');
                  +** 
                  +** +** This second example is an SQL syntax error. As a general rule you should +** always use %q instead of %s when inserting text into a string literal. +** +** ^(The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes).)^ So, for example, one could say: +** +**
                  +**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
                  +**  sqlite3_exec(db, zSQL, 0, 0, 0);
                  +**  sqlite3_free(zSQL);
                  +** 
                  +** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** ^(The "%w" formatting option is like "%q" except that it expects to +** be contained within double-quotes instead of single quotes, and it +** escapes the double-quote character instead of the single-quote +** character.)^ The "%w" formatting option is intended for safely inserting +** table and column names into a constructed SQL statement. +** +** ^(The "%z" formatting option works like "%s" but with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string.)^ */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); @@ -3110,11 +2541,11 @@ /* ** CAPI3REF: Memory Allocation Subsystem ** ** The SQLite core uses these three routines for all of its own ** internal memory allocation needs. "Core" in the previous sentence -** does not include operating-system specific [VFS] implementation. The +** does not include operating-system specific VFS implementation. The ** Windows VFS uses native malloc() and free() for some operations. ** ** ^The sqlite3_malloc() routine returns a pointer to a block ** of memory at least N bytes in length, where N is the parameter. ** ^If sqlite3_malloc() is unable to obtain sufficient free @@ -3170,10 +2601,23 @@ ** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), ** sqlite3_malloc64(), and sqlite3_realloc64() ** is always aligned to at least an 8 byte boundary, or to a ** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time ** option is used. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be used. +** +** Prior to SQLite version 3.7.10, the Windows OS interface layer called +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular Windows +** installation. Memory allocation errors were detected, but +** they were reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] ** must be either NULL or else pointers obtained from a prior ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. @@ -3219,11 +2663,11 @@ ** CAPI3REF: Pseudo-Random Number Generator ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to ** select random [ROWID | ROWIDs] when inserting new records into a table that ** already uses the largest possible [ROWID]. The PRNG is also used for -** the built-in random() and randomblob() SQL functions. This interface allows +** the build-in random() and randomblob() SQL functions. This interface allows ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. ** ^The P parameter can be a NULL pointer. ** @@ -3262,11 +2706,11 @@ ** ** When the callback returns [SQLITE_OK], that means the operation ** requested is ok. ^When the callback returns [SQLITE_DENY], the ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that -** access is denied. +** access is denied. ** ** ^The first parameter to the authorizer callback is a copy of the third ** parameter to the sqlite3_set_authorizer() interface. ^The second parameter ** to the callback is an integer [SQLITE_COPY | action code] that specifies ** the particular action to be authorized. ^The third through sixth parameters @@ -3315,11 +2759,11 @@ ** the database connection that invoked the authorizer callback. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** ** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the -** statement might be re-prepared during [sqlite3_step()] due to a +** statement might be re-prepared during [sqlite3_step()] due to a ** schema change. Hence, the application should ensure that the ** correct authorizer callback remains in place during the [sqlite3_step()]. ** ** ^Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not @@ -3402,12 +2846,12 @@ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* -** CAPI3REF: Deprecated Tracing And Profiling Functions -** DEPRECATED +** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 ** ** These routines are deprecated. Use the [sqlite3_trace_v2()] interface ** instead of the routines described here. ** ** These routines register callback functions that can be used for @@ -3429,13 +2873,13 @@ ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite -** might provide greater resolution on the profiler callback. Invoking -** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the -** profile callback. +** might provide greater resolution on the profiler callback. The +** sqlite3_profile() function is considered experimental and is +** subject to change in future versions of SQLite. */ SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); @@ -3443,12 +2887,12 @@ /* ** CAPI3REF: SQL Trace Event Codes ** KEYWORDS: SQLITE_TRACE ** ** These constants identify classes of events that can be monitored -** 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 +** using the [sqlite3_trace_v2()] tracing logic. The third argument +** to [sqlite3_trace_v2()] 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. ** ** New tracing constants may be added in future releases. ** @@ -3463,27 +2907,27 @@ **
                  ^An SQLITE_TRACE_STMT callback is invoked when a prepared statement ** first begins running and possibly at other times during the ** execution of the prepared statement, such as at the start of each ** trigger subprogram. ^The P argument is a pointer to the ** [prepared statement]. ^The X argument is a pointer to a string which -** is the unexpanded SQL text of the prepared statement or an SQL comment +** is the unexpanded SQL text of the prepared statement or an SQL comment ** that indicates the invocation of a trigger. ^The callback can compute ** the same text that would have been returned by the legacy [sqlite3_trace()] ** interface by using the X argument when X begins with "--" and invoking ** [sqlite3_expanded_sql(P)] otherwise. ** ** [[SQLITE_TRACE_PROFILE]]
                  SQLITE_TRACE_PROFILE
                  **
                  ^An SQLITE_TRACE_PROFILE callback provides approximately the same ** information as is provided by the [sqlite3_profile()] callback. ** ^The P argument is a pointer to the [prepared statement] and the -** X argument points to a 64-bit integer which is approximately -** the number of nanoseconds that the prepared statement took to run. +** X argument points to a 64-bit integer which is the estimated of +** the number of nanosecond that the prepared statement took to run. ** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. ** ** [[SQLITE_TRACE_ROW]]
                  SQLITE_TRACE_ROW
                  **
                  ^An SQLITE_TRACE_ROW callback is invoked whenever a prepared -** statement generates a single row of result. +** statement generates a single row of result. ** ^The P argument is a pointer to the [prepared statement] and the ** X argument is unused. ** ** [[SQLITE_TRACE_CLOSE]]
                  SQLITE_TRACE_CLOSE
                  **
                  ^An SQLITE_TRACE_CLOSE callback is invoked when a database @@ -3506,16 +2950,14 @@ ** and context pointer P. ^If the X callback is ** NULL or if the M mask is zero, then tracing is disabled. The ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** -** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P) -** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or -** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each -** database connection may have at most one trace callback. +** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides +** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). ** -** ^The X callback is invoked whenever any of the events identified by +** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently ** ignored, though this may change in future releases. Callback ** implementations should return zero to ensure future compatibility. ** ** ^A trace callback is invoked with four arguments: callback(T,C,P,X). @@ -3539,16 +2981,16 @@ ** CAPI3REF: Query Progress Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to -** [sqlite3_step()] and [sqlite3_prepare()] and similar for +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** -** ^The parameter P is passed through as the only parameter to the -** callback function X. ^The parameter N is the approximate number of +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the approximate number of ** [virtual machine instructions] that are evaluated between successive ** invocations of the callback X. ^If N is less than one then the progress ** handler is disabled. ** ** ^Only a single progress handler may be defined at one time per @@ -3564,25 +3006,18 @@ ** The progress handler callback must not do anything that will modify ** the database connection that invoked the progress handler. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** -** The progress handler callback would originally only be invoked from the -** bytecode engine. It still might be invoked during [sqlite3_prepare()] -** and similar because those routines might force a reparse of the schema -** which involves running the bytecode engine. However, beginning with -** SQLite version 3.41.0, the progress handler callback might also be -** invoked directly from [sqlite3_prepare()] while analyzing and generating -** code for complex queries. */ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection ** CONSTRUCTOR: sqlite3 ** -** ^These routines open an SQLite database file as specified by the +** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte ** order for sqlite3_open16(). ^(A [database connection] handle is usually ** returned in *ppDb, even if an error occurs. The only exception is that ** if SQLite is unable to allocate memory to hold the [sqlite3] object, @@ -3602,97 +3037,47 @@ ** passing it to [sqlite3_close()] when it is no longer required. ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. ^(The flags parameter to -** sqlite3_open_v2() must include, at a minimum, one of the following -** three flag combinations:)^ +** sqlite3_open_v2() can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ ** **
                  ** ^(
                  [SQLITE_OPEN_READONLY]
                  -**
                  The database is opened in read-only mode. If the database does -** not already exist, an error is returned.
                  )^ +**
                  The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
                  )^ ** ** ^(
                  [SQLITE_OPEN_READWRITE]
                  -**
                  The database is opened for reading and writing if possible, or -** reading only if the file is write protected by the operating -** system. In either case the database must already exist, otherwise -** an error is returned. For historical reasons, if opening in -** read-write mode fails due to OS-level permissions, an attempt is -** made to open it in read-only mode. [sqlite3_db_readonly()] can be -** used to determine whether the database is actually -** read-write.
                  )^ +**
                  The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
                  )^ ** ** ^(
                  [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
                  **
                  The database is opened for reading and writing, and is created if ** it does not already exist. This is the behavior that is always used for ** sqlite3_open() and sqlite3_open16().
                  )^ **
                  ** -** In addition to the required flags, the following optional flags are -** also supported: -** -**
                  -** ^(
                  [SQLITE_OPEN_URI]
                  -**
                  The filename can be interpreted as a URI if this flag is set.
                  )^ -** -** ^(
                  [SQLITE_OPEN_MEMORY]
                  -**
                  The database will be opened as an in-memory database. The database -** is named by the "filename" argument for the purposes of cache-sharing, -** if shared cache mode is enabled, but the "filename" is otherwise ignored. -**
                  )^ -** -** ^(
                  [SQLITE_OPEN_NOMUTEX]
                  -**
                  The new database connection will use the "multi-thread" -** [threading mode].)^ This means that separate threads are allowed -** to use SQLite at the same time, as long as each thread is using -** a different [database connection]. -** -** ^(
                  [SQLITE_OPEN_FULLMUTEX]
                  -**
                  The new database connection will use the "serialized" -** [threading mode].)^ This means the multiple threads can safely -** attempt to use the same database connection at the same time. -** (Mutexes will block any actual concurrency, but in this mode -** there is no harm in trying.) -** -** ^(
                  [SQLITE_OPEN_SHAREDCACHE]
                  -**
                  The database is opened [shared cache] enabled, overriding -** the default shared cache setting provided by -** [sqlite3_enable_shared_cache()].)^ -** The [use of shared cache mode is discouraged] and hence shared cache -** capabilities may be omitted from many builds of SQLite. In such cases, -** this option is a no-op. -** -** ^(
                  [SQLITE_OPEN_PRIVATECACHE]
                  -**
                  The database is opened [shared cache] disabled, overriding -** the default shared cache setting provided by -** [sqlite3_enable_shared_cache()].)^ -** -** [[OPEN_EXRESCODE]] ^(
                  [SQLITE_OPEN_EXRESCODE]
                  -**
                  The database connection comes up in "extended result code mode". -** In other words, the database behaves as if -** [sqlite3_extended_result_codes(db,1)] were called on the database -** connection as soon as the connection is created. In addition to setting -** the extended result code mode, this flag also causes [sqlite3_open_v2()] -** to return an extended result code.
                  -** -** [[OPEN_NOFOLLOW]] ^(
                  [SQLITE_OPEN_NOFOLLOW]
                  -**
                  The database filename is not allowed to contain a symbolic link
                  -**
                  )^ -** ** If the 3rd parameter to sqlite3_open_v2() is not one of the -** required combinations shown above optionally combined with other +** combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] -** then the behavior is undefined. Historic versions of SQLite -** have silently ignored surplus bits in the flags parameter to -** sqlite3_open_v2(), however that behavior might not be carried through -** into future versions of SQLite and so applications should not rely -** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op -** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause -** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE -** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not -** by sqlite3_open_v2(). +** then the behavior is undefined. +** +** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. ^If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. ^The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. @@ -3712,30 +3097,30 @@ ** [[URI filenames in sqlite3_open()]]

                  URI Filenames

                  ** ** ^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 third argument to sqlite3_open_v2(), or if it has +** set in the fourth 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. -** URI filename interpretation is turned off +** As of SQLite version 3.7.7, 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. ** ** URI filenames are parsed according to RFC 3986. ^If the URI contains an -** authority, then it must be either an empty string or the string -** "localhost". ^If the authority is not an empty string or "localhost", an -** error is returned to the caller. ^The fragment component of a URI, if +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file -** which contains the database. ^If the path begins with a '/' character, -** then it is interpreted as an absolute path. ^If the path does not begin +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) -** then the path is interpreted as a relative path. -** ^(On windows, the first component of an absolute path +** then the path is interpreted as a relative path. +** ^(On windows, the first component of an absolute path ** is a drive specification (e.g. "C:").)^ ** ** [[core URI query parameters]] ** The query component of a URI may contain parameters that are interpreted ** either by SQLite itself, or by a [VFS | custom VFS implementation]. @@ -3751,27 +3136,27 @@ ** present, then the VFS specified by the option takes precedence over ** the value passed as the fourth parameter to sqlite3_open_v2(). ** **
                50. mode: ^(The mode parameter may be set to either "ro", "rw", ** "rwc", or "memory". Attempting to set it to any other value is -** an error)^. -** ^If "ro" is specified, then the database is opened for read-only -** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the -** third argument to sqlite3_open_v2(). ^If the mode option is set to -** "rw", then the database is opened for read-write (but not create) -** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had -** been set. ^Value "rwc" is equivalent to setting both +** an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_open_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both ** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is ** set to "memory" then a pure [in-memory database] that never reads ** or writes from disk is used. ^It is an error to specify a value for ** the mode parameter that is less restrictive than that specified by ** the flags passed in the third parameter to sqlite3_open_v2(). ** **
                51. cache: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to -** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** @@ -3793,11 +3178,11 @@ ** privilege, and so the database is opened read-only and all locking ** and change detection is disabled. Caution: Setting the immutable ** property on a database file that does in fact change can result ** in incorrect query results and/or [SQLITE_CORRUPT] errors. ** See also: [SQLITE_IOCAP_IMMUTABLE]. -** +** ** ** ** ^Specifying an unknown parameter in the query component of a URI is not an ** error. Future versions of SQLite might understand additional query ** parameters. See "[query parameters with special meaning to SQLite]" for @@ -3805,41 +3190,40 @@ ** ** [[URI filename examples]]

                  URI filename examples

                  ** **
                **
                URI filenames Results -**
                file:data.db +**
                file:data.db ** Open the file "data.db" in the current directory. **
                file:/home/fred/data.db
                -** file:///home/fred/data.db
                -** file://localhost/home/fred/data.db
                +** file:///home/fred/data.db
                +** file://localhost/home/fred/data.db
                ** Open the database file "/home/fred/data.db". -**
                file://darkstar/home/fred/data.db +**
                file://darkstar/home/fred/data.db ** An error. "darkstar" is not a recognized authority. -**
                +**
                ** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db ** Windows only: Open the file "data.db" on fred's desktop on drive -** C:. Note that the %20 escaping in this example is not strictly +** C:. Note that the %20 escaping in this example is not strictly ** necessary - space characters can be used literally ** in URI filenames. -**
                file:data.db?mode=ro&cache=private +**
                file:data.db?mode=ro&cache=private ** Open file "data.db" in the current directory for read-only access. ** Regardless of whether or not shared-cache mode is enabled by ** default, use a private cache. **
                file:/home/fred/data.db?vfs=unix-dotfile ** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" ** that uses dot-files in place of posix advisory locking. -**
                file:data.db?mode=readonly +**
                file:data.db?mode=readonly ** An error. "readonly" is not a valid option for the "mode" parameter. -** Use "ro" instead: "file:data.db?mode=ro". **
                ** ** ^URI hexadecimal escape sequences (%HH) are supported within the path and ** query components of a URI. A hexadecimal escape sequence consists of a -** percent sign - "%" - followed by exactly two hexadecimal digits +** percent sign - "%" - followed by exactly two hexadecimal digits ** specifying an octet value. ^Before the path or query components of a -** URI filename are interpreted, they are encoded using UTF-8 and all +** URI filename are interpreted, they are encoded using UTF-8 and all ** hexadecimal escape sequences replaced by a single byte containing the ** corresponding octet. If this process generates an invalid UTF-8 encoding, ** the results are undefined. ** ** Note to Windows users: The encoding used for the filename argument @@ -3870,231 +3254,78 @@ ); /* ** CAPI3REF: Obtain Values For URI Parameters ** -** These are utility routines, useful to [VFS|custom VFS implementations], -** that check if a database file was a URI that contained a specific query +** These are utility routines, useful to VFS implementations, that check +** to see if a database file was a URI that contained a specific query ** parameter, and if so obtains the value of that query parameter. ** -** The first parameter to these interfaces (hereafter referred to -** as F) must be one of: -**
                  -**
                • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implementation, or -**
                • A filename obtained from [sqlite3_db_filename()], or -**
                • A new filename constructed using [sqlite3_create_filename()]. -**
                -** If the F parameter is not one of the above, then the behavior is -** undefined and probably undesirable. Older versions of SQLite were -** more tolerant of invalid F parameters than newer versions. -** -** If F is a suitable filename (as described in the previous paragraph) -** and if P is the name of the query parameter, then +** If F is the database filename pointer passed into the xOpen() method of +** a VFS implementation when the flags parameter to xOpen() has one or +** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and +** P is the name of the query parameter, then ** sqlite3_uri_parameter(F,P) returns the value of the P -** parameter if it exists or a NULL pointer if P does not appear as a -** query parameter on F. If P is a query parameter of F and it +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F ** has no explicit value, then sqlite3_uri_parameter(F,P) returns ** a pointer to an empty string. ** ** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean ** parameter and returns true (1) or false (0) according to the value ** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the ** value of query parameter P is one of "yes", "true", or "on" in any -** case or if the value begins with a non-zero number. The +** case or if the value begins with a non-zero number. The ** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of ** query parameter P is one of "no", "false", or "off" in any case or ** if the value begins with a numeric zero. If P is not a query -** parameter on F or if the value of P does not match any of the +** parameter on F or if the value of P is does not match any of the ** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). ** ** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a ** 64-bit signed integer and returns that integer, or D if P does not ** exist. If the value of P is something other than an integer, then ** zero is returned. -** -** The sqlite3_uri_key(F,N) returns a pointer to the name (not -** the value) of the N-th query parameter for filename F, or a NULL -** pointer if N is less than zero or greater than the number of query -** parameters minus 1. The N value is zero-based so N should be 0 to obtain -** the name of the first query parameter, 1 for the second parameter, and -** so forth. -** +** ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and ** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and -** is not a database file pathname pointer that the SQLite core passed -** into the xOpen VFS method, then the behavior of this routine is undefined -** and probably undesirable. -** -** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F -** parameter can also be the name of a rollback journal file or WAL file -** in addition to the main database file. Prior to version 3.31.0, these -** routines would only work if F was the name of the main database file. -** When the F parameter is the name of the rollback journal or WAL file, -** it has access to all the same query parameters as were found on the -** main database file. -** -** See the [URI filename] documentation for additional information. -*/ -SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam); -SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64); -SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N); - -/* -** CAPI3REF: Translate filenames -** -** These routines are available to [VFS|custom VFS implementations] for -** translating filenames between the main database file, the journal file, -** and the WAL file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** passed by the SQLite core into the VFS, then sqlite3_filename_database(F) -** returns the name of the corresponding database file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** passed by the SQLite core into the VFS, or if F is a database filename -** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F) -** returns the name of the corresponding rollback journal file. -** -** If F is the name of an sqlite database file, journal file, or WAL file -** that was passed by the SQLite core into the VFS, or if F is a database -** filename obtained from [sqlite3_db_filename()], then -** sqlite3_filename_wal(F) returns the name of the corresponding -** WAL file. -** -** In all of the above, if F is not the name of a database, journal or WAL -** filename passed into the VFS from the SQLite core and F is not the -** return value from [sqlite3_db_filename()], then the result is -** undefined and is likely a memory access violation. -*/ -SQLITE_API const char *sqlite3_filename_database(sqlite3_filename); -SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename); -SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename); - -/* -** CAPI3REF: Database File Corresponding To A Journal -** -** ^If X is the name of a rollback or WAL-mode journal file that is -** passed into the xOpen method of [sqlite3_vfs], then -** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file] -** object that represents the main database file. -** -** This routine is intended for use in custom [VFS] implementations -** only. It is not a general-purpose interface. -** The argument sqlite3_file_object(X) must be a filename pointer that -** has been passed into [sqlite3_vfs].xOpen method where the -** flags parameter to xOpen contains one of the bits -** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use -** of this routine results in undefined and probably undesirable -** behavior. -*/ -SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); - -/* -** CAPI3REF: Create and Destroy VFS Filenames -** -** These interfaces are provided for use by [VFS shim] implementations and -** are not useful outside of that context. -** -** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of -** database filename D with corresponding journal file J and WAL file W and -** with N URI parameters key/values pairs in the array P. The result from -** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that -** is safe to pass to routines like: -**
                  -**
                • [sqlite3_uri_parameter()], -**
                • [sqlite3_uri_boolean()], -**
                • [sqlite3_uri_int64()], -**
                • [sqlite3_uri_key()], -**
                • [sqlite3_filename_database()], -**
                • [sqlite3_filename_journal()], or -**
                • [sqlite3_filename_wal()]. -**
                -** If a memory allocation error occurs, sqlite3_create_filename() might -** return a NULL pointer. The memory obtained from sqlite3_create_filename(X) -** must be released by a corresponding call to sqlite3_free_filename(Y). -** -** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array -** of 2*N pointers to strings. Each pair of pointers in this array corresponds -** to a key and value for a query parameter. The P parameter may be a NULL -** pointer if N is zero. None of the 2*N pointers in the P array may be -** NULL pointers and key pointers should not be empty strings. -** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may -** be NULL pointers, though they can be empty strings. -** -** The sqlite3_free_filename(Y) routine releases a memory allocation -** previously obtained from sqlite3_create_filename(). Invoking -** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op. -** -** If the Y parameter to sqlite3_free_filename(Y) is anything other -** than a NULL pointer or a pointer previously acquired from -** sqlite3_create_filename(), then bad things such as heap -** corruption or segfaults may occur. The value Y should not be -** used again after sqlite3_free_filename(Y) has been called. This means -** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y, -** then the corresponding [sqlite3_module.xClose() method should also be -** invoked prior to calling sqlite3_free_filename(Y). -*/ -SQLITE_API sqlite3_filename sqlite3_create_filename( - const char *zDatabase, - const char *zJournal, - const char *zWal, - int nParam, - const char **azParam -); -SQLITE_API void sqlite3_free_filename(sqlite3_filename); +** is not a database file pathname pointer that SQLite passed into the xOpen +** VFS method, then the behavior of this routine is undefined and probably +** undesirable. +*/ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); + /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** -** ^If the most recent sqlite3_* API call associated with +** ^If the most recent sqlite3_* API call associated with ** [database connection] D failed, then the sqlite3_errcode(D) interface ** returns the numeric [result code] or [extended result code] for that ** API call. +** If the most recent API call was successful, +** then the return value from sqlite3_errcode() is undefined. ** ^The sqlite3_extended_errcode() -** interface is the same except that it always returns the +** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. ** -** The values returned by sqlite3_errcode() and/or -** sqlite3_extended_errcode() might change with each API call. -** Except, there are some interfaces that are guaranteed to never -** change the value of the error code. The error-code preserving -** interfaces include the following: -** -**
                  -**
                • sqlite3_errcode() -**
                • sqlite3_extended_errcode() -**
                • sqlite3_errmsg() -**
                • sqlite3_errmsg16() -**
                • sqlite3_error_offset() -**
                -** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF-8 or UTF-16 respectively, -** or NULL if no error message is available. -** (See how SQLite handles [invalid UTF] for exceptions to this rule.) +** text that describes the error, as either UTF-8 or UTF-16 respectively. ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** -** ^The sqlite3_errstr(E) interface returns the English-language text -** that describes the [result code] E, as UTF-8, or NULL if E is not an -** result code for which a text error message is available. +** ^The sqlite3_errstr() interface returns the English-language text +** that describes the [result code], as UTF-8. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** -** ^If the most recent error references a specific token in the input -** SQL, the sqlite3_error_offset() interface returns the byte offset -** of the start of that token. ^The byte offset returned by -** sqlite3_error_offset() assumes that the input SQL is UTF8. -** ^If the most recent error does not reference a specific token in the input -** SQL, then the sqlite3_error_offset() function returns -1. -** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. ** When that happens, the second error will be reported since these ** interfaces always report the most recent result. To avoid @@ -4110,21 +3341,20 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db); SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); SQLITE_API const char *sqlite3_errmsg(sqlite3*); SQLITE_API const void *sqlite3_errmsg16(sqlite3*); SQLITE_API const char *sqlite3_errstr(int); -SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* ** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** ** An instance of this object represents a single SQL statement that ** has been compiled into binary form and is ready to be evaluated. ** ** Think of each SQL statement as a separate computer program. The -** original SQL text is source code. A prepared statement object +** original SQL text is source code. A prepared statement object ** is the compiled object code. All SQL must be converted into a ** prepared statement before it can be run. ** ** The life-cycle of a prepared statement object usually goes like this: ** @@ -4150,19 +3380,19 @@ ** second parameter is one of the [limit categories] that define a ** class of constructs to be size limited. The third parameter is the ** new limit for that construct.)^ ** ** ^If the new limit is a negative number, the limit is unchanged. -** ^(For each limit category SQLITE_LIMIT_NAME there is a +** ^(For each limit category SQLITE_LIMIT_NAME there is a ** [limits | hard upper bound] ** set at compile-time by a C preprocessor macro called ** [limits | SQLITE_MAX_NAME]. ** (The "_LIMIT_" in the name is changed to "_MAX_".))^ ** ^Attempts to increase a limit above its hard upper bound are ** silently truncated to the hard upper bound. ** -** ^Regardless of whether or not the limit was changed, the +** ^Regardless of whether or not the limit was changed, the ** [sqlite3_limit()] interface returns the prior value of the limit. ** ^Hence, to find the current value of a limit without changing it, ** simply invoke this interface with the third parameter set to -1. ** ** Run-time limits are intended for use in applications that manage @@ -4263,45 +3493,19 @@ **
                ** [[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 +** 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. -** -** [[SQLITE_PREPARE_NORMALIZE]]
                SQLITE_PREPARE_NORMALIZE
                -**
                The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used -** to be required for any prepared statement that wanted to use the -** [sqlite3_normalized_sql()] interface. However, the -** [sqlite3_normalized_sql()] interface is now available to all -** prepared statements, regardless of whether or not they use this -** flag. -** -** [[SQLITE_PREPARE_NO_VTAB]]
                SQLITE_PREPARE_NO_VTAB
                -**
                The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler -** to return an error (error code SQLITE_ERROR) if the statement uses -** any virtual tables. -** -** [[SQLITE_PREPARE_DONT_LOG]]
                SQLITE_PREPARE_DONT_LOG
                -**
                The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler -** errors from being sent to the error log defined by -** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test -** compiles to see if some SQL syntax is well-formed, without generating -** messages on the global error log when it is not. If the test compile -** fails, the sqlite3_prepare_v3() call returns the same error indications -** with or without this flag; it just omits the call to [sqlite3_log()] that -** logs the error. **
                */ #define SQLITE_PREPARE_PERSISTENT 0x01 -#define SQLITE_PREPARE_NORMALIZE 0x02 -#define SQLITE_PREPARE_NO_VTAB 0x04 -#define SQLITE_PREPARE_DONT_LOG 0x10 /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** METHOD: sqlite3 @@ -4330,21 +3534,17 @@ ** 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 maximum -** number of bytes read from zSql. When nByte is positive, zSql is read -** up to the first zero terminator or until the nByte bytes have been read, -** whichever comes first. ^If nByte is zero, then no prepared +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared ** statement is generated. ** If the caller knows that the supplied string is nul-terminated, then ** there is a small performance advantage to passing an nByte parameter that ** is the number of bytes in the input string including ** the nul-terminator. -** Note that nByte measure the length of the input in bytes, not -** characters, even for the UTF-16 interfaces. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only ** compile the first statement in zSql, so *pzTail is left pointing to ** what remains uncompiled. @@ -4385,27 +3585,27 @@ ** in order to find the underlying cause of the problem. With the "v2" prepare ** interfaces, the underlying reason for the error is returned immediately. **
              • ** **
              • -** ^If the specific value bound to a [parameter | host parameter] in the +** ^If the specific value bound to [parameter | host parameter] in the ** WHERE clause might influence the choice of query plan for a statement, -** then the statement will be automatically recompiled, as if there had been -** a schema change, on the first [sqlite3_step()] call following any change -** to the [sqlite3_bind_text | bindings] of that [parameter]. -** ^The specific value of a WHERE-clause [parameter] might influence the +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column -** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. +** 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( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -4443,11 +3643,11 @@ ); 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 */ + unsigned int prepFalgs, /* Zero or more SQLITE_PREPARE_ flags */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); /* @@ -4459,15 +3659,10 @@ ** 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. -** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 -** string containing the normalized SQL text of prepared statement P. The -** semantics used to normalize a SQL statement are unspecified and subject -** to change. At a minimum, literal values will be replaced with suitable -** placeholders. ** ** ^(For example, if a prepared statement is created using the SQL ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** and parameter :xyz is unbound, then sqlite3_sql() will return ** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() @@ -4479,25 +3674,18 @@ ** ** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** -** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) -** are managed by SQLite and are automatically freed when the prepared -** statement is finalized. +** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +** automatically freed when the prepared statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, -** is obtained from [sqlite3_malloc()] and must be freed by the application +** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. -** -** ^The sqlite3_normalized_sql() interface is only available if -** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); -#ifdef SQLITE_ENABLE_NORMALIZE -SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); -#endif /* ** CAPI3REF: Determine If An SQL Statement Writes The Database ** METHOD: sqlite3_stmt ** @@ -4504,12 +3692,12 @@ ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to ** the content of the database file. ** ** Note that [application-defined SQL functions] or -** [virtual tables] might change the database indirectly as a side effect. -** ^(For example, if an application defines a function "eval()" that +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that ** calls [sqlite3_exec()], then the following SQL statement would ** change the database file through side-effects: ** **

         **    SELECT eval('DELETE FROM t1') FROM t2;
        @@ -4519,99 +3707,39 @@
         ** directly, sqlite3_stmt_readonly() would still return true.)^
         **
         ** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
         ** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
         ** since the statements themselves do not actually modify the database but
        -** rather they control the timing of when other statements modify the
        +** rather they control the timing of when other statements modify the 
         ** database.  ^The [ATTACH] and [DETACH] statements also cause
         ** sqlite3_stmt_readonly() to return true since, while those statements
        -** change the configuration of a database connection, they do not make
        +** 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.
        -**
        -** ^This routine returns false if there is any possibility that the
        -** statement might change the database file.  ^A false return does
        -** not guarantee that the statement will change the database file.
        -** ^For example, an UPDATE statement might have a WHERE clause that
        -** makes it a no-op, but the sqlite3_stmt_readonly() result would still
        -** be false.  ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
        -** read-only no-op if the table already exists, but
        -** sqlite3_stmt_readonly() still returns false for such a statement.
        -**
        -** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
        -** statement, then sqlite3_stmt_readonly(X) returns the same value as
        -** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
         */
         SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
         
        -/*
        -** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
        -** METHOD: sqlite3_stmt
        -**
        -** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
        -** prepared statement S is an EXPLAIN statement, or 2 if the
        -** statement S is an EXPLAIN QUERY PLAN.
        -** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
        -** an ordinary statement or a NULL pointer.
        -*/
        -SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
        -
        -/*
        -** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement
        -** METHOD: sqlite3_stmt
        -**
        -** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN
        -** setting for [prepared statement] S.  If E is zero, then S becomes
        -** a normal prepared statement.  If E is 1, then S behaves as if
        -** its SQL text began with "[EXPLAIN]".  If E is 2, then S behaves as if
        -** its SQL text began with "[EXPLAIN QUERY PLAN]".
        -**
        -** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.
        -** SQLite tries to avoid a reprepare, but a reprepare might be necessary
        -** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.
        -**
        -** Because of the potential need to reprepare, a call to
        -** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be
        -** reprepared because it was created using [sqlite3_prepare()] instead of
        -** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and
        -** hence has no saved SQL text with which to reprepare.
        -**
        -** Changing the explain setting for a prepared statement does not change
        -** the original SQL text for the statement.  Hence, if the SQL text originally
        -** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)
        -** is called to convert the statement into an ordinary statement, the EXPLAIN
        -** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)
        -** output, even though the statement now acts like a normal SQL statement.
        -**
        -** This routine returns SQLITE_OK if the explain mode is successfully
        -** changed, or an error code if the explain mode could not be changed.
        -** The explain mode cannot be changed while a statement is active.
        -** Hence, it is good practice to call [sqlite3_reset(S)]
        -** immediately prior to calling sqlite3_stmt_explain(S,E).
        -*/
        -SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);
        -
         /*
         ** CAPI3REF: Determine If A Prepared Statement Has Been Reset
         ** METHOD: sqlite3_stmt
         **
         ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
        -** [prepared statement] S has been stepped at least once using
        +** [prepared statement] S has been stepped at least once using 
         ** [sqlite3_step(S)] but has neither run to completion (returned
         ** [SQLITE_DONE] from [sqlite3_step(S)]) nor
         ** been reset using [sqlite3_reset(S)].  ^The sqlite3_stmt_busy(S)
        -** interface returns false if S is a NULL pointer.  If S is not a
        +** interface returns false if S is a NULL pointer.  If S is not a 
         ** NULL pointer and is not a pointer to a valid [prepared statement]
         ** object, then the behavior is undefined and probably undesirable.
         **
         ** This interface can be used in combination [sqlite3_next_stmt()]
        -** to locate all prepared statements associated with a database
        +** to locate all prepared statements associated with a database 
         ** connection that are in need of being reset.  This can be used,
        -** for example, in diagnostic routines to search for prepared
        +** for example, in diagnostic routines to search for prepared 
         ** statements that are holding a transaction open.
         */
         SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
         
         /*
        @@ -4626,35 +3754,32 @@
         ** An sqlite3_value object may be either "protected" or "unprotected".
         ** Some interfaces require a protected sqlite3_value.  Other interfaces
         ** will accept either a protected or an unprotected sqlite3_value.
         ** Every interface that accepts sqlite3_value arguments specifies
         ** whether or not it requires a protected sqlite3_value.  The
        -** [sqlite3_value_dup()] interface can be used to construct a new
        +** [sqlite3_value_dup()] interface can be used to construct a new 
         ** protected sqlite3_value from an unprotected sqlite3_value.
         **
         ** The terms "protected" and "unprotected" refer to whether or not
         ** a mutex is held.  An internal mutex is held for a protected
         ** sqlite3_value object but no mutex is held for an unprotected
         ** sqlite3_value object.  If SQLite is compiled to be single-threaded
         ** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
        -** or if SQLite is run in one of reduced mutex modes
        +** or if SQLite is run in one of reduced mutex modes 
         ** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
         ** then there is no distinction between protected and unprotected
         ** sqlite3_value objects and they can be used interchangeably.  However,
         ** for maximum code portability it is recommended that applications
         ** still make the distinction between protected and unprotected
         ** sqlite3_value objects even when not strictly required.
         **
         ** ^The sqlite3_value objects that are passed as parameters into the
         ** implementation of [application-defined SQL functions] are protected.
        -** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()]
        -** are protected.
         ** ^The sqlite3_value object returned by
         ** [sqlite3_column_value()] is unprotected.
        -** Unprotected sqlite3_value objects may only be used as arguments
        -** to [sqlite3_result_value()], [sqlite3_bind_value()], and
        -** [sqlite3_value_dup()].
        +** Unprotected sqlite3_value objects may only be used with
        +** [sqlite3_result_value()] and [sqlite3_bind_value()].
         ** The [sqlite3_value_blob | sqlite3_value_type()] family of
         ** interfaces require protected sqlite3_value objects.
         */
         typedef struct sqlite3_value sqlite3_value;
         
        @@ -4705,34 +3830,16 @@
         ** occurrences have the same index as the first occurrence.
         ** ^The index for named parameters can be looked up using the
         ** [sqlite3_bind_parameter_index()] API if desired.  ^The index
         ** for "?NNN" parameters is the value of NNN.
         ** ^The NNN value must be between 1 and the [sqlite3_limit()]
        -** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
        +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
         **
         ** ^The third argument is the value to bind to the parameter.
         ** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
         ** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
         ** is ignored and the end result is the same as sqlite3_bind_null().
        -** ^If the third parameter to sqlite3_bind_text() is not NULL, then
        -** it should be a pointer to well-formed UTF8 text.
        -** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
        -** it should be a pointer to well-formed UTF16 text.
        -** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
        -** it should be a pointer to a well-formed unicode string that is
        -** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
        -** otherwise.
        -**
        -** [[byte-order determination rules]] ^The byte-order of
        -** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
        -** found in first character, which is removed, or in the absence of a BOM
        -** the byte order is the native byte order of the host
        -** machine for sqlite3_bind_text16() or the byte order specified in
        -** the 6th parameter for sqlite3_bind_text64().)^
        -** ^If UTF16 input text contains invalid unicode
        -** characters, then SQLite might change those invalid characters
        -** into the unicode replacement character: U+FFFD.
         **
         ** ^(In those routines that have a fourth argument, its value is the
         ** number of bytes in the parameter.  To be clear: the value is the
         ** number of bytes in the value, not the number of characters.)^
         ** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
        @@ -4742,31 +3849,25 @@
         ** the behavior is undefined.
         ** If a non-negative fourth parameter is provided to sqlite3_bind_text()
         ** or sqlite3_bind_text16() or sqlite3_bind_text64() then
         ** that parameter must be the byte offset
         ** where the NUL terminator would occur assuming the string were NUL
        -** terminated.  If any NUL characters occurs at byte offsets less than
        +** terminated.  If any NUL characters occur at byte offsets less than 
         ** the value of the fourth parameter then the resulting string value will
         ** contain embedded NULs.  The result of expressions involving strings
         ** with embedded NULs is undefined.
         **
        -** ^The fifth argument to the BLOB and string binding interfaces controls
        -** or indicates the lifetime of the object referenced by the third parameter.
        -** These three options exist:
        -** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
        -** with it may be passed. ^It is called to dispose of the BLOB or string even
        -** if the call to the bind API fails, except the destructor is not called if
        -** the third parameter is a NULL pointer or the fourth parameter is negative.
        -** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that
        -** the application remains responsible for disposing of the object. ^In this
        -** case, the object and the provided pointer to it must remain valid until
        -** either the prepared statement is finalized or the same SQL parameter is
        -** bound to something else, whichever occurs sooner.
        -** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
        -** object is to be copied prior to the return from sqlite3_bind_*(). ^The
        -** object and pointer to it must remain valid until then. ^SQLite will then
        -** manage the lifetime of its private copy.
        +** ^The fifth argument to the BLOB and string binding interfaces
        +** is a destructor used to dispose of the BLOB or
        +** string after SQLite has finished with it.  ^The destructor is called
        +** to dispose of the BLOB or string even if the call to bind API fails.
        +** ^If the fifth argument is
        +** the special value [SQLITE_STATIC], then SQLite assumes that the
        +** information is in static, unmanaged space and does not need to be freed.
        +** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
        +** SQLite makes its own private copy of the data immediately, before
        +** the sqlite3_bind_*() routine returns.
         **
         ** ^The sixth argument to sqlite3_bind_text64() must be one of
         ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
         ** to specify the encoding of the text in the third parameter.  If
         ** the sixth argument to sqlite3_bind_text64() is not one of the
        @@ -4780,18 +3881,18 @@
         ** Zeroblobs are intended to serve as placeholders for BLOBs whose
         ** content is later written using
         ** [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
        +** ^The sqlite3_bind_pointer(S,I,P) 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.
        +** associated with the pointer P.
        +** ^The sqlite3_bind_pointer() routine can be used to pass
        +** host-language pointers into [application-defined SQL functions].
        +** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
        +** to be an ordinary SQL NULL value to everything other than
        +** [sqlite3_value_pointer()].
         **
         ** ^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()],
         ** then the call will return [SQLITE_MISUSE].  If any sqlite3_bind_()
        @@ -4822,11 +3923,11 @@
         SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
         SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(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_pointer(sqlite3_stmt*, int, void*);
         SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
         SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
         
         /*
         ** CAPI3REF: Number Of SQL Parameters
        @@ -4908,11 +4009,11 @@
         /*
         ** CAPI3REF: Number Of Columns In A Result Set
         ** METHOD: sqlite3_stmt
         **
         ** ^Return the number of columns in the result set returned by the
        -** [prepared statement]. ^If this routine returns 0, that means the
        +** [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.
        @@ -4976,19 +4077,23 @@
         ** the statement, where N is the second function argument.
         ** ^The left-most column is column 0 for these routines.
         **
         ** ^If the Nth column returned by the statement is an expression or
         ** subquery and is not a column value, then all of these functions return
        -** NULL.  ^These routines might also return NULL if a memory allocation error
        +** NULL.  ^These routine might also return NULL if a memory allocation error
         ** occurs.  ^Otherwise, they return the name of the attached database, table,
         ** or column that query result column was extracted from.
         **
         ** ^As with all other SQLite APIs, those whose names end with "16" return
         ** UTF-16 encoded strings and the other functions return UTF-8.
         **
         ** ^These APIs are only available if the library was compiled with the
         ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
        +**
        +** If two or more threads call one or more of these routines against the same
        +** prepared statement and column at the same time then the results are
        +** undefined.
         **
         ** If two or more threads call one or more
         ** [sqlite3_column_database_name | column metadata interfaces]
         ** for the same [prepared statement] and result column
         ** at the same time then the results are undefined.
        @@ -5090,11 +4195,11 @@
         ** more threads at the same moment in time.
         **
         ** For all versions of SQLite up to and including 3.6.23.1, a call to
         ** [sqlite3_reset()] was required after sqlite3_step() returned anything
         ** other than [SQLITE_ROW] before any subsequent invocation of
        -** sqlite3_step().  Failure to reset the prepared statement using
        +** sqlite3_step().  Failure to reset the prepared statement using 
         ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
         ** sqlite3_step().  But after [version 3.6.23.1] ([dateof:3.6.23.1],
         ** sqlite3_step() began
         ** calling [sqlite3_reset()] automatically in this circumstance rather
         ** than returning [SQLITE_MISUSE].  This is not considered a compatibility
        @@ -5122,11 +4227,11 @@
         ** METHOD: sqlite3_stmt
         **
         ** ^The sqlite3_data_count(P) interface returns the number of columns in the
         ** current row of the result set of [prepared statement] P.
         ** ^If prepared statement P does not have results ready to return
        -** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
        +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
         ** interfaces) then sqlite3_data_count(P) returns 0.
         ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
         ** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
         ** [sqlite3_step](P) returned [SQLITE_DONE].  ^The sqlite3_data_count(P)
         ** will return non-zero if previous call to [sqlite3_step](P) returned
        @@ -5181,11 +4286,11 @@
         ** 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_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  
        @@ -5229,11 +4334,11 @@
         ** of the result column.  ^The returned value is one of [SQLITE_INTEGER],
         ** [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.
        +** 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.
         **
        @@ -5257,38 +4362,34 @@
         ** ^If the result is a numeric value then sqlite3_column_bytes16() uses
         ** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns
         ** the number of bytes in that string.
         ** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
         **
        -** ^The values returned by [sqlite3_column_bytes()] and
        +** ^The values returned by [sqlite3_column_bytes()] and 
         ** [sqlite3_column_bytes16()] do not include the zero terminators at the end
         ** of the string.  ^For clarity: the values returned by
         ** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
         ** bytes in the string, not the number of characters.
         **
         ** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
         ** even empty strings, are always zero-terminated.  ^The return
         ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
         **
        -** ^Strings returned by sqlite3_column_text16() always have the endianness
        -** which is native to the platform, regardless of the text encoding set
        -** for the database.
        -**
         ** Warning: ^The object returned by [sqlite3_column_value()] is an
         ** [unprotected sqlite3_value] object.  In a multithreaded environment,
         ** an unprotected sqlite3_value object may only be used safely with
         ** [sqlite3_bind_value()] and [sqlite3_result_value()].
         ** If the [unprotected sqlite3_value] object returned by
         ** [sqlite3_column_value()] is used in any other way, including calls
         ** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
         ** or [sqlite3_value_bytes()], the behavior is not threadsafe.
         ** Hence, the sqlite3_column_value() interface
        -** is normally only useful within the implementation of
        +** is normally only useful within the implementation of 
         ** [application-defined SQL functions] or [virtual tables], not within
         ** top-level application code.
         **
        -** These routines may attempt to convert the datatype of the 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:
         **
        @@ -5309,11 +4410,11 @@
         **   TEXT     INTEGER    [CAST] to INTEGER
         **   TEXT      FLOAT     [CAST] to REAL
         **   TEXT       BLOB     No change
         **   BLOB     INTEGER    [CAST] to INTEGER
         **   BLOB      FLOAT     [CAST] to REAL
        -**   BLOB       TEXT     [CAST] to TEXT, ensure zero terminator
        +**   BLOB       TEXT     Add a zero terminator if needed
         ** 
         ** 
        )^ ** ** Note that when type conversions occur, pointers returned by prior ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or @@ -5361,29 +4462,15 @@ ** [sqlite3_finalize()] is called. ^The memory space used to hold strings ** and BLOBs is freed automatically. Do not pass the pointers returned ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** [sqlite3_free()]. ** -** As long as the input parameters are correct, these routines will only -** fail if an out-of-memory error occurs during a format conversion. -** Only the following subset of interfaces are subject to out-of-memory -** errors: -** -**
          -**
        • sqlite3_column_blob() -**
        • sqlite3_column_text() -**
        • sqlite3_column_text16() -**
        • sqlite3_column_bytes() -**
        • sqlite3_column_bytes16() -**
        -** -** If an out-of-memory error occurs, then the return value from these -** routines is the same as if the column had contained an SQL NULL value. -** Valid SQL NULL returns can be distinguished from out-of-memory errors -** by invoking the [sqlite3_errcode()] immediately after the suspect -** return value is obtained and before any -** other SQLite interface is called on the same [database connection]. +** ^(If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM].)^ */ SQLITE_API const void *sqlite3_column_blob(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); @@ -5433,61 +4520,48 @@ ** Use [sqlite3_clear_bindings()] to reset the bindings. ** ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** -** ^The return code from [sqlite3_reset(S)] indicates whether or not -** the previous evaluation of prepared statement S completed successfully. -** ^If [sqlite3_step(S)] has never before been called on S or if -** [sqlite3_step(S)] has not been called since the previous call -** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return -** [SQLITE_OK]. +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. -** ^The [sqlite3_reset(S)] interface might also return an [error code] -** if there were no prior errors but the process of resetting -** the prepared statement caused a new error. ^For example, if an -** [INSERT] statement with a [RETURNING] clause is only stepped one time, -** that one call to [sqlite3_step(S)] might return SQLITE_ROW but -** the overall statement might still fail and the [sqlite3_reset(S)] call -** might return SQLITE_BUSY if locking constraints prevent the -** database change from committing. Therefore, it is important that -** applications check the return code from [sqlite3_reset(S)] even if -** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); - /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} ** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior -** of existing SQL functions or aggregates. The only differences between -** the three "sqlite3_create_function*" routines are the text encoding -** expected for the second parameter (the name of the function being -** created) and the presence or absence of a destructor callback for -** the application data pointer. Function sqlite3_create_window_function() -** is similar, but allows the user to supply the extra callback functions -** needed by [aggregate window functions]. +** of existing SQL functions or aggregates. The only differences between +** these routines are the text encoding expected for +** the second parameter (the name of the function being created) +** and the presence or absence of a destructor callback for +** the application data pointer. ** ** ^The first parameter is the [database connection] to which the SQL ** function is to be added. ^If an application uses more than one database ** connection then application-defined SQL functions must be added ** to each database connection separately. ** ** ^The second parameter is the name of the SQL function to be created or ** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 ** representation, exclusive of the zero-terminator. ^Note that the name -** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. ** ^Any attempt to create a function with a longer name ** will result in [SQLITE_MISUSE] being returned. ** ** ^The third parameter (nArg) ** is the number of arguments that the SQL function or @@ -5498,11 +4572,11 @@ ** undefined. ** ** ^The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for ** its parameters. The application should set this parameter to -** [SQLITE_UTF16LE] if the function implementation invokes +** [SQLITE_UTF16LE] if the function implementation invokes ** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the ** implementation invokes [sqlite3_value_text16be()] on an input, or ** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] ** otherwise. ^The same SQL function may be registered multiple times using ** different preferred text encodings, with different implementations for @@ -5516,66 +4590,41 @@ ** deterministic. The built-in [random()] SQL function is an example of a ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** -** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] -** flag, which if present prevents the function from being invoked from -** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, -** index expressions, or the WHERE clause of partial indexes. -** -** For best security, the [SQLITE_DIRECTONLY] flag is recommended for -** all application-defined SQL functions that do not need to be -** used inside of triggers, view, CHECK constraints, or other elements of -** the database schema. This flags is especially recommended for SQL -** functions that have side effects or reveal internal application state. -** Without this flag, an attacker might be able to modify the schema of -** a database file to include invocations of the function with parameters -** chosen by the attacker, which the application will then execute when -** the database file is opened and read. -** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** -** ^The sixth, seventh and eighth parameters passed to the three -** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are +** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ** aggregate. ^A scalar SQL function requires an implementation of the xFunc ** callback only; NULL pointers must be passed as the xStep and xFinal ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** -** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue -** and xInverse) passed to sqlite3_create_window_function are pointers to -** C-language callbacks that implement the new function. xStep and xFinal -** must both be non-NULL. xValue and xInverse may either both be NULL, in -** which case a regular aggregate function is created, or must both be -** non-NULL, in which case the new function may be used as either an aggregate -** or aggregate window function. More details regarding the implementation -** of aggregate window functions are -** [user-defined window functions|available here]. -** -** ^(If the final parameter to sqlite3_create_function_v2() or -** sqlite3_create_window_function() is not NULL, then it is destructor for -** the application data pointer. The destructor is invoked when the function -** is deleted, either by being overloaded or when the database connection -** closes.)^ ^The destructor is also invoked if the call to -** sqlite3_create_function_v2() fails. ^When the destructor callback is -** invoked, it is passed a single argument which is a copy of the application -** data pointer which was the fifth parameter to sqlite3_create_function_v2(). +** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +** then it is destructor for the application data pointer. +** The destructor is invoked when the function is deleted, either by being +** overloaded or when the database connection closes.)^ +** ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. +** ^When the destructor callback of the tenth parameter is invoked, it +** is passed a single argument which is a copy of the application data +** pointer which was the fifth parameter to sqlite3_create_function_v2(). ** ** ^It is permitted to register multiple implementations of the same ** functions with the same name but with either differing numbers of ** arguments or differing preferred text encodings. ^SQLite will use ** the implementation that most closely matches the way in which the ** SQL function is used. ^A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with ** a negative nArg. ^A function where the preferred text encoding ** matches the database encoding is a better -** match than a function where the encoding is different. +** match than a function where the encoding is different. ** ^A function where the encoding difference is between UTF16le and UTF16be ** is a closer match than a function where the encoding difference is ** between UTF8 and UTF16. ** ** ^Built-in functions may be overloaded by new application-defined functions. @@ -5614,22 +4663,10 @@ void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void(*xDestroy)(void*) ); -SQLITE_API int sqlite3_create_window_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*) -); /* ** CAPI3REF: Text Encodings ** ** These constant define integer codes that represent the various @@ -5643,119 +4680,23 @@ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ /* ** CAPI3REF: Function Flags ** -** These constants may be ORed together with the +** These constants may be ORed together with the ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument ** to [sqlite3_create_function()], [sqlite3_create_function16()], or ** [sqlite3_create_function_v2()]. -** -**
        -** [[SQLITE_DETERMINISTIC]]
        SQLITE_DETERMINISTIC
        -** The SQLITE_DETERMINISTIC flag means that the new function always gives -** the same output when the input parameters are the same. -** The [abs|abs() function] is deterministic, for example, but -** [randomblob|randomblob()] is not. Functions must -** be deterministic in order to be used in certain contexts such as -** with the WHERE clause of [partial indexes] or in [generated columns]. -** SQLite might also optimize deterministic functions by factoring them -** out of inner loops. -**
        -** -** [[SQLITE_DIRECTONLY]]
        SQLITE_DIRECTONLY
        -** The SQLITE_DIRECTONLY flag means that the function may only be invoked -** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in -** schema structures such as [CHECK constraints], [DEFAULT clauses], -** [expression indexes], [partial indexes], or [generated columns]. -**

        -** The SQLITE_DIRECTONLY flag is recommended for any -** [application-defined SQL function] -** that has side-effects or that could potentially leak sensitive information. -** This will prevent attacks in which an application is tricked -** into using a database file that has had its schema surreptitiously -** modified to invoke the application-defined function in ways that are -** harmful. -**

        -** Some people say it is good practice to set SQLITE_DIRECTONLY on all -** [application-defined SQL functions], regardless of whether or not they -** are security sensitive, as doing so prevents those functions from being used -** inside of the database schema, and thus ensures that the database -** can be inspected and modified using generic tools (such as the [CLI]) -** that do not have access to the application-defined functions. -**

        -** -** [[SQLITE_INNOCUOUS]]
        SQLITE_INNOCUOUS
        -** The SQLITE_INNOCUOUS flag means that the function is unlikely -** to cause problems even if misused. An innocuous function should have -** no side effects and should not depend on any values other than its -** input parameters. The [abs|abs() function] is an example of an -** innocuous function. -** The [load_extension() SQL function] is not innocuous because of its -** side effects. -**

        SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not -** exactly the same. The [random|random() function] is an example of a -** function that is innocuous but not deterministic. -**

        Some heightened security settings -** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF]) -** disable the use of SQL functions inside views and triggers and in -** schema structures such as [CHECK constraints], [DEFAULT clauses], -** [expression indexes], [partial indexes], and [generated columns] unless -** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions -** are innocuous. Developers are advised to avoid using the -** SQLITE_INNOCUOUS flag for application-defined functions unless the -** function has been carefully audited and found to be free of potentially -** security-adverse side-effects and information-leaks. -**

        -** -** [[SQLITE_SUBTYPE]]
        SQLITE_SUBTYPE
        -** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. -** This flag instructs SQLite to omit some corner-case optimizations that -** might disrupt the operation of the [sqlite3_value_subtype()] function, -** causing it to return zero rather than the correct subtype(). -** All SQL functions that invoke [sqlite3_value_subtype()] should have this -** property. If the SQLITE_SUBTYPE property is omitted, then the return -** value from [sqlite3_value_subtype()] might sometimes be zero even though -** a non-zero subtype was specified by the function argument expression. -** -** [[SQLITE_RESULT_SUBTYPE]]
        SQLITE_RESULT_SUBTYPE
        -** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call -** [sqlite3_result_subtype()] to cause a sub-type to be associated with its -** result. -** Every function that invokes [sqlite3_result_subtype()] should have this -** property. If it does not, then the call to [sqlite3_result_subtype()] -** might become a no-op if the function is used as term in an -** [expression index]. On the other hand, SQL functions that never invoke -** [sqlite3_result_subtype()] should avoid setting this property, as the -** purpose of this property is to disable certain optimizations that are -** incompatible with subtypes. -** -** [[SQLITE_SELFORDER1]]
        SQLITE_SELFORDER1
        -** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate -** that internally orders the values provided to the first argument. The -** ordered-set aggregate SQL notation with a single ORDER BY term can be -** used to invoke this function. If the ordered-set aggregate notation is -** used on a function that lacks this flag, then an error is raised. Note -** that the ordered-set aggregate syntax is only available if SQLite is -** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option. -**
        -**
        */ -#define SQLITE_DETERMINISTIC 0x000000800 -#define SQLITE_DIRECTONLY 0x000080000 -#define SQLITE_SUBTYPE 0x000100000 -#define SQLITE_INNOCUOUS 0x000200000 -#define SQLITE_RESULT_SUBTYPE 0x001000000 -#define SQLITE_SELFORDER1 0x002000000 +#define SQLITE_DETERMINISTIC 0x800 /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** ** These functions are [deprecated]. In order to maintain -** backwards compatibility with older code, these functions continue +** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid ** the use of these functions. To encourage programmers to avoid ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED @@ -5792,23 +4733,18 @@ ** 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. -** sqlite3_value_frombind   -** →  True if value originated from a [bound parameter] ** ** ** Details: ** ** These routines extract type, size, and content information from ** [protected sqlite3_value] objects. Protected sqlite3_value objects -** are used to pass parameter information into the functions that -** implement [application-defined SQL functions] and [virtual tables]. +** 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] ** is not threadsafe. ** @@ -5819,16 +4755,14 @@ ** ^The sqlite3_value_text16() interface extracts a UTF-16 string ** in the native byte-order of the host machine. ^The ** 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. +** ^If [sqlite3_value] object V was initialized +** using [sqlite3_bind_pointer(S,I,P)] or [sqlite3_result_pointer(C,P)], then +** sqlite3_value_pointer(V) will return the pointer P. Otherwise, +** sqlite3_value_pointer(V) returns a NULL. ** ** ^(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].)^ @@ -5845,96 +4779,32 @@ ** such a conversion is possible without loss of information (in other ** words, if the value is a string that looks like a number) ** 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. -** -** ^The sqlite3_value_frombind(X) interface returns non-zero if the -** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] -** interfaces. ^If X comes from an SQL literal value, or a table column, -** or an expression, then sqlite3_value_frombind(X) returns zero. -** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. -** -** As long as the input parameter is correct, these routines can only -** fail if an out-of-memory error occurs during a format conversion. -** Only the following subset of interfaces are subject to out-of-memory -** errors: -** -**
          -**
        • sqlite3_value_blob() -**
        • sqlite3_value_text() -**
        • sqlite3_value_text16() -**
        • sqlite3_value_text16le() -**
        • sqlite3_value_text16be() -**
        • sqlite3_value_bytes() -**
        • sqlite3_value_bytes16() -**
        -** -** If an out-of-memory error occurs, then the return value from these -** routines is the same as if the column had contained an SQL NULL value. -** Valid SQL NULL returns can be distinguished from out-of-memory errors -** by invoking the [sqlite3_errcode()] immediately after the suspect -** return value is obtained and before any -** other SQLite interface is called on the same [database connection]. */ SQLITE_API const void *sqlite3_value_blob(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 void *sqlite3_value_pointer(sqlite3_value*); 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*); -SQLITE_API int sqlite3_value_frombind(sqlite3_value*); - -/* -** CAPI3REF: Report the internal text encoding state of an sqlite3_value object -** METHOD: sqlite3_value -** -** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding -** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X) -** returns something other than SQLITE_TEXT, then the return value from -** sqlite3_value_encoding(X) is meaningless. ^Calls to -** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)], -** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or -** [sqlite3_value_bytes16(X)] might change the encoding of the value X and -** thus change the return from subsequent calls to sqlite3_value_encoding(X). -** -** This routine is intended for used by applications that test and validate -** the SQLite implementation. This routine is inquiring about the opaque -** internal state of an [sqlite3_value] object. Ordinary applications should -** not need to know what the internal state of an sqlite3_value object is and -** hence should not need to use this interface. -*/ -SQLITE_API int sqlite3_value_encoding(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values ** METHOD: sqlite3_value ** @@ -5941,16 +4811,10 @@ ** The sqlite3_value_subtype(V) function returns the subtype for ** an [application-defined SQL function] argument V. The subtype ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_SUBTYPE] property in the text -** encoding argument when the function is [sqlite3_create_function|registered]. -** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype() -** might return zero instead of the upstream subtype in some corner cases. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values @@ -5958,12 +4822,11 @@ ** ** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a -** memory allocation fails. ^If V is a [pointer value], then the result -** of sqlite3_value_dup(V) is a NULL value. +** memory allocation fails. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ @@ -5975,13 +4838,13 @@ ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** -** ^The first time the sqlite3_aggregate_context(C,N) routine is called -** for a particular aggregate function, SQLite allocates -** N bytes of memory, zeroes out that memory, and returns a pointer +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite +** allocates N of memory, zeroes out that memory, and returns a pointer ** to the new memory. ^On second and subsequent calls to ** sqlite3_aggregate_context() for the same aggregate function instance, ** the same buffer is returned. Sqlite3_aggregate_context() is normally ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match @@ -5988,23 +4851,23 @@ ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** -** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory -** allocation error occurs. +** allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the -** value of N in any subsequent call to sqlite3_aggregate_context() within +** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ Within the xFinal callback, it is customary to set -** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** N=0 in calls to sqlite3_aggregate_context(C,N) so that no ** pointless memory allocations occur. ** -** ^SQLite automatically frees the memory allocated by +** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ** ** The first parameter must be a copy of the ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate @@ -6045,130 +4908,65 @@ /* ** CAPI3REF: Function Auxiliary Data ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to -** associate auxiliary data with argument values. If the same argument -** value is passed to multiple invocations of the same SQL function during -** query execution, under some circumstances the associated auxiliary data -** might be preserved. An example of where this might be useful is in a -** regular-expression matching function. The compiled version of the regular -** expression can be stored as auxiliary data associated with the pattern string. +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. An example +** of where this might be useful is in a regular-expression matching +** function. The compiled version of the regular expression can be stored as +** metadata associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. ** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data +** ^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 auxiliary data +** 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 auxiliary data for the -** N-th argument of the application-defined function. ^Subsequent +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th +** argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or -** NULL if the auxiliary data has been discarded. +** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or +** NULL if the metadata has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly -** once, when the auxiliary data is discarded. -** SQLite is free to discard the auxiliary data at any time, including:
          +** once, when the metadata is discarded. +** SQLite is free to discard the metadata at any time, including:
            **
          • ^(when the corresponding function parameter changes)^, or **
          • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or **
          • ^(when sqlite3_set_auxdata() is invoked again on the same ** parameter)^, or -**
          • ^(during the original sqlite3_set_auxdata() call when a memory -** allocation error occurs.)^ -**
          • ^(during the original sqlite3_set_auxdata() call if the function -** is evaluated during query planning instead of during query execution, -** as sometimes happens with [SQLITE_ENABLE_STAT4].)^
          +**
        • ^(during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.)^
        ** -** Note the last two bullets in particular. The destructor X in +** Note the last bullet in particular. The destructor X in ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the ** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** function implementation should not make any use of P after -** sqlite3_set_auxdata() has been called. Furthermore, a call to -** sqlite3_get_auxdata() that occurs immediately after a corresponding call -** to sqlite3_set_auxdata() might still return NULL if an out-of-memory -** condition occurred during the sqlite3_set_auxdata() call or if the -** function is being evaluated during query planning rather than during -** query execution. +** sqlite3_set_auxdata() has been called. ** -** ^(In practice, auxiliary data is preserved between function calls for +** ^(In practice, metadata is preserved between function calls for ** 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. -** -** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); -/* -** CAPI3REF: Database Connection Client Data -** METHOD: sqlite3 -** -** These functions are used to associate one or more named pointers -** with a [database connection]. -** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P -** to be attached to [database connection] D using name N. Subsequent -** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P -** or a NULL pointer if there were no prior calls to -** sqlite3_set_clientdata() with the same values of D and N. -** Names are compared using strcmp() and are thus case sensitive. -** -** If P and X are both non-NULL, then the destructor X is invoked with -** argument P on the first of the following occurrences: -**
          -**
        • An out-of-memory error occurs during the call to -** sqlite3_set_clientdata() which attempts to register pointer P. -**
        • A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made -** with the same D and N parameters. -**
        • The database connection closes. SQLite does not make any guarantees -** about the order in which destructors are called, only that all -** destructors will be called exactly once at some point during the -** database connection closing process. -**
        -** -** SQLite does not do anything with client data other than invoke -** destructors on the client data at the appropriate time. The intended -** use for client data is to provide a mechanism for wrapper libraries -** to store additional information about an SQLite database connection. -** -** There is no limit (other than available memory) on the number of different -** client data pointers (with different names) that can be attached to a -** single database connection. However, the implementation is optimized -** for the case of having only one or two different client data names. -** Applications and wrapper libraries are discouraged from using more than -** one client data name each. -** -** There is no way to enumerate the client data pointers -** associated with a database connection. The N parameter can be thought -** of as a secret key such that only code that knows the secret key is able -** to access the associated data. -** -** Security Warning: These interfaces should not be exposed in scripting -** languages or in other circumstances where it might be possible for an -** an attacker to invoke them. Any agent that can invoke these interfaces -** can probably also take control of the process. -** -** Database connection client data is only available for SQLite -** version 3.44.0 ([dateof:3.44.0]) and later. -** -** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()]. -*/ -SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*); -SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior ** ** These are special values for the destructor that is passed in as the @@ -6216,13 +5014,12 @@ ** cause the implemented SQL function to throw an exception. ** ^SQLite uses the string pointed to by the ** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() ** as the text of an error message. ^SQLite interprets the error ** message string from sqlite3_result_error() as UTF-8. ^SQLite -** interprets the string from sqlite3_result_error16() as UTF-16 using -** the same [byte-order determination rules] as [sqlite3_bind_text16()]. -** ^If the third parameter to sqlite3_result_error() +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. ^If the third parameter to sqlite3_result_error() ** or sqlite3_result_error16() is negative then SQLite takes as the error ** message all text up through the first zero character. ** ^If the third parameter to sqlite3_result_error() or ** sqlite3_result_error16() is non-negative then SQLite takes that many ** bytes (not characters) from the 2nd parameter as the error message. @@ -6260,14 +5057,13 @@ ** application-defined function to be a text string in an encoding ** specified by the fifth (and last) parameter, which must be one ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. -** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces -** other than sqlite3_result_text64() is negative, then SQLite computes -** the string length itself by searching the 2nd parameter for the first -** zero character. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is non-negative, then as many bytes (not characters) of the text ** pointed to by the 2nd parameter are taken as the application-defined ** function result. If the 3rd parameter is non-negative, then it ** must be the byte offset into the string where the NUL terminator would @@ -6287,29 +5083,10 @@ ** ^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 [sqlite3_malloc()] before it returns. ** -** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and -** sqlite3_result_text16be() routines, and for sqlite3_result_text64() -** when the encoding is not UTF8, if the input UTF16 begins with a -** byte-order mark (BOM, U+FEFF) then the BOM is removed from the -** string and the rest of the string is interpreted according to the -** byte-order specified by the BOM. ^The byte-order specified by -** the BOM at the beginning of the text overrides the byte-order -** specified by the interface procedure. ^So, for example, if -** sqlite3_result_text16le() is invoked with text that begins -** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the -** first two bytes of input are skipped and the remaining input -** is interpreted as UTF16BE text. -** -** ^For UTF16 input text to the sqlite3_result_text16(), -** sqlite3_result_text16be(), sqlite3_result_text16le(), and -** sqlite3_result_text64() routines, if the text contains invalid -** UTF16 characters, the invalid characters might be converted -** into the unicode replacement character, U+FFFD. -** ** ^The sqlite3_result_value() interface sets the result of ** the application-defined function to be a copy of the ** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The ** sqlite3_result_value() interface makes a copy of the [sqlite3_value] ** so that the [sqlite3_value] specified in the parameter may change or @@ -6316,20 +5093,17 @@ ** be deallocated after sqlite3_result_value() returns without harm. ** ^A [protected sqlite3_value] object may always be used where an ** [unprotected sqlite3_value] object is required, so either ** kind of [sqlite3_value] object can be used with this interface. ** -** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an +** ^The sqlite3_result_pointer(C,P) 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 +** also associates the host-language pointer P 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. +** This mechanism can be used to pass non-SQL values between +** application-defined functions. ** ** 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. */ @@ -6350,40 +5124,26 @@ void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); 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_pointer(sqlite3_context*, void*); SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Setting The Subtype Of An SQL Function ** METHOD: sqlite3_context ** ** The sqlite3_result_subtype(C,T) function causes the subtype of -** the result from the [application-defined SQL function] with -** [sqlite3_context] C to be the value T. Only the lower 8 bits +** the result from the [application-defined SQL function] with +** [sqlite3_context] C to be the value T. Only the lower 8 bits ** of the subtype T are preserved in current versions of SQLite; ** higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. -** -** Every [application-defined SQL function] that invokes this interface -** should include the [SQLITE_RESULT_SUBTYPE] property in its -** text encoding argument when the SQL function is -** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE] -** property is omitted from the function that invokes sqlite3_result_subtype(), -** then in some cases the sqlite3_result_subtype() might fail to set -** the result subtype. -** -** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any -** SQL function that invokes the sqlite3_result_subtype() interface -** and that does not have the SQLITE_RESULT_SUBTYPE property will raise -** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1 -** by default. */ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences @@ -6405,32 +5165,31 @@ **
      • [SQLITE_UTF16BE], **
      • [SQLITE_UTF16], or **
      • [SQLITE_UTF16_ALIGNED]. **
      )^ ** ^The eTextRep argument determines the encoding of strings passed -** to the collating function callback, xCompare. +** to the collating function callback, xCallback. ** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep ** force strings to be UTF16 with native byte order. ** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin ** on an even byte address. ** ** ^The fourth argument, pArg, is an application data pointer that is passed ** through as the first argument to the collating function callback. ** -** ^The fifth argument, xCompare, is a pointer to the collating function. +** ^The fifth argument, xCallback, is a pointer to the collating function. ** ^Multiple collating functions can be registered using the same name but ** with different eTextRep parameters and SQLite will use whichever ** function requires the least amount of data transformation. -** ^If the xCompare argument is NULL then the collating function is +** ^If the xCallback argument is NULL then the collating function is ** deleted. ^When all collating functions having the same name are deleted, ** that collation is no longer usable. ** -** ^The collating function callback is invoked with a copy of the pArg +** ^The collating function callback is invoked with a copy of the pArg ** application data pointer and with two strings in the encoding specified -** by the eTextRep argument. The two integer parameters to the collating -** function callback are the length of the two strings, in bytes. The collating -** function must return an integer that is negative, zero, or positive +** by the eTextRep argument. The collating function must return an +** integer that is negative, zero, or positive ** if the first string is less than, equal to, or greater than the second, ** respectively. A collating function must always return the same answer ** given the same inputs. If two or more collating functions are registered ** to the same collation name (using different eTextRep values) then all ** must give an equivalent answer when invoked with equivalent strings. @@ -6443,50 +5202,50 @@ **
    • If A<B THEN B>A. **
    • If A<B and B<C then A<C. ** ** ** If a collating function fails any of the above constraints and that -** collating function is registered and used, then the behavior of SQLite +** collating function is registered and used, then the behavior of SQLite ** is undefined. ** ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() ** with the addition that the xDestroy callback is invoked on pArg when ** the collating function is deleted. ** ^Collating functions are deleted when they are overridden by later ** calls to the collation creation functions or when the ** [database connection] is closed using [sqlite3_close()]. ** -** ^The xDestroy callback is not called if the +** ^The xDestroy callback is not called if the ** sqlite3_create_collation_v2() function fails. Applications that invoke -** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should ** check the return code and dispose of the application data pointer ** themselves rather than expecting SQLite to deal with it for them. -** This is different from every other SQLite interface. The inconsistency -** is unfortunate but cannot be changed without breaking backwards +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards ** compatibility. ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ SQLITE_API int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, + sqlite3*, + const char *zName, + int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); SQLITE_API int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, + sqlite3*, + const char *zName, + int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); SQLITE_API int sqlite3_create_collation16( - sqlite3*, + sqlite3*, const void *zName, - int eTextRep, + int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); /* @@ -6515,23 +5274,68 @@ ** The callback function should register the desired collation using ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ SQLITE_API int sqlite3_collation_needed( - sqlite3*, - void*, + sqlite3*, + void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); SQLITE_API int sqlite3_collation_needed16( - sqlite3*, + sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) ); + +#ifdef SQLITE_HAS_CODEC +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); +SQLITE_API int sqlite3_key_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); +SQLITE_API int sqlite3_rekey_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The new key */ +); + +/* +** Specify the activation key for a SEE database. Unless +** activated, none of the SEE routines will work. +*/ +SQLITE_API void sqlite3_activate_see( + const char *zPassPhrase /* Activation phrase */ +); +#endif #ifdef SQLITE_ENABLE_CEROD /* -** Specify the activation key for a CEROD database. Unless +** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); @@ -6551,17 +5355,10 @@ ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. -** -** If a negative argument is passed to sqlite3_sleep() the results vary by -** VFS and operating system. Some system treat a negative argument as an -** instruction to sleep forever. Others understand it to mean do not sleep -** at all. ^In SQLite version 3.42.0 and later, a negative -** argument passed into sqlite3_sleep() is changed to zero before it is relayed -** down into the xSleep method of the VFS. */ SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -6590,11 +5387,11 @@ ** thereafter. ** ** ^The [temp_store_directory pragma] may modify this variable and cause ** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, ** the [temp_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from +** that this variable points to is held in memory obtained from ** [sqlite3_malloc] and the pragma may attempt to free that memory ** using [sqlite3_free]. ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [temp_store_directory pragma] should be avoided. @@ -6647,54 +5444,19 @@ ** thereafter. ** ** ^The [data_store_directory pragma] may modify this variable and cause ** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, ** the [data_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from +** that this variable points to is held in memory obtained from ** [sqlite3_malloc] and the pragma may attempt to free that memory ** using [sqlite3_free]. ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [data_store_directory pragma] should be avoided. */ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; -/* -** CAPI3REF: Win32 Specific Interface -** -** These interfaces are available only on Windows. The -** [sqlite3_win32_set_directory] interface is used to set the value associated -** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to -** zValue, depending on the value of the type parameter. The zValue parameter -** should be NULL to cause the previous value to be freed via [sqlite3_free]; -** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] -** prior to being used. The [sqlite3_win32_set_directory] interface returns -** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, -** or [SQLITE_NOMEM] if memory could not be allocated. The value of the -** [sqlite3_data_directory] variable is intended to act as a replacement for -** the current directory on the sub-platforms of Win32 where that concept is -** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and -** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the -** sqlite3_win32_set_directory interface except the string parameter must be -** UTF-8 or UTF-16, respectively. -*/ -SQLITE_API int sqlite3_win32_set_directory( - unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ -); -SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); -SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); - -/* -** CAPI3REF: Win32 Directory Types -** -** These macros are only available on Windows. They define the allowed values -** for the type argument to the [sqlite3_win32_set_directory] interface. -*/ -#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 -#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 - /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} ** METHOD: sqlite3 ** @@ -6728,63 +5490,26 @@ ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); -/* -** CAPI3REF: Return The Schema Name For A Database Connection -** METHOD: sqlite3 -** -** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name -** for the N-th database on database connection D, or a NULL pointer of N is -** out of range. An N value of 0 means the main database file. An N of 1 is -** the "temp" schema. Larger values of N correspond to various ATTACH-ed -** databases. -** -** Space to hold the string that is returned by sqlite3_db_name() is managed -** by SQLite itself. The string might be deallocated by any operation that -** changes the schema, including [ATTACH] or [DETACH] or calls to -** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that -** occur on a different thread. Applications that need to -** remember the string long-term should make their own copy. Applications that -** are accessing the same database connection simultaneously on multiple -** threads should mutex-protect calls to this API and should make their own -** private copy of the result prior to releasing the mutex. -*/ -SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N); - /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** -** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename -** associated with database N of connection D. -** ^If there is no attached database N on the database +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then -** this function will return either a NULL pointer or an empty string. -** -** ^The string value returned by this routine is owned and managed by -** the database connection. ^The value will be valid until the database N -** is [DETACH]-ed or until the database connection closes. +** a NULL pointer is returned. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. -** -** If the filename pointer returned by this routine is not NULL, then it -** can be used as the filename input parameter to these routines: -**
        -**
      • [sqlite3_uri_parameter()] -**
      • [sqlite3_uri_boolean()] -**
      • [sqlite3_uri_int64()] -**
      • [sqlite3_filename_database()] -**
      • [sqlite3_filename_journal()] -**
      • [sqlite3_filename_wal()] -**
      */ -SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only ** METHOD: sqlite3 ** @@ -6792,61 +5517,10 @@ ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); -/* -** CAPI3REF: Determine the transaction state of a database -** METHOD: sqlite3 -** -** ^The sqlite3_txn_state(D,S) interface returns the current -** [transaction state] of schema S in database connection D. ^If S is NULL, -** then the highest transaction state of any schema on database connection D -** is returned. Transaction states are (in order of lowest to highest): -**
        -**
      1. SQLITE_TXN_NONE -**
      2. SQLITE_TXN_READ -**
      3. SQLITE_TXN_WRITE -**
      -** ^If the S argument to sqlite3_txn_state(D,S) is not the name of -** a valid schema, then -1 is returned. -*/ -SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); - -/* -** CAPI3REF: Allowed return values from sqlite3_txn_state() -** KEYWORDS: {transaction state} -** -** These constants define the current transaction state of a database file. -** ^The [sqlite3_txn_state(D,S)] interface returns one of these -** constants in order to describe the transaction state of schema S -** in [database connection] D. -** -**
      -** [[SQLITE_TXN_NONE]]
      SQLITE_TXN_NONE
      -**
      The SQLITE_TXN_NONE state means that no transaction is currently -** pending.
      -** -** [[SQLITE_TXN_READ]]
      SQLITE_TXN_READ
      -**
      The SQLITE_TXN_READ state means that the database is currently -** in a read transaction. Content has been read from the database file -** but nothing in the database file has changed. The transaction state -** will advanced to SQLITE_TXN_WRITE if any changes occur and there are -** no other conflicting concurrent write transactions. The transaction -** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or -** [COMMIT].
      -** -** [[SQLITE_TXN_WRITE]]
      SQLITE_TXN_WRITE
      -**
      The SQLITE_TXN_WRITE state means that the database is currently -** in a write transaction. Content has been written to the database file -** but has not yet committed. The transaction state will change to -** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
      -*/ -#define SQLITE_TXN_NONE 0 -#define SQLITE_TXN_READ 1 -#define SQLITE_TXN_WRITE 2 - /* ** CAPI3REF: Find the next prepared statement ** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after @@ -6908,76 +5582,10 @@ ** ** See also the [sqlite3_update_hook()] interface. */ SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Autovacuum Compaction Amount Callback -** METHOD: sqlite3 -** -** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback -** function C that is invoked prior to each autovacuum of the database -** file. ^The callback is passed a copy of the generic data pointer (P), -** the schema-name of the attached database that is being autovacuumed, -** the size of the database file in pages, the number of free pages, -** and the number of bytes per page, respectively. The callback should -** return the number of free pages that should be removed by the -** autovacuum. ^If the callback returns zero, then no autovacuum happens. -** ^If the value returned is greater than or equal to the number of -** free pages, then a complete autovacuum happens. -** -**

      ^If there are multiple ATTACH-ed database files that are being -** modified as part of a transaction commit, then the autovacuum pages -** callback is invoked separately for each file. -** -**

      The callback is not reentrant. The callback function should -** not attempt to invoke any other SQLite interface. If it does, bad -** things may happen, including segmentation faults and corrupt database -** files. The callback function should be a simple function that -** does some arithmetic on its input parameters and returns a result. -** -** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional -** destructor for the P parameter. ^If X is not NULL, then X(P) is -** invoked whenever the database connection closes or when the callback -** is overwritten by another invocation of sqlite3_autovacuum_pages(). -** -**

      ^There is only one autovacuum pages callback per database connection. -** ^Each call to the sqlite3_autovacuum_pages() interface overrides all -** previous invocations for that database connection. ^If the callback -** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, -** then the autovacuum steps callback is canceled. The return value -** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might -** be some other error code if something goes wrong. The current -** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other -** return codes might be added in future releases. -** -**

      If no autovacuum pages callback is specified (the usual case) or -** a NULL pointer is provided for the callback, -** then the default behavior is to vacuum all free pages. So, in other -** words, the default behavior is the same as if the callback function -** were something like this: -** -**

      -**     unsigned int demonstration_autovac_pages_callback(
      -**       void *pClientData,
      -**       const char *zSchema,
      -**       unsigned int nDbPage,
      -**       unsigned int nFreePage,
      -**       unsigned int nBytePerPage
      -**     ){
      -**       return nFreePage;
      -**     }
      -** 
      -*/ -SQLITE_API int sqlite3_autovacuum_pages( - sqlite3 *db, - unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), - void*, - void(*)(void*) -); - /* ** CAPI3REF: Data Change Notification Callbacks ** METHOD: sqlite3 ** @@ -6999,26 +5607,20 @@ ** database and table name containing the affected row. ** ^The final callback parameter is the [rowid] of the row. ** ^In the case of an update, this is the [rowid] after the update takes place. ** ** ^(The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_sequence).)^ +** modified (i.e. sqlite_master and sqlite_sequence).)^ ** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. ** ** ^In the current implementation, the update hook ** 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 ** release of SQLite. ** -** Whether the update hook is invoked before or after the -** corresponding change is currently unspecified and may differ -** depending on the type of change. Do not rely on the order of the -** hook call with regards to the final result of the operation which -** triggers the hook. -** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the update hook. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their @@ -7031,11 +5633,11 @@ ** ** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], ** and [sqlite3_preupdate_hook()] interfaces. */ SQLITE_API void *sqlite3_update_hook( - sqlite3*, + sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* ); /* @@ -7044,39 +5646,30 @@ ** ^(This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] ** to the same database. Sharing is enabled if the argument is true ** and disabled if the argument is false.)^ ** -** This interface is omitted if SQLite is compiled with -** [-DSQLITE_OMIT_SHARED_CACHE]. The [-DSQLITE_OMIT_SHARED_CACHE] -** compile-time option is recommended because the -** [use of shared cache mode is discouraged]. -** ** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). ** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent ** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** Existing database connections continue to use the sharing mode +** Existing database connections continue use the sharing mode ** that was in effect at the time they were opened.)^ ** ** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled ** successfully. An [error code] is returned otherwise.)^ ** -** ^Shared cache is disabled by default. It is recommended that it stay -** that way. In other words, do not use this routine. This interface -** continues to be provided for historical compatibility, but its use is -** discouraged. Any use of shared cache is discouraged. If shared cache -** must be used, it is recommended that shared cache only be enabled for -** individual database connections using the [sqlite3_open_v2()] interface -** with the [SQLITE_OPEN_SHAREDCACHE] flag. +** ^Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. ** ** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 -** and will always return SQLITE_MISUSE. On those systems, -** shared cache mode should be enabled per-database connection via +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via ** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. ** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** @@ -7115,58 +5708,34 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** -** These interfaces impose limits on the amount of heap memory that will be -** by all database connections within a single process. -** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap ** limit by reducing the number of pages held in the page cache ** as heap memory usages approaches the limit. ** ^The soft heap limit is "soft" because even though SQLite strives to stay ** below the limit, it will exceed the limit rather than generate -** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** an [SQLITE_NOMEM] error. In other words, the soft heap limit ** is advisory only. ** -** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of -** N bytes on the amount of memory that will be allocated. ^The -** sqlite3_hard_heap_limit64(N) interface is similar to -** sqlite3_soft_heap_limit64(N) except that memory allocations will fail -** when the hard heap limit is reached. -** -** ^The return value from both sqlite3_soft_heap_limit64() and -** sqlite3_hard_heap_limit64() is the size of -** the heap limit prior to the call, or negative in the case of an +** ^The return value from sqlite3_soft_heap_limit64() is the size of +** the soft heap limit prior to the call, or negative in the case of an ** error. ^If the argument N is negative -** then no change is made to the heap limit. Hence, the current -** size of heap limits can be determined by invoking -** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1). -** -** ^Setting the heap limits to zero disables the heap limiter mechanism. -** -** ^The soft heap limit may not be greater than the hard heap limit. -** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N) -** is invoked with a value of N that is greater than the hard heap limit, -** the soft heap limit is set to the value of the hard heap limit. -** ^The soft heap limit is automatically enabled whenever the hard heap -** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and -** the soft heap limit is outside the range of 1..N, then the soft heap -** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the -** hard heap limit is enabled makes the soft heap limit equal to the -** hard heap limit. -** -** The memory allocation limits can also be adjusted using -** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit]. -** -** ^(The heap limits are not enforced in the current implementation +** then no change is made to the soft heap limit. Hence, the current +** size of the soft heap limit can be determined by invoking +** sqlite3_soft_heap_limit64() with a negative argument. +** +** ^If the argument N is zero then the soft heap limit is disabled. +** +** ^(The soft heap limit is not enforced in the current implementation ** if one or more of following conditions are true: ** **
        -**
      • The limit value is set to zero. +**
      • The soft heap limit is set to zero. **
      • Memory accounting is disabled using a combination of the ** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and ** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. **
      • An alternative page cache implementation is specified using ** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). @@ -7173,15 +5742,25 @@ **
      • The page cache allocates from its own memory pool supplied ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** from the heap. **
      )^ ** -** The circumstances under which SQLite will enforce the heap limits may +** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), +** the soft heap limit is enforced +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], +** the soft heap limit is enforced on every memory allocation. Without +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced +** when memory is allocated by the page cache. Testing suggests that because +** the page cache is the predominate memory user in SQLite, most +** applications will achieve adequate soft heap limit enforcement without +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); -SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED ** @@ -7201,11 +5780,11 @@ ** information about column C of table T in database D ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() ** interface returns SQLITE_OK and fills in the non-NULL pointers in ** the final five arguments with appropriate values if the specified ** column exists. ^The sqlite3_table_column_metadata() interface returns -** SQLITE_ERROR if the specified column does not exist. +** SQLITE_ERROR and if the specified column does not exist. ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it ** 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 @@ -7241,11 +5820,11 @@ ** declaration type and collation sequence is valid until the next ** call to any SQLite API function. ** ** ^If the specified table is actually a view, an [error code] is returned. ** -** ^If the specified column is "rowid", "oid" or "_rowid_" and the table +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table ** is not a [WITHOUT ROWID] table and an ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output ** parameters are set for the explicitly declared column. ^(If there is no ** [INTEGER PRIMARY KEY] column, then the outputs ** for the [rowid] are set as follows: @@ -7307,11 +5886,11 @@ ** [sqlite3_enable_load_extension()] or ** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) ** prior to calling this API, ** otherwise an error will be returned. ** -** Security warning: It is recommended that the +** Security warning: It is recommended that the ** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this ** interface. The use of the [sqlite3_enable_load_extension()] interface ** should be avoided. This will keep the SQL function [load_extension()] ** disabled and prevent SQL injections from giving attackers ** access to extension loading capabilities. @@ -7343,11 +5922,11 @@ ** [sqlite3_load_extension()] and the SQL function [load_extension()]. ** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) ** to enable or disable only the C-API.)^ ** ** Security warning: It is recommended that extension loading -** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method +** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method ** rather than this interface, so the [load_extension()] SQL function ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); @@ -7394,11 +5973,11 @@ ** CAPI3REF: Cancel Automatic Extension Loading ** ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the ** initialization routine X that was registered using a prior call to ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] -** routine returns 1 if initialization routine X was successfully +** routine returns 1 if initialization routine X was successfully ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); @@ -7408,10 +5987,19 @@ ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ SQLITE_API void sqlite3_reset_auto_extension(void); +/* +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + /* ** Structures used by the virtual table interface */ typedef struct sqlite3_vtab sqlite3_vtab; typedef struct sqlite3_index_info sqlite3_index_info; @@ -7420,12 +6008,12 @@ /* ** CAPI3REF: Virtual Table Object ** KEYWORDS: sqlite3_module {virtual table module} ** -** This structure, sometimes called a "virtual table module", -** defines the implementation of a [virtual table]. +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual tables]. ** This structure consists mostly of methods for the module. ** ** ^A virtual table module is created by filling in a persistent ** instance of this structure and passing a pointer to that instance ** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. @@ -7460,22 +6048,15 @@ int (*xRollback)(sqlite3_vtab *pVTab); int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg); int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); - /* The methods above are in version 1 of the sqlite_module object. Those + /* The methods above are in version 1 of the sqlite_module object. Those ** below are for version 2 and greater. */ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); - /* The methods above are in versions 1 and 2 of the sqlite_module object. - ** Those below are for version 3 and greater. */ - int (*xShadowName)(const char*); - /* The methods above are in versions 1 through 3 of the sqlite_module object. - ** Those below are for version 4 and greater. */ - int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema, - const char *zTabName, int mFlags, char **pzErr); }; /* ** CAPI3REF: Virtual Table Indexing Information ** KEYWORDS: sqlite3_index_info @@ -7514,50 +6095,42 @@ ** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), ** the corresponding bit is set within the colUsed mask if the column may be ** required by SQLite. If the table has at least 64 columns and any column ** to the right of the first 63 is required, then bit 63 of colUsed is also ** set. In other words, column iCol may be required if the expression -** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to +** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to ** non-zero. ** ** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the -** virtual table and might not be checked again by the byte code.)^ ^(The -** aConstraintUsage[].omit flag is an optimization hint. When the omit flag -** is left in its default setting of false, the constraint will always be -** checked separately in byte code. If the omit flag is change to true, then -** the constraint may or may not be checked in byte code. In other words, -** when the omit flag is true there is no guarantee that the constraint will -** not be checked again using byte code.)^ +** virtual table and is not checked again by SQLite.)^ ** -** ^The idxNum and idxStr values are recorded and passed into the +** ^The idxNum and idxPtr values are recorded and passed into the ** [xFilter] method. -** ^[sqlite3_free()] is used to free idxStr if and only if -** needToFreeIdxStr is true. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate ** sorting step is required. ** ** ^The estimatedCost value is an estimate of the cost of a particular ** strategy. A cost of N indicates that the cost of the strategy is similar -** to a linear scan of an SQLite table with N rows. A cost of log(N) +** to a linear scan of an SQLite table with N rows. A cost of log(N) ** indicates that the expense of the operation is similar to that of a ** binary search on a unique indexed field of an SQLite table with N rows. ** ** ^The estimatedRows value is an estimate of the number of rows that ** will be returned by the strategy. ** -** The xBestIndex method may optionally populate the idxFlags field with a -** mask of SQLITE_INDEX_SCAN_* flags. One such flag is -** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN] -** output to show the idxNum has hex instead of as decimal. Another flag is -** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will -** return at most one row. +** The xBestIndex method may optionally populate the idxFlags field with a +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite +** assumes that the strategy may visit at most one row. ** ** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then ** SQLite also assumes that if a call to the xUpdate() method is made as ** part of the same statement to delete or update a virtual table row and the ** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback @@ -7566,18 +6139,18 @@ ** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not ** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by ** the xUpdate method are automatically rolled back by SQLite. ** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info -** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). ** If a virtual table extension is -** used with an SQLite version earlier than 3.8.2, the results of attempting -** to read or write the estimatedRows field are undefined (but are likely -** to include crashing the application). The estimatedRows field should +** used with an SQLite version earlier than 3.8.2, the results of attempting +** to read or write the estimatedRows field are undefined (but are likely +** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a ** value greater than or equal to 3008002. Similarly, the idxFlags field -** was added for [version 3.9.0] ([dateof:3.9.0]). +** was added for [version 3.9.0] ([dateof:3.9.0]). ** It may therefore only be used if ** sqlite3_libversion_number() returns a value greater than or equal to ** 3009000. */ struct sqlite3_index_info { @@ -7612,74 +6185,30 @@ sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ }; /* ** CAPI3REF: Virtual Table Scan Flags -** -** Virtual table implementations are allowed to set the -** [sqlite3_index_info].idxFlags field to some combination of -** these bits. */ -#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */ -#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */ - /* in EXPLAIN QUERY PLAN */ +#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** -** These macros define the allowed values for the +** These macros defined the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents -** an operator that is part of a constraint term in the WHERE clause of +** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. -** -** ^The left-hand operand of the operator is given by the corresponding -** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand -** operand is the rowid. -** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET -** operators have no left-hand operand, and so for those operators the -** corresponding aConstraint[].iColumn is meaningless and should not be -** used. -** -** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through -** value 255 are reserved to represent functions that are overloaded -** by the [xFindFunction|xFindFunction method] of the virtual table -** implementation. -** -** The right-hand operands for each constraint might be accessible using -** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand -** operand is only available if it appears as a single constant literal -** in the input SQL. If the right-hand operand is another column or an -** expression (even a constant expression) or a parameter, then the -** sqlite3_vtab_rhs_value() probably will not be able to extract it. -** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and -** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand -** and hence calls to sqlite3_vtab_rhs_value() for those operators will -** always return SQLITE_NOTFOUND. -** -** The collating sequence to be used for comparison can be found using -** the [sqlite3_vtab_collation()] interface. For most real-world virtual -** tables, the collating sequence of constraints does not matter (for example -** because the constraints are numeric) and so the sqlite3_vtab_collation() -** interface is not commonly needed. */ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 -#define SQLITE_INDEX_CONSTRAINT_NE 68 -#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 -#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 -#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 -#define SQLITE_INDEX_CONSTRAINT_IS 72 -#define SQLITE_INDEX_CONSTRAINT_LIMIT 73 -#define SQLITE_INDEX_CONSTRAINT_OFFSET 74 -#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 +#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 /* ** CAPI3REF: Register A Virtual Table Implementation ** METHOD: sqlite3 ** @@ -7687,11 +6216,11 @@ ** ^Module names must be registered before ** creating a new [virtual table] using the module and before using a ** preexisting [virtual table] for the module. ** ** ^The module name is registered on the [database connection] specified -** by the first parameter. ^The name of the module is given by the +** by the first parameter. ^The name of the module is given by the ** second parameter. ^The third parameter is a pointer to ** the implementation of the [virtual table module]. ^The fourth ** parameter is an arbitrary client data pointer that is passed through ** into the [xCreate] and [xConnect] methods of the virtual table module ** when a new virtual table is be being created or reinitialized. @@ -7702,16 +6231,10 @@ ** no longer needs the pClientData pointer. ^The destructor will also ** be invoked if the call to sqlite3_create_module_v2() fails. ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. -** -** ^If the third parameter (the pointer to the sqlite3_module object) is -** NULL then no new module is created and any existing modules with the -** same name are dropped. -** -** See also: [sqlite3_drop_modules()] */ SQLITE_API int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -7723,27 +6246,10 @@ const sqlite3_module *p, /* Methods for the module */ void *pClientData, /* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ ); -/* -** CAPI3REF: Remove Unnecessary Virtual Table Implementations -** METHOD: sqlite3 -** -** ^The sqlite3_drop_modules(D,L) interface removes all virtual -** table modules from database connection D except those named on list L. -** The L parameter must be either NULL or a pointer to an array of pointers -** to strings where the array is terminated by a single NULL pointer. -** ^If the L parameter is NULL, then all virtual table modules are removed. -** -** See also: [sqlite3_create_module()] -*/ -SQLITE_API int sqlite3_drop_modules( - sqlite3 *db, /* Remove modules from this connection */ - const char **azKeep /* Except, do not remove the ones named here */ -); - /* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab ** ** Every [virtual table module] implementation uses a subclass @@ -7802,11 +6308,11 @@ /* ** CAPI3REF: Overload A Function For A Virtual Table ** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions -** using the [xFindFunction] method of the [virtual table module]. +** using the [xFindFunction] method of the [virtual table module]. ** But global versions of those functions ** must exist in order to be overloaded.)^ ** ** ^(This API makes sure a global version of a function with a particular ** name and number of parameters exists. If no such function exists @@ -7815,10 +6321,20 @@ ** the new function is not good for anything by itself. Its only ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ /* ** CAPI3REF: A Handle To An Open BLOB ** KEYWORDS: {BLOB handle} {BLOB handles} ** @@ -7843,11 +6359,11 @@ ** **
       **     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
       ** 
      )^ ** -** ^(Parameter zDb is not the filename that contains the database, but +** ^(Parameter zDb is not the filename that contains the database, but ** rather the symbolic name of the database. For attached databases, this is ** the name that appears after the AS keyword in the [ATTACH] statement. ** For the main database file, the database name is "main". For TEMP ** tables, the database name is "temp".)^ ** @@ -7856,32 +6372,32 @@ ** read-only access. ** ** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored ** in *ppBlob. Otherwise an [error code] is returned and, unless the error ** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided -** the API is not misused, it is always safe to call [sqlite3_blob_close()] +** the API is not misused, it is always safe to call [sqlite3_blob_close()] ** on *ppBlob after this function it returns. ** ** This function fails with SQLITE_ERROR if any of the following are true: **
        -**
      • ^(Database zDb does not exist)^, -**
      • ^(Table zTable does not exist within database zDb)^, -**
      • ^(Table zTable is a WITHOUT ROWID table)^, +**
      • ^(Database zDb does not exist)^, +**
      • ^(Table zTable does not exist within database zDb)^, +**
      • ^(Table zTable is a WITHOUT ROWID table)^, **
      • ^(Column zColumn does not exist)^, **
      • ^(Row iRow is not present in the table)^, **
      • ^(The specified column of row iRow contains a value that is not ** a TEXT or BLOB value)^, -**
      • ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE +**
      • ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE ** constraint and the blob is being opened for read/write access)^, -**
      • ^([foreign key constraints | Foreign key constraints] are enabled, +**
      • ^([foreign key constraints | Foreign key constraints] are enabled, ** column zColumn is part of a [child key] definition and the blob is ** being opened for read/write access)^. **
      ** -** ^Unless it returns SQLITE_MISUSE, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** ^Unless it returns SQLITE_MISUSE, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** A BLOB referenced by sqlite3_blob_open() may be read using the ** [sqlite3_blob_read()] interface and modified by using ** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a ** different row of the same table using the [sqlite3_blob_reopen()] @@ -7903,11 +6419,11 @@ ** the opened blob. ^The size of a blob may not be changed by this ** interface. Use the [UPDATE] SQL command to change the size of a ** blob. ** ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces -** and the built-in [zeroblob] SQL function may be used to create a +** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. ** @@ -7953,33 +6469,33 @@ /* ** CAPI3REF: Close A BLOB Handle ** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed -** unconditionally. Even if this routine returns an error code, the +** unconditionally. Even if this routine returns an error code, the ** handle is still closed.)^ ** ** ^If the blob handle being closed was opened for read-write access, and if ** the database is in auto-commit mode and there are no other open read-write ** blob handles or active write statements, the current transaction is ** committed. ^If an error occurs while committing the transaction, an error ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behavior. ^Calling this routine -** with a null pointer (such as would be returned by a failed call to +** open blob handle results in undefined behaviour. ^Calling this routine +** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function -** is passed a valid open blob handle, the values returned by the +** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB ** METHOD: sqlite3_blob ** -** ^Returns the size in bytes of the BLOB accessible via the +** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The ** incremental blob I/O routines can only read or overwriting existing ** blob content; they cannot change the size of a blob. ** ** This routine only works on a [BLOB handle] which has been created @@ -8026,24 +6542,24 @@ ** caller-supplied buffer. N bytes of data are copied from the buffer Z ** into the open BLOB, starting at offset iOffset.)^ ** ** ^(On success, sqlite3_blob_write() returns SQLITE_OK. ** Otherwise, an [error code] or an [extended error code] is returned.)^ -** ^Unless SQLITE_MISUSE is returned, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** ^Unless SQLITE_MISUSE is returned, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** ^If the [BLOB handle] passed as the first argument was not opened for ** writing (the flags parameter to [sqlite3_blob_open()] was zero), ** this function returns [SQLITE_READONLY]. ** ** This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is written. The size of the -** BLOB (and hence the maximum value of N+iOffset) can be determined -** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less +** [SQLITE_ERROR] is returned and no data is written. The size of the +** BLOB (and hence the maximum value of N+iOffset) can be determined +** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less ** than zero [SQLITE_ERROR] is returned and no data is written. ** ** ^An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the @@ -8133,11 +6649,11 @@ ** integer constants: ** **
        **
      • SQLITE_MUTEX_FAST **
      • SQLITE_MUTEX_RECURSIVE -**
      • SQLITE_MUTEX_STATIC_MAIN +**
      • SQLITE_MUTEX_STATIC_MASTER **
      • SQLITE_MUTEX_STATIC_MEM **
      • SQLITE_MUTEX_STATIC_OPEN **
      • SQLITE_MUTEX_STATIC_PRNG **
      • SQLITE_MUTEX_STATIC_LRU **
      • SQLITE_MUTEX_STATIC_PMEM @@ -8190,24 +6706,22 @@ ** can enter.)^ If the same thread tries to enter any mutex other ** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined. ** ** ^(Some systems (for example, Windows 95) do not support the operation ** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() -** will always return SQLITE_BUSY. In most cases the SQLite core only uses -** sqlite3_mutex_try() as an optimization, so this is acceptable -** behavior. The exceptions are unix builds that set the -** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working -** sqlite3_mutex_try() is required.)^ +** will always return SQLITE_BUSY. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable +** behavior.)^ ** ** ^The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered by the ** calling thread or is not currently allocated. ** -** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), -** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer, -** then any of the four routines behaves as a no-op. +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); @@ -8258,11 +6772,11 @@ **
      )^ ** ** The only difference is that the public sqlite3_XXX functions enumerated ** above silently ignore any invocations that pass a NULL pointer instead ** of a valid mutex handle. The implementations of the methods defined -** by this structure are not required to handle this case. The results +** by this structure are not required to handle this case, the results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). ** ** The xMutexInit() method must be threadsafe. It must be harmless to @@ -8337,11 +6851,11 @@ ** next. Applications that override the built-in mutex logic must be ** prepared to accommodate additional static mutexes. */ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MAIN 2 +#define SQLITE_MUTEX_STATIC_MASTER 2 #define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ #define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ #define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ @@ -8351,20 +6865,16 @@ #define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */ #define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */ #define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */ #define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */ #define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */ - -/* Legacy compatibility: */ -#define SQLITE_MUTEX_STATIC_MASTER 2 - /* ** CAPI3REF: Retrieve the mutex for a database connection ** METHOD: sqlite3 ** -** ^This interface returns a pointer the [sqlite3_mutex] object that +** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ @@ -8371,11 +6881,10 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files ** METHOD: sqlite3 -** KEYWORDS: {file control} ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated ** with a particular database identified by the second argument. ^The ** name of the database is "main" for the main database or "temp" for the @@ -8386,32 +6895,25 @@ ** ^The third and fourth parameters to this routine ** are passed directly through to the second and third parameters of ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** -** A few opcodes for [sqlite3_file_control()] are handled directly -** by the SQLite core and never invoke the -** sqlite3_io_methods.xFileControl method. -** ^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_JOURNAL_POINTER] works similarly except that it returns -** the [sqlite3_file] object associated with the journal file instead of -** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns -** a pointer to the underlying [sqlite3_vfs] object for the file. -** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter -** from the pager. +** 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. ** ** ^If the second parameter (zDbName) does not match the name of any ** open database file, then SQLITE_ERROR is returned. ^This error ** code is not remembered and will not be recalled by [sqlite3_errcode()] ** or [sqlite3_errmsg()]. The underlying xFileControl method might ** also return SQLITE_ERROR. There is no way to distinguish between ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** -** See also: [file control opcodes] +** See also: [SQLITE_FCNTL_LOCKSTATE] */ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -8444,227 +6946,31 @@ ** [sqlite3_test_control()] interface. */ #define SQLITE_TESTCTRL_FIRST 5 #define SQLITE_TESTCTRL_PRNG_SAVE 5 #define SQLITE_TESTCTRL_PRNG_RESTORE 6 -#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ -#define SQLITE_TESTCTRL_FK_NO_ACTION 7 +#define SQLITE_TESTCTRL_PRNG_RESET 7 #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 -#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ -#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 +#define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ -#define SQLITE_TESTCTRL_GETOPT 16 -#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ -#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 +#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 -#define SQLITE_TESTCTRL_RESULT_INTREAL 27 -#define SQLITE_TESTCTRL_PRNG_SEED 28 -#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 -#define SQLITE_TESTCTRL_SEEK_COUNT 30 -#define SQLITE_TESTCTRL_TRACEFLAGS 31 -#define SQLITE_TESTCTRL_TUNE 32 -#define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ -#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ - -/* -** CAPI3REF: SQL Keyword Checking -** -** These routines provide access to the set of SQL language keywords -** recognized by SQLite. Applications can uses these routines to determine -** whether or not a specific identifier needs to be escaped (for example, -** by enclosing in double-quotes) so as not to confuse the parser. -** -** The sqlite3_keyword_count() interface returns the number of distinct -** keywords understood by SQLite. -** -** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and -** makes *Z point to that keyword expressed as UTF8 and writes the number -** of bytes in the keyword into *L. The string that *Z points to is not -** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns -** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z -** or L are NULL or invalid pointers then calls to -** sqlite3_keyword_name(N,Z,L) result in undefined behavior. -** -** The sqlite3_keyword_check(Z,L) interface checks to see whether or not -** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero -** if it is and zero if not. -** -** The parser used by SQLite is forgiving. It is often possible to use -** a keyword as an identifier as long as such use does not result in a -** parsing ambiguity. For example, the statement -** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and -** creates a new table named "BEGIN" with three columns named -** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid -** using keywords as identifiers. Common techniques used to avoid keyword -** name collisions include: -**
        -**
      • Put all identifier names inside double-quotes. This is the official -** SQL way to escape identifier names. -**
      • Put identifier names inside [...]. This is not standard SQL, -** but it is what SQL Server does and so lots of programmers use this -** technique. -**
      • Begin every identifier with the letter "Z" as no SQL keywords start -** with "Z". -**
      • Include a digit somewhere in every identifier name. -**
      -** -** Note that the number of keywords understood by SQLite can depend on -** compile-time options. For example, "VACUUM" is not a keyword if -** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, -** new keywords may be added to future releases of SQLite. -*/ -SQLITE_API int sqlite3_keyword_count(void); -SQLITE_API int sqlite3_keyword_name(int,const char**,int*); -SQLITE_API int sqlite3_keyword_check(const char*,int); - -/* -** CAPI3REF: Dynamic String Object -** KEYWORDS: {dynamic string} -** -** An instance of the sqlite3_str object contains a dynamically-sized -** string under construction. -** -** The lifecycle of an sqlite3_str object is as follows: -**
        -**
      1. ^The sqlite3_str object is created using [sqlite3_str_new()]. -**
      2. ^Text is appended to the sqlite3_str object using various -** methods, such as [sqlite3_str_appendf()]. -**
      3. ^The sqlite3_str object is destroyed and the string it created -** is returned using the [sqlite3_str_finish()] interface. -**
      -*/ -typedef struct sqlite3_str sqlite3_str; - -/* -** CAPI3REF: Create A New Dynamic String Object -** CONSTRUCTOR: sqlite3_str -** -** ^The [sqlite3_str_new(D)] interface allocates and initializes -** a new [sqlite3_str] object. To avoid memory leaks, the object returned by -** [sqlite3_str_new()] must be freed by a subsequent call to -** [sqlite3_str_finish(X)]. -** -** ^The [sqlite3_str_new(D)] interface always returns a pointer to a -** valid [sqlite3_str] object, though in the event of an out-of-memory -** error the returned object might be a special singleton that will -** silently reject new text, always return SQLITE_NOMEM from -** [sqlite3_str_errcode()], always return 0 for -** [sqlite3_str_length()], and always return NULL from -** [sqlite3_str_finish(X)]. It is always safe to use the value -** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter -** to any of the other [sqlite3_str] methods. -** -** The D parameter to [sqlite3_str_new(D)] may be NULL. If the -** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum -** length of the string contained in the [sqlite3_str] object will be -** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead -** of [SQLITE_MAX_LENGTH]. -*/ -SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); - -/* -** CAPI3REF: Finalize A Dynamic String -** DESTRUCTOR: sqlite3_str -** -** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X -** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] -** that contains the constructed string. The calling application should -** pass the returned value to [sqlite3_free()] to avoid a memory leak. -** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any -** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the -** string in [sqlite3_str] object X is zero bytes long. -*/ -SQLITE_API char *sqlite3_str_finish(sqlite3_str*); - -/* -** CAPI3REF: Add Content To A Dynamic String -** METHOD: sqlite3_str -** -** These interfaces add content to an sqlite3_str object previously obtained -** from [sqlite3_str_new()]. -** -** ^The [sqlite3_str_appendf(X,F,...)] and -** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] -** functionality of SQLite to append formatted text onto the end of -** [sqlite3_str] object X. -** -** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S -** onto the end of the [sqlite3_str] object X. N must be non-negative. -** S must contain at least N non-zero bytes of content. To append a -** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] -** method instead. -** -** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of -** zero-terminated string S onto the end of [sqlite3_str] object X. -** -** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the -** single-byte character C onto the end of [sqlite3_str] object X. -** ^This method can be used, for example, to add whitespace indentation. -** -** ^The [sqlite3_str_reset(X)] method resets the string under construction -** inside [sqlite3_str] object X back to zero bytes in length. -** -** These methods do not return a result code. ^If an error occurs, that fact -** is recorded in the [sqlite3_str] object and can be recovered by a -** subsequent call to [sqlite3_str_errcode(X)]. -*/ -SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); -SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); -SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); -SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); -SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); -SQLITE_API void sqlite3_str_reset(sqlite3_str*); - -/* -** CAPI3REF: Status Of A Dynamic String -** METHOD: sqlite3_str -** -** These interfaces return the current status of an [sqlite3_str] object. -** -** ^If any prior errors have occurred while constructing the dynamic string -** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return -** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns -** [SQLITE_NOMEM] following any out-of-memory error, or -** [SQLITE_TOOBIG] if the size of the dynamic string exceeds -** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. -** -** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, -** of the dynamic string under construction in [sqlite3_str] object X. -** ^The length returned by [sqlite3_str_length(X)] does not include the -** zero-termination byte. -** -** ^The [sqlite3_str_value(X)] method returns a pointer to the current -** content of the dynamic string under construction in X. The value -** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X -** and might be freed or altered by any subsequent method on the same -** [sqlite3_str] object. Applications must not used the pointer returned -** [sqlite3_str_value(X)] after any subsequent method call on the same -** object. ^Applications may change the content of the string returned -** by [sqlite3_str_value(X)] as long as they do not write into any bytes -** outside the range of 0 to [sqlite3_str_length(X)] and do not read or -** write any byte after any subsequent sqlite3_str method call. -*/ -SQLITE_API int sqlite3_str_errcode(sqlite3_str*); -SQLITE_API int sqlite3_str_length(sqlite3_str*); -SQLITE_API char *sqlite3_str_value(sqlite3_str*); +#define SQLITE_TESTCTRL_LAST 25 /* ** CAPI3REF: SQLite Runtime Status ** ** ^These interfaces are used to retrieve runtime status information @@ -8709,33 +7015,34 @@ **
      ** [[SQLITE_STATUS_MEMORY_USED]] ^(
      SQLITE_STATUS_MEMORY_USED
      **
      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. Auxiliary page-cache +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and 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].
      )^ ** ** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
      SQLITE_STATUS_MALLOC_SIZE
      **
      This parameter records the largest memory allocation request ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their ** internal equivalents). Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. +** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
      )^ ** ** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
      SQLITE_STATUS_MALLOC_COUNT
      **
      This parameter records the number of separate memory allocations ** currently checked out.
      )^ ** ** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
      SQLITE_STATUS_PAGECACHE_USED
      **
      This parameter returns the number of pages used out of the -** [pagecache memory allocator] that was configured using +** [pagecache memory allocator] that was configured using ** [SQLITE_CONFIG_PAGECACHE]. The ** value returned is in pages, not in bytes.
      )^ ** -** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] ** ^(
      SQLITE_STATUS_PAGECACHE_OVERFLOW
      **
      This parameter returns the number of bytes of page cache ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] ** buffer and where forced to overflow to [sqlite3_malloc()]. The ** returned value includes allocations that overflowed because they @@ -8743,52 +7050,67 @@ ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because ** no space was left in the page cache.
      )^ ** ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
      SQLITE_STATUS_PAGECACHE_SIZE
      **
      This parameter records the largest memory allocation request -** handed to the [pagecache memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.
      )^ ** -** [[SQLITE_STATUS_SCRATCH_USED]]
      SQLITE_STATUS_SCRATCH_USED
      -**
      No longer used.
      +** [[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_OVERFLOW]] ^(
      SQLITE_STATUS_SCRATCH_OVERFLOW
      -**
      No longer used.
      +**
      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
      -**
      No longer used.
      +** [[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.
      )^ ** ** [[SQLITE_STATUS_PARSER_STACK]] ^(
      SQLITE_STATUS_PARSER_STACK
      -**
      The *pHighwater parameter records the deepest parser stack. +**
      The *pHighwater parameter records the deepest parser stack. ** The *pCurrent value is undefined. The *pHighwater value is only ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
      )^ **
      ** ** New status parameters may be added from time to time. */ #define SQLITE_STATUS_MEMORY_USED 0 #define SQLITE_STATUS_PAGECACHE_USED 1 #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 -#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ -#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 #define SQLITE_STATUS_MALLOC_SIZE 5 #define SQLITE_STATUS_PARSER_STACK 6 #define SQLITE_STATUS_PAGECACHE_SIZE 7 -#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_SIZE 8 #define SQLITE_STATUS_MALLOC_COUNT 9 /* ** CAPI3REF: Database Connection Status ** METHOD: sqlite3 ** -** ^This interface is used to retrieve runtime status information +** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the ** database connection object to be interrogated. ^The second argument ** is an integer constant, taken from the set of ** [SQLITE_DBSTATUS options], that -** determines the parameter to interrogate. The set of +** determines the parameter to interrogate. The set of ** [SQLITE_DBSTATUS options] is likely ** to grow in future releases of SQLite. ** ** ^The current value of the requested parameter is written into *pCur ** and the highest instantaneous value is written into *pHiwtr. ^If @@ -8819,11 +7141,11 @@ ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
      SQLITE_DBSTATUS_LOOKASIDE_USED
      **
      This parameter returns the number of lookaside memory slots currently ** checked out.
      )^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
      SQLITE_DBSTATUS_LOOKASIDE_HIT
      -**
      This parameter returns the number of malloc attempts that were +**
      This parameter returns the number malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] ** ^(
      SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
      @@ -8844,11 +7166,11 @@ ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
      SQLITE_DBSTATUS_CACHE_USED
      **
      This parameter returns the approximate number of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** -** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] +** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] ** ^(
      SQLITE_DBSTATUS_CACHE_USED_SHARED
      **
      This parameter is similar to DBSTATUS_CACHE_USED, except that if a ** pager cache is shared between two or more connections the bytes of heap ** memory used by that pager cache is divided evenly between the attached ** connections.)^ In other words, if none of the pager caches associated @@ -8859,11 +7181,11 @@ ** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
      SQLITE_DBSTATUS_SCHEMA_USED
      **
      This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated -** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the ** schema memory is shared with other database connections due to ** [shared cache mode] being enabled. ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. ** @@ -8874,17 +7196,17 @@ ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. **
      ** ** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
      SQLITE_DBSTATUS_CACHE_HIT
      **
      This parameter returns the number of pager cache hits that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT ** is always 0. **
      ** ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
      SQLITE_DBSTATUS_CACHE_MISS
      **
      This parameter returns the number of pager cache misses that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. **
      ** ** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
      SQLITE_DBSTATUS_CACHE_WRITE
      **
      This parameter returns the number of dirty cache entries that have @@ -8895,19 +7217,10 @@ ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. **
      ** -** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(
      SQLITE_DBSTATUS_CACHE_SPILL
      -**
      This parameter returns the number of dirty cache entries that have -** been written to disk in the middle of a transaction due to the page -** cache overflowing. Transactions are more efficient if they are written -** to disk all at once. When pages spill mid-transaction, that introduces -** additional overhead. This parameter can be used help identify -** inefficiencies that can be resolved by increasing the cache size. -**
      -** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
      SQLITE_DBSTATUS_DEFERRED_FKS
      **
      This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. **
      @@ -8923,12 +7236,11 @@ #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_CACHE_SPILL 12 -#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** METHOD: sqlite3_stmt @@ -8938,11 +7250,11 @@ ** of times it has performed specific operations.)^ These counters can ** be used to monitor the performance characteristics of the prepared ** statements. For example, if the number of table steps greatly exceeds ** the number of table searches or result rows, that would tend to indicate ** that the prepared statement is using a full table scan rather than -** an index. +** an index. ** ** ^(This interface is used to retrieve and reset counter values from ** a [prepared statement]. The first argument is the prepared statement ** object to be interrogated. The second argument ** is an integer code for a specific [SQLITE_STMTSTATUS counter] @@ -8965,11 +7277,11 @@ ** **
      ** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
      SQLITE_STMTSTATUS_FULLSCAN_STEP
      **
      ^This is the number of times that SQLite has stepped forward in ** a table as part of a full table scan. Large numbers for this counter -** may indicate opportunities for performance improvement through +** may indicate opportunities for performance improvement through ** careful use of indices.
      ** ** [[SQLITE_STMTSTATUS_SORT]]
      SQLITE_STMTSTATUS_SORT
      **
      ^This is the number of sort operations that have occurred. ** A non-zero value in this counter may indicate an opportunity to @@ -8983,37 +7295,27 @@ ** need to be reinitialized each time the statement is run.
      ** ** [[SQLITE_STMTSTATUS_VM_STEP]]
      SQLITE_STMTSTATUS_VM_STEP
      **
      ^This is the number of virtual machine operations executed ** by the prepared statement if that number is less than or equal -** to 2147483647. The number of virtual machine operations can be +** to 2147483647. The number of virtual machine operations can be ** used as a proxy for the total work done by the prepared statement. ** If the number of virtual machine operations exceeds 2147483647 ** then the value returned by this statement status code is undefined. ** ** [[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 changes to +** 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_FILTER_MISS]] -** [[SQLITE_STMTSTATUS_FILTER HIT]] -**
      SQLITE_STMTSTATUS_FILTER_HIT
      -** SQLITE_STMTSTATUS_FILTER_MISS
      -**
      ^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join -** step was bypassed because a Bloom filter returned not-found. The -** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of -** times that the Bloom filter returned a find, and thus the join step -** had to be processed as normal. -** ** [[SQLITE_STMTSTATUS_MEMUSED]]
      SQLITE_STMTSTATUS_MEMUSED
      **
      ^This is the approximate number of bytes of heap memory ** 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. @@ -9024,12 +7326,10 @@ #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_FILTER_MISS 7 -#define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** @@ -9062,19 +7362,19 @@ /* ** CAPI3REF: Application Defined Page Cache. ** KEYWORDS: {page cache} ** ** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can -** register an alternative page cache implementation by passing in an +** register an alternative page cache implementation by passing in an ** instance of the sqlite3_pcache_methods2 structure.)^ -** In many applications, most of the heap memory allocated by +** In many applications, most of the heap memory allocated by ** SQLite is used for the page cache. -** By implementing a +** By implementing a ** custom page cache using this API, an application can better control -** the amount of memory consumed by SQLite, the way in which -** that memory is allocated and released, and the policies used to -** determine exactly which parts of a database file are cached and for +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for ** how long. ** ** The alternative page cache mechanism is an ** extreme measure that is only needed by the most demanding applications. ** The built-in page cache is recommended for most uses. @@ -9083,23 +7383,23 @@ ** internal buffer by SQLite within the call to [sqlite3_config]. Hence ** the application may discard the parameter after the call to ** [sqlite3_config()] returns.)^ ** ** [[the xInit() page cache method]] -** ^(The xInit() method is called once for each effective +** ^(The xInit() method is called once for each effective ** call to [sqlite3_initialize()])^ ** (usually only once during the lifetime of the process). ^(The xInit() ** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ -** The intent of the xInit() method is to set up global data structures -** required by the custom page cache implementation. -** ^(If the xInit() method is NULL, then the +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the ** built-in default page cache is used instead of the application defined ** page cache.)^ ** ** [[the xShutdown() page cache method]] ** ^The xShutdown() method is called by [sqlite3_shutdown()]. -** It can be used to clean up +** It can be used to clean up ** any outstanding resources before process shutdown, if required. ** ^The xShutdown() method may be NULL. ** ** ^SQLite automatically serializes calls to the xInit method, ** so the xInit method need not be threadsafe. ^The @@ -9114,11 +7414,11 @@ ** ^SQLite invokes the xCreate() method to construct a new cache instance. ** SQLite will typically create one cache instance for each open database file, ** though this is not guaranteed. ^The ** first parameter, szPage, is the size in bytes of the pages that must ** be allocated by the cache. ^szPage will always a power of two. ^The -** second parameter szExtra is a number of bytes of extra storage +** second parameter szExtra is a number of bytes of extra storage ** associated with each page cache entry. ^The szExtra parameter will ** a number less than 250. SQLite will use the ** extra szExtra bytes on each page to store metadata about the underlying ** database page on disk. The value passed into szExtra depends ** on the SQLite version, the target platform, and how SQLite was compiled. @@ -9127,11 +7427,11 @@ ** false if it is used for an in-memory database. The cache implementation ** does not have to do anything special based with the value of bPurgeable; ** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will ** never invoke xUnpin() except to deliberately delete a page. ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to -** false will always have the "discard" flag set to true. +** false will always have the "discard" flag set to true. ** ^Hence, a cache created with bPurgeable false will ** never contain any unpinned pages. ** ** [[the xCachesize() page cache method]] ** ^(The xCachesize() method may be called at any time by SQLite to set the @@ -9142,16 +7442,16 @@ ** value; it is advisory only. ** ** [[the xPagecount() page cache methods]] ** The xPagecount() method must return the number of pages currently ** stored in the cache, both pinned and unpinned. -** +** ** [[the xFetch() page cache methods]] -** The xFetch() method locates a page in the cache and returns a pointer to +** The xFetch() method locates a page in the cache and returns a pointer to ** an sqlite3_pcache_page object associated with that page, or a NULL pointer. ** The pBuf element of the returned sqlite3_pcache_page object will be a -** pointer to a buffer of szPage bytes used to store the content of a +** pointer to a buffer of szPage bytes used to store the content of a ** single database page. The pExtra element of sqlite3_pcache_page will be ** a pointer to the szExtra bytes of extra storage that SQLite has requested ** for each entry in the page cache. ** ** The page to be fetched is determined by the key. ^The minimum key value @@ -9173,11 +7473,11 @@ ** NULL if allocating a new page is effectively impossible. ** ** ** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite ** will only use a createFlag of 2 after a prior call with a createFlag of 1 -** failed.)^ In between the xFetch() calls, SQLite may +** failed.)^ In between the to xFetch() calls, SQLite may ** attempt to unpin one or more cache pages by spilling the content of ** pinned pages to disk and synching the operating system disk cache. ** ** [[the xUnpin() page cache method]] ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page @@ -9186,12 +7486,12 @@ ** ^If the discard parameter is ** zero, then the page may be discarded or retained at the discretion of ** page cache implementation. ^The page cache implementation ** may choose to evict unpinned pages at any time. ** -** The cache must not perform any reference counting. A single -** call to xUnpin() unpins the page regardless of the number of prior calls +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls ** to xFetch(). ** ** [[the xRekey() page cache methods]] ** The xRekey() method is used to change the key value associated with the ** page passed as the second argument. If the cache @@ -9227,11 +7527,11 @@ sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); void (*xCachesize)(sqlite3_pcache*, int nCachesize); int (*xPagecount)(sqlite3_pcache*); sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); - void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, unsigned oldKey, unsigned newKey); void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); void (*xDestroy)(sqlite3_pcache*); void (*xShrink)(sqlite3_pcache*); }; @@ -9272,11 +7572,11 @@ /* ** CAPI3REF: Online Backup API. ** ** The backup API copies the content of one database into another. ** It is useful either for creating backups of databases or -** for copying in-memory databases to or from persistent files. +** for copying in-memory databases to or from persistent files. ** ** See Also: [Using the SQLite Online Backup API] ** ** ^SQLite holds a write transaction open on the destination database file ** for the duration of the backup operation. @@ -9283,40 +7583,40 @@ ** ^The source database is read-locked only while it is being read; ** it is not locked continuously for the entire backup operation. ** ^Thus, the backup may be performed on a live source database without ** preventing other database connections from ** reading or writing to the source database while the backup is underway. -** -** ^(To perform a backup operation: +** +** ^(To perform a backup operation: **
        **
      1. sqlite3_backup_init() is called once to initialize the -** backup, -**
      2. sqlite3_backup_step() is called one or more times to transfer +** backup, +**
      3. sqlite3_backup_step() is called one or more times to transfer ** the data between the two databases, and finally -**
      4. sqlite3_backup_finish() is called to release all resources -** associated with the backup operation. +**
      5. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. **
      )^ ** There should be exactly one call to sqlite3_backup_finish() for each ** successful call to sqlite3_backup_init(). ** ** [[sqlite3_backup_init()]] sqlite3_backup_init() ** -** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the -** [database connection] associated with the destination database +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database ** and the database name, respectively. ** ^The database name is "main" for the main database, "temp" for the ** temporary database, or the name specified after the AS keyword in ** an [ATTACH] statement for an attached database. -** ^The S and M arguments passed to +** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** -** ^A call to sqlite3_backup_init() will fail, returning NULL, if -** there is already a read or read-write transaction open on the +** ^A call to sqlite3_backup_init() will fail, returning NULL, if +** there is already a read or read-write transaction open on the ** destination database. ** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. @@ -9324,18 +7624,18 @@ ** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or ** [sqlite3_errmsg16()] functions. ** ^A successful call to sqlite3_backup_init() returns a pointer to an ** [sqlite3_backup] object. ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and -** sqlite3_backup_finish() functions to perform the specified backup +** sqlite3_backup_finish() functions to perform the specified backup ** operation. ** ** [[sqlite3_backup_step()]] sqlite3_backup_step() ** -** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between ** the source and destination databases specified by [sqlite3_backup] object B. -** ^If N is negative, all remaining source pages are copied. +** ^If N is negative, all remaining source pages are copied. ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there ** are still more pages to be copied, then the function returns [SQLITE_OK]. ** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages ** from source to destination, then it returns [SQLITE_DONE]. ** ^If an error occurs while running sqlite3_backup_step(B,N), @@ -9353,48 +7653,48 @@ ** destination and source page sizes differ. ** )^ ** ** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then ** the [sqlite3_busy_handler | busy-handler function] -** is invoked (if one is specified). ^If the -** busy-handler returns non-zero before the lock is available, then +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then ** [SQLITE_BUSY] is returned to the caller. ^In this case the call to ** sqlite3_backup_step() can be retried later. ^If the source ** [database connection] ** is being used to write to the source database when sqlite3_backup_step() ** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this ** case the call to sqlite3_backup_step() can be retried later on. ^(If ** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or -** [SQLITE_READONLY] is returned, then -** there is no point in retrying the call to sqlite3_backup_step(). These -** errors are considered fatal.)^ The application must accept -** that the backup operation has failed and pass the backup operation handle +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle ** to the sqlite3_backup_finish() to release associated resources. ** ** ^The first call to sqlite3_backup_step() obtains an exclusive lock -** on the destination file. ^The exclusive lock is not released until either -** sqlite3_backup_finish() is called or the backup operation is complete +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete ** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to ** sqlite3_backup_step() obtains a [shared lock] on the source database that ** lasts for the duration of the sqlite3_backup_step() call. ** ^Because the source database is not locked between calls to ** sqlite3_backup_step(), the source database may be modified mid-way ** through the backup process. ^If the source database is modified by an ** external process or via a database connection other than the one being ** used by the backup operation, then the backup will be automatically -** restarted by the next call to sqlite3_backup_step(). ^If the source +** restarted by the next call to sqlite3_backup_step(). ^If the source ** database is modified by the using the same database connection as is used ** by the backup operation, then the backup database is automatically ** updated at the same time. ** ** [[sqlite3_backup_finish()]] sqlite3_backup_finish() ** -** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the ** application wishes to abandon the backup operation, the application ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). ** ^The sqlite3_backup_finish() interfaces releases all -** resources associated with the [sqlite3_backup] object. +** resources associated with the [sqlite3_backup] object. ** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any ** active write-transaction on the destination database is rolled back. ** The [sqlite3_backup] object is invalid ** and may not be used following a call to sqlite3_backup_finish(). ** @@ -9430,42 +7730,32 @@ ** purposes while a backup operation is underway or being initialized. ** ^If SQLite is compiled and configured to support threadsafe database ** connections, then the source database connection may be used concurrently ** from within other threads. ** -** However, the application must guarantee that the destination -** [database connection] is not passed to any other API (by any thread) after +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after ** sqlite3_backup_init() is called and before the corresponding call to ** sqlite3_backup_finish(). SQLite does not currently check to see ** if the application incorrectly accesses the destination [database connection] ** and so no error code is reported, but the operations may malfunction ** nevertheless. Use of the destination database connection while a -** backup is in progress might also cause a mutex deadlock. +** backup is in progress might also also cause a mutex deadlock. ** ** If running in [shared cache mode], the application must ** guarantee that the shared cache used by the destination database ** is not accessed while the backup is running. In practice this means -** that the application must guarantee that the disk file being +** that the application must guarantee that the disk file being ** backed up to is not accessed by any connection within the process, ** not just the specific connection that was passed to sqlite3_backup_init(). ** -** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** The [sqlite3_backup] object itself is partially threadsafe. Multiple ** threads may safely make multiple concurrent calls to sqlite3_backup_step(). ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** APIs are not strictly speaking threadsafe. If they are invoked at the ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. -** -** Alternatives To Using The Backup API -** -** Other techniques for safely creating a consistent backup of an SQLite -** database include: -** -**
        -**
      • The [VACUUM INTO] command. -**
      • The [sqlite3_rsync] utility program. -**
      */ SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ @@ -9481,49 +7771,49 @@ ** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or ** individual tables within the shared-cache cannot be obtained. See -** [SQLite Shared-Cache Mode] for a description of shared-cache locking. -** ^This API may be used to register a callback that SQLite will invoke +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke ** when the connection currently holding the required lock relinquishes it. ** ^This API is only available if the library was compiled with the ** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. ** ** See Also: [Using the SQLite Unlock Notification Feature]. ** ** ^Shared-cache locks are released when a database connection concludes -** its current transaction, either by committing it or rolling it back. +** its current transaction, either by committing it or rolling it back. ** ** ^When a connection (known as the blocked connection) fails to obtain a ** shared-cache lock and SQLITE_LOCKED is returned to the caller, the ** identity of the database connection (the blocking connection) that -** has locked the required resource is stored internally. ^After an +** has locked the required resource is stored internally. ^After an ** application receives an SQLITE_LOCKED error, it may call the -** sqlite3_unlock_notify() method with the blocked connection handle as +** sqlite3_unlock_notify() method with the blocked connection handle as ** the first argument to register for a callback that will be invoked ** when the blocking connections current transaction is concluded. ^The ** callback is invoked from within the [sqlite3_step] or [sqlite3_close] -** call that concludes the blocking connection's transaction. +** call that concludes the blocking connections transaction. ** ** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, ** there is a chance that the blocking connection will have already ** concluded its transaction by the time sqlite3_unlock_notify() is invoked. ** If this happens, then the specified callback is invoked immediately, ** from within the call to sqlite3_unlock_notify().)^ ** ** ^If the blocked connection is attempting to obtain a write-lock on a ** shared-cache table, and more than one other connection currently holds -** a read-lock on the same table, then SQLite arbitrarily selects one of +** a read-lock on the same table, then SQLite arbitrarily selects one of ** the other connections to use as the blocking connection. ** -** ^(There may be at most one unlock-notify callback registered by a +** ^(There may be at most one unlock-notify callback registered by a ** blocked connection. If sqlite3_unlock_notify() is called when the ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback is canceled. ^The blocked connections ** unlock-notify callback may also be canceled by closing the blocked ** connection using [sqlite3_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes ** any sqlite3_xxx API functions from within an unlock-notify callback, a @@ -9532,29 +7822,29 @@ ** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always ** returns SQLITE_OK. ** ** Callback Invocation Details ** -** When an unlock-notify callback is registered, the application provides a +** When an unlock-notify callback is registered, the application provides a ** single void* pointer that is passed to the callback when it is invoked. ** However, the signature of the callback function allows SQLite to pass ** it an array of void* context pointers. The first argument passed to ** an unlock-notify callback is a pointer to an array of void* pointers, ** and the second is the number of entries in the array. ** -** When a blocking connection's transaction is concluded, there may be +** When a blocking connections transaction is concluded, there may be ** more than one blocked connection that has registered for an unlock-notify ** callback. ^If two or more such blocked connections have specified the ** same callback function, then instead of invoking the callback function ** multiple times, it is invoked once with the set of void* context pointers ** specified by the blocked connections bundled together into an array. -** This gives the application an opportunity to prioritize any actions +** This gives the application an opportunity to prioritize any actions ** related to the set of unblocked database connections. ** ** Deadlock Detection ** -** Assuming that after registering for an unlock-notify callback a +** Assuming that after registering for an unlock-notify callback a ** database waits for the callback to be issued before taking any further ** action (a reasonable assumption), then using this API may cause the ** application to deadlock. For example, if connection X is waiting for ** connection Y's transaction to be concluded, and similarly connection ** Y is waiting on connection X's transaction, then neither connection @@ -9573,11 +7863,11 @@ ** C's transaction, where connection C is waiting on connection A. ^Any ** number of levels of indirection are allowed. ** ** The "DROP TABLE" Exception ** -** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost ** always appropriate to call sqlite3_unlock_notify(). There is however, ** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, ** SQLite checks if there are any currently executing SELECT statements ** that belong to the same connection. If there are, SQLITE_LOCKED is ** returned. In this case there is no "blocking connection", so invoking @@ -9586,11 +7876,11 @@ ** or "DROP INDEX" query, an infinite loop might be the result. ** ** One way around this problem is to check the extended error code returned ** by an sqlite3_step() call. ^(If there is a blocking connection, then the ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in -** the special "DROP TABLE/INDEX" case, the extended error code is just +** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ @@ -9677,12 +7967,12 @@ ** METHOD: sqlite3 ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** is invoked each time data is committed to a database in wal mode. ** -** ^(The callback is invoked by SQLite after the commit has taken place and -** the associated write-lock on the database released)^, so the implementation +** ^(The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released)^, so the implementation ** may read, write or [checkpoint] the database as required. ** ** ^The first parameter passed to the callback function when it is invoked ** is a copy of the third parameter passed to sqlite3_wal_hook() when ** registering the callback. ^The second is a copy of the database handle. @@ -9697,20 +7987,19 @@ ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** -** A single database handle may have at most a single write-ahead log callback +** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any -** previously registered write-ahead log callback. ^The return value is -** a copy of the third parameter from the previous call, if any, or 0. -** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the +** previously registered write-ahead log callback. ^Note that the +** [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( - sqlite3*, + sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* ); /* @@ -9719,11 +8008,11 @@ ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D ** to automatically [checkpoint] ** after committing a transaction if there are N or -** more frames in the [write-ahead log] file. ^Passing zero or +** more frames in the [write-ahead log] file. ^Passing zero or ** a negative value as the nFrame parameter disables automatic ** checkpoints entirely. ** ** ^The callback registered by this function replaces any existing callback ** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback @@ -9749,11 +8038,11 @@ ** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ ** -** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the ** [write-ahead log] for database X on [database connection] D to be ** transferred into the database file and for the write-ahead log to ** be reset. See the [checkpointing] documentation for addition ** information. ** @@ -9775,14 +8064,14 @@ ** information is written back into integers pointed to by L and C.)^ ** ^(The M parameter must be a valid [checkpoint mode]:)^ ** **
      **
      SQLITE_CHECKPOINT_PASSIVE
      -** ^Checkpoint as many frames as possible without waiting for any database -** readers or writers to finish, then sync the database file if all frames +** ^Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish, then sync the database file if all frames ** in the log were checkpointed. ^The [busy-handler callback] -** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. ** ^On the other hand, passive mode might leave the checkpoint unfinished ** if there are concurrent readers or writers. ** **
      SQLITE_CHECKPOINT_FULL
      ** ^This mode blocks (it invokes the @@ -9792,13 +8081,13 @@ ** database file. ^This mode blocks new database writers while it is pending, ** but new database readers are allowed to continue unimpeded. ** **
      SQLITE_CHECKPOINT_RESTART
      ** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition -** that after checkpointing the log file it blocks (calls the +** that after checkpointing the log file it blocks (calls the ** [busy-handler callback]) -** until all readers are reading from the database file only. ^This ensures +** until all readers are reading from the database file only. ^This ensures ** that the next writer will restart the log file from the beginning. ** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new ** database writer attempts while it is pending, but does not impede readers. ** **
      SQLITE_CHECKPOINT_TRUNCATE
      @@ -9816,35 +8105,35 @@ ** because the database is not in WAL mode. ^Note that upon successful ** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been ** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. ** ** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If -** any other process is running a checkpoint operation at the same time, the -** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a ** busy-handler configured, it will not be invoked in this case. ** -** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the ** exclusive "writer" lock on the database file. ^If the writer lock cannot be ** obtained immediately, and a busy-handler is configured, it is invoked and ** the writer lock retried until either the busy-handler returns 0 or the lock ** is successfully obtained. ^The busy-handler is also invoked while waiting for ** database readers as described above. ^If the busy-handler returns 0 before ** the writer lock is obtained or while waiting for database readers, the -** checkpoint operation proceeds from that point in the same way as -** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible ** without blocking any further. ^SQLITE_BUSY is returned in this case. ** ** ^If parameter zDb is NULL or points to a zero length string, then the -** specified operation is attempted on all WAL databases [attached] to +** specified operation is attempted on all WAL databases [attached] to ** [database connection] db. In this case the -** values written to output parameters *pnLog and *pnCkpt are undefined. ^If -** an SQLITE_BUSY error is encountered when processing one or more of the -** attached WAL databases, the operation is still attempted on any remaining -** attached databases and SQLITE_BUSY is returned at the end. ^If any other -** error occurs while processing an attached database, processing is abandoned -** and the error code is returned to the caller immediately. ^If no error -** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned at the end. ^If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code is returned to the caller immediately. ^If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached ** databases, SQLITE_OK is returned. ** ** ^If database zDb is the name of an attached database that is not in WAL ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If ** zDb is not NULL (or a zero length string) and is not the name of any @@ -9875,11 +8164,11 @@ ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the ** meaning of each of these checkpoint modes. */ #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ -#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ #define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ /* ** CAPI3REF: Virtual Table Interface Configuration ** @@ -9888,32 +8177,25 @@ ** various facets of the virtual table interface. ** ** If this interface is invoked outside the context of an xConnect or ** xCreate virtual table method then the behavior is undefined. ** -** In the call sqlite3_vtab_config(D,C,...) the D parameter is the -** [database connection] in which the virtual table is being created and -** which is passed in as the first argument to the [xConnect] or [xCreate] -** method that is invoking sqlite3_vtab_config(). The C parameter is one -** of the [virtual table configuration options]. The presence and meaning -** of parameters after C depend on which [virtual table configuration option] -** is used. +** At present, there is only one option that may be configured using +** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options +** may be added in the future. */ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options -** KEYWORDS: {virtual table configuration options} -** KEYWORDS: {virtual table configuration option} ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** **
      -** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] -**
      SQLITE_VTAB_CONSTRAINT_SUPPORT
      +**
      SQLITE_VTAB_CONSTRAINT_SUPPORT **
      Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if @@ -9923,60 +8205,28 @@ ** ON CONFLICT mode specified. ** ** If X is non-zero, then the virtual table implementation guarantees ** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before ** any modifications to internal or persistent data structures have been made. -** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite ** is able to roll back a statement or database transaction, and abandon -** or continue processing the current SQL statement as appropriate. +** or continue processing the current SQL statement as appropriate. ** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns ** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode ** had been ABORT. ** ** Virtual table implementations that are required to handle OR REPLACE -** must do so within the [xUpdate] method. If a call to the -** [sqlite3_vtab_on_conflict()] function indicates that the current ON -** CONFLICT policy is REPLACE, the virtual table implementation should +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should ** silently replace the appropriate rows within the xUpdate callback and ** return SQLITE_OK. Or, if this is not possible, it may return -** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT ** constraint handling. -**
      -** -** [[SQLITE_VTAB_DIRECTONLY]]
      SQLITE_VTAB_DIRECTONLY
      -**
      Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** prohibits that virtual table from being used from within triggers and -** views. -**
      -** -** [[SQLITE_VTAB_INNOCUOUS]]
      SQLITE_VTAB_INNOCUOUS
      -**
      Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** identify that virtual table as being safe to use from within triggers -** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the -** virtual table can do no serious harm even if it is controlled by a -** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS -** flag unless absolutely necessary. -**
      -** -** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]
      SQLITE_VTAB_USES_ALL_SCHEMAS
      -**
      Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implementation -** instruct the query planner to begin at least a read transaction on -** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the -** virtual table is used. -**
      **
      */ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 -#define SQLITE_VTAB_INNOCUOUS 2 -#define SQLITE_VTAB_DIRECTONLY 3 -#define SQLITE_VTAB_USES_ALL_SCHEMAS 4 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy ** ** This function may only be called from within a call to the [xUpdate] method @@ -9986,328 +8236,10 @@ ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ 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 might return true if the -** column is being fetched as part of an UPDATE operation during which the -** column value will not change. The virtual table implementation can use -** this hint as permission to substitute a return value that is less -** expensive to compute and that the corresponding -** [xUpdate] method understands as a "no-change" value. -** -** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that -** the column is not changed by the UPDATE statement, then 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. -** -** The sqlite3_vtab_nochange() routine is an optimization. Virtual table -** implementations should continue to give a correct answer even if the -** sqlite3_vtab_nochange() interface were to always return false. In the -** current implementation, the sqlite3_vtab_nochange() interface does always -** returns false for the enhanced [UPDATE FROM] statement. -*/ -SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); - -/* -** CAPI3REF: Determine The Collation For a Virtual Table Constraint -** METHOD: sqlite3_index_info -** -** This function may only be called from within a call to the [xBestIndex] -** method of a [virtual table]. This function returns a pointer to a string -** that is the name of the appropriate collation sequence to use for text -** comparisons on the constraint identified by its arguments. -** -** The first argument must be the pointer to the [sqlite3_index_info] object -** that is the first parameter to the xBestIndex() method. The second argument -** must be an index into the aConstraint[] array belonging to the -** sqlite3_index_info structure passed to xBestIndex. -** -** Important: -** The first parameter must be the same pointer that is passed into the -** xBestMethod() method. The first parameter may not be a pointer to a -** different [sqlite3_index_info] object, even an exact copy. -** -** The return value is computed as follows: -** -**
        -**
      1. If the constraint comes from a WHERE clause expression that contains -** a [COLLATE operator], then the name of the collation specified by -** that COLLATE operator is returned. -**

      2. If there is no COLLATE operator, but the column that is the subject -** of the constraint specifies an alternative collating sequence via -** a [COLLATE clause] on the column definition within the CREATE TABLE -** statement that was passed into [sqlite3_declare_vtab()], then the -** name of that alternative collating sequence is returned. -**

      3. Otherwise, "BINARY" is returned. -**

      -*/ -SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); - -/* -** CAPI3REF: Determine if a virtual table query is DISTINCT -** METHOD: sqlite3_index_info -** -** This API may only be used from within an [xBestIndex|xBestIndex method] -** of a [virtual table] implementation. The result of calling this -** interface from outside of xBestIndex() is undefined and probably harmful. -** -** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and -** 3. The integer returned by sqlite3_vtab_distinct() -** gives the virtual table additional information about how the query -** planner wants the output to be ordered. As long as the virtual table -** can meet the ordering requirements of the query planner, it may set -** the "orderByConsumed" flag. -** -**
      1. -** ^If the sqlite3_vtab_distinct() interface returns 0, that means -** that the query planner needs the virtual table to return all rows in the -** sort order defined by the "nOrderBy" and "aOrderBy" fields of the -** [sqlite3_index_info] object. This is the default expectation. If the -** virtual table outputs all rows in sorted order, then it is always safe for -** the xBestIndex method to set the "orderByConsumed" flag, regardless of -** the return value from sqlite3_vtab_distinct(). -**

      2. -** ^(If the sqlite3_vtab_distinct() interface returns 1, that means -** that the query planner does not need the rows to be returned in sorted order -** as long as all rows with the same values in all columns identified by the -** "aOrderBy" field are adjacent.)^ This mode is used when the query planner -** is doing a GROUP BY. -**

      3. -** ^(If the sqlite3_vtab_distinct() interface returns 2, that means -** that the query planner does not need the rows returned in any particular -** order, as long as rows with the same values in all columns identified -** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows -** contain the same values for all columns identified by "colUsed", all but -** one such row may optionally be omitted from the result.)^ -** The virtual table is not required to omit rows that are duplicates -** over the "colUsed" columns, but if the virtual table can do that without -** too much extra effort, it could potentially help the query to run faster. -** This mode is used for a DISTINCT query. -**

      4. -** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the -** virtual table must return rows in the order defined by "aOrderBy" as -** if the sqlite3_vtab_distinct() interface had returned 0. However if -** two or more rows in the result have the same values for all columns -** identified by "colUsed", then all but one such row may optionally be -** omitted.)^ Like when the return value is 2, the virtual table -** is not required to omit rows that are duplicates over the "colUsed" -** columns, but if the virtual table can do that without -** too much extra effort, it could potentially help the query to run faster. -** This mode is used for queries -** that have both DISTINCT and ORDER BY clauses. -**

      -** -**

      The following table summarizes the conditions under which the -** virtual table is allowed to set the "orderByConsumed" flag based on -** the value returned by sqlite3_vtab_distinct(). This table is a -** restatement of the previous four paragraphs: -** -** -** -**
      sqlite3_vtab_distinct() return value -** Rows are returned in aOrderBy order -** Rows with the same value in all aOrderBy columns are adjacent -** Duplicates over all colUsed columns may be omitted -**
      0yesyesno -**
      1noyesno -**
      2noyesyes -**
      3yesyesyes -**
      -** -** ^For the purposes of comparing virtual table output values to see if the -** values are same value for sorting purposes, two NULL values are considered -** to be the same. In other words, the comparison operator is "IS" -** (or "IS NOT DISTINCT FROM") and not "==". -** -** If a virtual table implementation is unable to meet the requirements -** specified above, then it must not set the "orderByConsumed" flag in the -** [sqlite3_index_info] object or an incorrect answer may result. -** -** ^A virtual table implementation is always free to return rows in any order -** it wants, as long as the "orderByConsumed" flag is not set. ^When the -** the "orderByConsumed" flag is unset, the query planner will add extra -** [bytecode] to ensure that the final results returned by the SQL query are -** ordered correctly. The use of the "orderByConsumed" flag and the -** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful -** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" -** flag might help queries against a virtual table to run faster. Being -** overly aggressive and setting the "orderByConsumed" flag when it is not -** valid to do so, on the other hand, might cause SQLite to return incorrect -** results. -*/ -SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); - -/* -** CAPI3REF: Identify and handle IN constraints in xBestIndex -** -** This interface may only be used from within an -** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. -** The result of invoking this interface from any other context is -** undefined and probably harmful. -** -** ^(A constraint on a virtual table of the form -** "[IN operator|column IN (...)]" is -** communicated to the xBestIndex method as a -** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use -** this constraint, it must set the corresponding -** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under -** the usual mode of handling IN operators, SQLite generates [bytecode] -** that invokes the [xFilter|xFilter() method] once for each value -** on the right-hand side of the IN operator.)^ Thus the virtual table -** only sees a single value from the right-hand side of the IN operator -** at a time. -** -** In some cases, however, it would be advantageous for the virtual -** table to see all values on the right-hand of the IN operator all at -** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: -** -**

        -**
      1. -** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) -** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint -** is an [IN operator] that can be processed all at once. ^In other words, -** sqlite3_vtab_in() with -1 in the third argument is a mechanism -** by which the virtual table can ask SQLite if all-at-once processing -** of the IN operator is even possible. -** -**

      2. -** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates -** to SQLite that the virtual table does or does not want to process -** the IN operator all-at-once, respectively. ^Thus when the third -** parameter (F) is non-negative, this interface is the mechanism by -** which the virtual table tells SQLite how it wants to process the -** IN operator. -**

      -** -** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times -** within the same xBestIndex method call. ^For any given P,N pair, -** the return value from sqlite3_vtab_in(P,N,F) will always be the same -** within the same xBestIndex call. ^If the interface returns true -** (non-zero), that means that the constraint is an IN operator -** that can be processed all-at-once. ^If the constraint is not an IN -** operator or cannot be processed all-at-once, then the interface returns -** false. -** -** ^(All-at-once processing of the IN operator is selected if both of the -** following conditions are met: -** -**
        -**
      1. The P->aConstraintUsage[N].argvIndex value is set to a positive -** integer. This is how the virtual table tells SQLite that it wants to -** use the N-th constraint. -** -**

      2. The last call to sqlite3_vtab_in(P,N,F) for which F was -** non-negative had F>=1. -**

      )^ -** -** ^If either or both of the conditions above are false, then SQLite uses -** the traditional one-at-a-time processing strategy for the IN constraint. -** ^If both conditions are true, then the argvIndex-th parameter to the -** xFilter method will be an [sqlite3_value] that appears to be NULL, -** but which can be passed to [sqlite3_vtab_in_first()] and -** [sqlite3_vtab_in_next()] to find all values on the right-hand side -** of the IN constraint. -*/ -SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); - -/* -** CAPI3REF: Find all elements on the right-hand side of an IN constraint. -** -** These interfaces are only useful from within the -** [xFilter|xFilter() method] of a [virtual table] implementation. -** The result of invoking these interfaces from any other context -** is undefined and probably harmful. -** -** The X parameter in a call to sqlite3_vtab_in_first(X,P) or -** sqlite3_vtab_in_next(X,P) should be one of the parameters to the -** xFilter method which invokes these routines, and specifically -** a parameter that was previously selected for all-at-once IN constraint -** processing use the [sqlite3_vtab_in()] interface in the -** [xBestIndex|xBestIndex method]. ^(If the X parameter is not -** an xFilter argument that was selected for all-at-once IN constraint -** processing, then these routines return [SQLITE_ERROR].)^ -** -** ^(Use these routines to access all values on the right-hand side -** of the IN constraint using code like the following: -** -**
      -**    for(rc=sqlite3_vtab_in_first(pList, &pVal);
      -**        rc==SQLITE_OK && pVal;
      -**        rc=sqlite3_vtab_in_next(pList, &pVal)
      -**    ){
      -**      // do something with pVal
      -**    }
      -**    if( rc!=SQLITE_OK ){
      -**      // an error has occurred
      -**    }
      -** 
      )^ -** -** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) -** routines return SQLITE_OK and set *P to point to the first or next value -** on the RHS of the IN constraint. ^If there are no more values on the -** right hand side of the IN constraint, then *P is set to NULL and these -** routines return [SQLITE_DONE]. ^The return value might be -** some other value, such as SQLITE_NOMEM, in the event of a malfunction. -** -** The *ppOut values returned by these routines are only valid until the -** next call to either of these routines or until the end of the xFilter -** method from which these routines were called. If the virtual table -** implementation needs to retain the *ppOut values for longer, it must make -** copies. The *ppOut values are [protected sqlite3_value|protected]. -*/ -SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); -SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); - -/* -** CAPI3REF: Constraint values in xBestIndex() -** METHOD: sqlite3_index_info -** -** This API may only be used from within the [xBestIndex|xBestIndex method] -** of a [virtual table] implementation. The result of calling this interface -** from outside of an xBestIndex method are undefined and probably harmful. -** -** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within -** the [xBestIndex] method of a [virtual table] implementation, with P being -** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and -** J being a 0-based index into P->aConstraint[], then this routine -** attempts to set *V to the value of the right-hand operand of -** that constraint if the right-hand operand is known. ^If the -** right-hand operand is not known, then *V is set to a NULL pointer. -** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if -** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) -** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th -** constraint is not available. ^The sqlite3_vtab_rhs_value() interface -** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if -** something goes wrong. -** -** The sqlite3_vtab_rhs_value() interface is usually only successful if -** the right-hand operand of a constraint is a literal value in the original -** SQL statement. If the right-hand operand is an expression or a reference -** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() -** will probably return [SQLITE_NOTFOUND]. -** -** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and -** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such -** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ -** -** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value -** and remains valid for the duration of the xBestIndex method call. -** ^When xBestIndex returns, the sqlite3_value object returned by -** sqlite3_vtab_rhs_value() is automatically deallocated. -** -** The "_rhs_" in the name of this routine is an abbreviation for -** "Right-Hand Side". -*/ -SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); - /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} ** ** These constants are returned by [sqlite3_vtab_on_conflict()] to @@ -10334,75 +8266,57 @@ ** ** When the value returned to V is a string, space to hold that string is ** managed by the prepared statement S and will be automatically freed when ** S is finalized. ** -** Not all values are available for all query elements. When a value is -** not available, the output variable is set to -1 if the value is numeric, -** or to NULL if it is a string (SQLITE_SCANSTAT_NAME). -** **
      ** [[SQLITE_SCANSTAT_NLOOP]]
      SQLITE_SCANSTAT_NLOOP
      -**
      ^The [sqlite3_int64] variable pointed to by the V parameter will be +**
      ^The [sqlite3_int64] variable pointed to by the T parameter will be ** set to the total number of times that the X-th loop has run.
      ** ** [[SQLITE_SCANSTAT_NVISIT]]
      SQLITE_SCANSTAT_NVISIT
      -**
      ^The [sqlite3_int64] variable pointed to by the V parameter will be set +**
      ^The [sqlite3_int64] variable pointed to by the T parameter will be set ** to the total number of rows examined by all iterations of the X-th loop.
      ** ** [[SQLITE_SCANSTAT_EST]]
      SQLITE_SCANSTAT_EST
      -**
      ^The "double" variable pointed to by the V parameter will be set to the +**
      ^The "double" variable pointed to by the T parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]]
      SQLITE_SCANSTAT_NAME
      -**
      ^The "const char *" variable pointed to by the V parameter will be set +**
      ^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the name of the index or table ** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]]
      SQLITE_SCANSTAT_EXPLAIN
      -**
      ^The "const char *" variable pointed to by the V parameter will be set +**
      ^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. ** -** [[SQLITE_SCANSTAT_SELECTID]]
      SQLITE_SCANSTAT_SELECTID
      -**
      ^The "int" variable pointed to by the V parameter will be set to the -** id for the X-th query plan element. The id value is unique within the -** statement. The select-id is the same value as is output in the first -** column of an [EXPLAIN QUERY PLAN] query. -** -** [[SQLITE_SCANSTAT_PARENTID]]
      SQLITE_SCANSTAT_PARENTID
      -**
      The "int" variable pointed to by the V parameter will be set to the -** the id of the parent of the current query element, if applicable, or -** to zero if the query element has no parent. This is the same value as -** returned in the second column of an [EXPLAIN QUERY PLAN] query. -** -** [[SQLITE_SCANSTAT_NCYCLE]]
      SQLITE_SCANSTAT_NCYCLE
      -**
      The sqlite3_int64 output value is set to the number of cycles, -** according to the processor time-stamp counter, that elapsed while the -** query element was being processed. This value is not available for -** all query elements - if it is unavailable the output variable is -** set to -1. +** [[SQLITE_SCANSTAT_SELECTID]]
      SQLITE_SCANSTAT_SELECT
      +**
      ^The "int" variable pointed to by the T parameter will be set to the +** "select-id" for the X-th loop. The select-id identifies which query or +** subquery the loop is part of. The main query has a select-id of zero. +** The select-id is the same value as is output in the first column +** of an [EXPLAIN QUERY PLAN] query. **
      */ #define SQLITE_SCANSTAT_NLOOP 0 #define SQLITE_SCANSTAT_NVISIT 1 #define SQLITE_SCANSTAT_EST 2 #define SQLITE_SCANSTAT_NAME 3 #define SQLITE_SCANSTAT_EXPLAIN 4 #define SQLITE_SCANSTAT_SELECTID 5 -#define SQLITE_SCANSTAT_PARENTID 6 -#define SQLITE_SCANSTAT_NCYCLE 7 /* ** CAPI3REF: Prepared Statement Scan Status ** METHOD: sqlite3_stmt ** -** These interfaces return information about the predicted and measured +** This interface returns information about the predicted and measured ** performance for pStmt. Advanced applications can use this ** interface to compare the predicted and the measured performance and ** issue warnings and/or rerun [ANALYZE] if discrepancies are found. ** ** Since this interface is expected to be rarely used, it is only @@ -10409,51 +8323,32 @@ ** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS] ** compile-time option. ** ** The "iScanStatusOp" parameter determines which status information to return. ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior -** of this interface is undefined. ^The requested measurement is written into -** a variable pointed to by the "pOut" parameter. -** -** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX -** is specified, then status information is available for all elements -** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If -** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements -** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of -** the EXPLAIN QUERY PLAN output) are available. Invoking API -** sqlite3_stmt_scanstatus() is equivalent to calling -** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter. -** -** Parameter "idx" identifies the specific query element to retrieve statistics -** for. Query elements are numbered starting from zero. A value of -1 may be -** to query for statistics regarding the entire query. ^If idx is out of range -** - less than -1 or greater than or equal to the total number of query -** elements used to implement the statement - a non-zero value is returned and -** the variable that pOut points to is unchanged. +** of this interface is undefined. +** ^The requested measurement is written into a variable pointed to by +** the "pOut" parameter. +** Parameter "idx" identifies the specific loop to retrieve statistics for. +** Loops are numbered starting from zero. ^If idx is out of range - less than +** zero or greater than or equal to the total number of loops used to implement +** the statement - a non-zero value is returned and the variable that pOut +** points to is unchanged. +** +** ^Statistics might not be available for all loops in all statements. ^In cases +** where there exist loops with no available statistics, this function behaves +** as if the loop did not exist - it returns non-zero and leave the variable +** that pOut points to unchanged. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ -); -SQLITE_API int sqlite3_stmt_scanstatus_v2( - sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ - int flags, /* Mask of flags defined below */ - void *pOut /* Result written here */ -); - -/* -** CAPI3REF: Prepared Statement Scan Status -** KEYWORDS: {scan status flags} -*/ -#define SQLITE_SCANSTAT_COMPLEX 0x0001 +); /* ** CAPI3REF: Zero Scan-Status Counters ** METHOD: sqlite3_stmt ** @@ -10464,23 +8359,22 @@ */ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction -** METHOD: sqlite3 ** ** ^If a write-transaction is open on [database connection] D when the ** [sqlite3_db_cacheflush(D)] interface invoked, any dirty -** pages in the pager-cache that are not currently in use are written out +** pages in the pager-cache that are not currently in use are written out ** to disk. A dirty page may be in use if a database cursor created by an ** active SQL statement is reading from it, or if it is page 1 of a database ** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)] ** interface flushes caches for all schemas - "main", "temp", and ** any [attached] databases. ** -** ^If this function needs to obtain extra database locks before dirty pages -** can be flushed to disk, it does so. ^If those locks cannot be obtained +** ^If this function needs to obtain extra database locks before dirty pages +** can be flushed to disk, it does so. ^If those locks cannot be obtained ** immediately and there is a busy-handler callback configured, it is invoked ** in the usual manner. ^If the required lock still cannot be obtained, then ** the database is skipped and an attempt made to flush any dirty pages ** belonging to the next (if any) database. ^If any databases are skipped ** because locks cannot be obtained, but no other error occurs, this @@ -10497,11 +8391,10 @@ */ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); /* ** CAPI3REF: The pre-update hook. -** METHOD: sqlite3 ** ** ^These interfaces are only available if SQLite is compiled using the ** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. ** ** ^The [sqlite3_preupdate_hook()] interface registers a callback function @@ -10515,38 +8408,34 @@ ** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as ** the first parameter to callbacks. ** ** ^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_sequence or sqlite_stat1. +** 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. ** ^The third parameter to the preupdate callback is one of the constants ** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the ** kind of update operation that is about to occur. ** ^(The fourth parameter to the preupdate callback is the name of the ** database within the database connection that is being modified. This -** will be "main" for the main database or "temp" for TEMP tables or +** will be "main" for the main database or "temp" for TEMP tables or ** the name given after the AS keyword in the [ATTACH] statement for attached ** databases.)^ ** ^The fifth parameter to the preupdate callback is the name of the ** table that is being modified. ** ** For an UPDATE or DELETE operation on a [rowid table], the sixth -** parameter passed to the preupdate callback is the initial [rowid] of the +** parameter passed to the preupdate callback is the initial [rowid] of the ** row being modified or deleted. For an INSERT operation on a rowid table, -** or any operation on a WITHOUT ROWID table, the value of the sixth +** or any operation on a WITHOUT ROWID table, the value of the sixth ** parameter is undefined. For an INSERT or UPDATE on a rowid table the ** seventh parameter is the final rowid value of the row being inserted ** or updated. The value of the seventh parameter passed to the callback ** function is not defined for operations on WITHOUT ROWID tables, or for -** DELETE operations on rowid tables. -** -** ^The sqlite3_preupdate_hook(D,C,P) function returns the P argument from -** the previous call on the same [database connection] D, or NULL for -** the first call on D. +** INSERT operations on rowid tables. ** ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces ** provide additional information about a preupdate event. These routines ** may only be called from within a preupdate callback. Invoking any of @@ -10576,23 +8465,14 @@ ** behavior is undefined. The [sqlite3_value] that P points to ** will be destroyed when the preupdate callback returns. ** ** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate ** callback was invoked as a result of a direct insert, update, or delete -** operation; or 1 for inserts, updates, or deletes invoked by top-level +** operation; or 1 for inserts, updates, or deletes invoked by top-level ** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; and so forth. ** -** When the [sqlite3_blob_write()] API is used to update a blob column, -** the pre-update hook is invoked with SQLITE_DELETE. This is because the -** in this case the new values are not available. In this case, when a -** callback made with op==SQLITE_DELETE is actually a write using the -** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns -** the index of the column being written. In other cases, where the -** pre-update hook is being invoked for some other reason, including a -** regular DELETE, sqlite3_preupdate_blobwrite() returns -1. -** ** See also: [sqlite3_update_hook()] */ #if defined(SQLITE_ENABLE_PREUPDATE_HOOK) SQLITE_API void *sqlite3_preupdate_hook( sqlite3 *db, @@ -10609,29 +8489,28 @@ ); SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); SQLITE_API int sqlite3_preupdate_count(sqlite3 *); SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); -SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *); #endif /* ** CAPI3REF: Low-level system error code -** METHOD: sqlite3 ** ** ^Attempt to return the underlying operating system error code or error ** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be ** called to get back the underlying "errno" that caused the problem, such -** as ENOSPC, EAUTH, EISDIR, and so forth. +** as ENOSPC, EAUTH, EISDIR, and so forth. */ SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot ** KEYWORDS: {snapshot} {sqlite3_snapshot} +** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] ** database for some specific point in history. ** ** In [WAL mode], multiple [database connections] that are open on the @@ -10644,356 +8523,181 @@ ** ** The sqlite3_snapshot object records state information about an historical ** version of the database file so that it is possible to later open a new read ** transaction that sees that historical version of the database rather than ** the most recent version. +** +** The constructor for this object is [sqlite3_snapshot_get()]. The +** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer +** to an historical snapshot (if possible). The destructor for +** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ typedef struct sqlite3_snapshot { unsigned char hidden[48]; } sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot -** CONSTRUCTOR: sqlite3_snapshot +** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a ** new [sqlite3_snapshot] object that records the current state of ** 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 there is not already a read-transaction open on schema S when -** this function is called, one is opened automatically. -** -** If a read-transaction is opened by this function, then it is guaranteed -** that the returned snapshot object may not be invalidated by a database -** writer or checkpointer until after the read-transaction is closed. This -** is not guaranteed if a read-transaction is already open when this -** function is called. In that case, any subsequent write or checkpoint -** operation on the database may invalidate the returned snapshot handle, -** even while the read-transaction remains open. +** this function is called, one is opened automatically. ** ** The following must be true for this function to succeed. If any of ** the following statements are false when sqlite3_snapshot_get() is ** called, SQLITE_ERROR is returned. The final value of *P is undefined -** in this case. +** in this case. ** **
        -**
      • The database handle must not be in [autocommit mode]. +**
      • 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 +** that a snapshot cannot be taken on a wal mode database with no wal ** file immediately after it is first opened. At least one transaction ** must be written to it first. **
      ** ** This function may also return SQLITE_NOMEM. If it is called with the -** database handle in autocommit mode but fails for some other reason, +** database handle in autocommit mode but fails for some other reason, ** whether or not a read transaction is opened on schema S is undefined. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** ** The [sqlite3_snapshot_get()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot ); /* ** CAPI3REF: Start a read transaction on an historical snapshot -** METHOD: sqlite3_snapshot -** -** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read -** transaction or upgrades an existing one for schema S of -** [database connection] D such that the read transaction refers to -** historical [snapshot] P, rather than the most recent change to the -** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK -** on success or an appropriate [error code] if it fails. -** -** ^In order to succeed, the database connection must not be in -** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there -** is already a read transaction open on schema S, then the database handle -** must have no active statements (SELECT statements that have been passed -** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). -** SQLITE_ERROR is returned if either of these conditions is violated, or -** if schema S does not exist, or if the snapshot object is invalid. -** -** ^A call to sqlite3_snapshot_open() will fail to open if the specified -** snapshot has been overwritten by a [checkpoint]. In this case -** SQLITE_ERROR_SNAPSHOT is returned. -** -** If there is already a read transaction open when this function is -** invoked, then the same read transaction remains open (on the same -** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT -** is returned. If another error code - for example SQLITE_PROTOCOL or an -** SQLITE_IOERR error code - is returned, then the final state of the -** read transaction is undefined. If SQLITE_OK is returned, then the -** read transaction is now open on database snapshot P. -** +** EXPERIMENTAL +** +** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +** read transaction for schema S of +** [database connection] D such that the read transaction +** refers to historical [snapshot] P, rather than the most +** recent change to the database. +** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success +** or an appropriate [error code] if it fails. +** +** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be +** the first operation following the [BEGIN] that takes the schema S +** out of [autocommit mode]. +** ^In other words, schema S must not currently be in +** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +** database connection D must be out of [autocommit mode]. +** ^A [snapshot] will fail to open if it has been overwritten by a +** [checkpoint]. ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the ** database connection D does not know that the database file for ** schema S is in [WAL mode]. A database connection might not know ** that the database file is in [WAL mode] if there has been no prior -** I/O on that database connection, or if the database entered [WAL mode] +** I/O on that database connection, or if the database entered [WAL mode] ** after the most recent I/O on the database connection.)^ ** (Hint: Run "[PRAGMA application_id]" against a newly opened ** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot ); /* ** CAPI3REF: Destroy a snapshot -** DESTRUCTOR: sqlite3_snapshot +** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. ** The application must eventually free every [sqlite3_snapshot] object ** using this routine to avoid a memory leak. ** ** The [sqlite3_snapshot_free()] interface is only available when the -** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. -** METHOD: sqlite3_snapshot +** EXPERIMENTAL ** ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages -** of two valid snapshot handles. +** of two valid snapshot handles. ** -** If the two snapshot handles are not associated with the same database -** file, the result of the comparison is undefined. +** If the two snapshot handles are not associated with the same database +** file, the result of the comparison is undefined. ** ** Additionally, the result of the comparison is only valid if both of the ** snapshot handles were obtained by calling sqlite3_snapshot_get() since the ** last time the wal file was deleted. The wal file is deleted when the ** database is changed back to rollback mode or when the number of database -** clients drops to zero. If either snapshot handle was obtained before the -** wal file was last deleted, the value returned by this function +** clients drops to zero. If either snapshot handle was obtained before the +** wal file was last deleted, the value returned by this function ** is undefined. ** ** Otherwise, this API returns a negative value if P1 refers to an older ** snapshot than P2, zero if the two handles refer to the same database ** snapshot, and a positive value if P1 is a newer snapshot than P2. -** -** This interface is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); /* ** CAPI3REF: Recover snapshots from a wal file -** METHOD: sqlite3_snapshot -** -** If a [WAL file] remains on disk after all database connections close -** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] -** or because the last process to have the database opened exited without -** calling [sqlite3_close()]) and a new connection is subsequently opened -** on that database and [WAL file], the [sqlite3_snapshot_open()] interface -** will only be able to open the last transaction added to the WAL file -** even though the WAL file contains other valid transactions. -** -** This function attempts to scan the WAL file associated with database zDb +** 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 +** 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. -** -** This interface is only available if SQLite is compiled with the -** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); -/* -** CAPI3REF: Serialize a database -** -** The sqlite3_serialize(D,S,P,F) interface returns a pointer to -** memory that is a serialization of the S database on -** [database connection] D. If S is a NULL pointer, the main database is used. -** If P is not a NULL pointer, then the size of the database in bytes -** is written into *P. -** -** For an ordinary on-disk database file, the serialization is just a -** copy of the disk file. For an in-memory database or a "TEMP" database, -** the serialization is the same sequence of bytes which would be written -** to disk if that database where backed up to disk. -** -** The usual case is that sqlite3_serialize() copies the serialization of -** the database into memory obtained from [sqlite3_malloc64()] and returns -** a pointer to that memory. The caller is responsible for freeing the -** returned value to avoid a memory leak. However, if the F argument -** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations -** are made, and the sqlite3_serialize() function will return a pointer -** to the contiguous memory representation of the database that SQLite -** is currently using for that database, or NULL if the no such contiguous -** memory representation of the database exists. A contiguous memory -** representation of the database will usually only exist if there has -** been a prior call to [sqlite3_deserialize(D,S,...)] with the same -** values of D and S. -** The size of the database is written into *P even if the -** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy -** of the database exists. -** -** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set, -** the returned buffer content will remain accessible and unchanged -** until either the next write operation on the connection or when -** the connection is closed, and applications must not modify the -** buffer. If the bit had been clear, the returned buffer will not -** be accessed by SQLite after the call. -** -** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the -** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory -** allocation error occurs. -** -** This interface is omitted if SQLite is compiled with the -** [SQLITE_OMIT_DESERIALIZE] option. -*/ -SQLITE_API unsigned char *sqlite3_serialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ - sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ - unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3_serialize -** -** Zero or more of the following constants can be OR-ed together for -** the F argument to [sqlite3_serialize(D,S,P,F)]. -** -** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return -** a pointer to contiguous in-memory database that it is currently using, -** without making a copy of the database. If SQLite is not currently using -** a contiguous in-memory database, then this option causes -** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be -** using a contiguous in-memory database if it has been initialized by a -** prior call to [sqlite3_deserialize()]. -*/ -#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ - -/* -** CAPI3REF: Deserialize a database -** -** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the -** [database connection] D to disconnect from database S and then -** reopen S as an in-memory database based on the serialization contained -** in P. The serialized database P is N bytes in size. M is the size of -** the buffer P, which might be larger than N. If M is larger than N, and -** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is -** permitted to add content to the in-memory database as long as the total -** size does not exceed M bytes. -** -** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will -** invoke sqlite3_free() on the serialization buffer when the database -** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then -** SQLite will try to increase the buffer size using sqlite3_realloc64() -** if writes on the database cause it to grow larger than M bytes. -** -** Applications must not modify the buffer P or invalidate it before -** the database connection D is closed. -** -** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the -** database is currently in a read transaction or is involved in a backup -** operation. -** -** It is not possible to deserialized into the TEMP database. If the -** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the -** function returns SQLITE_ERROR. -** -** The deserialized database should not be in [WAL mode]. If the database -** is in WAL mode, then any attempt to use the database file will result -** in an [SQLITE_CANTOPEN] error. The application can set the -** [file format version numbers] (bytes 18 and 19) of the input database P -** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the -** database file into rollback mode and work around this limitation. -** -** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the -** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then -** [sqlite3_free()] is invoked on argument P prior to returning. -** -** This interface is omitted if SQLite is compiled with the -** [SQLITE_OMIT_DESERIALIZE] option. -*/ -SQLITE_API int sqlite3_deserialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to reopen with the deserialization */ - unsigned char *pData, /* The serialized database content */ - sqlite3_int64 szDb, /* Number bytes in the deserialization */ - sqlite3_int64 szBuf, /* Total size of buffer pData[] */ - unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3_deserialize() -** -** The following are allowed values for 6th argument (the F argument) to -** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. -** -** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization -** in the P argument is held in memory obtained from [sqlite3_malloc64()] -** and that SQLite should take ownership of this memory and automatically -** free it when it has finished using it. Without this flag, the caller -** is responsible for freeing any dynamically allocated memory. -** -** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to -** grow the size of the database using calls to [sqlite3_realloc64()]. This -** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. -** Without this flag, the deserialized database cannot increase in size beyond -** the number of bytes specified by the M parameter. -** -** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database -** should be treated as read-only. -*/ -#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ -#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ -#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ - /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif -#if defined(__wasi__) -# undef SQLITE_WASI -# define SQLITE_WASI 1 -# ifndef SQLITE_OMIT_LOAD_EXTENSION -# define SQLITE_OMIT_LOAD_EXTENSION -# endif -# ifndef SQLITE_THREADSAFE -# define SQLITE_THREADSAFE 0 -# endif -#endif - #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif -/* #endif for SQLITE3_H will be added by mksqlite3.tcl */ +#endif /* SQLITE3_H */ /******** Begin file sqlite3rtree.h *********/ /* ** 2010 August 30 ** @@ -11052,11 +8756,11 @@ void *pUser; /* Callback implementation user data */ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ }; /* -** Register a 2nd-generation geometry callback named zScore that can be +** Register a 2nd-generation geometry callback named zScore that can be ** used as part of an R-Tree geometry query as follows: ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ SQLITE_API int sqlite3_rtree_query_callback( @@ -11067,11 +8771,11 @@ void (*xDestructor)(void*) ); /* -** A pointer to a structure of the following type is passed as the +** A pointer to a structure of the following type is passed as the ** argument to scored geometry callback registered using ** sqlite3_rtree_query_callback(). ** ** Note that the first 5 fields of this structure are identical to ** sqlite3_rtree_geometry. This structure is a subclass of @@ -11089,11 +8793,11 @@ int iLevel; /* Level of current node or entry */ int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visibility */ + int eWithin; /* OUT: Visiblity */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ }; @@ -11125,27 +8829,20 @@ #endif /* ** CAPI3REF: Session Object Handle -** -** An instance of this object is a [session] that can be used to -** record changes to a database. */ typedef struct sqlite3_session sqlite3_session; /* ** CAPI3REF: Changeset Iterator Handle -** -** An instance of this object acts as a cursor for iterating -** over the elements of a [changeset] or [patchset]. */ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* ** CAPI3REF: Create A New Session Object -** CONSTRUCTOR: sqlite3_session ** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is ** returned. If an error occurs, *ppSession is set to NULL and an SQLite ** error code (e.g. SQLITE_NOMEM) is returned. @@ -11162,11 +8859,11 @@ ** ** Because the session module uses the [sqlite3_preupdate_hook()] API, it ** is not possible for an application to register a pre-update hook on a ** database handle that has one or more session objects attached. Nor is ** it possible to create a session object attached to a database handle for -** which a pre-update hook is already defined. The results of attempting +** which a pre-update hook is already defined. The results of attempting ** either of these things are undefined. ** ** The session object will be used to create changesets for tables in ** database zDb, where zDb is either "main", or "temp", or the name of an ** attached database. It is not an error if database zDb is not attached @@ -11178,100 +8875,52 @@ sqlite3_session **ppSession /* OUT: New session object */ ); /* ** CAPI3REF: Delete A Session Object -** DESTRUCTOR: sqlite3_session ** -** Delete a session object previously allocated using +** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the ** results of attempting to use pSession with any other session module ** function are undefined. ** ** Session objects must be deleted before the database handle to which they -** are attached is closed. Refer to the documentation for +** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); -/* -** CAPI3REF: Configure a Session Object -** METHOD: sqlite3_session -** -** This method is used to configure a session object after it has been -** created. At present the only valid values for the second parameter are -** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. -** -*/ -SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); - -/* -** CAPI3REF: Options for sqlite3session_object_config -** -** The following values may passed as the the 2nd parameter to -** sqlite3session_object_config(). -** -**
      SQLITE_SESSION_OBJCONFIG_SIZE
      -** This option is used to set, clear or query the flag that enables -** the [sqlite3session_changeset_size()] API. Because it imposes some -** computational overhead, this API is disabled by default. Argument -** pArg must point to a value of type (int). If the value is initially -** 0, then the sqlite3session_changeset_size() API is disabled. If it -** is greater than 0, then the same API is enabled. Or, if the initial -** value is less than zero, no change is made. In all cases the (int) -** variable is set to 1 if the sqlite3session_changeset_size() API is -** enabled following the current call, or 0 otherwise. -** -** It is an error (SQLITE_MISUSE) to attempt to modify this setting after -** the first table has been attached to the session object. -** -**
      SQLITE_SESSION_OBJCONFIG_ROWID
      -** This option is used to set, clear or query the flag that enables -** collection of data for tables with no explicit PRIMARY KEY. -** -** Normally, tables with no explicit PRIMARY KEY are simply ignored -** by the sessions module. However, if this flag is set, it behaves -** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted -** as their leftmost columns. -** -** It is an error (SQLITE_MISUSE) to attempt to modify this setting after -** the first table has been attached to the session object. -*/ -#define SQLITE_SESSION_OBJCONFIG_SIZE 1 -#define SQLITE_SESSION_OBJCONFIG_ROWID 2 /* ** CAPI3REF: Enable Or Disable A Session Object -** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When ** disabled - it does not. A newly created session object is enabled. ** Refer to the documentation for [sqlite3session_changeset()] for further ** details regarding how enabling and disabling a session object affects ** the eventual changesets. ** ** Passing zero to this function disables the session. Passing a value -** greater than zero enables it. Passing a value less than zero is a +** greater than zero enables it. Passing a value less than zero is a ** no-op, and may be used to query the current state of the session. ** -** The return value indicates the final state of the session object: 0 if +** The return value indicates the final state of the session object: 0 if ** the session is disabled, or 1 if it is enabled. */ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag -** METHOD: sqlite3_session ** ** Each change recorded by a session object is marked as either direct or ** indirect. A change is marked as indirect if either: ** **
        **
      • The session object "indirect" flag is set when the change is ** made, or -**
      • The change is made by an SQL trigger or foreign key action +**
      • The change is made by an SQL trigger or foreign key action ** instead of directly as a result of a users SQL statement. **
      ** ** If a single row is affected by more than one operation within a session, ** then the change is considered indirect if all operations meet the criteria @@ -11279,89 +8928,58 @@ ** ** This function is used to set, clear or query the session object indirect ** flag. If the second argument passed to this function is zero, then the ** indirect flag is cleared. If it is greater than zero, the indirect flag ** is set. Passing a value less than zero does not modify the current value -** of the indirect flag, and may be used to query the current state of the +** of the indirect flag, and may be used to query the current state of the ** indirect flag for the specified session object. ** -** The return value indicates the final state of the indirect flag: 0 if +** The return value indicates the final state of the indirect flag: 0 if ** it is clear, or 1 if it is set. */ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); /* ** CAPI3REF: Attach A Table To A Session Object -** METHOD: sqlite3_session ** ** If argument zTab is not NULL, then it is the name of a table to attach -** to the session object passed as the first argument. All subsequent changes -** made to the table while the session object is enabled will be recorded. See +** to the session object passed as the first argument. All subsequent changes +** made to the table while the session object is enabled will be recorded. See ** documentation for [sqlite3session_changeset()] for further details. ** ** Or, if argument zTab is NULL, then changes are recorded for all tables -** in the database. If additional tables are added to the database (by -** executing "CREATE TABLE" statements) after this call is made, changes for +** in the database. If additional tables are added to the database (by +** executing "CREATE TABLE" statements) after this call is made, changes for ** the new tables are also recorded. ** ** Changes can only be recorded for tables that have a PRIMARY KEY explicitly -** defined as part of their CREATE TABLE statement. It does not matter if the +** defined as part of their CREATE TABLE statement. It does not matter if the ** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY ** KEY may consist of a single column, or may be a composite key. -** +** ** It is not an error if the named table does not exist in the database. Nor ** is it an error if the named table does not have a PRIMARY KEY. However, ** no changes will be recorded in either of these scenarios. ** ** Changes are not recorded for individual rows that have NULL values stored ** in one or more of their PRIMARY KEY columns. ** -** SQLITE_OK is returned if the call completes without error. Or, if an error +** SQLITE_OK is returned if the call completes without error. Or, if an error ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. -** -**

      Special sqlite_stat1 Handling

      -** -** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to -** 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. */ SQLITE_API int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zTab /* Table name */ ); /* ** CAPI3REF: Set a table filter on a Session Object. -** METHOD: sqlite3_session ** -** The second argument (xFilter) is the "filter callback". For changes to rows +** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called -** to determine whether changes to the table's rows should be tracked or not. -** If xFilter returns 0, changes are not tracked. Note that once a table is +** to determine whether changes to the table's rows should be tracked or not. +** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. */ SQLITE_API void sqlite3session_table_filter( sqlite3_session *pSession, /* Session object */ int(*xFilter)( @@ -11371,15 +8989,14 @@ void *pCtx /* First argument passed to xFilter */ ); /* ** CAPI3REF: Generate A Changeset From A Session Object -** METHOD: sqlite3_session ** -** Obtain a changeset containing changes to the tables attached to the -** session object passed as the first argument. If successful, -** set *ppChangeset to point to a buffer containing the changeset +** Obtain a changeset containing changes to the tables attached to the +** session object passed as the first argument. If successful, +** set *ppChangeset to point to a buffer containing the changeset ** and *pnChangeset to the size of the changeset in bytes before returning ** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to ** zero and return an SQLite error code. ** ** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, @@ -11390,11 +9007,11 @@ ** database row along with the updated values for each updated non-primary-key ** column. It is not possible for an UPDATE change to represent a change that ** modifies the values of primary key columns. If such a change is made, it ** is represented in a changeset as a DELETE followed by an INSERT. ** -** Changes are not recorded for rows that have NULL values stored in one or +** Changes are not recorded for rows that have NULL values stored in one or ** more of their PRIMARY KEY columns. If such a row is inserted or deleted, ** no corresponding change is present in the changesets returned by this ** function. If an existing row with one or more NULL values stored in ** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, ** only an INSERT is appears in the changeset. Similarly, if an existing row @@ -11443,38 +9060,38 @@ ** file. Specifically: ** **
        **
      • For each record generated by an insert, the database is queried ** for a row with a matching primary key. If one is found, an INSERT -** change is added to the changeset. If no such row is found, no change +** change is added to the changeset. If no such row is found, no change ** is added to the changeset. ** -**
      • For each record generated by an update or delete, the database is +**
      • For each record generated by an update or delete, the database is ** queried for a row with a matching primary key. If such a row is ** found and one or more of the non-primary key fields have been -** modified from their original values, an UPDATE change is added to -** the changeset. Or, if no such row is found in the table, a DELETE +** modified from their original values, an UPDATE change is added to +** the changeset. Or, if no such row is found in the table, a DELETE ** change is added to the changeset. If there is a row with a matching ** primary key in the database, but all fields contain their original ** values, no change is added to the changeset. **
      ** ** This means, amongst other things, that if a row is inserted and then later ** deleted while a session object is active, neither the insert nor the delete -** will be present in the changeset. Or if a row is deleted and then later a +** will be present in the changeset. Or if a row is deleted and then later a ** row with the same primary key values inserted while a session object is ** active, the resulting changeset will contain an UPDATE change instead of ** a DELETE and an INSERT. ** ** When a session object is disabled (see the [sqlite3session_enable()] API), ** it does not accumulate records when rows are inserted, updated or deleted. ** This may appear to have some counter-intuitive effects if a single row ** is written to more than once during a session. For example, if a row -** is inserted while a session object is enabled, then later deleted while +** is inserted while a session object is enabled, then later deleted while ** the same session object is disabled, no INSERT record will appear in the ** changeset, even though the delete took place while the session was disabled. -** Or, if one field of a row is updated while a session is disabled, and +** Or, if one field of a row is updated while a session is disabled, and ** another field of the same row is updated while the session is enabled, the ** resulting changeset will contain an UPDATE change that updates both fields. */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ @@ -11481,37 +9098,20 @@ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* -** CAPI3REF: Return An Upper-limit For The Size Of The Changeset -** METHOD: sqlite3_session -** -** By default, this function always returns 0. For it to return -** a useful result, the sqlite3_session object must have been configured -** to enable this API using sqlite3session_object_config() with the -** SQLITE_SESSION_OBJCONFIG_SIZE verb. -** -** When enabled, this function returns an upper limit, in bytes, for the size -** of the changeset that might be produced if sqlite3session_changeset() were -** called. The final changeset size might be equal to or smaller than the -** size in bytes returned by this function. -*/ -SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession); - -/* -** CAPI3REF: Load The Difference Between Tables Into A Session -** METHOD: sqlite3_session +** CAPI3REF: Load The Difference Between Tables Into A Session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the ** [sqlite3session_attach()] function. If zTbl does not exist, or if it ** does not have a primary key, this function is a no-op (but does not return ** an error). ** ** Argument zFromDb must be the name of a database ("main", "temp" etc.) -** attached to the same database handle as the session object that contains +** attached to the same database handle as the session object that contains ** a table compatible with the table attached to the session by this function. ** A table is considered compatible if it: ** **
        **
      • Has the same name, @@ -11523,37 +9123,37 @@ ** are compatible but do not have any PRIMARY KEY columns, it is not an error ** but no changes are added to the session object. As with other session ** APIs, tables without PRIMARY KEYs are simply ignored. ** ** This function adds a set of changes to the session object that could be -** used to update the table in database zFrom (call this the "from-table") -** so that its content is the same as the table attached to the session +** used to update the table in database zFrom (call this the "from-table") +** so that its content is the same as the table attached to the session ** object (call this the "to-table"). Specifically: ** **
          -**
        • For each row (primary key) that exists in the to-table but not in +**
        • For each row (primary key) that exists in the to-table but not in ** the from-table, an INSERT record is added to the session object. ** -**
        • For each row (primary key) that exists in the to-table but not in +**
        • For each row (primary key) that exists in the to-table but not in ** the from-table, a DELETE record is added to the session object. ** -**
        • For each row (primary key) that exists in both tables, but features +**
        • For each row (primary key) that exists in both tables, but features ** different non-PK values in each, an UPDATE record is added to the -** session. +** session. **
        ** ** To clarify, if this function is called and then a changeset constructed -** using [sqlite3session_changeset()], then after applying that changeset to -** database zFrom the contents of the two compatible tables would be +** using [sqlite3session_changeset()], then after applying that changeset to +** database zFrom the contents of the two compatible tables would be ** identical. ** ** It an error if database zFrom does not exist or does not contain the ** required compatible table. ** -** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite +** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite ** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg -** may be set to point to a buffer containing an English language error +** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to free this buffer using ** sqlite3_free(). */ SQLITE_API int sqlite3session_diff( sqlite3_session *pSession, @@ -11563,28 +9163,27 @@ ); /* ** CAPI3REF: Generate A Patchset From A Session Object -** METHOD: sqlite3_session ** ** The differences between a patchset and a changeset are that: ** **
          -**
        • DELETE records consist of the primary key fields only. The +**
        • DELETE records consist of the primary key fields only. The ** original values of other fields are omitted. -**
        • The original values of any modified fields are omitted from +**
        • The original values of any modified fields are omitted from ** UPDATE records. **
        ** -** A patchset blob may be used with up to date versions of all -** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), +** A patchset blob may be used with up to date versions of all +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), ** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, ** attempting to use a patchset blob with old versions of the -** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. ** -** Because the non-primary key "old.*" fields are omitted, no +** Because the non-primary key "old.*" fields are omitted, no ** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset ** is passed to the sqlite3changeset_apply() API. Other conflict types work ** in the same way as for changesets. ** ** Changes within a patchset are ordered in the same way as for changesets @@ -11592,49 +9191,40 @@ ** a single table are grouped together, tables appear in the order in which ** they were attached to the session object). */ SQLITE_API int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ - int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ - void **ppPatchset /* OUT: Buffer containing patchset */ + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ + void **ppPatchset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Test if a changeset has recorded any changes. ** -** Return non-zero if no changes to attached tables have been recorded by -** the session object passed as the first argument. Otherwise, if one or +** Return non-zero if no changes to attached tables have been recorded by +** the session object passed as the first argument. Otherwise, if one or ** more changes have been recorded, return zero. ** ** Even if this function returns zero, it is possible that calling ** [sqlite3session_changeset()] on the session handle may still return a -** changeset that contains no changes. This can happen when a row in -** an attached table is modified and then later on the original values +** changeset that contains no changes. This can happen when a row in +** an attached table is modified and then later on the original values ** are restored. However, if this function returns non-zero, then it is -** guaranteed that a call to sqlite3session_changeset() will return a +** guaranteed that a call to sqlite3session_changeset() will return a ** changeset containing zero changes. */ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); /* -** CAPI3REF: Query for the amount of heap memory used by a session object. -** -** This API returns the total amount of heap memory in bytes currently -** used by the session object passed as the only argument. -*/ -SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession); - -/* -** CAPI3REF: Create An Iterator To Traverse A Changeset -** CONSTRUCTOR: sqlite3_changeset_iter +** CAPI3REF: Create An Iterator To Traverse A Changeset ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK ** is returned. Otherwise, if an error occurs, *pp is set to zero and an ** SQLite error code is returned. ** -** The following functions can be used to advance and query a changeset +** The following functions can be used to advance and query a changeset ** iterator created by this function: ** **
          **
        • [sqlite3changeset_next()] **
        • [sqlite3changeset_op()] @@ -11647,56 +9237,29 @@ ** changeset (pChangeset) must remain valid until after the iterator is ** destroyed. ** ** Assuming the changeset blob was created by one of the ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or -** [sqlite3changeset_invert()] functions, all changes within the changeset -** that apply to a single table are grouped together. This means that when -** an application iterates through a changeset using an iterator created by -** this function, all changes that relate to a single table are visited -** consecutively. There is no chance that the iterator will visit a change -** the applies to table X, then one for table Y, and then later on visit +** [sqlite3changeset_invert()] functions, all changes within the changeset +** that apply to a single table are grouped together. This means that when +** an application iterates through a changeset using an iterator created by +** this function, all changes that relate to a single table are visited +** consecutively. There is no chance that the iterator will visit a change +** the applies to table X, then one for table Y, and then later on visit ** another change for table X. -** -** The behavior of sqlite3changeset_start_v2() and its streaming equivalent -** may be modified by passing a combination of -** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. -** -** Note that the sqlite3changeset_start_v2() API is still experimental -** and therefore subject to change. */ SQLITE_API int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); -SQLITE_API int sqlite3changeset_start_v2( - sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ - int nChangeset, /* Size of changeset blob in bytes */ - void *pChangeset, /* Pointer to blob containing changeset */ - int flags /* SESSION_CHANGESETSTART_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3changeset_start_v2 -** -** The following flags may passed via the 4th parameter to -** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: -** -**
          SQLITE_CHANGESETAPPLY_INVERT
          -** Invert the changeset while iterating through it. This is equivalent to -** inverting a changeset using sqlite3changeset_invert() before applying it. -** It is an error to specify this flag with a patchset. -*/ -#define SQLITE_CHANGESETSTART_INVERT 0x0002 /* ** CAPI3REF: Advance A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** -** This function may only be used with iterators created by the function +** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to ** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE ** is returned and the call has no effect. ** ** Immediately after an iterator is created by sqlite3changeset_start(), it @@ -11703,47 +9266,41 @@ ** does not point to any change in the changeset. Assuming the changeset ** is not empty, the first call to this function advances the iterator to ** point to the first change in the changeset. Each subsequent call advances ** the iterator to point to the next change in the changeset (if any). If ** no error occurs and the iterator points to a valid change after a call -** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. ** Otherwise, if all changes in the changeset have already been visited, ** SQLITE_DONE is returned. ** -** If an error occurs, an SQLite error code is returned. Possible error -** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or +** If an error occurs, an SQLite error code is returned. Possible error +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or ** SQLITE_NOMEM. */ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent ** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this ** is not the case, this function returns [SQLITE_MISUSE]. ** -** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three -** outputs are set through these pointers: -** -** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the type of change that the iterator currently points to; -** -** *pnCol is set to the number of columns in the table affected by the change; and -** -** *pzTab is set to point to a nul-terminated utf-8 encoded string containing -** the name of the table affected by the current change. The buffer remains -** valid until either sqlite3changeset_next() is called on the iterator -** or until the conflict-handler function returns. -** -** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change +** If argument pzTab is not NULL, then *pzTab is set to point to a +** nul-terminated utf-8 encoded string containing the name of the table +** affected by the current change. The buffer remains valid until either +** sqlite3changeset_next() is called on the iterator or until the +** conflict-handler function returns. If pnCol is not NULL, then *pnCol is +** set to the number of columns in the table affected by the change. If +** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change ** is an indirect change, or false (0) otherwise. See the documentation for ** [sqlite3session_indirect()] for a description of direct and indirect -** changes. +** changes. Finally, if pOp is not NULL, then *pOp is set to one of +** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the +** type of change that the iterator currently points to. ** ** If no error occurs, SQLITE_OK is returned. If an error does occur, an ** SQLite error code is returned. The values of the output variables may not ** be trusted in this case. */ @@ -11755,11 +9312,10 @@ int *pbIndirect /* OUT: True for an 'indirect' change */ ); /* ** CAPI3REF: Obtain The Primary Key Definition Of A Table -** METHOD: sqlite3_changeset_iter ** ** For each modified table, a changeset includes the following: ** **
            **
          • The number of columns in the table, and @@ -11787,28 +9343,27 @@ int *pnCol /* OUT: Number of entries in output array */ ); /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. ** Furthermore, it may only be called if the type of change that the iterator ** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, ** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, ** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the vector of +** sqlite3_value object containing the iVal'th value from the vector of ** original row values stored as part of the UPDATE or DELETE change and -** returns SQLITE_OK. The name of the function comes from the fact that this +** returns SQLITE_OK. The name of the function comes from the fact that this ** is similar to the "old.*" columns available to update or delete triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ @@ -11818,31 +9373,30 @@ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ); /* ** CAPI3REF: Obtain new.* Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator ** created by [sqlite3changeset_start()]. In the latter case, the most recent -** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. ** Furthermore, it may only be called if the type of change that the iterator ** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, ** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. ** ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, ** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the vector of +** sqlite3_value object containing the iVal'th value from the vector of ** new row values stored as part of the UPDATE or INSERT change and ** returns SQLITE_OK. If the change is an UPDATE and does not include -** a new value for the requested column, *ppValue is set to NULL and -** SQLITE_OK returned. The name of the function comes from the fact that -** this is similar to the "new.*" columns available to update or delete +** a new value for the requested column, *ppValue is set to NULL and +** SQLITE_OK returned. The name of the function comes from the fact that +** this is similar to the "new.*" columns available to update or delete ** triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ @@ -11852,11 +9406,10 @@ sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); /* ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either ** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function ** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue @@ -11865,11 +9418,11 @@ ** Argument iVal must be greater than or equal to 0, and less than the number ** of columns in the table affected by the current change. Otherwise, ** [SQLITE_RANGE] is returned and *ppValue is set to NULL. ** ** If successful, this function sets *ppValue to point to a protected -** sqlite3_value object containing the iVal'th value from the +** sqlite3_value object containing the iVal'th value from the ** "conflicting row" associated with the current conflict-handler callback ** and returns SQLITE_OK. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. @@ -11880,11 +9433,10 @@ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); /* ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations -** METHOD: sqlite3_changeset_iter ** ** This function may only be called with an iterator passed to an ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case ** it sets the output variable to the total number of known foreign key ** violations in the destination database and returns SQLITE_OK. @@ -11897,11 +9449,10 @@ ); /* ** CAPI3REF: Finalize A Changeset Iterator -** METHOD: sqlite3_changeset_iter ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. ** ** This function should only be called on iterators created using the @@ -11909,25 +9460,23 @@ ** function with an iterator passed to a conflict-handler by ** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the ** call has no effect. ** ** If an error was encountered within a call to an sqlite3changeset_xxx() -** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an ** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** -**
             **   sqlite3changeset_start();
             **   while( SQLITE_ROW==sqlite3changeset_next() ){
             **     // Do something with change.
             **   }
             **   rc = sqlite3changeset_finalize();
             **   if( rc!=SQLITE_OK ){
            -**     // An error has occurred
            +**     // An error has occurred 
             **   }
            -** 
            */ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Invert A Changeset @@ -11949,11 +9498,11 @@ ** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and ** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are ** zeroed and an SQLite error code returned. ** ** It is the responsibility of the caller to eventually call sqlite3_free() -** on the *ppOut pointer to free the buffer allocation following a successful +** on the *ppOut pointer to free the buffer allocation following a successful ** call to this function. ** ** WARNING/TODO: This function currently assumes that the input is a valid ** changeset. If it is not, the results are undefined. */ @@ -11963,19 +9512,18 @@ ); /* ** CAPI3REF: Concatenate Two Changeset Objects ** -** This function is used to concatenate two changesets, A and B, into a +** This function is used to concatenate two changesets, A and B, into a ** single changeset. The result is a changeset equivalent to applying -** changeset A followed by changeset B. +** changeset A followed by changeset B. ** -** This function combines the two input changesets using an +** This function combines the two input changesets using an ** sqlite3_changegroup object. Calling it produces similar results as the ** following code fragment: ** -**
             **   sqlite3_changegroup *pGrp;
             **   rc = sqlite3_changegroup_new(&pGrp);
             **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
             **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
             **   if( rc==SQLITE_OK ){
            @@ -11982,11 +9530,10 @@
             **     rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
             **   }else{
             **     *ppOut = 0;
             **     *pnOut = 0;
             **   }
            -** 
            ** ** Refer to the sqlite3_changegroup documentation below for details. */ SQLITE_API int sqlite3changeset_concat( int nA, /* Number of bytes in buffer pA */ @@ -11995,43 +9542,27 @@ void *pB, /* Pointer to buffer containing changeset B */ int *pnOut, /* OUT: Number of bytes in output changeset */ void **ppOut /* OUT: Buffer containing output changeset */ ); - -/* -** CAPI3REF: Upgrade the Schema of a Changeset/Patchset -*/ -SQLITE_API int sqlite3changeset_upgrade( - sqlite3 *db, - const char *zDb, - int nIn, const void *pIn, /* Input changeset */ - int *pnOut, void **ppOut /* OUT: Inverse of input */ -); - - /* ** CAPI3REF: Changegroup Handle -** -** A changegroup is an object used to combine two or more -** [changesets] or [patchsets] */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* ** CAPI3REF: Create A New Changegroup Object -** CONSTRUCTOR: sqlite3_changegroup ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup ** object may combine changesets or patchsets, but not both. The output is ** always in the same format as the input. ** ** If successful, this function returns SQLITE_OK and populates (*pp) with ** a pointer to a new sqlite3_changegroup object before returning. The caller -** should eventually free the returned object using a call to +** should eventually free the returned object using a call to ** sqlite3changegroup_delete(). If an error occurs, an SQLite error code ** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. ** ** The usual usage pattern for an sqlite3_changegroup object is as follows: ** @@ -12039,63 +9570,30 @@ **
          • It is created using a call to sqlite3changegroup_new(). ** **
          • Zero or more changesets (or patchsets) are added to the object ** by calling sqlite3changegroup_add(). ** -**
          • The result of combining all input changesets together is obtained +**
          • The result of combining all input changesets together is obtained ** by the application via a call to sqlite3changegroup_output(). ** **
          • The object is deleted using a call to sqlite3changegroup_delete(). **
          ** ** Any number of calls to add() and output() may be made between the calls to ** new() and delete(), and in any order. ** -** As well as the regular sqlite3changegroup_add() and +** As well as the regular sqlite3changegroup_add() and ** sqlite3changegroup_output() functions, also available are the streaming ** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). */ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); -/* -** CAPI3REF: Add a Schema to a Changegroup -** METHOD: sqlite3_changegroup_schema -** -** This method may be used to optionally enforce the rule that the changesets -** added to the changegroup handle must match the schema of database zDb -** ("main", "temp", or the name of an attached database). If -** sqlite3changegroup_add() is called to add a changeset that is not compatible -** with the configured schema, SQLITE_SCHEMA is returned and the changegroup -** object is left in an undefined state. -** -** A changeset schema is considered compatible with the database schema in -** the same way as for sqlite3changeset_apply(). Specifically, for each -** table in the changeset, there exists a database table with: -** -**
            -**
          • The name identified by the changeset, and -**
          • at least as many columns as recorded in the changeset, and -**
          • the primary key columns in the same position as recorded in -** the changeset. -**
          -** -** The output of the changegroup object always has the same schema as the -** database nominated using this function. In cases where changesets passed -** to sqlite3changegroup_add() have fewer columns than the corresponding table -** in the database schema, these are filled in using the default column -** values from the database schema. This makes it possible to combined -** changesets that have different numbers of columns for a single table -** within a changegroup, provided that they are otherwise compatible. -*/ -SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb); - /* ** CAPI3REF: Add A Changeset To A Changegroup -** METHOD: sqlite3_changegroup ** ** Add all changes within the changeset (or patchset) in buffer pData (size -** nData bytes) to the changegroup. +** nData bytes) to the changegroup. ** ** If the buffer contains a patchset, then all prior calls to this function ** on the same changegroup object must also have specified patchsets. Or, if ** the buffer contains a changeset, so must have the earlier calls to this ** function. Otherwise, SQLITE_ERROR is returned and no changes are added @@ -12118,11 +9616,11 @@ ** INSERT INSERT ** The new change is ignored. This case does not occur if the new ** changeset was recorded immediately after the changesets already ** added to the changegroup. ** INSERT UPDATE -** The INSERT change remains in the changegroup. The values in the +** The INSERT change remains in the changegroup. The values in the ** INSERT change are modified as if the row was inserted by the ** existing change and then updated according to the new change. ** INSERT DELETE ** The existing INSERT is removed from the changegroup. The DELETE is ** not added. @@ -12129,21 +9627,21 @@ ** UPDATE INSERT ** The new change is ignored. This case does not occur if the new ** changeset was recorded immediately after the changesets already ** added to the changegroup. ** UPDATE UPDATE -** The existing UPDATE remains within the changegroup. It is amended -** so that the accompanying values are as if the row was updated once +** The existing UPDATE remains within the changegroup. It is amended +** so that the accompanying values are as if the row was updated once ** by the existing change and then again by the new change. ** UPDATE DELETE ** The existing UPDATE is replaced by the new DELETE within the ** changegroup. ** DELETE INSERT ** If one or more of the column values in the row inserted by the -** new change differ from those in the row deleted by the existing +** new change differ from those in the row deleted by the existing ** change, the existing DELETE is replaced by an UPDATE within the -** changegroup. Otherwise, if the inserted row is exactly the same +** changegroup. Otherwise, if the inserted row is exactly the same ** as the deleted row, the existing DELETE is simply discarded. ** DELETE UPDATE ** The new change is ignored. This case does not occur if the new ** changeset was recorded immediately after the changesets already ** added to the changegroup. @@ -12154,52 +9652,22 @@ ** ** ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup -** object has been configured with a database schema using the -** sqlite3changegroup_schema() API, then it is possible to combine changesets -** with different numbers of columns for a single table, provided that -** they are otherwise compatible. -** -** If the input changeset appears to be corrupt and the corruption is -** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition -** occurs during processing, this function returns SQLITE_NOMEM. -** -** In all cases, if an error occurs the state of the final contents of the -** changegroup is undefined. If no error occurs, SQLITE_OK is returned. +** case, this function fails with SQLITE_SCHEMA. If the input changeset +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is +** returned. Or, if an out-of-memory condition occurs during processing, this +** function returns SQLITE_NOMEM. In all cases, if an error occurs the +** final contents of the changegroup is undefined. +** +** If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); - -/* -** CAPI3REF: Add A Single Change To A Changegroup -** METHOD: sqlite3_changegroup -** -** This function adds the single change currently indicated by the iterator -** passed as the second argument to the changegroup object. The rules for -** adding the change are just as described for [sqlite3changegroup_add()]. -** -** If the change is successfully added to the changegroup, SQLITE_OK is -** returned. Otherwise, an SQLite error code is returned. -** -** The iterator must point to a valid entry when this function is called. -** If it does not, SQLITE_ERROR is returned and no change is added to the -** changegroup. Additionally, the iterator must not have been opened with -** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also -** returned. -*/ -SQLITE_API int sqlite3changegroup_add_change( - sqlite3_changegroup*, - sqlite3_changeset_iter* -); - - /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup -** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup ** were themselves changesets, the output is a changeset. Or, if the ** inputs were patchsets, the output is also a patchset. @@ -12213,11 +9681,11 @@ ** appended onto the end of the output changeset, again in the order in ** which they are first encountered. ** ** If an error occurs, an SQLite error code is returned and the output ** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK -** is returned and the output variables are set to the size of and a +** is returned and the output variables are set to the size of and a ** pointer to the output buffer, respectively. In this case it is the ** responsibility of the caller to eventually free the buffer using a ** call to sqlite3_free(). */ SQLITE_API int sqlite3changegroup_output( @@ -12226,77 +9694,77 @@ void **ppData /* OUT: Pointer to output buffer */ ); /* ** CAPI3REF: Delete A Changegroup Object -** DESTRUCTOR: sqlite3_changegroup */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** -** Apply a changeset or patchset to a database. These functions attempt to -** update the "main" database attached to handle db with the changes found in -** the changeset passed via the second and third arguments. +** Apply a changeset to a database. This function attempts to update the +** "main" database attached to handle db with the changes found in the +** changeset passed via the second and third arguments. ** -** The fourth argument (xFilter) passed to these functions is the "filter +** The fourth argument (xFilter) passed to this function is the "filter ** callback". If it is not NULL, then for each table affected by at least one ** change in the changeset, the filter callback is invoked with ** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument as the first. If the "filter callback" -** returns zero, then no attempt is made to apply any changes to the table. -** Otherwise, if the return value is non-zero or the xFilter argument to -** is NULL, all changes related to the table are attempted. +** passed as the sixth argument to this function as the first. If the "filter +** callback" returns zero, then no attempt is made to apply any changes to +** the table. Otherwise, if the return value is non-zero or the xFilter +** argument to this function is NULL, all changes related to the table are +** attempted. ** -** For each table that is not excluded by the filter callback, this function -** tests that the target database contains a compatible table. A table is +** For each table that is not excluded by the filter callback, this function +** tests that the target database contains a compatible table. A table is ** considered compatible if all of the following are true: ** **
            -**
          • The table has the same name as the name recorded in the +**
          • The table has the same name as the name recorded in the ** changeset, and -**
          • The table has at least as many columns as recorded in the +**
          • The table has at least as many columns as recorded in the ** changeset, and -**
          • The table has primary key columns in the same position as +**
          • The table has primary key columns in the same position as ** recorded in the changeset. **
          ** ** If there is no compatible table, it is not an error, but none of the ** changes associated with the table are applied. A warning message is issued ** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most ** one such warning is issued for each table in the changeset. ** -** For each change for which there is a compatible table, an attempt is made -** to modify the table contents according to the UPDATE, INSERT or DELETE -** change. If a change cannot be applied cleanly, the conflict handler -** function passed as the fifth argument to sqlite3changeset_apply() may be -** invoked. A description of exactly when the conflict handler is invoked for +** For each change for which there is a compatible table, an attempt is made +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for ** each type of change is below. ** ** Unlike the xFilter argument, xConflict may not be passed NULL. The results ** of passing anything other than a valid function pointer as the xConflict ** argument are undefined. ** ** Each time the conflict handler function is invoked, it must return one -** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or ** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned ** if the second argument passed to the conflict handler is either ** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler ** returns an illegal value, any changes already made are rolled back and -** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different ** actions are taken by sqlite3changeset_apply() depending on the value ** returned by each invocation of the conflict-handler function. Refer to -** the documentation for the three +** the documentation for the three ** [SQLITE_CHANGESET_OMIT|available return values] for details. ** **
          **
          DELETE Changes
          -** For each DELETE change, the function checks if the target database -** contains a row with the same primary key value (or values) as the -** original row values stored in the changeset. If it does, and the values -** stored in all non-primary key columns also match the values stored in +** For each DELETE change, 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 deleted from 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 the original ** row value stored in the changeset, the conflict-handler function is @@ -12321,26 +9789,26 @@ ** For each INSERT change, an attempt is made to insert the new row into ** 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 +** If the attempt to insert the row fails because the database already ** contains a row with the same primary key values, the conflict handler -** function is invoked with the second argument set to +** function is invoked with the second argument set to ** [SQLITE_CHANGESET_CONFLICT]. ** ** If the attempt to insert the row fails because of some other constraint -** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is ** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. -** This includes the case where the INSERT operation is re-attempted because -** an earlier call to the conflict handler function returned +** This includes the case where the INSERT operation is re-attempted because +** an earlier call to the conflict handler function returned ** [SQLITE_CHANGESET_REPLACE]. ** **
          UPDATE Changes
          -** For each UPDATE change, the function checks if the target database -** contains a row with the same primary key value (or values) as the -** original row values stored in the changeset. If it does, and the values +** For each UPDATE change, 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 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 modified non-primary key fields contains a value different from an @@ -12352,45 +9820,28 @@ ** ** If no row with matching primary key values is found in the database, ** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] ** passed as the second argument. ** -** If the UPDATE operation is attempted, but SQLite returns -** SQLITE_CONSTRAINT, the conflict-handler function is invoked with +** If the UPDATE operation is attempted, but SQLite returns +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with ** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. -** This includes the case where the UPDATE operation is attempted after +** This includes the case where the UPDATE operation is attempted after ** an earlier call to the conflict handler function returned -** [SQLITE_CHANGESET_REPLACE]. +** [SQLITE_CHANGESET_REPLACE]. **
          ** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. -** This can be used to further customize the application's conflict +** This can be used to further customize the applications conflict ** resolution strategy. ** -** All changes made by these functions are enclosed in a savepoint transaction. +** All changes made by this function are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is -** rolled back, restoring the target database to its original state, and an +** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. -** -** If the output parameters (ppRebase) and (pnRebase) are non-NULL and -** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() -** may set (*ppRebase) to point to a "rebase" that may be used with the -** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) -** is set to the size of the buffer in bytes. It is the responsibility of the -** caller to eventually free any such buffer using sqlite3_free(). The buffer -** is only allocated and populated if one or more conflicts were encountered -** while applying the patchset. See comments surrounding the sqlite3_rebaser -** APIs for further details. -** -** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent -** may be modified by passing a combination of -** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. -** -** Note that the sqlite3changeset_apply_v2() API is still experimental -** and therefore subject to change. */ 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 */ @@ -12403,123 +9854,61 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); -SQLITE_API int sqlite3changeset_apply_v2( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* SESSION_CHANGESETAPPLY_* flags */ -); - -/* -** CAPI3REF: Flags for sqlite3changeset_apply_v2 -** -** The following flags may passed via the 9th parameter to -** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: -** -**
          -**
          SQLITE_CHANGESETAPPLY_NOSAVEPOINT
          -** Usually, the sessions module encloses all operations performed by -** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The -** SAVEPOINT is committed if the changeset or patchset is successfully -** applied, or rolled back if an error occurs. Specifying this flag -** causes the sessions module to omit this savepoint. In this case, if the -** caller has an open transaction or savepoint when apply_v2() is called, -** it may revert the partially applied changeset by rolling it back. -** -**
          SQLITE_CHANGESETAPPLY_INVERT
          -** Invert the changeset before applying it. This is equivalent to inverting -** a changeset using sqlite3changeset_invert() before applying it. It is -** an error to specify this flag with a patchset. -** -**
          SQLITE_CHANGESETAPPLY_IGNORENOOP
          -** Do not invoke the conflict handler callback for any changes that -** would not actually modify the database even if they were applied. -** Specifically, this means that the conflict handler is not invoked -** for: -**
            -**
          • a delete change if the row being deleted cannot be found, -**
          • an update change if the modified fields are already set to -** their new values in the conflicting row, or -**
          • an insert change if all fields of the conflicting row match -** the row being inserted. -**
          -** -**
          SQLITE_CHANGESETAPPLY_FKNOACTION
          -** If this flag it set, then all foreign key constraints in the target -** database behave as if they were declared with "ON UPDATE NO ACTION ON -** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL -** or SET DEFAULT. -*/ -#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 -#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 -#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004 -#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 - -/* + +/* ** CAPI3REF: Constants Passed To The Conflict Handler ** ** Values that may be passed as the second argument to a conflict-handler. ** **
          **
          SQLITE_CHANGESET_DATA
          ** The conflict handler is invoked with CHANGESET_DATA as the second argument ** when processing a DELETE or UPDATE change if a row with the required -** PRIMARY KEY fields is present in the database, but one or more other -** (non primary-key) fields modified by the update do not contain the +** PRIMARY KEY fields is present in the database, but one or more other +** (non primary-key) fields modified by the update do not contain the ** expected "before" values. -** +** ** The conflicting row, in this case, is the database row with the matching ** primary key. -** +** **
          SQLITE_CHANGESET_NOTFOUND
          ** The conflict handler is invoked with CHANGESET_NOTFOUND as the second ** argument when processing a DELETE or UPDATE change if a row with the ** required PRIMARY KEY fields is not present in the database. -** +** ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. -** +** **
          SQLITE_CHANGESET_CONFLICT
          ** CHANGESET_CONFLICT is passed as the second argument to the conflict -** handler while processing an INSERT change if the operation would result +** handler while processing an INSERT change if the operation would result ** in duplicate primary key values. -** +** ** The conflicting row in this case is the database row with the matching ** primary key. ** **
          SQLITE_CHANGESET_FOREIGN_KEY
          ** If foreign key handling is enabled, and applying a changeset leaves the -** database in a state containing foreign key violations, the conflict +** database in a state containing foreign key violations, the conflict ** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument ** exactly once before the changeset is committed. If the conflict handler ** returns CHANGESET_OMIT, the changes, including those that caused the ** foreign key constraint violation, are committed. Or, if it returns ** CHANGESET_ABORT, the changeset is rolled back. ** ** No current or conflicting row information is provided. The only function ** it is possible to call on the supplied sqlite3_changeset_iter handle ** is sqlite3changeset_fk_conflicts(). -** +** **
          SQLITE_CHANGESET_CONSTRAINT
          -** If any other constraint violation occurs while applying a change (i.e. -** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is +** If any other constraint violation occurs while applying a change (i.e. +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is ** invoked with CHANGESET_CONSTRAINT as the second argument. -** +** ** There is no conflicting row in this case. The results of invoking the ** sqlite3changeset_conflict() API are undefined. ** **
          */ @@ -12527,25 +9916,25 @@ #define SQLITE_CHANGESET_NOTFOUND 2 #define SQLITE_CHANGESET_CONFLICT 3 #define SQLITE_CHANGESET_CONSTRAINT 4 #define SQLITE_CHANGESET_FOREIGN_KEY 5 -/* +/* ** CAPI3REF: Constants Returned By The Conflict Handler ** ** A conflict handler callback must return one of the following three values. ** **
          **
          SQLITE_CHANGESET_OMIT
          ** If a conflict handler returns this value no special action is taken. The -** change that caused the conflict is not applied. The session module +** change that caused the conflict is not applied. The session module ** continues to the next change in the changeset. ** **
          SQLITE_CHANGESET_REPLACE
          ** This value may only be returned if the second argument to the conflict ** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this -** is not the case, any changes applied so far are rolled back and the +** is not the case, any changes applied so far are rolled back and the ** call to sqlite3changeset_apply() returns SQLITE_MISUSE. ** ** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict ** handler, then the conflicting row is either updated or deleted, depending ** on the type of change. @@ -12554,195 +9943,39 @@ ** handler, then the conflicting row is removed from the database and a ** second attempt to apply the change is made. If this second attempt fails, ** the original row is restored to the database before continuing. ** **
          SQLITE_CHANGESET_ABORT
          -** If this value is returned, any changes applied so far are rolled back +** If this value is returned, any changes applied so far are rolled back ** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. **
          */ #define SQLITE_CHANGESET_OMIT 0 #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 -/* -** CAPI3REF: Rebasing changesets -** EXPERIMENTAL -** -** Suppose there is a site hosting a database in state S0. And that -** modifications are made that move that database to state S1 and a -** changeset recorded (the "local" changeset). Then, a changeset based -** on S0 is received from another site (the "remote" changeset) and -** applied to the database. The database is then in state -** (S1+"remote"), where the exact state depends on any conflict -** resolution decisions (OMIT or REPLACE) made while applying "remote". -** Rebasing a changeset is to update it to take those conflict -** resolution decisions into account, so that the same conflicts -** do not have to be resolved elsewhere in the network. -** -** For example, if both the local and remote changesets contain an -** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": -** -** local: INSERT INTO t1 VALUES(1, 'v1'); -** remote: INSERT INTO t1 VALUES(1, 'v2'); -** -** and the conflict resolution is REPLACE, then the INSERT change is -** removed from the local changeset (it was overridden). Or, if the -** conflict resolution was "OMIT", then the local changeset is modified -** to instead contain: -** -** UPDATE t1 SET b = 'v2' WHERE a=1; -** -** Changes within the local changeset are rebased as follows: -** -**
          -**
          Local INSERT
          -** This may only conflict with a remote INSERT. If the conflict -** resolution was OMIT, then add an UPDATE change to the rebased -** changeset. Or, if the conflict resolution was REPLACE, add -** nothing to the rebased changeset. -** -**
          Local DELETE
          -** This may conflict with a remote UPDATE or DELETE. In both cases the -** only possible resolution is OMIT. If the remote operation was a -** DELETE, then add no change to the rebased changeset. If the remote -** operation was an UPDATE, then the old.* fields of change are updated -** to reflect the new.* values in the UPDATE. -** -**
          Local UPDATE
          -** This may conflict with a remote UPDATE or DELETE. If it conflicts -** with a DELETE, and the conflict resolution was OMIT, then the update -** is changed into an INSERT. Any undefined values in the new.* record -** from the update change are filled in using the old.* values from -** the conflicting DELETE. Or, if the conflict resolution was REPLACE, -** the UPDATE change is simply omitted from the rebased changeset. -** -** If conflict is with a remote UPDATE and the resolution is OMIT, then -** the old.* values are rebased using the new.* values in the remote -** change. Or, if the resolution is REPLACE, then the change is copied -** into the rebased changeset with updates to columns also updated by -** the conflicting remote UPDATE removed. If this means no columns would -** be updated, the change is omitted. -**
          -** -** A local change may be rebased against multiple remote changes -** simultaneously. If a single key is modified by multiple remote -** changesets, they are combined as follows before the local changeset -** is rebased: -** -**
            -**
          • If there has been one or more REPLACE resolutions on a -** key, it is rebased according to a REPLACE. -** -**
          • If there have been no REPLACE resolutions on a key, then -** the local changeset is rebased according to the most recent -** of the OMIT resolutions. -**
          -** -** Note that conflict resolutions from multiple remote changesets are -** combined on a per-field basis, not per-row. This means that in the -** case of multiple remote UPDATE operations, some fields of a single -** local change may be rebased for REPLACE while others are rebased for -** OMIT. -** -** In order to rebase a local changeset, the remote changeset must first -** be applied to the local database using sqlite3changeset_apply_v2() and -** the buffer of rebase information captured. Then: -** -**
            -**
          1. An sqlite3_rebaser object is created by calling -** sqlite3rebaser_create(). -**
          2. The new object is configured with the rebase buffer obtained from -** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). -** If the local changeset is to be rebased against multiple remote -** changesets, then sqlite3rebaser_configure() should be called -** multiple times, in the same order that the multiple -** sqlite3changeset_apply_v2() calls were made. -**
          3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). -**
          4. The sqlite3_rebaser object is deleted by calling -** sqlite3rebaser_delete(). -**
          -*/ -typedef struct sqlite3_rebaser sqlite3_rebaser; - -/* -** CAPI3REF: Create a changeset rebaser object. -** EXPERIMENTAL -** -** Allocate a new changeset rebaser object. If successful, set (*ppNew) to -** point to the new object and return SQLITE_OK. Otherwise, if an error -** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) -** to NULL. -*/ -SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); - -/* -** CAPI3REF: Configure a changeset rebaser object. -** EXPERIMENTAL -** -** Configure the changeset rebaser object to rebase changesets according -** to the conflict resolutions described by buffer pRebase (size nRebase -** bytes), which must have been obtained from a previous call to -** sqlite3changeset_apply_v2(). -*/ -SQLITE_API int sqlite3rebaser_configure( - sqlite3_rebaser*, - int nRebase, const void *pRebase -); - -/* -** CAPI3REF: Rebase a changeset -** EXPERIMENTAL -** -** Argument pIn must point to a buffer containing a changeset nIn bytes -** in size. This function allocates and populates a buffer with a copy -** of the changeset rebased according to the configuration of the -** rebaser object passed as the first argument. If successful, (*ppOut) -** is set to point to the new buffer containing the rebased changeset and -** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the -** responsibility of the caller to eventually free the new buffer using -** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) -** are set to zero and an SQLite error code returned. -*/ -SQLITE_API int sqlite3rebaser_rebase( - sqlite3_rebaser*, - int nIn, const void *pIn, - int *pnOut, void **ppOut -); - -/* -** CAPI3REF: Delete a changeset rebaser object. -** EXPERIMENTAL -** -** Delete the changeset rebaser object and all associated resources. There -** should be one call to this function for each successful invocation -** of sqlite3rebaser_create(). -*/ -SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); - /* ** CAPI3REF: Streaming Versions of API functions. ** -** The six streaming API xxx_strm() functions serve similar purposes to the +** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** ** -**
          Streaming functionNon-streaming equivalent
          sqlite3changeset_apply_strm[sqlite3changeset_apply] -**
          sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] -**
          sqlite3changeset_concat_strm[sqlite3changeset_concat] -**
          sqlite3changeset_invert_strm[sqlite3changeset_invert] -**
          sqlite3changeset_start_strm[sqlite3changeset_start] -**
          sqlite3session_changeset_strm[sqlite3session_changeset] -**
          sqlite3session_patchset_strm[sqlite3session_patchset] +**
          sqlite3changeset_apply_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] **
          ** ** Non-streaming functions that accept changesets (or patchsets) as input -** require that the entire changeset be stored in a single buffer in memory. -** Similarly, those that return a changeset or patchset do so by returning -** a pointer to a single large buffer allocated using sqlite3_malloc(). -** Normally this is convenient. However, if an application running in a +** require that the entire changeset be stored in a single buffer in memory. +** Similarly, those that return a changeset or patchset do so by returning +** a pointer to a single large buffer allocated using sqlite3_malloc(). +** Normally this is convenient. However, if an application running in a ** low-memory environment is required to handle very large changesets, the ** large contiguous memory allocations required can become onerous. ** ** In order to avoid this problem, instead of a single large buffer, input ** is passed to a streaming API functions by way of a callback function that @@ -12760,24 +9993,24 @@ **   int (*xInput)(void *pIn, void *pData, int *pnData), **   void *pIn, ** ** ** Each time the xInput callback is invoked by the sessions module, the first -** argument passed is a copy of the supplied pIn context pointer. The second -** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no -** error occurs the xInput method should copy up to (*pnData) bytes of data -** into the buffer and set (*pnData) to the actual number of bytes copied -** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) -** should be set to zero to indicate this. Or, if an error occurs, an SQLite +** argument passed is a copy of the supplied pIn context pointer. The second +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no +** error occurs the xInput method should copy up to (*pnData) bytes of data +** into the buffer and set (*pnData) to the actual number of bytes copied +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) +** should be set to zero to indicate this. Or, if an error occurs, an SQLite ** error code should be returned. In all cases, if an xInput callback returns ** an error, all processing is abandoned and the streaming API function ** returns a copy of the error code to the caller. ** ** In the case of sqlite3changeset_start_strm(), the xInput callback may be ** invoked by the sessions module at any point during the lifetime of the ** iterator. If such an xInput callback returns an error, the iterator enters -** an error state, whereby all subsequent calls to iterator functions +** an error state, whereby all subsequent calls to iterator functions ** immediately fail with the same error code as returned by xInput. ** ** Similarly, streaming API functions that return changesets (or patchsets) ** return them in chunks by way of a callback function instead of via a ** pointer to a single large buffer. In this case, a pair of parameters such @@ -12803,11 +10036,11 @@ ** supplied data, it should return SQLITE_OK to indicate success. Otherwise, ** it should return some other SQLite error code. In this case processing ** is immediately abandoned and the streaming API function returns a copy ** of the xOutput error code to the application. ** -** The sessions module never invokes an xOutput callback with the third +** The sessions module never invokes an xOutput callback with the third ** parameter set to a value less than or equal to zero. Other than this, ** no guarantees are made as to the size of the chunks of data returned. */ SQLITE_API int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -12822,27 +10055,10 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); -SQLITE_API int sqlite3changeset_apply_v2_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, @@ -12858,16 +10074,10 @@ SQLITE_API int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); -SQLITE_API int sqlite3changeset_start_v2_strm( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int flags -); SQLITE_API int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); @@ -12874,65 +10084,19 @@ SQLITE_API int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, +SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); -SQLITE_API int sqlite3rebaser_rebase_strm( - sqlite3_rebaser *pRebaser, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut -); - -/* -** CAPI3REF: Configure global parameters -** -** The sqlite3session_config() interface is used to make global configuration -** changes to the sessions module in order to tune it to the specific needs -** of the application. -** -** The sqlite3session_config() interface is not threadsafe. If it is invoked -** while any other thread is inside any other sessions method then the -** results are undefined. Furthermore, if it is invoked after any sessions -** related objects have been created, the results are also undefined. -** -** The first argument to the sqlite3session_config() function must be one -** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The -** interpretation of the (void*) value passed as the second parameter and -** the effect of calling this function depends on the value of the first -** parameter. -** -**
          -**
          SQLITE_SESSION_CONFIG_STRMSIZE
          -** By default, the sessions module streaming interfaces attempt to input -** and output data in approximately 1 KiB chunks. This operand may be used -** to set and query the value of this configuration setting. The pointer -** passed as the second argument must point to a value of type (int). -** If this value is greater than 0, it is used as the new streaming data -** chunk size for both input and output. Before returning, the (int) value -** pointed to by pArg is set to the final value of the streaming interface -** chunk size. -**
          -** -** This function returns SQLITE_OK if successful, or an SQLite error code -** otherwise. -*/ -SQLITE_API int sqlite3session_config(int op, void *pArg); - -/* -** CAPI3REF: Values for sqlite3session_config(). -*/ -#define SQLITE_SESSION_CONFIG_STRMSIZE 1 + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus @@ -12953,11 +10117,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** -** Interfaces to extend FTS5. Using the interfaces defined in this file, +** Interfaces to extend FTS5. Using the interfaces defined in this file, ** FTS5 may be extended with: ** ** * custom tokenizers, and ** * custom auxiliary functions. */ @@ -12997,23 +10161,23 @@ /* ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): -** Return a copy of the pUserData pointer passed to the xCreateFunction() -** API when the extension function was registered. +** Return a copy of the context pointer the extension function was +** registered with. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken ** to the total number of tokens in the FTS5 table. Or, if iCol is ** non-negative but less than the number of columns in the table, return -** the total number of tokens in column iCol, considering all rows in +** the total number of tokens in column iCol, considering all rows in ** the FTS5 table. ** ** If parameter iCol is greater than or equal to the number of columns ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is +** an OOM condition or IO error), an appropriate SQLite error code is ** returned. ** ** xColumnCount(pFts): ** Return the number of columns in the table. ** @@ -13023,60 +10187,58 @@ ** non-negative but less than the number of columns in the table, set ** *pnToken to the number of tokens in column iCol of the current row. ** ** If parameter iCol is greater than or equal to the number of columns ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is +** an OOM condition or IO error), an appropriate SQLite error code is ** returned. ** ** This function may be quite inefficient if used with an FTS5 table ** created with the "columnsize=0" option. ** ** xColumnText: -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the text of column iCol of -** the current document. If successful, (*pz) is set to point to a buffer +** This function attempts to retrieve the text of column iCol of the +** current document. If successful, (*pz) is set to point to a buffer ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values ** of (*pz) and (*pn) are undefined. ** ** xPhraseCount: ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: -** If parameter iCol is less than zero, or greater than or equal to the -** number of phrases in the current query, as returned by xPhraseCount, -** 0 is returned. Otherwise, this function returns the number of tokens in -** phrase iPhrase of the query. Phrases are numbered starting from zero. +** Returns the number of tokens in phrase iPhrase of the query. Phrases +** are numbered starting from zero. ** ** xInstCount: ** Set *pnInst to the total number of occurrences of all phrases within ** the query within the current row. Return SQLITE_OK if successful, or ** an error code (i.e. SQLITE_NOMEM) if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option ** (i.e. if it is a contentless table), then this API always returns 0. ** ** xInst: ** Query for the details of phrase match iIdx within the current row. ** Phrase matches are numbered starting from zero, so the iIdx argument ** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). If iIdx is less than zero or greater than -** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. +** output by xInstCount(). ** -** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol +** Usually, output parameter *piPhrase is set to the phrase number, *piCol ** to the column in which it occurs and *piOff the token offset of the -** first token of the phrase. SQLITE_OK is returned if successful, or an -** error code (i.e. SQLITE_NOMEM) if an error occurs. +** first token of the phrase. The exception is if the table was created +** with the offsets=0 option specified. In this case *piOff is always +** set to -1. +** +** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM) +** if an error occurs. ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. +** "detail=none" or "detail=column" option. ** ** xRowid: ** Returns the rowid of the current row. ** ** xTokenize: @@ -13088,21 +10250,17 @@ ** ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the ** current query is executed. Any column filter that applies to -** phrase iPhrase of the current query is included in $p. For each -** row visited, the callback function passed as the fourth argument -** is invoked. The context and API objects passed to the callback +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback ** function may be used to access the properties of each matched row. -** Invoking Api.xUserData() returns a copy of the pointer passed as +** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** -** If parameter iPhrase is less than zero, or greater than or equal to -** the number of phrases in the query, as returned by xPhraseCount(), -** this function returns SQLITE_RANGE. -** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. ** Otherwise, the error code is propagated upwards. ** @@ -13111,18 +10269,18 @@ ** the callback, an SQLite error code is returned. ** ** ** xSetAuxdata(pFts5, pAux, xDelete) ** -** Save the pointer passed as the second argument as the extension function's +** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of -** the same MATCH query using the xGetAuxdata() API. +** of the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for -** each FTS query (MATCH expression). If the extension function is invoked -** more than once for a single FTS query, then all invocations share a +** each FTS query (MATCH expression). If the extension function is invoked +** more than once for a single FTS query, then all invocations share a ** single auxiliary data context. ** ** If there is already an auxiliary data pointer when this function is ** invoked, then it is replaced by the new pointer. If an xDelete callback ** was specified along with the original pointer, it is invoked at this @@ -13129,19 +10287,19 @@ ** point. ** ** The xDelete callback, if one is specified, is also invoked on the ** auxiliary data pointer after the FTS5 query has finished. ** -** If an error (e.g. an OOM condition) occurs within this function, +** If an error (e.g. an OOM condition) occurs within this function, an ** the auxiliary data is set to NULL and an error code returned. If the ** xDelete parameter was not NULL, it is invoked on the auxiliary data ** pointer before returning. ** ** ** xGetAuxdata(pFts5, bClear) ** -** Returns the current auxiliary data pointer for the fts5 extension +** Returns the current auxiliary data pointer for the fts5 extension ** function. See the xSetAuxdata() method for details. ** ** If the bClear argument is non-zero, then the auxiliary data is cleared ** (set to NULL) before this function returns. In this case the xDelete, ** if any, is not invoked. @@ -13157,11 +10315,11 @@ ** xPhraseFirst() ** This function is used, along with type Fts5PhraseIter and the xPhraseNext ** method, to iterate through all instances of a single query phrase within ** the current row. This is the same information as is accessible via the ** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient -** to use, this API may be faster under some circumstances. To iterate +** to use, this API may be faster under some circumstances. To iterate ** through instances of phrase iPhrase, use the following code: ** ** Fts5PhraseIter iter; ** int iCol, iOff; ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); @@ -13175,19 +10333,15 @@ ** modify this structure directly - it should only be used as shown above ** with the xPhraseFirst() and xPhraseNext() API methods (and by ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. If the FTS5 table is created -** with either "detail=none" or "detail=column" and "content=" option +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option ** (i.e. if it is a contentless table), then this API always iterates ** through an empty set (all calls to xPhraseFirst() set iCol to -1). ** -** In all cases, matches are visited in (column ASC, offset ASC) order. -** i.e. all those in column 0, sorted by offset, followed by those in -** column 1, etc. -** ** xPhraseNext() ** See xPhraseFirst above. ** ** xPhraseFirstColumn() ** This function and xPhraseNextColumn() are similar to the xPhraseFirst() @@ -13204,105 +10358,34 @@ ** ){ ** // Column iCol contains at least one instance of phrase iPhrase ** } ** ** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" option. If the FTS5 table is created with either -** "detail=none" "content=" option (i.e. if it is a contentless table), -** then this API always iterates through an empty set (all calls to +** "detail=none" option. If the FTS5 table is created with either +** "detail=none" "content=" option (i.e. if it is a contentless table), +** then this API always iterates through an empty set (all calls to ** xPhraseFirstColumn() set iCol to -1). ** ** The information accessed using this API and its companion ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext ** (or xInst/xInstCount). The chief advantage of this API is that it is ** significantly more efficient than those alternatives when used with -** "detail=column" tables. +** "detail=column" tables. ** ** xPhraseNextColumn() ** See xPhraseFirstColumn above. -** -** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase iPhrase of the current -** query. Before returning, output parameter *ppToken is set to point -** to a buffer containing the requested token, and *pnToken to the -** size of this buffer in bytes. -** -** If iPhrase or iToken are less than zero, or if iPhrase is greater than -** or equal to the number of phrases in the query as reported by -** xPhraseCount(), or if iToken is equal to or greater than the number of -** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken - are both zeroed. -** -** The output text is not a copy of the query text that specified the -** token. It is the output of the tokenizer module. For tokendata=1 -** tables, this includes any embedded 0x00 and trailing data. -** -** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken) -** This is used to access token iToken of phrase hit iIdx within the -** current row. If iIdx is less than zero or greater than or equal to the -** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise, -** output variable (*ppToken) is set to point to a buffer containing the -** matching document token, and (*pnToken) to the size of that buffer in -** bytes. -** -** The output text is not a copy of the document text that was tokenized. -** It is the output of the tokenizer module. For tokendata=1 tables, this -** includes any embedded 0x00 and trailing data. -** -** This API may be slow in some cases if the token identified by parameters -** iIdx and iToken matched a prefix token in the query. In most cases, the -** first call to this API for each prefix token in the query is forced -** to scan the portion of the full-text index that matches the prefix -** token to collect the extra data required by this API. If the prefix -** token matches a large number of token instances in the document set, -** this may be a performance problem. -** -** If the user knows in advance that a query may use this API for a -** prefix token, FTS5 may be configured to collect all required data as part -** of the initial querying of the full-text index, avoiding the second scan -** entirely. This also causes prefix queries that do not use this API to -** run more slowly and use more memory. FTS5 may be configured in this way -** either on a per-table basis using the [FTS5 insttoken | 'insttoken'] -** option, or on a per-query basis using the -** [fts5_insttoken | fts5_insttoken()] user function. -** -** This API can be quite slow if used with an FTS5 table created with the -** "detail=none" or "detail=column" option. -** -** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale) -** If parameter iCol is less than zero, or greater than or equal to the -** number of columns in the table, SQLITE_RANGE is returned. -** -** Otherwise, this function attempts to retrieve the locale associated -** with column iCol of the current row. Usually, there is no associated -** locale, and output parameters (*pzLocale) and (*pnLocale) are set -** to NULL and 0, respectively. However, if the fts5_locale() function -** was used to associate a locale with the value when it was inserted -** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated -** buffer containing the name of the locale in utf-8 encoding. (*pnLocale) -** is set to the size in bytes of the buffer, not including the -** nul-terminator. -** -** If successful, SQLITE_OK is returned. Or, if an error occurs, an -** SQLite error code is returned. The final value of the output parameters -** is undefined in this case. -** -** xTokenize_v2: -** Tokenize text using the tokenizer belonging to the FTS5 table. This -** API is the same as the xTokenize() API, except that it allows a tokenizer -** locale to be specified. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 4 */ + int iVersion; /* Currently always set to 3 */ void *(*xUserData)(Fts5Context*); int (*xColumnCount)(Fts5Context*); int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); - int (*xTokenize)(Fts5Context*, + int (*xTokenize)(Fts5Context*, const char *pText, int nText, /* Text to tokenize */ void *pCtx, /* Context passed to xToken() */ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ ); @@ -13325,114 +10408,91 @@ int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); - - /* Below this point are iVersion>=3 only */ - int (*xQueryToken)(Fts5Context*, - int iPhrase, int iToken, - const char **ppToken, int *pnToken - ); - int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*); - - /* Below this point are iVersion>=4 only */ - int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xTokenize_v2)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - const char *pLocale, int nLocale, /* Locale to pass to tokenizer */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); }; -/* +/* ** CUSTOM AUXILIARY FUNCTIONS *************************************************************************/ /************************************************************************* ** CUSTOM TOKENIZERS ** -** Applications may also register custom tokenizer types. A tokenizer -** is registered by providing fts5 with a populated instance of the +** Applications may also register custom tokenizer types. A tokenizer +** is registered by providing fts5 with a populated instance of the ** following structure. All structure methods must be defined, setting ** any member of the fts5_tokenizer struct to NULL leads to undefined ** behaviour. The structure methods are expected to function as follows: ** ** xCreate: ** This function is used to allocate and initialize a tokenizer instance. ** A tokenizer instance is required to actually tokenize text. ** ** The first argument passed to this function is a copy of the (void*) -** pointer provided by the application when the fts5_tokenizer_v2 object -** was registered with FTS5 (the third argument to xCreateTokenizer()). +** pointer provided by the application when the fts5_tokenizer object +** was registered with FTS5 (the third argument to xCreateTokenizer()). ** The second and third arguments are an array of nul-terminated strings ** containing the tokenizer arguments, if any, specified following the ** tokenizer name as part of the CREATE VIRTUAL TABLE statement used ** to create the FTS5 table. ** -** The final argument is an output variable. If successful, (*ppOut) +** The final argument is an output variable. If successful, (*ppOut) ** should be set to point to the new tokenizer handle and SQLITE_OK ** returned. If an error occurs, some value other than SQLITE_OK should -** be returned. In this case, fts5 assumes that the final value of *ppOut +** be returned. In this case, fts5 assumes that the final value of *ppOut ** is undefined. ** ** xDelete: ** This function is invoked to delete a tokenizer handle previously ** allocated using xCreate(). Fts5 guarantees that this function will ** be invoked exactly once for each successful call to xCreate(). ** ** xTokenize: -** This function is expected to tokenize the nText byte string indicated +** This function is expected to tokenize the nText byte string indicated ** by argument pText. pText may or may not be nul-terminated. The first ** argument passed to this function is a pointer to an Fts5Tokenizer object ** returned by an earlier call to xCreate(). ** -** The third argument indicates the reason that FTS5 is requesting +** The second argument indicates the reason that FTS5 is requesting ** tokenization of the supplied text. This is always one of the following ** four values: ** **
          • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into ** or removed from the FTS table. The tokenizer is being invoked to ** determine the set of tokens to add to (or delete from) the ** FTS index. ** -**
          • FTS5_TOKENIZE_QUERY - A MATCH query is being executed -** against the FTS index. The tokenizer is being called to tokenize +**
          • FTS5_TOKENIZE_QUERY - A MATCH query is being executed +** against the FTS index. The tokenizer is being called to tokenize ** a bareword or quoted string specified as part of the query. ** **
          • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as ** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is ** followed by a "*" character, indicating that the last token ** returned by the tokenizer will be treated as a token prefix. ** -**
          • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to +**
          • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to ** satisfy an fts5_api.xTokenize() request made by an auxiliary ** function. Or an fts5_api.xColumnSize() request made by the same -** on a columnsize=0 database. +** on a columnsize=0 database. **
          ** -** The sixth and seventh arguments passed to xTokenize() - pLocale and -** nLocale - are a pointer to a buffer containing the locale to use for -** tokenization (e.g. "en_US") and its size in bytes, respectively. The -** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in -** which case nLocale is always 0) to indicate that the tokenizer should -** use its default locale. -** ** For each token in the input string, the supplied callback xToken() must ** be invoked. The first argument to it should be a copy of the pointer ** passed as the second argument to xTokenize(). The third and fourth ** arguments are a pointer to a buffer containing the token text, and the ** size of the token in bytes. The 4th and 5th arguments are the byte offsets ** of the first byte of and first byte immediately following the text from ** which the token is derived within the input. ** ** The second argument passed to the xToken() callback ("tflags") should -** normally be set to 0. The exception is if the tokenizer supports +** normally be set to 0. The exception is if the tokenizer supports ** synonyms. In this case see the discussion below for details. ** -** FTS5 assumes the xToken() callback is invoked for each token in the +** FTS5 assumes the xToken() callback is invoked for each token in the ** order that they occur within the input text. ** ** If an xToken() callback returns any value other than SQLITE_OK, then ** the tokenization should be abandoned and the xTokenize() method should ** immediately return a copy of the xToken() return value. Or, if the @@ -13439,86 +10499,62 @@ ** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, ** if an error occurs with the xTokenize() implementation itself, it ** may abandon the tokenization and return any error code other than ** SQLITE_OK or SQLITE_DONE. ** -** If the tokenizer is registered using an fts5_tokenizer_v2 object, -** then the xTokenize() method has two additional arguments - pLocale -** and nLocale. These specify the locale that the tokenizer should use -** for the current request. If pLocale and nLocale are both 0, then the -** tokenizer should use its default locale. Otherwise, pLocale points to -** an nLocale byte buffer containing the name of the locale to use as utf-8 -** text. pLocale is not nul-terminated. -** -** FTS5_TOKENIZER -** -** There is also an fts5_tokenizer object. This is an older, deprecated, -** version of fts5_tokenizer_v2. It is similar except that: -** -**
            -**
          • There is no "iVersion" field, and -**
          • The xTokenize() method does not take a locale argument. -**
          -** -** Legacy fts5_tokenizer tokenizers must be registered using the -** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2(). -** -** Tokenizer implementations registered using either API may be retrieved -** using both xFindTokenizer() and xFindTokenizer_v2(). -** ** SYNONYM SUPPORT ** ** Custom tokenizers may also support synonyms. Consider a case in which a -** user wishes to query for a phrase such as "first place". Using the +** user wishes to query for a phrase such as "first place". Using the ** built-in tokenizers, the FTS5 query 'first + place' will match instances ** of "first place" within the document set, but not alternative forms ** such as "1st place". In some applications, it would be better to match ** all instances of "first place" or "1st place" regardless of which form ** the user specified in the MATCH query text. ** ** There are several ways to approach this in FTS5: ** -**
          1. By mapping all synonyms to a single token. In this case, using -** the above example, this means that the tokenizer returns the +**
            1. By mapping all synonyms to a single token. In this case, the +** In the above example, this means that the tokenizer returns the ** same token for inputs "first" and "1st". Say that token is in ** fact "first", so that when the user inserts the document "I won ** 1st place" entries are added to the index for tokens "i", "won", ** "first" and "place". If the user then queries for '1st + place', ** the tokenizer substitutes "first" for "1st" and the query works ** as expected. ** -**
            2. By querying the index for all synonyms of each query term -** separately. In this case, when tokenizing query text, the -** tokenizer may provide multiple synonyms for a single term -** within the document. FTS5 then queries the index for each -** synonym individually. For example, faced with the query: +**
            3. By adding multiple synonyms for a single term to the FTS index. +** In this case, when tokenizing query text, the tokenizer may +** provide multiple synonyms for a single term within the document. +** FTS5 then queries the index for each synonym individually. For +** example, faced with the query: ** ** ** ... MATCH 'first place' ** ** the tokenizer offers both "1st" and "first" as synonyms for the -** first token in the MATCH query and FTS5 effectively runs a query +** first token in the MATCH query and FTS5 effectively runs a query ** similar to: ** ** ** ... MATCH '(first OR 1st) place' ** ** except that, for the purposes of auxiliary functions, the query -** still appears to contain just two phrases - "(first OR 1st)" +** still appears to contain just two phrases - "(first OR 1st)" ** being treated as a single phrase. ** **
            4. By adding multiple synonyms for a single term to the FTS index. ** Using this method, when tokenizing document text, the tokenizer -** provides multiple synonyms for each token. So that when a +** provides multiple synonyms for each token. So that when a ** document such as "I won first place" is tokenized, entries are ** added to the FTS index for "i", "won", "first", "1st" and ** "place". ** ** This way, even if the tokenizer does not provide synonyms -** when tokenizing query text (it should not - to do so would be -** inefficient), it doesn't matter if the user queries for -** 'first + place' or '1st + place', as there are entries in the +** when tokenizing query text (it should not - to do would be +** inefficient), it doesn't matter if the user queries for +** 'first + place' or '1st + place', as there are entires in the ** FTS index corresponding to both forms of the first token. **
            ** ** Whether it is parsing document or query text, any call to xToken that ** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit @@ -13534,58 +10570,55 @@ ** xToken(pCtx, 0, "place", 5, 12, 17); ** ** ** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time ** xToken() is called. Multiple synonyms may be specified for a single token -** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. +** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. ** There is no limit to the number of synonyms that may be provided for a ** single token. ** -** In many cases, method (1) above is the best approach. It does not add +** In many cases, method (1) above is the best approach. It does not add ** extra data to the FTS index or require FTS5 to query for multiple terms, ** so it is efficient in terms of disk space and query speed. However, it ** does not support prefix queries very well. If, as suggested above, the -** token "first" is substituted for "1st" by the tokenizer, then the query: +** token "first" is subsituted for "1st" by the tokenizer, then the query: ** ** ** ... MATCH '1s*' ** ** will not match documents that contain the token "1st" (as the tokenizer ** will probably not map "1s" to any prefix of "first"). ** -** For full prefix support, method (3) may be preferred. In this case, +** For full prefix support, method (3) may be preferred. In this case, ** because the index contains entries for both "first" and "1st", prefix ** queries such as 'fi*' or '1s*' will match correctly. However, because ** extra entries are added to the FTS index, this method uses more space ** within the database. ** ** Method (2) offers a midpoint between (1) and (3). Using this method, -** a query such as '1s*' will match documents that contain the literal +** a query such as '1s*' will match documents that contain the literal ** token "1st", but not "first" (assuming the tokenizer is not able to ** provide synonyms for prefixes). However, a non-prefix query like '1st' ** will match against "1st" and "first". This method does not require -** extra disk space, as no extra entries are added to the FTS index. +** extra disk space, as no extra entries are added to the FTS index. ** On the other hand, it may require more CPU cycles to run MATCH queries, ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (3)) or query -** text (method (2)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (2)) or query +** text (method (3)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; -typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2; -struct fts5_tokenizer_v2 { - int iVersion; /* Currently always 2 */ - +typedef struct fts5_tokenizer fts5_tokenizer; +struct fts5_tokenizer { int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, + int (*xTokenize)(Fts5Tokenizer*, void *pCtx, int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - const char *pLocale, int nLocale, + const char *pText, int nText, int (*xToken)( void *pCtx, /* Copy of 2nd argument to xTokenize() */ int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Pointer to buffer containing token */ int nToken, /* Size of token in bytes */ @@ -13592,35 +10625,10 @@ int iStart, /* Byte offset of token within input text */ int iEnd /* Byte offset of end of token within input text */ ) ); }; - -/* -** New code should use the fts5_tokenizer_v2 type to define tokenizer -** implementations. The following type is included for legacy applications -** that still use it. -*/ -typedef struct fts5_tokenizer fts5_tokenizer; -struct fts5_tokenizer { - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); -}; - /* Flags that may be passed as the third argument to xTokenize() */ #define FTS5_TOKENIZE_QUERY 0x0001 #define FTS5_TOKENIZE_PREFIX 0x0002 #define FTS5_TOKENIZE_DOCUMENT 0x0004 @@ -13637,56 +10645,37 @@ /************************************************************************* ** FTS5 EXTENSION REGISTRATION API */ typedef struct fts5_api fts5_api; struct fts5_api { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ /* Create a new tokenizer */ int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pUserData, + void *pContext, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); /* Find an existing tokenizer */ int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppUserData, + void **ppContext, fts5_tokenizer *pTokenizer ); /* Create a new auxiliary function */ int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pUserData, + void *pContext, fts5_extension_function xFunction, void (*xDestroy)(void*) ); - - /* APIs below this point are only available if iVersion>=3 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void *pUserData, - fts5_tokenizer_v2 *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer_v2)( - fts5_api *pApi, - const char *zName, - void **ppUserData, - fts5_tokenizer_v2 **ppTokenizer - ); }; /* ** END OF REGISTRATION API *************************************************************************/ @@ -13696,6 +10685,5 @@ #endif #endif /* _FTS5_H */ /******** End of fts5.h *********/ -#endif /* SQLITE3_H */ Index: src/sqllogictest.c ================================================================== --- src/sqllogictest.c +++ src/sqllogictest.c @@ -1,24 +1,25 @@ /* ** Copyright (c) 2008 D. Richard Hipp ** -** This program is free software. As far as the author is -** concerned, you can redistribute it and/or modify the code -** as you see fit. No attribution is required. Use whichever -** of the following license terms best applies to your situation. -** -** 1. GNU General Public License -** 2. BSD License -** 3. MIT License -** 4. CC0 License +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public +** License version 2 as published by the Free Software Foundation. ** ** This program is distributed in the hope that it will be useful, -** but without any warranty; without even the implied warranty of -** merchantability or fitness for a particular purpose. +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. ** +** You should have received a copy of the GNU General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** ** Author contact information: -** drh@sqlite.org +** drh@hwaci.com +** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This main driver for the sqllogictest program. */ @@ -670,24 +671,15 @@ ** from the query. Report an error if any differences are found. */ if( hashThreshold==0 || nResult<=hashThreshold ){ for(i=0; i col3 AND ((53 > col0) OR 54 > col0))) ---- query I rowsort label-4220 SELECT pk FROM tab4 WHERE ((col4 > 60.6 AND col3 < 32 AND ((col0 < 53) OR col0 < 54))) -----