From d805a3059c025e1659c00724251eaabe3665648b Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 10:21:55 -0600 Subject: [PATCH 1/8] update to new release patterns --- tasks/custom.rake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/custom.rake b/tasks/custom.rake index b770dbf..43f02a0 100644 --- a/tasks/custom.rake +++ b/tasks/custom.rake @@ -61,16 +61,16 @@ namespace :util do require 'uri' require 'open-uri' - asset_regex = /\Alibsql-amalgamation-(\d+\.\d+\.\d+)\.tar\.gz\Z/ + asset_regex = /\Asource\.tar\.gz\Z/ asset = nil require 'debug' if args[:version] then - all_releases_uri = "https://api.github.com/repos/libsql/libsql/releases" + all_releases_uri = "https://api.github.com/repos/tursodatabase/libsql/releases" all_releases_json = ::URI.parse(all_releases_uri).read all_releases_parsed = JSON.parse(all_releases_json) - version_release = all_releases_parsed.find { |p| p['tag_name'] == "libsql-#{args[:version]}" } + version_release = all_releases_parsed.find { |p| p['tag_name'] == "libsql-server-#{args[:version]}" } if version_release then assets_url = version_release['assets_url'] assets_json = ::URI.parse(assets_url).read @@ -87,7 +87,7 @@ namespace :util do abort msg.join("\n") end else - latest_uri = "https://api.github.com/repos/libsql/libsql/releases/latest" + latest_uri = "https://api.github.com/repos/tursodatabase/libsql/releases/latest" latest_json = ::URI.parse(latest_uri).read latest_parsed = JSON.parse(latest_json) asset = latest_parsed['assets'].find { |a| a['name'] =~ asset_regex } From 1d1e70f17756fb34fda9538790404d7d240be718 Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 10:23:44 -0600 Subject: [PATCH 2/8] update project management tooling --- .ruby-version | 2 +- .semaphore/ensure-bundle.sh | 18 +++++++ .semaphore/ensure-ruby-version.sh | 14 ++++++ .semaphore/semaphore.yml | 44 +++++++---------- Gemfile.lock | 2 +- Rakefile | 8 ++++ tasks/default.rake | 2 +- tasks/extension.rake | 7 +-- tasks/semaphore.rake | 79 +++++++++++++++++++++++++++++++ tasks/this.rb | 3 ++ 10 files changed, 144 insertions(+), 35 deletions(-) create mode 100644 .semaphore/ensure-bundle.sh create mode 100644 .semaphore/ensure-ruby-version.sh create mode 100644 tasks/semaphore.rake diff --git a/.ruby-version b/.ruby-version index be94e6f..15a2799 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.3.0 diff --git a/.semaphore/ensure-bundle.sh b/.semaphore/ensure-bundle.sh new file mode 100644 index 0000000..475c3a2 --- /dev/null +++ b/.semaphore/ensure-bundle.sh @@ -0,0 +1,18 @@ +# Ensure that the bundle is installed and cached +# + +bundle config set --local deployment true +bundle config set --local path vendor/bundle +gem update --no-doc bundler + +gemfile_checksum=$(checksum Gemfile.lock) +cache_key="${SEMAPHORE_AGENT_MACHINE_OS_IMAGE}-${RUBY_VERSION}-${gemfile_checksum}" + +if cache has_key "${cache_key}"; then + echo "Bundle for ${RUBY_VERSION} and Gemfile.lock found in cache" + cache restore "${cache_key}" +else + echo "Caching Bundle for ${RUBY_VERSION} and Gemfile.lock" + bundle install + cache store "${cache_key}" vendor/bundle +fi diff --git a/.semaphore/ensure-ruby-version.sh b/.semaphore/ensure-ruby-version.sh new file mode 100644 index 0000000..5d3ce46 --- /dev/null +++ b/.semaphore/ensure-ruby-version.sh @@ -0,0 +1,14 @@ +# Ensure the correct Ruby version is installed and cached +# +cache_key="${SEMAPHORE_AGENT_MACHINE_OS_IMAGE}-${RUBY_VERSION}" + +if cache has_key "${cache_key}"; then + echo "Ruby ${RUBY_VERSION} found in cache" + cache restore "${cache_key}" + sem-version ruby "${RUBY_VERSION}" -f +else + echo "Installing Ruby $RUBY_VERSION" + sem-version ruby "${RUBY_VERSION}" -f + cache store "${cache_key}" "${HOME}/.rbenv/versions/${RUBY_VERSION}" +fi + diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 980da62..75643fd 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -1,9 +1,14 @@ version: v1.0 -name: libsql-ruby +name: libsql agent: machine: type: e1-standard-2 os_image: ubuntu2004 + +auto_cancel: + running: + when: "branch != 'main'" + blocks: - name: Run Linux Tests dependencies: [] @@ -24,13 +29,11 @@ blocks: values: - 3.0.6 - 3.1.4 - - 3.2.2 + - 3.2.3 + - 3.3.0 commands: - - sem-version ruby ${RUBY_VERSION} -f - - bundle config set --local deployment true - - bundle config set --local path vendor/bundle - - gem update --no-doc bundler - - bundle install + - source .semaphore/ensure-ruby-version.sh + - source .semaphore/ensure-bundle.sh - mkdir -p tmp/test-results/ - export TEST_RESULTS_FILE=tmp/test-results/${RUBY_VERSION}.xml - bundle exec rake test @@ -41,7 +44,7 @@ blocks: agent: machine: type: a1-standard-4 - os_image: macos-xcode13 + os_image: macos-xcode14 prologue: commands: - checkout @@ -53,13 +56,11 @@ blocks: values: - 3.0.6 - 3.1.4 - - 3.2.2 + - 3.2.3 + - 3.3.0 commands: - - sem-version ruby ${RUBY_VERSION} -f - - bundle config set --local deployment true - - bundle config set --local path vendor/bundle - - gem update --no-doc bundler - - bundle install + - source .semaphore/ensure-ruby-version.sh + - source .semaphore/ensure-bundle.sh - mkdir -p tmp/test-results/ - export TEST_RESULTS_FILE=tmp/test-results/${RUBY_VERSION}.xml - bundle exec rake test @@ -68,16 +69,13 @@ blocks: dependencies: - Run Linux Tests task: - env_vars: - - name: RUBY_CC_VERSION - value: 3.0.0:3.1.0:3.2.0 agent: machine: type: e1-standard-2 os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.3.0-mri-x86-mingw32" + image: "larskanis/rake-compiler-dock-mri-x86-mingw32:1.2.2" jobs: - name: build x86-mingw32 gem commands: @@ -91,16 +89,13 @@ blocks: dependencies: - Run Linux Tests task: - env_vars: - - name: RUBY_CC_VERSION - value: 3.0.0 agent: machine: type: e1-standard-2 os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.3.0-mri-x64-mingw32" + image: "larskanis/rake-compiler-dock-mri-x64-mingw32:1.2.2" jobs: - name: build x64-mingw32 commands: @@ -114,16 +109,13 @@ blocks: dependencies: - Run Linux Tests task: - env_vars: - - name: RUBY_CC_VERSION - value: 3.0.0:3.1.0:3.2.0 agent: machine: type: e1-standard-2 os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.3.0-mri-x64-mingw-ucrt" + image: "larskanis/rake-compiler-dock-mri-x64-mingw-ucrt:1.2.2" jobs: - name: build x64-mingw-ucrt commands: diff --git a/Gemfile.lock b/Gemfile.lock index 7c3b6e1..2fb111c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,7 +50,7 @@ GEM simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - stringio (3.0.6) + stringio (3.1.0) PLATFORMS arm64-darwin-21 diff --git a/Rakefile b/Rakefile index cdc1f0e..30960d4 100644 --- a/Rakefile +++ b/Rakefile @@ -23,6 +23,14 @@ This.ruby_gemspec do |spec| spec.license = "BSD-3-Clause" end +This.cross_platforms = %w[ + x86-mingw32 + x64-mingw-ucrt + x64-mingw32 +] + + load 'tasks/default.rake' load 'tasks/extension.rake' load 'tasks/custom.rake' +load 'tasks/semaphore.rake' diff --git a/tasks/default.rake b/tasks/default.rake index 6c1ce7b..200eeed 100644 --- a/tasks/default.rake +++ b/tasks/default.rake @@ -153,7 +153,7 @@ namespace :fixme do def local_fixme_files local_files = This.manifest.select { |p| p =~ %r|^tasks/| } - local_files << ".semaphore/semaphore.yml" + local_files.concat( Dir.glob( ".semaphore/*" ) ) end def outdated_fixme_files diff --git a/tasks/extension.rake b/tasks/extension.rake index 46bc2bb..aacdc6e 100644 --- a/tasks/extension.rake +++ b/tasks/extension.rake @@ -7,17 +7,12 @@ begin require 'rake/extensiontask' Rake::ExtensionTask.new( This.name ) do |ext| - ext.name = "#{This.name}_ext" ext.ext_dir = File.join( 'ext', This.name, "c" ) ext.lib_dir = File.join( 'lib', This.name ) ext.gem_spec = This.ruby_gemspec ext.cross_compile = true # enable cross compilation (requires cross compile toolchain) - ext.cross_platform = %w[ - x86-mingw32 - x64-mingw-ucrt - x64-mingw32 - ] + ext.cross_platform = This.cross_platforms end task :test_requirements => :compile diff --git a/tasks/semaphore.rake b/tasks/semaphore.rake new file mode 100644 index 0000000..252eeff --- /dev/null +++ b/tasks/semaphore.rake @@ -0,0 +1,79 @@ +require 'yaml' +require 'uri' +require 'open-uri' + +namespace :semaphore do + + def semaphore_config + config_file = File.join(ENV['HOME'], '.sem.yaml') + if File.exist?(config_file) + config = YAML.load_file(config_file) + config.dig('contexts', 'copiousfreetime_semaphoreci_com') + else + nil + end + end + + def auth_token + semaphore_config.dig('auth', 'token') + end + + def semaphore_endpoint + "https://#{semaphore_config['host']}" + end + + def semaphore_api_endpoint + "#{semaphore_endpoint}/api/v1alpha" + end + + def project_meta + @project_meta ||= URI.open("#{semaphore_api_endpoint}/projects/#{This.name}", + "Authorization" => "Token #{auth_token}") do |f| + JSON.parse(f.read) + end + end + + def project_id + project_meta.dig('metadata', 'id') + end + + def artifacts + This.cross_platforms.map do |platform| + name = Gem::NameTuple.new(This.name, This.version, platform) + basename = "#{name.full_name}.gem" + basename + end + end + + desc "Dump semaphore config" + task :config do + puts semaphore_config.to_yaml + end + + desc "Dump semaphore project meta" + task :meta do + puts JSON.pretty_generate(project_meta) + end + + namespace :artifacts do + + desc "List artifacts" + task :list do + puts artifacts + end + + desc "Download artifacts" + task :download do + artifacts.each do |basename| + url = "#{semaphore_endpoint}/projects/#{project_id}/artifacts/#{basename}" + dest = File.join("pkg", basename) + puts "downloading #{url} => #{dest}" + URI.open(url, "Authorization" => "Token #{auth_token}") do |f| + File.open(dest, "wb") do |out| + out.write(f.read) + end + end + end + end + end +end diff --git a/tasks/this.rb b/tasks/this.rb index 73d0824..f05a599 100644 --- a/tasks/this.rb +++ b/tasks/this.rb @@ -21,6 +21,9 @@ class ThisProject # The hash of Gem::Specifications keyed' by platform attr_accessor :gemspecs + # List of cross platforms to build the gem for + attr_accessor :cross_platforms + # Public: Initialize ThisProject # # Yields self From 525be58a69b88a557953ded2a470427c6d9147ff Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 10:23:56 -0600 Subject: [PATCH 3/8] update libsql version --- ext/libsql/c/sqlite3.c | 22115 ++++++++++++++++++++++++++------------- ext/libsql/c/sqlite3.h | 634 +- 2 files changed, 15260 insertions(+), 7489 deletions(-) diff --git a/ext/libsql/c/sqlite3.c b/ext/libsql/c/sqlite3.c index a5e8cf0..9dcbc2c 100644 --- a/ext/libsql/c/sqlite3.c +++ b/ext/libsql/c/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.42.0. By combining all the individual C code files into this +** version 3.44.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 @@ -16,6 +16,64 @@ ** 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 +** 17129ba1ff7f0daf37100ee82d507aef7827 with changes in files: +** +** .fossil-settings/empty-dirs +** .fossil-settings/ignore-glob +** LICENSE.md +** Makefile.in +** README.md +** configure +** configure.ac +** ext/wasm/GNUmakefile +** ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api +** ext/wasm/api/sqlite3-api-oo1.js +** ext/wasm/fiddle.make +** ext/wasm/fiddle/fiddle-worker.js +** ext/wasm/fiddle/fiddle.js +** ext/wasm/fiddle/index.html +** main.mk +** src/alter.c +** src/attach.c +** src/bitvec.c +** src/btree.c +** src/btree.h +** src/build.c +** src/callback.c +** src/func.c +** src/insert.c +** src/loadext.c +** src/main.c +** src/os_unix.c +** src/os_win.c +** src/pager.c +** src/pager.h +** src/parse.y +** src/pcache.h +** src/pragma.c +** src/shell.c.in +** src/sqlite.h.in +** src/sqlite3ext.h +** src/sqliteInt.h +** src/status.c +** src/test2.c +** src/test3.c +** src/test8.c +** src/vdbe.c +** src/vdbeInt.h +** src/vdbeapi.c +** src/vtab.c +** src/wal.c +** src/wal.h +** src/wherecode.c +** test/permutations.test +** test/rowvaluevtab.test +** tool/mkkeywordhash.c +** tool/mksqlite3c.tcl +** tool/mksqlite3h.tcl +** manifest.uuid */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 @@ -50,11 +108,11 @@ ** used on lines of code that actually ** implement parts of coverage testing. ** -** OPTIMIZATION-IF-TRUE - This branch is allowed to alway be false +** OPTIMIZATION-IF-TRUE - This branch is allowed to always be false ** and the correct answer is still obtained, ** though perhaps more slowly. ** -** OPTIMIZATION-IF-FALSE - This branch is allowed to alway be true +** OPTIMIZATION-IF-FALSE - This branch is allowed to always be true ** and the correct answer is still obtained, ** though perhaps more slowly. ** @@ -75,6 +133,12 @@ # define SQLITE_TCLAPI #endif +// NOTICE: libSQL extension: disabled WAL also implies we don't want shared memory via mmap +#ifdef SQLITE_OMIT_WAL +# undef SQLITE_OMIT_SHARED_MEM +# define SQLITE_OMIT_SHARED_MEM 1 +#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 @@ -123,6 +187,10 @@ #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 ************************************************/ @@ -455,11 +523,11 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.42.0" -#define SQLITE_VERSION_NUMBER 3042000 -#define SQLITE_SOURCE_ID "2023-03-11 23:21:21 dc9f025dc43cb8008e7d8d644175d8b2d084e602a1513803c40c513d1e99alt1" +#define SQLITE_VERSION "3.44.0" +#define SQLITE_VERSION_NUMBER 3044000 +#define SQLITE_SOURCE_ID "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad8alt1" -#define LIBSQL_VERSION "0.2.1" +#define LIBSQL_VERSION "0.2.3" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -841,6 +909,7 @@ SQLITE_API int sqlite3_exec( #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)) @@ -1510,7 +1579,7 @@ struct sqlite3_io_methods { ** by clients within the current process, only within other processes. ** **
  • [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the +** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the ** [checksum VFS shim] only. ** **
  • [[SQLITE_FCNTL_RESET_CACHE]] @@ -2459,7 +2528,7 @@ struct sqlite3_mem_methods { ** 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 behaviour. +** 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. ** @@ -2475,28 +2544,28 @@ struct sqlite3_mem_methods { ** compile-time option is not set, then the default maximum is 1073741824. ** */ -#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 /* 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_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 */ @@ -2634,7 +2703,7 @@ struct sqlite3_mem_methods { ** 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 +** override this 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 @@ -2731,7 +2800,7 @@ struct sqlite3_mem_methods { ** ** ** [[SQLITE_DBCONFIG_DQS_DML]] -**
    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 @@ -2740,7 +2809,7 @@ struct sqlite3_mem_methods { **
    ** ** [[SQLITE_DBCONFIG_DQS_DDL]] -**
    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 @@ -2749,7 +2818,7 @@ struct sqlite3_mem_methods { **
    ** ** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] -**
    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 @@ -2769,7 +2838,7 @@ struct sqlite3_mem_methods { **
    ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] -**
    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 @@ -2778,7 +2847,7 @@ struct sqlite3_mem_methods { ** 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 generated database files that are compatible +** 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 @@ -2787,27 +2856,39 @@ struct sqlite3_mem_methods { ** 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 decending indexes. +** either generated columns or descending indexes. **
    ** ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] -**
    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.
    +** 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 change the default order +**
    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 configuration option -** is useful for application testing.
    +** 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. +** ** ** */ @@ -2829,7 +2910,7 @@ struct sqlite3_mem_methods { #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 1080 /* int int* */ +#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */ #define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */ #define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */ @@ -3056,6 +3137,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); ** ** ^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*); @@ -3709,8 +3791,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** -** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides -** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** ^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. ** ** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently @@ -4067,6 +4151,9 @@ SQLITE_API int sqlite3_open_v2( int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); + +typedef struct libsql_wal_manager libsql_wal_manager; + SQLITE_API int libsql_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ @@ -4075,6 +4162,28 @@ SQLITE_API int libsql_open( const char *zWal /* Name of WAL module to use */ ); +/* deprecated, only works with zWal == NULL */ +SQLITE_API int libsql_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs, /* Name of VFS module to use, NULL for default */ + const char *zWal, /* Name of WAL module to use */ + void* pWalMethodsData /* User data, passed to the libsql_wal struct*/ +); + +SQLITE_API int libsql_open_v3( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs, /* Name of VFS module to use, NULL for default */ + libsql_wal_manager wal_manager /* wal_manager instance, in charge of instanciating a wal */ +); + +typedef struct sqlite3_wal sqlite3_wal; +SQLITE_API int sqlite3_wal_backfilled(sqlite3_wal *pWal); +SQLITE_API unsigned int sqlite3_wal_frame_page_no(sqlite3_wal *pWal, unsigned int iFrame); + SQLITE_API LIBSQL_API int libsql_try_initialize_wasm_func_table(sqlite3 *db); /* @@ -4088,7 +4197,7 @@ SQLITE_API LIBSQL_API int libsql_try_initialize_wasm_func_table(sqlite3 *db); ** as F) must be one of: **
      **
    • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implemention, or +** 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()]. **
    @@ -4201,7 +4310,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); /* ** CAPI3REF: Create and Destroy VFS Filenames ** -** These interfces are provided for use by [VFS shim] implementations and +** 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 @@ -4281,6 +4390,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. +** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(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 @@ -4748,6 +4858,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); */ 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 @@ -4911,7 +5056,7 @@ typedef struct sqlite3_context sqlite3_context; ** 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 passsed to indicate that +** ^ (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 @@ -5590,20 +5735,33 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], -** or if [sqlite3_step(S)] has never before been called on S, -** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** ^The return code from [sqlite3_reset(S)] indicates whether or not +** the previous evaluation of prepared statement S completed successfully. +** ^If [sqlite3_step(S)] has never before been called on S or if +** [sqlite3_step(S)] has not been called since the previous call +** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return +** [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. +** ^The [sqlite3_reset(S)] interface might also return an [error code] +** if there were no prior errors but the process of resetting +** the prepared statement caused a new error. ^For example, if an +** [INSERT] statement with a [RETURNING] clause is only stepped one time, +** that one call to [sqlite3_step(S)] might return SQLITE_ROW but +** the overall statement might still fail and the [sqlite3_reset(S)] call +** might return SQLITE_BUSY if locking constraints prevent the +** database change from committing. Therefore, it is important that +** applications check the return code from [sqlite3_reset(S)] even if +** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} @@ -5814,7 +5972,7 @@ SQLITE_API int sqlite3_create_window_function( ** [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 surreptiously +** into using a database file that has had its schema surreptitiously ** modified to invoke the application-defined function in ways that are ** harmful. **

    @@ -6158,32 +6316,32 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to -** associate metadata with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated metadata may be preserved. An example -** of where this might be useful is in a regular-expression matching -** function. The compiled version of the regular expression can be stored as -** metadata associated with the pattern string. +** associate auxiliary data with argument values. If the same argument +** value is passed to multiple invocations of the same SQL function during +** query execution, under some circumstances the associated auxiliary data +** might be preserved. An example of where this might be useful is in a +** regular-expression matching function. The compiled version of the regular +** expression can be stored as auxiliary data associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. ** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata +** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data ** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument ** value to the application-defined function. ^N is zero for the left-most -** function argument. ^If there is no metadata +** function argument. ^If there is no auxiliary data ** associated with the function argument, the sqlite3_get_auxdata(C,N) interface ** returns a NULL pointer. ** -** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th -** argument of the application-defined function. ^Subsequent +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the +** N-th argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or -** NULL if the metadata has been discarded. +** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or +** NULL if the auxiliary data has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly -** once, when the metadata is discarded. -** SQLite is free to discard the metadata at any time, including:

      +** once, when the auxiliary data is discarded. +** SQLite is free to discard the auxiliary data at any time, including:
        **
      • ^(when the corresponding function parameter changes)^, or **
      • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or @@ -6199,7 +6357,7 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** function implementation should not make any use of P after ** sqlite3_set_auxdata() has been called. ** -** ^(In practice, metadata is preserved between function calls for +** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** @@ -6209,10 +6367,67 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** ** These routines must be called from the same thread in which ** the SQL function is running. +** +** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +/* +** CAPI3REF: Database Connection Client Data +** METHOD: sqlite3 +** +** These functions are used to associate one or more named pointers +** with a [database connection]. +** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P +** to be attached to [database connection] D using name N. Subsequent +** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P +** or a NULL pointer if there were no prior calls to +** sqlite3_set_clientdata() with the same values of D and N. +** Names are compared using strcmp() and are thus case sensitive. +** +** 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 @@ -6585,6 +6800,13 @@ SQLITE_API void sqlite3_activate_cerod( ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. +** +** If a negative argument is passed to sqlite3_sleep() the results vary by +** VFS and operating system. Some system treat a negative argument as an +** instruction to sleep forever. Others understand it to mean do not sleep +** at all. ^In SQLite version 3.42.0 and later, a negative +** argument passed into sqlite3_sleep() is changed to zero before it is relayed +** down into the xSleep method of the VFS. */ SQLITE_API int sqlite3_sleep(int); @@ -6838,7 +7060,7 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); /* -** CAPI3REF: Allowed return values from [sqlite3_txn_state()] +** CAPI3REF: Allowed return values from sqlite3_txn_state() ** KEYWORDS: {transaction state} ** ** These constants define the current transaction state of a database file. @@ -6970,7 +7192,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** ^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 cancelled. The return value +** 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 @@ -7489,8 +7711,14 @@ struct sqlite3_module { /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*); - /* The methods below relate to features contributed by the community and - ** are available for version 700 and greater. */ + /* 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); + + // reserved for sqlite extension + void (*reserved[5])(); + // following methods are added by libsql int (*xPreparedSql)(sqlite3_vtab_cursor*, const char*); }; @@ -7775,9 +8003,9 @@ SQLITE_API int sqlite3_drop_modules( ** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Number of open cursors */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Number of open cursors */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; @@ -7979,7 +8207,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behaviour. ^Calling this routine +** open blob handle results in undefined behavior. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the @@ -8128,12 +8356,6 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); ** ^Unregister WAL methods with the libsql_wal_methods_unregister() interface. */ typedef struct libsql_wal_methods libsql_wal_methods; -SQLITE_API libsql_wal_methods *libsql_wal_methods_find(const char *zName); -SQLITE_API int libsql_wal_methods_register(libsql_wal_methods*); -SQLITE_API int libsql_wal_methods_unregister(libsql_wal_methods*); - -SQLITE_API libsql_wal_methods *libsql_wal_methods_next(libsql_wal_methods *w); -SQLITE_API const char *libsql_wal_methods_name(libsql_wal_methods *w); /* ** CAPI3REF: Mutexes @@ -8243,9 +8465,9 @@ SQLITE_API const char *libsql_wal_methods_name(libsql_wal_methods *w); ** is undefined if the mutex is not currently entered by the ** calling thread or is not currently allocated. ** -** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or -** sqlite3_mutex_leave() is a NULL pointer, then all three routines -** behave as no-ops. +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), +** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer, +** then any of the four routines behaves as a no-op. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ @@ -8487,6 +8709,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #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_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 @@ -8515,7 +8738,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_USELONGDOUBLE 34 +#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking @@ -8838,6 +9062,10 @@ SQLITE_API int sqlite3_status64( */ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +SQLITE_API void *libsql_leak_pager(sqlite3*); +#endif + /* ** CAPI3REF: Status Parameters for database connections ** KEYWORDS: {SQLITE_DBSTATUS options} @@ -9983,7 +10211,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** [[SQLITE_VTAB_DIRECTONLY]]
        SQLITE_VTAB_DIRECTONLY
        **
        Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** the [xConnect] or [xCreate] methods of a [virtual table] implementation ** prohibits that virtual table from being used from within triggers and ** views. **
        @@ -9991,18 +10219,28 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** [[SQLITE_VTAB_INNOCUOUS]]
        SQLITE_VTAB_INNOCUOUS
        **
        Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** 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 @@ -10163,7 +10401,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); ** 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 postive integer. ^(Then, under +** 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 @@ -10592,7 +10830,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); ** When the [sqlite3_blob_write()] API is used to update a blob column, ** the pre-update hook is invoked with SQLITE_DELETE. This is because the ** in this case the new values are not available. In this case, when a -** callback made with op==SQLITE_DELETE is actuall a write using the +** 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 @@ -10621,6 +10859,22 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *); #endif +/* +** CAPI3REF: The close hook. +** METHOD: sqlite3 +** +** ^The [libsql_close_hook()] interface registers a callback function +** that is invoked prior to closing the database connection. +** ^At most one close hook may be registered at a time on a single +** [database connection]; each call to [libsql_close_hook()] overrides +** the previous setting. +** ^The close hook is disabled by invoking [libsql_close_hook()] +** with a NULL pointer as the second parameter. +** ^The third parameter to [libsql_close_hook()] is passed through as +** the first parameter to callbacks. +*/ +SQLITE_API void *libsql_close_hook(sqlite3 *db, void (*xClose)(void *pCtx, sqlite3 *db), void *arg); + /* ** CAPI3REF: Low-level system error code ** METHOD: sqlite3 @@ -10853,6 +11107,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c ** 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. @@ -10901,6 +11162,9 @@ SQLITE_API unsigned char *sqlite3_serialize( ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** +** Applications must not modify the buffer P or invalidate it before +** the database connection D is closed. +** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. @@ -10909,6 +11173,13 @@ SQLITE_API unsigned char *sqlite3_serialize( ** 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. @@ -10961,8 +11232,9 @@ SQLITE_API int sqlite3_deserialize( #if defined(__wasi__) # undef SQLITE_WASI # define SQLITE_WASI 1 -# undef SQLITE_OMIT_WAL -# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */ +// NOTICE: we do support WAL mode, we just don't support shared memory +//# undef SQLITE_OMIT_WAL +//# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */ # ifndef SQLITE_OMIT_LOAD_EXTENSION # define SQLITE_OMIT_LOAD_EXTENSION # endif @@ -11177,16 +11449,20 @@ SQLITE_API int sqlite3session_create( SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* -** CAPIREF: Conigure a Session Object +** 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 value for the second parameter is -** [SQLITE_SESSION_OBJCONFIG_SIZE]. +** created. At present the only valid values for the second parameter are +** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. ** -** Arguments for sqlite3session_object_config() +*/ +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 4th parameter to +** The following values may passed as the the 2nd parameter to ** sqlite3session_object_config(). ** **
        SQLITE_SESSION_OBJCONFIG_SIZE
        @@ -11202,12 +11478,21 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); ** ** 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. */ -SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); - -/* -*/ -#define SQLITE_SESSION_OBJCONFIG_SIZE 1 +#define SQLITE_SESSION_OBJCONFIG_SIZE 1 +#define SQLITE_SESSION_OBJCONFIG_ROWID 2 /* ** CAPI3REF: Enable Or Disable A Session Object @@ -11968,6 +12253,18 @@ SQLITE_API int sqlite3changeset_concat( ); +/* +** 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 ** @@ -12014,6 +12311,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; */ 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 @@ -12082,13 +12411,18 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. If the input changeset -** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is -** returned. Or, if an out-of-memory condition occurs during processing, this -** function returns SQLITE_NOMEM. In all cases, if an error occurs the state -** of the final contents of the changegroup is undefined. +** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup +** object has been configured with a database schema using the +** sqlite3changegroup_schema() API, then it is possible to combine changesets +** with different numbers of columns for a single table, provided that +** they are otherwise compatible. +** +** If the input changeset appears to be corrupt and the corruption is +** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition +** occurs during processing, this function returns SQLITE_NOMEM. ** -** If no error occurs, SQLITE_OK is returned. +** In all cases, if an error occurs the state of the final contents of the +** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); @@ -12353,10 +12687,17 @@ SQLITE_API int sqlite3changeset_apply_v2( **
      • 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 @@ -13097,7 +13438,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -13326,8 +13667,8 @@ struct Fts5ExtensionApi { ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (3)) or query +** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; @@ -13375,7 +13716,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -13384,7 +13725,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -13392,7 +13733,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); @@ -13440,7 +13781,7 @@ struct libsql_pghdr { ** private to pcache.c and should not be accessed by other modules. ** pCache is grouped with the public elements for efficiency. */ - short nRef; /* Number of users of this page */ + unsigned long long 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 @@ -13485,15 +13826,16 @@ typedef struct libsql_pghdr libsql_pghdr; ** There is one object of this type for each pager. */ typedef struct libsql_wal libsql_wal; +typedef struct libsql_wal_manager libsql_wal_manager; +/* Opaque types for wal method data */ +typedef struct wal_impl wal_impl; +typedef struct wal_manager_impl wal_manager_impl; typedef struct libsql_wal_methods { int iVersion; /* Current version is 1, versioning is here for backward compatibility */ - /* Open and close a connection to a write-ahead log. */ - int (*xOpen)(sqlite3_vfs*, sqlite3_file* , const char*, int no_shm_mode, long long max_size, struct libsql_wal_methods*, libsql_wal**); - int (*xClose)(libsql_wal*, sqlite3* db, int sync_flags, int nBuf, unsigned char *zBuf); /* Set the limiting size of a WAL file. */ - void (*xLimit)(libsql_wal*, long long limit); + void (*xLimit)(wal_impl* pWal, long long limit); /* 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 @@ -13502,37 +13844,37 @@ typedef struct libsql_wal_methods { ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the ** transaction and releases the lock. */ - int (*xBeginReadTransaction)(libsql_wal *, int *); - void (*xEndReadTransaction)(libsql_wal *); + int (*xBeginReadTransaction)(wal_impl* pWal, int *); + void (*xEndReadTransaction)(wal_impl *); /* Read a page from the write-ahead log, if it is present. */ - int (*xFindFrame)(libsql_wal *, unsigned int, unsigned int *); - int (*xReadFrame)(libsql_wal *, unsigned int, int, unsigned char *); + int (*xFindFrame)(wal_impl* pWal, unsigned int, unsigned int *); + int (*xReadFrame)(wal_impl* pWal, unsigned int, int, unsigned char *); /* If the WAL is not empty, return the size of the database. */ - unsigned int (*xDbsize)(libsql_wal *pWal); + unsigned int (*xDbsize)(wal_impl* pWal); /* Obtain or release the WRITER lock. */ - int (*xBeginWriteTransaction)(libsql_wal *pWal); - int (*xEndWriteTransaction)(libsql_wal *pWal); + int (*xBeginWriteTransaction)(wal_impl* pWal); + int (*xEndWriteTransaction)(wal_impl* pWal); /* Undo any frames written (but not committed) to the log */ - int (*xUndo)(libsql_wal *pWal, int (*xUndo)(void *, unsigned int), void *pUndoCtx); + int (*xUndo)(wal_impl* pWal, int (*xUndo)(void *, unsigned int), void *pUndoCtx); /* Return an integer that records the current (uncommitted) write ** position in the WAL */ - void (*xSavepoint)(libsql_wal *pWal, unsigned int *aWalData); + void (*xSavepoint)(wal_impl* pWal, unsigned int *aWalData); /* Move the write position of the WAL back to iFrame. Called in ** response to a ROLLBACK TO command. */ - int (*xSavepointUndo)(libsql_wal *pWal, unsigned int *aWalData); + int (*xSavepointUndo)(wal_impl* pWal, unsigned int *aWalData); /* Write a frame or frames to the log. */ - int (*xFrames)(libsql_wal *pWal, int, libsql_pghdr *, unsigned int, int, int); + int (*xFrames)(wal_impl* pWal, int, libsql_pghdr *, unsigned int, int, int, int*); /* Copy pages from the log to the database file */ int (*xCheckpoint)( - libsql_wal *pWal, /* Write-ahead log connection */ + wal_impl* 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 */ @@ -13541,7 +13883,12 @@ typedef struct libsql_wal_methods { int nBuf, /* Size of buffer nBuf */ unsigned char *zBuf, /* Temporary buffer to use */ int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ + int *pnCkpt, /* OUT: Number of backfilled frames in WAL */ + /* + * Called for each page being inserted in the wal, and once if the whole checkpoint operation was successfull with pPage == NULL + */ + int (*xCb)(void* pCbData, int mxSafeFrame, const unsigned char* pPage, int nPage, int page_no, int frame_no), /* called */ + void* pCbData /* user data passed to xCb */ ); /* Return the value to pass to a sqlite3_wal_hook callback, the @@ -13549,66 +13896,42 @@ typedef struct libsql_wal_methods { ** sqlite3WalCallback() was called. If no commits have occurred since ** the last call, then return 0. */ - int (*xCallback)(libsql_wal *pWal); + int (*xCallback)(wal_impl* pWal); /* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released) ** by the pager layer on the database file. */ - int (*xExclusiveMode)(libsql_wal *pWal, int op); + int (*xExclusiveMode)(wal_impl* 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. */ - int (*xHeapMemory)(libsql_wal *pWal); + int (*xHeapMemory)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_SNAPSHOT, but part of the ABI - int (*xSnapshotGet)(libsql_wal *pWal, sqlite3_snapshot **ppSnapshot); - void (*xSnapshotOpen)(libsql_wal *pWal, sqlite3_snapshot *pSnapshot); - int (*xSnapshotRecover)(libsql_wal *pWal); - int (*xSnapshotCheck)(libsql_wal *pWal, sqlite3_snapshot *pSnapshot); - void (*xSnapshotUnlock)(libsql_wal *pWal); + int (*xSnapshotGet)(wal_impl* pWal, sqlite3_snapshot **ppSnapshot); + void (*xSnapshotOpen)(wal_impl* pWal, sqlite3_snapshot *pSnapshot); + int (*xSnapshotRecover)(wal_impl* pWal); + int (*xSnapshotCheck)(void* pWal, sqlite3_snapshot *pSnapshot); + void (*xSnapshotUnlock)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_ZIPVFS, but part of the ABI /* 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). */ - int (*xFramesize)(libsql_wal *pWal); + int (*xFramesize)(wal_impl* pWal); /* Return the sqlite3_file object for the WAL file */ - sqlite3_file *(*xFile)(libsql_wal *pWal); + sqlite3_file *(*xFile)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_SETLK_TIMEOUT - int (*xWriteLock)(libsql_wal *pWal, int bLock); - - void (*xDb)(libsql_wal *pWal, sqlite3 *db); - - /* Return the WAL pathname length based on the owning pager's pathname len. - ** For WAL implementations not based on a single file, 0 should be returned. */ - int (*xPathnameLen)(int origPathname); - - /* Get the WAL pathname to given buffer. Assumes that the buffer can hold - ** at least xPathnameLen bytes. For WAL implementations not based on a single file, - ** this operation can safely be a no-op. - ** */ - void (*xGetWalPathname)(char *buf, const char *orig, int orig_len); - - /* - ** This optional callback gets called before the main database file which owns - ** the WAL file is open. It is a good place for initialization routines, as WAL - ** is otherwise open lazily. - */ - int (*xPreMainDbOpen)(libsql_wal_methods *methods, const char *main_db_path); - - /* True if the implementation relies on shared memory routines (e.g. locks) */ - int bUsesShm; + int (*xWriteLock)(wal_impl* pWal, int bLock); - const char *zName; - struct libsql_wal_methods *pNext; + void (*xDb)(wal_impl* pWal, sqlite3 *db); } libsql_wal_methods; -libsql_wal_methods* libsql_wal_methods_find(const char *zName); /* Object declarations */ typedef struct WalIndexHdr WalIndexHdr; @@ -13643,11 +13966,29 @@ struct WalIndexHdr { unsigned int aCksum[2]; /* Checksum over all prior fields */ }; +struct libsql_wal_manager { + /* True if the implementation relies on shared memory routines (e.g. locks) */ + int bUsesShm; + + /* Open and close a connection to a write-ahead log. */ + int (*xOpen)(wal_manager_impl* pData, sqlite3_vfs*, sqlite3_file*, int no_shm_mode, long long max_size, const char* zMainDbFileName, libsql_wal* out_wal); + int (*xClose)(wal_manager_impl* pData, wal_impl* pWal, sqlite3* db, int sync_flags, int nBuf, unsigned char *zBuf); + + /* destroy resources for this wal */ + int (*xLogDestroy)(wal_manager_impl* pData, sqlite3_vfs *vfs, const char* zMainDbFileName); + /* returns whether this wal exists */ + int (*xLogExists)(wal_manager_impl* pData, sqlite3_vfs *vfs, const char* zMainDbFileName, int* exist); + /* destructor */ + void (*xDestroy)(wal_manager_impl* pData); + + wal_manager_impl* pData; +}; + /* ** An open write-ahead log file is represented by an instance of the ** following object. */ -struct libsql_wal { +typedef struct sqlite3_wal { sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ sqlite3_file *pDbFd; /* File handle for the database file */ sqlite3_file *pWalFd; /* File handle for WAL file */ @@ -13675,11 +14016,29 @@ struct libsql_wal { unsigned char lockError; /* True if a locking error has occurred */ WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ sqlite3 *db; - libsql_wal_methods *pMethods; /* Virtual methods for interacting with WAL */ - void *pMethodsData; /* Optional context for private use of libsql_wal_methods */ +} sqlite3_wal; + +struct libsql_wal { + libsql_wal_methods methods; /* virtual wal methods */ + wal_impl* pData; /* methods receiver */ }; -typedef struct libsql_wal libsql_wal; +typedef struct RefCountedWalManager { + int n; + libsql_wal_manager ref; + int is_static; +} RefCountedWalManager; + +int make_ref_counted_wal_manager(libsql_wal_manager wal_manager, RefCountedWalManager **out); +void destroy_wal_manager(RefCountedWalManager *p); +RefCountedWalManager* clone_wal_manager(RefCountedWalManager *p); + +SQLITE_API int sqlite3_wal_backfilled(sqlite3_wal* pWal); +SQLITE_API unsigned int sqlite3_wal_frame_page_no(sqlite3_wal *pWal, unsigned int iFrame); + +RefCountedWalManager *make_sqlite3_wal_manager_rc(); + +SQLITE_API extern const libsql_wal_manager sqlite3_wal_manager; #endif /* SQLITE_WAL_H */ @@ -13735,6 +14094,7 @@ SQLITE_API void libsql_free_wasm_module(void *module); ** Creates a new wasm engine */ SQLITE_API libsql_wasm_engine_t *libsql_wasm_engine_new(); +SQLITE_API void libsql_wasm_engine_free(libsql_wasm_engine_t *); #endif //LIBSQL_WASM_BINDINGS_H #endif //LIBSQL_ENABLE_WASM_RUNTIME @@ -13834,7 +14194,7 @@ SQLITE_API libsql_wasm_engine_t *libsql_wasm_engine_new(); ** level of recursion for each term. A stack overflow can result ** if the number of terms is too large. In practice, most SQL ** never has more than 3 or 4 terms. Use a value of 0 to disable -** any limit on the number of terms in a compount SELECT. +** any limit on the number of terms in a compound SELECT. */ #ifndef SQLITE_MAX_COMPOUND_SELECT # define SQLITE_MAX_COMPOUND_SELECT 500 @@ -14041,15 +14401,22 @@ SQLITE_API libsql_wasm_engine_t *libsql_wasm_engine_new(); #endif /* -** A macro to hint to the compiler that a function should not be +** Macros to hint to the compiler that a function should or should not be ** inlined. */ #if defined(__GNUC__) # define SQLITE_NOINLINE __attribute__((noinline)) +# define SQLITE_INLINE __attribute__((always_inline)) inline #elif defined(_MSC_VER) && _MSC_VER>=1310 # define SQLITE_NOINLINE __declspec(noinline) +# define SQLITE_INLINE __forceinline #else # define SQLITE_NOINLINE +# define SQLITE_INLINE +#endif +#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__) +# undef SQLITE_INLINE +# define SQLITE_INLINE #endif /* @@ -14468,183 +14835,184 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #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_RANDOM 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_CONFLICT 38 -#define TK_DATABASE 39 -#define TK_DESC 40 -#define TK_DETACH 41 -#define TK_EACH 42 -#define TK_FAIL 43 -#define TK_FUNCTION 44 -#define TK_LANGUAGE 45 -#define TK_OR 46 -#define TK_AND 47 -#define TK_IS 48 -#define TK_MATCH 49 -#define TK_LIKE_KW 50 -#define TK_BETWEEN 51 -#define TK_IN 52 -#define TK_ISNULL 53 -#define TK_NOTNULL 54 -#define TK_NE 55 -#define TK_EQ 56 -#define TK_GT 57 -#define TK_LE 58 -#define TK_LT 59 -#define TK_GE 60 -#define TK_ESCAPE 61 -#define TK_ID 62 -#define TK_COLUMNKW 63 -#define TK_DO 64 -#define TK_FOR 65 -#define TK_IGNORE 66 -#define TK_INITIALLY 67 -#define TK_INSTEAD 68 -#define TK_NO 69 -#define TK_KEY 70 -#define TK_OF 71 -#define TK_OFFSET 72 -#define TK_PRAGMA 73 -#define TK_RAISE 74 -#define TK_RECURSIVE 75 -#define TK_REPLACE 76 -#define TK_RESTRICT 77 -#define TK_ROW 78 -#define TK_ROWS 79 -#define TK_TRIGGER 80 -#define TK_VACUUM 81 -#define TK_VIEW 82 -#define TK_VIRTUAL 83 -#define TK_WITH 84 -#define TK_NULLS 85 -#define TK_FIRST 86 -#define TK_LAST 87 -#define TK_CURRENT 88 -#define TK_FOLLOWING 89 -#define TK_PARTITION 90 -#define TK_PRECEDING 91 -#define TK_RANGE 92 -#define TK_UNBOUNDED 93 -#define TK_EXCLUDE 94 -#define TK_GROUPS 95 -#define TK_OTHERS 96 -#define TK_TIES 97 -#define TK_GENERATED 98 -#define TK_ALWAYS 99 -#define TK_MATERIALIZED 100 -#define TK_REINDEX 101 -#define TK_RENAME 102 -#define TK_CTIME_KW 103 -#define TK_ANY 104 -#define TK_BITAND 105 -#define TK_BITOR 106 -#define TK_LSHIFT 107 -#define TK_RSHIFT 108 -#define TK_PLUS 109 -#define TK_MINUS 110 -#define TK_STAR 111 -#define TK_SLASH 112 -#define TK_REM 113 -#define TK_CONCAT 114 -#define TK_PTR 115 -#define TK_COLLATE 116 -#define TK_BITNOT 117 -#define TK_ON 118 -#define TK_INDEXED 119 -#define TK_STRING 120 -#define TK_JOIN_KW 121 -#define TK_CONSTRAINT 122 -#define TK_DEFAULT 123 -#define TK_NULL 124 -#define TK_PRIMARY 125 -#define TK_UNIQUE 126 -#define TK_CHECK 127 -#define TK_REFERENCES 128 -#define TK_AUTOINCR 129 -#define TK_INSERT 130 -#define TK_DELETE 131 -#define TK_UPDATE 132 -#define TK_SET 133 -#define TK_DEFERRABLE 134 -#define TK_FOREIGN 135 -#define TK_DROP 136 -#define TK_BLOB 137 -#define TK_UNION 138 -#define TK_ALL 139 -#define TK_EXCEPT 140 -#define TK_INTERSECT 141 -#define TK_SELECT 142 -#define TK_VALUES 143 -#define TK_DISTINCT 144 -#define TK_DOT 145 -#define TK_FROM 146 -#define TK_JOIN 147 -#define TK_USING 148 -#define TK_ORDER 149 -#define TK_GROUP 150 -#define TK_HAVING 151 -#define TK_LIMIT 152 -#define TK_WHERE 153 -#define TK_RETURNING 154 -#define TK_INTO 155 -#define TK_NOTHING 156 -#define TK_FLOAT 157 -#define TK_INTEGER 158 -#define TK_VARIABLE 159 -#define TK_CASE 160 -#define TK_WHEN 161 -#define TK_THEN 162 -#define TK_ELSE 163 -#define TK_INDEX 164 -#define TK_ALTER 165 -#define TK_ADD 166 -#define TK_WINDOW 167 -#define TK_OVER 168 -#define TK_FILTER 169 -#define TK_COLUMN 170 -#define TK_AGG_FUNCTION 171 -#define TK_AGG_COLUMN 172 -#define TK_TRUEFALSE 173 -#define TK_ISNOT 174 -#define TK_UMINUS 175 -#define TK_UPLUS 176 -#define TK_TRUTH 177 -#define TK_REGISTER 178 -#define TK_VECTOR 179 -#define TK_SELECT_COLUMN 180 -#define TK_IF_NULL_ROW 181 -#define TK_ASTERISK 182 -#define TK_SPAN 183 -#define TK_ERROR 184 -#define TK_SPACE 185 -#define TK_ILLEGAL 186 +#define TK_READONLY 10 +#define TK_COMMIT 11 +#define TK_END 12 +#define TK_ROLLBACK 13 +#define TK_SAVEPOINT 14 +#define TK_RELEASE 15 +#define TK_TO 16 +#define TK_TABLE 17 +#define TK_CREATE 18 +#define TK_IF 19 +#define TK_NOT 20 +#define TK_EXISTS 21 +#define TK_TEMP 22 +#define TK_LP 23 +#define TK_RP 24 +#define TK_AS 25 +#define TK_COMMA 26 +#define TK_WITHOUT 27 +#define TK_RANDOM 28 +#define TK_ABORT 29 +#define TK_ACTION 30 +#define TK_AFTER 31 +#define TK_ANALYZE 32 +#define TK_ASC 33 +#define TK_ATTACH 34 +#define TK_BEFORE 35 +#define TK_BY 36 +#define TK_CASCADE 37 +#define TK_CAST 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_FUNCTION 45 +#define TK_LANGUAGE 46 +#define TK_OR 47 +#define TK_AND 48 +#define TK_IS 49 +#define TK_MATCH 50 +#define TK_LIKE_KW 51 +#define TK_BETWEEN 52 +#define TK_IN 53 +#define TK_ISNULL 54 +#define TK_NOTNULL 55 +#define TK_NE 56 +#define TK_EQ 57 +#define TK_GT 58 +#define TK_LE 59 +#define TK_LT 60 +#define TK_GE 61 +#define TK_ESCAPE 62 +#define TK_ID 63 +#define TK_COLUMNKW 64 +#define TK_DO 65 +#define TK_FOR 66 +#define TK_IGNORE 67 +#define TK_INITIALLY 68 +#define TK_INSTEAD 69 +#define TK_NO 70 +#define TK_KEY 71 +#define TK_OF 72 +#define TK_OFFSET 73 +#define TK_PRAGMA 74 +#define TK_RAISE 75 +#define TK_RECURSIVE 76 +#define TK_REPLACE 77 +#define TK_RESTRICT 78 +#define TK_ROW 79 +#define TK_ROWS 80 +#define TK_TRIGGER 81 +#define TK_VACUUM 82 +#define TK_VIEW 83 +#define TK_VIRTUAL 84 +#define TK_WITH 85 +#define TK_NULLS 86 +#define TK_FIRST 87 +#define TK_LAST 88 +#define TK_CURRENT 89 +#define TK_FOLLOWING 90 +#define TK_PARTITION 91 +#define TK_PRECEDING 92 +#define TK_RANGE 93 +#define TK_UNBOUNDED 94 +#define TK_EXCLUDE 95 +#define TK_GROUPS 96 +#define TK_OTHERS 97 +#define TK_TIES 98 +#define TK_GENERATED 99 +#define TK_ALWAYS 100 +#define TK_MATERIALIZED 101 +#define TK_REINDEX 102 +#define TK_RENAME 103 +#define TK_CTIME_KW 104 +#define TK_ANY 105 +#define TK_BITAND 106 +#define TK_BITOR 107 +#define TK_LSHIFT 108 +#define TK_RSHIFT 109 +#define TK_PLUS 110 +#define TK_MINUS 111 +#define TK_STAR 112 +#define TK_SLASH 113 +#define TK_REM 114 +#define TK_CONCAT 115 +#define TK_PTR 116 +#define TK_COLLATE 117 +#define TK_BITNOT 118 +#define TK_ON 119 +#define TK_INDEXED 120 +#define TK_STRING 121 +#define TK_JOIN_KW 122 +#define TK_CONSTRAINT 123 +#define TK_DEFAULT 124 +#define TK_NULL 125 +#define TK_PRIMARY 126 +#define TK_UNIQUE 127 +#define TK_CHECK 128 +#define TK_REFERENCES 129 +#define TK_AUTOINCR 130 +#define TK_INSERT 131 +#define TK_DELETE 132 +#define TK_UPDATE 133 +#define TK_SET 134 +#define TK_DEFERRABLE 135 +#define TK_FOREIGN 136 +#define TK_DROP 137 +#define TK_BLOB 138 +#define TK_UNION 139 +#define TK_ALL 140 +#define TK_EXCEPT 141 +#define TK_INTERSECT 142 +#define TK_SELECT 143 +#define TK_VALUES 144 +#define TK_DISTINCT 145 +#define TK_DOT 146 +#define TK_FROM 147 +#define TK_JOIN 148 +#define TK_USING 149 +#define TK_ORDER 150 +#define TK_GROUP 151 +#define TK_HAVING 152 +#define TK_LIMIT 153 +#define TK_WHERE 154 +#define TK_RETURNING 155 +#define TK_INTO 156 +#define TK_NOTHING 157 +#define TK_FLOAT 158 +#define TK_INTEGER 159 +#define TK_VARIABLE 160 +#define TK_CASE 161 +#define TK_WHEN 162 +#define TK_THEN 163 +#define TK_ELSE 164 +#define TK_INDEX 165 +#define TK_ALTER 166 +#define TK_ADD 167 +#define TK_WINDOW 168 +#define TK_OVER 169 +#define TK_FILTER 170 +#define TK_COLUMN 171 +#define TK_AGG_FUNCTION 172 +#define TK_AGG_COLUMN 173 +#define TK_TRUEFALSE 174 +#define TK_ISNOT 175 +#define TK_UMINUS 176 +#define TK_UPLUS 177 +#define TK_TRUTH 178 +#define TK_REGISTER 179 +#define TK_VECTOR 180 +#define TK_SELECT_COLUMN 181 +#define TK_IF_NULL_ROW 182 +#define TK_ASTERISK 183 +#define TK_SPAN 184 +#define TK_ERROR 185 +#define TK_SPACE 186 +#define TK_ILLEGAL 187 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -14932,8 +15300,31 @@ typedef INT16_TYPE LogEst; ** the end of buffer S. This macro returns true if P points to something ** contained within the buffer S. */ -#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) +#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) +/* +** P is one byte past the end of a large buffer. Return true if a span of bytes +** between S..E crosses the end of that buffer. In other words, return true +** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. +** +** S is the start of the span. E is one byte past the end of end of span. +** +** P +** |-----------------| FALSE +** |-------| +** S E +** +** P +** |-----------------| +** |-------| TRUE +** S E +** +** P +** |-----------------| +** |-------| FALSE +** S E +*/ +#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P))) /* ** Macros to determine whether the machine is big or little endian, @@ -14943,16 +15334,33 @@ typedef INT16_TYPE LogEst; ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined ** at run-time. +** +** If you are building SQLite on some obscure platform for which the +** following ifdef magic does not work, you can always include either: +** +** -DSQLITE_BYTEORDER=1234 +** +** or +** +** -DSQLITE_BYTEORDER=4321 +** +** to cause the build to work for little-endian or big-endian processors, +** respectively. */ -#ifndef SQLITE_BYTEORDER -# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ +#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(__ppc__) || \ - defined(__ARMEB__) || defined(__AARCH64EB__) -# define SQLITE_BYTEORDER 4321 +# define SQLITE_BYTEORDER 1234 +# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) +# define SQLITE_BYTEORDER 4321 # else # define SQLITE_BYTEORDER 0 # endif @@ -15167,7 +15575,7 @@ struct BusyHandler { /* ** Name of table that holds the database schema. ** -** The PREFERRED names are used whereever possible. But LEGACY is also +** 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 @@ -15276,11 +15684,13 @@ typedef struct Column Column; typedef struct Cte Cte; typedef struct CteUse CteUse; typedef struct Db Db; +typedef struct DbClientData DbClientData; typedef struct DbFixer DbFixer; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; +typedef struct FpDecode FpDecode; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; @@ -15299,6 +15709,7 @@ 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; @@ -15814,7 +16225,7 @@ typedef struct libsql_wal_methods libsql_wal_methods; /* Open and close a Pager connection. */ SQLITE_PRIVATE int sqlite3PagerOpen( sqlite3_vfs*, - libsql_wal_methods*, + RefCountedWalManager*, Pager **ppPager, const char*, int, @@ -15942,6 +16353,10 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); # 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 ***********************************************/ @@ -15995,7 +16410,6 @@ typedef struct libsql_wal_methods libsql_wal_methods; SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3_vfs *pVfs, /* VFS to use with this b-tree */ - libsql_wal_methods *pWal,/* WAL methods to use with this b-tree */ const char *zFilename, /* Name of database file to open */ sqlite3 *db, /* Associated database connection */ Btree **ppBtree, /* Return open Btree* here */ @@ -16273,9 +16687,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*); -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); -#endif SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); @@ -16315,7 +16727,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); #endif SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*); +SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*, i64*); #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); @@ -16565,8 +16977,8 @@ typedef struct VdbeOpList VdbeOpList; #define OP_If 16 /* jump */ #define OP_IfNot 17 /* jump */ #define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */ -#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ +#define OP_IfNullRow 19 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ +#define OP_Not 20 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ #define OP_SeekLT 21 /* jump, synopsis: key=r[P3@P4] */ #define OP_SeekLE 22 /* jump, synopsis: key=r[P3@P4] */ #define OP_SeekGE 23 /* jump, synopsis: key=r[P3@P4] */ @@ -16592,23 +17004,23 @@ typedef struct VdbeOpList VdbeOpList; #define OP_IdxGE 43 /* jump, synopsis: key=r[P3@P4] */ #define OP_RowSetRead 44 /* jump, synopsis: r[P3]=rowset(P1) */ #define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Or 46 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ -#define OP_And 47 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_Program 48 /* jump */ +#define OP_Program 46 /* jump */ +#define OP_Or 47 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ +#define OP_And 48 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ #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_IfNotZero 51 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ #define OP_DecrJumpZero 52 /* jump, synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IsNull 53 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ -#define OP_NotNull 54 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 55 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ -#define OP_Eq 56 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ -#define OP_Gt 57 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ -#define OP_Le 58 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ -#define OP_Lt 59 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */ -#define OP_ElseEq 61 /* jump, same as TK_ESCAPE */ -#define OP_IncrVacuum 62 /* jump */ +#define OP_IncrVacuum 53 /* jump */ +#define OP_IsNull 54 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ +#define OP_NotNull 55 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ +#define OP_Ne 56 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ +#define OP_Eq 57 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ +#define OP_Gt 58 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ +#define OP_Le 59 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ +#define OP_Lt 60 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */ +#define OP_ElseEq 62 /* jump, same as TK_ESCAPE */ #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]) */ @@ -16651,23 +17063,23 @@ typedef struct VdbeOpList VdbeOpList; #define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */ #define OP_OpenWrite 103 /* synopsis: root=P2 iDb=P3 */ #define OP_OpenDup 104 -#define OP_BitAnd 105 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 106 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 107 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 109 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 110 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 111 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 112 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 113 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 114 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_OpenAutoindex 115 /* synopsis: nColumn=P2 */ +#define OP_OpenAutoindex 105 /* synopsis: nColumn=P2 */ +#define OP_BitAnd 106 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +#define OP_BitOr 107 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +#define OP_ShiftLeft 108 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ +#define OP_Add 110 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +#define OP_Subtract 111 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +#define OP_Multiply 112 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +#define OP_Divide 113 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +#define OP_Remainder 114 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +#define OP_Concat 115 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ #define OP_OpenEphemeral 116 /* synopsis: nColumn=P2 */ -#define OP_BitNot 117 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ -#define OP_SorterOpen 118 +#define OP_SorterOpen 117 +#define OP_BitNot 118 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ #define OP_SequenceTest 119 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_String8 120 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */ +#define OP_OpenPseudo 120 /* synopsis: P3 columns in r[P2] */ +#define OP_String8 121 /* same as TK_STRING, synopsis: r[P2]='P4' */ #define OP_Close 122 #define OP_ColumnsUsed 123 #define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */ @@ -16703,8 +17115,8 @@ typedef struct VdbeOpList VdbeOpList; #define OP_DropIndex 154 #define OP_DropTrigger 155 #define OP_IntegrityCk 156 -#define OP_Real 157 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_RowSetAdd 158 /* synopsis: rowset(P1)=r[P2] */ +#define OP_RowSetAdd 157 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Real 158 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ #define OP_Param 159 #define OP_FkCounter 160 /* synopsis: fkctr[P1]+=P2 */ #define OP_MemMax 161 /* synopsis: r[P1]=max(r[P1],r[P2]) */ @@ -16722,20 +17134,21 @@ typedef struct VdbeOpList VdbeOpList; #define OP_VCreate 173 #define OP_VDestroy 174 #define OP_VOpen 175 -#define OP_VInitIn 176 /* synopsis: r[P2]=ValueList(P1,P3) */ -#define OP_VPreparedSql 177 -#define OP_VColumn 178 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 179 -#define OP_Pagecount 180 -#define OP_MaxPgcnt 181 -#define OP_ClrSubtype 182 /* synopsis: r[P1].subtype = 0 */ -#define OP_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_VCheck 176 +#define OP_VInitIn 177 /* synopsis: r[P2]=ValueList(P1,P3) */ +#define OP_VPreparedSql 178 +#define OP_VColumn 179 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 180 +#define OP_Pagecount 181 +#define OP_MaxPgcnt 182 +#define OP_ClrSubtype 183 /* synopsis: r[P1].subtype = 0 */ +#define OP_FilterAdd 184 /* synopsis: filter(P1) += key(P3@P4) */ +#define OP_Trace 185 +#define OP_CursorHint 186 +#define OP_ReleaseReg 187 /* synopsis: release r[P1@P2] mask P3 */ +#define OP_Noop 188 +#define OP_Explain 189 +#define OP_Abortable 190 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -16751,28 +17164,28 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_INITIALIZER {\ /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\ /* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\ -/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\ +/* 16 */ 0x03, 0x03, 0x01, 0x01, 0x12, 0x49, 0x49, 0x49,\ /* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\ -/* 32 */ 0x41, 0x01, 0x01, 0x01, 0x41, 0x01, 0x41, 0x41,\ -/* 40 */ 0x41, 0x41, 0x41, 0x41, 0x23, 0x0b, 0x26, 0x26,\ -/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0b,\ -/* 56 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x01, 0x01, 0x41,\ +/* 32 */ 0x41, 0x01, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41,\ +/* 40 */ 0x41, 0x41, 0x41, 0x41, 0x23, 0x0b, 0x01, 0x26,\ +/* 48 */ 0x26, 0x01, 0x03, 0x03, 0x03, 0x01, 0x03, 0x03,\ +/* 56 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 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, 0x00,\ -/* 104 */ 0x40, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ -/* 112 */ 0x26, 0x26, 0x26, 0x40, 0x40, 0x12, 0x00, 0x00,\ -/* 120 */ 0x10, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x00,\ -/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 104 */ 0x40, 0x40, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ +/* 112 */ 0x26, 0x26, 0x26, 0x26, 0x40, 0x00, 0x12, 0x00,\ +/* 120 */ 0x00, 0x10, 0x40, 0x00, 0x40, 0x40, 0x10, 0x00,\ +/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,\ /* 136 */ 0x00, 0x50, 0x00, 0x40, 0x04, 0x04, 0x00, 0x40,\ /* 144 */ 0x50, 0x40, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x06, 0x10,\ +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10,\ /* 160 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,\ -/* 176 */ 0x50, 0x00, 0x40, 0x00, 0x10, 0x10, 0x02, 0x00,\ -/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} +/* 176 */ 0x10, 0x50, 0x00, 0x40, 0x00, 0x10, 0x10, 0x02,\ +/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} /* The resolve3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -16947,7 +17360,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** The VdbeCoverage macros are used to set a coverage testing point ** for VDBE branch instructions. The coverage testing points are line ** numbers in the sqlite3.c source file. VDBE branch coverage testing -** only works with an amalagmation build. That's ok since a VDBE branch +** only works with an amalgamation build. That's ok since a VDBE branch ** coverage build designed for testing the test suite only. No application ** should ever ship with VDBE branch coverage measuring turned on. ** @@ -16965,7 +17378,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** // NULL option is not possible ** ** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested -** // in distingishing equal and not-equal. +** // in distinguishing equal and not-equal. ** ** Every VDBE branch operation must be tagged with one of the macros above. ** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and @@ -16975,7 +17388,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** During testing, the test application will invoke ** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback ** routine that is invoked as each bytecode branch is taken. The callback -** contains the sqlite3.c source line number ov the VdbeCoverage macro and +** contains the sqlite3.c source line number of the VdbeCoverage macro and ** flags to indicate whether or not the branch was taken. The test application ** is responsible for keeping track of this and reporting byte-code branches ** that are never taken. @@ -17023,6 +17436,10 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters(Vdbe*, int, int, int); 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); +#endif + #endif /* SQLITE_VDBE_H */ /************** End of vdbe.h ************************************************/ @@ -17078,7 +17495,7 @@ struct libsql_pghdr { ** private to pcache.c and should not be accessed by other modules. ** pCache is grouped with the public elements for efficiency. */ - short nRef; /* Number of users of this page */ + unsigned long long 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 @@ -17166,12 +17583,12 @@ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); /* Return the total number of outstanding page references */ -SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); +SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache*); /* Increment the reference count of an existing page */ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); -SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); +SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr*); /* Return the total number of pages stored in the cache */ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); @@ -17328,7 +17745,7 @@ SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); /* ** Default synchronous levels. ** -** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ +** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ ** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1. ** ** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS @@ -17367,7 +17784,7 @@ struct Db { ** An instance of the following structure stores a database schema. ** ** Most Schema objects are associated with a Btree. The exception is -** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. +** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing. ** In shared cache mode, a single Schema object can be shared by multiple ** Btrees that refer to the same underlying BtShared object. ** @@ -17478,7 +17895,7 @@ struct Lookaside { LookasideSlot *pInit; /* List of buffers not previously used */ LookasideSlot *pFree; /* List of available buffers */ #ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE - LookasideSlot *pSmallInit; /* List of small buffers not prediously used */ + LookasideSlot *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 */ @@ -17495,7 +17912,7 @@ struct LookasideSlot { #define EnableLookaside db->lookaside.bDisable--;\ db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue -/* Size of the smaller allocations in two-size lookside */ +/* Size of the smaller allocations in two-size lookaside */ #ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE # define LOOKASIDE_SMALL 0 #else @@ -17703,6 +18120,7 @@ struct sqlite3 { 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 ** mutex, not by sqlite3.mutex. They are used by code in notify.c. @@ -17726,7 +18144,13 @@ struct sqlite3 { #ifdef LIBSQL_ENABLE_WASM_RUNTIME libsql_wasm_ctx wasm; /* WebAssembly runtime context */ #endif - libsql_wal_methods* pWalMethods; /* Custom WAL methods */ +#ifndef SQLITE_OMIT_WAL + RefCountedWalManager *wal_manager; +#endif + void *pCloseArg; /* First argument to xCloseCallback */ + void (*xCloseCallback)( /* Registered using sqlite3_close_hook() */ + void*, sqlite3* + ); }; /* @@ -17789,6 +18213,7 @@ struct sqlite3 { /* 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 */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG @@ -17846,6 +18271,7 @@ struct sqlite3 { #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_AllOpts 0xffffffff /* All optimizations */ /* @@ -17928,6 +18354,7 @@ struct FuncDestructor { ** 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!!! @@ -17935,7 +18362,7 @@ struct FuncDestructor { ** ** 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 tha the function has side effects. +** 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. */ @@ -17946,6 +18373,7 @@ struct FuncDestructor { #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/ #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */ #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */ +#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */ #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */ /* 0x0200 -- available for reuse */ #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ @@ -18317,6 +18745,7 @@ struct VTable { sqlite3_vtab *pVtab; /* Pointer to vtab instance */ int nRef; /* Number of pointers to this structure */ u8 bConstraint; /* True if constraints are supported */ + u8 bAllSchemas; /* True if might use any attached schema */ u8 eVtabRisk; /* Riskiness of allowing hacker access */ int iSavepoint; /* Depth of the SAVEPOINT stack */ VTable *pNext; /* Next in linked list (see above) */ @@ -18528,7 +18957,7 @@ struct FKey { ** foreign key. ** ** The OE_Default value is a place holder that means to use whatever -** conflict resolution algorthm is required from context. +** conflict resolution algorithm is required from context. ** ** The following symbolic values are used to record which type ** of conflict resolution action to take. @@ -18701,6 +19130,7 @@ struct Index { ** expression, or a reference to a VIRTUAL column */ #ifdef SQLITE_ENABLE_STAT4 int nSample; /* Number of elements in aSample[] */ + int mxSample; /* Number of slots allocated to aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ @@ -18803,6 +19233,9 @@ struct AggInfo { FuncDef *pFunc; /* The aggregate function implementation */ 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 */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ u32 selId; /* Select to which this AggInfo belongs */ @@ -18941,7 +19374,7 @@ struct Expr { ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 134217728 times likelihood - ** TK_IN: ephemerial table holding RHS + ** 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. @@ -18987,7 +19420,7 @@ struct Expr { #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 */ - /* 0x020000 // Available for reuse */ +#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 */ @@ -19017,12 +19450,15 @@ struct Expr { #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) @@ -19132,6 +19568,7 @@ struct ExprList { #define ENAME_NAME 0 /* The AS clause of a result set */ #define ENAME_SPAN 1 /* Complete text of the result set expression */ #define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */ +#define ENAME_ROWID 3 /* "DB.TABLE._rowid_" for * expansion of rowid */ /* ** An instance of this structure can hold a simple list of identifiers, @@ -19211,7 +19648,7 @@ struct SrcItem { 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 synthensized from NATURAL */ + unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ @@ -19352,7 +19789,7 @@ struct NameContext { #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_VarSelect 0x000040 /* A correlated subquery has been seen */ +#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 */ @@ -19723,6 +20160,9 @@ struct Parse { u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ #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 int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ @@ -19737,6 +20177,7 @@ struct Parse { 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 */ @@ -19744,6 +20185,9 @@ struct Parse { 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() */ +#endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ @@ -19757,12 +20201,9 @@ struct Parse { int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ Returning *pReturning; /* The RETURNING clause */ } u1; - u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ -#endif + 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 */ @@ -19886,6 +20327,7 @@ struct AuthContext { #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ +#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ @@ -20007,6 +20449,7 @@ struct Returning { 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" */ }; /* @@ -20028,6 +20471,25 @@ struct sqlite3_str { #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(). +*/ +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 @@ -20054,7 +20516,7 @@ typedef struct { /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning ** parameters are for temporary use during development, to help find -** optimial values for parameters in the query planner. The should not +** 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. ** @@ -20080,6 +20542,7 @@ struct Sqlite3Config { 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 */ + u8 bUseLongDouble; /* Make use of long double */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ @@ -20166,6 +20629,7 @@ struct Walker { void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ int walkerDepth; /* Number of subqueries */ u16 eCode; /* A small processing code */ + u16 mWFlags; /* Use-dependent flags */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int n; /* A counter */ @@ -20184,6 +20648,7 @@ struct Walker { struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */ SrcItem *pSrcItem; /* A single FROM clause item */ DbFixer *pFix; /* See sqlite3FixSelect() */ + Mem *aMem; /* See sqlite3BtreeCursorHint() */ } u; }; @@ -20204,6 +20669,7 @@ struct DbFixer { /* 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*); @@ -20284,6 +20750,16 @@ struct CteUse { }; +/* 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 */ +}; + #ifdef SQLITE_DEBUG /* ** An instance of the TreeView object is used for printing the content of @@ -20453,6 +20929,8 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); # define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) # define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) # define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) +# define sqlite3JsonId1(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x42) +# define sqlite3JsonId2(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x46) #else # define sqlite3Toupper(x) toupper((unsigned char)(x)) # define sqlite3Isspace(x) isspace((unsigned char)(x)) @@ -20462,6 +20940,8 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) # define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') +# define sqlite3JsonId1(x) (sqlite3IsIdChar(x)&&(x)<'0') +# define sqlite3JsonId2(x) sqlite3IsIdChar(x) #endif SQLITE_PRIVATE int sqlite3IsIdChar(u8); @@ -20581,6 +21061,20 @@ struct PrintfArguments { 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 char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) @@ -20655,6 +21149,10 @@ 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 @@ -20666,6 +21164,8 @@ 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 void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); @@ -20725,8 +21225,8 @@ 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 int sqlite3ParseUri(const char*,const char*,const char*,unsigned int*, - sqlite3_vfs**,libsql_wal_methods**,char**,char **); +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*); @@ -20805,7 +21305,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList Expr*,ExprList*,u32,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); -SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); +SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*); SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); @@ -20867,7 +21367,7 @@ 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); +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,int); SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); @@ -20894,7 +21394,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); -SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*); +SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); #endif @@ -20902,6 +21402,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const 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); @@ -21016,6 +21517,7 @@ SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); + SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64); SQLITE_PRIVATE i64 sqlite3RealToI64(double); SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*); @@ -21120,6 +21622,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8); SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); +SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*)); SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); @@ -21159,6 +21662,7 @@ 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*); +void libsqlAlterAlterColumn(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); @@ -21171,7 +21675,8 @@ SQLITE_PRIVATE int sqlite3MatchEName( const struct ExprList_item*, const char*, const char*, - const char* + const char*, + int* ); SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*); SQLITE_PRIVATE u8 sqlite3StrIHash(const char*); @@ -21227,6 +21732,11 @@ 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 char *sqlite3StrAccumFinish(StrAccum*); @@ -21342,10 +21852,7 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); -#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ - && !defined(SQLITE_OMIT_VIRTUALTABLE) -SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info*); -#endif +SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse*); SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); @@ -21481,6 +21988,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); #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); @@ -21766,9 +22274,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif -#ifdef SQLITE_64BIT_STATS - "64BIT_STATS", -#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), @@ -22064,6 +22569,9 @@ static const char * const sqlite3azCompileOpt[] = { #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 @@ -22105,6 +22613,9 @@ static const char * const sqlite3azCompileOpt[] = { #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 @@ -22342,6 +22853,9 @@ static const char * const sqlite3azCompileOpt[] = { #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 @@ -22593,7 +23107,7 @@ SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP ** isalnum() 0x06 ** isxdigit() 0x08 ** toupper() 0x20 -** SQLite identifier character 0x40 +** SQLite identifier character 0x40 $, _, or non-ascii ** Quote character 0x80 ** ** Bit 0x20 is set if the mapped character requires translation to upper @@ -22739,6 +23253,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0, /* bSmallMalloc */ 1, /* bExtraSchemaChecks */ + sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ @@ -22968,6 +23483,9 @@ typedef struct VdbeSorter VdbeSorter; /* Elements of the linked list at Vdbe.pAuxData */ typedef struct AuxData AuxData; +/* A cache of large TEXT or BLOB values in a VdbeCursor */ +typedef struct VdbeTxtBlbCache VdbeTxtBlbCache; + /* Types of VDBE cursors */ #define CURTYPE_BTREE 0 #define CURTYPE_SORTER 1 @@ -22999,6 +23517,7 @@ struct VdbeCursor { 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 */ @@ -23039,6 +23558,7 @@ struct VdbeCursor { #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif + VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for @@ -23051,12 +23571,25 @@ struct VdbeCursor { #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 @@ -23377,16 +23910,18 @@ struct Vdbe { 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; /* True if EXPLAIN present on SQL command */ + bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */ bft changeCntOn:1; /* True to update the change-counter */ 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() */ @@ -23434,7 +23969,7 @@ struct PreUpdate { i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ - Table *pTab; /* Schema object being upated */ + Table *pTab; /* Schema object being updated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; @@ -23524,6 +24059,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); @@ -23805,6 +24341,24 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){ return db->lookaside.nSlot - (nInit+nFree); } +/* +** Hacky, and will be gone once we move WAL encryption layer +** entirely to virtual WAL. +** Assumes the BTree locks are already held. +*/ +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +void *libsql_leak_pager(sqlite3 *db) { + int i; + for(i=0; inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + return sqlite3BtreePager(pBt); + } + } + return NULL; +} +#endif + /* ** Query status information for a single database connection */ @@ -24087,6 +24641,7 @@ struct DateTime { char validTZ; /* True (1) if tz is valid */ char tzSet; /* Timezone was set explicitly */ char isError; /* An overflow has occurred */ + char useSubsec; /* Display subsecond precision */ }; @@ -24119,8 +24674,8 @@ struct DateTime { */ static int getDigits(const char *zDate, const char *zFormat, ...){ /* The aMx[] array translates the 3rd character of each format - ** spec into a max size: a b c d e f */ - static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 }; + ** spec into a max size: a b c d e f */ + static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 }; va_list ap; int cnt = 0; char nextC; @@ -24401,6 +24956,11 @@ static int parseDateOrTime( }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ setRawDateNumber(p, r); return 0; + }else if( (sqlite3StrICmp(zDate,"subsec")==0 + || sqlite3StrICmp(zDate,"subsecond")==0) + && sqlite3NotPureFunc(context) ){ + p->useSubsec = 1; + return setDateTimeToCurrent(context, p); } return 1; } @@ -24456,17 +25016,14 @@ static void computeYMD(DateTime *p){ ** Compute the Hour, Minute, and Seconds from the julian day number. */ static void computeHMS(DateTime *p){ - int s; + int day_ms, day_min; /* milliseconds, minutes into the day */ if( p->validHMS ) return; computeJD(p); - s = (int)((p->iJD + 43200000) % 86400000); - p->s = s/1000.0; - s = (int)p->s; - p->s -= s; - p->h = s/3600; - s -= p->h*3600; - p->m = s/60; - p->s += s - p->m*60; + day_ms = (int)((p->iJD + 43200000) % 86400000); + p->s = (day_ms % 60000)/1000.0; + day_min = day_ms/60000; + p->m = day_min % 60; + p->h = day_min / 60; p->rawS = 0; p->validHMS = 1; } @@ -24645,6 +25202,25 @@ static const struct { { 4, "year", 14713.0, 31536000.0 }, }; +/* +** If the DateTime p is raw number, try to figure out if it is +** a julian day number of a unix timestamp. Set the p value +** appropriately. +*/ +static void autoAdjustDate(DateTime *p){ + if( !p->rawS || p->validJD ){ + p->rawS = 0; + }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */ + && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */ + ){ + double r = p->s*1000.0 + 210866760000000.0; + clearYMD_HMS_TZ(p); + p->iJD = (sqlite3_int64)(r + 0.5); + p->validJD = 1; + p->rawS = 0; + } +} + /* ** Process a modifier to a date-time stamp. The modifiers are ** as follows: @@ -24688,19 +25264,8 @@ static int parseModifier( */ if( sqlite3_stricmp(z, "auto")==0 ){ if( idx>1 ) return 1; /* IMP: R-33611-57934 */ - if( !p->rawS || p->validJD ){ - rc = 0; - 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 */ - ){ - r = p->s*1000.0 + 210866760000000.0; - clearYMD_HMS_TZ(p); - p->iJD = (sqlite3_int64)(r + 0.5); - p->validJD = 1; - p->rawS = 0; - rc = 0; - } + autoAdjustDate(p); + rc = 0; } break; } @@ -24815,8 +25380,22 @@ static int parseModifier( ** ** Move the date backwards to the beginning of the current day, ** or month or year. + ** + ** subsecond + ** subsec + ** + ** Show subsecond precision in the output of datetime() and + ** unixepoch() and strftime('%s'). */ - if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break; + if( sqlite3_strnicmp(z, "start of ", 9)!=0 ){ + if( sqlite3_stricmp(z, "subsec")==0 + || sqlite3_stricmp(z, "subsecond")==0 + ){ + p->useSubsec = 1; + rc = 0; + } + break; + } if( !p->validJD && !p->validYMD && !p->validHMS ) break; z += 9; computeYMD(p); @@ -24852,18 +25431,73 @@ static int parseModifier( case '9': { double rRounder; int i; - for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} + 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 ){ - rc = 1; + assert( rc==1 ); break; } - if( z[n]==':' ){ + if( z[n]=='-' ){ + /* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the + ** specified number of years, months, and days. MM is limited to + ** the range 0-11 and DD is limited to 0-30. + */ + if( z0!='+' && z0!='-' ) break; /* Must start with +/- */ + if( n==5 ){ + if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break; + }else{ + assert( n==6 ); + if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break; + z++; + } + if( M>=12 ) break; /* M range 0..11 */ + if( D>=31 ) break; /* D range 0..30 */ + computeYMD_HMS(p); + p->validJD = 0; + if( z0=='-' ){ + p->Y -= Y; + p->M -= M; + D = -D; + }else{ + p->Y += Y; + p->M += M; + } + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + computeJD(p); + p->validHMS = 0; + p->validYMD = 0; + p->iJD += (i64)D*86400000; + if( z[11]==0 ){ + rc = 0; + break; + } + if( sqlite3Isspace(z[11]) + && getDigits(&z[12], "20c:20e", &h, &m)==2 + ){ + z2 = &z[12]; + n = 2; + }else{ + break; + } + } + if( z2[n]==':' ){ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the ** specified number of hours, minutes, seconds, and fractional seconds ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be ** omitted. */ - const char *z2 = z; + DateTime tx; sqlite3_int64 day; if( !sqlite3Isdigit(*z2) ) z2++; @@ -24873,7 +25507,7 @@ static int parseModifier( tx.iJD -= 43200000; day = tx.iJD/86400000; tx.iJD -= day*86400000; - if( z[0]=='-' ) tx.iJD = -tx.iJD; + if( z0=='-' ) tx.iJD = -tx.iJD; computeJD(p); clearYMD_HMS_TZ(p); p->iJD += tx.iJD; @@ -24889,7 +25523,7 @@ static int parseModifier( if( n>10 || n<3 ) break; if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; computeJD(p); - rc = 1; + assert( rc==1 ); rRounder = r<0 ? -0.5 : +0.5; for(i=0; iM += (int)r; @@ -25014,7 +25647,11 @@ static void unixepochFunc( DateTime x; if( isDate(context, argc, argv, &x)==0 ){ computeJD(&x); - sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000); + 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); + } } } @@ -25030,8 +25667,8 @@ static void datetimeFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - int Y, s; - char zBuf[24]; + int Y, s, n; + char zBuf[32]; computeYMD_HMS(&x); Y = x.Y; if( Y<0 ) Y = -Y; @@ -25052,15 +25689,28 @@ static void datetimeFunc( zBuf[15] = '0' + (x.m/10)%10; zBuf[16] = '0' + (x.m)%10; zBuf[17] = ':'; - s = (int)x.s; - zBuf[18] = '0' + (s/10)%10; - zBuf[19] = '0' + (s)%10; - zBuf[20] = 0; + 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, 20, SQLITE_TRANSIENT); + sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); }else{ - sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT); + sqlite3_result_text(context, &zBuf[1], n-1, SQLITE_TRANSIENT); } } } @@ -25077,7 +25727,7 @@ static void timeFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - int s; + int s, n; char zBuf[16]; computeHMS(&x); zBuf[0] = '0' + (x.h/10)%10; @@ -25086,11 +25736,24 @@ static void timeFunc( zBuf[3] = '0' + (x.m/10)%10; zBuf[4] = '0' + (x.m)%10; zBuf[5] = ':'; - s = (int)x.s; - zBuf[6] = '0' + (s/10)%10; - zBuf[7] = '0' + (s)%10; - zBuf[8] = 0; - sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT); + 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); } } @@ -25145,7 +25808,7 @@ static void dateFunc( ** %M minute 00-59 ** %s seconds since 1970-01-01 ** %S seconds 00-59 -** %w day of week 0-6 sunday==0 +** %w day of week 0-6 Sunday==0 ** %W week of year 00-53 ** %Y year 0000-9999 ** %% % @@ -25171,13 +25834,16 @@ static void strftimeFunc( computeJD(&x); computeYMD_HMS(&x); for(i=j=0; zFmt[i]; i++){ + char cf; if( zFmt[i]!='%' ) continue; if( j12 ) h -= 12; + if( h==0 ) h = 12; + sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); break; } case 'W': /* Fall thru */ @@ -25199,7 +25878,7 @@ static void strftimeFunc( y.D = 1; computeJD(&y); nDay = (int)((x.iJD-y.iJD+43200000)/86400000); - if( zFmt[i]=='W' ){ + if( cf=='W' ){ int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ wd = (int)(((x.iJD+43200000)/86400000)%7); sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7); @@ -25220,18 +25899,42 @@ static void strftimeFunc( 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': { - i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000); - sqlite3_str_appendf(&sRes,"%lld",iS); + 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': /* Fall thru */ case 'w': { - sqlite3_str_appendchar(&sRes, 1, - (char)(((x.iJD+129600000)/86400000) % 7) + '0'); + char c = (char)(((x.iJD+129600000)/86400000) % 7) + '0'; + if( c=='0' && cf=='u' ) c = '7'; + sqlite3_str_appendchar(&sRes, 1, c); break; } case 'Y': { @@ -25280,6 +25983,117 @@ static void cdateFunc( 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; + } + d1.validYMD = 0; + d1.validHMS = 0; + d1.validTZ = 0; + 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() ** @@ -25354,6 +26168,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ 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 ), DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), DFUNCTION(current_date, 0, 0, 0, cdateFunc ), @@ -25507,7 +26322,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite ** is using a regular VFS, it is called after the corresponding ** transaction has been committed. Injecting a fault at this point - ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM + ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM ** but the transaction is committed anyway. ** ** The core must call OsFileControl() though, not OsFileControlHint(), @@ -26128,7 +26943,7 @@ static void *sqlite3MemMalloc(int nByte){ ** or sqlite3MemRealloc(). ** ** For this low-level routine, we already know that pPrior!=0 since -** cases where pPrior==0 will have been intecepted and dealt with +** cases where pPrior==0 will have been intercepted and dealt with ** by higher-level routines. */ static void sqlite3MemFree(void *pPrior){ @@ -26216,7 +27031,7 @@ static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; } len = sizeof(cpuCount); - /* One usually wants to use hw.acctivecpu for MT decisions, but not here */ + /* One usually wants to use hw.activecpu for MT decisions, but not here */ sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0); if( cpuCount>1 ){ /* defer MT decisions to system malloc */ @@ -28208,7 +29023,7 @@ static void checkMutexFree(sqlite3_mutex *p){ assert( SQLITE_MUTEX_FAST<2 ); assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); -#if SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( ((CheckMutex*)p)->iType<2 ) #endif { @@ -28683,7 +29498,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ /* ** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields -** are necessary under two condidtions: (1) Debug builds and (2) using +** are necessary under two conditions: (1) Debug builds and (2) using ** home-grown mutexes. Encapsulate these conditions into a single #define. */ #if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX) @@ -28880,7 +29695,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ */ static void pthreadMutexFree(sqlite3_mutex *p){ assert( p->nRef==0 ); -#if SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) #endif { @@ -29184,7 +29999,7 @@ struct sqlite3_mutex { CRITICAL_SECTION mutex; /* Mutex controlling the lock */ int id; /* Mutex type */ #ifdef SQLITE_DEBUG - volatile int nRef; /* Number of enterances */ + volatile int nRef; /* Number of entrances */ volatile DWORD owner; /* Thread holding this mutex */ volatile LONG trace; /* True to trace changes */ #endif @@ -30444,7 +31259,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ if( db->mallocFailed || rc ){ return apiHandleError(db, rc); } - return rc & db->errMask; + return 0; } /************** End of malloc.c **********************************************/ @@ -30556,57 +31371,6 @@ static const et_info fmtinfo[] = { ** %!S Like %S but prefer the zName over the zAlias */ -/* Floating point constants used for rounding */ -static const double arRound[] = { - 5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05, - 5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10, -}; - -/* -** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point -** conversions will work. -*/ -#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. -** -** 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 */ - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** "*val" is a u64. *msd is a divisor used to extract the -** most significant digit of *val. Extract that most significant -** digit and return it. -*/ -static char et_getdigit_int(u64 *val, u64 *msd){ - u64 x = (*val)/(*msd); - *val -= x*(*msd); - if( *msd>=10 ) *msd /= 10; - return '0' + (char)(x & 15); -} -#endif /* SQLITE_OMIT_FLOATING_POINT */ - /* ** Set the StrAccum object to an error mode. */ @@ -30698,20 +31462,15 @@ SQLITE_API void sqlite3_str_vappendf( u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ - LONGDOUBLE_TYPE realvalue; /* Value for real types */ - sqlite_uint64 msd; /* Divisor to get most-significant-digit - ** of longvalue */ + double realvalue; /* Value for real types */ const et_info *infop; /* Pointer to the appropriate info structure */ char *zOut; /* Rendering buffer */ int nOut; /* Size of the rendering buffer */ char *zExtra = 0; /* Malloced memory used by some conversion */ -#ifndef SQLITE_OMIT_FLOATING_POINT - int exp, e2; /* exponent of real numbers */ - int nsd; /* Number of significant digits returned */ - double rounder; /* Used for rounding floating point values */ + int exp, e2; /* exponent of real numbers */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ -#endif + PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ @@ -30986,84 +31745,61 @@ SQLITE_API void sqlite3_str_vappendf( break; case etFLOAT: case etEXP: - case etGENERIC: + case etGENERIC: { + FpDecode s; + int iRound; + int j; + if( bArgList ){ realvalue = getDoubleArg(pArgList); }else{ realvalue = va_arg(ap,double); } -#ifdef SQLITE_OMIT_FLOATING_POINT - length = 0; -#else if( precision<0 ) precision = 6; /* Set default precision */ #ifdef SQLITE_FP_PRECISION_LIMIT if( precision>SQLITE_FP_PRECISION_LIMIT ){ precision = SQLITE_FP_PRECISION_LIMIT; } #endif - if( realvalue<0.0 ){ - realvalue = -realvalue; - prefix = '-'; + if( xtype==etFLOAT ){ + iRound = -precision; + }else if( xtype==etGENERIC ){ + iRound = precision; }else{ - prefix = flag_prefix; + iRound = precision+1; } - exp = 0; - if( xtype==etGENERIC && precision>0 ) precision--; - testcase( precision>0xfff ); - if( realvalue<1.0e+16 - && realvalue==(LONGDOUBLE_TYPE)(longvalue = (u64)realvalue) - ){ - /* Number is a pure integer that can be represented as u64 */ - for(msd=1; msd*10<=longvalue; msd *= 10, exp++){} - if( exp>precision && xtype!=etFLOAT ){ - u64 rnd = msd/2; - int kk = precision; - while( kk-- > 0 ){ rnd /= 10; } - longvalue += rnd; - } - }else{ - msd = 0; - longvalue = 0; /* To prevent a compiler warning */ - idx = precision & 0xfff; - rounder = arRound[idx%10]; - while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; } - if( xtype==etFLOAT ){ - double rx = (double)realvalue; - sqlite3_uint64 u; - int ex; - memcpy(&u, &rx, sizeof(u)); - ex = -1023 + (int)((u>>52)&0x7ff); - if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16; - realvalue += rounder; - } - if( sqlite3IsNaN((double)realvalue) ){ - bufpt = "NaN"; - length = 3; + sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16); + if( s.isSpecial ){ + if( s.isSpecial==2 ){ + bufpt = flag_zeropad ? "null" : "NaN"; + length = sqlite3Strlen30(bufpt); break; - } - - /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ - if( ALWAYS(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; - } - if( xtype!=etFLOAT ){ - realvalue += rounder; - if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } + }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=='-' ){ + prefix = '-'; + }else{ + prefix = flag_prefix; + } + + exp = s.iDP-1; + if( xtype==etGENERIC && precision>0 ) precision--; /* ** If the field type is etGENERIC, then convert to either etEXP @@ -31083,13 +31819,13 @@ SQLITE_API void sqlite3_str_vappendf( if( xtype==etEXP ){ e2 = 0; }else{ - e2 = exp; + e2 = s.iDP - 1; } - nsd = 16 + flag_altform2*10; 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; @@ -31102,15 +31838,13 @@ SQLITE_API void sqlite3_str_vappendf( *(bufpt++) = prefix; } /* Digits prior to the decimal point */ + j = 0; if( e2<0 ){ *(bufpt++) = '0'; - }else if( msd>0 ){ - for(; e2>=0; e2--){ - *(bufpt++) = et_getdigit_int(&longvalue,&msd); - } }else{ for(; e2>=0; e2--){ - *(bufpt++) = et_getdigit(&realvalue,&nsd); + *(bufpt++) = j1 ) *(bufpt++) = ','; } } /* The decimal point */ @@ -31119,19 +31853,12 @@ SQLITE_API void sqlite3_str_vappendf( } /* "0" digits after the decimal point but before the first ** significant digit of the number */ - for(e2++; e2<0; precision--, e2++){ - assert( precision>0 ); + for(e2++; e2<0 && precision>0; precision--, e2++){ *(bufpt++) = '0'; } /* Significant digits after the decimal point */ - if( msd>0 ){ - while( (precision--)>0 ){ - *(bufpt++) = et_getdigit_int(&longvalue,&msd); - } - }else{ - while( (precision--)>0 ){ - *(bufpt++) = et_getdigit(&realvalue,&nsd); - } + while( (precision--)>0 ){ + *(bufpt++) = jcharset]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; @@ -31180,8 +31908,8 @@ SQLITE_API void sqlite3_str_vappendf( while( nPad-- ) bufpt[i++] = '0'; length = width; } -#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ break; + } case etSIZE: if( !bArgList ){ *(va_arg(ap,int*)) = pAccum->nChar; @@ -31905,6 +32633,75 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ va_end(ap); } + +/***************************************************************************** +** Reference counted string 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 ****************************************/ /* @@ -32321,6 +33118,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u sqlite3TreeViewItem(pView, "FILTER", 1); sqlite3TreeViewExpr(pView, pWin->pFilter, 0); sqlite3TreeViewPop(&pView); + if( pWin->eFrmType==TK_FILTER ) return; } sqlite3TreeViewPush(&pView, more); if( pWin->zName ){ @@ -32330,7 +33128,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u } if( pWin->zBase ) nElement++; if( pWin->pOrderBy ) nElement++; - if( pWin->eFrmType ) nElement++; + if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++; if( pWin->eExclude ) nElement++; if( pWin->zBase ){ sqlite3TreeViewPush(&pView, (--nElement)>0); @@ -32343,7 +33141,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u if( pWin->pOrderBy ){ sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); } - if( pWin->eFrmType ){ + if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){ char zBuf[30]; const char *zFrmType = "ROWS"; if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; @@ -32552,7 +33350,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m }; assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); assert( pExpr->pRight ); - assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE ); + assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op + == TK_TRUEFALSE ); x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); zUniOp = azOp[x]; break; @@ -32590,7 +33389,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m assert( ExprUseXList(pExpr) ); pFarg = pExpr->x.pList; #ifndef SQLITE_OMIT_WINDOWFUNC - pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0; + pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0; #else pWin = 0; #endif @@ -32616,7 +33415,13 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); } if( pFarg ){ - sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); + sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0); + if( pExpr->pLeft ){ + Expr *pOB = pExpr->pLeft; + assert( pOB->op==TK_ORDER ); + assert( ExprUseXList(pOB) ); + sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY"); + } } #ifndef SQLITE_OMIT_WINDOWFUNC if( pWin ){ @@ -32625,6 +33430,10 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m #endif break; } + case TK_ORDER: { + sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY"); + break; + } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: { assert( ExprUseXSelect(pExpr) ); @@ -34211,7 +35020,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){ /* ** Calls to sqlite3FaultSim() are used to simulate a failure during testing, ** or to bypass normal error detection during testing in order to let -** execute proceed futher downstream. +** execute proceed further downstream. ** ** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The ** sqlite3FaultSim() function only returns non-zero during testing. @@ -34328,6 +35137,23 @@ SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){ */ SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ if( rc==SQLITE_IOERR_NOMEM ) return; +#ifdef SQLITE_USE_SEH + 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); @@ -34372,12 +35198,16 @@ SQLITE_PRIVATE void sqlite3ProgressCheck(Parse *p){ p->rc = SQLITE_INTERRUPT; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress && (++p->nProgressSteps)>=db->nProgressOps ){ - if( db->xProgress(db->pProgressArg) ){ - p->nErr++; - p->rc = SQLITE_INTERRUPT; + 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; } - p->nProgressSteps = 0; } #endif } @@ -34573,43 +35403,40 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ return h; } -/* -** Compute 10 to the E-th power. Examples: E==1 results in 10. -** E==2 results in 100. E==50 results in 1.0e50. +/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) ** -** This routine only works for values of E between 1 and 341. +** Reference: +** T. J. Dekker, "A Floating-Point Technique for Extending the +** Available Precision". 1971-07-26. */ -static LONGDOUBLE_TYPE sqlite3Pow10(int E){ -#if defined(_MSC_VER) - static const LONGDOUBLE_TYPE x[] = { - 1.0e+001L, - 1.0e+002L, - 1.0e+004L, - 1.0e+008L, - 1.0e+016L, - 1.0e+032L, - 1.0e+064L, - 1.0e+128L, - 1.0e+256L - }; - LONGDOUBLE_TYPE r = 1.0; - int i; - assert( E>=0 && E<=307 ); - for(i=0; E!=0; i++, E >>=1){ - if( E & 1 ) r *= x[i]; - } - return r; -#else - LONGDOUBLE_TYPE x = 10.0; - LONGDOUBLE_TYPE r = 1.0; - while(1){ - if( E & 1 ) r *= x; - E >>= 1; - if( E==0 ) break; - x *= x; - } - return r; -#endif +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; } /* @@ -34650,12 +35477,11 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ - i64 s = 0; /* significand */ + u64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ - double result; int nDigit = 0; /* Number of digits processed */ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ @@ -34695,7 +35521,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en while( z=((LARGEST_INT64-9)/10) ){ + if( s>=((LARGEST_UINT64-9)/10) ){ /* skip non-significant significand digits ** (increase exponent by d to shift decimal left) */ while( z0 ){ /*OPTIMIZATION-IF-TRUE*/ - if( esign>0 ){ - if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ - s *= 10; - }else{ - if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ - s /= 10; - } - e--; - } + /* adjust exponent by d, and update sign */ + e = (e*esign) + d; - /* adjust the sign of significand */ - s = sign<0 ? -s : s; + /* Try to adjust the exponent to make it smaller */ + while( e>0 && s<(LARGEST_UINT64/10) ){ + s *= 10; + e--; + } + while( e<0 && (s%10)==0 ){ + s /= 10; + e++; + } - if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ - result = (double)s; + if( e==0 ){ + *pResult = s; + }else if( sqlite3Config.bUseLongDouble ){ + LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s; + if( e>0 ){ + while( e>=100 ){ e-=100; r *= 1.0e+100L; } + while( e>=10 ){ e-=10; r *= 1.0e+10L; } + while( e>=1 ){ e-=1; r *= 1.0e+01L; } }else{ - /* attempt to handle extremely small/large numbers better */ - if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ - if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ - LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); - if( esign<0 ){ - result = s / scale; - result /= 1.0e+308; - }else{ - result = s * scale; - result *= 1.0e+308; - } - }else{ assert( e>=342 ); - if( esign<0 ){ - result = 0.0*s; - }else{ + while( e<=-100 ){ e+=100; r *= 1.0e-100L; } + while( e<=-10 ){ e+=10; r *= 1.0e-10L; } + while( e<=-1 ){ e+=1; r *= 1.0e-01L; } + } + assert( r>=0.0 ); + if( r>+1.7976931348623157081452742373e+308L ){ #ifdef INFINITY - result = INFINITY*s; + *pResult = +INFINITY; #else - result = 1e308*1e308*s; /* Infinity */ + *pResult = 1.0e308*10.0; #endif - } - } - }else{ - LONGDOUBLE_TYPE scale = sqlite3Pow10(e); - if( esign<0 ){ - result = s / scale; - }else{ - result = s * scale; - } + }else{ + *pResult = (double)r; + } + }else{ + double rr[2]; + u64 s2; + rr[0] = (double)s; + s2 = (u64)rr[0]; + rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); + 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) ); - /* store the result */ - *pResult = result; - - /* return true if number and no extra non-whitespace chracters after */ +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 ){ @@ -34857,13 +35693,15 @@ SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){ } i = sizeof(zTemp)-2; zTemp[sizeof(zTemp)-1] = 0; - do{ - zTemp[i--] = (x%10) + '0'; + while( 1 /*exit-by-break*/ ){ + zTemp[i] = (x%10) + '0'; x = x/10; - }while( x ); - if( v<0 ) zTemp[i--] = '-'; - memcpy(zOut, &zTemp[i+1], sizeof(zTemp)-1-i); - return sizeof(zTemp)-2-i; + if( x==0 ) break; + i--; + }; + if( v<0 ) zTemp[--i] = '-'; + memcpy(zOut, &zTemp[i], sizeof(zTemp)-i); + return sizeof(zTemp)-1-i; } /* @@ -34956,7 +35794,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc /* 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 appaise the undefined-behavior pharisees. */ + ** them, but we must appease the undefined-behavior pharisees. */ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; }else if( neg ){ *pNum = -(i64)u; @@ -35028,11 +35866,15 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ u = u*16 + sqlite3HexToInt(z[k]); } memcpy(pOut, &u, 8); - return (z[k]==0 && k-i<=16) ? 0 : 2; + if( k-i>16 ) return 2; + if( z[k]!=0 ) return 1; + return 0; }else #endif /* SQLITE_OMIT_HEX_INTEGER */ { - return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); + int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789")); + if( z[n] ) n++; + return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8); } } @@ -35064,7 +35906,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){ u32 u = 0; zNum += 2; while( zNum[0]=='0' ) zNum++; - for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){ + for(i=0; i<8 && sqlite3Isxdigit(zNum[i]); i++){ u = u*16 + sqlite3HexToInt(zNum[i]); } if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ @@ -35111,6 +35953,153 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ return x; } +/* +** Decode a floating-point value into an approximate decimal +** representation. +** +** Round the decimal representation to n significant digits if +** n is positive. Or round to -n signficant digits after the +** decimal point if n is negative. No rounding is performed if +** n is zero. +** +** 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; + p->isSpecial = 0; + p->z = p->zBuf; + + /* 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. + */ + if( sqlite3Config.bUseLongDouble ){ + LONGDOUBLE_TYPE rr = r; + if( rr>=1.0e+19 ){ + while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; } + while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; } + while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; } + }else{ + while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; } + while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; } + while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; } + } + v = (u64)rr; + }else{ + /* If high-precision floating point is not available using "long double", + ** then 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))); + */ + double rr[2]; + 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. @@ -35374,121 +36363,32 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ ** this function assumes the single-byte case has already been handled. */ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ - u32 a,b; + u64 v64; + u8 n; - /* The 1-byte case. Overwhelmingly the most common. Handled inline - ** by the getVarin32() macro */ - a = *p; - /* a: p0 (unmasked) */ -#ifndef getVarint32 - if (!(a&0x80)) - { - /* Values between 0 and 127 */ - *v = a; - return 1; - } -#endif + /* Assume that the single-byte case has already been handled by + ** the getVarint32() macro */ + assert( (p[0] & 0x80)!=0 ); - /* The 2-byte case */ - p++; - b = *p; - /* b: p1 (unmasked) */ - if (!(b&0x80)) - { - /* Values between 128 and 16383 */ - a &= 0x7f; - a = a<<7; - *v = a | b; + if( (p[1] & 0x80)==0 ){ + /* This is the two-byte case */ + *v = ((p[0]&0x7f)<<7) | p[1]; return 2; } - - /* The 3-byte case */ - p++; - a = a<<14; - a |= *p; - /* a: p0<<14 | p2 (unmasked) */ - if (!(a&0x80)) - { - /* Values between 16384 and 2097151 */ - a &= (0x7f<<14)|(0x7f); - b &= 0x7f; - b = b<<7; - *v = a | b; + if( (p[2] & 0x80)==0 ){ + /* This is the three-byte case */ + *v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2]; return 3; } - - /* A 32-bit varint is used to store size information in btrees. - ** Objects are rarely larger than 2MiB limit of a 3-byte varint. - ** A 3-byte varint is sufficient, for example, to record the size - ** of a 1048569-byte BLOB or string. - ** - ** We only unroll the first 1-, 2-, and 3- byte cases. The very - ** rare larger cases can be handled by the slower 64-bit varint - ** routine. - */ -#if 1 - { - u64 v64; - u8 n; - - n = sqlite3GetVarint(p-2, &v64); - assert( n>3 && n<=9 ); - if( (v64 & SQLITE_MAX_U32)!=v64 ){ - *v = 0xffffffff; - }else{ - *v = (u32)v64; - } - return n; - } - -#else - /* For following code (kept for historical record only) shows an - ** unrolling for the 3- and 4-byte varint cases. This code is - ** slightly faster, but it is also larger and much harder to test. - */ - p++; - b = b<<14; - b |= *p; - /* b: p1<<14 | p3 (unmasked) */ - if (!(b&0x80)) - { - /* Values between 2097152 and 268435455 */ - b &= (0x7f<<14)|(0x7f); - a &= (0x7f<<14)|(0x7f); - a = a<<7; - *v = a | b; - return 4; - } - - p++; - a = a<<14; - a |= *p; - /* a: p0<<28 | p2<<14 | p4 (unmasked) */ - if (!(a&0x80)) - { - /* Values between 268435456 and 34359738367 */ - a &= SLOT_4_2_0; - b &= SLOT_4_2_0; - b = b<<7; - *v = a | b; - return 5; - } - - /* We can only reach this point when reading a corrupt database - ** file. In that case we are not in any hurry. Use the (relatively - ** slow) general-purpose sqlite3GetVarint() routine to extract the - ** value. */ - { - u64 v64; - u8 n; - - p -= 4; - n = sqlite3GetVarint(p, &v64); - assert( n>5 && n<=9 ); + /* four or more bytes */ + n = sqlite3GetVarint(p, &v64); + assert( n>3 && n<=9 ); + if( (v64 & SQLITE_MAX_U32)!=v64 ){ + *v = 0xffffffff; + }else{ *v = (u32)v64; - return n; } -#endif + return n; } /* @@ -35639,7 +36539,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ } /* -** Attempt to add, substract, or multiply the 64-bit signed value iB against +** Attempt to add, subtract, or multiply the 64-bit signed value iB against ** the other 64-bit signed integer at *pA and store the result in *pA. ** Return 0 on success. Or if the operation would have resulted in an ** overflow, leave *pA unchanged and return 1. @@ -35952,7 +36852,7 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam #define SQLITE_HWTIME_H /* -** The following routine only works on pentium-class (or newer) processors. +** 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. @@ -36124,7 +37024,7 @@ static void insertElement( } -/* Resize the hash table so that it cantains "new_size" buckets. +/* Resize the hash table so that it contains "new_size" buckets. ** ** The hash table might fail to resize if sqlite3_malloc() fails or ** if the new size is the same as the prior size. @@ -36329,8 +37229,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 16 */ "If" OpHelp(""), /* 17 */ "IfNot" OpHelp(""), /* 18 */ "IsType" OpHelp("if typeof(P1.P3) in P5 goto P2"), - /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), + /* 19 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), + /* 20 */ "Not" OpHelp("r[P2]= !r[P1]"), /* 21 */ "SeekLT" OpHelp("key=r[P3@P4]"), /* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"), /* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"), @@ -36356,23 +37256,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 43 */ "IdxGE" OpHelp("key=r[P3@P4]"), /* 44 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 46 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 47 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 48 */ "Program" OpHelp(""), + /* 46 */ "Program" OpHelp(""), + /* 47 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 48 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), /* 51 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), /* 52 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 53 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 54 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 55 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), - /* 56 */ "Eq" OpHelp("IF r[P3]==r[P1]"), - /* 57 */ "Gt" OpHelp("IF r[P3]>r[P1]"), - /* 58 */ "Le" OpHelp("IF r[P3]<=r[P1]"), - /* 59 */ "Lt" OpHelp("IF r[P3]=r[P1]"), - /* 61 */ "ElseEq" OpHelp(""), - /* 62 */ "IncrVacuum" OpHelp(""), + /* 53 */ "IncrVacuum" OpHelp(""), + /* 54 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 55 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 56 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), + /* 57 */ "Eq" OpHelp("IF r[P3]==r[P1]"), + /* 58 */ "Gt" OpHelp("IF r[P3]>r[P1]"), + /* 59 */ "Le" OpHelp("IF r[P3]<=r[P1]"), + /* 60 */ "Lt" OpHelp("IF r[P3]=r[P1]"), + /* 62 */ "ElseEq" 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])"), @@ -36415,23 +37315,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"), /* 103 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), /* 104 */ "OpenDup" OpHelp(""), - /* 105 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 106 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 107 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 109 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 110 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 111 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 112 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 113 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 114 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 115 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 105 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 106 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), + /* 107 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), + /* 108 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), + /* 110 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), + /* 111 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), + /* 112 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), + /* 113 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), + /* 114 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), + /* 115 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), /* 116 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 117 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), - /* 118 */ "SorterOpen" OpHelp(""), + /* 117 */ "SorterOpen" OpHelp(""), + /* 118 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), /* 119 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 120 */ "String8" OpHelp("r[P2]='P4'"), - /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 120 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 121 */ "String8" OpHelp("r[P2]='P4'"), /* 122 */ "Close" OpHelp(""), /* 123 */ "ColumnsUsed" OpHelp(""), /* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"), @@ -36467,8 +37367,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 154 */ "DropIndex" OpHelp(""), /* 155 */ "DropTrigger" OpHelp(""), /* 156 */ "IntegrityCk" OpHelp(""), - /* 157 */ "Real" OpHelp("r[P2]=P4"), - /* 158 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 157 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 158 */ "Real" OpHelp("r[P2]=P4"), /* 159 */ "Param" OpHelp(""), /* 160 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), /* 161 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), @@ -36486,20 +37386,21 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 173 */ "VCreate" OpHelp(""), /* 174 */ "VDestroy" OpHelp(""), /* 175 */ "VOpen" OpHelp(""), - /* 176 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), - /* 177 */ "VPreparedSql" OpHelp(""), - /* 178 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 179 */ "VRename" OpHelp(""), - /* 180 */ "Pagecount" OpHelp(""), - /* 181 */ "MaxPgcnt" OpHelp(""), - /* 182 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), - /* 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(""), + /* 176 */ "VCheck" OpHelp(""), + /* 177 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), + /* 178 */ "VPreparedSql" OpHelp(""), + /* 179 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 180 */ "VRename" OpHelp(""), + /* 181 */ "Pagecount" OpHelp(""), + /* 182 */ "MaxPgcnt" OpHelp(""), + /* 183 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), + /* 184 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), + /* 185 */ "Trace" OpHelp(""), + /* 186 */ "CursorHint" OpHelp(""), + /* 187 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), + /* 188 */ "Noop" OpHelp(""), + /* 189 */ "Explain" OpHelp(""), + /* 190 */ "Abortable" OpHelp(""), }; return azName[i]; } @@ -37513,7 +38414,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){ ** This source file is organized into divisions where the logic for various ** subfunctions is contained within the appropriate division. PLEASE ** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed -** in the correct division and should be clearly labeled. +** in the correct division and should be clearly labelled. ** ** The layout of divisions is as follows: ** @@ -37563,7 +38464,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){ #endif /* Use pread() and pwrite() if they are available */ -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__linux__) # define HAVE_PREAD 1 # define HAVE_PWRITE 1 #endif @@ -37586,7 +38487,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){ /* #include */ #include /* amalgamator: keep */ #include -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ +#if (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) \ && !defined(SQLITE_WASI) # include #endif @@ -38026,7 +38927,7 @@ static struct unix_syscall { #endif #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ +#if (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) \ && !defined(SQLITE_WASI) { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, #else @@ -38034,7 +38935,7 @@ static struct unix_syscall { #endif #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent) -#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ +#if (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) \ && !defined(SQLITE_WASI) { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, #else @@ -38042,14 +38943,14 @@ static struct unix_syscall { #endif #define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent) -#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if HAVE_MREMAP && (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, #else { "mremap", (sqlite3_syscall_ptr)0, 0 }, #endif #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent) -#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +#if !defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0 { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 }, #else { "getpagesize", (sqlite3_syscall_ptr)0, 0 }, @@ -38100,7 +39001,7 @@ static int robustFchown(int fd, uid_t uid, gid_t gid){ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "unix" VFSes. Return SQLITE_OK opon successfully updating the +** "unix" VFSes. Return SQLITE_OK upon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. */ @@ -38622,7 +39523,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ ** If you close a file descriptor that points to a file that has locks, ** all locks on that file that are owned by the current process are ** released. To work around this problem, each unixInodeInfo object -** maintains a count of the number of pending locks on tha inode. +** maintains a count of the number of pending locks on the inode. ** When an attempt is made to close an unixFile, if there are ** other unixFile open on the same inode that are holding locks, the call ** to close() the file descriptor is deferred until all of the locks clear. @@ -38636,7 +39537,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ ** not posix compliant. Under LinuxThreads, a lock created by thread ** A cannot be modified or overridden by a different thread B. ** Only thread A can modify the lock. Locking behavior is correct -** if the appliation uses the newer Native Posix Thread Library (NPTL) +** if the application uses the newer Native Posix Thread Library (NPTL) ** on linux - with NPTL a lock created by thread A can override locks ** in thread B. But there is no way to know at compile-time which ** threading library is being used. So there is no way to know at @@ -38838,7 +39739,7 @@ static void storeLastErrno(unixFile *pFile, int error){ } /* -** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. +** Close all file descriptors accumulated in the unixInodeInfo->pUnused list. */ static void closePendingFds(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; @@ -39201,7 +40102,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** slightly in order to be compatible with Windows95 systems simultaneously ** accessing the same database file, in case that is ever required. ** - ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved + ** Symbols defined in os.h identify the 'pending byte' and the 'reserved ** byte', each single bytes at well known offsets, and the 'shared byte ** range', a range of 510 bytes at a well known offset. ** @@ -39209,7 +40110,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** byte'. If this is successful, 'shared byte range' is read-locked ** and the lock on the 'pending byte' released. (Legacy note: When ** SQLite was first developed, Windows95 systems were still very common, - ** and Widnows95 lacks a shared-lock capability. So on Windows95, a + ** and Windows95 lacks a shared-lock capability. So on Windows95, a ** single randomly selected by from the 'shared byte range' is locked. ** Windows95 is now pretty much extinct, but this work-around for the ** lack of shared-locks on Windows95 lives on, for backwards @@ -39230,7 +40131,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ ** 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 intead. The client may + ** 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. */ @@ -39258,7 +40159,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ /* Make sure the locking sequence is correct. ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pendig lock. + ** (2) SQLite never explicitly requests a pending lock. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); @@ -40476,7 +41377,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ /* Make sure the locking sequence is correct ** (1) We never move from unlocked to anything higher than shared lock. - ** (2) SQLite never explicitly requests a pendig lock. + ** (2) SQLite never explicitly requests a pending lock. ** (3) A shared lock is always held when a reserve lock is requested. */ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK ); @@ -40592,7 +41493,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + pInode->sharedByte, 1, 0)) ){ int failed2 = SQLITE_OK; - /* now attemmpt to get the exclusive lock range */ + /* now attempt to get the exclusive lock range */ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 1); if( failed && (failed2 = afpSetLock(context->dbPath, pFile, @@ -40641,9 +41542,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { unixInodeInfo *pInode; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int skipShared = 0; -#ifdef SQLITE_TEST - int h = pFile->h; -#endif assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, @@ -40659,9 +41557,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { assert( pInode->nShared!=0 ); if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); - SimulateIOErrorBenign(1); - SimulateIOError( h=(-1) ) - SimulateIOErrorBenign(0); #ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start @@ -40710,9 +41605,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; pInode->nShared--; if( pInode->nShared==0 ){ - SimulateIOErrorBenign(1); - SimulateIOError( h=(-1) ) - SimulateIOErrorBenign(0); if( !skipShared ){ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); } @@ -40813,12 +41705,6 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){ ** 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. */ @@ -40893,7 +41779,7 @@ static int unixRead( #endif #if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transfering + /* Deal with as much of this read request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -41045,7 +41931,7 @@ static int unixWrite( #endif #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transfering + /* Deal with as much of this write request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -41167,7 +42053,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a ** no-op. But go ahead and call fstat() to validate the file ** descriptor as we need a method to provoke a failure during - ** coverate testing. + ** coverage testing. */ #ifdef SQLITE_NO_SYNC { @@ -41489,7 +42375,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){ /* Forward declaration */ static int unixGetTempname(int nBuf, char *zBuf); -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM static int unixFcntlExternalReader(unixFile*, int*); #endif @@ -41610,7 +42496,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ case SQLITE_FCNTL_EXTERNAL_READER: { -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM return unixFcntlExternalReader((unixFile*)id, (int*)pArg); #else *(int*)pArg = 0; @@ -41763,7 +42649,7 @@ static int unixDeviceCharacteristics(sqlite3_file *id){ return pFd->deviceCharacteristics; } -#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +#if !defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0 /* ** Return the system page size. @@ -41781,9 +42667,9 @@ static int unixGetpagesize(void){ #endif } -#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */ +#endif /* !defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0 */ -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM /* ** Object used to represent an shared memory buffer. @@ -42649,7 +43535,7 @@ static int unixShmUnmap( # define unixShmLock 0 # define unixShmBarrier 0 # define unixShmUnmap 0 -#endif /* #ifndef SQLITE_OMIT_WAL */ +#endif /* #ifndef SQLITE_OMIT_SHARED_MEM */ #if SQLITE_MAX_MMAP_SIZE>0 /* @@ -44212,12 +45098,17 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** than the argument. */ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ -#if OS_VXWORKS || _POSIX_C_SOURCE >= 199309L +#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0 struct timespec sp; - sp.tv_sec = microseconds / 1000000; sp.tv_nsec = (microseconds % 1000000) * 1000; + + /* Almost all modern unix systems support nanosleep(). But if you are + ** compiling for one of the rare exceptions, you can use + ** -DHAVE_NANOSLEEP=0 (perhaps in 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 @@ -45606,7 +46497,7 @@ SQLITE_API int sqlite3_os_init(void){ #endif unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM /* Validate lock assumptions */ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */ @@ -45677,9 +46568,9 @@ SQLITE_API int sqlite3_os_end(void){ ** Compiling and using WAL mode requires several APIs that are only ** available in Windows platforms based on the NT kernel. */ -#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) +#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_SHARED_MEM) # error "WAL mode requires support from the Windows NT kernel, compile\ - with SQLITE_OMIT_WAL." + with SQLITE_OMIT_SHARED_MEM." #endif #if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0 @@ -45837,7 +46728,7 @@ SQLITE_API int sqlite3_os_end(void){ ** CE SDK; however, they are not present in the header file)? */ #if SQLITE_WIN32_FILEMAPPING_API && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) /* ** Two of the file mapping APIs are different under WinRT. Figure out which ** set we need. @@ -45884,7 +46775,7 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); # define FILE_ATTRIBUTE_MASK (0x0003FFF7) #endif -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM /* Forward references to structures used for WAL */ typedef struct winShm winShm; /* A connection to shared-memory */ typedef struct winShmNode winShmNode; /* A region of shared-memory */ @@ -45916,7 +46807,7 @@ struct winFile { short sharedLockByte; /* Randomly chosen byte used as a shared lock */ u8 ctrlFlags; /* Flags. See WINFILE_* below */ DWORD lastErrno; /* The Windows errno from the last I/O error */ -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM winShm *pShm; /* Instance of shared memory on this file */ #endif const char *zPath; /* Full pathname of this file */ @@ -46204,7 +47095,7 @@ static struct win_syscall { LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ + (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) && \ SQLITE_WIN32_CREATEFILEMAPPINGA { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, #else @@ -46215,7 +47106,7 @@ static struct win_syscall { DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, @@ -46555,7 +47446,7 @@ static struct win_syscall { #endif #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0)) { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, #else { "MapViewOfFile", (SYSCALL)0, 0 }, @@ -46625,7 +47516,7 @@ static struct win_syscall { #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[58].pCurrent) -#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0 { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, #else { "UnmapViewOfFile", (SYSCALL)0, 0 }, @@ -46688,7 +47579,7 @@ static struct win_syscall { #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) -#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, #else { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, @@ -46752,7 +47643,7 @@ static struct win_syscall { #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) -#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_SHARED_MEM) || SQLITE_MAX_MMAP_SIZE>0) { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, #else { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, @@ -46807,7 +47698,7 @@ static struct win_syscall { /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the -** "win32" VFSes. Return SQLITE_OK opon successfully updating the +** "win32" VFSes. Return SQLITE_OK upon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. */ @@ -48314,7 +49205,7 @@ static int winClose(sqlite3_file *id){ winFile *pFile = (winFile*)id; assert( id!=0 ); -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM assert( pFile->pShm==0 ); #endif assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); @@ -48387,7 +49278,7 @@ static int winRead( pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this read request as possible by transfering + /* Deal with as much of this read request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -48465,7 +49356,7 @@ static int winWrite( pFile->h, pBuf, amt, offset, pFile->locktype)); #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 - /* Deal with as much of this write request as possible by transfering + /* Deal with as much of this write request as possible by transferring ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ @@ -48575,7 +49466,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ ** all references to memory-mapped content are closed. That is doable, ** but involves adding a few branches in the common write code path which ** could slow down normal operations slightly. Hence, we have decided for - ** now to simply make trancations a no-op if there are pending reads. We + ** now to simply make transactions a no-op if there are pending reads. We ** can maybe revisit this decision in the future. */ return SQLITE_OK; @@ -48634,7 +49525,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test -** that syncs and fullsyncs are occuring at the right times. +** that syncs and fullsyncs are occurring at the right times. */ SQLITE_API int sqlite3_sync_count = 0; SQLITE_API int sqlite3_fullsync_count = 0; @@ -48991,7 +49882,7 @@ static int winLock(sqlite3_file *id, int locktype){ */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); - res = winUnlockReadLock(pFile); + (void)winUnlockReadLock(pFile); res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ @@ -49320,7 +50211,7 @@ static int winDeviceCharacteristics(sqlite3_file *id){ */ static SYSTEM_INFO winSysInfo; -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM /* ** Helper functions to obtain and relinquish the global mutex. The @@ -50005,7 +50896,7 @@ static int winShmMap( # define winShmLock 0 # define winShmBarrier 0 # define winShmUnmap 0 -#endif /* #ifndef SQLITE_OMIT_WAL */ +#endif /* #ifndef SQLITE_OMIT_SHARED_MEM */ /* ** Cleans up the mapped region of the specified file, if any. @@ -50395,6 +51286,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; size_t i, j; + DWORD pid; int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX); int nMax, nBuf, nDir, nLen; char *zBuf; @@ -50607,7 +51499,10 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ 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; @@ -50845,7 +51740,7 @@ static int winOpen( if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } @@ -50862,7 +51757,7 @@ static int winOpen( if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } @@ -50882,7 +51777,7 @@ static int winOpen( if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); - rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } @@ -51105,6 +52000,13 @@ static int winAccess( 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)); @@ -51818,7 +52720,7 @@ SQLITE_API int sqlite3_os_init(void){ sqlite3_vfs_register(&winLongPathNolockVfs, 0); #endif -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); #endif @@ -51833,7 +52735,7 @@ SQLITE_API int sqlite3_os_end(void){ } #endif -#ifndef SQLITE_OMIT_WAL +#ifndef SQLITE_OMIT_SHARED_MEM winBigLock = 0; #endif @@ -52866,7 +53768,7 @@ SQLITE_PRIVATE int sqlite3MemdbInit(void){ ** values between 1 and iDivisor. apSub[1] holds values between ** iDivisor+1 and 2*iDivisor. apSub[N] holds values between ** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized -** to hold deal with values between 1 and iDivisor. +** to deal with values between 1 and iDivisor. */ struct Bitvec { u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */ @@ -52965,7 +53867,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ h = BITVEC_HASH(i++); /* if there wasn't a hash collision, and this doesn't */ /* completely fill the hash, then just add it without */ - /* worring about sub-dividing and re-hashing. */ + /* worrying about sub-dividing and re-hashing. */ if( !p->u.aHash[h] ){ if (p->nSet<(BITVEC_NINT-1)) { goto bitvec_set_end; @@ -53232,7 +54134,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ - int nRefSum; /* Sum of ref counts over all pages */ + i64 nRefSum; /* Sum of ref counts over all pages */ int szCache; /* Configured cache size */ int szSpill; /* Size before spilling occurs */ int szPage; /* Size of every page in this cache */ @@ -53261,11 +54163,15 @@ struct PCache { PgHdr *pPg; unsigned char *a; int j; - 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(" ptr %p\n", pPg); + 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; @@ -53278,9 +54184,8 @@ struct PCache { if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; for(i=1; i<=N; i++){ pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); - if( pLower==0 ) continue; pcachePageTrace(i, pLower); - if( ((PgHdr*)pLower)->pPage==0 ){ + if( pLower && ((PgHdr*)pLower)->pPage==0 ){ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); } } @@ -53295,7 +54200,7 @@ struct PCache { ** Return 1 if pPg is on the dirty list for pCache. Return 0 if not. ** This routine runs inside of assert() statements only. */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){ PgHdr *p; for(p=pCache->pDirty; p; p=p->pDirtyNext){ @@ -53303,6 +54208,16 @@ static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){ } 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 /* @@ -53323,7 +54238,7 @@ SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ assert( pCache!=0 ); /* Every page has an associated PCache */ if( pPg->flags & PGHDR_CLEAN ){ assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ - assert( !pageOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirty list */ + 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 ); @@ -53459,7 +54374,7 @@ static int numberOfCachePages(PCache *p){ return p->szCache; }else{ i64 n; - /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the + /* 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. */ @@ -53947,7 +54862,7 @@ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ } /* -** Sort the list of pages in accending order by pgno. Pages are +** Sort the list of pages in ascending order by pgno. Pages are ** connected by pDirty pointers. The pDirtyPrev pointers are ** corrupted by this sort. ** @@ -54006,14 +54921,14 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){ ** This is not the total number of pages referenced, but the sum of the ** reference count for all pages. */ -SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){ +SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache *pCache){ return pCache->nRefSum; } /* ** Return the number of references to the page supplied as an argument. */ -SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){ +SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr *p){ return p->nRef; } @@ -54187,7 +55102,7 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd ** If N is positive, then N pages worth of memory are allocated using a single ** sqlite3Malloc() call and that memory is used for the first N pages allocated. ** Or if N is negative, then -1024*N bytes of memory are allocated and used -** for as many pages as can be accomodated. +** for as many pages as can be accommodated. ** ** Only one of (2) or (3) can be used. Once the memory available to (2) or ** (3) is exhausted, subsequent allocations fail over to the general-purpose @@ -54221,7 +55136,7 @@ typedef struct PGroup PGroup; ** in memory directly after the associated page data, if the database is ** corrupt, code at the b-tree layer may overread the page buffer and ** read part of this structure before the corruption is detected. This -** can cause a valgrind error if the unitialized gap is accessed. Using u16 +** 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. ** @@ -55441,7 +56356,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ** The TEST primitive includes a "batch" number. The TEST primitive ** will only see elements that were inserted before the last change ** in the batch number. In other words, if an INSERT occurs between -** two TESTs where the TESTs have the same batch nubmer, then the +** two TESTs where the TESTs have the same batch number, then the ** value added by the INSERT will not be visible to the second TEST. ** The initial batch number is zero, so if the very first TEST contains ** a non-zero batch number, it will see all prior INSERTs. @@ -55960,15 +56875,16 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 ** There is one object of this type for each pager. */ typedef struct libsql_wal libsql_wal; +typedef struct libsql_wal_manager libsql_wal_manager; +/* Opaque types for wal method data */ +typedef struct wal_impl wal_impl; +typedef struct wal_manager_impl wal_manager_impl; typedef struct libsql_wal_methods { int iVersion; /* Current version is 1, versioning is here for backward compatibility */ - /* Open and close a connection to a write-ahead log. */ - int (*xOpen)(sqlite3_vfs*, sqlite3_file* , const char*, int no_shm_mode, long long max_size, struct libsql_wal_methods*, libsql_wal**); - int (*xClose)(libsql_wal*, sqlite3* db, int sync_flags, int nBuf, unsigned char *zBuf); /* Set the limiting size of a WAL file. */ - void (*xLimit)(libsql_wal*, long long limit); + void (*xLimit)(wal_impl* pWal, long long limit); /* 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 @@ -55977,37 +56893,37 @@ typedef struct libsql_wal_methods { ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the ** transaction and releases the lock. */ - int (*xBeginReadTransaction)(libsql_wal *, int *); - void (*xEndReadTransaction)(libsql_wal *); + int (*xBeginReadTransaction)(wal_impl* pWal, int *); + void (*xEndReadTransaction)(wal_impl *); /* Read a page from the write-ahead log, if it is present. */ - int (*xFindFrame)(libsql_wal *, unsigned int, unsigned int *); - int (*xReadFrame)(libsql_wal *, unsigned int, int, unsigned char *); + int (*xFindFrame)(wal_impl* pWal, unsigned int, unsigned int *); + int (*xReadFrame)(wal_impl* pWal, unsigned int, int, unsigned char *); /* If the WAL is not empty, return the size of the database. */ - unsigned int (*xDbsize)(libsql_wal *pWal); + unsigned int (*xDbsize)(wal_impl* pWal); /* Obtain or release the WRITER lock. */ - int (*xBeginWriteTransaction)(libsql_wal *pWal); - int (*xEndWriteTransaction)(libsql_wal *pWal); + int (*xBeginWriteTransaction)(wal_impl* pWal); + int (*xEndWriteTransaction)(wal_impl* pWal); /* Undo any frames written (but not committed) to the log */ - int (*xUndo)(libsql_wal *pWal, int (*xUndo)(void *, unsigned int), void *pUndoCtx); + int (*xUndo)(wal_impl* pWal, int (*xUndo)(void *, unsigned int), void *pUndoCtx); /* Return an integer that records the current (uncommitted) write ** position in the WAL */ - void (*xSavepoint)(libsql_wal *pWal, unsigned int *aWalData); + void (*xSavepoint)(wal_impl* pWal, unsigned int *aWalData); /* Move the write position of the WAL back to iFrame. Called in ** response to a ROLLBACK TO command. */ - int (*xSavepointUndo)(libsql_wal *pWal, unsigned int *aWalData); + int (*xSavepointUndo)(wal_impl* pWal, unsigned int *aWalData); /* Write a frame or frames to the log. */ - int (*xFrames)(libsql_wal *pWal, int, libsql_pghdr *, unsigned int, int, int); + int (*xFrames)(wal_impl* pWal, int, libsql_pghdr *, unsigned int, int, int, int*); /* Copy pages from the log to the database file */ int (*xCheckpoint)( - libsql_wal *pWal, /* Write-ahead log connection */ + wal_impl* 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 */ @@ -56016,7 +56932,12 @@ typedef struct libsql_wal_methods { int nBuf, /* Size of buffer nBuf */ unsigned char *zBuf, /* Temporary buffer to use */ int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ + int *pnCkpt, /* OUT: Number of backfilled frames in WAL */ + /* + * Called for each page being inserted in the wal, and once if the whole checkpoint operation was successfull with pPage == NULL + */ + int (*xCb)(void* pCbData, int mxSafeFrame, const unsigned char* pPage, int nPage, int page_no, int frame_no), /* called */ + void* pCbData /* user data passed to xCb */ ); /* Return the value to pass to a sqlite3_wal_hook callback, the @@ -56024,66 +56945,42 @@ typedef struct libsql_wal_methods { ** sqlite3WalCallback() was called. If no commits have occurred since ** the last call, then return 0. */ - int (*xCallback)(libsql_wal *pWal); + int (*xCallback)(wal_impl* pWal); /* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released) ** by the pager layer on the database file. */ - int (*xExclusiveMode)(libsql_wal *pWal, int op); + int (*xExclusiveMode)(wal_impl* 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. */ - int (*xHeapMemory)(libsql_wal *pWal); + int (*xHeapMemory)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_SNAPSHOT, but part of the ABI - int (*xSnapshotGet)(libsql_wal *pWal, sqlite3_snapshot **ppSnapshot); - void (*xSnapshotOpen)(libsql_wal *pWal, sqlite3_snapshot *pSnapshot); - int (*xSnapshotRecover)(libsql_wal *pWal); - int (*xSnapshotCheck)(libsql_wal *pWal, sqlite3_snapshot *pSnapshot); - void (*xSnapshotUnlock)(libsql_wal *pWal); + int (*xSnapshotGet)(wal_impl* pWal, sqlite3_snapshot **ppSnapshot); + void (*xSnapshotOpen)(wal_impl* pWal, sqlite3_snapshot *pSnapshot); + int (*xSnapshotRecover)(wal_impl* pWal); + int (*xSnapshotCheck)(void* pWal, sqlite3_snapshot *pSnapshot); + void (*xSnapshotUnlock)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_ZIPVFS, but part of the ABI /* 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). */ - int (*xFramesize)(libsql_wal *pWal); + int (*xFramesize)(wal_impl* pWal); /* Return the sqlite3_file object for the WAL file */ - sqlite3_file *(*xFile)(libsql_wal *pWal); + sqlite3_file *(*xFile)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_SETLK_TIMEOUT - int (*xWriteLock)(libsql_wal *pWal, int bLock); - - void (*xDb)(libsql_wal *pWal, sqlite3 *db); + int (*xWriteLock)(wal_impl* pWal, int bLock); - /* Return the WAL pathname length based on the owning pager's pathname len. - ** For WAL implementations not based on a single file, 0 should be returned. */ - int (*xPathnameLen)(int origPathname); - - /* Get the WAL pathname to given buffer. Assumes that the buffer can hold - ** at least xPathnameLen bytes. For WAL implementations not based on a single file, - ** this operation can safely be a no-op. - ** */ - void (*xGetWalPathname)(char *buf, const char *orig, int orig_len); - - /* - ** This optional callback gets called before the main database file which owns - ** the WAL file is open. It is a good place for initialization routines, as WAL - ** is otherwise open lazily. - */ - int (*xPreMainDbOpen)(libsql_wal_methods *methods, const char *main_db_path); - - /* True if the implementation relies on shared memory routines (e.g. locks) */ - int bUsesShm; - - const char *zName; - struct libsql_wal_methods *pNext; + void (*xDb)(wal_impl* pWal, sqlite3 *db); } libsql_wal_methods; -libsql_wal_methods* libsql_wal_methods_find(const char *zName); /* Object declarations */ typedef struct WalIndexHdr WalIndexHdr; @@ -56118,11 +57015,29 @@ struct WalIndexHdr { unsigned int aCksum[2]; /* Checksum over all prior fields */ }; +struct libsql_wal_manager { + /* True if the implementation relies on shared memory routines (e.g. locks) */ + int bUsesShm; + + /* Open and close a connection to a write-ahead log. */ + int (*xOpen)(wal_manager_impl* pData, sqlite3_vfs*, sqlite3_file*, int no_shm_mode, long long max_size, const char* zMainDbFileName, libsql_wal* out_wal); + int (*xClose)(wal_manager_impl* pData, wal_impl* pWal, sqlite3* db, int sync_flags, int nBuf, unsigned char *zBuf); + + /* destroy resources for this wal */ + int (*xLogDestroy)(wal_manager_impl* pData, sqlite3_vfs *vfs, const char* zMainDbFileName); + /* returns whether this wal exists */ + int (*xLogExists)(wal_manager_impl* pData, sqlite3_vfs *vfs, const char* zMainDbFileName, int* exist); + /* destructor */ + void (*xDestroy)(wal_manager_impl* pData); + + wal_manager_impl* pData; +}; + /* ** An open write-ahead log file is represented by an instance of the ** following object. */ -struct libsql_wal { +typedef struct sqlite3_wal { sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ sqlite3_file *pDbFd; /* File handle for the database file */ sqlite3_file *pWalFd; /* File handle for WAL file */ @@ -56150,11 +57065,29 @@ struct libsql_wal { unsigned char lockError; /* True if a locking error has occurred */ WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ sqlite3 *db; - libsql_wal_methods *pMethods; /* Virtual methods for interacting with WAL */ - void *pMethodsData; /* Optional context for private use of libsql_wal_methods */ +} sqlite3_wal; + +struct libsql_wal { + libsql_wal_methods methods; /* virtual wal methods */ + wal_impl* pData; /* methods receiver */ }; -typedef struct libsql_wal libsql_wal; +typedef struct RefCountedWalManager { + int n; + libsql_wal_manager ref; + int is_static; +} RefCountedWalManager; + +int make_ref_counted_wal_manager(libsql_wal_manager wal_manager, RefCountedWalManager **out); +void destroy_wal_manager(RefCountedWalManager *p); +RefCountedWalManager* clone_wal_manager(RefCountedWalManager *p); + +SQLITE_API int sqlite3_wal_backfilled(sqlite3_wal* pWal); +SQLITE_API unsigned int sqlite3_wal_frame_page_no(sqlite3_wal *pWal, unsigned int iFrame); + +RefCountedWalManager *make_sqlite3_wal_manager_rc(); + +SQLITE_API extern const libsql_wal_manager sqlite3_wal_manager; #endif /* SQLITE_WAL_H */ @@ -56440,7 +57373,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ ** outstanding transactions have been abandoned, the pager is able to ** transition back to OPEN state, discarding the contents of the ** page-cache and any other in-memory state at the same time. Everything -** is reloaded from disk (and, if necessary, hot-journal rollback peformed) +** is reloaded from disk (and, if necessary, hot-journal rollback performed) ** when a read-transaction is next opened on the pager (transitioning ** the pager into READER state). At that point the system has recovered ** from the error. @@ -56553,7 +57486,6 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ */ #define MAX_SECTOR_SIZE 0x10000 - /* ** An instance of the following structure is allocated for each active ** savepoint and statement transaction in the system. All such structures @@ -56836,12 +57768,45 @@ struct Pager { char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ PCache *pPCache; /* Pointer to page cache object */ #ifndef SQLITE_OMIT_WAL - libsql_wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ - libsql_wal_methods *pWalMethods; /* Virtual methods for interacting with WAL */ - char *zWal; /* File name for write-ahead log */ + RefCountedWalManager* wal_manager; + libsql_wal *wal; + char *zWal; /* Name of the WAL file: + FIXME: to remove, and be handled by virtual WAL. + We leave it temporarily to keep sqlite3_filename_wal working + */ #endif }; + +/* libSQL extension: pager codec */ + +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +int libsql_pager_has_codec_impl(struct Pager *_p); +int libsql_pager_codec_impl(libsql_pghdr *hdr, void **ret); +#endif + +int libsql_pager_has_codec(struct Pager *_p) { +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + return libsql_pager_has_codec_impl(_p); +#else + return 0; +#endif +} + +int libsql_pager_codec(libsql_pghdr *hdr, void **ret) { + if (!ret) { + return SQLITE_MISUSE_BKPT; + } +#ifdef LIBSQL_CUSTOM_PAGER_CODEC + return libsql_pager_codec_impl(hdr, ret); +#else + *ret = hdr->pData; + return SQLITE_OK; +#endif +} +/* end of libSQL extension: pager codec */ + + /* ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains ** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS @@ -56955,11 +57920,12 @@ static const unsigned char aJournalMagic[] = { SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ if( pPager->fd->pMethods==0 ) return 0; if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; + if( libsql_pager_has_codec(pPager) != 0 ) return 0; #ifndef SQLITE_OMIT_WAL - if( pPager->pWal ){ + if( pagerUseWal(pPager) ){ u32 iRead = 0; int rc; - rc = pPager->pWalMethods->xFindFrame(pPager->pWal, pgno, &iRead); + rc = pPager->wal.xFindFrame(pPager->wal.pData, pgno, &iRead); return (rc==SQLITE_OK && iRead==0); } #endif @@ -56968,7 +57934,7 @@ SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ #endif #ifndef SQLITE_OMIT_WAL -# define pagerUseWal(x) ((x)->pWal!=0) +# define pagerUseWal(x) ((x)->wal!=0) // check that methods have been initialized #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 @@ -57188,7 +58154,7 @@ 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) && libsql_pager_has_codec(pPager) == 0 ){ pPager->xGet = getPageMMap; #endif /* SQLITE_MAX_MMAP_SIZE>0 */ }else{ @@ -57632,9 +58598,32 @@ static int writeJournalHdr(Pager *pPager){ memset(zHeader, 0, sizeof(aJournalMagic)+4); } + + /* The random check-hash initializer */ - sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + 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 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 */ @@ -57814,7 +58803,7 @@ static int readJournalHdr( ** + 4 bytes: super-journal name checksum. ** + 8 bytes: aJournalMagic[]. ** -** The super-journal page checksum is the sum of the bytes in thesuper-journal +** 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. ** ** If zSuper is a NULL pointer (occurs for a single database transaction), @@ -57867,7 +58856,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){ } pPager->journalOff += (nSuper+20); - /* If the pager is in peristent-journal mode, then the physical + /* 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 ** dangerous because the code to rollback a hot-journal file @@ -57971,7 +58960,7 @@ static void pager_unlock(Pager *pPager){ if( pagerUseWal(pPager) ){ assert( !isOpen(pPager->jfd) ); #ifndef SQLITE_OMIT_WAL - pPager->pWalMethods->xEndReadTransaction(pPager->pWal); + pPager->wal->methods.xEndReadTransaction(pPager->wal->pData); #endif pPager->eState = PAGER_OPEN; }else if( !pPager->exclusiveMode ){ @@ -58039,7 +59028,7 @@ static void pager_unlock(Pager *pPager){ /* ** This function is called whenever an IOERR or FULL error that requires -** the pager to transition into the ERROR state may ahve occurred. +** 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. @@ -58252,7 +59241,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ ** lock held on the database file. */ #ifndef SQLITE_OMIT_WAL - rc2 = pPager->pWalMethods->xEndWriteTransaction(pPager->pWal); + rc2 = pPager->wal->methods.xEndWriteTransaction(pPager->wal->pData); #endif assert( rc2==SQLITE_OK ); }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ @@ -58274,7 +59263,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ int should_unlock = !pPager->exclusiveMode; #ifndef SQLITE_OMIT_WAL if (should_unlock && pagerUseWal(pPager)) { - should_unlock &= pPager->pWalMethods->xExclusiveMode(pPager->pWal, 0); + should_unlock &= pPager->wal->methods.xExclusiveMode(pPager->wal->pData, 0); } #endif if( should_unlock ){ @@ -58286,6 +59275,9 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ 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. @@ -58314,13 +59306,28 @@ static void pagerUnlockAndRollback(Pager *pPager){ 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 ont the contents of the +** of data. Compute and return a checksum based on 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 @@ -58753,6 +59760,8 @@ 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) @@ -59124,11 +60133,11 @@ static int readDbPage(PgHdr *pPg){ assert( isOpen(pPager->fd) ); if( pagerUseWal(pPager) ){ - rc = pPager->pWalMethods->xFindFrame(pPager->pWal, pPg->pgno, &iFrame); + rc = pPager->wal->methods.xFindFrame(pPager->wal->pData, pPg->pgno, &iFrame); if( rc ) return rc; } if( iFrame ){ - rc = pPager->pWalMethods->xReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData); + rc = pPager->wal->methods.xReadFrame(pPager->wal->pData, iFrame,pPager->pageSize,pPg->pData); }else #endif { @@ -59251,7 +60260,7 @@ static int pagerRollbackWal(Pager *pPager){ ** + Reload page content from the database (if refcount>0). */ pPager->dbSize = pPager->dbOrigSize; - rc = pPager->pWalMethods->xUndo(pPager->pWal, pagerUndoCallback, (void *)pPager); + rc = pPager->wal->methods.xUndo(pPager->wal->pData, pagerUndoCallback, (void *)pPager); pList = sqlite3PcacheDirtyList(pPager->pPCache); while( pList && rc==SQLITE_OK ){ PgHdr *pNext = pList->pDirty; @@ -59281,10 +60290,10 @@ static int pagerWalFrames( int nList; /* Number of pages in pList */ PgHdr *p; /* For looping over pages */ - assert( pPager->pWal ); + assert( pagerUseWal(pPager) ); assert( pList ); #ifdef SQLITE_DEBUG - /* Verify that the page list is in accending order */ + /* Verify that the page list is in ascending order */ for(p=pList; p && p->pDirty; p=p->pDirty){ assert( p->pgno < p->pDirty->pgno ); } @@ -59311,8 +60320,8 @@ static int pagerWalFrames( pPager->aStat[PAGER_STAT_WRITE] += nList; if( pList->pgno==1 ) pager_write_changecounter(pList); - rc = pPager->pWalMethods->xFrames(pPager->pWal, - pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags + rc = pPager->wal->methods.xFrames(pPager->wal->pData, + pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags, NULL ); if( rc==SQLITE_OK && pPager->pBackup ){ for(p=pList; p; p=p->pDirty){ @@ -59350,9 +60359,9 @@ static int pagerBeginReadTransaction(Pager *pPager){ ** are in locking_mode=NORMAL and EndRead() was previously called, ** the duplicate call is harmless. */ - pPager->pWalMethods->xEndReadTransaction(pPager->pWal); + pPager->wal->methods.xEndReadTransaction(pPager->wal->pData); - rc = pPager->pWalMethods->xBeginReadTransaction(pPager->pWal, &changed); + rc = pPager->wal->methods.xBeginReadTransaction(pPager->wal->pData, &changed); if( rc!=SQLITE_OK || changed ){ pager_reset(pPager); if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); @@ -59385,7 +60394,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ assert( isOpen(pPager->fd) ); assert( pPager->tempFile==0 ); #ifndef SQLITE_OMIT_WAL - nPage = pagerUseWal(pPager) ? pPager->pWalMethods->xDbsize(pPager->pWal) : 0; + nPage = pagerUseWal(pPager) ? pPager->wal->methods.xDbsize(pPager->wal->pData) : 0; #else nPage = 0; #endif @@ -59419,7 +60428,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ #ifndef SQLITE_OMIT_WAL /* ** Check if the *-wal file that corresponds to the database opened by pPager -** exists if the database is not empy, or verify that the *-wal file does +** exists if the database is not empty, 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 @@ -59442,9 +60451,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){ if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal - ); + rc =pPager->wal_manager->ref.xLogExists(pPager->wal_manager->ref.pData, pPager->pVfs, pPager->zFilename, &isWal); if( rc==SQLITE_OK ){ if( isWal ){ Pgno nPage; /* Size of the database file */ @@ -59452,7 +60459,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){ rc = pagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); + rc = pPager->wal_manager->ref.xLogDestroy(pPager->wal_manager->ref.pData, pPager->pVfs, pPager->zFilename); }else{ testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); rc = sqlite3PagerOpenWal(pPager, 0); @@ -59594,7 +60601,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ #ifndef SQLITE_OMIT_WAL if( pagerUseWal(pPager) ){ - rc = pPager->pWalMethods->xSavepointUndo(pPager->pWal, pSavepoint->aWalData); + rc = pPager->wal->methods.xSavepointUndo(pPager->wal->pData, pSavepoint->aWalData); } #endif for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && iinSubRec; ii++){ @@ -60272,16 +61279,18 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ #ifndef SQLITE_OMIT_WAL { u8 *a = 0; - assert( db || pPager->pWal==0 ); + assert( db || !pagerUseWal(pPager) ); if( db && 0==(db->flags & SQLITE_NoCkptOnClose) && SQLITE_OK==databaseIsUnmoved(pPager) ){ a = pTmp; } if (pagerUseWal(pPager)) { - pPager->pWalMethods->xClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); + pPager->wal_manager->ref.xClose(pPager->wal_manager->ref.pData, pPager->wal->pData, db, pPager->walSyncFlags, pPager->pageSize,a); + sqlite3_free(pPager->wal); + pPager->wal = NULL; } - pPager->pWal = 0; + destroy_wal_manager(pPager->wal_manager); } #endif pager_reset(pPager); @@ -60821,7 +61830,7 @@ SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){ */ SQLITE_PRIVATE int sqlite3PagerOpen( sqlite3_vfs *pVfs, /* The virtual file system to use */ - libsql_wal_methods *pWalMethods, /* WAL methods to use */ + RefCountedWalManager *wal_manager, /* WAL methods to use */ Pager **ppPager, /* OUT: Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ @@ -60834,11 +61843,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ -#ifndef SQLITE_OMIT_DESERIALIZE int memJM = 0; /* Memory journal mode */ -#else -# define memJM 0 -#endif 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 */ @@ -60913,10 +61918,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( } } -#ifndef SQLITE_OMIT_WAL - int nWalPathname = pWalMethods->xPathnameLen(nPathname); -#endif - /* Allocate memory for the Pager structure, PCache object, the ** three file descriptors, the database file name and the journal ** file name. The layout in memory is as follows: @@ -60961,19 +61962,18 @@ SQLITE_PRIVATE int sqlite3PagerOpen( ** specific formatting and order of the various filenames, so if the format ** changes here, be sure to change it there as well. */ + 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 */ - sizeof(pPager) + /* Space to hold a pointer */ + SQLITE_PTRSIZE + /* Space to hold a pointer */ 4 + /* Database prefix */ nPathname + 1 + /* database filename */ nUriByte + /* query parameters */ + nPathname + 4 + 1 + /* WAL filename (FIXME: move to virtual WAL) */ nPathname + 8 + 1 + /* Journal filename */ -#ifndef SQLITE_OMIT_WAL - nWalPathname + 1 + /* WAL filename */ -#endif 3 /* Terminator */ ); assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); @@ -60986,8 +61986,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile); pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; + pPager->wal_manager = clone_wal_manager(wal_manager); assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); - memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager); + memcpy(pPtr, &pPager, SQLITE_PTRSIZE); pPtr += SQLITE_PTRSIZE; /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ pPtr += 4; /* Skip zero prefix */ @@ -61015,15 +62016,14 @@ SQLITE_PRIVATE int sqlite3PagerOpen( pPager->zJournal = 0; } + /* Fill in Pager.zWal: FIXME: it will make sqlite3_filename_database work for regular WAL, + but those routines need to be rewritten to take virtual WAL into account. */ #ifndef SQLITE_OMIT_WAL - pPager->pWalMethods = pWalMethods; /* Fill in Pager.zWal */ - if( nWalPathname>0 ){ + if( nPathname>0 ){ pPager->zWal = (char*)pPtr; - pWalMethods->xGetWalPathname((char *)pPtr, zPathname, nPathname); - pPtr += nWalPathname; - pPtr[0] = '\0'; - 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); @@ -61031,13 +62031,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen( }else{ pPager->zWal = 0; } +#endif - if (pWalMethods->xPreMainDbOpen) { - int rc = pWalMethods->xPreMainDbOpen(pWalMethods, zPathname); - if (rc != SQLITE_OK) { - return rc; - } - } +#ifndef SQLITE_OMIT_WAL + pPager->wal = NULL; #endif (void)pPtr; /* Suppress warning about unused pPtr value */ @@ -61051,9 +62048,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); -#ifndef SQLITE_OMIT_DESERIALIZE pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0; -#endif readOnly = (fout&SQLITE_OPEN_READONLY)!=0; /* If the file was successfully opened for read/write access, @@ -61138,6 +62133,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( if( rc!=SQLITE_OK ){ sqlite3OsClose(pPager->fd); sqlite3PageFree(pPager->pTmpSpace); + destroy_wal_manager(pPager->wal_manager); sqlite3_free(pPager); return rc; } @@ -61190,7 +62186,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* ** Return the sqlite3_file for the main database given the name -** of the corresonding WAL or Journal name as passed into +** of the corresponding WAL or Journal name as passed into ** xOpen. */ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){ @@ -61538,7 +62534,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ */ rc = pagerOpenWalIfPresent(pPager); #ifndef SQLITE_OMIT_WAL - assert( pPager->pWal==0 || rc==SQLITE_OK ); + assert( !pagerUseWal(pPager) || rc==SQLITE_OK ); #endif } @@ -61693,6 +62689,10 @@ static int getPageNormal( if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){ rc = SQLITE_FULL; + if( pgno<=pPager->dbSize ){ + sqlite3PcacheRelease(pPg); + pPg = 0; + } goto pager_acquire_err; } if( noContent ){ @@ -61771,7 +62771,7 @@ static int getPageMMap( if( bMmapOk && pagerUseWal(pPager) ){ #ifndef SQLITE_OMIT_WAL - rc = pPager->pWalMethods->xFindFrame(pPager->pWal, pgno, &iFrame); + rc = pPager->wal->methods.xFindFrame(pPager->wal->pData, pgno, &iFrame); if( rc!=SQLITE_OK ){ *ppPage = 0; return rc; @@ -61830,8 +62830,20 @@ SQLITE_PRIVATE int sqlite3PagerGet( DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ - /* printf("PAGE %u\n", pgno); fflush(stdout); */ +#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 } /* @@ -61859,10 +62871,12 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ /* ** Release a page reference. ** -** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be -** used if we know that the page being released is not the last page. +** 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 -** to routines can be used to release any page other than BtShared.pPage1. +** 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 @@ -61878,7 +62892,7 @@ SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ sqlite3PcacheRelease(pPg); } /* Do not use this routine to release the last reference to page1 */ - assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); + assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); /* tag-20230419-2 */ } SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ if( pPg ) sqlite3PagerUnrefNotNull(pPg); @@ -62021,12 +63035,12 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory /* If the pager is configured to use locking_mode=exclusive, and an ** exclusive lock on the database is not already held, obtain it now. */ - if( pPager->exclusiveMode && pPager->pWalMethods->xExclusiveMode(pPager->pWal, -1) ){ + if( pPager->exclusiveMode && pPager->wal->methods.xExclusiveMode(pPager->wal->pData, -1) ){ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ return rc; } - (void)pPager->pWalMethods->xExclusiveMode(pPager->pWal, 1); + (void)pPager->wal->methods.xExclusiveMode(pPager->wal->pData, 1); } /* Grab the write lock on the log file. If successful, upgrade to @@ -62034,7 +63048,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory ** The busy-handler is not invoked if another connection already ** holds the write-lock. If possible, the upper layer will call it. */ - rc = pPager->pWalMethods->xBeginWriteTransaction(pPager->pWal); + rc = pPager->wal->methods.xBeginWriteTransaction(pPager->wal->pData); #endif }else{ /* Obtain a RESERVED lock on the database file. If the exFlag parameter @@ -62707,6 +63721,13 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( 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); } @@ -63037,7 +64058,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ } if( pagerUseWal(pPager) ){ #ifndef SQLITE_OMIT_WAL - pPager->pWalMethods->xSavepoint(pPager->pWal, aNew[ii].aWalData); + pPager->wal->methods.xSavepoint(pPager->wal->pData, aNew[ii].aWalData); #endif } pPager->nSavepoint = ii+1; @@ -63190,7 +64211,7 @@ SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ ** Return the WAL methods structure for the pager. */ SQLITE_PRIVATE libsql_wal_methods *sqlite3PagerWalMethods(Pager *pPager){ - return pPager->pWalMethods; + return &(pPager->wal->methods); } #endif @@ -63211,7 +64232,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ #if SQLITE_OMIT_WAL return pPager->jfd; #else - return pPager->pWal ? pPager->pWalMethods->xFile(pPager->pWal) : pPager->jfd; + return pagerUseWal(pPager) ? pPager->wal->methods.xFile(pPager->wal->pData) : pPager->jfd; #endif } @@ -63411,7 +64432,7 @@ SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){ static int pagerWalHeapMemory(Pager *pPager) { #ifndef SQLITE_OMIT_WAL if (pagerUseWal(pPager)) { - return pPager->pWalMethods->xHeapMemory(pPager->pWal); + return pPager->wal->methods.xHeapMemory(pPager->wal->pData); } #endif return 0; @@ -63493,7 +64514,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ assert( pPager->eState!=PAGER_ERROR ); pPager->journalMode = (u8)eMode; - /* When transistioning from TRUNCATE or PERSIST to any other journal + /* When transitioning from TRUNCATE or PERSIST to any other journal ** mode except WAL, unless the pager is in locking_mode=exclusive mode, ** delete the journal file. */ @@ -63538,7 +64559,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ } assert( state==pPager->eState ); } - }else if( eMode==PAGER_JOURNALMODE_OFF ){ + }else if( eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ){ sqlite3OsClose(pPager->jfd); } } @@ -63576,7 +64597,9 @@ SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ if( iLimit>=-1 ){ pPager->journalSizeLimit = iLimit; #ifndef SQLITE_OMIT_WAL - pPager->pWalMethods->xLimit(pPager->pWal, iLimit); + if (pagerUseWal(pPager)) { + pPager->wal->methods.xLimit(pPager->wal->pData, iLimit); + } #endif } return pPager->journalSizeLimit; @@ -63619,7 +64642,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( int *pnCkpt /* OUT: Final number of checkpointed frames */ ){ int rc = SQLITE_OK; - if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){ + if( !pagerUseWal(pPager) && 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 @@ -63631,12 +64654,12 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( */ sqlite3_exec(db, "PRAGMA table_list",0,0,0); } - if( pPager->pWal ){ - rc = pPager->pWalMethods->xCheckpoint(pPager->pWal, db, eMode, + if(pagerUseWal(pPager)){ + rc = pPager->wal->methods.xCheckpoint(pPager->wal->pData, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, - pnLog, pnCkpt + pnLog, pnCkpt, NULL, NULL ); } return rc; @@ -63644,7 +64667,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ if (pagerUseWal(pPager)) { - return pPager->pWalMethods->xCallback(pPager->pWal); + return pPager->wal->methods.xCallback(pPager->wal->pData); } return SQLITE_OK; } @@ -63656,7 +64679,7 @@ SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ const sqlite3_io_methods *pMethods = pPager->fd->pMethods; if( pPager->noLock ) return 0; - return pPager->exclusiveMode || (pPager->pWalMethods->bUsesShm == 0) || (pMethods->iVersion>=2 && pMethods->xShmMap); + return pPager->exclusiveMode || (pPager->wal_manager->ref.bUsesShm == 0) || (pMethods->iVersion>=2 && pMethods->xShmMap); } /* @@ -63665,13 +64688,15 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ */ static int pagerExclusiveLock(Pager *pPager){ int rc; /* Return code */ + u8 eOrigLock; /* Original lock */ - assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); + assert( pPager->eLock>=SHARED_LOCK ); + eOrigLock = pPager->eLock; rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ /* If the attempt to grab the exclusive lock failed, release the ** pending lock that may have been obtained instead. */ - pagerUnlockDb(pPager, SHARED_LOCK); + pagerUnlockDb(pPager, eOrigLock); } return rc; @@ -63686,7 +64711,7 @@ static int pagerExclusiveLock(Pager *pPager){ static int pagerOpenWal(Pager *pPager){ int rc = SQLITE_OK; - assert( pPager->pWal==0 && pPager->tempFile==0 ); + assert( !pagerUseWal(pPager) && 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 @@ -63701,11 +64726,23 @@ static int pagerOpenWal(Pager *pPager){ /* 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 = pPager->pWalMethods->xOpen(pPager->pVfs, - pPager->fd, pPager->zWal, pPager->exclusiveMode, - pPager->journalSizeLimit, pPager->pWalMethods, &pPager->pWal - ); + libsql_wal *wal = (libsql_wal*)sqlite3MallocZero(sizeof(libsql_wal)); + if (!wal) { + rc = SQLITE_NOMEM; + } + if (rc == SQLITE_OK) { + rc = pPager->wal_manager->ref.xOpen(pPager->wal_manager->ref.pData, pPager->pVfs, + pPager->fd, pPager->exclusiveMode, + pPager->journalSizeLimit, pPager->zFilename, wal + ); + if (rc == SQLITE_OK) { + pPager->wal = wal; + } else { + sqlite3_free(wal); + } + } } pagerFixMaplimit(pPager); @@ -63738,9 +64775,9 @@ SQLITE_PRIVATE int sqlite3PagerOpenWal( assert( pPager->eState==PAGER_OPEN || pbOpen ); assert( pPager->eState==PAGER_READER || !pbOpen ); assert( pbOpen==0 || *pbOpen==0 ); - assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) ); + assert( pbOpen!=0 || (!pPager->tempFile && !pagerUseWal(pPager)) ); - if( !pPager->tempFile && !pPager->pWal ){ + if( !pPager->tempFile && !pagerUseWal(pPager) ){ if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; /* Close any rollback journal previously open */ @@ -63776,13 +64813,11 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ ** it may need to be checkpointed before the connection can switch to ** rollback mode. Open it now so this can happen. */ - if( !pPager->pWal ){ + if( !pagerUseWal(pPager) ){ int logexists = 0; rc = pagerLockDb(pPager, SHARED_LOCK); if( rc==SQLITE_OK ){ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists - ); + rc = pPager->wal_manager->ref.xLogExists(pPager->wal_manager->ref.pData, pPager->pVfs, pPager->zFilename, &logexists); } if( rc==SQLITE_OK && logexists ){ rc = pagerOpenWal(pPager); @@ -63792,12 +64827,13 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ /* 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 ){ + if( rc==SQLITE_OK && pagerUseWal(pPager) ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ - rc = pPager->pWalMethods->xClose(pPager->pWal, db, pPager->walSyncFlags, + rc = pPager->wal_manager->ref.xClose(pPager->wal_manager->ref.pData, pPager->wal->pData, db, pPager->walSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); - pPager->pWal = 0; + sqlite3_free(pPager->wal); + pPager->wal = NULL; pagerFixMaplimit(pPager); if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } @@ -63838,8 +64874,8 @@ SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){ */ SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ int rc = SQLITE_ERROR; - if( pPager->pWal ){ - rc = pPager->pWalMethods->xSnapshotGet(pPager->pWal, ppSnapshot); + if( pagerUseWal(pPager) ){ + rc = pPager->walxSnapshotGet(pPager->wal.pData, ppSnapshot); } return rc; } @@ -63854,8 +64890,8 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen( sqlite3_snapshot *pSnapshot ){ int rc = SQLITE_OK; - if( pPager->pWal ){ - pPager->pWalMethods->xSnapshotOpen(pPager->pWal, pSnapshot); + if( pagerUseWal(pPager) ){ + pPager->wal.xSnapshotOpen(pPager->wal.pData, pSnapshot); }else{ rc = SQLITE_ERROR; } @@ -63868,8 +64904,8 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen( */ SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){ int rc; - if( pPager->pWal ){ - rc = pPager->pWalMethods->xSnapshotRecover(pPager->pWal); + if( pagerUseWal(pPage) ){ + rc = pPager->wal.xSnapshotRecover(pPager->wal.pData); }else{ rc = SQLITE_ERROR; } @@ -63890,8 +64926,8 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){ */ SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){ int rc; - if( pPager->pWal ){ - rc = pPager->pWalMethods->xSnapshotCheck(pPager->pWal, pSnapshot); + if( pagerUseWal(pPager) ){ + rc = pPager->wal.xSnapshotCheck(pPager->wal.pData, pSnapshot); }else{ rc = SQLITE_ERROR; } @@ -63903,8 +64939,8 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pS ** sqlite3PagerSnapshotCheck(). */ SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){ - assert( pPager->pWal ); - pPager->pWalMethods->xSnapshotUnlock(pPager->pWal); + assert( pagerUseWal(pPager) ); + pPager->wal.xSnapshotUnlock(pPager->wal.pData) } #endif /* SQLITE_ENABLE_SNAPSHOT */ @@ -63924,6 +64960,12 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ } #endif +#ifdef SQLITE_USE_SEH +SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ + return sqlite3WalSystemErrno(pPager->pWal); +} +#endif + #endif /* SQLITE_OMIT_DISKIO */ /************** End of pager.c ***********************************************/ @@ -64182,8 +65224,33 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ /* #include "wal.h" */ +int libsql_pager_codec(libsql_pghdr *p, void **ret); + typedef libsql_pghdr PgHdr; -typedef libsql_wal Wal; +typedef sqlite3_wal Wal; + +static int sqlite3WalCheckpoint( + Wal *pWal, /* Wal connection */ + sqlite3 *db, /* Check this handle's interrupt flag */ + int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ + int (*xBusy)(void*), /* Function to call when busy */ + void *pBusyArg, /* Context argument for xBusyHandler */ + int sync_flags, /* Flags to sync db file with (or 0) */ + int nBuf, /* Size of temporary buffer */ + u8 *zBuf, /* Temporary buffer to use */ + int *pnLog, /* OUT: Number of frames in WAL */ + int *pnCkpt, /* OUT: Number of backfilled frames in WAL */ + int (*xCb)(void*, int, const unsigned char*, int, int, int), + void *pCbData +); +static void sqlite3WalEndReadTransaction(Wal *pWal); +static int sqlite3WalEndWriteTransaction(Wal *pWal); +static int walFindFrame( + Wal *pWal, /* WAL handle */ + Pgno pgno, /* Database page number to read data for */ + u32 iLast, /* Last page in WAL for this reader */ + u32 *piRead /* OUT: Frame number (or zero) */ +); /* ** Trace output macros @@ -64218,7 +65285,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0; ** ** Technically, the various VFSes are free to implement these locks however ** they see fit. However, compatibility is encouraged so that VFSes can -** interoperate. The standard implemention used on both unix and windows +** 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 @@ -64260,7 +65327,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0; ** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) ** for any aReadMark[] means that entry is unused. aReadMark[0] is ** a special case; its value is never used and it exists as a place-holder -** to avoid having to offset aReadMark[] indexs by one. Readers holding +** to avoid having to offset aReadMark[] indexes by one. Readers holding ** WAL_READ_LOCK(0) always ignore the entire WAL and read all content ** directly from the database. ** @@ -64446,6 +65513,12 @@ struct WalIterator { } aSegment[1]; /* One for every 32KB page in the wal-index */ }; +struct WalIteratorRev { + u32 current; + /* A sparse array of page no, where frames[frame_no] = page_no if frame_no is the most recent version of this page, page_no = 0 otherwise */ + u32 *frames; +}; + /* ** Define the parameters of the hash tables in the wal-index file. There ** is a hash-table following every HASHTABLE_NPAGE page numbers in the @@ -64470,6 +65543,28 @@ struct WalIterator { 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 +# error "SEH is not supported in libSQL due to virtual WAL backward compatibility!" +#else +# define SEH_TRY +# define SEH_EXCEPT(X) +# define SEH_INJECT_FAULT +# 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 @@ -64542,6 +65637,7 @@ static int walIndexPage( 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); } @@ -64553,6 +65649,7 @@ static int walIndexPage( */ 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]); } @@ -64561,6 +65658,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ */ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalIndexHdr*)pWal->apWiData[0]; } @@ -64606,19 +65704,40 @@ static void walChecksumBytes( assert( nByte>=8 ); assert( (nByte&0x00000007)==0 ); assert( nByte<=65536 ); + assert( nByte%4==0 ); - if( nativeCksum ){ + if( !nativeCksum ){ do { + s1 += BYTESWAP32(aData[0]) + s2; + s2 += BYTESWAP32(aData[1]) + s1; + aData += 2; + }while( aDataapWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; } - return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; + + volatile u32 *page; + int rc = walIndexPage(pWal, iHash, &page); + assert( rc==SQLITE_OK || iHash>0 ); + if (rc != SQLITE_OK) { + return 0; + } + return page[(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; } /* @@ -65169,6 +66296,7 @@ static int walIndexRecover(Wal *pWal){ /* 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); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -65187,6 +66315,7 @@ static int walIndexRecover(Wal *pWal){ 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++){ @@ -65214,6 +66343,7 @@ static int walIndexRecover(Wal *pWal){ } } 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 @@ -65244,9 +66374,11 @@ static int walIndexRecover(Wal *pWal){ } } #endif + SEH_INJECT_FAULT; if( iFrame<=iLast ) break; } + SEH_FREE_ON_ERROR(aFrame, 0); sqlite3_free(aFrame); } @@ -65274,6 +66406,7 @@ static int walIndexRecover(Wal *pWal){ }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; @@ -65315,127 +66448,9 @@ static void walIndexClose(Wal *pWal, int isDelete){ } } -/* -** 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. -** -** Custom virtual methods may be provided via the pMethods parameter. -** -** 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 -** *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. -*/ -static int sqlite3WalOpen( - sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ - sqlite3_file *pDbFd, /* The open database file */ - const char *zWalName, /* Name of the WAL file */ - int bNoShm, /* True to run in heap-memory mode */ - i64 mxWalSize, /* Truncate WAL to this size on reset */ - libsql_wal_methods* pMethods, /* Virtual methods for interacting with WAL */ - Wal **ppWal /* OUT: Allocated Wal handle */ -){ - int rc; /* Return Code */ - Wal *pRet; /* Object to allocate and return */ - 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. - */ -#ifdef WIN_SHM_BASE - assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); -#endif -#ifdef UNIX_SHM_BASE - assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); -#endif - - - /* Allocate an instance of struct Wal to return. */ - *ppWal = 0; - pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile); - if( !pRet ){ - return SQLITE_NOMEM_BKPT; - } - - pRet->pVfs = pVfs; - pRet->pWalFd = (sqlite3_file *)&pRet[1]; - pRet->pDbFd = pDbFd; - pRet->readLock = -1; - pRet->mxWalSize = mxWalSize; - pRet->zWalName = zWalName; - pRet->syncHeader = 1; - pRet->padToSectorBoundary = 1; - pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); - - /* Open file handle on the write-ahead log file. */ - flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL); - rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags); - if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){ - pRet->readOnly = WAL_RDONLY; - } - - if( rc!=SQLITE_OK ){ - walIndexClose(pRet, 0); - sqlite3OsClose(pRet->pWalFd); - sqlite3_free(pRet); - }else{ - int iDC = sqlite3OsDeviceCharacteristics(pDbFd); - if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } - if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ - pRet->padToSectorBoundary = 0; - } - *ppWal = pRet; - WALTRACE(("WAL%d: opened\n", pRet)); - } - pRet->pMethods = pMethods; - return rc; -} /* -** Change the size to which the WAL file is trucated on each reset. +** Change the size to which the WAL file is truncated on each reset. */ static void sqlite3WalLimit(Wal *pWal, i64 iLimit){ if( pWal ) pWal->mxWalSize = iLimit; @@ -65481,6 +66496,31 @@ static int walIteratorNext( return (iRet==0xFFFFFFFF); } +/* +** Return 0 on success. If there are no pages in the WAL with a page +** number larger than *piPage, then return 1. +*/ +static int walIteratorRevNext( + struct WalIteratorRev *p, /* Iterator */ + u32 *piPage, /* OUT: The page number of the next page */ + u32 *piFrame /* OUT: Wal frame index of next page */ +){ + while (p->current > 0 && p->frames[p->current] == 0) { + p->current -= 1; + } + + if (p->current == 0) { + return 1; + } + + *piFrame = p->current; + *piPage = p->frames[p->current]; + + p->current--; + + return 0; +} + /* ** This function merges two sorted lists into a single sorted list. ** @@ -65661,23 +66701,16 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte); + p = (WalIterator *)sqlite3_malloc64(nByte + + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) + ); if( !p ){ return SQLITE_NOMEM_BKPT; } memset(p, 0, nByte); p->nSegment = nSegment; - - /* Allocate temporary space used by the merge-sort routine. This block - ** of memory will be freed before this function returns. - */ - aTmp = (ht_slot *)sqlite3_malloc64( - sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); - if( !aTmp ){ - rc = SQLITE_NOMEM_BKPT; - } - + aTmp = (ht_slot*)&(((u8*)p)[nByte]); + SEH_FREE_ON_ERROR(0, p); for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iaSegment[i].aPgno = (u32 *)sLoc.aPgno; } } - sqlite3_free(aTmp); - if( rc!=SQLITE_OK ){ + SEH_FREE_ON_ERROR(p, 0); walIteratorFree(p); p = 0; } @@ -65715,6 +66747,51 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ return rc; } +static int walIteratorRevInit(Wal *pWal, u32 nBackfill, struct WalIteratorRev *p, u32 mxSafeFrame, int ignoreFrameIfNewerExist){ + WalIterator *pIter; + u32 *frames; + u32 iFrame, iPageno; + int rc; + + frames = (u32*)sqlite3MallocZero((pWal->hdr.mxFrame + 1) * sizeof(u32)); + if (!frames) return SQLITE_NOMEM_BKPT; + rc = walIteratorInit(pWal, nBackfill, &pIter); + if (rc || !pIter) { + sqlite3_free(frames); + return rc; + } + + while (walIteratorNext(pIter, &iPageno, &iFrame) == 0) { + /* + * If we get a page with a frame_no greater than mxSafeFrame, and ignoreFrameIfNewerExist is false, + * then we replace it with the latest page with frame_no <= mxSafeFrame. + */ + if (iFrame > mxSafeFrame && !ignoreFrameIfNewerExist) { + rc = walFindFrame(pWal, iPageno, mxSafeFrame, &iFrame); + if( rc!=SQLITE_OK ) break; + if (iFrame == 0) { + continue; + } + } + frames[iFrame] = iPageno; + } + walIteratorFree(pIter); + if (rc != 0) { + sqlite3_free(frames); + return rc; + } + + p->current = pWal->hdr.mxFrame; + p->frames = frames; + + return SQLITE_OK; +} + +static void walIteratorRevFree(struct WalIteratorRev *p) { + p->current = 0; + sqlite3_free(p->frames); +} + #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* ** Attempt to enable blocking locks. Blocking locks are enabled only if (a) @@ -65805,7 +66882,7 @@ static void sqlite3WalDb(Wal *pWal, sqlite3 *db){ ** lock is successfully obtained or the busy-handler returns 0. */ static int walBusyLock( - Wal *pWal, /* WAL connection */ + Wal *pWal, /* WAL connection */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int lockIdx, /* Offset of first byte to lock */ @@ -65903,11 +66980,13 @@ static int walCheckpoint( int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags for OsSync() (or 0) */ - u8 *zBuf /* Temporary buffer to use */ + u8 *zBuf, /* Temporary buffer to use */ + void *pCbData, /* User data passed to xCb */ + int (*xCb)(void* pCbData, int mxSafeFrame, const unsigned char* pPage, int nPage, int pageNo, int frameNo) /* Checkpoint callback */ ){ int rc = SQLITE_OK; /* Return code */ int szPage; /* Database page-size */ - WalIterator *pIter = 0; /* Wal iterator context */ + struct WalIteratorRev pIter = { 0 }; /* Wal iterator context */ u32 iDbpage = 0; /* Next database page to write */ u32 iFrame = 0; /* Wal frame containing data for iDbpage */ u32 mxSafeFrame; /* Max frame that can be backfilled */ @@ -65933,13 +67012,13 @@ static int walCheckpoint( mxSafeFrame = pWal->hdr.mxFrame; mxPage = pWal->hdr.nPage; for(i=1; iaReadMark+i); + u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; 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); + AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc==SQLITE_BUSY ){ mxSafeFrame = y; @@ -65952,16 +67031,13 @@ static int walCheckpoint( /* Allocate the iterator */ if( pInfo->nBackfillnBackfill, &pIter); - assert( rc==SQLITE_OK || pIter==0 ); + rc = walIteratorRevInit(pWal, pInfo->nBackfill, &pIter, mxSafeFrame, xCb == NULL); + assert(rc == SQLITE_OK || pIter.frames == NULL); } - if( pIter - && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK - ){ + if(( pIter.frames != NULL && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK)){ u32 nBackfill = pInfo->nBackfill; - - pInfo->nBackfillAttempted = mxSafeFrame; + pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; /* Sync the WAL to disk */ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); @@ -65989,9 +67065,10 @@ static int walCheckpoint( } /* Iterate through the contents of the WAL, copying data to the db file */ - while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ + while( rc==SQLITE_OK && 0==walIteratorRevNext(&pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); + SEH_INJECT_FAULT; if( AtomicLoad(&db->u1.isInterrupted) ){ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; break; @@ -66007,12 +67084,19 @@ static int walCheckpoint( testcase( IS_BIG_INT(iOffset) ); rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); if( rc!=SQLITE_OK ) break; + if (xCb) { + rc = (xCb)(pCbData, mxSafeFrame, zBuf, szPage, iDbpage, iFrame); + } + 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 ){ + if (xCb) { + rc = (xCb)(pCbData, mxSafeFrame, NULL, 0, 0, 0); + } i64 szDb = pWal->hdr.nPage*(i64)szPage; testcase( IS_BIG_INT(szDb) ); rc = sqlite3OsTruncate(pWal->pDbFd, szDb); @@ -66021,7 +67105,7 @@ static int walCheckpoint( } } if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); + AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; } } @@ -66043,6 +67127,7 @@ static int walCheckpoint( */ 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 ){ @@ -66074,7 +67159,8 @@ static int walCheckpoint( } walcheckpoint_out: - walIteratorFree(pIter); + SEH_FREE_ON_ERROR(pIter, 0); + walIteratorRevFree(&pIter); return rc; } @@ -66096,11 +67182,18 @@ static void walLimitSize(Wal *pWal, i64 nMax){ } } +#ifdef SQLITE_USE_SEH +# error "SEH is not supported in libSQL due to virtual WAL backward compatibility!" +#else +# define walAssertLockmask(x) 1 +#endif /* ifdef SQLITE_USE_SEH */ + /* ** Close a connection to a log file. */ static int sqlite3WalClose( - Wal *pWal, /* Wal to close */ + wal_manager_impl *self, + Wal *pWal, /* Wal to close */ sqlite3 *db, /* For interrupt flag */ int sync_flags, /* Flags to pass to OsSync() (or 0) */ int nBuf, @@ -66110,6 +67203,8 @@ static int sqlite3WalClose( 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 @@ -66124,8 +67219,8 @@ static int sqlite3WalClose( if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } - rc = pWal->pMethods->xCheckpoint(pWal, db, - SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 + rc = sqlite3WalCheckpoint(pWal, db, + SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0, NULL, NULL ); if( rc==SQLITE_OK ){ int bPersist = -1; @@ -66134,7 +67229,7 @@ static int sqlite3WalClose( ); if( bPersist!=1 ){ /* Try to delete the WAL file if the checkpoint completed and - ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal + ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal ** mode (!bPersist) */ isDelete = 1; }else if( pWal->mxWalSize>=0 ){ @@ -66201,7 +67296,7 @@ static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){ ** give false-positive warnings about these accesses because the tools do not ** account for the double-read and the memory barrier. The use of mutexes ** here would be problematic as the memory being accessed is potentially - ** shared among multiple processes and not all mutex implementions work + ** shared among multiple processes and not all mutex implementations work ** reliably in that environment. */ aHdr = walIndexHdr(pWal); @@ -66515,7 +67610,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ pWal->apWiData[i] = 0; } pWal->bShmUnreliable = 0; - pWal->pMethods->xEndReadTransaction(pWal); + sqlite3WalEndReadTransaction(pWal); *pChanged = 1; } return rc; @@ -66652,6 +67747,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ assert( pWal->nWiData>0 ); assert( pWal->apWiData[0]!=0 ); pInfo = walCkptInfo(pWal); + SEH_INJECT_FAULT; if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame #ifdef SQLITE_ENABLE_SNAPSHOT && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) @@ -66701,7 +67797,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } #endif for(i=1; iaReadMark+i); + u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxReadMark<=thisMark && thisMark<=mxFrame ){ assert( thisMark!=READMARK_NOT_USED ); mxReadMark = thisMark; @@ -66767,7 +67863,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** 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; + 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)) @@ -66782,6 +67878,54 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } #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 ** variable so that older snapshots can be accessed. To do this, loop @@ -66807,50 +67951,21 @@ static int sqlite3WalSnapshotRecover(Wal *pWal){ assert( pWal->readLock>=0 ); rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int szPage = (int)pWal->szPage; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(szPage); - void *pBuf2 = sqlite3_malloc(szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>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; - } + 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); } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + pWal->ckptLock = 0; } + + sqlite3_free(pBuf1); + sqlite3_free(pBuf2); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); } @@ -66859,23 +67974,14 @@ static int sqlite3WalSnapshotRecover(Wal *pWal){ #endif /* SQLITE_ENABLE_SNAPSHOT */ /* -** 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. +** This function does the work of sqlite3WalBeginReadTransaction() (see +** below). That function simply calls this one inside an SEH_TRY{...} block. */ -static int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ +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 @@ -66903,7 +68009,7 @@ static int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ if( rc!=SQLITE_OK ){ return rc; } - pWal->ckptLock = 1; + ckptLock = 1; } #endif @@ -66967,21 +68073,43 @@ static int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ } /* Release the shared CKPT lock obtained above. */ - if( pWal->ckptLock ){ + if( ckptLock ){ assert( pSnapshot ); walUnlockShared(pWal, WAL_CKPT_LOCK); - pWal->ckptLock = 0; } #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. +*/ +static 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. */ static void sqlite3WalEndReadTransaction(Wal *pWal){ - pWal->pMethods->xEndWriteTransaction(pWal); + sqlite3WalEndWriteTransaction(pWal); if( pWal->readLock>=0 ){ walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); pWal->readLock = -1; @@ -66996,13 +68124,13 @@ static void sqlite3WalEndReadTransaction(Wal *pWal){ ** 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 sqlite3WalFindFrame( +static int walFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ + u32 iLast, /* Last page in WAL for this reader */ u32 *piRead /* OUT: Frame number (or zero) */ ){ u32 iRead = 0; /* If !=0, WAL frame to return data from */ - u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ int iHash; /* Used to loop through N hash tables */ int iMinHash; @@ -67059,6 +68187,7 @@ static int sqlite3WalFindFrame( } 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 ){ @@ -67095,6 +68224,30 @@ static int sqlite3WalFindFrame( 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, pWal->hdr.mxFrame, 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 @@ -67176,12 +68329,17 @@ static int sqlite3WalBeginWriteTransaction(Wal *pWal){ ** time the read transaction on this connection was started, then ** the write is disallowed. */ - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + 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 ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; - rc = SQLITE_BUSY_SNAPSHOT; } - return rc; } @@ -67217,30 +68375,33 @@ static int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx) Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - 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. + 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. */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + 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); } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; } @@ -67284,7 +68445,10 @@ static int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; - walCleanupHash(pWal); + SEH_TRY { + walCleanupHash(pWal); + } + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; @@ -67302,10 +68466,12 @@ static int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ ** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned ** if an error occurs. */ -static int walRestartLog(Wal *pWal){ +static int walRestartLog(Wal *pWal, int *pRestarted){ int rc = SQLITE_OK; int cnt; + *pRestarted = 0; + if( pWal->readLock==0 ){ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); assert( pInfo->nBackfill==pWal->hdr.mxFrame ); @@ -67325,6 +68491,7 @@ static int walRestartLog(Wal *pWal){ ** to handle if this transaction is rolled back. */ walRestartHdr(pWal, salt1); walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + *pRestarted = 1; }else if( rc!=SQLITE_BUSY ){ return rc; } @@ -67400,6 +68567,9 @@ static int walWriteOneFrame( void *pData; /* Data actually written */ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ pData = pPage->pData; + rc = libsql_pager_codec(pPage, &pData); + if( rc ) return rc; + walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); if( rc ) return rc; @@ -67465,13 +68635,14 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){ ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). */ -static int sqlite3WalFrames( +static int walFrames( 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 sync_flags, /* Flags to pass to OsSync() (or 0) */ + int *pnFrames /* Number of frames written to the wal in the transaction. 0 for non-commit call*/ ){ int rc; /* Used to catch return codes */ u32 iFrame; /* Next frame address */ @@ -67483,6 +68654,7 @@ static int sqlite3WalFrames( WalWriter w; /* The writer */ u32 iFirst = 0; /* First frame that may be overwritten */ WalIndexHdr *pLive; /* Pointer to shared header */ + int walRestarted; /* Whether the wal was restarted */ assert( pList ); assert( pWal->writeLock ); @@ -67506,7 +68678,7 @@ static int sqlite3WalFrames( /* See if it is possible to write these frames into the start of the ** log file, instead of appending to it at pWal->hdr.mxFrame. */ - if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){ + if( SQLITE_OK!=(rc = walRestartLog(pWal, &walRestarted)) ){ return rc; } @@ -67553,7 +68725,9 @@ static int sqlite3WalFrames( if( rc ) return rc; } } - assert( (int)pWal->szPage==szPage ); + if( (int)pWal->szPage!=szPage ){ + return SQLITE_CORRUPT_BKPT; /* TH3 test case: cov1/corrupt155.test */ + } /* Setup information needed to write frames into the WAL */ w.pWal = pWal; @@ -67574,7 +68748,7 @@ static int sqlite3WalFrames( ** checksums must be recomputed when the transaction is committed. */ if( iFirst && (p->pDirty || isCommit==0) ){ u32 iWrite = 0; - VVA_ONLY(rc =) pWal->pMethods->xFindFrame(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; @@ -67582,7 +68756,9 @@ static int sqlite3WalFrames( if( pWal->iReCksum==0 || iWriteiReCksum ){ pWal->iReCksum = iWrite; } - pData = p->pData; + + rc = libsql_pager_codec(p, &pData); + if( rc ) return rc; rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff); if( rc ) return rc; p->flags &= ~PGHDR_WAL_APPEND; @@ -67677,6 +68853,17 @@ static int sqlite3WalFrames( pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); testcase( szPage<=32768 ); testcase( szPage>=65536 ); + if (pnFrames) { + if (isCommit) { + if (walRestarted) { + *pnFrames = iFrame; + } else { + *pnFrames = iFrame - pWal->hdr.mxFrame; + } + } else { + *pnFrames = 0; + } + } pWal->hdr.mxFrame = iFrame; if( isCommit ){ pWal->hdr.iChange++; @@ -67693,6 +68880,30 @@ static int sqlite3WalFrames( 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 *pnFrames /* OUT: Number of frames appended to the wal on commit */ +){ + int rc; + SEH_TRY { + rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags, pnFrames); + } + SEH_EXCEPT( rc = walHandleException(pWal); ) + return rc; +} + /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -67704,7 +68915,7 @@ static int sqlite3WalFrames( ** callback. In this case this function runs a blocking checkpoint. */ static int sqlite3WalCheckpoint( - Wal *pWal, /* Wal connection */ + Wal *pWal, /* Wal connection */ sqlite3 *db, /* Check this handle's interrupt flag */ int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ int (*xBusy)(void*), /* Function to call when busy */ @@ -67713,7 +68924,9 @@ static int sqlite3WalCheckpoint( int nBuf, /* Size of temporary buffer */ u8 *zBuf, /* Temporary buffer to use */ int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ + int *pnCkpt, /* OUT: Number of backfilled frames in WAL */ + int (*xCb)(void*, int, const unsigned char*, int, int, int), /* page, page_no, frame_no */ + void *pCbData ){ int rc; /* Return code */ int isChanged = 0; /* True if a new wal-index header is loaded */ @@ -67732,7 +68945,7 @@ static int sqlite3WalCheckpoint( /* Enable blocking locks, if possible. If blocking locks are successfully ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ - pWal->pMethods->xDb(pWal, db); + sqlite3WalDb(pWal, db); (void)walEnableBlocking(pWal); /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive @@ -67772,30 +68985,33 @@ static int sqlite3WalCheckpoint( /* Read the wal-index header. */ - if( rc==SQLITE_OK ){ - walDisableBlocking(pWal); - rc = walIndexReadHdr(pWal, &isChanged); - (void)walEnableBlocking(pWal); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + SEH_TRY { + if( rc==SQLITE_OK ){ + walDisableBlocking(pWal); + rc = walIndexReadHdr(pWal, &isChanged); + (void)walEnableBlocking(pWal); + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + } } - } - - /* 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); - } + /* 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, pCbData, xCb); + } - /* 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 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( isChanged ){ /* If a new wal-index header was loaded before the checkpoint was @@ -67808,10 +69024,10 @@ static int sqlite3WalCheckpoint( } walDisableBlocking(pWal); - pWal->pMethods->xDb(pWal, 0); + sqlite3WalDb(pWal, 0); /* Release the locks. */ - pWal->pMethods->xEndWriteTransaction(pWal); + sqlite3WalEndWriteTransaction(pWal); if( pWal->ckptLock ){ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; @@ -67947,7 +69163,7 @@ static void sqlite3WalSnapshotOpen( ** 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. */ -static int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ +SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ WalIndexHdr *pHdr1 = (WalIndexHdr*)p1; WalIndexHdr *pHdr2 = (WalIndexHdr*)p2; @@ -67973,16 +69189,19 @@ static int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ */ static int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ int rc; - 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_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; } @@ -68025,150 +69244,244 @@ static void libsqlGetWalPathname(char *buf, const char *orig, int orig_len) { memcpy(buf + orig_len, "-wal", 4); } -static int libsqlPreMainDbOpen(struct libsql_wal_methods *methods, const char *main_db_path) { - return SQLITE_OK; +SQLITE_PRIVATE int sqlite3LogExists(wal_manager_impl* self, sqlite3_vfs *vfs, const char *main_db_path_name, int *exists) { + const char *zWal = sqlite3_filename_wal(main_db_path_name); + int rc = sqlite3OsAccess(vfs, zWal, SQLITE_ACCESS_EXISTS, exists); + return rc; } -libsql_wal_methods *libsql_wal_methods_find(const char *zName) { - static libsql_wal_methods methods; - static libsql_wal_methods *methods_head = NULL; +SQLITE_PRIVATE int sqlite3LogDestroy(wal_manager_impl* self, sqlite3_vfs *vfs, const char *main_db_path_name) { + const char *zWal = sqlite3_filename_wal(main_db_path_name); + int rc = sqlite3OsDelete(vfs, zWal, 0); + return rc; +} -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if (rc != SQLITE_OK) { - return NULL; - } +/* +** 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. +** +** Custom virtual methods may be provided via the pMethods parameter. +** +** 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 +** *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. +*/ +static int sqlite3WalOpen( + wal_manager_impl *self, + sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ + sqlite3_file *pDbFd, /* The open database file */ + int bNoShm, /* True to run in heap-memory mode */ + i64 mxWalSize, /* Truncate WAL to this size on reset */ + const char* main_db_file_name, + libsql_wal *out /* OUT: Allocated Wal handle */ +){ + int rc; /* Return Code */ + Wal *pRet; /* Object to allocate and return */ + int flags; /* Flags passed to OsOpen() */ + + 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. + */ +#ifdef WIN_SHM_BASE + assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); +#endif +#ifdef UNIX_SHM_BASE + assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); #endif - if (!zName || *zName == '\0') { - zName = "default"; - } - if (methods_head == NULL && strncmp(zName, "default", 7) == 0) { - methods.iVersion = 1; - methods.xOpen = sqlite3WalOpen; - methods.xClose = sqlite3WalClose; - methods.xLimit = sqlite3WalLimit; - methods.xBeginReadTransaction = sqlite3WalBeginReadTransaction; - methods.xEndReadTransaction = sqlite3WalEndReadTransaction; - methods.xFindFrame = sqlite3WalFindFrame; - methods.xReadFrame = sqlite3WalReadFrame; - methods.xDbsize = sqlite3WalDbsize; - methods.xBeginWriteTransaction = sqlite3WalBeginWriteTransaction; - methods.xEndWriteTransaction = sqlite3WalEndWriteTransaction; - methods.xUndo = sqlite3WalUndo; - methods.xSavepoint = sqlite3WalSavepoint; - methods.xSavepointUndo = sqlite3WalSavepointUndo; - methods.xFrames = sqlite3WalFrames; - methods.xCheckpoint = sqlite3WalCheckpoint; - methods.xCallback = sqlite3WalCallback; - methods.xExclusiveMode = sqlite3WalExclusiveMode; - methods.xHeapMemory = sqlite3WalHeapMemory; + const char *zWalName = sqlite3_filename_wal(main_db_file_name); + + /* Allocate an instance of struct Wal to return. */ + pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile); + if( !pRet ){ + return SQLITE_NOMEM_BKPT; + } + + pRet->pVfs = pVfs; + pRet->pWalFd = (sqlite3_file *)&pRet[1]; + pRet->pDbFd = pDbFd; + pRet->readLock = -1; + pRet->mxWalSize = mxWalSize; + pRet->zWalName = zWalName; + pRet->syncHeader = 1; + pRet->padToSectorBoundary = 1; + pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); + + /* Open file handle on the write-ahead log file. */ + flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL); + rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags); + if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){ + pRet->readOnly = WAL_RDONLY; + } + + if( rc!=SQLITE_OK ){ + walIndexClose(pRet, 0); + sqlite3OsClose(pRet->pWalFd); + sqlite3_free(pRet); + }else{ + int iDC = sqlite3OsDeviceCharacteristics(pDbFd); + if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } + if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ + pRet->padToSectorBoundary = 0; + } + out->pData = (wal_impl*) pRet; + out->methods.iVersion = 1; + out->methods.xLimit = (void (*)(wal_impl *, long long))sqlite3WalLimit; + out->methods.xBeginReadTransaction = (int (*)(wal_impl *, int *))sqlite3WalBeginReadTransaction; + out->methods.xEndReadTransaction = (void (*)(wal_impl *))sqlite3WalEndReadTransaction; + out->methods.xFindFrame = (int (*)(wal_impl *, unsigned int, unsigned int *))sqlite3WalFindFrame; + out->methods.xReadFrame = (int (*)(wal_impl *, unsigned int, int, unsigned char *))sqlite3WalReadFrame; + out->methods.xDbsize = (unsigned int (*)(wal_impl *))sqlite3WalDbsize; + out->methods.xBeginWriteTransaction = (int (*)(wal_impl *))sqlite3WalBeginWriteTransaction; + out->methods.xEndWriteTransaction = (int (*)(wal_impl *))sqlite3WalEndWriteTransaction; + out->methods.xUndo = (int (*)(wal_impl *, int (*)(void *, unsigned int), void *))sqlite3WalUndo; + out->methods.xSavepoint = (void (*)(wal_impl *, unsigned int *))sqlite3WalSavepoint; + out->methods.xSavepointUndo = (int (*)(wal_impl *, unsigned int *))sqlite3WalSavepointUndo; + out->methods.xFrames = (int (*)(wal_impl *, int, libsql_pghdr *, unsigned int, int, int, int *))sqlite3WalFrames; + out->methods.xCheckpoint = (int (*)(wal_impl *, sqlite3 *, int, int (*)(void *), void *, int, int, unsigned char *, int *, int *, int (*)(void*, int, const unsigned char*, int, int, int), void*))sqlite3WalCheckpoint; + out->methods.xCallback = (int (*)(wal_impl *))sqlite3WalCallback; + out->methods.xExclusiveMode = (int (*)(wal_impl *, int))sqlite3WalExclusiveMode; + out->methods.xHeapMemory = (int (*)(wal_impl *))sqlite3WalHeapMemory; #ifdef SQLITE_ENABLE_SNAPSHOT - methods.xSnapshotGet = sqlite3WalSnapshotGet; - methods.xSnapshotOpen = sqlite3WalSnapshotOpen; - methods.xSnapshotRecover = sqlite3WalSnapshotRecover; - methods.xSnapshotCheck = sqlite3WalSnapshotCheck; - methods.xSnapshotUnlock = sqlite3WalSnapshotUnlock; + out->methods.xSnapshotGet = sqlite3WalSnapshotGet; + out->methods.xSnapshotOpen = sqlite3WalSnapshotOpen; + out->methods.xSnapshotRecover = sqlite3WalSnapshotRecover; + out->methods.xSnapshotCheck = sqlite3WalSnapshotCheck; + out->methods.xSnapshotUnlock = sqlite3WalSnapshotUnlock; #endif #ifdef SQLITE_ENABLE_ZIPVFS - methods.xFramesize = sqlite3WalFramesize; + outWal->methods.xFramesize = sqlite3WalFramesize; #endif - methods.xFile = sqlite3WalFile; + out->methods.xFile = (sqlite3_file *(*)(wal_impl *))sqlite3WalFile; #ifdef SQLITE_ENABLE_SETLK_TIMEOUT - methods.xWriteLock = sqlite3WalWriteLock; + outWal->methods.xWriteLock = sqlite3WalWriteLock; #endif - methods.xDb = sqlite3WalDb; - methods.xPathnameLen = libsqlWalPathnameLen; - methods.xGetWalPathname = libsqlGetWalPathname; - methods.xPreMainDbOpen = libsqlPreMainDbOpen; - - methods.bUsesShm = 1; - methods.zName = "default"; - methods.pNext = NULL; - methods_head = &methods; + out->methods.xDb = (void (*)(wal_impl *, sqlite3 *))sqlite3WalDb; - return methods_head; - } - - // Look up in the methods table - for (libsql_wal_methods *m = methods_head; m != NULL; m = m->pNext) { - if (m && strcmp(zName, m->zName) == 0) { - return m; - } + WALTRACE(("WAL%d: opened\n", pRet)); } - return NULL; + return rc; } -int libsql_wal_methods_register(libsql_wal_methods* pWalMethods) { -#ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); - if (rc != SQLITE_OK) { - return rc; - } -#endif - - if (strncmp(pWalMethods->zName, "default", 7) == 0) { - return SQLITE_MISUSE; - } - MUTEX_LOGIC(sqlite3_mutex *mutex;) - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(mutex); +SQLITE_PRIVATE void sqlite3DestroyWalManager(wal_manager_impl *self) { } - libsql_wal_methods *prev = libsql_wal_methods_find("default"); - libsql_wal_methods *m = prev->pNext; +int make_ref_counted_wal_manager(libsql_wal_manager wal_manager, RefCountedWalManager **out) { + RefCountedWalManager *p = (RefCountedWalManager*)sqlite3MallocZero(sizeof(RefCountedWalManager)); + if (!p) return SQLITE_NOMEM; + p->n = 1; + p->ref = wal_manager; + p->is_static = 0; + *out = p; + return SQLITE_OK; +} - while (1) { - if (m == NULL) { - prev->pNext = pWalMethods; - pWalMethods->pNext = NULL; - break; - } - if (strcmp(m->zName, pWalMethods->zName) == 0) { - prev->pNext = pWalMethods; - pWalMethods->pNext = m->pNext; - break; +/* + * Decrease the ref count and call the wal_manager destructor when the count reaches 0. + * Must be called from withing a critical section. + */ +void destroy_wal_manager(RefCountedWalManager *p) { + if (p->is_static) return; + assert(p->n != 0); + p->n -= 1; + if (p->n == 0) { + (p->ref.xDestroy)(p->ref.pData); + sqlite3_free(p); } - prev = m; - m = m->pNext; - } - sqlite3_mutex_leave(mutex); - return SQLITE_OK; } -int libsql_wal_methods_unregister(libsql_wal_methods *pWalMethods) { - if (strncmp(pWalMethods->zName, "default", 7) == 0) { - return SQLITE_MISUSE; - } - MUTEX_LOGIC(sqlite3_mutex *mutex;) - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); ) - sqlite3_mutex_enter(mutex); +/* + * Increase the ref count and return a pointer to the wal. + * Must be called from withing a critical section. + * Return NULL if the passed pointer ref count is already 0. + */ +RefCountedWalManager* clone_wal_manager(RefCountedWalManager *p) { + assert(p->n != 0); + p->n += 1; + return p; +} - libsql_wal_methods *prev = libsql_wal_methods_find("default"); - libsql_wal_methods *m = prev->pNext; +SQLITE_API const libsql_wal_manager sqlite3_wal_manager = { + .pData = NULL, + .xOpen = (int (*)(wal_manager_impl *, sqlite3_vfs *, sqlite3_file *, int, long long, const char*, libsql_wal *))sqlite3WalOpen, + .xClose = (int (*)(wal_manager_impl *, wal_impl *, sqlite3 *, int, int, unsigned char *))sqlite3WalClose, + .bUsesShm = 1, + .xLogDestroy = (int (*)(wal_manager_impl *, sqlite3_vfs*, const char*))sqlite3LogDestroy, + .xLogExists = (int (*)(wal_manager_impl *, sqlite3_vfs*, const char*, int *))sqlite3LogExists, + .xDestroy =(void (*)(wal_manager_impl*))sqlite3DestroyWalManager, +}; - while (m != NULL) { - if (strcmp(m->zName, pWalMethods->zName) == 0) { - prev->pNext = m->pNext; - break; +RefCountedWalManager *make_sqlite3_wal_manager_rc() { + static int initialized = 0; + static RefCountedWalManager manager = { 0 }; + /* + * re-initializing is idempotent + */ + if (!initialized) { + manager.is_static = 1; + manager.ref = sqlite3_wal_manager; + manager.n = 1; + initialized = 1; } - prev = m; - m = m->pNext; - } - sqlite3_mutex_leave(mutex); - return SQLITE_OK; + + return &manager; } -libsql_wal_methods *libsql_wal_methods_next(libsql_wal_methods *w) { - return w->pNext; +typedef struct wal_impl wal_impl; + +SQLITE_API int sqlite3_wal_backfilled(sqlite3_wal *pWal) { + return walCkptInfo(pWal)->nBackfill; } -const char *libsql_wal_methods_name(libsql_wal_methods *w) { - return w->zName; +SQLITE_API u32 sqlite3_wal_frame_page_no(sqlite3_wal *pWal, u32 iFrame) { + return walFramePgno(pWal, iFrame); } #endif /* #ifndef SQLITE_OMIT_WAL */ @@ -68368,7 +69681,7 @@ const char *libsql_wal_methods_name(libsql_wal_methods *w) { ** 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 bytes of the 9th byte are used as data. This +** As a special case, all 8 bits of the 9th byte are used as data. This ** allows a 64-bit integer to be encoded in 9 bytes. ** ** 0x00 becomes 0x00000000 @@ -68376,7 +69689,7 @@ const char *libsql_wal_methods_name(libsql_wal_methods *w) { ** 0x81 0x00 becomes 0x00000080 ** 0x82 0x00 becomes 0x00000100 ** 0x80 0x7f becomes 0x0000007f -** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 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 @@ -68459,7 +69772,7 @@ typedef struct CellInfo CellInfo; ** 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 allocats an +** As each database page is loaded into memory, the pager allocates an ** instance of this object and zeros the first 8 bytes. (This is the ** "extra" information associated with each page of the pager.) ** @@ -68752,7 +70065,7 @@ struct BtCursor { #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 ot the last entry */ +#define BTCF_AtLast 0x08 /* Cursor is pointing to 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 */ @@ -68891,14 +70204,15 @@ 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 nPage; /* Number of pages in the database */ + Pgno nCkPage; /* Pages in the database. 0 for partial check */ 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 */ const char *zPfx; /* Error message prefix */ - Pgno v1; /* Value for first %u substitution in zPfx */ - int v2; /* Value for second %d substitution in zPfx */ + 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 */ StrAccum errMsg; /* Accumulate the error message text here */ u32 *heap; /* Min-heap used for analyzing cell coverage */ sqlite3 *db; /* Database connection running the check */ @@ -68914,7 +70228,7 @@ struct IntegrityCk { /* ** get2byteAligned(), unlike get2byte(), requires that its argument point to a -** two-byte aligned address. get2bytea() is only used for accessing the +** two-byte aligned address. get2byteAligned() is only used for accessing the ** cell addresses in a btree header. */ #if SQLITE_BYTEORDER==4321 @@ -69091,7 +70405,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){ ** ** There is a corresponding leave-all procedures. ** -** Enter the mutexes in accending order by BtShared pointer address +** Enter the mutexes in ascending 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. @@ -69361,8 +70675,8 @@ SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){ int corruptPageError(int lineno, MemPage *p){ char *zMsg; sqlite3BeginBenignMalloc(); - zMsg = sqlite3_mprintf("database corruption page %d of %s", - (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) + zMsg = sqlite3_mprintf("database corruption page %u of %s", + p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) ); sqlite3EndBenignMalloc(); if( zMsg ){ @@ -70171,8 +71485,25 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow) */ 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 +#endif /* SQLITE_ENABLE_CURSOR_HINTS */ + /* ** Provide flag hints to the cursor. @@ -70257,7 +71588,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ - TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); + TRACE(("PTRMAP_UPDATE: %u->(%u,%u)\n", key, eType, parent)); *pRC= rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ pPtrmap[offset] = eType; @@ -70741,7 +72072,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocalaDataEnd, pCell, pCell+info.nLocal) ){ + if( SQLITE_OVERFLOW(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){ testcase( pSrc!=pPage ); *pRC = SQLITE_CORRUPT_BKPT; return; @@ -70842,7 +72173,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ iCellStart = get2byte(&data[hdr+5]); if( nCell>0 ){ temp = sqlite3PagerTempSpace(pPage->pBt->pPager); - memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart); + memcpy(temp, data, usableSize); src = temp; for(i=0; ihdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int top; /* First byte of cell content area */ @@ -70997,13 +72328,14 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ ** integer, so a value of 0 is used in its place. */ pTmp = &data[hdr+5]; top = get2byte(pTmp); - assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */ if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ return SQLITE_CORRUPT_PAGE(pPage); } + }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, @@ -71065,7 +72397,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ ** ** Even though the freeblock list was checked by btreeComputeFreeSpace(), ** that routine will not detect overlap between cells or freeblocks. Nor -** does it detect cells or freeblocks that encrouch into the reserved bytes +** does it detect cells or freeblocks that encroach 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. */ @@ -71086,7 +72418,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iSize>=4 ); /* Minimum cell size is 4 */ - assert( iStart<=pPage->pBt->usableSize-4 ); + assert( CORRUPT_DB || iStart<=pPage->pBt->usableSize-4 ); /* The list of freeblocks must be in ascending order. Find the ** spot on the list where iStart should be inserted. @@ -71143,6 +72475,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ } 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 ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another @@ -71154,14 +72491,9 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ }else{ /* Insert the new freeblock into the freelist */ put2byte(&data[iPtr], iStart); + put2byte(&data[iStart], iFreeBlk); + put2byte(&data[iStart+2], iSize); } - if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ - memset(&data[iStart], 0, iSize); - } - put2byte(&data[iStart], iFreeBlk); - put2byte(&data[iStart+2], iSize); pPage->nFree += iOrigSize; return SQLITE_OK; } @@ -71524,68 +72856,41 @@ SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree *p){ /* ** 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->pPage ); - assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); - assert( pCur==0 || pCur->iPage>0 ); if( pgno>btreePagecount(pBt) ){ - rc = SQLITE_CORRUPT_BKPT; - goto getAndInitPage_error1; + *ppPage = 0; + return SQLITE_CORRUPT_BKPT; } rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); if( rc ){ - goto getAndInitPage_error1; + *ppPage = 0; + return rc; } - *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( (*ppPage)->isInit==0 ){ + pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); + if( pPage->isInit==0 ){ btreePageFromDbPage(pDbPage, pgno, pBt); - rc = btreeInitPage(*ppPage); + rc = btreeInitPage(pPage); if( rc!=SQLITE_OK ){ - goto getAndInitPage_error2; + releasePage(pPage); + *ppPage = 0; + return rc; } } - assert( (*ppPage)->pgno==pgno || CORRUPT_DB ); - 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); - goto getAndInitPage_error2; - } + assert( pPage->pgno==pgno || CORRUPT_DB ); + assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); + *ppPage = pPage; return SQLITE_OK; - -getAndInitPage_error2: - releasePage(*ppPage); -getAndInitPage_error1: - if( pCur ){ - pCur->iPage--; - pCur->pPage = pCur->apPage[pCur->iPage]; - } - testcase( pgno==0 ); - assert( pgno!=0 || rc!=SQLITE_OK ); - return rc; } /* @@ -71668,7 +72973,7 @@ static void pageReinit(DbPage *pData){ ** 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-initing. */ + ** the call for every page that comes in for re-initializing. */ btreeInitPage(pPage); } } @@ -71707,7 +73012,6 @@ static int btreeInvokeBusyHandler(void *pArg){ */ SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3_vfs *pVfs, /* VFS to use for this b-tree */ - libsql_wal_methods *pWal,/* WAL methods to use for this b-tree */ const char *zFilename, /* Name of the file containing the BTree database */ sqlite3 *db, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ @@ -71848,12 +73152,15 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( 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; } - rc = sqlite3PagerOpen(pVfs, pWal, &pBt->pPager, zFilename, + rc = sqlite3PagerOpen(pVfs, db->wal_manager ,&pBt->pPager, zFilename, sizeof(MemPage), flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); @@ -72064,7 +73371,7 @@ static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ ** can mean that fillInCell() only initializes the first 2 or 3 ** bytes of pTmpSpace, but that the first 4 bytes are copied from ** it into a database page. This is not actually a problem, but it - ** does cause a valgrind error when the 1 or 2 bytes of unitialized + ** does cause a valgrind error when the 1 or 2 bytes of uninitialized ** data is passed to system call write(). So to avoid this error, ** zero the first 4 bytes of temp space here. ** @@ -72299,7 +73606,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ /* ** Return the number of bytes of space at the end of every page that -** are intentually left unused. This is the "reserved" space that is +** are intentionally 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 @@ -72546,7 +73853,6 @@ static int lockBtree(BtShared *pBt){ ){ goto page1_init_failed; } - pBt->btsFlags |= BTS_PAGESIZE_FIXED; assert( (pageSize & 7)==0 ); /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte ** integer at offset 20 is the number of bytes of space at the end of @@ -72566,6 +73872,7 @@ static int lockBtree(BtShared *pBt){ releasePageOne(pPage1); pBt->usableSize = usableSize; pBt->pageSize = pageSize; + pBt->btsFlags |= BTS_PAGESIZE_FIXED; freeTempSpace(pBt); rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, pageSize-usableSize); @@ -72585,6 +73892,7 @@ static int lockBtree(BtShared *pBt){ if( usableSize<480 ){ goto page1_init_failed; } + pBt->btsFlags |= BTS_PAGESIZE_FIXED; pBt->pageSize = pageSize; pBt->usableSize = usableSize; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -72763,7 +74071,11 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){ ** when A already has a read lock, we encourage A to give up and let B ** proceed. */ -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ +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 */ +){ BtShared *pBt = p->pBt; Pager *pPager = pBt->pPager; int rc = SQLITE_OK; @@ -72935,6 +74247,28 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers 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 @@ -73072,7 +74406,7 @@ static int relocatePage( if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; /* Move page iDbPage from its current location to page number iFreePage */ - TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", + TRACE(("AUTOVACUUM: Moving %u to free page %u (ptr page %u type %u)\n", iDbPage, iFreePage, iPtrPage, eType)); rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); if( rc!=SQLITE_OK ){ @@ -74030,7 +75364,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){ pCur->curFlags &= ~BTCF_Pinned; } -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC /* ** Return the offset into the database file for the start of the ** payload to which the cursor is pointing. @@ -74042,7 +75375,6 @@ SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){ return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + (i64)(pCur->info.pPayload - pCur->pPage->aData); } -#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* ** Return the number of bytes of payload for the entry that pCur is @@ -74068,7 +75400,7 @@ SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){ ** routine always returns 2147483647 (which is the largest record ** that SQLite can handle) or more. But returning a smaller value might ** prevent large memory allocations when trying to interpret a -** corrupt datrabase. +** corrupt database. ** ** The current implementation merely returns the size of the underlying ** database file. @@ -74530,6 +75862,7 @@ SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){ ** vice-versa). */ static int moveToChild(BtCursor *pCur, u32 newPgno){ + int rc; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPageapPage[pCur->iPage] = pCur->pPage; pCur->ix = 0; pCur->iPage++; - return getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur, - pCur->curPagerFlags); + 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; } #ifdef SQLITE_DEBUG @@ -74651,7 +75994,7 @@ static int moveToRoot(BtCursor *pCur){ sqlite3BtreeClearCursor(pCur); } rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage, - 0, pCur->curPagerFlags); + pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; @@ -74763,7 +76106,7 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ *pRes = 0; rc = moveToLeftmost(pCur); }else if( rc==SQLITE_EMPTY ){ - assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); + assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); *pRes = 1; rc = SQLITE_OK; } @@ -74868,7 +76211,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( /* If the requested key is one more than the previous key, then ** try to get there using sqlite3BtreeNext() rather than a full ** binary search. This is an optimization only. The correct answer - ** is still obtained without this case, only a little more slowely */ + ** is still obtained without this case, only a little more slowly. */ if( pCur->info.nKey+1==intKey ){ *pRes = 0; rc = sqlite3BtreeNext(pCur, 0); @@ -75264,10 +76607,36 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( }else{ chldPg = get4byte(findCell(pPage, lwr)); } - pCur->ix = (u16)lwr; - rc = moveToChild(pCur, chldPg); - if( rc ) break; - } + + /* 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: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); @@ -75358,7 +76727,8 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){ pPage = pCur->pPage; idx = ++pCur->ix; - if( NEVER(!pPage->isInit) || sqlite3FaultSim(412) ){ + if( sqlite3FaultSim(412) ) pPage->isInit = 0; + if( !pPage->isInit ){ return SQLITE_CORRUPT_BKPT; } @@ -75621,7 +76991,7 @@ static int allocateBtreePage( memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; - TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); + TRACE(("ALLOCATE: %u trunk - %u 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); @@ -75687,7 +77057,7 @@ static int allocateBtreePage( } } pTrunk = 0; - TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); + TRACE(("ALLOCATE: %u trunk - %u free pages left\n", *pPgno, n-1)); #endif }else if( k>0 ){ /* Extract a leaf from the trunk */ @@ -75732,8 +77102,8 @@ static int allocateBtreePage( ){ int noContent; *pPgno = iPage; - TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" - ": %d more free pages\n", + TRACE(("ALLOCATE: %u was leaf %u of %u on trunk %u" + ": %u more free pages\n", *pPgno, closest+1, k, pTrunk->pgno, n-1)); rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ) goto end_allocate_page; @@ -75789,7 +77159,7 @@ static int allocateBtreePage( ** becomes a new pointer-map page, the second is used by the caller. */ MemPage *pPg = 0; - TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); + TRACE(("ALLOCATE: %u 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 ){ @@ -75812,7 +77182,7 @@ static int allocateBtreePage( releasePage(*ppPage); *ppPage = 0; } - TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); + TRACE(("ALLOCATE: %u from end of file\n", *pPgno)); } assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) ); @@ -75940,7 +77310,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ } rc = btreeSetHasContent(pBt, iPage); } - TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); + TRACE(("FREE-PAGE: %u leaf on trunk page %u\n",pPage->pgno,pTrunk->pgno)); goto freepage_out; } } @@ -75961,7 +77331,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ put4byte(pPage->aData, iTrunk); put4byte(&pPage->aData[4], 0); put4byte(&pPage1->aData[32], iPage); - TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk)); + TRACE(("FREE-PAGE: %u new trunk page replacing %u\n", pPage->pgno, iTrunk)); freepage_out: if( pPage ){ @@ -76050,7 +77420,7 @@ static SQLITE_NOINLINE int clearCellOverflow( /* 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. +** Store the result code (SQLITE_OK or some error code) in rc. ** ** Implemented as macro to force inlining for performance. */ @@ -76320,6 +77690,14 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ ** 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()! */ static int insertCell( MemPage *pPage, /* Page into which we are copying */ @@ -76342,14 +77720,103 @@ static int insertCell( assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); assert( pPage->nFree>=0 ); + assert( iChild>0 ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp, pCell, sz); pCell = pTemp; } - if( iChild ){ - put4byte(pCell, 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 ); + 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 ){ 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 @@ -76381,17 +77848,7 @@ static int insertCell( assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); assert( idx+sz <= (int)pPage->pBt->usableSize ); pPage->nFree -= (u16)(2 + sz); - if( iChild ){ - /* In a corrupt database where an entry in the cell index section of - ** a btree page has a value of 3 or less, the pCell value might point - ** as many as 4 bytes in front of the start of the aData buffer for - ** the source page. Make sure this does not cause problems by not - ** reading the first 4 bytes */ - memcpy(&data[idx+4], pCell+4, sz-4); - put4byte(&data[idx], iChild); - }else{ - memcpy(&data[idx], pCell, sz); - } + memcpy(&data[idx], pCell, sz); pIns = pPage->aCellIdx + i*2; memmove(pIns+2, pIns, 2*(pPage->nCell - i)); put2byte(pIns, idx); @@ -76574,12 +78031,13 @@ static int rebuildPage( 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); - for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kixNx[k]<=i; k++){} pSrcEnd = pCArray->apEnd[k]; pData = pEnd; @@ -76642,7 +78100,7 @@ static int rebuildPage( ** 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 accomodate all +** area must be extended to before this point in order to accommodate all ** cells in apCell[], then the cells do not fit and non-zero is returned. */ static int pageInsertArray( @@ -76662,7 +78120,7 @@ static int pageInsertArray( u8 *pEnd; /* Maximum extent of cell data */ assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ if( iEnd<=iFirst ) return 0; - for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kixNx[k]<=i ; k++){} pEnd = pCArray->apEnd[k]; while( 1 /*Exit by break*/ ){ int sz, rc; @@ -76720,42 +78178,50 @@ static int pageFreeArray( u8 * const pEnd = &aData[pPg->pBt->usableSize]; u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; int nRet = 0; - int i; + int i, j; int iEnd = iFirst + nCell; - u8 *pFree = 0; /* \__ Parameters for pending call to */ - int szFree = 0; /* / freeSpace() */ + int nFree = 0; + int aOfst[10]; + int aAfter[10]; 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 ); - 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; + 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++; } nRet++; } } - if( pFree ){ - assert( pFree>aData && (pFree - aData)<65536 ); - freeSpace(pPg, (u16)(pFree - aData), szFree); + for(j=0; jpPg->aDataEnd ) goto editpage_fail; + if( NEVER(pData>pPg->aDataEnd) ) goto editpage_fail; /* Add cells to the start of the page */ if( iNew0), or ** (2) pPage is a virtual root page. A virtual root page is when @@ -77547,7 +79014,7 @@ static int balance_nonroot( ** that page. */ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); - TRACE(("BALANCE: old: %d(nc=%d) %d(nc=%d) %d(nc=%d)\n", + TRACE(("BALANCE: old: %u(nc=%u) %u(nc=%u) %u(nc=%u)\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 @@ -77631,8 +79098,8 @@ static int balance_nonroot( } } - TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) " - "%d(%d nc=%d) %d(%d nc=%d)\n", + TRACE(("BALANCE: new: %u(%u nc=%u) %u(%u nc=%u) %u(%u nc=%u) " + "%u(%u nc=%u) %u(%u nc=%u)\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, @@ -77764,9 +79231,9 @@ static int balance_nonroot( iOvflSpace += sz; assert( sz<=pBt->maxLocal+23 ); assert( iOvflSpace <= (int)pBt->pageSize ); - for(k=0; b.ixNx[k]<=j && ALWAYS(k=0 && iPg=1 || i>=0 ); + assert( iPg=0 /* On the upwards pass, or... */ || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */ @@ -77877,7 +79346,7 @@ static int balance_nonroot( } assert( pParent->isInit ); - TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", + TRACE(("BALANCE: finished: old=%u new=%u cells=%u\n", nOld, nNew, b.nCell)); /* Free any old pages that were not reused as new pages. @@ -77962,7 +79431,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); - TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); + TRACE(("BALANCE: copy root %u into %u\n", pRoot->pgno, pChild->pgno)); /* Copy the overflow cells from pRoot to pChild */ memcpy(pChild->aiOvfl, pRoot->aiOvfl, @@ -78156,7 +79625,7 @@ static int btreeOverwriteContent( ){ int nData = pX->nData - iOffset; if( nData<=0 ){ - /* Overwritting with zeros */ + /* Overwriting with zeros */ int i; for(i=0; ipData to write */ @@ -78445,7 +79914,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } } assert( pCur->eState==CURSOR_VALID - || (pCur->eState==CURSOR_INVALID && loc) ); + || (pCur->eState==CURSOR_INVALID && loc) || CORRUPT_DB ); pPage = pCur->pPage; assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) ); @@ -78460,7 +79929,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( if( rc ) return rc; } - TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", + 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 ); @@ -78487,6 +79956,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( 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 ); @@ -78535,7 +80005,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( }else{ assert( pPage->leaf ); } - rc = insertCell(pPage, idx, newCell, szNew, 0, 0); + rc = insertCellFast(pPage, idx, newCell, szNew); assert( pPage->nOverflow==0 || rc==SQLITE_OK ); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); @@ -78559,7 +80029,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** 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); @@ -78760,6 +80229,9 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ return SQLITE_CORRUPT_BKPT; } + if( pCell<&pPage->aCellIdx[pPage->nCell] ){ + return SQLITE_CORRUPT_BKPT; + } /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must ** be preserved following this delete operation. If the current delete @@ -78936,7 +80408,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ MemPage *pRoot; Pgno pgnoRoot; int rc; - int ptfFlags; /* Page-type flage for the root page of new table */ + int ptfFlags; /* Page-type flags for the root page of new table */ assert( sqlite3BtreeHoldsMutex(p) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -79105,7 +80577,7 @@ static int clearDatabasePage( if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); + rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; if( (pBt->openFlags & BTREE_SINGLE)==0 && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) @@ -79381,8 +80853,9 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ ** 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(sqlite3 *db, BtCursor *pCur, i64 *pnEntry, i64 *pnPages){ i64 nEntry = 0; /* Value to return in *pnEntry */ + i64 nPages = 0; /* Number of visited pages */ int rc; /* Return code */ rc = moveToRoot(pCur); @@ -79405,6 +80878,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){ pPage = pCur->pPage; if( pPage->leaf || !pPage->intKey ){ nEntry += pPage->nCell; + nPages++; } /* pPage is a leaf node. This loop navigates the cursor so that it @@ -79422,6 +80896,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){ if( pCur->iPage==0 ){ /* All pages of the b-tree have been visited. Return successfully. */ *pnEntry = nEntry; + *pnPages = nPages; return moveToRoot(pCur); } moveToParent(pCur); @@ -79508,7 +80983,8 @@ static void checkAppendMsg( sqlite3_str_append(&pCheck->errMsg, "\n", 1); } if( pCheck->zPfx ){ - sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); + sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, + pCheck->v0, pCheck->v1, pCheck->v2); } sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); va_end(ap); @@ -79525,7 +81001,8 @@ static void checkAppendMsg( ** corresponds to page iPg is already set. */ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + assert( pCheck->aPgRef!=0 ); + assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); } @@ -79533,7 +81010,8 @@ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ ** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. */ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + assert( pCheck->aPgRef!=0 ); + assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); } @@ -79547,12 +81025,12 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ - if( iPage>pCheck->nPage || iPage==0 ){ - checkAppendMsg(pCheck, "invalid page number %d", iPage); + if( iPage>pCheck->nCkPage || iPage==0 ){ + checkAppendMsg(pCheck, "invalid page number %u", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ - checkAppendMsg(pCheck, "2nd reference to page %d", iPage); + checkAppendMsg(pCheck, "2nd reference to page %u", iPage); return 1; } setPageReferenced(pCheck, iPage); @@ -79578,13 +81056,13 @@ static void checkPtrmap( 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=%d", iChild); + checkAppendMsg(pCheck, "Failed to read ptrmap key=%u", iChild); return; } if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ checkAppendMsg(pCheck, - "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", + "Bad ptr map entry key=%u expected=(%u,%u) got=(%u,%u)", iChild, eType, iParent, ePtrmapType, iPtrmapParent); } } @@ -79609,7 +81087,7 @@ static void checkList( if( checkRef(pCheck, iPage) ) break; N--; if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ - checkAppendMsg(pCheck, "failed to get page %d", iPage); + checkAppendMsg(pCheck, "failed to get page %u", iPage); break; } pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); @@ -79622,7 +81100,7 @@ static void checkList( #endif if( n>pCheck->pBt->usableSize/4-2 ){ checkAppendMsg(pCheck, - "freelist leaf count too big on page %d", iPage); + "freelist leaf count too big on page %u", iPage); N--; }else{ for(i=0; i<(int)n; i++){ @@ -79654,7 +81132,7 @@ static void checkList( } if( N && nErrAtStart==pCheck->nErr ){ checkAppendMsg(pCheck, - "%s is %d but should be %d", + "%s is %u but should be %u", isFreeList ? "size" : "overflow list length", expected-N, expected); } @@ -79769,11 +81247,12 @@ static int checkTreePage( usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; - pCheck->zPfx = "Page %u: "; + pCheck->zPfx = "Tree %u page %u: "; pCheck->v1 = iPage; if( (rc = btreeGetPage(pBt, 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; } @@ -79796,7 +81275,7 @@ static int checkTreePage( hdr = pPage->hdrOffset; /* Set up for cell analysis */ - pCheck->zPfx = "On tree page %u cell %d: "; + pCheck->zPfx = "Tree %u page %u cell %u: "; contentOffset = get2byteNotZero(&data[hdr+5]); assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ @@ -79816,7 +81295,7 @@ static int checkTreePage( pgno = get4byte(&data[hdr+8]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - pCheck->zPfx = "On page %u at right child: "; + pCheck->zPfx = "Tree %u page %u right child: "; checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); } #endif @@ -79840,7 +81319,7 @@ static int checkTreePage( pc = get2byteAligned(pCellIdx); pCellIdx -= 2; if( pcusableSize-4 ){ - checkAppendMsg(pCheck, "Offset %d out of range %d..%d", + checkAppendMsg(pCheck, "Offset %u out of range %u..%u", pc, contentOffset, usableSize-4); doCoverageCheck = 0; continue; @@ -79972,7 +81451,7 @@ static int checkTreePage( */ if( heap[0]==0 && nFrag!=data[hdr+7] ){ checkAppendMsg(pCheck, - "Fragmentation of %d bytes reported as %d on page %u", + "Fragmentation of %u bytes reported as %u on page %u", nFrag, data[hdr+7], iPage); } } @@ -80044,15 +81523,15 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( sCheck.db = db; sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; - sCheck.nPage = btreePagecount(sCheck.pBt); + sCheck.nCkPage = btreePagecount(sCheck.pBt); sCheck.mxErr = mxErr; sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; - if( sCheck.nPage==0 ){ + if( sCheck.nCkPage==0 ){ goto integrity_ck_cleanup; } - sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); + sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); if( !sCheck.aPgRef ){ checkOom(&sCheck); goto integrity_ck_cleanup; @@ -80064,12 +81543,12 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( } i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); + if( i<=sCheck.nCkPage ) setPageReferenced(&sCheck, i); /* Check the integrity of the freelist */ if( bCkFreelist ){ - sCheck.zPfx = "Main freelist: "; + sCheck.zPfx = "Freelist: "; checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36])); sCheck.zPfx = 0; @@ -80086,7 +81565,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( mxInHdr = get4byte(&pBt->pPage1->aData[52]); if( mx!=mxInHdr ){ checkAppendMsg(&sCheck, - "max rootpage (%d) disagrees with header (%d)", + "max rootpage (%u) disagrees with header (%u)", mx, mxInHdr ); } @@ -80107,6 +81586,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); } #endif + sCheck.v0 = aRoot[i]; checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); } pBt->db->flags = savedDbFlags; @@ -80114,10 +81594,10 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( /* Make sure every page in the file is referenced */ if( !bPartial ){ - for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ + for(i=1; i<=sCheck.nCkPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( getPageReferenced(&sCheck, i)==0 ){ - checkAppendMsg(&sCheck, "Page %d is never used", i); + checkAppendMsg(&sCheck, "Page %u: never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain @@ -80125,11 +81605,11 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck( */ if( getPageReferenced(&sCheck, i)==0 && (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Page %d is never used", i); + checkAppendMsg(&sCheck, "Page %u: never used", i); } if( getPageReferenced(&sCheck, i)!=0 && (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i); + checkAppendMsg(&sCheck, "Page %u: pointer map referenced", i); } #endif } @@ -80691,13 +82171,7 @@ static int backupOnePage( assert( !isFatalError(p->rc) ); assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); assert( zSrcData ); - - /* 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; - } + assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 ); /* This loop runs once for each destination page spanned by the source ** page. For each iteration, variable iOff is set to the byte offset @@ -80830,7 +82304,10 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); pgszDest = sqlite3BtreeGetPageSize(p->pDest); destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); - if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ + if( SQLITE_OK==rc + && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager)) + && pgszSrc!=pgszDest + ){ rc = SQLITE_READONLY; } @@ -81379,6 +82856,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){ 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 */ @@ -81535,6 +83013,40 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ 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. @@ -81661,7 +83173,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ vdbeMemRenderNum(nByte, pMem->z, pMem); assert( pMem->z!=0 ); - assert( pMem->n==sqlite3Strlen30NN(pMem->z) ); + assert( pMem->n==(int)sqlite3Strlen30NN(pMem->z) ); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); @@ -81796,36 +83308,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){ if( p->szMalloc ) vdbeMemClear(p); } -/* -** 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. -*/ -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. @@ -81852,7 +83334,7 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ testcase( flags & MEM_IntReal ); return pMem->u.i; }else if( flags & MEM_Real ){ - return doubleToInt64(pMem->u.r); + return sqlite3RealToI64(pMem->u.r); }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){ return memIntValue(pMem); }else{ @@ -81914,7 +83396,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ if( pMem->flags & MEM_IntReal ){ MemSetTypeFlag(pMem, MEM_Int); }else{ - i64 ix = doubleToInt64(pMem->u.r); + i64 ix = sqlite3RealToI64(pMem->u.r); /* Only mark the value as an integer if ** @@ -81982,8 +83464,8 @@ SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ ** from UBSAN. */ SQLITE_PRIVATE i64 sqlite3RealToI64(double r){ - if( r<=(double)SMALLEST_INT64 ) return SMALLEST_INT64; - if( r>=(double)LARGEST_INT64) return LARGEST_INT64; + if( r<-9223372036854774784.0 ) return SMALLEST_INT64; + if( r>+9223372036854774784.0 ) return LARGEST_INT64; return (i64)r; } @@ -82054,6 +83536,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ break; } default: { + int rc; assert( aff==SQLITE_AFF_TEXT ); assert( MEM_Str==(MEM_Blob>>3) ); pMem->flags |= (pMem->flags&MEM_Blob)>>3; @@ -82061,7 +83544,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 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; - return sqlite3VdbeChangeEncoding(pMem, encoding); + rc = sqlite3VdbeChangeEncoding(pMem, encoding); + if( rc ) return rc; + sqlite3VdbeMemZeroTerminateIfAble(pMem); } } return SQLITE_OK; @@ -82585,6 +84070,24 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ 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. */ @@ -82652,6 +84155,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ } pRec->nField = p->iVal+1; + sqlite3VdbeMemSetNull(&pRec->aMem[p->iVal]); return &pRec->aMem[p->iVal]; } #else @@ -82705,6 +84209,9 @@ static int valueFromFunction( 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) @@ -82741,16 +84248,11 @@ static int valueFromFunction( }else{ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); assert( rc==SQLITE_OK ); - assert( enc==pVal->enc - || (pVal->flags & MEM_Str)==0 - || db->mallocFailed ); -#if 0 /* Not reachable except after a prior failure */ rc = sqlite3VdbeChangeEncoding(pVal, enc); - if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ + if( NEVER(rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal)) ){ rc = SQLITE_TOOBIG; pCtx->pParse->nErr++; } -#endif } value_from_function_out: @@ -82814,6 +84316,13 @@ static int valueFromExpr( 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); } @@ -82906,6 +84415,7 @@ static int valueFromExpr( if( pVal ){ pVal->flags = MEM_Int; pVal->u.i = pExpr->u.zToken[4]==0; + sqlite3ValueApplyAffinity(pVal, affinity, enc); } } @@ -83435,6 +84945,35 @@ static void test_addop_breakpoint(int pc, Op *pOp){ } #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. @@ -83445,17 +84984,16 @@ static void test_addop_breakpoint(int pc, Op *pOp){ ** ** op The opcode for this instruction ** -** p1, p2, p3 Operands -** -** Use the sqlite3VdbeResolveLabel() function to fix an address and -** the sqlite3VdbeChangeP4() function to change the value of the P4 -** operand. +** p1, p2, p3, p4 Operands */ -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); +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; @@ -83478,6 +85016,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ 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 @@ -83494,16 +85035,59 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ #ifdef SQLITE_VDBE_COVERAGE pOp->iSrcLine = 0; #endif + /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ** Replicate in sqlite3VdbeAddOp4Int() */ + 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 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 @@ -83681,7 +85265,7 @@ SQLITE_PRIVATE int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, if( bPush){ pParse->addrExplain = iThis; } - sqlite3VdbeScanStatus(v, iThis, 0, 0, 0, 0); + sqlite3VdbeScanStatus(v, iThis, -1, -1, 0, 0); } return addr; } @@ -83711,26 +85295,6 @@ SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, 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){ @@ -84037,11 +85601,13 @@ static void resolveP2Values(Vdbe *p, int *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 termates when it reaches the OP_Init opcode */ ){ + while( 1 /* Loop terminates when it reaches the OP_Init opcode */ ){ /* 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 @@ -84096,6 +85662,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ ** 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)]; } break; @@ -84162,6 +85729,10 @@ SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn( 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 ); @@ -84410,8 +85981,8 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters( pScan = 0; } if( pScan ){ - pScan->addrLoop = addrLoop; - pScan->addrVisit = addrVisit; + if( addrLoop>0 ) pScan->addrLoop = addrLoop; + if( addrVisit>0 ) pScan->addrVisit = addrVisit; } } } @@ -84494,7 +86065,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ /* ** If the input FuncDef structure is ephemeral, then free it. If -** the FuncDef is not ephermal, then do nothing. +** the FuncDef is not ephemeral, then do nothing. */ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ assert( db!=0 ); @@ -84658,7 +86229,6 @@ SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters( } #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 @@ -84839,7 +86409,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ /* Return the most recently added opcode */ -VdbeOp * sqlite3VdbeGetLastOp(Vdbe *p){ +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe *p){ return sqlite3VdbeGetOp(p, p->nOp - 1); } @@ -85579,7 +87149,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( sqlite3VdbeMemSetInt64(pMem+1, pOp->p2); sqlite3VdbeMemSetInt64(pMem+2, pOp->p3); sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free); - p->nResColumn = 4; + assert( p->nResColumn==4 ); }else{ sqlite3VdbeMemSetInt64(pMem+0, i); sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode), @@ -85598,7 +87168,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( sqlite3VdbeMemSetNull(pMem+7); #endif sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free); - p->nResColumn = 8; + assert( p->nResColumn==8 ); } p->pResultRow = pMem; if( db->mallocFailed ){ @@ -85812,26 +87382,9 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); if( pParse->explain ){ - static const char * const azColName[] = { - "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", - "id", "parent", "notused", "detail" - }; - int iFirst, mx, i; if( nMem<10 ) nMem = 10; p->explain = pParse->explain; - if( pParse->explain==2 ){ - sqlite3VdbeSetNumCols(p, 4); - iFirst = 8; - mx = 12; - }else{ - sqlite3VdbeSetNumCols(p, 8); - iFirst = 0; - mx = 8; - } - for(i=iFirst; inResColumn = 12 - 4*p->explain; } p->expired = 0; @@ -85883,7 +87436,23 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( 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); + return; + } switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); @@ -85984,12 +87553,12 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ int n; sqlite3 *db = p->db; - if( p->nResColumn ){ - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + if( p->nResAlloc ){ + releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); sqlite3DbFree(db, p->aColName); } n = nResColumn*COLNAME_N; - p->nResColumn = (u16)nResColumn; + p->nResColumn = p->nResAlloc = (u16)nResColumn; p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; initMemArray(p->aColName, n, db, MEM_Null); @@ -86014,14 +87583,14 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName( ){ int rc; Mem *pColName; - assert( idxnResColumn ); + assert( idxnResAlloc ); assert( vardb->mallocFailed ){ assert( !zName || xDel!=SQLITE_DYNAMIC ); return SQLITE_NOMEM_BKPT; } assert( p->aColName!=0 ); - pColName = &(p->aColName[idx+var*p->nResColumn]); + pColName = &(p->aColName[idx+var*p->nResAlloc]); rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); return rc; @@ -86534,6 +88103,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ + sqlite3SystemError(db, rc); p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; @@ -86543,6 +88113,8 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ db->flags &= ~(u64)SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } + }else if( p->rc==SQLITE_SCHEMA && db->nVdbeActive>1 ){ + p->nChange = 0; }else{ sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; @@ -86843,7 +88415,7 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ assert( db!=0 ); assert( p->db==0 || p->db==db ); if( p->aColName ){ - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); sqlite3DbNNFreeNN(db, p->aColName); } for(pSub=p->pProgram; pSub; pSub=pNext){ @@ -86861,9 +88433,9 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ #ifdef SQLITE_ENABLE_NORMALIZE sqlite3DbFree(db, p->zNormSql); { - DblquoteStr *pThis, *pNext; - for(pThis=p->pDblStr; pThis; pThis=pNext){ - pNext = pThis->pNextStr; + DblquoteStr *pThis, *pNxt; + for(pThis=p->pDblStr; pThis; pThis=pNxt){ + pNxt = pThis->pNextStr; sqlite3DbFree(db, pThis); } } @@ -87443,6 +89015,15 @@ static int vdbeRecordCompareDebug( 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() */ + } break; } @@ -87611,20 +89192,33 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem 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 ){ + if( sqlite3IsNaN(r) ){ + /* SQLite considers NaN to be a NULL. And all integer values are greater + ** than NULL */ + return 1; + } + if( sqlite3Config.bUseLongDouble ){ LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; testcase( xr ); testcase( x==r ); - if( xr ) return +1; /*NO_TEST*/ /* work around bugs in gcov */ - return 0; /*NO_TEST*/ /* work around bugs in gcov */ + return (xr); }else{ i64 y; double s; @@ -87634,9 +89228,10 @@ SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){ if( iy ) return +1; s = (double)i; - if( sr ) return +1; - return 0; + testcase( doubleLt(s,r) ); + testcase( doubleLt(r,s) ); + testcase( doubleEq(r,s) ); + return (sr); } } @@ -87886,7 +89481,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* Serial types 12 or greater are strings and blobs (greater than ** numbers). Types 10 and 11 are currently "reserved for future ** use", so it doesn't really matter what the results of comparing - ** them to numberic values are. */ + ** them to numeric values are. */ rc = serial_type==10 ? -1 : +1; }else if( serial_type==0 ){ rc = -1; @@ -88490,6 +90085,20 @@ SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){ 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 @@ -88552,6 +90161,16 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( 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)); @@ -88568,8 +90187,8 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( assert( pCsr!=0 ); assert( pCsr->eCurType==CURTYPE_BTREE ); - assert( pCsr->nField==pTab->nCol - || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) + assert( pCsr->nField==nRealCol + || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1) ); preupdate.v = v; @@ -88876,7 +90495,7 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ SQLITE_NULL, /* 0x1f (not possible) */ SQLITE_FLOAT, /* 0x20 INTREAL */ SQLITE_NULL, /* 0x21 (not possible) */ - SQLITE_TEXT, /* 0x22 INTREAL + TEXT */ + SQLITE_FLOAT, /* 0x22 INTREAL + TEXT */ SQLITE_NULL, /* 0x23 (not possible) */ SQLITE_FLOAT, /* 0x24 (not possible) */ SQLITE_NULL, /* 0x25 (not possible) */ @@ -88980,7 +90599,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ ** is too big or if an OOM occurs. ** ** The invokeValueDestructor(P,X) routine invokes destructor function X() -** on value P is not going to be used and need to be destroyed. +** on value P if P is not going to be used and need to be destroyed. */ static void setResultStrOrError( sqlite3_context *pCtx, /* Function context */ @@ -89010,7 +90629,7 @@ static void setResultStrOrError( static int invokeValueDestructor( const void *p, /* Value to destroy */ void (*xDel)(void*), /* The destructor */ - sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */ + sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if not NULL */ ){ assert( xDel!=SQLITE_DYNAMIC ); if( xDel==0 ){ @@ -89020,7 +90639,14 @@ static int invokeValueDestructor( }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 return SQLITE_TOOBIG; } SQLITE_API void sqlite3_result_blob( @@ -89029,6 +90655,12 @@ SQLITE_API void sqlite3_result_blob( 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); @@ -89039,8 +90671,14 @@ SQLITE_API void sqlite3_result_blob64( sqlite3_uint64 n, void (*xDel)(void *) ){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); 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) ); if( n>0x7fffffff ){ (void)invokeValueDestructor(z, xDel, pCtx); }else{ @@ -89048,30 +90686,48 @@ SQLITE_API void sqlite3_result_blob64( } } 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; 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; 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); } @@ -89081,14 +90737,25 @@ SQLITE_API void sqlite3_result_pointer( const char *zPType, void (*xDestructor)(void*) ){ - Mem *pOut = pCtx->pOut; + Mem *pOut; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ){ + invokeValueDestructor(pPtr, xDestructor, 0); + return; + } +#endif + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); sqlite3VdbeMemRelease(pOut); pOut->flags = MEM_Null; sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor); } SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ - Mem *pOut = pCtx->pOut; + Mem *pOut; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return; +#endif + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; pOut->flags |= MEM_Subtype; @@ -89099,6 +90766,12 @@ SQLITE_API void sqlite3_result_text( 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); } @@ -89109,6 +90782,12 @@ SQLITE_API void sqlite3_result_text64( 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 ){ @@ -89119,6 +90798,7 @@ SQLITE_API void sqlite3_result_text64( (void)invokeValueDestructor(z, xDel, pCtx); }else{ setResultStrOrError(pCtx, z, (int)n, enc, xDel); + sqlite3VdbeMemZeroTerminateIfAble(pCtx->pOut); } } #ifndef SQLITE_OMIT_UTF16 @@ -89151,7 +90831,16 @@ SQLITE_API void sqlite3_result_text16le( } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - Mem *pOut = pCtx->pOut; + 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); @@ -89163,7 +90852,12 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0); } SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ - Mem *pOut = pCtx->pOut; + Mem *pOut; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCtx==0 ) return SQLITE_MISUSE_BKPT; +#endif + pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(pCtx); @@ -89177,6 +90871,9 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 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; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; @@ -89189,6 +90886,9 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ /* 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, @@ -89197,6 +90897,9 @@ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ /* 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; @@ -89449,7 +91152,11 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ ** pointer to it. */ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( p==0 ) return 0; +#else assert( p && p->pFunc ); +#endif return p->pFunc->pUserData; } @@ -89464,7 +91171,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ ** 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; } @@ -89483,7 +91194,11 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ ** 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); } @@ -89491,7 +91206,7 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ ** 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 -** preceeded by activation of IN processing via sqlite3_vtab_int() do 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){ @@ -89511,7 +91226,7 @@ static int valueFromValueList( ValueList *pRhs; *ppOut = 0; - if( pVal==0 ) return SQLITE_MISUSE; + if( pVal==0 ) return SQLITE_MISUSE_BKPT; if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){ return SQLITE_ERROR; }else{ @@ -89642,6 +91357,9 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ 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( pCtx->pVdbe==0 ) return 0; @@ -89674,8 +91392,12 @@ SQLITE_API void sqlite3_set_auxdata( void (*xDelete)(void*) ){ AuxData *pAuxData; - Vdbe *pVdbe = pCtx->pVdbe; + Vdbe *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 if( pVdbe==0 ) goto failed; @@ -89731,7 +91453,8 @@ SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ */ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; - return pVm ? pVm->nResColumn : 0; + if( pVm==0 ) return 0; + return pVm->nResColumn; } /* @@ -89820,7 +91543,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ ** sqlite3_column_real() ** sqlite3_column_bytes() ** sqlite3_column_bytes16() -** sqiite3_column_blob() +** sqlite3_column_blob() */ static void columnMallocFailure(sqlite3_stmt *pStmt) { @@ -89904,6 +91627,32 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ 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. @@ -89936,15 +91685,29 @@ static const void *columnName( return 0; } #endif + if( N<0 ) return 0; ret = 0; p = (Vdbe *)pStmt; db = p->db; assert( db!=0 ); - n = sqlite3_column_count(pStmt); - if( N=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 += useType*n; - sqlite3_mutex_enter(db->mutex); - assert( db->mallocFailed==0 ); #ifndef SQLITE_OMIT_UTF16 if( useUtf16 ){ ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); @@ -89956,12 +91719,14 @@ static const void *columnName( /* A malloc may have failed inside of the _text() call. If this ** is the case, clear the mallocFailed flag and return NULL. */ - if( db->mallocFailed ){ + assert( db->mallocFailed==0 || db->mallocFailed==1 ); + if( db->mallocFailed > prior_mallocFailed ){ sqlite3OomClear(db); ret = 0; } - sqlite3_mutex_leave(db->mutex); } +columnName_end: + sqlite3_mutex_leave(db->mutex); return ret; } @@ -90054,7 +91819,7 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ /* ** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is -** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. +** out of range, then SQLITE_RANGE is returned. Otherwise SQLITE_OK. ** ** A successful evaluation of this routine acquires the mutex on p. ** the mutex is released if any kind of error occurs. @@ -90069,7 +91834,7 @@ static int vdbeUnbind(Vdbe *p, unsigned int i){ } sqlite3_mutex_enter(p->db->mutex); if( p->eVdbeState!=VDBE_READY_STATE ){ - sqlite3Error(p->db, SQLITE_MISUSE); + sqlite3Error(p->db, SQLITE_MISUSE_BKPT); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); @@ -90298,6 +92063,9 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ 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; @@ -90418,6 +92186,42 @@ 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. */ @@ -90458,7 +92262,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ u32 v; #ifdef SQLITE_ENABLE_API_ARMOR if( !pStmt - || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) + || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||(op>=ArraySize(pVdbe->aCounter)&&oppPreUpdate; + PreUpdate *p; Mem *pMem; int rc = SQLITE_OK; +#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 ){ @@ -90624,7 +92434,12 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa ** the number of columns in the row being updated, deleted or inserted. */ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; +#ifdef SQLITE_ENABLE_API_ARMOR + p = db!=0 ? db->pPreUpdate : 0; +#else + p = db->pPreUpdate; +#endif return (p ? p->keyinfo.nKeyField : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ @@ -90642,7 +92457,12 @@ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ ** or SET DEFAULT action is considered a trigger. */ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; +#ifdef SQLITE_ENABLE_API_ARMOR + p = db!=0 ? db->pPreUpdate : 0; +#else + p = db->pPreUpdate; +#endif return (p ? p->v->nFrame : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ @@ -90653,7 +92473,12 @@ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ ** only. */ SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ - PreUpdate *p = db->pPreUpdate; + PreUpdate *p; +#ifdef SQLITE_ENABLE_API_ARMOR + p = db!=0 ? db->pPreUpdate : 0; +#else + p = db->pPreUpdate; +#endif return (p ? p->iBlobWrite : -1); } #endif @@ -90664,10 +92489,16 @@ SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ ** 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 = db->pPreUpdate; + PreUpdate *p; int rc = SQLITE_OK; Mem *pMem; +#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; @@ -90746,15 +92577,33 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; - ScanStatus *pScan; + 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; iinOp; ii++){ - res += p->aOp[ii].nCycle; + for(ii=0; iiaddrLoop>0 ){ - *(sqlite3_int64*)pOut = p->aOp[pScan->addrLoop].nExec; + *(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec; }else{ *(sqlite3_int64*)pOut = -1; } @@ -90788,7 +92637,7 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( } case SQLITE_SCANSTAT_NVISIT: { if( pScan->addrVisit>0 ){ - *(sqlite3_int64*)pOut = p->aOp[pScan->addrVisit].nExec; + *(sqlite3_int64*)pOut = aOp[pScan->addrVisit].nExec; }else{ *(sqlite3_int64*)pOut = -1; } @@ -90810,7 +92659,7 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( } case SQLITE_SCANSTAT_EXPLAIN: { if( pScan->addrExplain ){ - *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; + *(const char**)pOut = aOp[ pScan->addrExplain ].p4.z; }else{ *(const char**)pOut = 0; } @@ -90818,7 +92667,7 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( } case SQLITE_SCANSTAT_SELECTID: { if( pScan->addrExplain ){ - *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; + *(int*)pOut = aOp[ pScan->addrExplain ].p1; }else{ *(int*)pOut = -1; } @@ -90826,7 +92675,7 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( } case SQLITE_SCANSTAT_PARENTID: { if( pScan->addrExplain ){ - *(int*)pOut = p->aOp[ pScan->addrExplain ].p2; + *(int*)pOut = aOp[ pScan->addrExplain ].p2; }else{ *(int*)pOut = -1; } @@ -90844,18 +92693,18 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2( if( iIns==0 ) break; if( iIns>0 ){ while( iIns<=iEnd ){ - res += p->aOp[iIns].nCycle; + res += aOp[iIns].nCycle; iIns++; } }else{ int iOp; - for(iOp=0; iOpnOp; iOp++){ - Op *pOp = &p->aOp[iOp]; + for(iOp=0; iOpp1!=iEnd ) continue; if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){ continue; } - res += p->aOp[iOp].nCycle; + res += aOp[iOp].nCycle; } } } @@ -90888,7 +92737,7 @@ SQLITE_API int sqlite3_stmt_scanstatus( SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; int ii; - for(ii=0; iinOp; ii++){ + for(ii=0; p!=0 && iinOp; ii++){ Op *pOp = &p->aOp[ii]; pOp->nExec = 0; pOp->nCycle = 0; @@ -91654,6 +93503,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){ 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)"); + } } } #endif @@ -91790,6 +93642,93 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){ 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 */ @@ -91837,6 +93776,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( 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; @@ -92032,8 +93972,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec( case OP_Goto: { /* jump */ #ifdef SQLITE_DEBUG - /* In debuggging mode, when the p5 flags is set on an OP_Goto, that - ** means we should really jump back to the preceeding OP_ReleaseReg + /* 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) ); @@ -92241,7 +94181,7 @@ case OP_HaltIfNull: { /* in3 */ ** P5 is a value between 0 and 4, inclusive, that modifies the P4 string. ** ** 0: (no change) -** 1: NOT NULL contraint failed: P4 +** 1: NOT NULL constraint failed: P4 ** 2: UNIQUE constraint failed: P4 ** 3: CHECK constraint failed: P4 ** 4: FOREIGN KEY constraint failed: P4 @@ -93372,10 +95312,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** opcodes are allowed to occur between this instruction and the previous ** OP_Lt or OP_Gt. ** -** If result of an OP_Eq comparison on the same two operands as the -** prior OP_Lt or OP_Gt would have been true, then jump to P2. -** If the result of an OP_Eq comparison on the two previous -** operands would have been false or NULL, then fall through. +** 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 */ @@ -93502,7 +95442,7 @@ case OP_Compare: { /* 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. @@ -93729,6 +95669,12 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ ** (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. @@ -93799,7 +95745,7 @@ case OP_IsType: { /* jump */ /* Opcode: ZeroOrNull P1 P2 P3 * * ** Synopsis: r[P2] = 0 OR NULL ** -** If all both registers P1 and P3 are NOT NULL, then store a zero in +** 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. */ @@ -93842,7 +95788,7 @@ case OP_IfNullRow: { /* jump */ VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - if( ALWAYS(pC) && pC->nullRow ){ + if( pC && pC->nullRow ){ sqlite3VdbeMemSetNull(aMem + pOp->p3); goto jump_to_p2; } @@ -94153,11 +96099,16 @@ case OP_Column: { /* ncycle */ 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( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 - && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) - || (len = sqlite3VdbeSerialTypeLen(t))==0 + if( ((p5 = (pOp->p5 & OPFLAG_BYTELENARG))!=0 + && (p5==OPFLAG_TYPEOFARG + || (t>=12 && ((t&1)==0 || p5==OPFLAG_BYTELENARG)) + ) + ) + || sqlite3VdbeSerialTypeLen(t)==0 ){ /* Content is irrelevant for ** 1. the typeof() function, @@ -94174,11 +96125,13 @@ case OP_Column: { /* ncycle */ */ sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); }else{ - if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big; - 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; + 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; + } } } @@ -94337,7 +96290,7 @@ case OP_Affinity: { }else{ pIn1->u.r = (double)pIn1->u.i; pIn1->flags |= MEM_Real; - pIn1->flags &= ~MEM_Int; + pIn1->flags &= ~(MEM_Int|MEM_Str); } } REGISTER_TRACE((int)(pIn1-aMem), pIn1); @@ -94640,7 +96593,6 @@ case OP_MakeRecord: { /* NULL value. No change in zPayload */ }else{ u64 v; - u32 i; if( serial_type==7 ){ assert( sizeof(v)==sizeof(pRec->u.r) ); memcpy(&v, &pRec->u.r, sizeof(v)); @@ -94648,12 +96600,17 @@ case OP_MakeRecord: { }else{ v = pRec->u.i; } - len = i = sqlite3SmallTypeSizes[serial_type]; - assert( i>0 ); - while( 1 /*exit-by-break*/ ){ - zPayload[--i] = (u8)(v&0xFF); - if( i==0 ) break; - v >>= 8; + 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; + case 6: zPayload[5] = (u8)(v&0xff); v >>= 8; + zPayload[4] = (u8)(v&0xff); v >>= 8; + case 4: zPayload[3] = (u8)(v&0xff); v >>= 8; + case 3: zPayload[2] = (u8)(v&0xff); v >>= 8; + case 2: zPayload[1] = (u8)(v&0xff); v >>= 8; + case 1: zPayload[0] = (u8)(v&0xff); } zPayload += len; } @@ -94704,8 +96661,9 @@ case OP_Count: { /* out2 */ nEntry = sqlite3BtreeRowCountEst(pCrsr); }else{ nEntry = 0; /* Not needed. Only used to silence a warning. */ - rc = sqlite3BtreeCount(db, pCrsr, &nEntry); - p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE] += nEntry; + i64 nPages = 0; + rc = sqlite3BtreeCount(db, pCrsr, &nEntry, &nPages); + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE] += nPages; if( rc ) goto abort_due_to_error; } pOut = out2Prerelease(p, pOp); @@ -95463,7 +97421,7 @@ case OP_OpenEphemeral: { /* ncycle */ } pCx = p->apCsr[pOp->p1]; if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){ - /* If the ephermeral table is already open and has no duplicates from + /* 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 ); @@ -95474,7 +97432,7 @@ case OP_OpenEphemeral: { /* ncycle */ pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, db->pWalMethods, 0, db, &pCx->ub.pBtx, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ @@ -95955,7 +97913,7 @@ case OP_SeekGT: { /* jump, in3, group, ncycle */ ** 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 constraing. The jump to SeekGE.P2 ends the loop. The P5!=0 case +** 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 @@ -95963,7 +97921,7 @@ case OP_SeekGT: { /* jump, in3, group, ncycle */ ** ** Possible outcomes from this opcode:
        ** -**
      1. If the cursor is initally not pointed to any valid row, then +**
      2. If the cursor is initially not pointed to any valid row, then ** fall through into the subsequent OP_SeekGE opcode. ** **
      3. If the cursor is left pointing to a row that is before the target @@ -96078,6 +98036,7 @@ case OP_SeekScan: { /* ncycle */ break; } nStep--; + pC->cacheStatus = CACHE_STALE; rc = sqlite3BtreeNext(pC->uc.pCursor, 0); if( rc ){ if( rc==SQLITE_DONE ){ @@ -96194,13 +98153,13 @@ case OP_IfNotOpen: { /* jump */ ** 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 works +** 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 skips some work. So if seekHit +** 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. ** @@ -96736,8 +98695,8 @@ case OP_Insert: { #endif assert( (pOp->p5 & OPFLAG_LASTROWID)==0 || (pOp->p5 & OPFLAG_NCHANGE)!=0 ); + if (!pC->isEphemeral) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; if( pOp->p5 & OPFLAG_NCHANGE ){ - p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; p->nChange++; if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; } @@ -96758,6 +98717,7 @@ case OP_Insert: { ); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + colCacheCtr++; /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; @@ -96811,13 +98771,18 @@ case OP_RowCell: { ** left in an undefined state. ** ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this -** 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. +** 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 flag of P2 (NB: P2 not P5) is set, then the row -** change count is incremented (otherwise not). +** 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. ** ** P1 must not be pseudo-table. It has to be a real table with ** multiple rows. @@ -96918,12 +98883,13 @@ case OP_Delete: { 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->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; + if (!pC->isEphemeral) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; p->nChange++; if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, @@ -96986,13 +98952,13 @@ case OP_SorterCompare: { ** 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 use to move a record out of the sorter and into +** This opcode is normally used 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: { +case OP_SorterData: { /* ncycle */ VdbeCursor *pC; pOut = &aMem[pOp->p2]; @@ -97211,6 +99177,7 @@ case OP_Last: { /* jump, ncycle */ pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( rc ) goto abort_due_to_error; + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; if( pOp->p2>0 ){ VdbeBranchTaken(res!=0,2); if( res ) goto jump_to_p2; @@ -97267,8 +99234,8 @@ case OP_IfSmaller: { /* jump */ ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ -case OP_SorterSort: /* jump */ -case OP_Sort: { /* jump */ +case OP_SorterSort: /* jump ncycle */ +case OP_Sort: { /* jump ncycle */ #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; @@ -97478,7 +99445,7 @@ case OP_IdxInsert: { /* in2 */ pIn2 = &aMem[pOp->p2]; assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) ); if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_NCHANGE ) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; + if (!pC->isEphemeral) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->isTable==0 ); rc = ExpandBlob(pIn2); @@ -97798,7 +99765,7 @@ case OP_IdxGE: { /* jump, ncycle */ ** 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 clear is in the auxiliary database file +** P3==1 then the table to be destroyed 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 @@ -97858,8 +99825,8 @@ case OP_Destroy: { /* out2 */ ** 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 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 +** 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 ** 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 @@ -97879,7 +99846,7 @@ case OP_Clear: { rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange); if( pOp->p3 ){ p->nChange += nChange; - p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE] += nChange; if( pOp->p3>0 ){ assert( memIsValid(&aMem[pOp->p3]) ); memAboutToChange(p, &aMem[pOp->p3]); @@ -97946,13 +99913,41 @@ case OP_CreateBtree: { /* out2 */ /* Opcode: SqlExec * * * P4 * ** ** Run the SQL statement or statements specified in the P4 string. +** Disable Auth and Trace callbacks while those statements are running if +** P1 is true. */ case OP_SqlExec: { + char *zErr; +#ifndef SQLITE_OMIT_AUTHORIZATION + sqlite3_xauth xAuth; +#endif + u8 mTrace; + sqlite3VdbeIncrWriteCounter(p, 0); db->nSqlExec++; - rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); + zErr = 0; +#ifndef SQLITE_OMIT_AUTHORIZATION + xAuth = db->xAuth; +#endif + mTrace = db->mTrace; + if( pOp->p1 ){ +#ifndef SQLITE_OMIT_AUTHORIZATION + db->xAuth = 0; +#endif + db->mTrace = 0; + } + rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); db->nSqlExec--; - if( rc ) goto abort_due_to_error; +#ifndef SQLITE_OMIT_AUTHORIZATION + db->xAuth = xAuth; +#endif + db->mTrace = mTrace; + if( zErr || rc ){ + sqlite3VdbeError(p, "%s", zErr); + sqlite3_free(zErr); + if( rc==SQLITE_NOMEM ) goto no_mem; + goto abort_due_to_error; + } break; } @@ -98686,7 +100681,7 @@ case OP_AggStep1: { /* 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 */ + ** reinitializes the relevant 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]; @@ -99173,6 +101168,53 @@ case OP_VOpen: { /* ncycle */ } #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_TABLE ); + pTab = pOp->p4.pTab; + assert( pTab!=0 ); + assert( IsVirtual(pTab) ); + assert( pTab->u.vtab.p!=0 ); + pVtab = pTab->u.vtab.p->pVtab; + assert( pVtab!=0 ); + pModule = pVtab->pModule; + assert( pModule!=0 ); + assert( pModule->iVersion>=4 ); + assert( pModule->xIntegrity!=0 ); + pTab->nTabRef++; + 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); + sqlite3DeleteTable(db, pTab); + 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) @@ -99223,11 +101265,11 @@ case OP_VPreparedSql: { pModule = pVtab->pModule; /* Invoke the xPreparedSql method */ - if( pModule->iVersion>=700 ){ - if( pModule->xPreparedSql && p->zSql ){ - rc = pModule->xPreparedSql(pVCur, p->zSql); - if( rc ) goto abort_due_to_error; - } + if( pModule->iVersion>=700 ) { + if (pModule->xPreparedSql && p->zSql) { + rc = pModule->xPreparedSql(pVCur, p->zSql); + if (rc) goto abort_due_to_error; + } } break; @@ -99391,6 +101433,7 @@ case OP_VNext: { /* jump, ncycle */ rc = pModule->xNext(pCur->uc.pVCur); sqlite3VtabImportErrmsg(p, pVtab); if( rc ) goto abort_due_to_error; + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; res = pModule->xEof(pCur->uc.pVCur); VdbeBranchTaken(!res,2); if( !res ){ @@ -99598,7 +101641,7 @@ case OP_MaxPgcnt: { /* out2 */ ** 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 determinitic of non-deterministic, depending on their arguments. +** 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. @@ -99616,7 +101659,7 @@ case OP_Function: { /* group */ /* 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 */ + ** reinitializes the relevant parts of the sqlite3_context object */ pOut = &aMem[pOp->p3]; if( pCtx->pOut != pOut ){ pCtx->pVdbe = p; @@ -99692,7 +101735,7 @@ case OP_FilterAdd: { printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); } #endif - h %= pIn1->n; + h %= (pIn1->n*8); pIn1->z[h/8] |= 1<<(h&7); break; } @@ -99728,7 +101771,7 @@ case OP_Filter: { /* jump */ printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); } #endif - h %= pIn1->n; + h %= (pIn1->n*8); if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ VdbeBranchTaken(1, 2); p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++; @@ -99980,7 +102023,7 @@ default: { /* This is really OP_Noop, OP_Explain */ } if( opProperty==0xff ){ /* Never happens. This code exists to avoid a harmless linkage - ** warning aboud sqlite3VdbeRegisterDump() being defined but not + ** warning about sqlite3VdbeRegisterDump() being defined but not ** used. */ sqlite3VdbeRegisterDump(p); } @@ -100153,8 +102196,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ /* Set the value of register r[1] in the SQL statement to integer iRow. ** This is done directly as a performance optimization */ - v->aMem[1].flags = MEM_Int; - v->aMem[1].u.i = iRow; + sqlite3VdbeMemSetInt64(&v->aMem[1], 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 @@ -100237,7 +102279,7 @@ SQLITE_API int sqlite3_blob_open( #endif *ppBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ + if( !sqlite3SafetyCheckOk(db) || zTable==0 || zColumn==0 ){ return SQLITE_MISUSE_BKPT; } #endif @@ -100436,7 +102478,7 @@ SQLITE_API int sqlite3_blob_open( if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); sqlite3DbFree(db, zErr); sqlite3ParseObjectReset(&sParse); rc = sqlite3ApiExit(db, rc); @@ -100595,7 +102637,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ ((Vdbe*)p->pStmt)->rc = SQLITE_OK; rc = blobSeekToRow(p, iRow, &zErr); if( rc!=SQLITE_OK ){ - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); sqlite3DbFree(db, zErr); } assert( rc!=SQLITE_SCHEMA ); @@ -100698,7 +102740,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ ** 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" multipled by +** the value returned by "PRAGMA main.page_size" multiplied by ** that returned by "PRAGMA main.cache_size", in bytes. ** ** If the sorter is running in single-threaded mode, then all PMAs generated @@ -100721,7 +102763,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ ** ** 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 retreived from the sorter by the VDBE. The +** incrementally as keys are retrieved from the sorter by the VDBE. The ** MergeEngine object, described in further detail below, performs this ** merge. ** @@ -100799,7 +102841,7 @@ struct SorterFile { struct SorterList { SorterRecord *pList; /* Linked list of records */ u8 *aMemory; /* If non-NULL, bulk memory to hold pList */ - int szPMA; /* Size of pList as PMA in bytes */ + i64 szPMA; /* Size of pList as PMA in bytes */ }; /* @@ -100884,7 +102926,7 @@ struct MergeEngine { ** ** Essentially, this structure contains all those fields of the VdbeSorter ** structure for which each thread requires a separate instance. For example, -** each thread requries its own UnpackedRecord object to unpack records in +** each thread requeries 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, @@ -100908,10 +102950,10 @@ 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 */ @@ -100956,7 +102998,7 @@ struct VdbeSorter { ** 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 poitn to aAlloc. +** and the key is copied into aAlloc and aKey is made to point to aAlloc. ** ** pFd==0 at EOF. */ @@ -102327,7 +104369,7 @@ static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ ** 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 prefered as they use background threads - the final + ** sub-tasks are preferred as they use background threads - the final ** sub-task uses the main thread. */ for(i=0; iiPrev + i + 1) % nWorker; @@ -102385,8 +104427,8 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( int rc = SQLITE_OK; /* Return Code */ SorterRecord *pNew; /* New list element */ int bFlush; /* True to flush contents of memory to PMA */ - int nReq; /* Bytes of memory required */ - int nPMA; /* Bytes of PMA space required */ + i64 nReq; /* Bytes of memory required */ + i64 nPMA; /* Bytes of PMA space required */ int t; /* serial type of first record field */ assert( pCsr->eCurType==CURTYPE_SORTER ); @@ -102811,7 +104853,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - /* Set up the required files for pIncr. A multi-theaded IncrMerge object + /* Set up the required files for pIncr. A multi-threaded IncrMerge object ** requires two temp files to itself, whereas a single-threaded object ** only requires a region of pTask->file2. */ if( rc==SQLITE_OK ){ @@ -103451,6 +105493,8 @@ static int bytecodevtabConnect( "p5 INT," "comment TEXT," "subprog TEXT," + "nexec INT," + "ncycle INT," "stmt HIDDEN" ");", @@ -103613,7 +105657,7 @@ static int bytecodevtabColumn( } } } - i += 10; + i += 20; } } switch( i ){ @@ -103663,16 +105707,31 @@ static int bytecodevtabColumn( } break; } - case 10: /* tables_used.type */ + +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + case 9: /* nexec */ + sqlite3_result_int(ctx, pOp->nExec); + break; + case 10: /* ncycle */ + sqlite3_result_int(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 11: /* tables_used.schema */ + case 21: /* tables_used.schema */ sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC); break; - case 12: /* tables_used.name */ + case 22: /* tables_used.name */ sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC); break; - case 13: /* tables_used.wr */ + case 23: /* tables_used.wr */ sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite); break; } @@ -103746,7 +105805,7 @@ static int bytecodevtabBestIndex( int rc = SQLITE_CONSTRAINT; struct sqlite3_index_constraint *p; bytecodevtab *pVTab = (bytecodevtab*)tab; - int iBaseCol = pVTab->bTablesUsed ? 4 : 8; + int iBaseCol = pVTab->bTablesUsed ? 4 : 10; pIdxInfo->estimatedCost = (double)100; pIdxInfo->estimatedRows = 100; pIdxInfo->idxNum = 0; @@ -103793,7 +105852,8 @@ static sqlite3_module bytecodevtabModule = { /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, - /* xShadowName */ 0 + /* xShadowName */ 0, + /* xIntegrity */ 0 }; @@ -104317,7 +106377,7 @@ static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){ ** The return value from this routine is WRC_Abort to abandon the tree walk ** and WRC_Continue to continue. */ -static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ +SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3WalkExprNN(Walker *pWalker, Expr *pExpr){ int rc; testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); @@ -104326,7 +106386,9 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *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 && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; + if( pExpr->pLeft && sqlite3WalkExprNN(pWalker, pExpr->pLeft) ){ + return WRC_Abort; + } if( pExpr->pRight ){ assert( !ExprHasProperty(pExpr, EP_WinFunc) ); pExpr = pExpr->pRight; @@ -104350,7 +106412,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ - return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; + return pExpr ? sqlite3WalkExprNN(pWalker,pExpr) : WRC_Continue; } /* @@ -104476,7 +106538,7 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ } /* Increase the walkerDepth when entering a subquery, and -** descrease when leaving the subquery. +** decrease when leaving the subquery. */ SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){ UNUSED_PARAMETER(pSelect); @@ -104620,21 +106682,36 @@ static void resolveAlias( } /* -** 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. +** 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. */ SQLITE_PRIVATE int sqlite3MatchEName( const struct ExprList_item *pItem, const char *zCol, const char *zTab, - const char *zDb + const char *zDb, + int *pbRowid ){ int n; const char *zSpan; - if( pItem->fg.eEName!=ENAME_TAB ) return 0; + 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) ){ @@ -104646,9 +106723,11 @@ SQLITE_PRIVATE int sqlite3MatchEName( return 0; } zSpan += n+1; - if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ - return 0; + 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; } @@ -104781,7 +106860,7 @@ static int lookupName( ){ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ - int cntTab = 0; /* Number of matching table names */ + int cntTab = 0; /* Number of potential "rowid" matches */ int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ SrcItem *pItem; /* Use for looping over pSrcList items */ @@ -104858,39 +106937,49 @@ static int lookupName( assert( pEList!=0 ); assert( pEList->nExpr==pTab->nCol ); for(j=0; jnExpr; j++){ - if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){ + int bRowid = 0; /* True if possible rowid match */ + if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, &bRowid) ){ continue; } - 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( 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); + } } + cnt++; + 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; } - cnt++; - cntTab = 2; + cntTab++; pMatch = pItem; pExpr->iColumn = j; pEList->a[j].fg.bUsed = 1; - hit = 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; @@ -104983,7 +107072,8 @@ static int lookupName( assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); if( pParse->bReturning ){ if( (pNC->ncFlags & NC_UBaseReg)!=0 - && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) + && ALWAYS(zTab==0 + || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) ){ pExpr->iTable = op!=TK_DELETE; pTab = pParse->pTriggerTab; @@ -105084,10 +107174,10 @@ static int lookupName( && pMatch && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && sqlite3IsRowid(zCol) - && ALWAYS(VisibleRowid(pMatch->pTab)) + && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom) ){ cnt = 1; - pExpr->iColumn = -1; + if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; pExpr->affExpr = SQLITE_AFF_INTEGER; } @@ -105540,6 +107630,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ 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 ); zId = pExpr->u.zToken; pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ @@ -105681,6 +107772,10 @@ static int resolveExprStep(Walker *pWalker, Expr *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 @@ -105699,6 +107794,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #endif 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 ){ Select *pSel = pNC->pWinSelect; @@ -105768,8 +107868,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); - pNC->ncFlags |= NC_VarSelect; } + pNC->ncFlags |= NC_Subquery; } break; } @@ -106209,7 +108309,7 @@ static int resolveOrderGroupBy( } for(j=0; jpEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ - /* Since this expresion is being changed into a reference + /* 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); @@ -106262,10 +108362,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ while( p ){ assert( (p->selFlags & SF_Expanded)!=0 ); assert( (p->selFlags & SF_Resolved)==0 ); - assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */ p->selFlags |= SF_Resolved; - /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ @@ -106532,7 +108630,8 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( return SQLITE_ERROR; } #endif - sqlite3WalkExpr(&w, pExpr); + assert( pExpr!=0 ); + sqlite3WalkExprNN(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif @@ -106574,7 +108673,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames( return WRC_Abort; } #endif - sqlite3WalkExpr(&w, pExpr); + sqlite3WalkExprNN(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif @@ -106596,7 +108695,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames( /* ** Resolve all names in all expressions of a SELECT and in all -** decendents of the SELECT, including compounds off of p->pPrior, +** descendants of the SELECT, including compounds off of p->pPrior, ** subqueries in expressions, and subqueries used as FROM clause ** terms. ** @@ -106746,6 +108845,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){ 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 @@ -106957,11 +109057,10 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ }else{ Expr *pNext = p->pRight; /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( ExprUseXList(p) ); - assert( p->x.pList==0 || p->pRight==0 ); - if( p->x.pList!=0 && !db->mallocFailed ){ + assert( !ExprUseXList(p) || p->x.pList==0 || p->pRight==0 ); + if( ExprUseXList(p) && p->x.pList!=0 && !db->mallocFailed ){ int i; - for(i=0; ALWAYS(ix.pList->nExpr); i++){ + for(i=0; ix.pList->nExpr; i++){ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ pNext = p->x.pList->a[i].pExpr; break; @@ -106983,7 +109082,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ /* ** Return the collation sequence for the expression pExpr. If ** there is no defined collating sequence, return a pointer to the -** defautl collation sequence. +** default collation sequence. ** ** See also: sqlite3ExprCollSeq() ** @@ -107113,7 +109212,7 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( return pColl; } -/* Expresssion p is a comparison operator. Return a collation sequence +/* Expression p is a comparison operator. Return a collation sequence ** appropriate for the comparison operator. ** ** This is normally just a wrapper around sqlite3BinaryCompareCollSeq(). @@ -107270,6 +109369,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( */ pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); if( pRet ){ + ExprSetProperty(pRet, EP_FullSize); pRet->iTable = nField; pRet->iColumn = iField; pRet->pLeft = pVector; @@ -107569,6 +109669,15 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ #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. ** @@ -107793,9 +109902,9 @@ SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprLis ** 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, 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, 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. */ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ sqlite3 *db = pParse->db; @@ -107803,14 +109912,17 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ return pRight; }else if( pRight==0 ){ return pLeft; - }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) - && !IN_RENAME_OBJECT - ){ - sqlite3ExprDeferredDelete(pParse, pLeft); - sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3Expr(db, TK_INTEGER, "0"); }else{ - return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); + 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); + } } } @@ -107848,6 +109960,69 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction( 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, + (void(*)(sqlite3*,void*))sqlite3ExprListDelete, + 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: @@ -108026,7 +110201,7 @@ SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ /* ** Arrange to cause pExpr to be deleted when the pParse is deleted. ** This is similar to sqlite3ExprDelete() except that the delete is -** deferred untilthe pParse is deleted. +** deferred until the pParse is deleted. ** ** The pExpr might be deleted immediately on an OOM error. ** @@ -108101,11 +110276,7 @@ static int dupedExprStructSize(const Expr *p, int flags){ assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ assert( EXPR_FULLSIZE<=0xfff ); assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); - if( 0==flags || p->op==TK_SELECT_COLUMN -#ifndef SQLITE_OMIT_WINDOWFUNC - || ExprHasProperty(p, EP_WinFunc) -#endif - ){ + if( 0==flags || ExprHasProperty(p, EP_FullSize) ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); @@ -108136,56 +110307,93 @@ static int dupedExprNodeSize(const Expr *p, int flags){ /* ** 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. +** expression passed as the first argument. ** ** 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. ** -** 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). +** 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. */ -static int dupedExprSize(const 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); - } - } +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) ); return nByte; } /* -** 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. +** 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, const Expr *p, int dupFlags, u8 **pzBuffer){ +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 */ +){ Expr *pNew; /* Value to return */ - u8 *zAlloc; /* Memory space from which to build Expr object */ + EdupBuf sEdupBuf; /* 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( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE ); + assert( pEdupBuf==0 || dupFlags==EXPRDUP_REDUCE ); /* Figure out where to write the new Expr structure. */ - if( pzBuffer ){ - zAlloc = *pzBuffer; + if( pEdupBuf ){ + sEdupBuf.zAlloc = pEdupBuf->zAlloc; +#ifdef SQLITE_DEBUG + sEdupBuf.zEnd = pEdupBuf->zEnd; +#endif staticFlag = EP_Static; - assert( zAlloc!=0 ); + assert( sEdupBuf.zAlloc!=0 ); + assert( dupFlags==EXPRDUP_REDUCE ); }else{ - zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags)); + 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 + staticFlag = 0; } - pNew = (Expr *)zAlloc; + pNew = (Expr *)sEdupBuf.zAlloc; + assert( EIGHT_BYTE_ALIGNMENT(pNew) ); if( pNew ){ /* Set nNewSize to the size allocated for the structure pointed to @@ -108194,22 +110402,27 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ ** by the copy of the p->u.zToken string (if any). */ const unsigned nStructSize = dupedExprStructSize(p, dupFlags); - const int nNewSize = nStructSize & 0xfff; - int nToken; - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30(p->u.zToken) + 1; - }else{ - nToken = 0; + int nNewSize = nStructSize & 0xfff; + if( nToken<0 ){ + 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(zAlloc, p, nNewSize); + memcpy(sEdupBuf.zAlloc, p, nNewSize); }else{ u32 nSize = (u32)exprStructSize(p); - memcpy(zAlloc, p, nSize); + assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= + (int)EXPR_FULLSIZE+nToken ); + memcpy(sEdupBuf.zAlloc, p, nSize); if( nSizeu.zToken string, if any. */ - if( nToken ){ - char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + assert( nToken>=0 ); + if( nToken>0 ){ + char *zToken = pNew->u.zToken = (char*)&sEdupBuf.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) ){ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); + pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, + p->op!=TK_ORDER ? dupFlags : 0); } - } - /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ - 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; - } #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 */ - if( pzBuffer ){ - *pzBuffer = zAlloc; - } - }else{ - if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ - if( pNew->op==TK_SELECT_COLUMN ){ + + /* 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) ); + 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) ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); } @@ -108267,6 +110486,8 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ } } } + if( pEdupBuf ) memcpy(pEdupBuf, &sEdupBuf, sizeof(sEdupBuf)); + assert( sEdupBuf.zAlloc <= sEdupBuf.zEnd ); return pNew; } @@ -108531,11 +110752,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags) ** initially NULL, then create a new expression list. ** ** The pList argument must be either NULL or a pointer to an ExprList -** obtained from a prior call to sqlite3ExprListAppend(). This routine -** may not be used with an ExprList obtained from sqlite3ExprListDup(). -** Reason: This routine assumes that the number of slots in pList->a[] -** is a power of two. That is true for sqlite3ExprListAppend() returns -** but is not necessarily true from the return value of sqlite3ExprListDup(). +** 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 @@ -108868,7 +111085,7 @@ SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ ** and 0 if it is FALSE. */ SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ - pExpr = sqlite3ExprSkipCollate((Expr*)pExpr); + pExpr = sqlite3ExprSkipCollateAndLikely((Expr*)pExpr); assert( pExpr->op==TK_TRUEFALSE ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 @@ -109055,12 +111272,17 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ } /* -** Check pExpr to see if it is an invariant constraint on data source pSrc. +** 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 invariant constraint, the following must be true: +** To be an single-source constraint, the following must be true: ** ** (1) pExpr cannot refer to any table other than pSrc->iCursor. ** @@ -109071,13 +111293,31 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ ** ** (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. +** (4b) and specifically the ON clause associated with the LEFT JOIN. ** ** (5) If pSrc is not 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 sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){ +SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint( + Expr *pExpr, /* The constraint */ + const SrcList *pSrcList, /* Complete FROM clause */ + int iSrc /* Which element of pSrcList to use */ +){ + const SrcItem *pSrc = &pSrcList->a[iSrc]; if( pSrc->fg.jointype & JT_LTORJ ){ return 0; /* rule (3) */ } @@ -109087,6 +111327,19 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc }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; + } + } + } return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */ } @@ -109325,6 +111578,27 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){ 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 ** that can be simplified to a direct table access, then return @@ -109425,7 +111699,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** 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 epheremal table. +** populated ephemeral table. ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be ** implemented as a sequence of comparisons. ** @@ -109438,7 +111712,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** 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 -** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag +** 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. ** @@ -109450,12 +111724,12 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate ** through the set members) then the b-tree must not contain duplicates. -** An epheremal table will be created unless the selected columns are guaranteed +** An ephemeral table will be created unless the selected columns are guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or due to ** a UNIQUE constraint or index. ** ** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used -** for fast set membership tests) then an epheremal table must +** for fast set membership tests) then an ephemeral 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. ** @@ -109615,7 +111889,6 @@ SQLITE_PRIVATE int sqlite3FindInIndex( 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] ); @@ -109789,7 +112062,7 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ ** 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 ephermeral table is returned. The first time the ephemeral +** 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. @@ -110518,6 +112791,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( ){ int iAddr; Vdbe *v = pParse->pVdbe; + int nErr = pParse->nErr; assert( v!=0 ); assert( pParse->iSelfTab!=0 ); if( pParse->iSelfTab>0 ){ @@ -110530,6 +112804,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( 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 */ @@ -110546,6 +112821,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( Column *pCol; assert( v!=0 ); assert( pTab!=0 ); + assert( iCol!=XN_EXPR ); if( iCol<0 || iCol==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); VdbeComment((v, "%s.rowid", pTab->zName)); @@ -110601,10 +112877,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( 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); 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); } return iReg; } @@ -110633,7 +112912,7 @@ static void exprToRegister(Expr *pExpr, int iReg){ /* ** Evaluate an expression (either a vector or a scalar expression) and store -** the result in continguous temporary registers. Return the index of +** the result in contiguous 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 @@ -110673,7 +112952,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ */ static void setDoNotMergeFlagOnCopy(Vdbe *v){ if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){ - sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */ + sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergeable */ } } @@ -110763,13 +113042,13 @@ static int exprCodeInlineFunction( } case INLINEFUNC_implies_nonnull_row: { - /* REsult of sqlite3ExprImpliesNonNullRow() */ + /* 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), + sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable,1), target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); @@ -110857,6 +113136,41 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup( } +/* +** 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". @@ -110893,12 +113207,25 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) 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 && pExpr->iAggnColumn ); + 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]; if( !pAggInfo->directMode ){ return AggInfoColumnReg(pAggInfo, pExpr->iAgg); @@ -110933,7 +113260,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) 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 - ** expresssion. However, make sure the constant has the correct + ** expression. However, make sure the constant has the correct ** datatype by applying the Affinity of the table column to the ** constant. */ @@ -111002,6 +113329,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) iTab = pParse->iSelfTab - 1; } } + 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, @@ -111073,11 +113405,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - if( inReg!=target ){ - sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); - inReg = target; - } + sqlite3ExprCode(pParse, pExpr->pLeft, target); + assert( inReg==target ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeAddOp2(v, OP_Cast, target, sqlite3AffinityType(pExpr->u.zToken, 0)); @@ -111262,7 +113591,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); break; } - if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ + 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, @@ -111288,10 +113617,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) r1 = sqlite3GetTempRange(pParse, nFarg); } - /* For length() and typeof() functions with a column argument, + /* For length() and typeof() and octet_length() functions, ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG - ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data - ** loading. + ** or OPFLAG_TYPEOFARG or OPFLAG_BYTELENARG respectively, to avoid + ** unnecessary data loading. */ if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ u8 exprOp; @@ -111301,14 +113630,16 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); - testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); - pFarg->a[0].pExpr->op2 = - pDef->funcFlags & (OPFLAG_LENGTHARG|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; } } - sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, - SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); + sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, SQLITE_ECEL_FACTOR); }else{ r1 = 0; } @@ -111416,13 +113747,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) ** Clear subtypes as subtypes may not cross a subquery boundary. */ assert( pExpr->pLeft ); - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - if( inReg!=target ){ - sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); - inReg = target; - } - sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg); - return inReg; + 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. */ @@ -111532,12 +113859,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) ** "target" and not someplace else. */ pParse->okConstFactor = 0; /* note (1) above */ - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + sqlite3ExprCode(pParse, pExpr->pLeft, target); + assert( target==inReg ); pParse->okConstFactor = okConstFactor; - if( inReg!=target ){ /* note (2) above */ - sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); - inReg = target; - } sqlite3VdbeJumpHere(v, addrINR); break; } @@ -111670,9 +113994,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) ** 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 +** 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 +** 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 @@ -111685,6 +114009,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( ){ ExprList *p; assert( ConstFactorOk(pParse) ); + assert( regDest!=0 ); p = pParse->pConstExpr; if( regDest<0 && p ){ struct ExprList_item *pItem; @@ -111775,7 +114100,9 @@ SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); if( inReg!=target ){ u8 op; - if( ALWAYS(pExpr) && ExprHasProperty(pExpr,EP_Subquery) ){ + if( ALWAYS(pExpr) + && (ExprHasProperty(pExpr,EP_Subquery) || pExpr->op==TK_REGISTER) + ){ op = OP_Copy; }else{ op = OP_SCopy; @@ -112588,7 +114915,7 @@ static int exprImpliesNotNull( ** 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 +** pE1: x IS ?2 pE2: x IS NOT NULL Result: false ** ** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has ** Expr.iTable<0 then assume a table number given by iTab. @@ -112625,11 +114952,29 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr( 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. @@ -112638,28 +114983,33 @@ 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_OR: case TK_VECTOR: - case TK_CASE: - case TK_IN: 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_OR ); testcase( pExpr->op==TK_VECTOR ); - testcase( pExpr->op==TK_CASE ); - testcase( pExpr->op==TK_IN ); 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; @@ -112667,21 +115017,38 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ } return WRC_Prune; + case TK_OR: case TK_AND: - if( pWalker->eCode==0 ){ + /* 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); - if( pWalker->eCode ){ - pWalker->eCode = 0; - sqlite3WalkExpr(pWalker, pExpr->pRight); - } } return WRC_Prune; case TK_BETWEEN: - if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){ - assert( pWalker->eCode ); - return WRC_Abort; - } + /* 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 @@ -112743,7 +115110,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ** be non-NULL, then the LEFT JOIN can be safely converted into an ** ordinary join. */ -SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){ Walker w; p = sqlite3ExprSkipCollateAndLikely(p); if( p==0 ) return 0; @@ -112751,7 +115118,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ p = p->pLeft; }else{ while( p->op==TK_AND ){ - if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1; + if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1; p = p->pRight; } } @@ -112759,6 +115126,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ w.xSelectCallback = 0; w.xSelectCallback2 = 0; w.eCode = 0; + w.mWFlags = isRJ!=0; w.u.iCur = iTab; sqlite3WalkExpr(&w, p); return w.eCode; @@ -112819,7 +115187,7 @@ SQLITE_PRIVATE int sqlite3ExprCoveredByIndex( } -/* Structure used to pass information throught the Walker in order to +/* Structure used to pass information throughout the Walker in order to ** implement sqlite3ReferencesSrcList(). */ struct RefSrcList { @@ -112926,6 +115294,12 @@ SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList assert( pExpr->op==TK_AGG_FUNCTION ); assert( ExprUseXList(pExpr) ); 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); @@ -112960,9 +115334,11 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ int iAgg = pExpr->iAgg; Parse *pParse = pWalker->pParse; sqlite3 *db = pParse->db; + assert( iAgg>=0 ); if( pExpr->op!=TK_AGG_FUNCTION ){ - assert( iAgg>=0 && iAggnColumn ); - if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){ + if( iAggnColumn + && pAggInfo->aCol[iAgg].pCExpr==pExpr + ){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aCol[iAgg].pCExpr = pExpr; @@ -112971,8 +115347,9 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ } }else{ assert( pExpr->op==TK_AGG_FUNCTION ); - assert( iAgg>=0 && iAggnFunc ); - if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ + if( ALWAYS(iAggnFunc) + && pAggInfo->aFunc[iAgg].pFExpr==pExpr + ){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aFunc[iAgg].pFExpr = pExpr; @@ -113032,7 +115409,7 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ ** 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 idex of pAggInfo->nColumn-1. +** new column will have an index of pAggInfo->nColumn-1. */ static void findOrCreateAggInfoColumn( Parse *pParse, /* Parsing context */ @@ -113045,6 +115422,7 @@ static void findOrCreateAggInfoColumn( 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 @@ -113122,7 +115500,12 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ } if( pIEpr==0 ) break; if( NEVER(!ExprUseYTab(pExpr)) ) break; - if( pExpr->pAggInfo!=0 ) break; /* Already resolved by outer context */ + 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 @@ -113133,6 +115516,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ 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; @@ -113156,7 +115542,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } - return WRC_Prune; + return WRC_Continue; } case TK_AGG_FUNCTION: { if( (pNC->ncFlags & NC_InAggFunc)==0 @@ -113178,14 +115564,42 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ 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->pFunc = sqlite3FindFunction(pParse->db, - pExpr->u.zToken, - pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); - if( pExpr->flags & EP_Distinct ){ + 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; + } + }else{ + pItem->iOBTab = -1; + } + if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){ pItem->iDistinct = pParse->nTab++; }else{ pItem->iDistinct = -1; @@ -113309,6 +115723,37 @@ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ 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() @@ -113328,6 +115773,14 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int 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 */ @@ -113782,14 +116235,19 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ /* 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*'", + " WHERE quick_check GLOB 'CHECK*'" + " OR quick_check GLOB 'NULL*'" + " OR quick_check GLOB 'non-* value in*'", zTab, zDb ); } @@ -113878,7 +116336,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ 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; - pNew->nTabRef = 1; + assert( pNew->nTabRef==1 ); exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); @@ -114012,6 +116470,101 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn( return; } +/* +** Handles the following parser reduction: +** +** cmd ::= ALTER TABLE pSrc ALTER COLUMN pOld TO pNew +*/ +void libsqlAlterAlterColumn( + Parse *pParse, /* Parsing context */ + SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ + Token *pOld, /* Name of column being changed */ + Token *pNew /* New column declaration */ +){ + sqlite3 *db = pParse->db; /* Database connection */ + Table *pTab; /* Table being updated */ + int iCol; /* Index of column being updated */ + char *zOld = 0; /* Old column name */ + char *zNew = 0; /* New column declaration */ + 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_update_column; + + /* Cannot alter a system table */ + if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_update_column; + if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_update_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_update_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 updated */ + zOld = sqlite3NameFromToken(db, pOld); + if( !zOld ) goto exit_update_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_update_column; + } + + /* Ensure the schema contains no double-quoted strings */ + renameTestSchema(pParse, zDb, iSchema==1, "", 0); + renameFixQuotes(pParse, zDb, iSchema==1); + + /* Do the update operation using a recursive UPDATE statement that + ** uses the sqlite_update_column() SQL function to compute the new + ** CREATE statement text for the sqlite_schema table. + */ + sqlite3MayAbort(pParse); + if(pOld->n != pNew->n || sqlite3StrNICmp(pOld->z, pNew->z, pOld->n) != 0) { + sqlite3ErrorMsg(pParse, "UPDATE cannot also rename column: \"%T\" to \"%T\". Use ALTER TABLE RENAME instead", pOld, pNew); + goto exit_update_column; + } + // NOTICE: this is the main difference in ALTER COLUMN compared to RENAME COLUMN, + // we just take the whole new column declaration as it is. + // FIXME: the semicolon can also appear in the middle of the declaration when it's quoted, + // so we should check from the end. + pNew->n = sqlite3Strlen30(pNew->z); + while (pNew->n > 0 && pNew->z[pNew->n - 1] == ';') pNew->n--; + zNew = sqlite3DbStrNDup(db, pNew->z, pNew->n); + if( !zNew ) goto exit_update_column; + assert( pNew->n>0 ); + bQuote = -1; // Contrary to RENAME, we leave quotes as is and not dequote them + sqlite3NestedParse(pParse, + "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " + "sql = libsql_alter_column(sql, %Q, %Q, %d, %Q, %d, %d, %d) " + "WHERE tbl_name = %Q", + zDb, + zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, pTab->aCol[iCol].colFlags, + pTab->zName + ); + + /* Drop and reload the database schema. */ + renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename); + renameTestSchema(pParse, zDb, iSchema==1, "after update", 1); + + exit_update_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 @@ -114383,7 +116936,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ } /* -** An error occured while parsing or otherwise processing a database +** 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 @@ -114519,7 +117072,7 @@ static int renameEditSql( RenameCtx *pRename, /* Rename context */ const char *zSql, /* SQL statement to edit */ const char *zNew, /* New token text */ - int bQuote /* True to always quote token */ + int bQuote /* 1 to always quote token, -1 to never quote */ ){ i64 nNew = sqlite3Strlen30(zNew); i64 nSql = sqlite3Strlen30(zSql); @@ -114568,7 +117121,7 @@ static int renameEditSql( RenameToken *pBest = renameColumnTokenNext(pRename); if( zNew ){ - if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){ + if( bQuote==-1 || (bQuote==0 && sqlite3IsIdChar(*pBest->t.z)) ){ nReplace = nNew; zReplace = zNew; }else{ @@ -114615,6 +117168,19 @@ static int renameEditSql( 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 @@ -114662,7 +117228,17 @@ static int renameResolveTrigger(Parse *pParse){ 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 ); @@ -114959,6 +117535,180 @@ static void renameColumnFunc( sqlite3BtreeLeaveAll(db); } +/* +** SQL function: +** +** libsql_alter_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP) +** +** 0. zSql: SQL statement to rewrite +** 1. Database: Database name (e.g. "main") +** 2. Table: Table name +** 3. iCol: Index of column to rename +** 4. zNew: New column clause to add, e.g. "x REFERENCES other_table(y)" +** 5. bQuote: Non-zero if the new column name should be quoted. +** 6. bTemp: True if zSql comes from temp schema +** +** Do a ALTER TABLE ALTER COLUMN operation on the CREATE statement given in zSql. +** The iCol-th column (left-most is 0) of table zTable is translated from zCol +** into zNew definition, which the new constraints. +** The name should be quoted if bQuote is true. +** +** This function is used internally by the ALTER TABLE ALTER 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 alterColumnFunc( + 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[1]); + const char *zTable = (const char*)sqlite3_value_text(argv[2]); + int iCol = sqlite3_value_int(argv[3]); + const char *zNew = (const char*)sqlite3_value_text(argv[4]); + int bQuote = sqlite3_value_int(argv[5]); + int bTemp = sqlite3_value_int(argv[6]); + u16 iColFlags = sqlite3_value_int(argv[7]); + + const char *zOld; + int rc; + Parse sParse; + Parse sPostAlterParse; + 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); + + sCtx.pTab = pTab; + if( rc!=SQLITE_OK ) goto alterColumnFunc_done; + if( sParse.pNewTable ){ + if( IsOrdinaryTable(sParse.pNewTable) ){ + int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); + FKey *pFKey; + sCtx.pTab = sParse.pNewTable; + if( bFKOnly==0 ){ + if (iColnCol) { + Column *col = &sParse.pNewTable->aCol[iCol]; + RenameToken *pCol = renameTokenFind( + &sParse, &sCtx, (void*)col->zCnName + ); + // Expand the token until we find the end of the column definition + // FIXME: corner cases we don't cover are expected here, like quoted identifiers + // and other kinds of parentheses, and they would result in an incorrect SQL statement being generated. + // What we want here is to expand to the whole definition, including constraints, types, etc. + int open_parens = 0; + while (pCol->t.z[pCol->t.n] != 0 && pCol->t.z[pCol->t.n] != ',') { + if (pCol->t.z[pCol->t.n] == '(') open_parens++; + if (pCol->t.z[pCol->t.n] == ')') open_parens--; + if (open_parens < 0) { + break; + } + pCol->t.n++; + } + } + if( sCtx.iCol<0 ){ + renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); + } + } + } else { + rc = SQLITE_ERROR; + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "Only ordinary tables can be altered, not ", IsView(sParse.pNewTable) ? "views" : "virtual tables"); + goto alterColumnFunc_done; } + } else if (sParse.pNewIndex) { + rc = SQLITE_ERROR; + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "Only ordinary tables can be altered, not indexes"); + goto alterColumnFunc_done; + } else { + rc = SQLITE_ERROR; + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "Only ordinary tables can be altered"); + goto alterColumnFunc_done; + } + + assert( rc==SQLITE_OK ); + rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); + + // Validate flags - PRIMARY KEY, UNIQUE and GENERATED constrains are not allowed to be altered + // TODO: figure out more illegal combinations to validate + rc = renameParseSql(&sPostAlterParse, zDb, db, (const char *)sqlite3_value_text((sqlite3_value *)context->pOut), bTemp); + Table *pNewTab = sPostAlterParse.pNewTable; + int iNewCol; + for (iNewCol = 0; iNewCol < pNewTab->nCol; iNewCol++) { + if (sqlite3StrICmp(pNewTab->aCol[iNewCol].zCnName, zOld) == 0) break; + } + if (iNewCol == pNewTab->nCol) { + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "no such column: \"%T\"", zOld); + goto alterColumnFunc_done; + } + u16 primkey_differs = (iColFlags & COLFLAG_PRIMKEY) != (pNewTab->aCol[iNewCol].colFlags & COLFLAG_PRIMKEY); + u16 unique_differs = (iColFlags & COLFLAG_UNIQUE) != (pNewTab->aCol[iNewCol].colFlags & COLFLAG_UNIQUE); + u16 generated_differs = (iColFlags & COLFLAG_GENERATED) != (pNewTab->aCol[iNewCol].colFlags & COLFLAG_GENERATED); + renameParseCleanup(&sPostAlterParse); + + if (primkey_differs) { + rc = SQLITE_ERROR; + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "PRIMARY KEY constraint cannot be altered"); + goto alterColumnFunc_done; + } else if (unique_differs) { + rc = SQLITE_ERROR; + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "UNIQUE constraint cannot be altered"); + goto alterColumnFunc_done; + } else if (generated_differs) { + rc = SQLITE_ERROR; + sParse.zErrMsg = sqlite3MPrintf(sParse.db, "GENERATED constraint cannot be altered"); + goto alterColumnFunc_done; + } + +alterColumnFunc_done: + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[0]); + }else if( sParse.zErrMsg ){ + char *zErr = sqlite3MPrintf(sParse.db, "error in adding %s to %s: %s", + zNew, + zTable, + sParse.zErrMsg + ); + sqlite3_result_error(context, zErr, -1); + sqlite3DbFree(sParse.db, zErr); + }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". */ @@ -115608,6 +118358,8 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void){ INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest), INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc), INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc), + // libSQL extensions + INTERNAL_FUNCTION(libsql_alter_column, 8, alterColumnFunc), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } @@ -116611,11 +119363,15 @@ static void analyzeOneTable( int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */ int regPrev = iMem; /* MUST BE LAST (see below) */ +#ifdef SQLITE_ENABLE_STAT4 + int doOnce = 1; /* Flag for a one-time computation */ +#endif #ifdef SQLITE_ENABLE_PREUPDATE_HOOK Table *pStat1 = 0; #endif - pParse->nMem = MAX(pParse->nMem, iMem); + sqlite3TouchRegister(pParse, iMem); + assert( sqlite3NoTempsInRange(pParse, regNewRowid, iMem) ); v = sqlite3GetVdbe(pParse); if( v==0 || NEVER(pTab==0) ){ return; @@ -116721,7 +119477,7 @@ static void analyzeOneTable( ** the regPrev array and a trailing rowid (the rowid slot is required ** when building a record to insert into the sample column of ** the sqlite_stat4 table. */ - pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); + sqlite3TouchRegister(pParse, regPrev+nColTest); /* Open a read-only cursor on the index being analyzed. */ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); @@ -116893,7 +119649,35 @@ static void analyzeOneTable( int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - pParse->nMem = MAX(pParse->nMem, regCol+nCol); + 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) ); addrNext = sqlite3VdbeCurrentAddr(v); callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid); @@ -116974,6 +119758,11 @@ static void analyzeDatabase(Parse *pParse, int iDb){ 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); } @@ -117361,6 +120150,10 @@ static int loadStatTbl( 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; @@ -117368,6 +120161,7 @@ static int loadStatTbl( nIdxCol = pIdx->nColumn; } pIdx->nSampleCol = nIdxCol; + pIdx->mxSample = nSample; nByte = sizeof(IndexSample) * nSample; nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ @@ -117407,6 +120201,11 @@ static int loadStatTbl( 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. */ nCol = pIdx->nSampleCol; @@ -117419,14 +120218,15 @@ static int loadStatTbl( 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 two 0x00 bytes the end of the buffer. + /* Take a copy of the sample. Add 8 extra 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. Adding the two 0x00 bytes prevents this from causing + ** 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 buffer overread. */ pSample->n = sqlite3_column_bytes(pStmt, 4); - pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); + pSample->p = sqlite3DbMallocZero(db, pSample->n + 8); if( pSample->p==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; @@ -117450,11 +120250,12 @@ static int loadStat4(sqlite3 *db, const char *zDb){ const Table *pStat4; assert( db->lookaside.bDisable ); - if( (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0 + 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", + "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx COLLATE nocase", "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", zDb ); @@ -117616,6 +120417,10 @@ SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){ ); } +#ifdef LIBSQL_EXTRA_URI_PARAMS +int libsql_handle_extra_attach_params(sqlite3* db, const char* zName, const char* zPath, sqlite3_value* pKey, char** zErrDyn); +#endif + /* ** 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: @@ -117648,7 +120453,6 @@ static void attachFunc( Db *pNew = 0; /* Db object for the newly attached database */ char *zErrDyn = 0; sqlite3_vfs *pVfs; - libsql_wal_methods *pWal; UNUSED_PARAMETER(NotUsed); zFile = (const char *)sqlite3_value_text(argv[0]); @@ -117668,9 +120472,8 @@ static void attachFunc( ** reopen it as a MemDB */ Btree *pNewBt = 0; pVfs = sqlite3_vfs_find("memdb"); - pWal = libsql_wal_methods_find(NULL); if( pVfs==0 ) return; - rc = sqlite3BtreeOpen(pVfs, pWal, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); if( rc==SQLITE_OK ){ Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); if( pNewSchema ){ @@ -117730,7 +120533,7 @@ static void attachFunc( ** or may not be initialized. */ flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, db->pWalMethods->zName, zFile, &flags, &pVfs, &pWal, &zPath, &zErr); + 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); @@ -117739,7 +120542,7 @@ static void attachFunc( } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, pWal, zPath, db, &pNew->pBt, 0, flags); + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); db->nDb++; pNew->zDbSName = sqlite3DbStrDup(db, zName); } @@ -117772,6 +120575,11 @@ static void attachFunc( if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } +#ifdef LIBSQL_EXTRA_URI_PARAMS + if (rc == SQLITE_OK) { + rc = libsql_handle_extra_attach_params(db, zName, zPath, argv, &zErrDyn); + } +#endif sqlite3_free_filename( zPath ); /* If the file was opened successfully, read the schema for the new database. @@ -118386,7 +121194,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck( sqlite3 *db = pParse->db; int rc; - /* Don't do any authorization checks if the database is initialising + /* Don't do any authorization checks if the database is initializing ** or if the parser is being invoked from within sqlite3_declare_vtab. */ assert( !IN_RENAME_OBJECT || db->xAuth==0 ); @@ -118687,29 +121495,26 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ 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. */ - codeTableLocks(pParse); + if( pParse->nTableLock ) codeTableLocks(pParse); +#endif /* Initialize any AUTOINCREMENT data structures required. */ - sqlite3AutoincrementBegin(pParse); + if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse); - /* Code constant expressions that where factored out of inner loops. - ** - ** The pConstExpr list might also contain expressions that we simply - ** want to keep around until the Parse object is deleted. Such - ** expressions have iConstExprReg==0. Do not generate code for - ** those expressions, of course. + /* 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++){ - int iReg = pEL->a[i].u.iConstExprReg; - sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg); + assert( pEL->a[i].u.iConstExprReg>0 ); + sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); } } @@ -119208,7 +122013,7 @@ SQLITE_PRIVATE void sqlite3ColumnSetColl( } /* -** Return the collating squence name for a column +** Return the collating sequence name for a column */ SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){ const char *z; @@ -119301,7 +122106,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ if( IsOrdinaryTable(pTable) ){ sqlite3FkDelete(db, pTable); } -#ifndef SQLITE_OMIT_VIRTUAL_TABLE +#ifndef SQLITE_OMIT_VIRTUALTABLE else if( IsVirtual(pTable) ){ sqlite3VtabClear(db, pTable); } @@ -119863,20 +122668,13 @@ SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ } #endif -/* -** Name of the special TEMP trigger used to implement RETURNING. The -** name begins with "sqlite_" so that it is guaranteed not to collide -** with any application-generated triggers. -*/ -#define RETURNING_TRIGGER_NAME "sqlite_returning" - /* ** Clean up the data structures associated with the RETURNING clause. */ static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){ Hash *pHash; pHash = &(db->aDb[1].pSchema->trigHash); - sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0); + sqlite3HashInsert(pHash, pRet->zName, 0); sqlite3ExprListDelete(db, pRet->pReturnEL); sqlite3DbFree(db, pRet); } @@ -119904,7 +122702,7 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ if( pParse->pNewTrigger ){ sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger"); }else{ - assert( pParse->bReturning==0 ); + assert( pParse->bReturning==0 || pParse->ifNotExists ); } pParse->bReturning = 1; pRet = sqlite3DbMallocZero(db, sizeof(*pRet)); @@ -119919,7 +122717,9 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet); testcase( pParse->earlyCleanup ); if( db->mallocFailed ) return; - pRet->retTrig.zName = RETURNING_TRIGGER_NAME; + 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; @@ -119930,8 +122730,9 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); - assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr ); - if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) + assert( sqlite3HashFind(pHash, pRet->zName)==0 + || pParse->nErr || pParse->ifNotExists ); + if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) ==&pRet->retTrig ){ sqlite3OomFault(db); } @@ -119965,7 +122766,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){ } if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName); - /* Because keywords GENERATE ALWAYS can be converted into indentifiers + /* 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. */ @@ -120186,7 +122987,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The parsed expression of the default value */ const char *zStart, /* Start of the default value text */ - const char *zEnd /* First character past end of defaut value text */ + const char *zEnd /* First character past end of default value text */ ){ Table *p; Column *pCol; @@ -120534,7 +123335,7 @@ static int identLength(const char *z){ ** 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 alpha-numeric +** If the string zSignedIdent consists entirely of alphanumeric ** 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. @@ -120686,7 +123487,7 @@ static void estimateIndexWidth(Index *pIdx){ for(i=0; inColumn; i++){ i16 x = pIdx->aiColumn[i]; assert( xpTable->nCol ); - wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst; + wIndex += x<0 ? 1 : aCol[x].szEst; } pIdx->szIdxRow = sqlite3LogEst(wIndex*4); } @@ -121384,6 +124185,17 @@ SQLITE_PRIVATE void sqlite3EndTable( /* 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, 1, 0, 0, + sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", + db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); + } + sqlite3VdbeAddOp4(v, OP_SqlExec, 1, 0, 0, + sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)", + db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); } /* Add the table to the in-memory representation of the database. @@ -122433,7 +125245,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( #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 initialising a database schema. + ** if initializing a database schema. */ if( !db->init.busy ){ pTab = sqlite3SrcListLookup(pParse, pTblName); @@ -123672,7 +126484,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TEMP_DB; - rc = sqlite3BtreeOpen(db->pVfs, db->pWalMethods, 0, db, &pBt, 0, flags); + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "unable to open a temporary database " "file for storing temporary tables"); @@ -124090,7 +126902,7 @@ SQLITE_PRIVATE void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ /* ** This routine is invoked once per CTE by the parser while parsing a -** WITH clause. The CTE described by teh third argument is added to +** 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. */ @@ -124286,6 +127098,7 @@ void libsql_drop_function( } #endif + /************** End of build.c ***********************************************/ /************** Begin file callback.c ****************************************/ /* @@ -124475,6 +127288,7 @@ SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){ ** strings is BINARY. */ db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0); + sqlite3ExpirePreparedStatements(db, 1); } /* @@ -124865,8 +127679,9 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ Table *pTab; assert( pItem && pSrc->nSrc>=1 ); pTab = sqlite3LocateTableItem(pParse, 0, pItem); - sqlite3DeleteTable(pParse->db, pItem->pTab); + if( pItem->pTab ) sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; + pItem->fg.notCte = 1; if( pTab ){ pTab->nTabRef++; if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){ @@ -124946,13 +127761,15 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){ ** 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, int viewOk){ +SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, Trigger *pTrigger){ if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } #ifndef SQLITE_OMIT_VIEW - if( !viewOk && IsView(pTab) ){ + if( IsView(pTab) + && (pTrigger==0 || (pTrigger->bReturning && pTrigger->pNext==0)) + ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); return 1; } @@ -125017,7 +127834,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( sqlite3 *db = pParse->db; Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ - ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ + ExprList *pEList = NULL; /* Expression list containing only pSelectRowid*/ SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ Select *pSelect = NULL; /* Complete SELECT tree */ Table *pTab; @@ -125055,14 +127872,20 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( ); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk!=0 ); + assert( pPk->nKeyCol>=1 ); if( pPk->nKeyCol==1 ){ - const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName; + 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 = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); + 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); @@ -125091,7 +127914,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( pOrderBy,0,pLimit ); - /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ + /* now generate the new WHERE rowid IN clause for the DELETE/UPDATE */ pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0); sqlite3PExprAddSelect(pParse, pInClause, pSelect); return pInClause; @@ -125206,7 +128029,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( goto delete_from_cleanup; } - if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ + if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ goto delete_from_cleanup; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -125315,12 +128138,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; - if( sNC.ncFlags & NC_VarSelect ) bComplex = 1; + if( sNC.ncFlags & NC_Subquery ) bComplex = 1; wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; - nPk = 1; + assert( nPk==1 ); iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); }else{ @@ -125348,7 +128171,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( 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 ); + 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); @@ -125685,9 +128509,11 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); /* Invoke AFTER DELETE trigger programs. */ - sqlite3CodeRowTrigger(pParse, pTrigger, - TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel - ); + if( pTrigger ){ + 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 @@ -126004,6 +128830,42 @@ static void lengthFunc( } } +/* +** 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])); + } + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + /* ** Implementation of the abs() function. ** @@ -126280,7 +129142,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ }else if( n==0 ){ r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); }else{ - zBuf = sqlite3_mprintf("%.*f",n,r); + zBuf = sqlite3_mprintf("%!.*f",n,r); if( zBuf==0 ){ sqlite3_result_error_nomem(context); return; @@ -126480,7 +129342,7 @@ struct compareInfo { /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every -** character is exactly one byte in size. Also, provde the Utf8Read() +** character is exactly one byte in size. Also, provide the Utf8Read() ** macro for fast reading of the next character in the common case where ** the next character is ASCII. */ @@ -126713,7 +129575,7 @@ SQLITE_API int sqlite3_like_count = 0; /* ** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the +** the built-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 @@ -127046,6 +129908,7 @@ static void charFunc( *zOut++ = 0x80 + (u8)(c & 0x3F); } \ } + *zOut = 0; sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); } @@ -127074,7 +129937,8 @@ static void hexFunc( *(z++) = hexdigits[c&0xf]; } *z = 0; - sqlite3_result_text(context, zHex, n*2, sqlite3_free); + sqlite3_result_text64(context, zHex, (u64)(z-zHex), + sqlite3_free, SQLITE_UTF8); } } @@ -127099,7 +129963,7 @@ static int strContainsChar(const u8 *zStr, int nStr, u32 ch){ ** decoded and returned as a blob. ** ** If there is only a single argument, then it must consist only of an -** even number of hexadeximal digits. Otherwise, return NULL. +** even number of hexadecimal digits. Otherwise, return NULL. ** ** Or, if there is a second argument, then any character that appears in ** the second argument is also allowed to appear between pairs of hexadecimal @@ -127368,12 +130232,87 @@ static void trimFunc( 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_FUNCTION compile-time option is used. +** when the SQLITE_ENABLE_UNKNOWN_SQL_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 @@ -127489,13 +130428,68 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ */ typedef struct SumCtx SumCtx; struct SumCtx { - double rSum; /* Floating point sum */ - i64 iSum; /* Integer sum */ + 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 */ i64 cnt; /* Number of elements summed */ - u8 overflow; /* True if integer overflow seen */ - u8 approx; /* True if non-integer value was input to the sum */ + u8 approx; /* True if any non-integer value was input to the sum */ + u8 ovrfl; /* Integer overflow seen */ }; +/* +** 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. ** @@ -127515,15 +130509,29 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ p->cnt++; - 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->approx = p->overflow = 1; + 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{ - p->rSum += sqlite3_value_double(argv[0]); - p->approx = 1; + if( type==SQLITE_INTEGER ){ + kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); + }else{ + p->ovrfl = 0; + kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); + } } } } @@ -127540,13 +130548,18 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ if( ALWAYS(p) && type!=SQLITE_NULL ){ assert( p->cnt>0 ); p->cnt--; - assert( type==SQLITE_INTEGER || p->approx ); - if( type==SQLITE_INTEGER && p->approx==0 ){ - i64 v = sqlite3_value_int64(argv[0]); - p->rSum -= v; - p->iSum -= v; + 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{ - p->rSum -= sqlite3_value_double(argv[0]); + kahanBabuskaNeumaierStep(p, -sqlite3_value_double(argv[0])); } } } @@ -127557,10 +130570,14 @@ static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - if( p->overflow ){ - sqlite3_result_error(context,"integer overflow",-1); - }else if( p->approx ){ - sqlite3_result_double(context, p->rSum); + if( p->approx ){ + if( p->ovrfl ){ + sqlite3_result_error(context,"integer overflow",-1); + }else if( !sqlite3IsNaN(p->rErr) ){ + sqlite3_result_double(context, p->rSum+p->rErr); + }else{ + sqlite3_result_double(context, p->rSum); + } }else{ sqlite3_result_int64(context, p->iSum); } @@ -127570,14 +130587,29 @@ static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - sqlite3_result_double(context, p->rSum/(double)p->cnt); + double r; + if( p->approx ){ + r = p->rSum; + if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; + }else{ + r = (double)(p->iSum); + } + sqlite3_result_double(context, r/(double)p->cnt); } } static void totalFinalize(sqlite3_context *context){ SumCtx *p; + double r = 0.0; p = sqlite3_aggregate_context(context, 0); - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - sqlite3_result_double(context, p ? p->rSum : (double)0); + if( p ){ + if( p->approx ){ + r = p->rSum; + if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; + }else{ + r = (double)(p->iSum); + } + } + sqlite3_result_double(context, r); } /* @@ -127696,6 +130728,7 @@ static void minMaxFinalize(sqlite3_context *context){ /* ** group_concat(EXPR, ?SEPARATOR?) +** string_agg(EXPR, SEPARATOR) ** ** The SEPARATOR goes before the EXPR string. This is tragic. The ** groupConcatInverse() implementation would have been easier if the @@ -127799,7 +130832,7 @@ static void groupConcatInverse( 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 frist to initialize it */ + ** run first to initialize it */ if( ALWAYS(pGCC) ){ int nVS; /* Must call sqlite3_value_text() to convert the argument into text prior @@ -127883,8 +130916,10 @@ SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ ** 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; @@ -127892,10 +130927,13 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) pInfo = (struct compareInfo*)&likeInfoNorm; flags = SQLITE_FUNC_LIKE; } - sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); - sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); - sqlite3FindFunction(db, "like", 2, SQLITE_UTF8, 0)->funcFlags |= flags; - sqlite3FindFunction(db, "like", 3, SQLITE_UTF8, 0)->funcFlags |= flags; + 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; + } } /* @@ -128285,9 +131323,9 @@ int libsql_try_initialize_wasm_func_table(sqlite3 *db) { sqlite3_finalize(stmt); return rc; } - const char *pName = sqlite3_column_text(stmt, 0); + const unsigned char *pName = sqlite3_column_text(stmt, 0); const void *pBody = body_type == SQLITE_TEXT ? sqlite3_column_text(stmt, 1) : sqlite3_column_blob(stmt, 1); - try_instantiate_wasm_function(db, pName, name_size, pBody, body_size, -1, NULL); + try_instantiate_wasm_function(db, (const char *)pName, name_size, pBody, body_size, -1, NULL); } } sqlite3_finalize(stmt); @@ -128298,6 +131336,37 @@ int libsql_try_initialize_wasm_func_table(sqlite3 *db) { #endif // LIBSQL_ENABLE_WASM_RUNTIME +#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. +*/ +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]); + 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 */ + /* ** All of the FuncDef structures in the aBuiltinFunc[] array above ** to the global function hash table. This occurs at start-time (as @@ -128362,12 +131431,16 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), + FUNCTION2(octet_length, 1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), FUNCTION(format, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), +#ifdef SQLITE_DEBUG + FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ), +#endif #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), @@ -128377,6 +131450,11 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ FUNCTION(hex, 1, 0, 0, hexFunc ), FUNCTION(unhex, 1, 0, 0, unhexFunc ), FUNCTION(unhex, 2, 0, 0, unhexFunc ), + FUNCTION(concat, -1, 0, 0, concatFunc ), + FUNCTION(concat, 0, 0, 0, 0 ), + FUNCTION(concat_ws, -1, 0, 0, concatwsFunc ), + FUNCTION(concat_ws, 0, 0, 0, 0 ), + FUNCTION(concat_ws, 1, 0, 0, 0 ), INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), @@ -128406,6 +131484,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), + WAGGREGATE(string_agg, 2, 0, 0, groupConcatStep, + groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #ifdef SQLITE_CASE_SENSITIVE_LIKE @@ -129348,6 +132428,7 @@ static int isSetNullAction(Parse *pParse, FKey *pFKey){ 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; } } @@ -129542,6 +132623,8 @@ SQLITE_PRIVATE void sqlite3FkCheck( } 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 @@ -129657,7 +132740,11 @@ SQLITE_PRIVATE int sqlite3FkRequired( /* Check if any parent key columns are being modified. */ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ if( fkParentIsModified(pTab, p, aChange, chngRowid) ){ - if( p->aAction[1]!=OE_None ) return 2; + if( (pParse->db->flags & SQLITE_FkNoAction)==0 + && p->aAction[1]!=OE_None + ){ + return 2; + } bHaveFK = 1; } } @@ -129707,6 +132794,7 @@ static Trigger *fkActionTrigger( 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; } @@ -129807,22 +132895,22 @@ static Trigger *fkActionTrigger( if( action==OE_Restrict ){ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - Token tFrom; - Token tDb; + SrcList *pSrc; Expr *pRaise; - tFrom.z = zFrom; - tFrom.n = nFrom; - tDb.z = db->aDb[iDb].zDbSName; - tDb.n = sqlite3Strlen30(tDb.z); - 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); + pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); + } pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), - sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom), + pSrc, pWhere, 0, 0, 0, 0, 0 ); @@ -129938,9 +133026,8 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ if( pFKey->pPrevTo ){ pFKey->pPrevTo->pNextTo = pFKey->pNextTo; }else{ - void *p = (void *)pFKey->pNextTo; - const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); + const char *z = (pFKey->pNextTo ? pFKey->pNextTo->zTo : pFKey->zTo); + sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, pFKey->pNextTo); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; @@ -130003,8 +133090,10 @@ SQLITE_PRIVATE void sqlite3OpenTable( assert( pParse->pVdbe!=0 ); v = pParse->pVdbe; assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); - sqlite3TableLock(pParse, iDb, pTab->tnum, - (opcode==OP_OpenWrite)?1:0, pTab->zName); + if( !pParse->db->noSharedCache ){ + sqlite3TableLock(pParse, iDb, pTab->tnum, + (opcode==OP_OpenWrite)?1:0, pTab->zName); + } if( HasRowid(pTab) ){ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol); VdbeComment((v, "%s", pTab->zName)); @@ -130133,7 +133222,7 @@ SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){ ** For STRICT tables: ** ------------------ ** -** Generate an appropropriate OP_TypeCheck opcode that will verify the +** 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 @@ -130764,7 +133853,7 @@ SQLITE_PRIVATE void sqlite3Insert( /* Cannot insert into a read-only table. */ - if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ + if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ goto insert_cleanup; } @@ -131214,7 +134303,7 @@ SQLITE_PRIVATE void sqlite3Insert( } /* Copy the new data already generated. */ - assert( pTab->nNVCol>0 ); + assert( pTab->nNVCol>0 || pParse->nErr>0 ); sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1); #ifndef SQLITE_OMIT_GENERATED_COLUMNS @@ -131428,7 +134517,7 @@ SQLITE_PRIVATE void sqlite3Insert( /* 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 modifed by an UPDATE statement. +** columns that are being modified by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_COLUMN ){ @@ -131651,7 +134740,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int *aiChng, /* column i is unchanged if aiChng[i]<0 */ Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ ){ - Vdbe *v; /* VDBE under constrution */ + Vdbe *v; /* VDBE under construction */ Index *pIdx; /* Pointer to one of the indices */ Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */ sqlite3 *db; /* Database connection */ @@ -132134,7 +135223,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( pIdx; pIdx = indexIteratorNext(&sIdxIter, &ix) ){ - int regIdx; /* Range of registers hold conent for pIdx */ + int regIdx; /* Range of registers holding content 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 */ @@ -132629,6 +135718,8 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( 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 @@ -132641,18 +135732,18 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( assert( v!=0 ); if( iBase<0 ) iBase = pParse->nTab; iDataCur = iBase++; - if( piDataCur ) *piDataCur = iDataCur; + *piDataCur = iDataCur; if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); - }else{ + }else if( pParse->db->noSharedCache==0 ){ sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); } - if( piIdxCur ) *piIdxCur = iBase; + *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) ){ - if( piDataCur ) *piDataCur = iIdxCur; + *piDataCur = iIdxCur; p5 = 0; } if( aToOpen==0 || aToOpen[i+1] ){ @@ -132950,7 +136041,7 @@ static int xferOptimization( } #endif #ifndef SQLITE_OMIT_FOREIGN_KEY - /* Disallow the transfer optimization if the destination table constains + /* Disallow the transfer optimization if the destination table contains ** any foreign key constraints. This is more restrictive than necessary. ** But the main beneficiary of the transfer optimization is the VACUUM ** command, and the VACUUM command disables foreign key constraints. So @@ -133028,7 +136119,7 @@ static int xferOptimization( } autoIncStep(pParse, regNextRowid, regRowid); }else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){ - addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); + addr1 = sqlite3VdbeAddOp3(v, OP_NewRowid, iDest, regRowid, regNextRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); @@ -133663,14 +136754,16 @@ struct sqlite3_api_routines { int (*value_encoding)(sqlite3_value*); /* Version 3.41.0 and later */ int (*is_interrupted)(sqlite3*); - + /* Version 3.43.0 and later */ + int (*stmt_explain)(sqlite3_stmt*,int); + /* Version 3.44.0 and later */ + void *(*get_clientdata)(sqlite3*,const char*); + int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); }; struct libsql_api_routines { - /* libSQL 0.1.1 */ - struct libsql_wal_methods *(*wal_methods_find)(const char *); - int (*wal_methods_register)(struct libsql_wal_methods*); - int (*wal_methods_unregister)(struct libsql_wal_methods*); + /* libSQL 0.2.3 */ + void *(*close_hook)(sqlite3*, void(*)(void*,sqlite3*), void *pArg); }; /* @@ -134000,10 +137093,13 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_value_encoding sqlite3_api->value_encoding /* Version 3.41.0 and later */ #define sqlite3_is_interrupted sqlite3_api->is_interrupted -/* libSQL 0.1.1 */ -#define libsql_wal_methods_find libsql_api->wal_methods_find -#define libsql_wal_methods_register libsql_api->wal_methods_register -#define libsql_wal_methods_unregister libsql_api->wal_methods_unregister +/* Version 3.43.0 and later */ +#define sqlite3_stmt_explain sqlite3_api->stmt_explain +/* libSQL 0.2.3 */ +#define libsql_close_hook libsql_api->close_hook +/* 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) @@ -134531,14 +137627,16 @@ static const sqlite3_api_routines sqlite3Apis = { /* Version 3.40.0 and later */ sqlite3_value_encoding, /* Version 3.41.0 and later */ - sqlite3_is_interrupted + sqlite3_is_interrupted, + /* Version 3.43.0 and later */ + sqlite3_stmt_explain, + /* Version 3.44.0 and later */ + sqlite3_get_clientdata, + sqlite3_set_clientdata }; static const libsql_api_routines libsqlApis = { - /* libSQL 0.1.1 */ - libsql_wal_methods_find, - libsql_wal_methods_register, - libsql_wal_methods_unregister + libsql_close_hook, }; /* True if x is the directory separator character */ @@ -134610,15 +137708,25 @@ static int sqlite3LoadExtension( /* 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 */ + ** 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; iimutex); if( onoff ){ db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; @@ -134792,6 +137903,9 @@ 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 ){ @@ -134844,6 +137958,9 @@ SQLITE_API int sqlite3_cancel_auto_extension( int i; int n = 0; wsdAutoextInit; +#ifdef SQLITE_ENABLE_API_ARMOR + if( xInit==0 ) return 0; +#endif sqlite3_mutex_enter(mutex); for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ if( wsdAutoext.aExt[i]==xInit ){ @@ -135954,6 +139071,10 @@ static int integrityCheckResultRow(Vdbe *v){ return addr; } +#ifdef LIBSQL_EXTRA_PRAGMAS +int libsql_extra_pragma(sqlite3* db, const char* zDbName, void* pArg); +#endif + /* ** Process a pragma statement. ** @@ -136040,6 +139161,11 @@ SQLITE_PRIVATE void sqlite3Pragma( aFcntl[3] = 0; db->busyHandler.nBusy = 0; rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); +#ifdef LIBSQL_EXTRA_PRAGMAS + if(rc == SQLITE_NOTFOUND) { + rc = libsql_extra_pragma(db, zDb, (void*)aFcntl); + } +#endif if( rc==SQLITE_OK ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT); @@ -136445,7 +139571,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** ** The first form reports the current local setting for the ** page cache spill size. The second form turns cache spill on - ** or off. When turnning cache spill on, the size is set to the + ** or off. When turning 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 @@ -136715,7 +139841,11 @@ SQLITE_PRIVATE void sqlite3Pragma( #endif if( sqlite3GetBoolean(zRight, 0) ){ - db->flags |= mask; + if( (mask & SQLITE_WriteSchema)==0 + || (db->flags & SQLITE_Defensive)==0 + ){ + db->flags |= mask; + } }else{ db->flags &= ~mask; if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; @@ -137115,7 +140245,7 @@ SQLITE_PRIVATE void sqlite3Pragma( zDb = db->aDb[iDb].zDbSName; sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; + sqlite3TouchRegister(pParse, pTab->nCol+regRow); sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regResult, pTab->zName); assert( IsOrdinaryTable(pTab) ); @@ -137156,7 +140286,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** 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. */ - if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol; + 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); @@ -137223,9 +140353,9 @@ SQLITE_PRIVATE void sqlite3Pragma( ** 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 wherease integrity_check is O(NlogN). + ** is linear time whereas integrity_check is O(NlogN). ** - ** The maximum nubmer of errors is 100 by default. A different default + ** 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 @@ -137285,6 +140415,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( iDb>=0 && i!=iDb ) continue; sqlite3CodeVerifySchema(pParse, i); + pParse->okConstFactor = 0; /* tag-20230327-1 */ /* Do an integrity check of the B-Tree ** @@ -137320,7 +140451,7 @@ SQLITE_PRIVATE void sqlite3Pragma( aRoot[0] = cnt; /* Make sure sufficient number of registers have been allocated */ - pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); + sqlite3TouchRegister(pParse, 8+mxIdx); sqlite3ClearTempRegCache(pParse); /* Do the b-tree integrity checks */ @@ -137347,8 +140478,31 @@ SQLITE_PRIVATE void sqlite3Pragma( int r2; /* Previous key for WITHOUT ROWID tables */ int mxCol; /* Maximum non-virtual column number */ - if( !IsOrdinaryTable(pTab) ) continue; if( pObjTab && pObjTab!=pTab ) continue; + if( !IsOrdinaryTable(pTab) ){ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_vtab *pVTab; + int a1; + 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); + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v); + integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, a1); +#endif + continue; + } if( isQuick || HasRowid(pTab) ){ pPk = 0; r2 = 0; @@ -137470,15 +140624,29 @@ SQLITE_PRIVATE void sqlite3Pragma( 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); - sqlite3VdbeChangeP5(v, 0x0f); 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); + 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 */ } @@ -137968,7 +141136,7 @@ SQLITE_PRIVATE void sqlite3Pragma( Schema *pSchema; /* The current schema */ Table *pTab; /* A table in the schema */ Index *pIdx; /* An index of the table */ - LogEst szThreshold; /* Size threshold above which reanalysis is needd */ + LogEst szThreshold; /* Size threshold above which reanalysis needed */ char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ u32 opMask; /* Mask of operations to perform */ @@ -138460,7 +141628,8 @@ static const sqlite3_module pragmaVtabModule = { 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; /* @@ -138792,7 +141961,9 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl #else encoding = SQLITE_UTF8; #endif - if( db->nVdbeActive>0 && encoding!=ENC(db) ){ + if( db->nVdbeActive>0 && encoding!=ENC(db) + && (db->mDbFlags & DBFLAG_Vacuum)==0 + ){ rc = SQLITE_LOCKED; goto initone_error_out; }else{ @@ -139082,8 +142253,6 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; assert( pParse->db->pParse==pParse ); db->pParse = pParse->pOuterParse; - pParse->db = 0; - pParse->disableLookaside = 0; } /* @@ -139092,7 +142261,7 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ ** immediately. ** ** Use this mechanism for uncommon cleanups. There is a higher setup -** cost for this mechansim (an extra malloc), so it should not be used +** 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. @@ -139184,9 +142353,18 @@ static int sqlite3Prepare( sParse.pOuterParse = db->pParse; db->pParse = &sParse; sParse.db = db; - sParse.pReprepare = pReprepare; + if( pReprepare ){ + sParse.pReprepare = pReprepare; + sParse.explain = sqlite3_stmt_isexplain((sqlite3_stmt*)pReprepare); + }else{ + assert( sParse.pReprepare==0 ); + } assert( ppStmt && *ppStmt==0 ); - if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory"); + if( db->mallocFailed ){ + sqlite3ErrorMsg(&sParse, "out of memory"); + db->errCode = rc = SQLITE_NOMEM; + goto end_prepare; + } assert( sqlite3_mutex_held(db->mutex) ); /* For a long-term use prepared statement avoid the use of @@ -139790,7 +142968,7 @@ static Select *findRightmost(Select *p){ ** 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 non-sensical join types. +** 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: @@ -140012,6 +143190,7 @@ static void unsetJoinExpr(Expr *p, int iTable, int nullable){ } 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++){ @@ -140061,7 +143240,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON; - /* If this is a NATURAL join, synthesize an approprate USING clause + /* If this is a NATURAL join, synthesize an appropriate USING clause ** to specify which columns should be joined. */ if( pRight->fg.jointype & JT_NATURAL ){ @@ -140275,9 +143454,9 @@ static void pushOntoSorter( ** (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_REFERENCE optimization, or due to the + ** the SQLITE_ENABLE_SORTER_REFERENCES optimization, or due to the ** SQLITE_ECEL_OMITREF optimization, or due to the - ** SortCtx.pDeferredRowLoad optimiation. In any of these cases + ** 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. */ @@ -140333,7 +143512,7 @@ static void pushOntoSorter( 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 sqltie3VdbeAddOp3() */ + pOp = 0; /* Ensure pOp not used after sqlite3VdbeAddOp3() */ addrJmp = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse); @@ -140427,7 +143606,7 @@ static void codeOffset( ** 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 ephermal +** 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, @@ -140856,6 +144035,16 @@ static void selectInnerLoop( 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 @@ -141659,13 +144848,6 @@ SQLITE_PRIVATE void sqlite3GenerateColumnNames( 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 ) return; /* Column names are determined by the left-most term of a compound select */ while( pSelect->pPrior ) pSelect = pSelect->pPrior; @@ -141852,7 +145034,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( ** 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 infomation" means: +** subquery. For the purposes of this routine, "type information" means: ** ** * The datatype name, as it might appear in a CREATE TABLE statement ** * Which collating sequence to use for the column @@ -141876,7 +145058,7 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( 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 ) return; + if( db->mallocFailed || IN_RENAME_OBJECT ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; a = pSelect->pEList->a; memset(&sNC, 0, sizeof(sNC)); @@ -141921,18 +145103,16 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( break; } } - } - } - if( zType ){ - i64 m = sqlite3Strlen30(zType); - n = sqlite3Strlen30(pCol->zCnName); - pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); - if( pCol->zCnName ){ - memcpy(&pCol->zCnName[n+1], zType, m+1); - pCol->colFlags |= COLFLAG_HASTYPE; - }else{ - testcase( pCol->colFlags & COLFLAG_HASTYPE ); - pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); + } + } + if( zType ){ + i64 m = sqlite3Strlen30(zType); + n = sqlite3Strlen30(pCol->zCnName); + pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); + pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); + if( pCol->zCnName ){ + memcpy(&pCol->zCnName[n+1], zType, m+1); + pCol->colFlags |= COLFLAG_HASTYPE; } } pColl = sqlite3ExprCollSeq(pParse, p); @@ -142183,7 +145363,7 @@ static void generateWithRecursiveQuery( 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 targetting the Queue table */ + SelectDest destQueue; /* SelectDest targeting the Queue table */ int i; /* Loop counter */ int rc; /* Result code */ ExprList *pOrderBy; /* The ORDER BY clause */ @@ -142783,7 +145963,7 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ /* ** Code an output subroutine for a coroutine implementation of a -** SELECT statment. +** SELECT statement. ** ** The data to be output is contained in pIn->iSdst. There are ** pIn->nSdst columns to be output. pDest is where the output should @@ -143005,7 +146185,7 @@ static int generateOutputSubroutine( ** ** 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" labe. AltB, AeqB, +** until all data is exhausted then jump to the "end" label. AltB, AeqB, ** and AgtB jump to either L2 or to one of EofA or EofB. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT @@ -143042,7 +146222,7 @@ static int multiSelectOrderBy( 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 retargetted */ + int addr1; /* Jump instructions that get retargeted */ 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 */ @@ -143411,11 +146591,14 @@ static Expr *substExpr( #endif { Expr *pNew; - int iColumn = pExpr->iColumn; - Expr *pCopy = pSubst->pEList->a[iColumn].pExpr; + int iColumn; + Expr *pCopy; Expr ifNullRow; + iColumn = pExpr->iColumn; + assert( iColumn>=0 ); assert( pSubst->pEList!=0 && iColumnpEList->nExpr ); assert( pExpr->pRight==0 ); + pCopy = pSubst->pEList->a[iColumn].pExpr; if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ @@ -143764,7 +146947,7 @@ static int compoundHasDifferentAffinities(Select *p){ ** (9) If the subquery uses LIMIT then the outer query may not be aggregate. ** ** (**) Restriction (10) was removed from the code on 2005-02-05 but we -** accidently carried the comment forward until 2014-09-15. Original +** accidentally carried the comment forward until 2014-09-15. Original ** constraint: "If the subquery is aggregate then the outer query ** may not use LIMIT." ** @@ -143856,7 +147039,8 @@ static int compoundHasDifferentAffinities(Select *p){ ** (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. +** (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. @@ -143966,9 +147150,9 @@ static int flattenSubquery( if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* Restriction (27a) */ } - if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){ - return 0; /* (28) */ - } + + /* 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 ** use only the UNION ALL operator. And none of the simple select queries @@ -144038,7 +147222,7 @@ static int flattenSubquery( testcase( i==SQLITE_DENY ); pParse->zAuthContext = zSavedAuthContext; - /* Delete the transient structures associated with thesubquery */ + /* Delete the transient structures associated with the subquery */ pSub1 = pSubitem->pSelect; sqlite3DbFree(db, pSubitem->zDatabase); sqlite3DbFree(db, pSubitem->zName); @@ -144220,7 +147404,7 @@ static int flattenSubquery( ** 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 transfering the ORDER BY clause. + ** zero them before transferring 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 @@ -144280,8 +147464,7 @@ static int flattenSubquery( } } - /* Finially, delete what is left of the subquery and return - ** success. + /* Finally, delete what is left of the subquery and return success. */ sqlite3AggInfoPersistWalkerInit(&w, pParse); sqlite3WalkSelect(&w,pSub1); @@ -144316,7 +147499,7 @@ struct WhereConst { /* ** Add a new entry to the pConst object. Except, do not add duplicate -** pColumn entires. Also, do not add if doing so would not be appropriate. +** 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 @@ -144502,7 +147685,7 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){ ** SELECT * FROM t1 WHERE a=123 AND b=123; ** ** The two SELECT statements above should return different answers. b=a -** is alway true because the comparison uses numeric affinity, but b=123 +** 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 @@ -144586,7 +147769,7 @@ static int propagateConstants( ** 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 clase. +** * that the window frame has a PARTITION BY clause. */ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ assert( pSubq->pWin->pPartition ); @@ -144667,6 +147850,24 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){ ** 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 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 ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. @@ -144675,13 +147876,20 @@ 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 */ - SrcItem *pSrc /* The subquery term of the outer FROM clause */ + SrcList *pSrcList, /* The complete from clause of the outer query */ + int iSrc /* Which FROM clause term to try to push into */ ){ Expr *pNew; + SrcItem *pSrc; /* The subquery FROM term into which WHERE is pushed */ int nChng = 0; + pSrc = &pSrcList->a[iSrc]; if( pWhere==0 ) return 0; - if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0; - if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ) 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; @@ -144736,11 +147944,28 @@ static int pushDownWhereTerms( return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrcList, iSrc); pWhere = pWhere->pLeft; } -#if 0 /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */ +#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) @@ -144754,7 +147979,7 @@ static int pushDownWhereTerms( } #endif - if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){ + if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ @@ -144813,22 +148038,24 @@ static int disableUnusedSubqueryResultColumns(SrcItem *pItem){ assert( pItem->pSelect!=0 ); pSub = pItem->pSelect; assert( pSub->pEList->nExpr==pTab->nCol ); - if( (pSub->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){ - testcase( pSub->selFlags & SF_Distinct ); - testcase( pSub->selFlags & SF_Aggregate ); - return 0; - } 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 ){ @@ -145622,12 +148849,20 @@ static int selectExpander(Walker *pWalker, Select *p){ ** 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->pTab; /* Table for this data source */ ExprList *pNestedFrom; /* Result-set of a nested FROM clause */ char *zTabName; /* AS name for this data source */ @@ -145645,6 +148880,7 @@ static int selectExpander(Walker *pWalker, Select *p){ pNestedFrom = pFrom->pSelect->pEList; assert( pNestedFrom!=0 ); assert( pNestedFrom->nExpr==pTab->nCol ); + assert( VisibleRowid(pTab)==0 ); }else{ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; @@ -145662,6 +148898,7 @@ static int selectExpander(Walker *pWalker, Select *p){ 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]; @@ -145674,33 +148911,48 @@ static int selectExpander(Walker *pWalker, Select *p){ }else{ pUsing = 0; } - for(j=0; jnCol; j++){ - char *zName = pTab->aCol[j].zCnName; + + nAdd = pTab->nCol + (VisibleRowid(pTab) && (selFlags&SF_NestedFrom)); + for(j=0; ja[j], 0, zTName, 0)==0 - ){ - continue; - } + if( j==pTab->nCol ){ + zName = sqlite3RowidAlias(pTab); + if( zName==0 ) continue; + }else{ + zName = pTab->aCol[j].zCnName; - /* 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; + /* 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 ){ @@ -145734,6 +148986,7 @@ static int selectExpander(Walker *pWalker, Select *p){ }else{ pExpr = pRight; } + sqlite3ExprSetErrorOffset(pExpr, iErrOfst); pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); if( pNew==0 ){ break; /* OOM */ @@ -145749,11 +149002,11 @@ static int selectExpander(Walker *pWalker, Select *p){ zSchemaName, zTabName, zName); testcase( pX->zEName==0 ); } - pX->fg.eEName = ENAME_TAB; + 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) - || (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 + || (jnCol && (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)) ){ pX->fg.bNoExpand = 1; } @@ -145974,8 +149227,14 @@ static void analyzeAggFuncArgs( 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) ){ @@ -146004,12 +149263,13 @@ static void optimizeAggregateUseOfIndexedExpr( assert( pSelect->pGroupBy!=0 ); pAggInfo->nColumn = pAggInfo->nAccumulator; if( ALWAYS(pAggInfo->nSortingColumn>0) ){ - if( pAggInfo->nColumn==0 ){ - pAggInfo->nSortingColumn = pSelect->pGroupBy->nExpr; - }else{ - pAggInfo->nSortingColumn = - pAggInfo->aCol[pAggInfo->nColumn-1].iSorterColumn+1; + 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 @@ -146043,11 +149303,13 @@ static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue; if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue; pAggInfo = pExpr->pAggInfo; - assert( pExpr->iAgg>=0 && pExpr->iAggnColumn ); + 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; } @@ -146078,7 +149340,7 @@ static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){ ** * The aCol[] and aFunc[] arrays may be modified ** * The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used ** -** After clling this routine: +** After calling this routine: ** ** * The aCol[] and aFunc[] arrays are fixed ** * The AggInfoColumnReg() and AggInfoFuncReg() macros may be used @@ -146127,6 +149389,32 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ 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) ); + 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; + } + 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)); + } } } @@ -146142,13 +149430,46 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ ExprList *pList; assert( ExprUseXList(pF->pFExpr) ); pList = pF->pFExpr->x.pList; + if( pF->iOBTab>=0 ){ + /* For an ORDER BY aggregate, calls to OP_AggStep where deferred and + ** all content was stored in emphermal table pF->iOBTab. Extract that + ** content now (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 */ + + 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); + } + sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)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); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); } } - /* ** Generate code that will update the accumulator memory cells for an ** aggregate based on the current cursor position. @@ -146157,6 +149478,13 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ ** 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). */ static void updateAccumulator( Parse *pParse, @@ -146178,6 +149506,8 @@ static void updateAccumulator( int nArg; int addrNext = 0; int regAgg; + int regAggSz = 0; + int regDistinct = 0; ExprList *pList; assert( ExprUseXList(pF->pFExpr) ); assert( !IsWindowFunc(pF->pFExpr) ); @@ -146204,9 +149534,44 @@ static void updateAccumulator( addrNext = sqlite3VdbeMakeLabel(pParse); sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL); } - if( pList ){ + 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; + } + 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); + } + }else if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); + regDistinct = regAgg; sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); }else{ nArg = 0; @@ -146217,26 +149582,37 @@ static void updateAccumulator( addrNext = sqlite3VdbeMakeLabel(pParse); } pF->iDistinct = codeDistinct(pParse, eDistinctType, - pF->iDistinct, addrNext, pList, 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; + 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); } - 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, (u8)nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); } - sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i)); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nArg); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); } @@ -146428,6 +149804,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ 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; @@ -146447,7 +149824,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ 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 */ - pSub = pSub->pPrior; /* Repeat over compound */ + assert( pSub->pHaving==0 ); /* Due to the previous */ + pSub = pSub->pPrior; /* Repeat over compound */ }while( pSub ); /* If we reach this point then it is OK to perform the transformation */ @@ -146730,22 +150108,59 @@ SQLITE_PRIVATE int sqlite3Select( ** to a real table */ assert( pTab!=0 ); - /* Convert LEFT JOIN into JOIN if there are terms of the right table - ** of the LEFT JOIN used in the WHERE clause. + /* 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. */ - if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT - && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) + if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 + && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor, + pItem->fg.jointype & JT_LTORJ) && OptimizationEnabled(db, SQLITE_SimplifyJoin) ){ - TREETRACE(0x1000,pParse,p, - ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); - pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + 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); + } + } + 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); + } + } + } + for(j=pTabList->nSrc-1; j>=i; j--){ + pTabList->a[j].fg.jointype &= ~JT_LTORJ; + if( pTabList->a[j].fg.jointype & JT_RIGHT ) break; + } + } assert( pItem->iCursor>=0 ); unsetJoinExpr(p->pWhere, pItem->iCursor, pTabList->a[0].fg.jointype & JT_LTORJ); } - /* No futher action if this term of the FROM clause is no a subquery */ + /* No further action if this term of the FROM clause is not a subquery */ if( pSub==0 ) continue; /* Catch mismatch in the declared columns of a view and the number of @@ -146756,6 +150171,14 @@ SQLITE_PRIVATE int sqlite3Select( 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 @@ -146785,6 +150208,8 @@ SQLITE_PRIVATE int sqlite3Select( ** (a) The outer query has a different ORDER BY clause ** (b) The subquery is part of a join ** See forum post 062d576715d277c8 + ** + ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled. */ if( pSub->pOrderBy!=0 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ @@ -146942,7 +150367,7 @@ SQLITE_PRIVATE int sqlite3Select( 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, pItem) + && pushDownWhereTerms(pParse, pSub, p->pWhere, pTabList, i) ){ #if TREETRACE_ENABLED if( sqlite3TreeTrace & 0x4000 ){ @@ -146999,7 +150424,7 @@ SQLITE_PRIVATE int sqlite3Select( }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, - ** the make the pItem->iCursor be a copy of the ephemerial table that + ** the make the pItem->iCursor be a copy of the ephemeral table that ** holds the result of the materialization. */ CteUse *pCteUse = pItem->u2.pCteUse; sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e); @@ -147382,7 +150807,7 @@ SQLITE_PRIVATE int sqlite3Select( */ if( pGroupBy ){ KeyInfo *pKeyInfo; /* Keying information for the group by clause */ - int addr1; /* A-vs-B comparision jump */ + int addr1; /* A-vs-B comparison 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 */ @@ -147473,9 +150898,13 @@ SQLITE_PRIVATE int sqlite3Select( int nCol; int nGroupBy; - explainTempTable(pParse, +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + int addrExp; /* Address of OP_Explain instruction */ +#endif + ExplainQueryPlan2(addrExp, (pParse, 0, "USE TEMP B-TREE FOR %s", (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? - "DISTINCT" : "GROUP BY"); + "DISTINCT" : "GROUP BY" + )); groupBySort = 1; nGroupBy = pGroupBy->nExpr; @@ -147500,18 +150929,23 @@ SQLITE_PRIVATE int sqlite3Select( } 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); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); TREETRACE(0x2,pParse,p,("WhereEnd\n")); sqlite3WhereEnd(pWInfo); pAggInfo->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); 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 @@ -148239,6 +151673,10 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( 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; + } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ @@ -148258,6 +151696,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( }else{ assert( !db->init.busy ); sqlite3CodeVerifySchema(pParse, iDb); + VVA_ONLY( pParse->ifNotExists = 1; ) } goto trigger_cleanup; } @@ -149021,10 +152460,17 @@ static void codeReturningTrigger( SrcList sFrom; assert( v!=0 ); - assert( pParse->bReturning ); + 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; - assert( pTrigger == &(pReturning->retTrig) ); + 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); @@ -149508,6 +152954,9 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask( 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) @@ -149758,7 +153207,7 @@ static void updateFromSelect( assert( pTabList->nSrc>1 ); if( pSrc ){ - pSrc->a[0].fg.notCte = 1; + assert( pSrc->a[0].fg.notCte ); pSrc->a[0].iCursor = -1; pSrc->a[0].pTab->nTabRef--; pSrc->a[0].pTab = 0; @@ -149942,7 +153391,7 @@ SQLITE_PRIVATE void sqlite3Update( if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto update_cleanup; } - if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ + if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ goto update_cleanup; } @@ -150261,12 +153710,22 @@ SQLITE_PRIVATE void sqlite3Update( /* 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. */ + ** 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 ){ + 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); @@ -150337,6 +153796,8 @@ SQLITE_PRIVATE void sqlite3Update( if( !isView ){ int addrOnce = 0; + int iNotUsed1 = 0; + int iNotUsed2 = 0; /* Open every index that needs updating. */ if( eOnePass!=ONEPASS_OFF ){ @@ -150348,7 +153809,7 @@ SQLITE_PRIVATE void sqlite3Update( addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, - aToOpen, 0, 0); + aToOpen, &iNotUsed1, &iNotUsed2); if( addrOnce ){ sqlite3VdbeJumpHereOrPopInst(v, addrOnce); } @@ -150639,8 +154100,10 @@ SQLITE_PRIVATE void sqlite3Update( sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); + if( pTrigger ){ + 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. @@ -150735,7 +154198,7 @@ static void updateVirtualTable( 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 ephem table rowid */ + int regRowid; /* Register for ephemeral 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 */ @@ -150779,7 +154242,9 @@ static void updateVirtualTable( sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) ); }else{ - pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); + Expr *pRowExpr = exprRowColumn(pParse, i); + if( pRowExpr ) pRowExpr->op2 = OPFLAG_NOCHNG; + pList = sqlite3ExprListAppend(pParse, pList, pRowExpr); } } @@ -150856,7 +154321,7 @@ static void updateVirtualTable( sqlite3WhereEnd(pWInfo); } - /* Begin scannning through the ephemeral table. */ + /* Begin scanning through the ephemeral table. */ addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); /* Extract arguments from the current row of the ephemeral table and @@ -151064,7 +154529,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( pExpr = &sCol[0]; } for(jj=0; jja[jj].pExpr,pExpr,iCursor)<2 ){ + if( sqlite3ExprCompare(0,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){ break; /* Column ii of the index matches column jj of target */ } } @@ -151413,7 +154878,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( ** (possibly synchronous) transaction opened on the main database before ** sqlite3BtreeCopyFile() is called. ** - ** An optimisation would be to use a non-journaled pager. + ** An optimization 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 @@ -151658,11 +155123,11 @@ struct VtabCtx { ** 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 */ + 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; @@ -151706,11 +155171,11 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule( ** sqlite3_create_module_v2() interfaces. */ static int createModule( - 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 */ + 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 */ ){ int rc = SQLITE_OK; @@ -151744,7 +155209,7 @@ SQLITE_API int sqlite3_create_module( SQLITE_API int sqlite3_create_module_v2( 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 */ + const sqlite3_module *pModule, /* The definition of the libSQL module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ @@ -152102,7 +155567,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ ** the information we've collected. ** ** The VM register number pParse->regRowid holds the rowid of an - ** entry in the sqlite_schema table tht was created for this vtab + ** entry in the sqlite_schema table that was created for this vtab ** by sqlite3StartTable(). */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); @@ -152231,7 +155696,9 @@ static int vtabCallConstructor( sCtx.pPrior = db->pVtabCtx; sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; + pTab->nTabRef++; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); + sqlite3DeleteTable(db, pTab); db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); assert( sCtx.pTab==pTab ); @@ -152440,7 +155907,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ sqlite3_mutex_enter(db->mutex); pCtx = db->pVtabCtx; if( !pCtx || pCtx->bDeclared ){ - sqlite3Error(db, SQLITE_MISUSE); + sqlite3Error(db, SQLITE_MISUSE_BKPT); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } @@ -152721,7 +156188,10 @@ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ 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); } @@ -152841,7 +156311,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ ** ** 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 existance. Eponymous virtual table +** statement in order to come into existence. Eponymous virtual table ** instances always exist. They cannot be DROP-ed. ** ** Any virtual table module for which xConnect and xCreate are the same @@ -152950,6 +156420,10 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ p->pVTable->eVtabRisk = SQLITE_VTABRISK_High; break; } + case SQLITE_VTAB_USES_ALL_SCHEMAS: { + p->pVTable->bAllSchemas = 1; + break; + } default: { rc = SQLITE_MISUSE_BKPT; break; @@ -153028,7 +156502,7 @@ typedef struct WhereRightJoin WhereRightJoin; /* ** This object is a header on a block of allocated memory that will be -** automatically freed when its WInfo oject is destructed. +** automatically freed when its WInfo object is destructed. */ struct WhereMemBlock { WhereMemBlock *pNext; /* Next block in the chain */ @@ -153089,7 +156563,7 @@ struct WhereLevel { 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 entires in the key */ + 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 */ @@ -153339,7 +156813,7 @@ struct WhereClause { 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 cluase */ + WhereTerm *a; /* Each a[] describes a term of the WHERE clause */ #if defined(SQLITE_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ #else @@ -153624,7 +157098,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #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_VIEWSCAN 0x02000000 /* A full-scan of a VIEW or subquery */ + /* 0x02000000 -- available for reuse */ #define WHERE_EXPRIDX 0x04000000 /* Uses an index-on-expressions */ #endif /* !defined(SQLITE_WHEREINT_H) */ @@ -153927,6 +157401,12 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( if( wsFlags & WHERE_INDEXED ){ sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur); } + }else{ + int addr = pSrclist->a[pLvl->iFrom].addrFillSub; + VdbeOp *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); } } } @@ -154424,7 +157904,7 @@ static int codeAllEqualityTerms( /* Figure out how many memory cells we will need then allocate them. */ regBase = pParse->nMem + 1; - nReg = pLoop->u.btree.nEq + nExtraReg; + nReg = nEq + nExtraReg; pParse->nMem += nReg; zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); @@ -154471,9 +157951,6 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); } } - } - for(j=nSkip; jaLTerm[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 @@ -154616,18 +158093,19 @@ static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ ** 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 idenified +** Also, if the node is a TK_COLUMN that does access the table identified ** 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 ){ - int reg = ++pWalker->pParse->nMem; /* Register for column value */ - sqlite3ExprCode(pWalker->pParse, pExpr, reg); + reg = ++pWalker->pParse->nMem; /* Register for column value */ + reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg); pExpr->op = TK_REGISTER; pExpr->iTable = reg; }else if( pHint->pIdx!=0 ){ @@ -154635,15 +158113,15 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn); assert( pExpr->iColumn>=0 ); } - }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. */ + }else if( pExpr->pAggInfo ){ 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; } @@ -154745,7 +158223,7 @@ static void codeCursorHint( } if( pExpr!=0 ){ sWalker.xExprCallback = codeCursorHintFixExpr; - sqlite3WalkExpr(&sWalker, pExpr); + if( pParse->nErr==0 ) sqlite3WalkExpr(&sWalker, pExpr); sqlite3VdbeAddOp4(v, OP_CursorHint, (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0, (const char*)pExpr, P4_EXPR); @@ -155235,7 +158713,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( }; 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 correcct. */ + assert( TK_GE==TK_GT+3 ); /* ... is correct. */ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); @@ -155541,7 +159019,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** guess. */ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10); - if( pRangeStart ){ + if( pRangeStart || pRangeEnd ){ sqlite3VdbeChangeP5(v, 1); sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1); addrSeekScan = 0; @@ -155582,16 +159060,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( assert( pLevel->p2==0 ); if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; - if( addrSeekScan ){ - /* For a seek-scan that has a range on the lowest term of the index, - ** we have to make the top of the loop be code that sets the end - ** condition of the range. Otherwise, the OP_SeekScan might jump - ** over that initialization, leaving the range-end value set to the - ** range-start value, resulting in a wrong answer. - ** See ticket 5981a8c041a3c2f3 (2021-11-02). - */ - pLevel->p2 = sqlite3VdbeCurrentAddr(v); - } + assert( addrSeekScan==0 ); codeExprOrVector(pParse, pRight, regBase+nEq, nTop); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 @@ -155625,7 +159094,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff); /* Top of the loop body */ - if( pLevel->p2==0 ) pLevel->p2 = sqlite3VdbeCurrentAddr(v); + pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ @@ -156424,7 +159893,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( ** the WHERE clause of SQL statements. ** ** This file was originally part of where.c but was split out to improve -** readability and editabiliity. This file contains utility routines for +** readability and editability. This file contains utility routines for ** analyzing Expr objects in the WHERE clause. */ /* #include "sqliteInt.h" */ @@ -156640,7 +160109,7 @@ static int isLikeOrGlob( ** 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!=0 && 255!=(u8)z[cnt-1] && (cnt>1 || z[0]!=wc[3]) ){ + if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){ Expr *pPrefix; /* A "complete" match if the pattern ends with "*" or "%" */ @@ -157213,7 +160682,7 @@ static void exprAnalyzeOrTerm( 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 follwed by an inverted copy (t2.b==t1.a). Skip this term + ** or followed 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 ); @@ -157475,8 +160944,8 @@ static void exprAnalyze( WhereTerm *pTerm; /* The term to be analyzed */ WhereMaskSet *pMaskSet; /* Set of table index masks */ Expr *pExpr; /* The expression to be analyzed */ - Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ - Bitmask prereqAll; /* Prerequesites of pExpr */ + Bitmask prereqLeft; /* Prerequisites of the pExpr->pLeft */ + Bitmask prereqAll; /* Prerequisites 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 */ @@ -157622,7 +161091,7 @@ static void exprAnalyze( && 0==sqlite3ExprCanBeNull(pLeft) ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pExpr->op = TK_TRUEFALSE; + pExpr->op = TK_TRUEFALSE; /* See tag-20230504-1 */ pExpr->u.zToken = "false"; ExprSetProperty(pExpr, EP_IsFalse); pTerm->prereqAll = 0; @@ -159154,8 +162623,7 @@ static void explainAutomaticIndex( */ static SQLITE_NOINLINE void constructAutomaticIndex( Parse *pParse, /* The parsing context */ - const WhereClause *pWC, /* The WHERE clause */ - const SrcItem *pSrc, /* The FROM clause term to get the next index */ + WhereClause *pWC, /* The WHERE clause */ const Bitmask notReady, /* Mask of cursors that are not available */ WhereLevel *pLevel /* Write new index here */ ){ @@ -159180,7 +162648,8 @@ static SQLITE_NOINLINE void constructAutomaticIndex( u8 useBloomFilter = 0; /* True to also add a Bloom filter */ Expr *pPartial = 0; /* Partial Index Expression */ int iContinue = 0; /* Jump here to skip excluded rows */ - SrcItem *pTabItem; /* FROM clause term being indexed */ + SrcList *pTabList; /* The complete FROM clause */ + SrcItem *pSrc; /* The FROM clause term to get the next index */ int addrCounter = 0; /* Address where integer counter is initialized */ int regBase; /* Array of registers where record is assembled */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS @@ -159196,6 +162665,8 @@ static SQLITE_NOINLINE void constructAutomaticIndex( /* 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->pTab; pWCEnd = &pWC->a[pWC->nTerm]; pLoop = pLevel->pWLoop; @@ -159206,7 +162677,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex( ** 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 - && sqlite3ExprIsTableConstraint(pExpr, pSrc) + && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom) ){ pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); @@ -159247,7 +162718,11 @@ static SQLITE_NOINLINE void constructAutomaticIndex( ** original table changes and the index and table cannot both be used ** if they go out of sync. */ - extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); + if( IsView(pTable) ){ + extraCols = ALLBITS; + }else{ + extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); + } mxBitCol = MIN(BMS-1,pTable->nCol); testcase( pTable->nCol==BMS-1 ); testcase( pTable->nCol==BMS-2 ); @@ -159332,14 +162807,14 @@ static SQLITE_NOINLINE void constructAutomaticIndex( } /* Fill the automatic index with content */ - pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; - if( pTabItem->fg.viaCoroutine ){ - int regYield = pTabItem->regReturn; + assert( pSrc == &pWC->pWInfo->pTabList->a[pLevel->iFrom] ); + if( pSrc->fg.viaCoroutine ){ + int regYield = pSrc->regReturn; addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSrc->addrFillSub); addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); VdbeCoverage(v); - VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); + VdbeComment((v, "next row of %s", pSrc->pTab->zName)); }else{ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); } @@ -159360,14 +162835,14 @@ static SQLITE_NOINLINE void constructAutomaticIndex( sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); - if( pTabItem->fg.viaCoroutine ){ + if( pSrc->fg.viaCoroutine ){ sqlite3VdbeChangeP2(v, addrCounter, regBase+n); testcase( pParse->db->mallocFailed ); assert( pLevel->iIdxCur>0 ); translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, - pTabItem->regResult, pLevel->iIdxCur); + pSrc->regResult, pLevel->iIdxCur); sqlite3VdbeGoto(v, addrTop); - pTabItem->fg.viaCoroutine = 0; + pSrc->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); @@ -159419,16 +162894,26 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( 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; @@ -159442,7 +162927,9 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( ** testing complicated. By basing the blob size on the value in the ** sqlite_stat1 table, testing is much easier. */ - pItem = &pWInfo->pTabList->a[pLevel->iFrom]; + pTabList = pWInfo->pTabList; + iSrc = pLevel->iFrom; + pItem = &pTabList->a[iSrc]; assert( pItem!=0 ); pTab = pItem->pTab; assert( pTab!=0 ); @@ -159459,7 +162946,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( for(pTerm=pWInfo->sWC.a; pTermpExpr; if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsTableConstraint(pExpr, pItem) + && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc) ){ sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); } @@ -159475,9 +162962,8 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( int r1 = sqlite3GetTempRange(pParse, n); int jj; for(jj=0; jjaiColumn[jj]; assert( pIdx->pTable==pItem->pTab ); - sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); + sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj); } sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); sqlite3ReleaseTempRange(pParse, r1, n); @@ -159508,6 +162994,8 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( } }while( iLevel < pWInfo->nLevel ); sqlite3VdbeJumpHere(v, addrOnce); + pParse->pIdxEpr = saved_pIdxEpr; + pParse->pIdxPartExpr = saved_pIdxPartExpr; } @@ -159763,6 +163251,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); } } + if( pTab->u.vtab.p->bAllSchemas ){ + sqlite3VtabUsesAllSchemas(pParse); + } sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; return rc; @@ -159807,6 +163298,7 @@ static int whereKeyStats( assert( pIdx->nSample>0 ); assert( pRec->nField>0 ); + /* 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 @@ -159851,7 +163343,12 @@ static int whereKeyStats( ** it is extended to two fields. The duplicates that this creates do not ** cause any problems. */ - nField = MIN(pRec->nField, pIdx->nSample); + if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ + nField = pIdx->nKeyCol; + }else{ + nField = pIdx->nColumn; + } + nField = MIN(pRec->nField, nField); iCol = 0; iSample = pIdx->nSample * nField; do{ @@ -160014,7 +163511,7 @@ SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCo ** 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 peformed multiple +** 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 ** by the caller. ** @@ -160287,7 +163784,7 @@ static int whereRangeScanEst( UNUSED_PARAMETER(pBuilder); assert( pLower || pUpper ); #endif - assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); + assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 || pParse->nErr>0 ); nNew = whereRangeAdjust(pLower, nOut); nNew = whereRangeAdjust(pUpper, nNew); @@ -160769,7 +164266,7 @@ static WhereLoop **whereLoopFindLesser( ** rSetup. Call this SETUP-INVARIANT */ assert( p->rSetup>=pTemplate->rSetup ); - /* Any loop using an appliation-defined index (or PRIMARY KEY or + /* Any loop using an application-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 @@ -160796,7 +164293,7 @@ static WhereLoop **whereLoopFindLesser( /* 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 dependences than p, and + ** (1) pTemplate has no more dependencies than p, and ** (2) pTemplate has an equal or lower cost than p. */ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ @@ -160914,7 +164411,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ }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 supplated by pTemplate */ + ** p[] that are also supplanted by pTemplate */ WhereLoop **ppTail = &p->pNextLoop; WhereLoop *pToDel; while( *ppTail ){ @@ -161114,7 +164611,7 @@ static int whereRangeVectorLen( } /* -** Adjust the cost C by the costMult facter T. This only occurs if +** Adjust the cost C by the costMult factor T. This only occurs if ** compiled with -DSQLITE_ENABLE_COSTMULT */ #ifdef SQLITE_ENABLE_COSTMULT @@ -161141,7 +164638,7 @@ static int whereLoopAddBtreeIndex( Index *pProbe, /* An index on pSrc */ LogEst nInMul /* log(Number of iterations due to IN) */ ){ - WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ + WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyze context */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ @@ -161451,7 +164948,7 @@ static int whereLoopAddBtreeIndex( assert( pSrc->pTab->szTabRow>0 ); if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ /* The pProbe->szIdxRow is low for an IPK table since the interior - ** pages are small. Thuse szIdxRow gives a good estimate of seek cost. + ** 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; @@ -161758,6 +165255,100 @@ static SQLITE_NOINLINE u32 whereIsCoveringIndex( 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(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 @@ -161796,7 +165387,7 @@ static SQLITE_NOINLINE u32 whereIsCoveringIndex( */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq /* Extra prerequesites for using this table */ + Bitmask mPrereq /* Extra prerequisites for using this table */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ @@ -161961,9 +165552,6 @@ static int whereLoopAddBtree( #else pNew->rRun = rSize + 16; #endif - if( IsView(pTab) || (pTab->tabFlags & TF_Ephemeral)!=0 ){ - pNew->wsFlags |= WHERE_VIEWSCAN; - } ApplyCostMultiplier(pNew->rRun, pTab->costMult); whereLoopOutputAdjust(pWC, pNew, rSize); rc = whereLoopInsert(pBuilder, pNew); @@ -161976,6 +165564,11 @@ static int whereLoopAddBtree( 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); @@ -162303,7 +165896,7 @@ static int whereLoopAddVirtualOne( ** ** Return a pointer to the collation name: ** -** 1. If there is an explicit COLLATE operator on the constaint, return it. +** 1. If there is an explicit COLLATE operator on the constraint, return it. ** ** 2. Else, if the column has an alternative collation, return that. ** @@ -162358,7 +165951,7 @@ SQLITE_API int sqlite3_vtab_rhs_value( sqlite3_value *pVal = 0; int rc = SQLITE_OK; if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ - rc = SQLITE_MISUSE; /* EV: R-30545-25046 */ + rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */ }else{ if( pH->aRhs[iCons]==0 ){ WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset]; @@ -162388,8 +165981,6 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ return pHidden->eDistinct; } -#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ - && !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** Cause the prepared statement that is associated with a call to ** xBestIndex to potentially use all schemas. If the statement being @@ -162399,9 +165990,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ ** ** This is used by the (built-in) sqlite_dbpage virtual table. */ -SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - Parse *pParse = pHidden->pParse; +SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse *pParse){ int nDb = pParse->db->nDb; int i; for(i=0; ipTabList->nSrc ); - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); + WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n", + nRowEst, pParse->nQueryLoop)); /* 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 @@ -163372,7 +166961,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ); } /* TUNING: Add a small extra penalty (3) to sorting as an - ** extra encouragment to the query planner to select a plan + ** extra encouragement to the query planner to select a plan ** where the rows emerge in the correct order without any sorting ** required. */ rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 3; @@ -163386,13 +166975,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */ } - /* TUNING: A full-scan of a VIEW or subquery in the outer loop - ** is not so bad. */ - if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 ){ - rCost += -10; - nOut += -30; - } - /* Check to see if pWLoop should be added to the set of ** mxChoice best-so-far paths. ** @@ -163579,6 +167161,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } + if( pWInfo->pSelect->pOrderBy + && pWInfo->nOBSat > pWInfo->pSelect->pOrderBy->nExpr ){ + pWInfo->nOBSat = pWInfo->pSelect->pOrderBy->nExpr; + } }else{ pWInfo->revMask = pFrom->revLoop; if( pWInfo->nOBSat<=0 ){ @@ -163790,6 +167376,13 @@ static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){ ** 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. ** ** For example, given: ** @@ -163815,6 +167408,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( ){ int i; Bitmask tabUsed; + int hasRightJoin; /* Preconditions checked by the caller */ assert( pWInfo->nLevel>=2 ); @@ -163829,6 +167423,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( 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; @@ -163851,6 +167446,12 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( break; } } + if( hasRightJoin + && ExprHasProperty(pTerm->pExpr, EP_InnerON) + && pTerm->pExpr->w.iJoin==pItem->iCursor + ){ + break; /* restriction (5) */ + } } if( pTerm drop loop %c not used\n", pLoop->cId)); @@ -163923,20 +167524,6 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( } } -/* -** 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){ - Parse *pParse = (Parse*)pObject; - while( pParse->pIdxEpr!=0 ){ - IndexedExpr *p = pParse->pIdxEpr; - pParse->pIdxEpr = p->pIENext; - sqlite3ExprDelete(db, p->pExpr); - sqlite3DbFreeNN(db, p); - } -} - /* ** 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 @@ -163998,7 +167585,30 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( #endif pParse->pIdxEpr = p; if( p->pIENext==0 ){ - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse); + 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->pSelect==0) + || pItem->pSelect->pOrderBy==0 + ){ + pWInfo->revMask |= MASKBIT(ii); } } } @@ -164061,7 +167671,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( ** ** OUTER JOINS ** -** An outer join of tables t1 and t2 is conceptally coded as follows: +** An outer join of tables t1 and t2 is conceptually coded as follows: ** ** foreach row1 in t1 do ** flag = 0 @@ -164216,7 +167826,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** ** The N-th term of the FROM clause is assigned a bitmask of 1<nErr ) 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. + /* 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. ** - ** 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: + ** Conditions: ** - ** FROM ... WHERE random()>0; -- eval random() once per row - ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall + ** (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]; + WhereTerm *pT = &sWLB.pWC->a[ii]; /* A term of the WHERE clause */ + Expr *pX; /* The expression of pT */ if( pT->wtFlags & TERM_VIRTUAL ) continue; - if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ - sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); + 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); pT->wtFlags |= TERM_CODED; } } @@ -164343,9 +167976,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( 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 ){ - pWInfo->revMask = ALLBITS; + whereReverseScanOrder(pWInfo); } if( pParse->nErr ){ goto whereBeginError; @@ -164445,6 +168089,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) && !IsVirtual(pTabList->a[0].pTab) && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) + && OptimizationEnabled(db, SQLITE_OnePass) )){ pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ @@ -164508,7 +168153,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( assert( n<=pTab->nCol ); } #ifdef SQLITE_ENABLE_CURSOR_HINTS - if( pLoop->u.btree.pIndex!=0 ){ + if( pLoop->u.btree.pIndex!=0 && (pTab->tabFlags & TF_WithoutRowid)==0 ){ sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); }else #endif @@ -164553,6 +168198,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( 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 ); @@ -164645,11 +168295,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( 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, - &pTabList->a[pLevel->iFrom], notReady, pLevel); + constructAutomaticIndex(pParse, &pWInfo->sWC, notReady, pLevel); #endif }else{ sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady); @@ -164966,7 +168616,8 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ k = pLevel->addrBody + 1; #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE opcodes in range %d..%d\n", k, last-1); + 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); @@ -165173,7 +168824,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ ** ** 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 funtions) allows them to +** 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. @@ -165703,7 +169354,7 @@ static Window *windowFind(Parse *pParse, Window *pList, const char *zName){ ** is the Window object representing the associated OVER clause. This ** function updates the contents of pWin as follows: ** -** * If the OVER clause refered to a named window (as in "max(x) OVER win"), +** * 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. @@ -165841,6 +169492,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ } /* no break */ deliberate_fall_through + case TK_IF_NULL_ROW: case TK_AGG_FUNCTION: case TK_COLUMN: { int iCol = -1; @@ -166323,7 +169975,7 @@ SQLITE_PRIVATE Window *sqlite3WindowAssemble( } /* -** Window *pWin has just been created from a WINDOW clause. Tokne pBase +** 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 @@ -166367,8 +170019,9 @@ 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); + ExprSetProperty(p, EP_WinFunc|EP_FullSize); pWin->pOwner = p; if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){ sqlite3ErrorMsg(pParse, @@ -166629,7 +170282,7 @@ struct WindowCsrAndReg { ** ** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING) ** -** The windows functions implmentation caches the input rows in a temp +** 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 @@ -167638,7 +171291,7 @@ static int windowExprGtZero(Parse *pParse, Expr *pExpr){ ** ** 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 equivilent to "0 PRECEDING/FOLLOWING". +** 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: @@ -167917,7 +171570,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( } /* Allocate registers for the array of values from the sub-query, the - ** samve values in record form, and the rowid used to insert said record + ** same values in record form, and the rowid used to insert said record ** into the ephemeral table. */ regNew = pParse->nMem+1; pParse->nMem += nInput; @@ -168158,7 +171811,8 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( /************** End of window.c **********************************************/ /************** Begin file parse.c *******************************************/ /* This file is automatically generated by Lemon from input grammar -** source file "parse.y". */ +** source file "parse.y". +*/ /* ** 2001-09-15 ** @@ -168175,7 +171829,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( ** 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 grammer. You might be reading +** 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. */ @@ -168395,183 +172049,184 @@ static void updateDeleteLimitError( #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_RANDOM 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_CONFLICT 38 -#define TK_DATABASE 39 -#define TK_DESC 40 -#define TK_DETACH 41 -#define TK_EACH 42 -#define TK_FAIL 43 -#define TK_FUNCTION 44 -#define TK_LANGUAGE 45 -#define TK_OR 46 -#define TK_AND 47 -#define TK_IS 48 -#define TK_MATCH 49 -#define TK_LIKE_KW 50 -#define TK_BETWEEN 51 -#define TK_IN 52 -#define TK_ISNULL 53 -#define TK_NOTNULL 54 -#define TK_NE 55 -#define TK_EQ 56 -#define TK_GT 57 -#define TK_LE 58 -#define TK_LT 59 -#define TK_GE 60 -#define TK_ESCAPE 61 -#define TK_ID 62 -#define TK_COLUMNKW 63 -#define TK_DO 64 -#define TK_FOR 65 -#define TK_IGNORE 66 -#define TK_INITIALLY 67 -#define TK_INSTEAD 68 -#define TK_NO 69 -#define TK_KEY 70 -#define TK_OF 71 -#define TK_OFFSET 72 -#define TK_PRAGMA 73 -#define TK_RAISE 74 -#define TK_RECURSIVE 75 -#define TK_REPLACE 76 -#define TK_RESTRICT 77 -#define TK_ROW 78 -#define TK_ROWS 79 -#define TK_TRIGGER 80 -#define TK_VACUUM 81 -#define TK_VIEW 82 -#define TK_VIRTUAL 83 -#define TK_WITH 84 -#define TK_NULLS 85 -#define TK_FIRST 86 -#define TK_LAST 87 -#define TK_CURRENT 88 -#define TK_FOLLOWING 89 -#define TK_PARTITION 90 -#define TK_PRECEDING 91 -#define TK_RANGE 92 -#define TK_UNBOUNDED 93 -#define TK_EXCLUDE 94 -#define TK_GROUPS 95 -#define TK_OTHERS 96 -#define TK_TIES 97 -#define TK_GENERATED 98 -#define TK_ALWAYS 99 -#define TK_MATERIALIZED 100 -#define TK_REINDEX 101 -#define TK_RENAME 102 -#define TK_CTIME_KW 103 -#define TK_ANY 104 -#define TK_BITAND 105 -#define TK_BITOR 106 -#define TK_LSHIFT 107 -#define TK_RSHIFT 108 -#define TK_PLUS 109 -#define TK_MINUS 110 -#define TK_STAR 111 -#define TK_SLASH 112 -#define TK_REM 113 -#define TK_CONCAT 114 -#define TK_PTR 115 -#define TK_COLLATE 116 -#define TK_BITNOT 117 -#define TK_ON 118 -#define TK_INDEXED 119 -#define TK_STRING 120 -#define TK_JOIN_KW 121 -#define TK_CONSTRAINT 122 -#define TK_DEFAULT 123 -#define TK_NULL 124 -#define TK_PRIMARY 125 -#define TK_UNIQUE 126 -#define TK_CHECK 127 -#define TK_REFERENCES 128 -#define TK_AUTOINCR 129 -#define TK_INSERT 130 -#define TK_DELETE 131 -#define TK_UPDATE 132 -#define TK_SET 133 -#define TK_DEFERRABLE 134 -#define TK_FOREIGN 135 -#define TK_DROP 136 -#define TK_BLOB 137 -#define TK_UNION 138 -#define TK_ALL 139 -#define TK_EXCEPT 140 -#define TK_INTERSECT 141 -#define TK_SELECT 142 -#define TK_VALUES 143 -#define TK_DISTINCT 144 -#define TK_DOT 145 -#define TK_FROM 146 -#define TK_JOIN 147 -#define TK_USING 148 -#define TK_ORDER 149 -#define TK_GROUP 150 -#define TK_HAVING 151 -#define TK_LIMIT 152 -#define TK_WHERE 153 -#define TK_RETURNING 154 -#define TK_INTO 155 -#define TK_NOTHING 156 -#define TK_FLOAT 157 -#define TK_INTEGER 158 -#define TK_VARIABLE 159 -#define TK_CASE 160 -#define TK_WHEN 161 -#define TK_THEN 162 -#define TK_ELSE 163 -#define TK_INDEX 164 -#define TK_ALTER 165 -#define TK_ADD 166 -#define TK_WINDOW 167 -#define TK_OVER 168 -#define TK_FILTER 169 -#define TK_COLUMN 170 -#define TK_AGG_FUNCTION 171 -#define TK_AGG_COLUMN 172 -#define TK_TRUEFALSE 173 -#define TK_ISNOT 174 -#define TK_UMINUS 175 -#define TK_UPLUS 176 -#define TK_TRUTH 177 -#define TK_REGISTER 178 -#define TK_VECTOR 179 -#define TK_SELECT_COLUMN 180 -#define TK_IF_NULL_ROW 181 -#define TK_ASTERISK 182 -#define TK_SPAN 183 -#define TK_ERROR 184 -#define TK_SPACE 185 -#define TK_ILLEGAL 186 +#define TK_READONLY 10 +#define TK_COMMIT 11 +#define TK_END 12 +#define TK_ROLLBACK 13 +#define TK_SAVEPOINT 14 +#define TK_RELEASE 15 +#define TK_TO 16 +#define TK_TABLE 17 +#define TK_CREATE 18 +#define TK_IF 19 +#define TK_NOT 20 +#define TK_EXISTS 21 +#define TK_TEMP 22 +#define TK_LP 23 +#define TK_RP 24 +#define TK_AS 25 +#define TK_COMMA 26 +#define TK_WITHOUT 27 +#define TK_RANDOM 28 +#define TK_ABORT 29 +#define TK_ACTION 30 +#define TK_AFTER 31 +#define TK_ANALYZE 32 +#define TK_ASC 33 +#define TK_ATTACH 34 +#define TK_BEFORE 35 +#define TK_BY 36 +#define TK_CASCADE 37 +#define TK_CAST 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_FUNCTION 45 +#define TK_LANGUAGE 46 +#define TK_OR 47 +#define TK_AND 48 +#define TK_IS 49 +#define TK_MATCH 50 +#define TK_LIKE_KW 51 +#define TK_BETWEEN 52 +#define TK_IN 53 +#define TK_ISNULL 54 +#define TK_NOTNULL 55 +#define TK_NE 56 +#define TK_EQ 57 +#define TK_GT 58 +#define TK_LE 59 +#define TK_LT 60 +#define TK_GE 61 +#define TK_ESCAPE 62 +#define TK_ID 63 +#define TK_COLUMNKW 64 +#define TK_DO 65 +#define TK_FOR 66 +#define TK_IGNORE 67 +#define TK_INITIALLY 68 +#define TK_INSTEAD 69 +#define TK_NO 70 +#define TK_KEY 71 +#define TK_OF 72 +#define TK_OFFSET 73 +#define TK_PRAGMA 74 +#define TK_RAISE 75 +#define TK_RECURSIVE 76 +#define TK_REPLACE 77 +#define TK_RESTRICT 78 +#define TK_ROW 79 +#define TK_ROWS 80 +#define TK_TRIGGER 81 +#define TK_VACUUM 82 +#define TK_VIEW 83 +#define TK_VIRTUAL 84 +#define TK_WITH 85 +#define TK_NULLS 86 +#define TK_FIRST 87 +#define TK_LAST 88 +#define TK_CURRENT 89 +#define TK_FOLLOWING 90 +#define TK_PARTITION 91 +#define TK_PRECEDING 92 +#define TK_RANGE 93 +#define TK_UNBOUNDED 94 +#define TK_EXCLUDE 95 +#define TK_GROUPS 96 +#define TK_OTHERS 97 +#define TK_TIES 98 +#define TK_GENERATED 99 +#define TK_ALWAYS 100 +#define TK_MATERIALIZED 101 +#define TK_REINDEX 102 +#define TK_RENAME 103 +#define TK_CTIME_KW 104 +#define TK_ANY 105 +#define TK_BITAND 106 +#define TK_BITOR 107 +#define TK_LSHIFT 108 +#define TK_RSHIFT 109 +#define TK_PLUS 110 +#define TK_MINUS 111 +#define TK_STAR 112 +#define TK_SLASH 113 +#define TK_REM 114 +#define TK_CONCAT 115 +#define TK_PTR 116 +#define TK_COLLATE 117 +#define TK_BITNOT 118 +#define TK_ON 119 +#define TK_INDEXED 120 +#define TK_STRING 121 +#define TK_JOIN_KW 122 +#define TK_CONSTRAINT 123 +#define TK_DEFAULT 124 +#define TK_NULL 125 +#define TK_PRIMARY 126 +#define TK_UNIQUE 127 +#define TK_CHECK 128 +#define TK_REFERENCES 129 +#define TK_AUTOINCR 130 +#define TK_INSERT 131 +#define TK_DELETE 132 +#define TK_UPDATE 133 +#define TK_SET 134 +#define TK_DEFERRABLE 135 +#define TK_FOREIGN 136 +#define TK_DROP 137 +#define TK_BLOB 138 +#define TK_UNION 139 +#define TK_ALL 140 +#define TK_EXCEPT 141 +#define TK_INTERSECT 142 +#define TK_SELECT 143 +#define TK_VALUES 144 +#define TK_DISTINCT 145 +#define TK_DOT 146 +#define TK_FROM 147 +#define TK_JOIN 148 +#define TK_USING 149 +#define TK_ORDER 150 +#define TK_GROUP 151 +#define TK_HAVING 152 +#define TK_LIMIT 153 +#define TK_WHERE 154 +#define TK_RETURNING 155 +#define TK_INTO 156 +#define TK_NOTHING 157 +#define TK_FLOAT 158 +#define TK_INTEGER 159 +#define TK_VARIABLE 160 +#define TK_CASE 161 +#define TK_WHEN 162 +#define TK_THEN 163 +#define TK_ELSE 164 +#define TK_INDEX 165 +#define TK_ALTER 166 +#define TK_ADD 167 +#define TK_WINDOW 168 +#define TK_OVER 169 +#define TK_FILTER 170 +#define TK_COLUMN 171 +#define TK_AGG_FUNCTION 172 +#define TK_AGG_COLUMN 173 +#define TK_TRUEFALSE 174 +#define TK_ISNOT 175 +#define TK_UMINUS 176 +#define TK_UPLUS 177 +#define TK_TRUTH 178 +#define TK_REGISTER 179 +#define TK_VECTOR 180 +#define TK_SELECT_COLUMN 181 +#define TK_IF_NULL_ROW 182 +#define TK_ASTERISK 183 +#define TK_SPAN 184 +#define TK_ERROR 185 +#define TK_SPACE 186 +#define TK_ILLEGAL 187 #endif /**************** End token definitions ***************************************/ @@ -168631,31 +172286,31 @@ static void updateDeleteLimitError( #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 321 +#define YYNOCODE 322 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 104 +#define YYWILDCARD 105 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - OnOrUsing yy5; - Upsert* yy6; - With* yy19; - u32 yy135; - Select* yy136; - TriggerStep* yy137; - Expr* yy224; - struct {int value; int mask;} yy275; - int yy436; - u8 yy480; - SrcList* yy493; - struct TrigEvent yy510; - struct FrameBound yy537; - ExprList* yy586; - Window* yy591; - const char* yy594; - IdList* yy600; - Cte* yy615; + ExprList* yy14; + With* yy59; + Cte* yy67; + Upsert* yy122; + IdList* yy132; + int yy144; + const char* yy168; + SrcList* yy203; + Window* yy211; + OnOrUsing yy269; + struct TrigEvent yy286; + struct {int value; int mask;} yy383; + u32 yy391; + TriggerStep* yy427; + Expr* yy454; + u8 yy462; + struct FrameBound yy509; + Select* yy555; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -168671,18 +172326,18 @@ typedef union { #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 -#define YYNSTATE 585 -#define YYNRULE 409 +#define YYNSTATE 594 +#define YYNRULE 411 #define YYNRULE_WITH_ACTION 346 -#define YYNTOKEN 187 -#define YY_MAX_SHIFT 584 -#define YY_MIN_SHIFTREDUCE 848 -#define YY_MAX_SHIFTREDUCE 1256 -#define YY_ERROR_ACTION 1257 -#define YY_ACCEPT_ACTION 1258 -#define YY_NO_ACTION 1259 -#define YY_MIN_REDUCE 1260 -#define YY_MAX_REDUCE 1668 +#define YYNTOKEN 188 +#define YY_MAX_SHIFT 593 +#define YY_MIN_SHIFTREDUCE 858 +#define YY_MAX_SHIFTREDUCE 1268 +#define YY_ERROR_ACTION 1269 +#define YY_ACCEPT_ACTION 1270 +#define YY_NO_ACTION 1271 +#define YY_MIN_REDUCE 1272 +#define YY_MAX_REDUCE 1682 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -168749,621 +172404,628 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2096) +#define YY_ACTTAB_COUNT (2115) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 500, 481, 577, 283, 208, 118, 115, 229, 1258, 1, - /* 10 */ 1, 584, 2, 1262, 118, 115, 229, 414, 321, 416, - /* 20 */ 143, 1607, 584, 2, 1262, 41, 41, 1348, 1628, 321, - /* 30 */ 1285, 143, 988, 405, 1440, 1547, 1304, 1294, 1348, 307, - /* 40 */ 989, 307, 1282, 500, 532, 423, 125, 126, 80, 1234, - /* 50 */ 1234, 1067, 1070, 1057, 1057, 123, 123, 124, 124, 124, - /* 60 */ 124, 577, 288, 288, 118, 115, 229, 1297, 288, 288, - /* 70 */ 208, 577, 383, 288, 288, 574, 296, 329, 577, 288, - /* 80 */ 288, 574, 526, 403, 13, 13, 574, 176, 1546, 240, - /* 90 */ 1296, 384, 574, 483, 51, 51, 262, 226, 479, 428, - /* 100 */ 240, 41, 41, 456, 430, 122, 122, 122, 122, 121, - /* 110 */ 121, 120, 120, 120, 119, 116, 451, 288, 288, 1664, - /* 120 */ 401, 455, 129, 1588, 382, 416, 577, 118, 115, 229, - /* 130 */ 574, 527, 455, 122, 122, 122, 122, 121, 121, 120, - /* 140 */ 120, 120, 119, 116, 451, 416, 118, 115, 229, 41, - /* 150 */ 41, 101, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, - /* 160 */ 1057, 123, 123, 124, 124, 124, 124, 1511, 1054, 1054, - /* 170 */ 1068, 1071, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, - /* 180 */ 1057, 123, 123, 124, 124, 124, 124, 120, 120, 120, - /* 190 */ 119, 116, 451, 481, 1285, 1180, 534, 1180, 127, 1590, - /* 200 */ 451, 381, 524, 1582, 580, 1209, 580, 6, 176, 412, - /* 210 */ 411, 122, 122, 122, 122, 121, 121, 120, 120, 120, - /* 220 */ 119, 116, 451, 121, 121, 120, 120, 120, 119, 116, - /* 230 */ 451, 122, 122, 122, 122, 121, 121, 120, 120, 120, - /* 240 */ 119, 116, 451, 1058, 472, 347, 577, 1588, 546, 448, - /* 250 */ 447, 416, 448, 447, 500, 124, 124, 124, 124, 117, - /* 260 */ 1175, 1238, 1209, 1210, 1211, 552, 1240, 1024, 299, 70, - /* 270 */ 70, 542, 1634, 1175, 1239, 144, 1175, 144, 125, 126, - /* 280 */ 80, 1234, 1234, 1067, 1070, 1057, 1057, 123, 123, 124, - /* 290 */ 124, 124, 124, 275, 274, 97, 535, 1241, 1241, 1510, - /* 300 */ 1241, 1241, 82, 122, 122, 122, 122, 121, 121, 120, - /* 310 */ 120, 120, 119, 116, 451, 425, 461, 124, 124, 124, - /* 320 */ 124, 345, 416, 550, 1582, 536, 1024, 83, 6, 1209, - /* 330 */ 541, 389, 1604, 320, 568, 320, 568, 122, 122, 122, - /* 340 */ 122, 121, 121, 120, 120, 120, 119, 116, 451, 125, - /* 350 */ 126, 80, 1234, 1234, 1067, 1070, 1057, 1057, 123, 123, - /* 360 */ 124, 124, 124, 124, 416, 122, 122, 122, 122, 121, - /* 370 */ 121, 120, 120, 120, 119, 116, 451, 100, 553, 1575, - /* 380 */ 345, 467, 332, 577, 331, 197, 1209, 1210, 1211, 379, - /* 390 */ 379, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, 1057, - /* 400 */ 123, 123, 124, 124, 124, 124, 13, 13, 122, 122, - /* 410 */ 122, 122, 121, 121, 120, 120, 120, 119, 116, 451, - /* 420 */ 144, 433, 531, 255, 933, 577, 513, 510, 509, 1209, - /* 430 */ 1332, 1175, 1311, 224, 523, 416, 508, 1209, 154, 362, - /* 440 */ 1332, 934, 146, 151, 1175, 16, 16, 1175, 71, 71, - /* 450 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, - /* 460 */ 116, 451, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, - /* 470 */ 1057, 123, 123, 124, 124, 124, 124, 416, 320, 568, - /* 480 */ 1209, 514, 583, 878, 1262, 559, 1209, 1210, 1211, 321, - /* 490 */ 552, 143, 425, 533, 1209, 1210, 1211, 377, 1348, 214, - /* 500 */ 1574, 1573, 320, 568, 125, 126, 80, 1234, 1234, 1067, - /* 510 */ 1070, 1057, 1057, 123, 123, 124, 124, 124, 124, 1337, - /* 520 */ 1337, 122, 122, 122, 122, 121, 121, 120, 120, 120, - /* 530 */ 119, 116, 451, 288, 288, 577, 435, 1209, 1210, 1211, - /* 540 */ 255, 878, 208, 513, 510, 509, 574, 462, 416, 1209, - /* 550 */ 394, 379, 890, 508, 1209, 408, 190, 379, 71, 71, - /* 560 */ 240, 206, 148, 122, 122, 122, 122, 121, 121, 120, - /* 570 */ 120, 120, 119, 116, 451, 125, 126, 80, 1234, 1234, - /* 580 */ 1067, 1070, 1057, 1057, 123, 123, 124, 124, 124, 124, - /* 590 */ 416, 577, 455, 1315, 883, 559, 1209, 12, 379, 157, - /* 600 */ 571, 571, 571, 558, 1576, 153, 1209, 1210, 1211, 577, - /* 610 */ 576, 1209, 1210, 1211, 71, 71, 906, 125, 126, 80, - /* 620 */ 1234, 1234, 1067, 1070, 1057, 1057, 123, 123, 124, 124, - /* 630 */ 124, 124, 133, 133, 122, 122, 122, 122, 121, 121, - /* 640 */ 120, 120, 120, 119, 116, 451, 155, 85, 577, 517, - /* 650 */ 373, 559, 425, 1209, 1210, 1211, 1110, 907, 1213, 525, - /* 660 */ 372, 416, 1573, 1335, 1335, 1193, 191, 487, 1573, 1209, - /* 670 */ 32, 71, 71, 1455, 5, 488, 122, 122, 122, 122, - /* 680 */ 121, 121, 120, 120, 120, 119, 116, 451, 125, 126, - /* 690 */ 80, 1234, 1234, 1067, 1070, 1057, 1057, 123, 123, 124, - /* 700 */ 124, 124, 124, 416, 282, 282, 1209, 1045, 538, 1573, - /* 710 */ 1209, 375, 1601, 438, 1209, 1583, 1213, 574, 954, 6, - /* 720 */ 3, 207, 577, 449, 449, 449, 1209, 1210, 1211, 1314, - /* 730 */ 125, 126, 80, 1234, 1234, 1067, 1070, 1057, 1057, 123, - /* 740 */ 123, 124, 124, 124, 124, 71, 71, 122, 122, 122, - /* 750 */ 122, 121, 121, 120, 120, 120, 119, 116, 451, 12, - /* 760 */ 1209, 577, 380, 1209, 1210, 1211, 298, 1209, 1210, 1211, - /* 770 */ 1175, 1209, 1210, 1211, 416, 1352, 472, 347, 1029, 1115, - /* 780 */ 1115, 497, 316, 1175, 71, 71, 1175, 574, 294, 122, - /* 790 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, - /* 800 */ 451, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, 1057, - /* 810 */ 123, 123, 124, 124, 124, 124, 416, 1209, 1210, 1211, - /* 820 */ 390, 317, 386, 288, 288, 289, 289, 537, 119, 116, - /* 830 */ 451, 575, 203, 943, 943, 577, 574, 471, 574, 1373, - /* 840 */ 315, 303, 227, 125, 126, 80, 1234, 1234, 1067, 1070, - /* 850 */ 1057, 1057, 123, 123, 124, 124, 124, 124, 71, 71, - /* 860 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, - /* 870 */ 116, 451, 1209, 337, 481, 577, 288, 288, 460, 1313, - /* 880 */ 1154, 1662, 1440, 1662, 853, 854, 855, 416, 440, 574, - /* 890 */ 258, 257, 256, 366, 360, 446, 460, 459, 71, 71, - /* 900 */ 477, 335, 122, 122, 122, 122, 121, 121, 120, 120, - /* 910 */ 120, 119, 116, 451, 125, 126, 80, 1234, 1234, 1067, - /* 920 */ 1070, 1057, 1057, 123, 123, 124, 124, 124, 124, 1209, - /* 930 */ 1210, 1211, 577, 521, 1131, 450, 216, 333, 1371, 336, - /* 940 */ 577, 1154, 1663, 481, 1663, 865, 1440, 400, 1254, 302, - /* 950 */ 1132, 560, 431, 1286, 421, 13, 13, 976, 355, 104, - /* 960 */ 358, 949, 1152, 71, 71, 1133, 948, 516, 351, 460, - /* 970 */ 436, 505, 1454, 122, 122, 122, 122, 121, 121, 120, - /* 980 */ 120, 120, 119, 116, 451, 437, 288, 288, 926, 1209, - /* 990 */ 577, 273, 291, 374, 519, 369, 518, 260, 927, 574, - /* 1000 */ 559, 259, 577, 365, 416, 464, 1175, 470, 561, 209, - /* 1010 */ 375, 1601, 1440, 13, 13, 413, 432, 549, 304, 1175, - /* 1020 */ 1209, 334, 1175, 1152, 416, 135, 135, 886, 306, 1255, - /* 1030 */ 107, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, 1057, - /* 1040 */ 123, 123, 124, 124, 124, 124, 1209, 1210, 1211, 577, - /* 1050 */ 1090, 125, 126, 80, 1234, 1234, 1067, 1070, 1057, 1057, - /* 1060 */ 123, 123, 124, 124, 124, 124, 419, 1580, 1044, 388, - /* 1070 */ 420, 6, 13, 13, 400, 1153, 540, 1209, 1210, 1211, - /* 1080 */ 1557, 974, 496, 500, 886, 1035, 365, 200, 1503, 1034, - /* 1090 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, - /* 1100 */ 116, 451, 1034, 577, 1343, 975, 1516, 9, 577, 265, - /* 1110 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, - /* 1120 */ 116, 451, 1034, 1036, 1516, 1518, 13, 13, 1344, 1559, - /* 1130 */ 416, 13, 13, 487, 1394, 285, 487, 974, 1440, 288, - /* 1140 */ 288, 201, 570, 421, 320, 568, 554, 1230, 500, 492, - /* 1150 */ 416, 577, 574, 489, 199, 534, 1255, 125, 114, 80, - /* 1160 */ 1234, 1234, 1067, 1070, 1057, 1057, 123, 123, 124, 124, - /* 1170 */ 124, 124, 577, 548, 55, 55, 577, 228, 126, 80, - /* 1180 */ 1234, 1234, 1067, 1070, 1057, 1057, 123, 123, 124, 124, - /* 1190 */ 124, 124, 547, 353, 1044, 56, 56, 1516, 1581, 15, - /* 1200 */ 15, 1186, 6, 974, 457, 1230, 500, 1555, 444, 287, - /* 1210 */ 226, 1035, 555, 324, 377, 1034, 122, 122, 122, 122, - /* 1220 */ 121, 121, 120, 120, 120, 119, 116, 451, 1034, 1280, - /* 1230 */ 149, 528, 344, 228, 562, 305, 122, 122, 122, 122, - /* 1240 */ 121, 121, 120, 120, 120, 119, 116, 451, 1034, 1036, - /* 1250 */ 577, 1340, 1131, 443, 1186, 535, 416, 577, 1579, 974, - /* 1260 */ 422, 177, 6, 501, 288, 288, 288, 288, 1132, 288, - /* 1270 */ 288, 233, 1112, 43, 43, 577, 1112, 574, 222, 574, - /* 1280 */ 57, 57, 574, 1133, 577, 80, 1234, 1234, 1067, 1070, - /* 1290 */ 1057, 1057, 123, 123, 124, 124, 124, 124, 44, 44, - /* 1300 */ 577, 1578, 577, 222, 577, 6, 565, 58, 58, 577, - /* 1310 */ 495, 111, 569, 577, 4, 577, 463, 577, 265, 1249, - /* 1320 */ 463, 465, 100, 59, 59, 60, 60, 61, 61, 572, - /* 1330 */ 297, 413, 62, 62, 297, 577, 45, 45, 46, 46, - /* 1340 */ 47, 47, 122, 122, 122, 122, 121, 121, 120, 120, - /* 1350 */ 120, 119, 116, 451, 452, 577, 1230, 577, 49, 49, - /* 1360 */ 577, 474, 577, 478, 111, 569, 566, 4, 577, 988, - /* 1370 */ 577, 413, 485, 413, 577, 325, 144, 989, 50, 50, - /* 1380 */ 63, 63, 572, 64, 64, 65, 65, 86, 213, 319, - /* 1390 */ 1229, 14, 14, 66, 66, 1044, 8, 131, 131, 413, - /* 1400 */ 97, 109, 109, 1633, 259, 915, 98, 452, 108, 110, - /* 1410 */ 106, 452, 579, 578, 1230, 113, 1034, 577, 949, 566, - /* 1420 */ 577, 893, 577, 948, 217, 152, 897, 38, 530, 1034, - /* 1430 */ 536, 328, 473, 544, 320, 568, 577, 1149, 543, 402, - /* 1440 */ 132, 132, 290, 67, 67, 52, 52, 30, 1044, 1034, - /* 1450 */ 1036, 1037, 27, 577, 109, 109, 342, 905, 904, 68, - /* 1460 */ 68, 237, 110, 577, 452, 579, 578, 475, 343, 1034, - /* 1470 */ 100, 1385, 486, 420, 293, 577, 69, 69, 17, 893, - /* 1480 */ 1384, 31, 1034, 1606, 1197, 454, 53, 53, 292, 111, - /* 1490 */ 569, 300, 4, 398, 398, 397, 277, 395, 163, 163, - /* 1500 */ 862, 466, 1034, 1036, 1037, 27, 1347, 572, 323, 1158, - /* 1510 */ 577, 217, 1562, 577, 234, 1026, 327, 264, 338, 577, - /* 1520 */ 426, 480, 577, 264, 326, 577, 1535, 482, 577, 264, - /* 1530 */ 1595, 577, 452, 164, 164, 1097, 76, 76, 577, 555, - /* 1540 */ 912, 913, 54, 54, 566, 72, 72, 577, 134, 134, - /* 1550 */ 564, 73, 73, 577, 161, 161, 236, 348, 544, 100, - /* 1560 */ 280, 136, 136, 545, 169, 1621, 506, 142, 261, 1534, - /* 1570 */ 130, 130, 577, 1044, 577, 399, 162, 162, 490, 109, - /* 1580 */ 109, 577, 239, 363, 235, 100, 349, 110, 577, 452, - /* 1590 */ 579, 578, 577, 1097, 1034, 156, 156, 140, 140, 111, - /* 1600 */ 569, 1093, 4, 261, 139, 139, 493, 1034, 577, 991, - /* 1610 */ 992, 137, 137, 577, 1038, 138, 138, 572, 979, 415, - /* 1620 */ 264, 946, 876, 113, 150, 320, 568, 1034, 1036, 1037, - /* 1630 */ 27, 75, 75, 947, 577, 113, 77, 77, 494, 577, - /* 1640 */ 211, 577, 452, 1109, 1109, 1108, 1108, 1381, 458, 354, - /* 1650 */ 357, 1364, 359, 361, 566, 1328, 1312, 74, 74, 368, - /* 1660 */ 378, 1439, 42, 42, 48, 48, 1367, 1379, 544, 563, - /* 1670 */ 1445, 1293, 1038, 543, 1284, 1197, 454, 1283, 312, 292, - /* 1680 */ 1271, 313, 1270, 1044, 398, 398, 397, 277, 395, 109, - /* 1690 */ 109, 862, 1272, 314, 1614, 11, 219, 110, 232, 452, - /* 1700 */ 579, 578, 1426, 1421, 1034, 234, 295, 327, 1431, 1414, - /* 1710 */ 340, 341, 484, 511, 1430, 326, 301, 1034, 1617, 1249, - /* 1720 */ 406, 223, 1311, 371, 346, 179, 1507, 1506, 1376, 204, - /* 1730 */ 1377, 567, 230, 268, 1554, 1246, 393, 1034, 1036, 1037, - /* 1740 */ 27, 218, 1375, 1552, 292, 1374, 424, 236, 85, 398, - /* 1750 */ 398, 397, 277, 395, 205, 169, 862, 215, 142, 111, - /* 1760 */ 569, 174, 4, 188, 181, 468, 183, 469, 184, 241, - /* 1770 */ 234, 504, 327, 35, 185, 235, 186, 572, 111, 569, - /* 1780 */ 326, 4, 1427, 243, 98, 1512, 404, 1433, 1432, 81, - /* 1790 */ 84, 36, 1435, 476, 407, 192, 572, 1501, 491, 91, - /* 1800 */ 499, 247, 452, 249, 1523, 251, 352, 281, 196, 502, - /* 1810 */ 415, 356, 236, 252, 566, 1273, 320, 568, 253, 520, - /* 1820 */ 169, 452, 439, 142, 409, 93, 1331, 1330, 1329, 897, - /* 1830 */ 224, 1600, 441, 566, 1301, 442, 266, 1632, 529, 458, - /* 1840 */ 235, 410, 1631, 1044, 1322, 1300, 370, 1299, 1321, 109, - /* 1850 */ 109, 953, 1630, 310, 311, 267, 376, 110, 1586, 452, - /* 1860 */ 579, 578, 1044, 445, 1034, 128, 1585, 555, 109, 109, - /* 1870 */ 79, 569, 385, 4, 1357, 415, 110, 1034, 452, 579, - /* 1880 */ 578, 320, 568, 1034, 10, 387, 105, 1399, 572, 111, - /* 1890 */ 569, 1398, 4, 1356, 99, 210, 1034, 1034, 1036, 1037, - /* 1900 */ 27, 539, 391, 557, 458, 392, 318, 572, 1487, 34, - /* 1910 */ 581, 1203, 276, 452, 279, 582, 1034, 1036, 1037, 27, - /* 1920 */ 278, 1268, 1263, 165, 1539, 566, 1540, 1538, 147, 166, - /* 1930 */ 849, 308, 452, 417, 453, 418, 212, 178, 1537, 167, - /* 1940 */ 322, 145, 220, 231, 566, 221, 78, 1107, 330, 180, - /* 1950 */ 1105, 170, 182, 238, 1044, 1229, 929, 242, 339, 1121, - /* 1960 */ 109, 109, 187, 171, 172, 427, 189, 87, 110, 88, - /* 1970 */ 452, 579, 578, 1044, 89, 1034, 429, 90, 173, 109, - /* 1980 */ 109, 244, 1124, 245, 1120, 158, 18, 110, 1034, 452, - /* 1990 */ 579, 578, 246, 350, 1034, 556, 434, 248, 264, 498, - /* 2000 */ 1243, 250, 37, 1113, 193, 194, 864, 1034, 1034, 1036, - /* 2010 */ 1037, 27, 503, 372, 254, 507, 195, 92, 19, 512, - /* 2020 */ 364, 20, 895, 94, 367, 309, 175, 1034, 1036, 1037, - /* 2030 */ 27, 908, 159, 515, 95, 522, 96, 1191, 160, 1073, - /* 2040 */ 1160, 39, 225, 1159, 284, 286, 198, 263, 113, 977, - /* 2050 */ 1177, 1179, 1181, 21, 983, 22, 1165, 7, 33, 1185, - /* 2060 */ 23, 24, 1184, 25, 551, 26, 202, 100, 1088, 102, - /* 2070 */ 1074, 1072, 1076, 1130, 1077, 1129, 269, 270, 28, 40, - /* 2080 */ 942, 1039, 877, 103, 112, 573, 29, 396, 1199, 271, - /* 2090 */ 168, 141, 272, 1623, 1198, 1622, + /* 0 */ 587, 119, 116, 234, 587, 1307, 1298, 587, 119, 116, + /* 10 */ 234, 587, 491, 587, 1298, 587, 589, 1639, 589, 587, + /* 20 */ 422, 541, 1560, 42, 42, 1317, 1295, 42, 42, 388, + /* 30 */ 42, 42, 562, 999, 72, 72, 72, 72, 72, 72, + /* 40 */ 17, 1000, 71, 71, 16, 16, 1310, 126, 127, 81, + /* 50 */ 1243, 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, + /* 60 */ 125, 125, 422, 493, 1270, 1, 1, 593, 2, 1274, + /* 70 */ 1345, 569, 1324, 569, 326, 548, 144, 1350, 1350, 543, + /* 80 */ 1345, 568, 432, 1361, 119, 116, 234, 301, 542, 126, + /* 90 */ 127, 81, 1243, 1243, 1079, 1082, 1069, 1069, 124, 124, + /* 100 */ 125, 125, 125, 125, 394, 382, 123, 123, 123, 123, + /* 110 */ 122, 122, 121, 121, 121, 120, 117, 459, 294, 294, + /* 120 */ 384, 1600, 387, 294, 294, 1602, 334, 386, 1600, 556, + /* 130 */ 1219, 584, 1190, 422, 1190, 9, 584, 270, 1123, 102, + /* 140 */ 267, 231, 1123, 147, 441, 245, 1589, 389, 123, 123, + /* 150 */ 123, 123, 122, 122, 121, 121, 121, 120, 117, 459, + /* 160 */ 126, 127, 81, 1243, 1243, 1079, 1082, 1069, 1069, 124, + /* 170 */ 124, 125, 125, 125, 125, 1239, 505, 463, 122, 122, + /* 180 */ 121, 121, 121, 120, 117, 459, 128, 1219, 1220, 1219, + /* 190 */ 123, 123, 123, 123, 122, 122, 121, 121, 121, 120, + /* 200 */ 117, 459, 119, 116, 234, 260, 227, 422, 523, 520, + /* 210 */ 519, 125, 125, 125, 125, 118, 1524, 195, 518, 123, + /* 220 */ 123, 123, 123, 122, 122, 121, 121, 121, 120, 117, + /* 230 */ 459, 1588, 587, 1239, 126, 127, 81, 1243, 1243, 1079, + /* 240 */ 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, 422, + /* 250 */ 585, 587, 954, 954, 84, 72, 72, 1219, 83, 123, + /* 260 */ 123, 123, 123, 122, 122, 121, 121, 121, 120, 117, + /* 270 */ 459, 581, 581, 581, 72, 72, 126, 127, 81, 1243, + /* 280 */ 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, + /* 290 */ 125, 459, 321, 123, 123, 123, 123, 122, 122, 121, + /* 300 */ 121, 121, 120, 117, 459, 121, 121, 121, 120, 117, + /* 310 */ 459, 569, 179, 1309, 1219, 1220, 1219, 1185, 12, 448, + /* 320 */ 422, 125, 125, 125, 125, 1219, 179, 395, 552, 391, + /* 330 */ 1185, 280, 279, 1185, 99, 123, 123, 123, 123, 122, + /* 340 */ 122, 121, 121, 121, 120, 117, 459, 126, 127, 81, + /* 350 */ 1243, 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, + /* 360 */ 125, 125, 482, 352, 1219, 1166, 1674, 1219, 1674, 123, + /* 370 */ 123, 123, 123, 122, 122, 121, 121, 121, 120, 117, + /* 380 */ 459, 1185, 1219, 1220, 1219, 260, 1219, 551, 523, 520, + /* 390 */ 519, 208, 559, 1365, 1185, 587, 481, 1185, 518, 149, + /* 400 */ 1645, 1066, 1066, 1080, 1083, 584, 123, 123, 123, 123, + /* 410 */ 122, 122, 121, 121, 121, 120, 117, 459, 134, 134, + /* 420 */ 472, 1219, 1220, 1219, 1219, 1220, 1219, 535, 535, 422, + /* 430 */ 876, 114, 6, 367, 196, 562, 1219, 457, 457, 457, + /* 440 */ 1616, 560, 560, 1219, 1220, 1219, 6, 1164, 456, 455, + /* 450 */ 422, 550, 586, 356, 524, 219, 126, 127, 81, 1243, + /* 460 */ 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, + /* 470 */ 125, 422, 229, 534, 1219, 901, 1070, 126, 127, 81, + /* 480 */ 1243, 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, + /* 490 */ 125, 125, 480, 1219, 1220, 1219, 1251, 1251, 126, 127, + /* 500 */ 81, 1243, 1243, 1079, 1082, 1069, 1069, 124, 124, 125, + /* 510 */ 125, 125, 125, 145, 385, 123, 123, 123, 123, 122, + /* 520 */ 122, 121, 121, 121, 120, 117, 459, 1219, 1453, 86, + /* 530 */ 587, 1219, 1220, 1219, 1328, 1101, 123, 123, 123, 123, + /* 540 */ 122, 122, 121, 121, 121, 120, 117, 459, 563, 563, + /* 550 */ 491, 470, 471, 72, 72, 565, 411, 123, 123, 123, + /* 560 */ 123, 122, 122, 121, 121, 121, 120, 117, 459, 470, + /* 570 */ 469, 325, 578, 1516, 456, 455, 547, 587, 422, 1348, + /* 580 */ 1348, 213, 894, 1248, 1219, 1220, 1219, 1219, 1250, 399, + /* 590 */ 322, 294, 294, 1595, 414, 101, 1249, 6, 436, 422, + /* 600 */ 136, 136, 232, 1203, 584, 126, 127, 81, 1243, 1243, + /* 610 */ 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, + /* 620 */ 422, 489, 1251, 1251, 1057, 304, 126, 127, 81, 1243, + /* 630 */ 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, + /* 640 */ 125, 289, 470, 33, 1219, 1220, 1219, 126, 127, 81, + /* 650 */ 1243, 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, + /* 660 */ 125, 125, 1529, 213, 123, 123, 123, 123, 122, 122, + /* 670 */ 121, 121, 121, 120, 117, 459, 420, 897, 1593, 1219, + /* 680 */ 1529, 1531, 6, 1219, 299, 123, 123, 123, 123, 122, + /* 690 */ 122, 121, 121, 121, 120, 117, 459, 531, 312, 908, + /* 700 */ 312, 1453, 119, 116, 234, 393, 123, 123, 123, 123, + /* 710 */ 122, 122, 121, 121, 121, 120, 117, 459, 1056, 294, + /* 720 */ 294, 863, 864, 865, 866, 960, 587, 422, 965, 1594, + /* 730 */ 959, 1040, 584, 6, 897, 1045, 1219, 1220, 1219, 1044, + /* 740 */ 1219, 1220, 1219, 120, 117, 459, 1676, 406, 422, 56, + /* 750 */ 56, 202, 1044, 1529, 126, 127, 81, 1243, 1243, 1079, + /* 760 */ 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, 422, + /* 770 */ 587, 437, 1044, 1046, 145, 126, 127, 81, 1243, 1243, + /* 780 */ 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, + /* 790 */ 1469, 5, 1570, 72, 72, 1219, 126, 127, 81, 1243, + /* 800 */ 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, + /* 810 */ 125, 1453, 365, 123, 123, 123, 123, 122, 122, 121, + /* 820 */ 121, 121, 120, 117, 459, 1219, 587, 1453, 380, 1613, + /* 830 */ 454, 1219, 325, 578, 123, 123, 123, 123, 122, 122, + /* 840 */ 121, 121, 121, 120, 117, 459, 1035, 587, 510, 72, + /* 850 */ 72, 587, 1219, 1220, 1219, 123, 123, 123, 123, 122, + /* 860 */ 122, 121, 121, 121, 120, 117, 459, 426, 325, 578, + /* 870 */ 13, 13, 587, 515, 57, 57, 360, 1056, 363, 1572, + /* 880 */ 987, 438, 1219, 1220, 1219, 434, 458, 422, 1219, 1220, + /* 890 */ 1219, 105, 214, 425, 1045, 15, 15, 506, 1044, 467, + /* 900 */ 350, 477, 337, 264, 1166, 1675, 1568, 1675, 422, 544, + /* 910 */ 986, 1044, 108, 3, 126, 127, 81, 1243, 1243, 1079, + /* 920 */ 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, 422, + /* 930 */ 329, 1044, 1046, 1386, 320, 126, 127, 81, 1243, 1243, + /* 940 */ 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, + /* 950 */ 502, 464, 330, 1219, 499, 497, 126, 115, 81, 1243, + /* 960 */ 1243, 1079, 1082, 1069, 1069, 124, 124, 125, 125, 125, + /* 970 */ 125, 491, 427, 123, 123, 123, 123, 122, 122, 121, + /* 980 */ 121, 121, 120, 117, 459, 101, 1164, 333, 370, 1126, + /* 990 */ 1126, 507, 308, 384, 123, 123, 123, 123, 122, 122, + /* 1000 */ 121, 121, 121, 120, 117, 459, 587, 1398, 98, 545, + /* 1010 */ 1219, 1220, 1219, 1356, 342, 123, 123, 123, 123, 122, + /* 1020 */ 122, 121, 121, 121, 120, 117, 459, 294, 294, 13, + /* 1030 */ 13, 1142, 558, 405, 1264, 587, 422, 213, 546, 1185, + /* 1040 */ 584, 155, 340, 213, 439, 1035, 307, 1143, 294, 294, + /* 1050 */ 408, 557, 1185, 145, 303, 1185, 409, 422, 44, 44, + /* 1060 */ 1196, 584, 1144, 565, 127, 81, 1243, 1243, 1079, 1082, + /* 1070 */ 1069, 1069, 124, 124, 125, 125, 125, 125, 338, 587, + /* 1080 */ 341, 150, 587, 1299, 428, 575, 81, 1243, 1243, 1079, + /* 1090 */ 1082, 1069, 1069, 124, 124, 125, 125, 125, 125, 350, + /* 1100 */ 1397, 491, 58, 58, 1587, 13, 13, 1453, 288, 288, + /* 1110 */ 431, 325, 578, 1196, 587, 1265, 112, 579, 587, 4, + /* 1120 */ 442, 584, 123, 123, 123, 123, 122, 122, 121, 121, + /* 1130 */ 121, 120, 117, 459, 582, 510, 1222, 45, 45, 431, + /* 1140 */ 587, 13, 13, 123, 123, 123, 123, 122, 122, 121, + /* 1150 */ 121, 121, 120, 117, 459, 238, 311, 1293, 592, 460, + /* 1160 */ 1274, 476, 339, 13, 13, 326, 587, 144, 1384, 112, + /* 1170 */ 579, 576, 4, 587, 1361, 587, 309, 452, 447, 336, + /* 1180 */ 1559, 145, 295, 295, 570, 580, 428, 582, 12, 13, + /* 1190 */ 13, 1468, 294, 294, 1222, 584, 72, 72, 59, 59, + /* 1200 */ 1056, 8, 587, 1259, 205, 584, 110, 110, 211, 294, + /* 1210 */ 294, 1142, 460, 536, 111, 384, 460, 588, 460, 294, + /* 1220 */ 294, 1044, 584, 587, 576, 52, 52, 1143, 587, 380, + /* 1230 */ 1613, 917, 584, 569, 1044, 291, 245, 985, 554, 325, + /* 1240 */ 578, 571, 1144, 553, 384, 1467, 60, 60, 294, 294, + /* 1250 */ 538, 61, 61, 1056, 1044, 1046, 1047, 28, 587, 110, + /* 1260 */ 110, 584, 537, 158, 527, 937, 498, 111, 463, 460, + /* 1270 */ 588, 460, 918, 587, 1044, 938, 112, 579, 1644, 4, + /* 1280 */ 926, 62, 62, 380, 1613, 294, 294, 1044, 1618, 1207, + /* 1290 */ 462, 587, 154, 285, 582, 152, 13, 13, 584, 403, + /* 1300 */ 403, 402, 282, 400, 572, 213, 873, 1044, 1046, 1047, + /* 1310 */ 28, 206, 382, 587, 13, 13, 130, 1360, 465, 460, + /* 1320 */ 239, 497, 332, 587, 999, 587, 1587, 985, 444, 564, + /* 1330 */ 331, 576, 1000, 233, 587, 889, 63, 63, 1121, 294, + /* 1340 */ 294, 587, 510, 431, 510, 554, 46, 46, 47, 47, + /* 1350 */ 555, 451, 584, 474, 384, 1587, 587, 48, 48, 985, + /* 1360 */ 1056, 544, 241, 419, 50, 50, 110, 110, 587, 1185, + /* 1370 */ 172, 429, 180, 143, 111, 587, 460, 588, 460, 51, + /* 1380 */ 51, 1044, 1185, 112, 579, 1185, 4, 1523, 497, 1357, + /* 1390 */ 240, 64, 64, 889, 1044, 587, 1207, 462, 65, 65, + /* 1400 */ 285, 582, 156, 418, 417, 944, 403, 403, 402, 282, + /* 1410 */ 400, 587, 212, 873, 1044, 1046, 1047, 28, 66, 66, + /* 1420 */ 349, 587, 945, 233, 587, 421, 460, 239, 1576, 332, + /* 1430 */ 510, 325, 578, 285, 14, 14, 343, 331, 576, 403, + /* 1440 */ 403, 402, 282, 400, 67, 67, 873, 132, 132, 985, + /* 1450 */ 112, 579, 554, 4, 468, 587, 1548, 553, 482, 352, + /* 1460 */ 239, 545, 332, 405, 1165, 1587, 587, 1056, 582, 241, + /* 1470 */ 331, 587, 510, 110, 110, 1353, 587, 172, 133, 133, + /* 1480 */ 143, 111, 1592, 460, 588, 460, 6, 310, 1044, 68, + /* 1490 */ 68, 587, 483, 460, 53, 53, 587, 240, 1327, 69, + /* 1500 */ 69, 1044, 241, 325, 578, 576, 263, 262, 261, 227, + /* 1510 */ 172, 1238, 587, 143, 70, 70, 347, 358, 475, 54, + /* 1520 */ 54, 1044, 1046, 1047, 28, 270, 112, 579, 419, 4, + /* 1530 */ 240, 540, 421, 587, 1056, 165, 165, 484, 325, 578, + /* 1540 */ 110, 110, 964, 587, 582, 1265, 298, 419, 111, 488, + /* 1550 */ 460, 588, 460, 587, 1591, 1044, 166, 166, 6, 419, + /* 1560 */ 473, 468, 587, 1239, 473, 421, 77, 77, 1044, 460, + /* 1570 */ 302, 325, 578, 587, 302, 587, 55, 55, 293, 231, + /* 1580 */ 328, 576, 324, 587, 98, 73, 73, 1547, 1044, 1046, + /* 1590 */ 1047, 28, 419, 487, 468, 587, 135, 135, 74, 74, + /* 1600 */ 87, 218, 80, 579, 242, 4, 163, 163, 264, 466, + /* 1610 */ 1056, 587, 1170, 587, 546, 587, 110, 110, 137, 137, + /* 1620 */ 582, 1239, 904, 587, 111, 31, 460, 588, 460, 221, + /* 1630 */ 222, 1044, 222, 162, 131, 131, 164, 164, 157, 157, + /* 1640 */ 109, 153, 107, 39, 1044, 460, 141, 141, 587, 495, + /* 1650 */ 587, 567, 587, 1619, 593, 2, 1274, 576, 485, 32, + /* 1660 */ 1161, 326, 407, 144, 1044, 1046, 1047, 28, 916, 915, + /* 1670 */ 1361, 140, 140, 138, 138, 139, 139, 427, 112, 579, + /* 1680 */ 904, 4, 305, 960, 446, 587, 1056, 587, 959, 371, + /* 1690 */ 587, 378, 110, 110, 1108, 348, 582, 101, 296, 587, + /* 1700 */ 111, 377, 460, 588, 460, 294, 294, 1044, 76, 76, + /* 1710 */ 78, 78, 587, 75, 75, 1037, 1048, 269, 584, 500, + /* 1720 */ 1044, 460, 43, 43, 490, 244, 269, 566, 492, 353, + /* 1730 */ 269, 101, 245, 576, 354, 49, 49, 516, 503, 266, + /* 1740 */ 1044, 1046, 1047, 28, 504, 368, 161, 101, 101, 496, + /* 1750 */ 923, 924, 1108, 1104, 990, 266, 269, 1002, 1003, 532, + /* 1760 */ 1394, 359, 1056, 526, 463, 957, 362, 114, 110, 110, + /* 1770 */ 1120, 1120, 1119, 1119, 1048, 887, 111, 151, 460, 588, + /* 1780 */ 460, 443, 958, 1044, 114, 364, 366, 278, 297, 379, + /* 1790 */ 529, 374, 528, 265, 1341, 1325, 1044, 1326, 204, 370, + /* 1800 */ 373, 383, 1407, 1452, 1380, 1607, 1392, 573, 574, 1457, + /* 1810 */ 511, 1306, 1297, 1296, 404, 1284, 1044, 1046, 1047, 28, + /* 1820 */ 1283, 1633, 1285, 1626, 286, 216, 237, 11, 1439, 1377, + /* 1830 */ 317, 318, 319, 1434, 300, 345, 346, 1427, 224, 577, + /* 1840 */ 306, 351, 494, 223, 209, 521, 1389, 1390, 398, 1444, + /* 1850 */ 1443, 412, 376, 1324, 1520, 228, 1519, 1388, 1387, 1629, + /* 1860 */ 1259, 182, 235, 273, 1567, 1565, 1256, 86, 430, 1525, + /* 1870 */ 220, 193, 177, 478, 186, 82, 1440, 479, 188, 189, + /* 1880 */ 210, 246, 190, 191, 514, 85, 248, 99, 1448, 410, + /* 1890 */ 501, 197, 252, 92, 486, 413, 254, 1514, 509, 287, + /* 1900 */ 256, 201, 512, 415, 361, 257, 36, 530, 445, 1286, + /* 1910 */ 1446, 258, 1335, 1344, 1343, 94, 1342, 908, 1334, 1445, + /* 1920 */ 37, 229, 449, 1314, 1643, 450, 1642, 271, 272, 375, + /* 1930 */ 453, 416, 129, 1313, 1412, 1312, 381, 1641, 1370, 565, + /* 1940 */ 1411, 315, 1536, 10, 357, 392, 106, 1501, 316, 100, + /* 1950 */ 323, 549, 35, 590, 1213, 284, 281, 283, 591, 1281, + /* 1960 */ 1275, 1552, 1553, 539, 167, 1612, 168, 169, 859, 1551, + /* 1970 */ 390, 215, 1369, 396, 397, 423, 181, 1598, 1550, 1597, + /* 1980 */ 148, 170, 424, 225, 226, 79, 313, 461, 217, 327, + /* 1990 */ 183, 184, 236, 1118, 146, 1116, 335, 185, 173, 1238, + /* 2000 */ 243, 940, 187, 344, 1132, 247, 192, 174, 175, 433, + /* 2010 */ 88, 435, 89, 194, 90, 91, 176, 249, 1135, 1131, + /* 2020 */ 159, 250, 18, 251, 253, 355, 440, 1253, 1124, 255, + /* 2030 */ 269, 198, 508, 199, 38, 875, 513, 377, 259, 517, + /* 2040 */ 200, 522, 93, 19, 178, 369, 20, 372, 906, 95, + /* 2050 */ 525, 160, 533, 314, 919, 96, 1201, 1085, 230, 1172, + /* 2060 */ 97, 21, 40, 1171, 290, 292, 994, 268, 203, 988, + /* 2070 */ 114, 1187, 22, 23, 24, 1191, 7, 1189, 25, 1195, + /* 2080 */ 1194, 1176, 26, 34, 561, 27, 103, 207, 101, 104, + /* 2090 */ 1099, 1086, 1084, 1088, 1141, 1089, 1140, 274, 275, 29, + /* 2100 */ 41, 953, 1049, 888, 113, 30, 583, 401, 1209, 276, + /* 2110 */ 171, 142, 277, 1634, 1208, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 195, 195, 195, 215, 195, 276, 277, 278, 187, 188, - /* 10 */ 189, 190, 191, 192, 276, 277, 278, 208, 197, 19, - /* 20 */ 199, 189, 190, 191, 192, 218, 219, 206, 217, 197, - /* 30 */ 195, 199, 32, 206, 195, 297, 225, 218, 206, 230, - /* 40 */ 40, 232, 207, 195, 206, 240, 46, 47, 48, 49, + /* 0 */ 196, 277, 278, 279, 196, 219, 196, 196, 277, 278, + /* 10 */ 279, 196, 196, 196, 196, 196, 206, 218, 208, 196, + /* 20 */ 20, 196, 298, 219, 220, 226, 208, 219, 220, 222, + /* 30 */ 219, 220, 196, 33, 219, 220, 219, 220, 219, 220, + /* 40 */ 23, 41, 219, 220, 219, 220, 219, 47, 48, 49, /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - /* 60 */ 60, 195, 241, 242, 276, 277, 278, 218, 241, 242, - /* 70 */ 195, 195, 221, 241, 242, 254, 270, 195, 195, 241, - /* 80 */ 242, 254, 206, 208, 218, 219, 254, 195, 240, 268, - /* 90 */ 218, 221, 254, 195, 218, 219, 258, 259, 271, 233, - /* 100 */ 268, 218, 219, 298, 265, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 113, 114, 115, 116, 241, 242, 303, - /* 120 */ 304, 300, 22, 316, 317, 19, 195, 276, 277, 278, - /* 130 */ 254, 255, 300, 105, 106, 107, 108, 109, 110, 111, - /* 140 */ 112, 113, 114, 115, 116, 19, 276, 277, 278, 218, - /* 150 */ 219, 25, 46, 47, 48, 49, 50, 51, 52, 53, - /* 160 */ 54, 55, 56, 57, 58, 59, 60, 285, 49, 50, - /* 170 */ 51, 52, 46, 47, 48, 49, 50, 51, 52, 53, - /* 180 */ 54, 55, 56, 57, 58, 59, 60, 111, 112, 113, - /* 190 */ 114, 115, 116, 195, 195, 89, 19, 91, 72, 316, - /* 200 */ 116, 318, 310, 311, 205, 62, 207, 315, 195, 109, - /* 210 */ 110, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 220 */ 114, 115, 116, 109, 110, 111, 112, 113, 114, 115, - /* 230 */ 116, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 240 */ 114, 115, 116, 124, 131, 132, 195, 316, 317, 109, - /* 250 */ 110, 19, 109, 110, 195, 57, 58, 59, 60, 61, - /* 260 */ 79, 118, 119, 120, 121, 195, 123, 76, 270, 218, - /* 270 */ 219, 90, 232, 92, 131, 84, 95, 84, 46, 47, - /* 280 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 290 */ 58, 59, 60, 26, 27, 118, 119, 157, 158, 240, - /* 300 */ 157, 158, 70, 105, 106, 107, 108, 109, 110, 111, - /* 310 */ 112, 113, 114, 115, 116, 195, 123, 57, 58, 59, - /* 320 */ 60, 130, 19, 310, 311, 148, 76, 24, 315, 62, - /* 330 */ 149, 280, 195, 142, 143, 142, 143, 105, 106, 107, - /* 340 */ 108, 109, 110, 111, 112, 113, 114, 115, 116, 46, - /* 350 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 360 */ 57, 58, 59, 60, 19, 105, 106, 107, 108, 109, - /* 370 */ 110, 111, 112, 113, 114, 115, 116, 25, 308, 309, - /* 380 */ 130, 131, 132, 195, 264, 25, 119, 120, 121, 195, - /* 390 */ 195, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 400 */ 55, 56, 57, 58, 59, 60, 218, 219, 105, 106, - /* 410 */ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - /* 420 */ 84, 233, 195, 122, 120, 195, 125, 126, 127, 62, - /* 430 */ 225, 79, 227, 168, 169, 19, 135, 62, 243, 23, - /* 440 */ 235, 137, 75, 22, 92, 218, 219, 95, 218, 219, - /* 450 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 460 */ 115, 116, 46, 47, 48, 49, 50, 51, 52, 53, - /* 470 */ 54, 55, 56, 57, 58, 59, 60, 19, 142, 143, - /* 480 */ 62, 23, 190, 62, 192, 255, 119, 120, 121, 197, - /* 490 */ 195, 199, 195, 263, 119, 120, 121, 195, 206, 154, - /* 500 */ 306, 306, 142, 143, 46, 47, 48, 49, 50, 51, - /* 510 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 237, - /* 520 */ 238, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 530 */ 114, 115, 116, 241, 242, 195, 234, 119, 120, 121, - /* 540 */ 122, 120, 195, 125, 126, 127, 254, 271, 19, 62, - /* 550 */ 203, 195, 23, 135, 62, 208, 22, 195, 218, 219, - /* 560 */ 268, 264, 75, 105, 106, 107, 108, 109, 110, 111, - /* 570 */ 112, 113, 114, 115, 116, 46, 47, 48, 49, 50, - /* 580 */ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - /* 590 */ 19, 195, 300, 228, 23, 255, 62, 215, 195, 243, - /* 600 */ 212, 213, 214, 263, 309, 243, 119, 120, 121, 195, - /* 610 */ 195, 119, 120, 121, 218, 219, 36, 46, 47, 48, - /* 620 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 630 */ 59, 60, 218, 219, 105, 106, 107, 108, 109, 110, - /* 640 */ 111, 112, 113, 114, 115, 116, 243, 155, 195, 69, - /* 650 */ 124, 255, 195, 119, 120, 121, 11, 77, 62, 263, - /* 660 */ 134, 19, 306, 237, 238, 23, 22, 195, 306, 62, - /* 670 */ 22, 218, 219, 275, 22, 293, 105, 106, 107, 108, - /* 680 */ 109, 110, 111, 112, 113, 114, 115, 116, 46, 47, - /* 690 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 700 */ 58, 59, 60, 19, 241, 242, 62, 23, 255, 306, - /* 710 */ 62, 313, 314, 133, 62, 311, 120, 254, 111, 315, - /* 720 */ 22, 264, 195, 212, 213, 214, 119, 120, 121, 228, - /* 730 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 740 */ 56, 57, 58, 59, 60, 218, 219, 105, 106, 107, - /* 750 */ 108, 109, 110, 111, 112, 113, 114, 115, 116, 215, - /* 760 */ 62, 195, 195, 119, 120, 121, 294, 119, 120, 121, - /* 770 */ 79, 119, 120, 121, 19, 242, 131, 132, 23, 130, - /* 780 */ 131, 132, 255, 92, 218, 219, 95, 254, 206, 105, - /* 790 */ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - /* 800 */ 116, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 810 */ 55, 56, 57, 58, 59, 60, 19, 119, 120, 121, - /* 820 */ 251, 255, 253, 241, 242, 241, 242, 195, 114, 115, - /* 830 */ 116, 138, 288, 140, 141, 195, 254, 293, 254, 261, - /* 840 */ 262, 206, 195, 46, 47, 48, 49, 50, 51, 52, - /* 850 */ 53, 54, 55, 56, 57, 58, 59, 60, 218, 219, - /* 860 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 870 */ 115, 116, 62, 16, 195, 195, 241, 242, 195, 228, - /* 880 */ 22, 23, 195, 25, 7, 8, 9, 19, 19, 254, - /* 890 */ 130, 131, 132, 24, 16, 255, 213, 214, 218, 219, - /* 900 */ 118, 44, 105, 106, 107, 108, 109, 110, 111, 112, - /* 910 */ 113, 114, 115, 116, 46, 47, 48, 49, 50, 51, - /* 920 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 119, - /* 930 */ 120, 121, 195, 111, 12, 255, 154, 80, 260, 82, - /* 940 */ 195, 22, 23, 195, 25, 21, 195, 22, 23, 270, - /* 950 */ 28, 206, 265, 210, 211, 218, 219, 147, 80, 162, - /* 960 */ 82, 139, 104, 218, 219, 43, 144, 98, 44, 286, - /* 970 */ 233, 19, 275, 105, 106, 107, 108, 109, 110, 111, - /* 980 */ 112, 113, 114, 115, 116, 116, 241, 242, 66, 62, - /* 990 */ 195, 122, 123, 124, 125, 126, 127, 128, 76, 254, - /* 1000 */ 255, 49, 195, 134, 19, 246, 79, 83, 263, 24, - /* 1010 */ 313, 314, 195, 218, 219, 256, 265, 90, 270, 92, - /* 1020 */ 62, 164, 95, 104, 19, 218, 219, 62, 233, 104, - /* 1030 */ 162, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1040 */ 55, 56, 57, 58, 59, 60, 119, 120, 121, 195, - /* 1050 */ 126, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1060 */ 55, 56, 57, 58, 59, 60, 200, 311, 103, 195, - /* 1070 */ 118, 315, 218, 219, 22, 23, 149, 119, 120, 121, - /* 1080 */ 195, 25, 265, 195, 119, 120, 134, 233, 164, 124, - /* 1090 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 1100 */ 115, 116, 137, 195, 206, 147, 195, 22, 195, 24, - /* 1110 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 1120 */ 115, 116, 157, 158, 213, 214, 218, 219, 240, 195, - /* 1130 */ 19, 218, 219, 195, 195, 23, 195, 25, 195, 241, - /* 1140 */ 242, 233, 210, 211, 142, 143, 233, 62, 195, 283, - /* 1150 */ 19, 195, 254, 287, 257, 19, 104, 46, 47, 48, - /* 1160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1170 */ 59, 60, 195, 69, 218, 219, 195, 121, 47, 48, - /* 1180 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1190 */ 59, 60, 88, 240, 103, 218, 219, 286, 311, 218, - /* 1200 */ 219, 97, 315, 147, 195, 120, 195, 195, 265, 258, - /* 1210 */ 259, 120, 149, 195, 195, 124, 105, 106, 107, 108, - /* 1220 */ 109, 110, 111, 112, 113, 114, 115, 116, 137, 206, - /* 1230 */ 167, 206, 294, 121, 206, 294, 105, 106, 107, 108, - /* 1240 */ 109, 110, 111, 112, 113, 114, 115, 116, 157, 158, - /* 1250 */ 195, 240, 12, 234, 150, 119, 19, 195, 311, 147, - /* 1260 */ 301, 302, 315, 290, 241, 242, 241, 242, 28, 241, - /* 1270 */ 242, 15, 30, 218, 219, 195, 34, 254, 25, 254, - /* 1280 */ 218, 219, 254, 43, 195, 48, 49, 50, 51, 52, - /* 1290 */ 53, 54, 55, 56, 57, 58, 59, 60, 218, 219, - /* 1300 */ 195, 311, 195, 25, 195, 315, 66, 218, 219, 195, - /* 1310 */ 68, 19, 20, 195, 22, 195, 262, 195, 24, 63, - /* 1320 */ 266, 246, 25, 218, 219, 218, 219, 218, 219, 37, - /* 1330 */ 262, 256, 218, 219, 266, 195, 218, 219, 218, 219, - /* 1340 */ 218, 219, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1350 */ 113, 114, 115, 116, 62, 195, 62, 195, 218, 219, - /* 1360 */ 195, 246, 195, 246, 19, 20, 74, 22, 195, 32, - /* 1370 */ 195, 256, 19, 256, 195, 195, 84, 40, 218, 219, - /* 1380 */ 218, 219, 37, 218, 219, 218, 219, 153, 154, 246, - /* 1390 */ 25, 218, 219, 218, 219, 103, 51, 218, 219, 256, - /* 1400 */ 118, 109, 110, 23, 49, 25, 153, 62, 161, 117, - /* 1410 */ 163, 119, 120, 121, 120, 25, 124, 195, 139, 74, - /* 1420 */ 195, 62, 195, 144, 146, 22, 129, 24, 19, 137, - /* 1430 */ 148, 195, 132, 88, 142, 143, 195, 23, 93, 25, - /* 1440 */ 218, 219, 22, 218, 219, 218, 219, 22, 103, 157, - /* 1450 */ 158, 159, 160, 195, 109, 110, 156, 123, 124, 218, - /* 1460 */ 219, 24, 117, 195, 119, 120, 121, 132, 23, 124, - /* 1470 */ 25, 195, 119, 118, 102, 195, 218, 219, 22, 120, - /* 1480 */ 195, 56, 137, 0, 1, 2, 218, 219, 5, 19, - /* 1490 */ 20, 156, 22, 10, 11, 12, 13, 14, 218, 219, - /* 1500 */ 17, 195, 157, 158, 159, 160, 195, 37, 136, 100, - /* 1510 */ 195, 146, 195, 195, 31, 23, 33, 25, 195, 195, - /* 1520 */ 64, 23, 195, 25, 41, 195, 195, 23, 195, 25, - /* 1530 */ 320, 195, 62, 218, 219, 62, 218, 219, 195, 149, - /* 1540 */ 7, 8, 218, 219, 74, 218, 219, 195, 218, 219, - /* 1550 */ 238, 218, 219, 195, 218, 219, 73, 23, 88, 25, - /* 1560 */ 289, 218, 219, 93, 81, 145, 23, 84, 25, 195, - /* 1570 */ 218, 219, 195, 103, 195, 193, 218, 219, 195, 109, - /* 1580 */ 110, 195, 145, 23, 101, 25, 195, 117, 195, 119, - /* 1590 */ 120, 121, 195, 120, 124, 218, 219, 218, 219, 19, - /* 1600 */ 20, 23, 22, 25, 218, 219, 195, 137, 195, 86, - /* 1610 */ 87, 218, 219, 195, 62, 218, 219, 37, 23, 136, - /* 1620 */ 25, 23, 23, 25, 25, 142, 143, 157, 158, 159, - /* 1630 */ 160, 218, 219, 23, 195, 25, 218, 219, 195, 195, - /* 1640 */ 244, 195, 62, 157, 158, 157, 158, 195, 165, 195, - /* 1650 */ 195, 257, 195, 195, 74, 195, 195, 218, 219, 195, - /* 1660 */ 195, 195, 218, 219, 218, 219, 195, 195, 88, 195, - /* 1670 */ 195, 195, 120, 93, 195, 1, 2, 195, 257, 5, - /* 1680 */ 195, 257, 195, 103, 10, 11, 12, 13, 14, 109, - /* 1690 */ 110, 17, 195, 257, 195, 245, 216, 117, 299, 119, - /* 1700 */ 120, 121, 273, 269, 124, 31, 247, 33, 273, 269, - /* 1710 */ 295, 248, 295, 222, 273, 41, 248, 137, 198, 63, - /* 1720 */ 273, 231, 227, 221, 247, 299, 221, 221, 261, 251, - /* 1730 */ 261, 282, 299, 145, 202, 39, 247, 157, 158, 159, - /* 1740 */ 160, 245, 261, 202, 5, 261, 202, 73, 155, 10, - /* 1750 */ 11, 12, 13, 14, 251, 81, 17, 154, 84, 19, - /* 1760 */ 20, 46, 22, 22, 236, 18, 239, 202, 239, 239, - /* 1770 */ 31, 18, 33, 272, 239, 101, 239, 37, 19, 20, - /* 1780 */ 41, 22, 274, 201, 153, 285, 248, 274, 274, 296, - /* 1790 */ 296, 272, 236, 248, 248, 236, 37, 248, 202, 161, - /* 1800 */ 65, 201, 62, 201, 292, 201, 291, 202, 22, 223, - /* 1810 */ 136, 202, 73, 201, 74, 202, 142, 143, 201, 118, - /* 1820 */ 81, 62, 67, 84, 223, 22, 220, 220, 220, 129, - /* 1830 */ 168, 314, 24, 74, 220, 116, 202, 226, 307, 165, - /* 1840 */ 101, 223, 226, 103, 229, 222, 220, 220, 229, 109, - /* 1850 */ 110, 111, 220, 284, 284, 94, 223, 117, 319, 119, - /* 1860 */ 120, 121, 103, 85, 124, 152, 319, 149, 109, 110, - /* 1870 */ 19, 20, 251, 22, 252, 136, 117, 137, 119, 120, - /* 1880 */ 121, 142, 143, 124, 22, 202, 161, 267, 37, 19, - /* 1890 */ 20, 267, 22, 252, 151, 250, 137, 157, 158, 159, - /* 1900 */ 160, 150, 249, 144, 165, 248, 281, 37, 279, 25, - /* 1910 */ 204, 13, 196, 62, 6, 194, 157, 158, 159, 160, - /* 1920 */ 196, 194, 194, 209, 215, 74, 215, 215, 224, 209, - /* 1930 */ 4, 224, 62, 305, 3, 305, 22, 302, 215, 209, - /* 1940 */ 166, 16, 216, 15, 74, 216, 215, 23, 143, 155, - /* 1950 */ 23, 133, 146, 24, 103, 25, 20, 148, 16, 1, - /* 1960 */ 109, 110, 146, 133, 133, 64, 155, 56, 117, 56, - /* 1970 */ 119, 120, 121, 103, 56, 124, 38, 56, 133, 109, - /* 1980 */ 110, 35, 119, 145, 1, 5, 22, 117, 137, 119, - /* 1990 */ 120, 121, 118, 164, 124, 144, 24, 45, 25, 42, - /* 2000 */ 78, 145, 24, 71, 71, 118, 20, 137, 157, 158, - /* 2010 */ 159, 160, 19, 134, 128, 70, 22, 22, 22, 70, - /* 2020 */ 23, 22, 62, 22, 24, 70, 38, 157, 158, 159, - /* 2030 */ 160, 29, 23, 99, 153, 22, 25, 23, 23, 23, - /* 2040 */ 23, 22, 145, 100, 23, 23, 22, 35, 25, 147, - /* 2050 */ 91, 89, 78, 35, 119, 35, 23, 47, 22, 78, - /* 2060 */ 35, 35, 96, 35, 24, 35, 25, 25, 23, 146, - /* 2070 */ 23, 23, 23, 23, 11, 23, 25, 22, 22, 22, - /* 2080 */ 139, 23, 23, 146, 22, 25, 22, 15, 1, 145, - /* 2090 */ 25, 23, 145, 145, 1, 145, 321, 321, 321, 321, - /* 2100 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2110 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2120 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2130 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2140 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2150 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2160 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2170 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2180 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2190 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2200 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2210 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2220 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2230 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2240 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2250 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2260 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2270 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 2280 */ 321, 321, 321, + /* 60 */ 60, 61, 20, 196, 188, 189, 190, 191, 192, 193, + /* 70 */ 226, 256, 228, 256, 198, 256, 200, 238, 239, 264, + /* 80 */ 236, 264, 65, 207, 277, 278, 279, 271, 207, 47, + /* 90 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 100 */ 58, 59, 60, 61, 281, 196, 106, 107, 108, 109, + /* 110 */ 110, 111, 112, 113, 114, 115, 116, 117, 242, 243, + /* 120 */ 196, 317, 318, 242, 243, 317, 196, 319, 317, 318, + /* 130 */ 63, 255, 90, 20, 92, 23, 255, 25, 31, 26, + /* 140 */ 259, 260, 35, 76, 235, 269, 310, 222, 106, 107, + /* 150 */ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + /* 160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 170 */ 57, 58, 59, 60, 61, 63, 69, 301, 110, 111, + /* 180 */ 112, 113, 114, 115, 116, 117, 73, 120, 121, 122, + /* 190 */ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + /* 200 */ 116, 117, 277, 278, 279, 123, 26, 20, 126, 127, + /* 210 */ 128, 58, 59, 60, 61, 62, 286, 23, 136, 106, + /* 220 */ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + /* 230 */ 117, 307, 196, 121, 47, 48, 49, 50, 51, 52, + /* 240 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 20, + /* 250 */ 139, 196, 141, 142, 25, 219, 220, 63, 71, 106, + /* 260 */ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + /* 270 */ 117, 213, 214, 215, 219, 220, 47, 48, 49, 50, + /* 280 */ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + /* 290 */ 61, 117, 256, 106, 107, 108, 109, 110, 111, 112, + /* 300 */ 113, 114, 115, 116, 117, 112, 113, 114, 115, 116, + /* 310 */ 117, 256, 196, 219, 120, 121, 122, 80, 216, 264, + /* 320 */ 20, 58, 59, 60, 61, 63, 196, 252, 91, 254, + /* 330 */ 93, 27, 28, 96, 154, 106, 107, 108, 109, 110, + /* 340 */ 111, 112, 113, 114, 115, 116, 117, 47, 48, 49, + /* 350 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + /* 360 */ 60, 61, 132, 133, 63, 23, 24, 63, 26, 106, + /* 370 */ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + /* 380 */ 117, 80, 120, 121, 122, 123, 63, 150, 126, 127, + /* 390 */ 128, 289, 91, 243, 93, 196, 294, 96, 136, 76, + /* 400 */ 233, 50, 51, 52, 53, 255, 106, 107, 108, 109, + /* 410 */ 110, 111, 112, 113, 114, 115, 116, 117, 219, 220, + /* 420 */ 272, 120, 121, 122, 120, 121, 122, 311, 312, 20, + /* 430 */ 22, 26, 316, 24, 23, 196, 63, 213, 214, 215, + /* 440 */ 196, 311, 312, 120, 121, 122, 316, 105, 110, 111, + /* 450 */ 20, 150, 196, 45, 24, 155, 47, 48, 49, 50, + /* 460 */ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + /* 470 */ 61, 20, 169, 170, 63, 24, 125, 47, 48, 49, + /* 480 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + /* 490 */ 60, 61, 84, 120, 121, 122, 158, 159, 47, 48, + /* 500 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 510 */ 59, 60, 61, 85, 196, 106, 107, 108, 109, 110, + /* 520 */ 111, 112, 113, 114, 115, 116, 117, 63, 196, 156, + /* 530 */ 196, 120, 121, 122, 229, 127, 106, 107, 108, 109, + /* 540 */ 110, 111, 112, 113, 114, 115, 116, 117, 309, 310, + /* 550 */ 196, 196, 124, 219, 220, 150, 207, 106, 107, 108, + /* 560 */ 109, 110, 111, 112, 113, 114, 115, 116, 117, 214, + /* 570 */ 215, 143, 144, 165, 110, 111, 196, 196, 20, 238, + /* 580 */ 239, 196, 24, 119, 120, 121, 122, 63, 124, 204, + /* 590 */ 256, 242, 243, 312, 209, 26, 132, 316, 266, 20, + /* 600 */ 219, 220, 196, 24, 255, 47, 48, 49, 50, 51, + /* 610 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + /* 620 */ 20, 272, 158, 159, 24, 271, 47, 48, 49, 50, + /* 630 */ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + /* 640 */ 61, 216, 287, 23, 120, 121, 122, 47, 48, 49, + /* 650 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + /* 660 */ 60, 61, 196, 196, 106, 107, 108, 109, 110, 111, + /* 670 */ 112, 113, 114, 115, 116, 117, 209, 63, 312, 63, + /* 680 */ 214, 215, 316, 63, 207, 106, 107, 108, 109, 110, + /* 690 */ 111, 112, 113, 114, 115, 116, 117, 112, 231, 130, + /* 700 */ 233, 196, 277, 278, 279, 196, 106, 107, 108, 109, + /* 710 */ 110, 111, 112, 113, 114, 115, 116, 117, 104, 242, + /* 720 */ 243, 7, 8, 9, 10, 140, 196, 20, 112, 312, + /* 730 */ 145, 24, 255, 316, 120, 121, 120, 121, 122, 125, + /* 740 */ 120, 121, 122, 115, 116, 117, 304, 305, 20, 219, + /* 750 */ 220, 26, 138, 287, 47, 48, 49, 50, 51, 52, + /* 760 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 20, + /* 770 */ 196, 266, 158, 159, 85, 47, 48, 49, 50, 51, + /* 780 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + /* 790 */ 276, 23, 196, 219, 220, 63, 47, 48, 49, 50, + /* 800 */ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + /* 810 */ 61, 196, 17, 106, 107, 108, 109, 110, 111, 112, + /* 820 */ 113, 114, 115, 116, 117, 63, 196, 196, 314, 315, + /* 830 */ 256, 63, 143, 144, 106, 107, 108, 109, 110, 111, + /* 840 */ 112, 113, 114, 115, 116, 117, 77, 196, 196, 219, + /* 850 */ 220, 196, 120, 121, 122, 106, 107, 108, 109, 110, + /* 860 */ 111, 112, 113, 114, 115, 116, 117, 201, 143, 144, + /* 870 */ 219, 220, 196, 20, 219, 220, 81, 104, 83, 196, + /* 880 */ 148, 266, 120, 121, 122, 234, 256, 20, 120, 121, + /* 890 */ 122, 163, 25, 241, 121, 219, 220, 266, 125, 196, + /* 900 */ 131, 132, 133, 50, 23, 24, 196, 26, 20, 20, + /* 910 */ 148, 138, 163, 23, 47, 48, 49, 50, 51, 52, + /* 920 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 20, + /* 930 */ 196, 158, 159, 262, 263, 47, 48, 49, 50, 51, + /* 940 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + /* 950 */ 284, 299, 196, 63, 288, 196, 47, 48, 49, 50, + /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + /* 970 */ 61, 196, 119, 106, 107, 108, 109, 110, 111, 112, + /* 980 */ 113, 114, 115, 116, 117, 26, 105, 196, 135, 131, + /* 990 */ 132, 133, 207, 196, 106, 107, 108, 109, 110, 111, + /* 1000 */ 112, 113, 114, 115, 116, 117, 196, 196, 119, 120, + /* 1010 */ 120, 121, 122, 207, 17, 106, 107, 108, 109, 110, + /* 1020 */ 111, 112, 113, 114, 115, 116, 117, 242, 243, 219, + /* 1030 */ 220, 13, 70, 23, 24, 196, 20, 196, 149, 80, + /* 1040 */ 255, 244, 45, 196, 234, 77, 271, 29, 242, 243, + /* 1050 */ 209, 89, 93, 85, 295, 96, 209, 20, 219, 220, + /* 1060 */ 98, 255, 44, 150, 48, 49, 50, 51, 52, 53, + /* 1070 */ 54, 55, 56, 57, 58, 59, 60, 61, 81, 196, + /* 1080 */ 83, 168, 196, 211, 212, 67, 49, 50, 51, 52, + /* 1090 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 131, + /* 1100 */ 196, 196, 219, 220, 307, 219, 220, 196, 242, 243, + /* 1110 */ 196, 143, 144, 151, 196, 105, 20, 21, 196, 23, + /* 1120 */ 234, 255, 106, 107, 108, 109, 110, 111, 112, 113, + /* 1130 */ 114, 115, 116, 117, 38, 196, 63, 219, 220, 196, + /* 1140 */ 196, 219, 220, 106, 107, 108, 109, 110, 111, 112, + /* 1150 */ 113, 114, 115, 116, 117, 16, 234, 207, 191, 63, + /* 1160 */ 193, 196, 165, 219, 220, 198, 196, 200, 261, 20, + /* 1170 */ 21, 75, 23, 196, 207, 196, 271, 266, 234, 265, + /* 1180 */ 241, 85, 242, 243, 207, 211, 212, 38, 216, 219, + /* 1190 */ 220, 276, 242, 243, 121, 255, 219, 220, 219, 220, + /* 1200 */ 104, 52, 196, 64, 234, 255, 110, 111, 265, 242, + /* 1210 */ 243, 13, 63, 207, 118, 196, 120, 121, 122, 242, + /* 1220 */ 243, 125, 255, 196, 75, 219, 220, 29, 196, 314, + /* 1230 */ 315, 37, 255, 256, 138, 24, 269, 26, 89, 143, + /* 1240 */ 144, 264, 44, 94, 196, 276, 219, 220, 242, 243, + /* 1250 */ 207, 219, 220, 104, 158, 159, 160, 161, 196, 110, + /* 1260 */ 111, 255, 256, 244, 70, 67, 294, 118, 301, 120, + /* 1270 */ 121, 122, 78, 196, 125, 77, 20, 21, 24, 23, + /* 1280 */ 26, 219, 220, 314, 315, 242, 243, 138, 0, 1, + /* 1290 */ 2, 196, 244, 5, 38, 23, 219, 220, 255, 11, + /* 1300 */ 12, 13, 14, 15, 207, 196, 18, 158, 159, 160, + /* 1310 */ 161, 234, 196, 196, 219, 220, 23, 196, 209, 63, + /* 1320 */ 32, 196, 34, 196, 33, 196, 307, 26, 134, 234, + /* 1330 */ 42, 75, 41, 122, 196, 63, 219, 220, 12, 242, + /* 1340 */ 243, 196, 196, 196, 196, 89, 219, 220, 219, 220, + /* 1350 */ 94, 235, 255, 247, 196, 307, 196, 219, 220, 148, + /* 1360 */ 104, 20, 74, 257, 219, 220, 110, 111, 196, 80, + /* 1370 */ 82, 302, 303, 85, 118, 196, 120, 121, 122, 219, + /* 1380 */ 220, 125, 93, 20, 21, 96, 23, 241, 196, 241, + /* 1390 */ 102, 219, 220, 121, 138, 196, 1, 2, 219, 220, + /* 1400 */ 5, 38, 244, 110, 111, 121, 11, 12, 13, 14, + /* 1410 */ 15, 196, 265, 18, 158, 159, 160, 161, 219, 220, + /* 1420 */ 295, 196, 138, 122, 196, 137, 63, 32, 196, 34, + /* 1430 */ 196, 143, 144, 5, 219, 220, 196, 42, 75, 11, + /* 1440 */ 12, 13, 14, 15, 219, 220, 18, 219, 220, 148, + /* 1450 */ 20, 21, 89, 23, 166, 196, 196, 94, 132, 133, + /* 1460 */ 32, 120, 34, 23, 24, 307, 196, 104, 38, 74, + /* 1470 */ 42, 196, 196, 110, 111, 241, 196, 82, 219, 220, + /* 1480 */ 85, 118, 312, 120, 121, 122, 316, 295, 125, 219, + /* 1490 */ 220, 196, 133, 63, 219, 220, 196, 102, 229, 219, + /* 1500 */ 220, 138, 74, 143, 144, 75, 131, 132, 133, 26, + /* 1510 */ 82, 26, 196, 85, 219, 220, 157, 241, 247, 219, + /* 1520 */ 220, 158, 159, 160, 161, 25, 20, 21, 257, 23, + /* 1530 */ 102, 20, 137, 196, 104, 219, 220, 247, 143, 144, + /* 1540 */ 110, 111, 112, 196, 38, 105, 103, 257, 118, 247, + /* 1550 */ 120, 121, 122, 196, 312, 125, 219, 220, 316, 257, + /* 1560 */ 263, 166, 196, 63, 267, 137, 219, 220, 138, 63, + /* 1570 */ 263, 143, 144, 196, 267, 196, 219, 220, 259, 260, + /* 1580 */ 137, 75, 247, 196, 119, 219, 220, 196, 158, 159, + /* 1590 */ 160, 161, 257, 119, 166, 196, 219, 220, 219, 220, + /* 1600 */ 154, 155, 20, 21, 25, 23, 219, 220, 50, 166, + /* 1610 */ 104, 196, 101, 196, 149, 196, 110, 111, 219, 220, + /* 1620 */ 38, 121, 63, 196, 118, 23, 120, 121, 122, 155, + /* 1630 */ 147, 125, 147, 24, 219, 220, 219, 220, 219, 220, + /* 1640 */ 162, 23, 164, 25, 138, 63, 219, 220, 196, 20, + /* 1650 */ 196, 145, 196, 190, 191, 192, 193, 75, 133, 57, + /* 1660 */ 24, 198, 26, 200, 158, 159, 160, 161, 124, 125, + /* 1670 */ 207, 219, 220, 219, 220, 219, 220, 119, 20, 21, + /* 1680 */ 121, 23, 157, 140, 20, 196, 104, 196, 145, 25, + /* 1690 */ 196, 125, 110, 111, 63, 24, 38, 26, 23, 196, + /* 1700 */ 118, 135, 120, 121, 122, 242, 243, 125, 219, 220, + /* 1710 */ 219, 220, 196, 219, 220, 24, 63, 26, 255, 196, + /* 1720 */ 138, 63, 219, 220, 24, 146, 26, 145, 24, 24, + /* 1730 */ 26, 26, 269, 75, 196, 219, 220, 24, 196, 26, + /* 1740 */ 158, 159, 160, 161, 196, 24, 24, 26, 26, 120, + /* 1750 */ 7, 8, 121, 24, 24, 26, 26, 87, 88, 150, + /* 1760 */ 196, 196, 104, 99, 301, 24, 196, 26, 110, 111, + /* 1770 */ 158, 159, 158, 159, 121, 24, 118, 26, 120, 121, + /* 1780 */ 122, 117, 24, 125, 26, 196, 196, 123, 124, 125, + /* 1790 */ 126, 127, 128, 129, 196, 196, 138, 229, 258, 135, + /* 1800 */ 196, 196, 196, 196, 196, 321, 196, 196, 239, 196, + /* 1810 */ 291, 196, 196, 196, 194, 196, 158, 159, 160, 161, + /* 1820 */ 196, 146, 196, 196, 290, 245, 300, 246, 274, 258, + /* 1830 */ 258, 258, 258, 270, 248, 296, 249, 270, 217, 283, + /* 1840 */ 249, 248, 296, 246, 252, 223, 262, 262, 248, 274, + /* 1850 */ 274, 274, 222, 228, 222, 232, 222, 262, 262, 199, + /* 1860 */ 64, 300, 300, 146, 203, 203, 40, 156, 203, 286, + /* 1870 */ 155, 23, 47, 19, 237, 297, 275, 203, 240, 240, + /* 1880 */ 252, 240, 240, 240, 19, 297, 202, 154, 237, 249, + /* 1890 */ 203, 237, 202, 162, 249, 249, 202, 249, 66, 203, + /* 1900 */ 202, 23, 224, 224, 203, 202, 273, 119, 68, 203, + /* 1910 */ 275, 202, 230, 221, 221, 23, 221, 130, 230, 275, + /* 1920 */ 273, 169, 25, 221, 227, 117, 227, 203, 95, 221, + /* 1930 */ 86, 224, 153, 223, 268, 221, 224, 221, 253, 150, + /* 1940 */ 268, 285, 293, 23, 292, 203, 162, 280, 285, 152, + /* 1950 */ 282, 151, 26, 205, 14, 6, 197, 197, 195, 195, + /* 1960 */ 195, 216, 216, 308, 210, 315, 210, 210, 4, 216, + /* 1970 */ 252, 251, 253, 250, 249, 306, 303, 320, 216, 320, + /* 1980 */ 225, 210, 306, 217, 217, 216, 225, 3, 23, 167, + /* 1990 */ 16, 64, 16, 24, 17, 24, 144, 156, 134, 26, + /* 2000 */ 25, 21, 147, 17, 1, 149, 147, 134, 134, 65, + /* 2010 */ 57, 39, 57, 156, 57, 57, 134, 36, 120, 1, + /* 2020 */ 5, 146, 23, 119, 46, 165, 25, 79, 72, 146, + /* 2030 */ 26, 72, 43, 119, 25, 21, 20, 135, 129, 71, + /* 2040 */ 23, 71, 23, 23, 39, 24, 23, 25, 63, 23, + /* 2050 */ 100, 24, 23, 71, 30, 154, 24, 24, 146, 24, + /* 2060 */ 26, 36, 23, 101, 24, 24, 120, 36, 23, 148, + /* 2070 */ 26, 92, 36, 36, 36, 79, 48, 90, 36, 79, + /* 2080 */ 97, 24, 36, 23, 25, 36, 147, 26, 26, 147, + /* 2090 */ 24, 24, 24, 24, 24, 12, 24, 26, 23, 23, + /* 2100 */ 23, 140, 24, 24, 23, 23, 26, 16, 1, 146, + /* 2110 */ 26, 24, 146, 146, 1, 322, 322, 322, 322, 322, + /* 2120 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2130 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2140 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2150 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2160 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2170 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2180 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2190 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2200 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2210 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2220 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2230 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2240 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2250 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2260 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2270 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2280 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2290 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + /* 2300 */ 322, 322, 322, }; -#define YY_SHIFT_COUNT (584) +#define YY_SHIFT_COUNT (593) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2093) +#define YY_SHIFT_MAX (2113) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 1674, 1483, 1739, 1292, 1292, 336, 1345, 1470, 1580, 1870, - /* 10 */ 1870, 1870, 191, 0, 0, 232, 1005, 1870, 1870, 1870, - /* 20 */ 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, - /* 30 */ 143, 143, 927, 927, 418, 193, 336, 336, 336, 336, - /* 40 */ 336, 106, 126, 303, 345, 416, 458, 529, 571, 642, - /* 50 */ 684, 755, 797, 868, 985, 1005, 1005, 1005, 1005, 1005, - /* 60 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 70 */ 1005, 1005, 1005, 1111, 1005, 1131, 1237, 1237, 1740, 1759, - /* 80 */ 1851, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, - /* 90 */ 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, - /* 100 */ 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, - /* 110 */ 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, - /* 120 */ 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, - /* 130 */ 198, 260, 260, 260, 260, 260, 260, 260, 28, 114, - /* 140 */ 76, 267, 367, 924, 487, 375, 375, 952, 375, 375, - /* 150 */ 140, 140, 375, 360, 360, 360, 714, 360, 113, 265, - /* 160 */ 265, 84, 84, 2096, 2096, 869, 869, 869, 267, 492, - /* 170 */ 534, 534, 534, 534, 922, 922, 181, 858, 919, 375, - /* 180 */ 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, - /* 190 */ 375, 375, 375, 375, 375, 375, 375, 375, 375, 177, - /* 200 */ 352, 352, 375, 645, 691, 691, 1136, 1136, 596, 596, - /* 210 */ 1063, 1002, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 965, - /* 220 */ 1091, 1091, 644, 301, 648, 607, 652, 810, 958, 698, - /* 230 */ 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, - /* 240 */ 250, 375, 375, 375, 375, 375, 375, 375, 375, 375, - /* 250 */ 375, 375, 375, 375, 375, 375, 580, 580, 580, 375, - /* 260 */ 375, 375, 1112, 375, 375, 375, 1085, 1104, 375, 375, - /* 270 */ 1240, 375, 375, 375, 375, 375, 375, 375, 375, 375, - /* 280 */ 649, 1242, 693, 1294, 1294, 1294, 1294, 1056, 693, 693, - /* 290 */ 822, 100, 877, 1256, 782, 1234, 1278, 1234, 1353, 1253, - /* 300 */ 782, 782, 1253, 782, 1278, 1353, 1297, 1380, 1355, 1337, - /* 310 */ 1337, 1337, 1282, 1282, 1282, 1282, 1390, 1390, 1247, 1365, - /* 320 */ 1279, 1403, 1656, 1656, 1588, 1588, 1696, 1696, 1588, 1593, - /* 330 */ 1603, 1741, 1715, 1747, 1747, 1747, 1747, 1747, 1588, 1753, - /* 340 */ 1631, 1603, 1603, 1631, 1741, 1715, 1631, 1715, 1631, 1588, - /* 350 */ 1753, 1753, 1638, 1735, 1588, 1753, 1786, 1588, 1753, 1588, - /* 360 */ 1753, 1786, 1701, 1701, 1701, 1755, 1803, 1803, 1786, 1701, - /* 370 */ 1700, 1701, 1755, 1701, 1701, 1662, 1808, 1719, 1719, 1786, - /* 380 */ 1588, 1761, 1761, 1778, 1778, 1713, 1718, 1862, 1588, 1725, - /* 390 */ 1713, 1743, 1751, 1631, 1884, 1898, 1898, 1908, 1908, 1908, - /* 400 */ 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, - /* 410 */ 2096, 2096, 2096, 2096, 2096, 857, 119, 925, 1052, 878, - /* 420 */ 760, 421, 1414, 1372, 1425, 1437, 1300, 1335, 1445, 1456, - /* 430 */ 1492, 1498, 1504, 1534, 304, 1543, 1560, 1359, 1334, 1533, - /* 440 */ 526, 1409, 1473, 1578, 1595, 1523, 1598, 1486, 1488, 1599, - /* 450 */ 1610, 1552, 1420, 1926, 1931, 1914, 1774, 1928, 1925, 1924, - /* 460 */ 1927, 1805, 1794, 1818, 1930, 1930, 1929, 1806, 1936, 1809, - /* 470 */ 1942, 1958, 1816, 1830, 1930, 1831, 1901, 1938, 1930, 1811, - /* 480 */ 1911, 1913, 1918, 1921, 1845, 1863, 1946, 1838, 1983, 1980, - /* 490 */ 1964, 1874, 1829, 1972, 1952, 1932, 1973, 1933, 1922, 1957, - /* 500 */ 1856, 1887, 1978, 1986, 1993, 1879, 1886, 1994, 1945, 1995, - /* 510 */ 1996, 1997, 1999, 1949, 1960, 2000, 1934, 2002, 2001, 1955, - /* 520 */ 1988, 2009, 1881, 2013, 2014, 2015, 2016, 2011, 2017, 2019, - /* 530 */ 1943, 1897, 2021, 2022, 1935, 2012, 2024, 1902, 2023, 2018, - /* 540 */ 2020, 2025, 2026, 1959, 1974, 1962, 2010, 1981, 1966, 2028, - /* 550 */ 2033, 2036, 2040, 2041, 2042, 2030, 1923, 1937, 2045, 2023, - /* 560 */ 2047, 2048, 2049, 2050, 2051, 2052, 2055, 2063, 2056, 2057, - /* 570 */ 2058, 2059, 2062, 2064, 2060, 1941, 1944, 1947, 1948, 1950, - /* 580 */ 2065, 2068, 2072, 2087, 2093, + /* 0 */ 1395, 1288, 1428, 1096, 1096, 689, 1149, 1256, 1363, 1658, + /* 10 */ 1658, 1658, 968, 0, 0, 187, 888, 1658, 1658, 1658, + /* 20 */ 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, + /* 30 */ 1658, 464, 464, 301, 301, 262, 428, 689, 689, 689, + /* 40 */ 689, 689, 42, 113, 229, 300, 409, 430, 451, 558, + /* 50 */ 579, 600, 707, 728, 749, 867, 888, 888, 888, 888, + /* 60 */ 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, + /* 70 */ 888, 888, 888, 888, 909, 888, 1016, 1037, 1037, 1430, + /* 80 */ 1506, 1582, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, + /* 90 */ 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, + /* 100 */ 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, + /* 110 */ 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, + /* 120 */ 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, + /* 130 */ 1658, 153, 263, 263, 263, 263, 263, 263, 263, 84, + /* 140 */ 68, 193, 304, 67, 408, 323, 524, 524, 853, 524, + /* 150 */ 524, 338, 338, 524, 725, 725, 725, 628, 725, 230, + /* 160 */ 303, 303, 303, 174, 174, 2115, 2115, 1664, 1664, 1664, + /* 170 */ 1664, 304, 373, 194, 194, 194, 194, 1198, 1198, 237, + /* 180 */ 342, 881, 524, 524, 524, 524, 524, 524, 524, 524, + /* 190 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524, + /* 200 */ 524, 524, 524, 524, 889, 959, 959, 524, 1326, 1289, + /* 210 */ 1289, 1341, 1341, 1073, 1073, 913, 1360, 2115, 2115, 2115, + /* 220 */ 2115, 2115, 2115, 2115, 614, 773, 773, 411, 82, 620, + /* 230 */ 616, 768, 732, 762, 890, 524, 524, 524, 524, 524, + /* 240 */ 524, 524, 524, 524, 524, 769, 524, 524, 524, 524, + /* 250 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524, + /* 260 */ 524, 1194, 1194, 1194, 524, 524, 524, 1211, 524, 524, + /* 270 */ 524, 112, 962, 524, 524, 1018, 524, 524, 524, 524, + /* 280 */ 524, 524, 524, 524, 524, 714, 858, 107, 111, 1500, + /* 290 */ 1500, 1500, 1500, 1301, 111, 111, 585, 1293, 1139, 1474, + /* 300 */ 1446, 1483, 1446, 1629, 180, 1474, 1474, 180, 1474, 1483, + /* 310 */ 1629, 569, 1254, 1558, 1291, 1291, 1291, 1465, 1465, 1465, + /* 320 */ 1465, 405, 405, 1478, 1485, 1543, 1618, 1796, 1796, 1717, + /* 330 */ 1717, 1826, 1826, 1717, 1711, 1715, 1848, 1825, 1854, 1854, + /* 340 */ 1854, 1854, 1854, 1717, 1865, 1733, 1715, 1715, 1733, 1848, + /* 350 */ 1825, 1733, 1825, 1733, 1717, 1865, 1865, 1731, 1832, 1717, + /* 360 */ 1865, 1878, 1717, 1865, 1717, 1865, 1878, 1788, 1788, 1788, + /* 370 */ 1840, 1892, 1892, 1878, 1788, 1787, 1788, 1840, 1788, 1788, + /* 380 */ 1752, 1897, 1808, 1808, 1878, 1717, 1833, 1833, 1844, 1844, + /* 390 */ 1779, 1789, 1920, 1717, 1784, 1779, 1797, 1800, 1733, 1926, + /* 400 */ 1940, 1940, 1949, 1949, 1949, 2115, 2115, 2115, 2115, 2115, + /* 410 */ 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, 2115, + /* 420 */ 2115, 997, 351, 1010, 1440, 1443, 795, 1375, 1272, 1636, + /* 430 */ 1602, 1579, 1359, 1525, 1671, 17, 1691, 1700, 1704, 1705, + /* 440 */ 1284, 1713, 1721, 1559, 1544, 1743, 1566, 1722, 1609, 1511, + /* 450 */ 1631, 1729, 1730, 1670, 1741, 1612, 1614, 1751, 1758, 1653, + /* 460 */ 1675, 1964, 1984, 1965, 1822, 1974, 1927, 1976, 1977, 1969, + /* 470 */ 1971, 1852, 1841, 1864, 1973, 1973, 1975, 1855, 1980, 1856, + /* 480 */ 1986, 2003, 1859, 1873, 1973, 1874, 1944, 1972, 1973, 1857, + /* 490 */ 1953, 1955, 1957, 1958, 1882, 1898, 1981, 1875, 2018, 2015, + /* 500 */ 1999, 1904, 1860, 2001, 1978, 1956, 2004, 1959, 1948, 1989, + /* 510 */ 1883, 1914, 2009, 2014, 2016, 1902, 1909, 2017, 1968, 2019, + /* 520 */ 2020, 2021, 2023, 1970, 1985, 2022, 1950, 2024, 2026, 1982, + /* 530 */ 2005, 2027, 2025, 1901, 2029, 2032, 2033, 2034, 2035, 2039, + /* 540 */ 1962, 1912, 2040, 2041, 1946, 2031, 2045, 1921, 2044, 2036, + /* 550 */ 2037, 2038, 2042, 1979, 1996, 1987, 2028, 2000, 1983, 2046, + /* 560 */ 2057, 2060, 2059, 2061, 2062, 2049, 1939, 1942, 2066, 2044, + /* 570 */ 2067, 2068, 2069, 2070, 2071, 2072, 2075, 2083, 2076, 2077, + /* 580 */ 2078, 2079, 2081, 2082, 2080, 1961, 1963, 1966, 1967, 2084, + /* 590 */ 2087, 2091, 2107, 2113, }; -#define YY_REDUCE_COUNT (414) -#define YY_REDUCE_MIN (-271) -#define YY_REDUCE_MAX (1731) +#define YY_REDUCE_COUNT (420) +#define YY_REDUCE_MIN (-276) +#define YY_REDUCE_MAX (1771) static const short yy_reduce_ofst[] = { - /* 0 */ -179, -168, 292, 745, -124, -162, -193, -117, -69, 230, - /* 10 */ 340, 396, -173, -149, -130, -262, -212, -134, 188, 737, - /* 20 */ 795, 453, 854, 908, 527, 566, 913, 51, 640, 680, - /* 30 */ 683, 911, -108, 13, -191, 582, 635, 898, 1023, 1025, - /* 40 */ 1028, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 50 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 60 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 70 */ -271, -271, -271, -271, -271, -271, -271, -271, 227, 414, - /* 80 */ 807, 956, 977, 981, 1055, 1062, 1080, 1089, 1105, 1107, - /* 90 */ 1109, 1114, 1118, 1120, 1122, 1140, 1160, 1162, 1165, 1167, - /* 100 */ 1173, 1175, 1179, 1222, 1225, 1227, 1241, 1258, 1268, 1280, - /* 110 */ 1315, 1318, 1324, 1327, 1330, 1333, 1336, 1343, 1352, 1358, - /* 120 */ 1377, 1379, 1386, 1393, 1397, 1413, 1418, 1439, 1444, 1446, - /* 130 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, - /* 140 */ -271, -1, 195, 866, 356, -195, 362, 205, 403, 70, - /* 150 */ 388, 511, 347, 463, 584, 463, -271, 584, 544, 398, - /* 160 */ 697, -271, -271, -271, -271, -189, -189, -189, -165, -118, - /* 170 */ -194, -2, 679, 748, 282, 426, 404, -184, -184, -125, - /* 180 */ 120, 297, 457, -152, 59, 888, 1011, 472, -161, 938, - /* 190 */ 687, 751, 941, 817, 953, 302, 1019, 194, 943, 578, - /* 200 */ 756, 887, 295, 382, 947, 990, 1054, 1068, 743, 932, - /* 210 */ 569, 533, 959, 759, 1075, 1115, 1117, 951, 1143, -181, - /* 220 */ -151, -128, -102, 40, 137, 415, 567, 632, 647, 874, - /* 230 */ 885, 934, 1009, 1012, 1018, 1180, 1236, 1276, 1285, 1306, - /* 240 */ 276, 1311, 1317, 1323, 1331, 1374, 1383, 1391, 1411, 1443, - /* 250 */ 1452, 1454, 1455, 1457, 1458, 1460, 365, 501, 651, 1461, - /* 260 */ 1464, 1465, 678, 939, 1466, 1471, 897, 1210, 1472, 1474, - /* 270 */ 1312, 1475, 415, 1476, 1479, 1482, 1485, 1487, 1497, 1499, - /* 280 */ 973, 1271, 1396, 1394, 1421, 1424, 1436, 678, 1396, 1396, - /* 290 */ 1450, 1480, 1382, 1399, 1429, 1434, 1459, 1440, 1415, 1463, - /* 300 */ 1435, 1441, 1468, 1447, 1477, 1417, 1491, 1490, 1495, 1502, - /* 310 */ 1505, 1506, 1467, 1469, 1481, 1484, 1478, 1503, 1449, 1489, - /* 320 */ 1496, 1520, 1426, 1433, 1532, 1541, 1493, 1494, 1544, 1500, - /* 330 */ 1508, 1501, 1528, 1527, 1529, 1530, 1535, 1537, 1565, 1582, - /* 340 */ 1538, 1513, 1514, 1545, 1519, 1556, 1546, 1559, 1549, 1596, - /* 350 */ 1600, 1602, 1512, 1515, 1605, 1604, 1586, 1609, 1612, 1613, - /* 360 */ 1617, 1601, 1606, 1607, 1608, 1615, 1611, 1616, 1618, 1614, - /* 370 */ 1623, 1626, 1619, 1627, 1632, 1517, 1531, 1569, 1570, 1633, - /* 380 */ 1634, 1539, 1547, 1620, 1624, 1622, 1621, 1629, 1683, 1625, - /* 390 */ 1641, 1645, 1653, 1657, 1706, 1716, 1724, 1721, 1727, 1728, - /* 400 */ 1628, 1630, 1635, 1714, 1709, 1711, 1712, 1723, 1720, 1704, - /* 410 */ 1707, 1726, 1729, 1731, 1730, + /* 0 */ -124, 1463, 967, 977, 1006, -119, -196, -192, -189, -185, + /* 10 */ -183, 55, 349, -193, -75, -276, 425, 651, 810, 886, + /* 20 */ 922, 944, -181, 970, 1077, 36, 334, 1095, -177, 574, + /* 30 */ 630, 355, 466, 116, 130, 467, 477, 785, 806, 950, + /* 40 */ 1043, 1097, -269, -269, -269, -269, -269, -269, -269, -269, + /* 50 */ -269, -269, -269, -269, -269, -269, -269, -269, -269, -269, + /* 60 */ -269, -269, -269, -269, -269, -269, -269, -269, -269, -269, + /* 70 */ -269, -269, -269, -269, -269, -269, -269, -269, -269, -175, + /* 80 */ 199, 381, 530, 655, 676, 839, 883, 918, 979, 1027, + /* 90 */ 1032, 1062, 1117, 1127, 1129, 1138, 1145, 1160, 1172, 1179, + /* 100 */ 1199, 1215, 1225, 1228, 1259, 1270, 1275, 1280, 1295, 1300, + /* 110 */ 1316, 1337, 1347, 1357, 1366, 1377, 1379, 1387, 1399, 1415, + /* 120 */ 1417, 1419, 1427, 1452, 1454, 1456, 1489, 1491, 1494, 1503, + /* 130 */ 1516, -269, -269, -269, -269, -269, -269, -269, -269, -269, + /* 140 */ -269, -269, -190, 797, 666, 1019, 652, 1048, -156, 1158, + /* 150 */ 239, 58, 224, 385, 866, 940, 866, -269, 940, 102, + /* 160 */ 514, 915, 969, -269, -269, -269, -269, -201, -201, -201, + /* 170 */ -201, -182, -70, -184, 354, 775, 905, -161, 341, 281, + /* 180 */ 442, 442, 841, 847, 1109, 914, 943, 1147, 939, 1146, + /* 190 */ 1148, 1234, 759, 332, 1125, 505, 615, 1192, 631, 1276, + /* 200 */ -91, 1116, -76, 911, 671, 366, 417, -164, 972, 1170, + /* 210 */ 1242, 1297, 1307, 872, 974, 75, 150, 1069, 1106, 1271, + /* 220 */ 1290, 1302, 1319, 1335, -214, -173, 94, -133, 167, 244, + /* 230 */ 256, 318, 380, 406, 509, 596, 683, 703, 710, 734, + /* 240 */ 756, 791, 811, 904, 965, 148, 1121, 1232, 1240, 1260, + /* 250 */ 1391, 1523, 1538, 1542, 1548, 1564, 1565, 1570, 1589, 1590, + /* 260 */ 1598, 305, 1269, 1568, 1599, 1604, 1605, 907, 1606, 1607, + /* 270 */ 1608, 1540, 1484, 1610, 1611, 1569, 1613, 256, 1615, 1616, + /* 280 */ 1617, 1619, 1624, 1626, 1627, 1620, 1519, 1534, 1580, 1571, + /* 290 */ 1572, 1573, 1574, 907, 1580, 1580, 1581, 1621, 1526, 1554, + /* 300 */ 1563, 1586, 1567, 1539, 1587, 1575, 1576, 1591, 1577, 1593, + /* 310 */ 1546, 1622, 1623, 1625, 1630, 1632, 1634, 1584, 1585, 1595, + /* 320 */ 1596, 1592, 1628, 1556, 1600, 1597, 1660, 1561, 1562, 1661, + /* 330 */ 1662, 1578, 1588, 1665, 1583, 1601, 1633, 1637, 1638, 1639, + /* 340 */ 1641, 1642, 1643, 1674, 1684, 1640, 1635, 1644, 1645, 1647, + /* 350 */ 1651, 1646, 1654, 1648, 1687, 1690, 1694, 1649, 1652, 1696, + /* 360 */ 1698, 1678, 1701, 1703, 1706, 1709, 1679, 1692, 1693, 1695, + /* 370 */ 1682, 1697, 1699, 1707, 1702, 1710, 1708, 1688, 1714, 1716, + /* 380 */ 1650, 1655, 1656, 1663, 1712, 1724, 1657, 1659, 1666, 1672, + /* 390 */ 1685, 1718, 1667, 1742, 1668, 1719, 1720, 1723, 1725, 1748, + /* 400 */ 1759, 1760, 1763, 1764, 1765, 1669, 1676, 1673, 1754, 1756, + /* 410 */ 1745, 1746, 1753, 1762, 1757, 1755, 1761, 1766, 1767, 1769, + /* 420 */ 1771, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1668, 1668, 1668, 1496, 1257, 1372, 1257, 1257, 1257, 1496, - /* 10 */ 1496, 1496, 1257, 1402, 1402, 1549, 1291, 1257, 1257, 1257, - /* 20 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1495, 1257, 1257, - /* 30 */ 1257, 1257, 1584, 1584, 1257, 1257, 1257, 1257, 1257, 1257, - /* 40 */ 1257, 1257, 1411, 1257, 1418, 1257, 1257, 1257, 1257, 1257, - /* 50 */ 1497, 1498, 1257, 1257, 1257, 1548, 1550, 1513, 1425, 1424, - /* 60 */ 1423, 1422, 1531, 1390, 1416, 1409, 1413, 1491, 1492, 1490, - /* 70 */ 1494, 1498, 1497, 1257, 1412, 1459, 1475, 1458, 1257, 1257, - /* 80 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 90 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 100 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 110 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 120 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 130 */ 1467, 1474, 1473, 1472, 1481, 1471, 1468, 1461, 1460, 1462, - /* 140 */ 1463, 1281, 1257, 1278, 1257, 1257, 1257, 1333, 1257, 1257, - /* 150 */ 1257, 1257, 1257, 1568, 1567, 1257, 1464, 1257, 1291, 1453, - /* 160 */ 1452, 1478, 1465, 1477, 1476, 1556, 1620, 1619, 1257, 1514, - /* 170 */ 1257, 1257, 1257, 1257, 1257, 1257, 1584, 1257, 1257, 1257, - /* 180 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 190 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1392, - /* 200 */ 1584, 1584, 1257, 1291, 1584, 1584, 1393, 1393, 1287, 1287, - /* 210 */ 1396, 1257, 1563, 1363, 1363, 1363, 1363, 1372, 1363, 1257, - /* 220 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 230 */ 1257, 1257, 1257, 1257, 1553, 1551, 1257, 1257, 1257, 1257, - /* 240 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 250 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 260 */ 1257, 1257, 1257, 1257, 1257, 1257, 1368, 1257, 1257, 1257, - /* 270 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1613, - /* 280 */ 1257, 1526, 1350, 1368, 1368, 1368, 1368, 1370, 1351, 1349, - /* 290 */ 1362, 1292, 1264, 1660, 1428, 1417, 1369, 1417, 1657, 1415, - /* 300 */ 1428, 1428, 1415, 1428, 1369, 1657, 1308, 1636, 1303, 1402, - /* 310 */ 1402, 1402, 1392, 1392, 1392, 1392, 1396, 1396, 1493, 1369, - /* 320 */ 1362, 1257, 1660, 1660, 1378, 1378, 1659, 1659, 1378, 1514, - /* 330 */ 1644, 1437, 1336, 1342, 1342, 1342, 1342, 1342, 1378, 1275, - /* 340 */ 1415, 1644, 1644, 1415, 1437, 1336, 1415, 1336, 1415, 1378, - /* 350 */ 1275, 1275, 1530, 1654, 1378, 1275, 1504, 1378, 1275, 1378, - /* 360 */ 1275, 1504, 1334, 1334, 1334, 1323, 1257, 1257, 1504, 1334, - /* 370 */ 1308, 1334, 1323, 1334, 1334, 1602, 1257, 1508, 1508, 1504, - /* 380 */ 1378, 1594, 1594, 1405, 1405, 1410, 1396, 1499, 1378, 1257, - /* 390 */ 1410, 1408, 1406, 1415, 1326, 1616, 1616, 1612, 1612, 1612, - /* 400 */ 1665, 1665, 1563, 1629, 1291, 1291, 1291, 1291, 1629, 1310, - /* 410 */ 1310, 1292, 1292, 1291, 1629, 1257, 1257, 1257, 1257, 1257, - /* 420 */ 1257, 1624, 1257, 1558, 1515, 1382, 1257, 1257, 1257, 1257, - /* 430 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 440 */ 1257, 1569, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 450 */ 1257, 1257, 1442, 1257, 1260, 1560, 1257, 1257, 1257, 1257, - /* 460 */ 1257, 1257, 1257, 1257, 1419, 1420, 1383, 1257, 1257, 1257, - /* 470 */ 1257, 1257, 1257, 1257, 1434, 1257, 1257, 1257, 1429, 1257, - /* 480 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1656, 1257, 1257, - /* 490 */ 1257, 1257, 1257, 1257, 1257, 1257, 1529, 1528, 1257, 1257, - /* 500 */ 1380, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 510 */ 1257, 1257, 1257, 1257, 1306, 1257, 1257, 1257, 1257, 1257, - /* 520 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 530 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1407, 1257, - /* 540 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 550 */ 1257, 1257, 1257, 1599, 1397, 1257, 1257, 1257, 1257, 1647, - /* 560 */ 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, 1257, - /* 570 */ 1257, 1257, 1257, 1257, 1640, 1353, 1444, 1257, 1443, 1447, - /* 580 */ 1279, 1257, 1269, 1257, 1257, + /* 0 */ 1680, 1680, 1680, 1509, 1269, 1385, 1269, 1269, 1269, 1509, + /* 10 */ 1509, 1509, 1269, 1415, 1415, 1562, 1304, 1269, 1269, 1269, + /* 20 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1508, 1269, + /* 30 */ 1269, 1269, 1269, 1596, 1596, 1269, 1269, 1269, 1269, 1269, + /* 40 */ 1269, 1269, 1269, 1424, 1269, 1431, 1269, 1269, 1269, 1269, + /* 50 */ 1269, 1510, 1511, 1269, 1269, 1269, 1561, 1563, 1526, 1438, + /* 60 */ 1437, 1436, 1435, 1544, 1403, 1429, 1422, 1426, 1505, 1506, + /* 70 */ 1504, 1658, 1511, 1510, 1269, 1425, 1473, 1489, 1472, 1269, + /* 80 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 90 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 100 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 110 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 120 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 130 */ 1269, 1481, 1488, 1487, 1486, 1495, 1485, 1482, 1475, 1474, + /* 140 */ 1476, 1477, 1294, 1269, 1291, 1269, 1269, 1269, 1346, 1269, + /* 150 */ 1269, 1269, 1269, 1269, 1582, 1581, 1269, 1478, 1269, 1304, + /* 160 */ 1466, 1465, 1464, 1492, 1479, 1491, 1490, 1569, 1573, 1632, + /* 170 */ 1631, 1269, 1527, 1269, 1269, 1269, 1269, 1269, 1269, 1596, + /* 180 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 190 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 200 */ 1269, 1269, 1269, 1269, 1405, 1596, 1596, 1269, 1304, 1596, + /* 210 */ 1596, 1406, 1406, 1300, 1300, 1409, 1269, 1577, 1376, 1376, + /* 220 */ 1376, 1376, 1385, 1376, 1269, 1269, 1269, 1269, 1269, 1269, + /* 230 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1566, + /* 240 */ 1564, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 250 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 260 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 270 */ 1269, 1381, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 280 */ 1269, 1269, 1269, 1269, 1625, 1276, 1269, 1539, 1363, 1381, + /* 290 */ 1381, 1381, 1381, 1383, 1364, 1362, 1375, 1305, 1672, 1441, + /* 300 */ 1430, 1382, 1430, 1669, 1428, 1441, 1441, 1428, 1441, 1382, + /* 310 */ 1669, 1321, 1647, 1316, 1415, 1415, 1415, 1405, 1405, 1405, + /* 320 */ 1405, 1409, 1409, 1507, 1382, 1375, 1269, 1672, 1672, 1391, + /* 330 */ 1391, 1671, 1671, 1391, 1527, 1655, 1450, 1349, 1355, 1355, + /* 340 */ 1355, 1355, 1355, 1391, 1288, 1428, 1655, 1655, 1428, 1450, + /* 350 */ 1349, 1428, 1349, 1428, 1391, 1288, 1288, 1543, 1666, 1391, + /* 360 */ 1288, 1517, 1391, 1288, 1391, 1288, 1517, 1347, 1347, 1347, + /* 370 */ 1336, 1269, 1269, 1517, 1347, 1321, 1347, 1336, 1347, 1347, + /* 380 */ 1614, 1269, 1521, 1521, 1517, 1391, 1606, 1606, 1418, 1418, + /* 390 */ 1423, 1409, 1512, 1391, 1269, 1423, 1421, 1419, 1428, 1339, + /* 400 */ 1628, 1628, 1624, 1624, 1624, 1677, 1677, 1577, 1640, 1640, + /* 410 */ 1304, 1304, 1304, 1304, 1640, 1323, 1323, 1305, 1305, 1304, + /* 420 */ 1640, 1269, 1269, 1269, 1269, 1571, 1269, 1269, 1635, 1269, + /* 430 */ 1528, 1395, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 440 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1583, + /* 450 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 460 */ 1455, 1269, 1272, 1574, 1269, 1269, 1269, 1269, 1269, 1269, + /* 470 */ 1269, 1269, 1269, 1269, 1432, 1433, 1396, 1269, 1269, 1269, + /* 480 */ 1269, 1269, 1269, 1269, 1447, 1269, 1269, 1269, 1442, 1269, + /* 490 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1668, 1269, 1269, + /* 500 */ 1269, 1269, 1269, 1269, 1269, 1269, 1542, 1541, 1269, 1269, + /* 510 */ 1393, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 520 */ 1269, 1269, 1269, 1269, 1319, 1269, 1269, 1269, 1269, 1269, + /* 530 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 540 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1420, 1269, + /* 550 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 560 */ 1269, 1269, 1269, 1611, 1410, 1269, 1269, 1269, 1269, 1659, + /* 570 */ 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, 1269, + /* 580 */ 1269, 1269, 1269, 1269, 1651, 1366, 1456, 1269, 1459, 1292, + /* 590 */ 1269, 1282, 1269, 1269, }; /********** End of lemon-generated parsing tables *****************************/ @@ -169385,55 +173047,56 @@ static const YYACTIONTYPE yy_default[] = { static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ 0, /* SEMI => nothing */ - 62, /* EXPLAIN => ID */ - 62, /* QUERY => ID */ - 62, /* PLAN => ID */ - 62, /* BEGIN => ID */ + 63, /* EXPLAIN => ID */ + 63, /* QUERY => ID */ + 63, /* PLAN => ID */ + 63, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ - 62, /* DEFERRED => ID */ - 62, /* IMMEDIATE => ID */ - 62, /* EXCLUSIVE => ID */ + 63, /* DEFERRED => ID */ + 63, /* IMMEDIATE => ID */ + 63, /* EXCLUSIVE => ID */ + 63, /* READONLY => ID */ 0, /* COMMIT => nothing */ - 62, /* END => ID */ - 62, /* ROLLBACK => ID */ - 62, /* SAVEPOINT => ID */ - 62, /* RELEASE => ID */ + 63, /* END => ID */ + 63, /* ROLLBACK => ID */ + 63, /* SAVEPOINT => ID */ + 63, /* RELEASE => ID */ 0, /* TO => nothing */ 0, /* TABLE => nothing */ 0, /* CREATE => nothing */ - 62, /* IF => ID */ + 63, /* IF => ID */ 0, /* NOT => nothing */ 0, /* EXISTS => nothing */ - 62, /* TEMP => ID */ + 63, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ 0, /* COMMA => nothing */ - 62, /* WITHOUT => ID */ - 62, /* RANDOM => ID */ - 62, /* ABORT => ID */ - 62, /* ACTION => ID */ - 62, /* AFTER => ID */ - 62, /* ANALYZE => ID */ - 62, /* ASC => ID */ - 62, /* ATTACH => ID */ - 62, /* BEFORE => ID */ - 62, /* BY => ID */ - 62, /* CASCADE => ID */ - 62, /* CAST => ID */ - 62, /* CONFLICT => ID */ - 62, /* DATABASE => ID */ - 62, /* DESC => ID */ - 62, /* DETACH => ID */ - 62, /* EACH => ID */ - 62, /* FAIL => ID */ - 62, /* FUNCTION => ID */ - 62, /* LANGUAGE => ID */ + 63, /* WITHOUT => ID */ + 63, /* RANDOM => ID */ + 63, /* ABORT => ID */ + 63, /* ACTION => ID */ + 63, /* AFTER => ID */ + 63, /* ANALYZE => ID */ + 63, /* ASC => ID */ + 63, /* ATTACH => ID */ + 63, /* BEFORE => ID */ + 63, /* BY => ID */ + 63, /* CASCADE => ID */ + 63, /* CAST => ID */ + 63, /* CONFLICT => ID */ + 63, /* DATABASE => ID */ + 63, /* DESC => ID */ + 63, /* DETACH => ID */ + 63, /* EACH => ID */ + 63, /* FAIL => ID */ + 63, /* FUNCTION => ID */ + 63, /* LANGUAGE => ID */ 0, /* OR => nothing */ 0, /* AND => nothing */ 0, /* IS => nothing */ - 62, /* MATCH => ID */ - 62, /* LIKE_KW => ID */ + 63, /* MATCH => ID */ + 63, /* LIKE_KW => ID */ 0, /* BETWEEN => nothing */ 0, /* IN => nothing */ 0, /* ISNULL => nothing */ @@ -169446,47 +173109,47 @@ static const YYCODETYPE yyFallback[] = { 0, /* GE => nothing */ 0, /* ESCAPE => nothing */ 0, /* ID => nothing */ - 62, /* COLUMNKW => ID */ - 62, /* DO => ID */ - 62, /* FOR => ID */ - 62, /* IGNORE => ID */ - 62, /* INITIALLY => ID */ - 62, /* INSTEAD => ID */ - 62, /* NO => ID */ - 62, /* KEY => ID */ - 62, /* OF => ID */ - 62, /* OFFSET => ID */ - 62, /* PRAGMA => ID */ - 62, /* RAISE => ID */ - 62, /* RECURSIVE => ID */ - 62, /* REPLACE => ID */ - 62, /* RESTRICT => ID */ - 62, /* ROW => ID */ - 62, /* ROWS => ID */ - 62, /* TRIGGER => ID */ - 62, /* VACUUM => ID */ - 62, /* VIEW => ID */ - 62, /* VIRTUAL => ID */ - 62, /* WITH => ID */ - 62, /* NULLS => ID */ - 62, /* FIRST => ID */ - 62, /* LAST => ID */ - 62, /* CURRENT => ID */ - 62, /* FOLLOWING => ID */ - 62, /* PARTITION => ID */ - 62, /* PRECEDING => ID */ - 62, /* RANGE => ID */ - 62, /* UNBOUNDED => ID */ - 62, /* EXCLUDE => ID */ - 62, /* GROUPS => ID */ - 62, /* OTHERS => ID */ - 62, /* TIES => ID */ - 62, /* GENERATED => ID */ - 62, /* ALWAYS => ID */ - 62, /* MATERIALIZED => ID */ - 62, /* REINDEX => ID */ - 62, /* RENAME => ID */ - 62, /* CTIME_KW => ID */ + 63, /* COLUMNKW => ID */ + 63, /* DO => ID */ + 63, /* FOR => ID */ + 63, /* IGNORE => ID */ + 63, /* INITIALLY => ID */ + 63, /* INSTEAD => ID */ + 63, /* NO => ID */ + 63, /* KEY => ID */ + 63, /* OF => ID */ + 63, /* OFFSET => ID */ + 63, /* PRAGMA => ID */ + 63, /* RAISE => ID */ + 63, /* RECURSIVE => ID */ + 63, /* REPLACE => ID */ + 63, /* RESTRICT => ID */ + 63, /* ROW => ID */ + 63, /* ROWS => ID */ + 63, /* TRIGGER => ID */ + 63, /* VACUUM => ID */ + 63, /* VIEW => ID */ + 63, /* VIRTUAL => ID */ + 63, /* WITH => ID */ + 63, /* NULLS => ID */ + 63, /* FIRST => ID */ + 63, /* LAST => ID */ + 63, /* CURRENT => ID */ + 63, /* FOLLOWING => ID */ + 63, /* PARTITION => ID */ + 63, /* PRECEDING => ID */ + 63, /* RANGE => ID */ + 63, /* UNBOUNDED => ID */ + 63, /* EXCLUDE => ID */ + 63, /* GROUPS => ID */ + 63, /* OTHERS => ID */ + 63, /* TIES => ID */ + 63, /* GENERATED => ID */ + 63, /* ALWAYS => ID */ + 63, /* MATERIALIZED => ID */ + 63, /* REINDEX => ID */ + 63, /* RENAME => ID */ + 63, /* CTIME_KW => ID */ 0, /* ANY => nothing */ 0, /* BITAND => nothing */ 0, /* BITOR => nothing */ @@ -169668,317 +173331,318 @@ static const char *const yyTokenName[] = { /* 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 */ "RANDOM", - /* 28 */ "ABORT", - /* 29 */ "ACTION", - /* 30 */ "AFTER", - /* 31 */ "ANALYZE", - /* 32 */ "ASC", - /* 33 */ "ATTACH", - /* 34 */ "BEFORE", - /* 35 */ "BY", - /* 36 */ "CASCADE", - /* 37 */ "CAST", - /* 38 */ "CONFLICT", - /* 39 */ "DATABASE", - /* 40 */ "DESC", - /* 41 */ "DETACH", - /* 42 */ "EACH", - /* 43 */ "FAIL", - /* 44 */ "FUNCTION", - /* 45 */ "LANGUAGE", - /* 46 */ "OR", - /* 47 */ "AND", - /* 48 */ "IS", - /* 49 */ "MATCH", - /* 50 */ "LIKE_KW", - /* 51 */ "BETWEEN", - /* 52 */ "IN", - /* 53 */ "ISNULL", - /* 54 */ "NOTNULL", - /* 55 */ "NE", - /* 56 */ "EQ", - /* 57 */ "GT", - /* 58 */ "LE", - /* 59 */ "LT", - /* 60 */ "GE", - /* 61 */ "ESCAPE", - /* 62 */ "ID", - /* 63 */ "COLUMNKW", - /* 64 */ "DO", - /* 65 */ "FOR", - /* 66 */ "IGNORE", - /* 67 */ "INITIALLY", - /* 68 */ "INSTEAD", - /* 69 */ "NO", - /* 70 */ "KEY", - /* 71 */ "OF", - /* 72 */ "OFFSET", - /* 73 */ "PRAGMA", - /* 74 */ "RAISE", - /* 75 */ "RECURSIVE", - /* 76 */ "REPLACE", - /* 77 */ "RESTRICT", - /* 78 */ "ROW", - /* 79 */ "ROWS", - /* 80 */ "TRIGGER", - /* 81 */ "VACUUM", - /* 82 */ "VIEW", - /* 83 */ "VIRTUAL", - /* 84 */ "WITH", - /* 85 */ "NULLS", - /* 86 */ "FIRST", - /* 87 */ "LAST", - /* 88 */ "CURRENT", - /* 89 */ "FOLLOWING", - /* 90 */ "PARTITION", - /* 91 */ "PRECEDING", - /* 92 */ "RANGE", - /* 93 */ "UNBOUNDED", - /* 94 */ "EXCLUDE", - /* 95 */ "GROUPS", - /* 96 */ "OTHERS", - /* 97 */ "TIES", - /* 98 */ "GENERATED", - /* 99 */ "ALWAYS", - /* 100 */ "MATERIALIZED", - /* 101 */ "REINDEX", - /* 102 */ "RENAME", - /* 103 */ "CTIME_KW", - /* 104 */ "ANY", - /* 105 */ "BITAND", - /* 106 */ "BITOR", - /* 107 */ "LSHIFT", - /* 108 */ "RSHIFT", - /* 109 */ "PLUS", - /* 110 */ "MINUS", - /* 111 */ "STAR", - /* 112 */ "SLASH", - /* 113 */ "REM", - /* 114 */ "CONCAT", - /* 115 */ "PTR", - /* 116 */ "COLLATE", - /* 117 */ "BITNOT", - /* 118 */ "ON", - /* 119 */ "INDEXED", - /* 120 */ "STRING", - /* 121 */ "JOIN_KW", - /* 122 */ "CONSTRAINT", - /* 123 */ "DEFAULT", - /* 124 */ "NULL", - /* 125 */ "PRIMARY", - /* 126 */ "UNIQUE", - /* 127 */ "CHECK", - /* 128 */ "REFERENCES", - /* 129 */ "AUTOINCR", - /* 130 */ "INSERT", - /* 131 */ "DELETE", - /* 132 */ "UPDATE", - /* 133 */ "SET", - /* 134 */ "DEFERRABLE", - /* 135 */ "FOREIGN", - /* 136 */ "DROP", - /* 137 */ "BLOB", - /* 138 */ "UNION", - /* 139 */ "ALL", - /* 140 */ "EXCEPT", - /* 141 */ "INTERSECT", - /* 142 */ "SELECT", - /* 143 */ "VALUES", - /* 144 */ "DISTINCT", - /* 145 */ "DOT", - /* 146 */ "FROM", - /* 147 */ "JOIN", - /* 148 */ "USING", - /* 149 */ "ORDER", - /* 150 */ "GROUP", - /* 151 */ "HAVING", - /* 152 */ "LIMIT", - /* 153 */ "WHERE", - /* 154 */ "RETURNING", - /* 155 */ "INTO", - /* 156 */ "NOTHING", - /* 157 */ "FLOAT", - /* 158 */ "INTEGER", - /* 159 */ "VARIABLE", - /* 160 */ "CASE", - /* 161 */ "WHEN", - /* 162 */ "THEN", - /* 163 */ "ELSE", - /* 164 */ "INDEX", - /* 165 */ "ALTER", - /* 166 */ "ADD", - /* 167 */ "WINDOW", - /* 168 */ "OVER", - /* 169 */ "FILTER", - /* 170 */ "COLUMN", - /* 171 */ "AGG_FUNCTION", - /* 172 */ "AGG_COLUMN", - /* 173 */ "TRUEFALSE", - /* 174 */ "ISNOT", - /* 175 */ "UMINUS", - /* 176 */ "UPLUS", - /* 177 */ "TRUTH", - /* 178 */ "REGISTER", - /* 179 */ "VECTOR", - /* 180 */ "SELECT_COLUMN", - /* 181 */ "IF_NULL_ROW", - /* 182 */ "ASTERISK", - /* 183 */ "SPAN", - /* 184 */ "ERROR", - /* 185 */ "SPACE", - /* 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 */ "sclp", - /* 257 */ "as", - /* 258 */ "seltablist", - /* 259 */ "stl_prefix", - /* 260 */ "joinop", - /* 261 */ "on_using", - /* 262 */ "indexed_by", - /* 263 */ "exprlist", - /* 264 */ "xfullname", - /* 265 */ "idlist", - /* 266 */ "indexed_opt", - /* 267 */ "nulls", - /* 268 */ "with", - /* 269 */ "where_opt_ret", - /* 270 */ "setlist", - /* 271 */ "insert_cmd", - /* 272 */ "idlist_opt", - /* 273 */ "upsert", - /* 274 */ "returning", - /* 275 */ "filter_over", - /* 276 */ "likeop", - /* 277 */ "between_op", - /* 278 */ "in_op", - /* 279 */ "paren_exprlist", - /* 280 */ "case_operand", - /* 281 */ "case_exprlist", - /* 282 */ "case_else", - /* 283 */ "uniqueflag", - /* 284 */ "collate", - /* 285 */ "vinto", - /* 286 */ "nmnum", - /* 287 */ "trigger_decl", - /* 288 */ "trigger_cmd_list", - /* 289 */ "trigger_time", - /* 290 */ "trigger_event", - /* 291 */ "foreach_clause", - /* 292 */ "when_clause", - /* 293 */ "trigger_cmd", - /* 294 */ "trnm", - /* 295 */ "tridxby", - /* 296 */ "database_kw_opt", - /* 297 */ "key_opt", - /* 298 */ "add_column_fullname", - /* 299 */ "kwcolumn_opt", - /* 300 */ "create_vtab", - /* 301 */ "vtabarglist", - /* 302 */ "vtabarg", - /* 303 */ "vtabargtoken", - /* 304 */ "lp", - /* 305 */ "anylist", - /* 306 */ "wqitem", - /* 307 */ "wqas", - /* 308 */ "windowdefn_list", - /* 309 */ "windowdefn", - /* 310 */ "window", - /* 311 */ "frame_opt", - /* 312 */ "part_opt", - /* 313 */ "filter_clause", - /* 314 */ "over_clause", - /* 315 */ "range_or_rows", - /* 316 */ "frame_bound", - /* 317 */ "frame_bound_s", - /* 318 */ "frame_bound_e", - /* 319 */ "frame_exclude_opt", - /* 320 */ "frame_exclude", + /* 10 */ "READONLY", + /* 11 */ "COMMIT", + /* 12 */ "END", + /* 13 */ "ROLLBACK", + /* 14 */ "SAVEPOINT", + /* 15 */ "RELEASE", + /* 16 */ "TO", + /* 17 */ "TABLE", + /* 18 */ "CREATE", + /* 19 */ "IF", + /* 20 */ "NOT", + /* 21 */ "EXISTS", + /* 22 */ "TEMP", + /* 23 */ "LP", + /* 24 */ "RP", + /* 25 */ "AS", + /* 26 */ "COMMA", + /* 27 */ "WITHOUT", + /* 28 */ "RANDOM", + /* 29 */ "ABORT", + /* 30 */ "ACTION", + /* 31 */ "AFTER", + /* 32 */ "ANALYZE", + /* 33 */ "ASC", + /* 34 */ "ATTACH", + /* 35 */ "BEFORE", + /* 36 */ "BY", + /* 37 */ "CASCADE", + /* 38 */ "CAST", + /* 39 */ "CONFLICT", + /* 40 */ "DATABASE", + /* 41 */ "DESC", + /* 42 */ "DETACH", + /* 43 */ "EACH", + /* 44 */ "FAIL", + /* 45 */ "FUNCTION", + /* 46 */ "LANGUAGE", + /* 47 */ "OR", + /* 48 */ "AND", + /* 49 */ "IS", + /* 50 */ "MATCH", + /* 51 */ "LIKE_KW", + /* 52 */ "BETWEEN", + /* 53 */ "IN", + /* 54 */ "ISNULL", + /* 55 */ "NOTNULL", + /* 56 */ "NE", + /* 57 */ "EQ", + /* 58 */ "GT", + /* 59 */ "LE", + /* 60 */ "LT", + /* 61 */ "GE", + /* 62 */ "ESCAPE", + /* 63 */ "ID", + /* 64 */ "COLUMNKW", + /* 65 */ "DO", + /* 66 */ "FOR", + /* 67 */ "IGNORE", + /* 68 */ "INITIALLY", + /* 69 */ "INSTEAD", + /* 70 */ "NO", + /* 71 */ "KEY", + /* 72 */ "OF", + /* 73 */ "OFFSET", + /* 74 */ "PRAGMA", + /* 75 */ "RAISE", + /* 76 */ "RECURSIVE", + /* 77 */ "REPLACE", + /* 78 */ "RESTRICT", + /* 79 */ "ROW", + /* 80 */ "ROWS", + /* 81 */ "TRIGGER", + /* 82 */ "VACUUM", + /* 83 */ "VIEW", + /* 84 */ "VIRTUAL", + /* 85 */ "WITH", + /* 86 */ "NULLS", + /* 87 */ "FIRST", + /* 88 */ "LAST", + /* 89 */ "CURRENT", + /* 90 */ "FOLLOWING", + /* 91 */ "PARTITION", + /* 92 */ "PRECEDING", + /* 93 */ "RANGE", + /* 94 */ "UNBOUNDED", + /* 95 */ "EXCLUDE", + /* 96 */ "GROUPS", + /* 97 */ "OTHERS", + /* 98 */ "TIES", + /* 99 */ "GENERATED", + /* 100 */ "ALWAYS", + /* 101 */ "MATERIALIZED", + /* 102 */ "REINDEX", + /* 103 */ "RENAME", + /* 104 */ "CTIME_KW", + /* 105 */ "ANY", + /* 106 */ "BITAND", + /* 107 */ "BITOR", + /* 108 */ "LSHIFT", + /* 109 */ "RSHIFT", + /* 110 */ "PLUS", + /* 111 */ "MINUS", + /* 112 */ "STAR", + /* 113 */ "SLASH", + /* 114 */ "REM", + /* 115 */ "CONCAT", + /* 116 */ "PTR", + /* 117 */ "COLLATE", + /* 118 */ "BITNOT", + /* 119 */ "ON", + /* 120 */ "INDEXED", + /* 121 */ "STRING", + /* 122 */ "JOIN_KW", + /* 123 */ "CONSTRAINT", + /* 124 */ "DEFAULT", + /* 125 */ "NULL", + /* 126 */ "PRIMARY", + /* 127 */ "UNIQUE", + /* 128 */ "CHECK", + /* 129 */ "REFERENCES", + /* 130 */ "AUTOINCR", + /* 131 */ "INSERT", + /* 132 */ "DELETE", + /* 133 */ "UPDATE", + /* 134 */ "SET", + /* 135 */ "DEFERRABLE", + /* 136 */ "FOREIGN", + /* 137 */ "DROP", + /* 138 */ "BLOB", + /* 139 */ "UNION", + /* 140 */ "ALL", + /* 141 */ "EXCEPT", + /* 142 */ "INTERSECT", + /* 143 */ "SELECT", + /* 144 */ "VALUES", + /* 145 */ "DISTINCT", + /* 146 */ "DOT", + /* 147 */ "FROM", + /* 148 */ "JOIN", + /* 149 */ "USING", + /* 150 */ "ORDER", + /* 151 */ "GROUP", + /* 152 */ "HAVING", + /* 153 */ "LIMIT", + /* 154 */ "WHERE", + /* 155 */ "RETURNING", + /* 156 */ "INTO", + /* 157 */ "NOTHING", + /* 158 */ "FLOAT", + /* 159 */ "INTEGER", + /* 160 */ "VARIABLE", + /* 161 */ "CASE", + /* 162 */ "WHEN", + /* 163 */ "THEN", + /* 164 */ "ELSE", + /* 165 */ "INDEX", + /* 166 */ "ALTER", + /* 167 */ "ADD", + /* 168 */ "WINDOW", + /* 169 */ "OVER", + /* 170 */ "FILTER", + /* 171 */ "COLUMN", + /* 172 */ "AGG_FUNCTION", + /* 173 */ "AGG_COLUMN", + /* 174 */ "TRUEFALSE", + /* 175 */ "ISNOT", + /* 176 */ "UMINUS", + /* 177 */ "UPLUS", + /* 178 */ "TRUTH", + /* 179 */ "REGISTER", + /* 180 */ "VECTOR", + /* 181 */ "SELECT_COLUMN", + /* 182 */ "IF_NULL_ROW", + /* 183 */ "ASTERISK", + /* 184 */ "SPAN", + /* 185 */ "ERROR", + /* 186 */ "SPACE", + /* 187 */ "ILLEGAL", + /* 188 */ "input", + /* 189 */ "cmdlist", + /* 190 */ "ecmd", + /* 191 */ "cmdx", + /* 192 */ "explain", + /* 193 */ "cmd", + /* 194 */ "transtype", + /* 195 */ "trans_opt", + /* 196 */ "nm", + /* 197 */ "savepoint_opt", + /* 198 */ "create_table", + /* 199 */ "create_table_args", + /* 200 */ "createkw", + /* 201 */ "temp", + /* 202 */ "ifnotexists", + /* 203 */ "dbnm", + /* 204 */ "columnlist", + /* 205 */ "conslist_opt", + /* 206 */ "table_option_set", + /* 207 */ "select", + /* 208 */ "table_option", + /* 209 */ "columnname", + /* 210 */ "carglist", + /* 211 */ "typetoken", + /* 212 */ "typename", + /* 213 */ "signed", + /* 214 */ "plus_num", + /* 215 */ "minus_num", + /* 216 */ "scanpt", + /* 217 */ "scantok", + /* 218 */ "ccons", + /* 219 */ "term", + /* 220 */ "expr", + /* 221 */ "onconf", + /* 222 */ "sortorder", + /* 223 */ "autoinc", + /* 224 */ "eidlist_opt", + /* 225 */ "refargs", + /* 226 */ "defer_subclause", + /* 227 */ "generated", + /* 228 */ "refarg", + /* 229 */ "refact", + /* 230 */ "init_deferred_pred_opt", + /* 231 */ "conslist", + /* 232 */ "tconscomma", + /* 233 */ "tcons", + /* 234 */ "sortlist", + /* 235 */ "eidlist", + /* 236 */ "defer_subclause_opt", + /* 237 */ "orconf", + /* 238 */ "resolvetype", + /* 239 */ "raisetype", + /* 240 */ "ifexists", + /* 241 */ "fullname", + /* 242 */ "selectnowith", + /* 243 */ "oneselect", + /* 244 */ "wqlist", + /* 245 */ "multiselect_op", + /* 246 */ "distinct", + /* 247 */ "selcollist", + /* 248 */ "from", + /* 249 */ "where_opt", + /* 250 */ "groupby_opt", + /* 251 */ "having_opt", + /* 252 */ "orderby_opt", + /* 253 */ "limit_opt", + /* 254 */ "window_clause", + /* 255 */ "values", + /* 256 */ "nexprlist", + /* 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 */ "windowdefn_list", + /* 310 */ "windowdefn", + /* 311 */ "window", + /* 312 */ "frame_opt", + /* 313 */ "part_opt", + /* 314 */ "filter_clause", + /* 315 */ "over_clause", + /* 316 */ "range_or_rows", + /* 317 */ "frame_bound", + /* 318 */ "frame_bound_s", + /* 319 */ "frame_bound_e", + /* 320 */ "frame_exclude_opt", + /* 321 */ "frame_exclude", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -169994,182 +173658,182 @@ static const char *const yyRuleName[] = { /* 5 */ "transtype ::= DEFERRED", /* 6 */ "transtype ::= IMMEDIATE", /* 7 */ "transtype ::= EXCLUSIVE", - /* 8 */ "cmd ::= COMMIT|END trans_opt", - /* 9 */ "cmd ::= ROLLBACK trans_opt", - /* 10 */ "cmd ::= SAVEPOINT nm", - /* 11 */ "cmd ::= RELEASE savepoint_opt nm", - /* 12 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm", - /* 13 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm", - /* 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", - /* 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 ::= RANDOM nm", - /* 25 */ "table_option ::= nm", - /* 26 */ "columnname ::= nm typetoken", - /* 27 */ "typetoken ::=", - /* 28 */ "typetoken ::= typename LP signed RP", - /* 29 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 30 */ "typename ::= typename ID|STRING", - /* 31 */ "scanpt ::=", - /* 32 */ "scantok ::=", - /* 33 */ "ccons ::= CONSTRAINT nm", - /* 34 */ "ccons ::= DEFAULT scantok term", - /* 35 */ "ccons ::= DEFAULT LP expr RP", - /* 36 */ "ccons ::= DEFAULT PLUS scantok term", - /* 37 */ "ccons ::= DEFAULT MINUS scantok term", - /* 38 */ "ccons ::= DEFAULT scantok ID|INDEXED", - /* 39 */ "ccons ::= NOT NULL onconf", - /* 40 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 41 */ "ccons ::= UNIQUE onconf", - /* 42 */ "ccons ::= CHECK LP expr RP", - /* 43 */ "ccons ::= REFERENCES nm eidlist_opt refargs", - /* 44 */ "ccons ::= defer_subclause", - /* 45 */ "ccons ::= COLLATE ID|STRING", - /* 46 */ "generated ::= LP expr RP", - /* 47 */ "generated ::= LP expr RP ID", - /* 48 */ "autoinc ::=", - /* 49 */ "autoinc ::= AUTOINCR", - /* 50 */ "refargs ::=", - /* 51 */ "refargs ::= refargs refarg", - /* 52 */ "refarg ::= MATCH nm", - /* 53 */ "refarg ::= ON INSERT refact", - /* 54 */ "refarg ::= ON DELETE refact", - /* 55 */ "refarg ::= ON UPDATE refact", - /* 56 */ "refact ::= SET NULL", - /* 57 */ "refact ::= SET DEFAULT", - /* 58 */ "refact ::= CASCADE", - /* 59 */ "refact ::= RESTRICT", - /* 60 */ "refact ::= NO ACTION", - /* 61 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 62 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 63 */ "init_deferred_pred_opt ::=", - /* 64 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 65 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 66 */ "conslist_opt ::=", - /* 67 */ "tconscomma ::= COMMA", - /* 68 */ "tcons ::= CONSTRAINT nm", - /* 69 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", - /* 70 */ "tcons ::= UNIQUE LP sortlist RP onconf", - /* 71 */ "tcons ::= CHECK LP expr RP onconf", - /* 72 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", - /* 73 */ "defer_subclause_opt ::=", - /* 74 */ "onconf ::=", - /* 75 */ "onconf ::= ON CONFLICT resolvetype", - /* 76 */ "orconf ::=", - /* 77 */ "orconf ::= OR resolvetype", - /* 78 */ "resolvetype ::= IGNORE", - /* 79 */ "resolvetype ::= REPLACE", - /* 80 */ "cmd ::= DROP TABLE ifexists fullname", - /* 81 */ "ifexists ::= IF EXISTS", - /* 82 */ "ifexists ::=", - /* 83 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", - /* 84 */ "cmd ::= DROP VIEW ifexists fullname", - /* 85 */ "cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING", - /* 86 */ "cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB", - /* 87 */ "cmd ::= DROP FUNCTION ifexists nm", - /* 88 */ "cmd ::= select", - /* 89 */ "select ::= WITH wqlist selectnowith", - /* 90 */ "select ::= WITH RECURSIVE wqlist selectnowith", - /* 91 */ "select ::= selectnowith", - /* 92 */ "selectnowith ::= selectnowith multiselect_op oneselect", - /* 93 */ "multiselect_op ::= UNION", - /* 94 */ "multiselect_op ::= UNION ALL", - /* 95 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 96 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 97 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt", - /* 98 */ "values ::= VALUES LP nexprlist RP", - /* 99 */ "values ::= values COMMA LP nexprlist RP", - /* 100 */ "distinct ::= DISTINCT", - /* 101 */ "distinct ::= ALL", - /* 102 */ "distinct ::=", - /* 103 */ "sclp ::=", - /* 104 */ "selcollist ::= sclp scanpt expr scanpt as", - /* 105 */ "selcollist ::= sclp scanpt STAR", - /* 106 */ "selcollist ::= sclp scanpt nm DOT STAR", - /* 107 */ "as ::= AS nm", - /* 108 */ "as ::=", - /* 109 */ "from ::=", - /* 110 */ "from ::= FROM seltablist", - /* 111 */ "stl_prefix ::= seltablist joinop", - /* 112 */ "stl_prefix ::=", - /* 113 */ "seltablist ::= stl_prefix nm dbnm as on_using", - /* 114 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", - /* 115 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", - /* 116 */ "seltablist ::= stl_prefix LP select RP as on_using", - /* 117 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", - /* 118 */ "dbnm ::=", - /* 119 */ "dbnm ::= DOT nm", - /* 120 */ "fullname ::= nm", - /* 121 */ "fullname ::= nm DOT nm", - /* 122 */ "xfullname ::= nm", - /* 123 */ "xfullname ::= nm DOT nm", - /* 124 */ "xfullname ::= nm DOT nm AS nm", - /* 125 */ "xfullname ::= nm AS nm", - /* 126 */ "joinop ::= COMMA|JOIN", - /* 127 */ "joinop ::= JOIN_KW JOIN", - /* 128 */ "joinop ::= JOIN_KW nm JOIN", - /* 129 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 130 */ "on_using ::= ON expr", - /* 131 */ "on_using ::= USING LP idlist RP", - /* 132 */ "on_using ::=", - /* 133 */ "indexed_opt ::=", - /* 134 */ "indexed_by ::= INDEXED BY nm", - /* 135 */ "indexed_by ::= NOT INDEXED", - /* 136 */ "orderby_opt ::=", - /* 137 */ "orderby_opt ::= ORDER BY sortlist", - /* 138 */ "sortlist ::= sortlist COMMA expr sortorder nulls", - /* 139 */ "sortlist ::= expr sortorder nulls", - /* 140 */ "sortorder ::= ASC", - /* 141 */ "sortorder ::= DESC", - /* 142 */ "sortorder ::=", - /* 143 */ "nulls ::= NULLS FIRST", - /* 144 */ "nulls ::= NULLS LAST", - /* 145 */ "nulls ::=", - /* 146 */ "groupby_opt ::=", - /* 147 */ "groupby_opt ::= GROUP BY nexprlist", - /* 148 */ "having_opt ::=", - /* 149 */ "having_opt ::= HAVING expr", - /* 150 */ "limit_opt ::=", - /* 151 */ "limit_opt ::= LIMIT expr", - /* 152 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 153 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 154 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret", - /* 155 */ "where_opt ::=", - /* 156 */ "where_opt ::= WHERE expr", - /* 157 */ "where_opt_ret ::=", - /* 158 */ "where_opt_ret ::= WHERE expr", - /* 159 */ "where_opt_ret ::= RETURNING selcollist", - /* 160 */ "where_opt_ret ::= WHERE expr RETURNING selcollist", - /* 161 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret", - /* 162 */ "setlist ::= setlist COMMA nm EQ expr", - /* 163 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 164 */ "setlist ::= nm EQ expr", - /* 165 */ "setlist ::= LP idlist RP EQ expr", - /* 166 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", - /* 167 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning", - /* 168 */ "upsert ::=", - /* 169 */ "upsert ::= RETURNING selcollist", - /* 170 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert", - /* 171 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert", - /* 172 */ "upsert ::= ON CONFLICT DO NOTHING returning", - /* 173 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning", - /* 174 */ "returning ::= RETURNING selcollist", - /* 175 */ "insert_cmd ::= INSERT orconf", - /* 176 */ "insert_cmd ::= REPLACE", - /* 177 */ "idlist_opt ::=", - /* 178 */ "idlist_opt ::= LP idlist RP", - /* 179 */ "idlist ::= idlist COMMA nm", - /* 180 */ "idlist ::= nm", - /* 181 */ "expr ::= LP expr RP", - /* 182 */ "expr ::= ID|INDEXED", - /* 183 */ "expr ::= JOIN_KW", + /* 8 */ "transtype ::= READONLY", + /* 9 */ "cmd ::= COMMIT|END trans_opt", + /* 10 */ "cmd ::= ROLLBACK trans_opt", + /* 11 */ "cmd ::= SAVEPOINT nm", + /* 12 */ "cmd ::= RELEASE savepoint_opt nm", + /* 13 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm", + /* 14 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm", + /* 15 */ "createkw ::= CREATE", + /* 16 */ "ifnotexists ::=", + /* 17 */ "ifnotexists ::= IF NOT EXISTS", + /* 18 */ "temp ::= TEMP", + /* 19 */ "temp ::=", + /* 20 */ "create_table_args ::= LP columnlist conslist_opt RP table_option_set", + /* 21 */ "create_table_args ::= AS select", + /* 22 */ "table_option_set ::=", + /* 23 */ "table_option_set ::= table_option_set COMMA table_option", + /* 24 */ "table_option ::= WITHOUT nm", + /* 25 */ "table_option ::= RANDOM nm", + /* 26 */ "table_option ::= nm", + /* 27 */ "columnname ::= nm typetoken", + /* 28 */ "typetoken ::=", + /* 29 */ "typetoken ::= typename LP signed RP", + /* 30 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 31 */ "typename ::= typename ID|STRING", + /* 32 */ "scanpt ::=", + /* 33 */ "scantok ::=", + /* 34 */ "ccons ::= CONSTRAINT nm", + /* 35 */ "ccons ::= DEFAULT scantok term", + /* 36 */ "ccons ::= DEFAULT LP expr RP", + /* 37 */ "ccons ::= DEFAULT PLUS scantok term", + /* 38 */ "ccons ::= DEFAULT MINUS scantok term", + /* 39 */ "ccons ::= DEFAULT scantok ID|INDEXED", + /* 40 */ "ccons ::= NOT NULL onconf", + /* 41 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 42 */ "ccons ::= UNIQUE onconf", + /* 43 */ "ccons ::= CHECK LP expr RP", + /* 44 */ "ccons ::= REFERENCES nm eidlist_opt refargs", + /* 45 */ "ccons ::= defer_subclause", + /* 46 */ "ccons ::= COLLATE ID|STRING", + /* 47 */ "generated ::= LP expr RP", + /* 48 */ "generated ::= LP expr RP ID", + /* 49 */ "autoinc ::=", + /* 50 */ "autoinc ::= AUTOINCR", + /* 51 */ "refargs ::=", + /* 52 */ "refargs ::= refargs refarg", + /* 53 */ "refarg ::= MATCH nm", + /* 54 */ "refarg ::= ON INSERT refact", + /* 55 */ "refarg ::= ON DELETE refact", + /* 56 */ "refarg ::= ON UPDATE refact", + /* 57 */ "refact ::= SET NULL", + /* 58 */ "refact ::= SET DEFAULT", + /* 59 */ "refact ::= CASCADE", + /* 60 */ "refact ::= RESTRICT", + /* 61 */ "refact ::= NO ACTION", + /* 62 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 63 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 64 */ "init_deferred_pred_opt ::=", + /* 65 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 66 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 67 */ "conslist_opt ::=", + /* 68 */ "tconscomma ::= COMMA", + /* 69 */ "tcons ::= CONSTRAINT nm", + /* 70 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", + /* 71 */ "tcons ::= UNIQUE LP sortlist RP onconf", + /* 72 */ "tcons ::= CHECK LP expr RP onconf", + /* 73 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", + /* 74 */ "defer_subclause_opt ::=", + /* 75 */ "onconf ::=", + /* 76 */ "onconf ::= ON CONFLICT resolvetype", + /* 77 */ "orconf ::=", + /* 78 */ "orconf ::= OR resolvetype", + /* 79 */ "resolvetype ::= IGNORE", + /* 80 */ "resolvetype ::= REPLACE", + /* 81 */ "cmd ::= DROP TABLE ifexists fullname", + /* 82 */ "ifexists ::= IF EXISTS", + /* 83 */ "ifexists ::=", + /* 84 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", + /* 85 */ "cmd ::= DROP VIEW ifexists fullname", + /* 86 */ "cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING", + /* 87 */ "cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB", + /* 88 */ "cmd ::= DROP FUNCTION ifexists nm", + /* 89 */ "cmd ::= select", + /* 90 */ "select ::= WITH wqlist selectnowith", + /* 91 */ "select ::= WITH RECURSIVE wqlist selectnowith", + /* 92 */ "select ::= selectnowith", + /* 93 */ "selectnowith ::= selectnowith multiselect_op oneselect", + /* 94 */ "multiselect_op ::= UNION", + /* 95 */ "multiselect_op ::= UNION ALL", + /* 96 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 97 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 98 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt", + /* 99 */ "values ::= VALUES LP nexprlist RP", + /* 100 */ "values ::= values COMMA LP nexprlist RP", + /* 101 */ "distinct ::= DISTINCT", + /* 102 */ "distinct ::= ALL", + /* 103 */ "distinct ::=", + /* 104 */ "sclp ::=", + /* 105 */ "selcollist ::= sclp scanpt expr scanpt as", + /* 106 */ "selcollist ::= sclp scanpt STAR", + /* 107 */ "selcollist ::= sclp scanpt nm DOT STAR", + /* 108 */ "as ::= AS nm", + /* 109 */ "as ::=", + /* 110 */ "from ::=", + /* 111 */ "from ::= FROM seltablist", + /* 112 */ "stl_prefix ::= seltablist joinop", + /* 113 */ "stl_prefix ::=", + /* 114 */ "seltablist ::= stl_prefix nm dbnm as on_using", + /* 115 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", + /* 116 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", + /* 117 */ "seltablist ::= stl_prefix LP select RP as on_using", + /* 118 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", + /* 119 */ "dbnm ::=", + /* 120 */ "dbnm ::= DOT nm", + /* 121 */ "fullname ::= nm", + /* 122 */ "fullname ::= nm DOT nm", + /* 123 */ "xfullname ::= nm", + /* 124 */ "xfullname ::= nm DOT nm", + /* 125 */ "xfullname ::= nm DOT nm AS nm", + /* 126 */ "xfullname ::= nm AS nm", + /* 127 */ "joinop ::= COMMA|JOIN", + /* 128 */ "joinop ::= JOIN_KW JOIN", + /* 129 */ "joinop ::= JOIN_KW nm JOIN", + /* 130 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 131 */ "on_using ::= ON expr", + /* 132 */ "on_using ::= USING LP idlist RP", + /* 133 */ "on_using ::=", + /* 134 */ "indexed_opt ::=", + /* 135 */ "indexed_by ::= INDEXED BY nm", + /* 136 */ "indexed_by ::= NOT INDEXED", + /* 137 */ "orderby_opt ::=", + /* 138 */ "orderby_opt ::= ORDER BY sortlist", + /* 139 */ "sortlist ::= sortlist COMMA expr sortorder nulls", + /* 140 */ "sortlist ::= expr sortorder nulls", + /* 141 */ "sortorder ::= ASC", + /* 142 */ "sortorder ::= DESC", + /* 143 */ "sortorder ::=", + /* 144 */ "nulls ::= NULLS FIRST", + /* 145 */ "nulls ::= NULLS LAST", + /* 146 */ "nulls ::=", + /* 147 */ "groupby_opt ::=", + /* 148 */ "groupby_opt ::= GROUP BY nexprlist", + /* 149 */ "having_opt ::=", + /* 150 */ "having_opt ::= HAVING expr", + /* 151 */ "limit_opt ::=", + /* 152 */ "limit_opt ::= LIMIT expr", + /* 153 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 154 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 155 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret", + /* 156 */ "where_opt ::=", + /* 157 */ "where_opt ::= WHERE expr", + /* 158 */ "where_opt_ret ::=", + /* 159 */ "where_opt_ret ::= WHERE expr", + /* 160 */ "where_opt_ret ::= RETURNING selcollist", + /* 161 */ "where_opt_ret ::= WHERE expr RETURNING selcollist", + /* 162 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret", + /* 163 */ "setlist ::= setlist COMMA nm EQ expr", + /* 164 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 165 */ "setlist ::= nm EQ expr", + /* 166 */ "setlist ::= LP idlist RP EQ expr", + /* 167 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", + /* 168 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning", + /* 169 */ "upsert ::=", + /* 170 */ "upsert ::= RETURNING selcollist", + /* 171 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert", + /* 172 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert", + /* 173 */ "upsert ::= ON CONFLICT DO NOTHING returning", + /* 174 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning", + /* 175 */ "returning ::= RETURNING selcollist", + /* 176 */ "insert_cmd ::= INSERT orconf", + /* 177 */ "insert_cmd ::= REPLACE", + /* 178 */ "idlist_opt ::=", + /* 179 */ "idlist_opt ::= LP idlist RP", + /* 180 */ "idlist ::= idlist COMMA nm", + /* 181 */ "idlist ::= nm", + /* 182 */ "expr ::= LP expr RP", + /* 183 */ "expr ::= ID|INDEXED|JOIN_KW", /* 184 */ "expr ::= nm DOT nm", /* 185 */ "expr ::= nm DOT nm DOT nm", /* 186 */ "term ::= NULL|FLOAT|BLOB", @@ -170178,137 +173842,137 @@ static const char *const yyRuleName[] = { /* 189 */ "expr ::= VARIABLE", /* 190 */ "expr ::= expr COLLATE ID|STRING", /* 191 */ "expr ::= CAST LP expr AS typetoken RP", - /* 192 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 193 */ "expr ::= ID|INDEXED LP STAR RP", - /* 194 */ "expr ::= ID|INDEXED LP distinct exprlist RP filter_over", - /* 195 */ "expr ::= ID|INDEXED LP STAR RP filter_over", - /* 196 */ "term ::= CTIME_KW", - /* 197 */ "expr ::= LP nexprlist COMMA expr RP", - /* 198 */ "expr ::= expr AND expr", - /* 199 */ "expr ::= expr OR expr", - /* 200 */ "expr ::= expr LT|GT|GE|LE expr", - /* 201 */ "expr ::= expr EQ|NE expr", - /* 202 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 203 */ "expr ::= expr PLUS|MINUS expr", - /* 204 */ "expr ::= expr STAR|SLASH|REM expr", - /* 205 */ "expr ::= expr CONCAT expr", - /* 206 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 207 */ "expr ::= expr likeop expr", - /* 208 */ "expr ::= expr likeop expr ESCAPE expr", - /* 209 */ "expr ::= expr ISNULL|NOTNULL", - /* 210 */ "expr ::= expr NOT NULL", - /* 211 */ "expr ::= expr IS expr", - /* 212 */ "expr ::= expr IS NOT expr", - /* 213 */ "expr ::= expr IS NOT DISTINCT FROM expr", - /* 214 */ "expr ::= expr IS DISTINCT FROM expr", - /* 215 */ "expr ::= NOT expr", - /* 216 */ "expr ::= BITNOT expr", - /* 217 */ "expr ::= PLUS|MINUS expr", - /* 218 */ "expr ::= expr PTR expr", - /* 219 */ "between_op ::= BETWEEN", - /* 220 */ "between_op ::= NOT BETWEEN", - /* 221 */ "expr ::= expr between_op expr AND expr", - /* 222 */ "in_op ::= IN", - /* 223 */ "in_op ::= NOT IN", - /* 224 */ "expr ::= expr in_op LP exprlist RP", - /* 225 */ "expr ::= LP select RP", - /* 226 */ "expr ::= expr in_op LP select RP", - /* 227 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 228 */ "expr ::= EXISTS LP select RP", - /* 229 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 230 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 231 */ "case_exprlist ::= WHEN expr THEN expr", - /* 232 */ "case_else ::= ELSE expr", - /* 233 */ "case_else ::=", - /* 234 */ "case_operand ::= expr", - /* 235 */ "case_operand ::=", - /* 236 */ "exprlist ::=", - /* 237 */ "nexprlist ::= nexprlist COMMA expr", - /* 238 */ "nexprlist ::= expr", - /* 239 */ "paren_exprlist ::=", - /* 240 */ "paren_exprlist ::= LP exprlist RP", - /* 241 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 242 */ "uniqueflag ::= UNIQUE", - /* 243 */ "uniqueflag ::=", - /* 244 */ "eidlist_opt ::=", - /* 245 */ "eidlist_opt ::= LP eidlist RP", - /* 246 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 247 */ "eidlist ::= nm collate sortorder", - /* 248 */ "collate ::=", - /* 249 */ "collate ::= COLLATE ID|STRING", - /* 250 */ "cmd ::= DROP INDEX ifexists fullname", - /* 251 */ "cmd ::= VACUUM vinto", - /* 252 */ "cmd ::= VACUUM nm vinto", - /* 253 */ "vinto ::= INTO expr", - /* 254 */ "vinto ::=", - /* 255 */ "cmd ::= PRAGMA nm dbnm", - /* 256 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 257 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 258 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 259 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 260 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 261 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 262 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 263 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 264 */ "trigger_time ::= BEFORE|AFTER", - /* 265 */ "trigger_time ::= INSTEAD OF", - /* 266 */ "trigger_time ::=", - /* 267 */ "trigger_event ::= DELETE|INSERT", - /* 268 */ "trigger_event ::= UPDATE", - /* 269 */ "trigger_event ::= UPDATE OF idlist", - /* 270 */ "when_clause ::=", - /* 271 */ "when_clause ::= WHEN expr", - /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 273 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 274 */ "trnm ::= nm DOT nm", - /* 275 */ "tridxby ::= INDEXED BY nm", - /* 276 */ "tridxby ::= NOT INDEXED", - /* 277 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", - /* 278 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", - /* 279 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", - /* 280 */ "trigger_cmd ::= scanpt select scanpt", - /* 281 */ "expr ::= RAISE LP IGNORE RP", - /* 282 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 283 */ "raisetype ::= ROLLBACK", - /* 284 */ "raisetype ::= ABORT", - /* 285 */ "raisetype ::= FAIL", - /* 286 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 287 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 288 */ "cmd ::= DETACH database_kw_opt expr", - /* 289 */ "key_opt ::=", - /* 290 */ "key_opt ::= KEY expr", - /* 291 */ "cmd ::= REINDEX", - /* 292 */ "cmd ::= REINDEX nm dbnm", - /* 293 */ "cmd ::= ANALYZE", - /* 294 */ "cmd ::= ANALYZE nm dbnm", - /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 297 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 298 */ "add_column_fullname ::= fullname", - /* 299 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 300 */ "cmd ::= create_vtab", - /* 301 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 302 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 303 */ "vtabarg ::=", - /* 304 */ "vtabargtoken ::= ANY", - /* 305 */ "vtabargtoken ::= lp anylist RP", - /* 306 */ "lp ::= LP", - /* 307 */ "with ::= WITH wqlist", - /* 308 */ "with ::= WITH RECURSIVE wqlist", - /* 309 */ "wqas ::= AS", - /* 310 */ "wqas ::= AS MATERIALIZED", - /* 311 */ "wqas ::= AS NOT MATERIALIZED", - /* 312 */ "wqitem ::= nm eidlist_opt wqas LP select RP", - /* 313 */ "wqlist ::= wqitem", - /* 314 */ "wqlist ::= wqlist COMMA wqitem", - /* 315 */ "windowdefn_list ::= windowdefn", - /* 316 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 317 */ "windowdefn ::= nm AS LP window RP", - /* 318 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 319 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 320 */ "window ::= ORDER BY sortlist frame_opt", - /* 321 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 322 */ "window ::= frame_opt", + /* 192 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP", + /* 193 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP", + /* 194 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP", + /* 195 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over", + /* 196 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over", + /* 197 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over", + /* 198 */ "term ::= CTIME_KW", + /* 199 */ "expr ::= LP nexprlist COMMA expr RP", + /* 200 */ "expr ::= expr AND expr", + /* 201 */ "expr ::= expr OR expr", + /* 202 */ "expr ::= expr LT|GT|GE|LE expr", + /* 203 */ "expr ::= expr EQ|NE expr", + /* 204 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 205 */ "expr ::= expr PLUS|MINUS expr", + /* 206 */ "expr ::= expr STAR|SLASH|REM expr", + /* 207 */ "expr ::= expr CONCAT expr", + /* 208 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 209 */ "expr ::= expr likeop expr", + /* 210 */ "expr ::= expr likeop expr ESCAPE expr", + /* 211 */ "expr ::= expr ISNULL|NOTNULL", + /* 212 */ "expr ::= expr NOT NULL", + /* 213 */ "expr ::= expr IS expr", + /* 214 */ "expr ::= expr IS NOT expr", + /* 215 */ "expr ::= expr IS NOT DISTINCT FROM expr", + /* 216 */ "expr ::= expr IS DISTINCT FROM expr", + /* 217 */ "expr ::= NOT expr", + /* 218 */ "expr ::= BITNOT expr", + /* 219 */ "expr ::= PLUS|MINUS expr", + /* 220 */ "expr ::= expr PTR expr", + /* 221 */ "between_op ::= BETWEEN", + /* 222 */ "between_op ::= NOT BETWEEN", + /* 223 */ "expr ::= expr between_op expr AND expr", + /* 224 */ "in_op ::= IN", + /* 225 */ "in_op ::= NOT IN", + /* 226 */ "expr ::= expr in_op LP exprlist RP", + /* 227 */ "expr ::= LP select RP", + /* 228 */ "expr ::= expr in_op LP select RP", + /* 229 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 230 */ "expr ::= EXISTS LP select RP", + /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 233 */ "case_exprlist ::= WHEN expr THEN expr", + /* 234 */ "case_else ::= ELSE expr", + /* 235 */ "case_else ::=", + /* 236 */ "case_operand ::=", + /* 237 */ "exprlist ::=", + /* 238 */ "nexprlist ::= nexprlist COMMA expr", + /* 239 */ "nexprlist ::= expr", + /* 240 */ "paren_exprlist ::=", + /* 241 */ "paren_exprlist ::= LP exprlist RP", + /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 243 */ "uniqueflag ::= UNIQUE", + /* 244 */ "uniqueflag ::=", + /* 245 */ "eidlist_opt ::=", + /* 246 */ "eidlist_opt ::= LP eidlist RP", + /* 247 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 248 */ "eidlist ::= nm collate sortorder", + /* 249 */ "collate ::=", + /* 250 */ "collate ::= COLLATE ID|STRING", + /* 251 */ "cmd ::= DROP INDEX ifexists fullname", + /* 252 */ "cmd ::= VACUUM vinto", + /* 253 */ "cmd ::= VACUUM nm vinto", + /* 254 */ "vinto ::= INTO expr", + /* 255 */ "vinto ::=", + /* 256 */ "cmd ::= PRAGMA nm dbnm", + /* 257 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 258 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 259 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 260 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 261 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 262 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 263 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 264 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 265 */ "trigger_time ::= BEFORE|AFTER", + /* 266 */ "trigger_time ::= INSTEAD OF", + /* 267 */ "trigger_time ::=", + /* 268 */ "trigger_event ::= DELETE|INSERT", + /* 269 */ "trigger_event ::= UPDATE", + /* 270 */ "trigger_event ::= UPDATE OF idlist", + /* 271 */ "when_clause ::=", + /* 272 */ "when_clause ::= WHEN expr", + /* 273 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 274 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 275 */ "trnm ::= nm DOT nm", + /* 276 */ "tridxby ::= INDEXED BY nm", + /* 277 */ "tridxby ::= NOT INDEXED", + /* 278 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", + /* 279 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", + /* 280 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", + /* 281 */ "trigger_cmd ::= scanpt select scanpt", + /* 282 */ "expr ::= RAISE LP IGNORE RP", + /* 283 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 284 */ "raisetype ::= ROLLBACK", + /* 285 */ "raisetype ::= ABORT", + /* 286 */ "raisetype ::= FAIL", + /* 287 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 288 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 289 */ "cmd ::= DETACH database_kw_opt expr", + /* 290 */ "key_opt ::=", + /* 291 */ "key_opt ::= KEY expr", + /* 292 */ "cmd ::= REINDEX", + /* 293 */ "cmd ::= REINDEX nm dbnm", + /* 294 */ "cmd ::= ANALYZE", + /* 295 */ "cmd ::= ANALYZE nm dbnm", + /* 296 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 297 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 298 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", + /* 299 */ "add_column_fullname ::= fullname", + /* 300 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", + /* 301 */ "cmd ::= ALTER TABLE fullname ALTER COLUMNKW columnname TO columnname carglist", + /* 302 */ "cmd ::= create_vtab", + /* 303 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 304 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 305 */ "vtabarg ::=", + /* 306 */ "vtabargtoken ::= ANY", + /* 307 */ "vtabargtoken ::= lp anylist RP", + /* 308 */ "lp ::= LP", + /* 309 */ "with ::= WITH wqlist", + /* 310 */ "with ::= WITH RECURSIVE wqlist", + /* 311 */ "wqas ::= AS", + /* 312 */ "wqas ::= AS MATERIALIZED", + /* 313 */ "wqas ::= AS NOT MATERIALIZED", + /* 314 */ "wqitem ::= nm eidlist_opt wqas LP select RP", + /* 315 */ "wqlist ::= wqitem", + /* 316 */ "wqlist ::= wqlist COMMA wqitem", + /* 317 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", + /* 318 */ "windowdefn ::= nm AS LP window RP", + /* 319 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 320 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 321 */ "window ::= ORDER BY sortlist frame_opt", + /* 322 */ "window ::= nm ORDER BY sortlist frame_opt", /* 323 */ "window ::= nm frame_opt", /* 324 */ "frame_opt ::=", /* 325 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", @@ -170347,32 +174011,32 @@ static const char *const yyRuleName[] = { /* 358 */ "table_option_set ::= table_option", /* 359 */ "columnlist ::= columnlist COMMA columnname carglist", /* 360 */ "columnlist ::= columnname carglist", - /* 361 */ "nm ::= ID|INDEXED", + /* 361 */ "nm ::= ID|INDEXED|JOIN_KW", /* 362 */ "nm ::= STRING", - /* 363 */ "nm ::= JOIN_KW", - /* 364 */ "typetoken ::= typename", - /* 365 */ "typename ::= ID|STRING", - /* 366 */ "signed ::= plus_num", - /* 367 */ "signed ::= minus_num", - /* 368 */ "carglist ::= carglist ccons", - /* 369 */ "carglist ::=", - /* 370 */ "ccons ::= NULL onconf", - /* 371 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 372 */ "ccons ::= AS generated", - /* 373 */ "conslist_opt ::= COMMA conslist", - /* 374 */ "conslist ::= conslist tconscomma tcons", - /* 375 */ "conslist ::= tcons", - /* 376 */ "tconscomma ::=", - /* 377 */ "defer_subclause_opt ::= defer_subclause", - /* 378 */ "resolvetype ::= raisetype", - /* 379 */ "selectnowith ::= oneselect", - /* 380 */ "oneselect ::= values", - /* 381 */ "sclp ::= selcollist COMMA", - /* 382 */ "as ::= ID|STRING", - /* 383 */ "indexed_opt ::= indexed_by", - /* 384 */ "returning ::=", - /* 385 */ "expr ::= term", - /* 386 */ "likeop ::= LIKE_KW|MATCH", + /* 363 */ "typetoken ::= typename", + /* 364 */ "typename ::= ID|STRING", + /* 365 */ "signed ::= plus_num", + /* 366 */ "signed ::= minus_num", + /* 367 */ "carglist ::= carglist ccons", + /* 368 */ "carglist ::=", + /* 369 */ "ccons ::= NULL onconf", + /* 370 */ "ccons ::= GENERATED ALWAYS AS generated", + /* 371 */ "ccons ::= AS generated", + /* 372 */ "conslist_opt ::= COMMA conslist", + /* 373 */ "conslist ::= conslist tconscomma tcons", + /* 374 */ "conslist ::= tcons", + /* 375 */ "tconscomma ::=", + /* 376 */ "defer_subclause_opt ::= defer_subclause", + /* 377 */ "resolvetype ::= raisetype", + /* 378 */ "selectnowith ::= oneselect", + /* 379 */ "oneselect ::= values", + /* 380 */ "sclp ::= selcollist COMMA", + /* 381 */ "as ::= ID|STRING", + /* 382 */ "indexed_opt ::= indexed_by", + /* 383 */ "returning ::=", + /* 384 */ "expr ::= term", + /* 385 */ "likeop ::= LIKE_KW|MATCH", + /* 386 */ "case_operand ::= expr", /* 387 */ "exprlist ::= nexprlist", /* 388 */ "nmnum ::= plus_num", /* 389 */ "nmnum ::= nm", @@ -170395,6 +174059,8 @@ static const char *const yyRuleName[] = { /* 406 */ "anylist ::= anylist LP anylist RP", /* 407 */ "anylist ::= anylist ANY", /* 408 */ "with ::=", + /* 409 */ "windowdefn_list ::= windowdefn", + /* 410 */ "window ::= frame_opt", }; #endif /* NDEBUG */ @@ -170520,97 +174186,97 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 206: /* select */ - case 241: /* selectnowith */ - case 242: /* oneselect */ - case 254: /* values */ + case 207: /* select */ + case 242: /* selectnowith */ + case 243: /* oneselect */ + case 255: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy136)); -} - break; - case 218: /* term */ - case 219: /* expr */ - case 248: /* where_opt */ - case 250: /* having_opt */ - case 269: /* where_opt_ret */ - case 280: /* case_operand */ - case 282: /* case_else */ - case 285: /* vinto */ - case 292: /* when_clause */ - case 297: /* key_opt */ - case 313: /* filter_clause */ +sqlite3SelectDelete(pParse->db, (yypminor->yy555)); +} + break; + case 219: /* term */ + case 220: /* expr */ + case 249: /* where_opt */ + case 251: /* 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 314: /* filter_clause */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy224)); -} - 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 256: /* sclp */ - case 263: /* exprlist */ - case 270: /* setlist */ - case 279: /* paren_exprlist */ - case 281: /* case_exprlist */ - case 312: /* part_opt */ +sqlite3ExprDelete(pParse->db, (yypminor->yy454)); +} + break; + case 224: /* eidlist_opt */ + case 234: /* sortlist */ + case 235: /* eidlist */ + case 247: /* selcollist */ + case 250: /* groupby_opt */ + case 252: /* orderby_opt */ + case 256: /* nexprlist */ + case 257: /* sclp */ + case 264: /* exprlist */ + case 271: /* setlist */ + case 280: /* paren_exprlist */ + case 282: /* case_exprlist */ + case 313: /* part_opt */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy586)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); } break; - case 240: /* fullname */ - case 247: /* from */ - case 258: /* seltablist */ - case 259: /* stl_prefix */ - case 264: /* xfullname */ + case 241: /* fullname */ + case 248: /* from */ + case 259: /* seltablist */ + case 260: /* stl_prefix */ + case 265: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy493)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy203)); } break; - case 243: /* wqlist */ + case 244: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy19)); +sqlite3WithDelete(pParse->db, (yypminor->yy59)); } break; - case 253: /* window_clause */ - case 308: /* windowdefn_list */ + case 254: /* window_clause */ + case 309: /* windowdefn_list */ { -sqlite3WindowListDelete(pParse->db, (yypminor->yy591)); +sqlite3WindowListDelete(pParse->db, (yypminor->yy211)); } break; - case 265: /* idlist */ - case 272: /* idlist_opt */ + case 266: /* idlist */ + case 273: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy600)); +sqlite3IdListDelete(pParse->db, (yypminor->yy132)); } break; - case 275: /* filter_over */ - case 309: /* windowdefn */ - case 310: /* window */ - case 311: /* frame_opt */ - case 314: /* over_clause */ + case 276: /* filter_over */ + case 310: /* windowdefn */ + case 311: /* window */ + case 312: /* frame_opt */ + case 315: /* over_clause */ { -sqlite3WindowDelete(pParse->db, (yypminor->yy591)); +sqlite3WindowDelete(pParse->db, (yypminor->yy211)); } break; - case 288: /* trigger_cmd_list */ - case 293: /* trigger_cmd */ + case 289: /* trigger_cmd_list */ + case 294: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy137)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427)); } break; - case 290: /* trigger_event */ + case 291: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy510).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy286).b); } break; - case 316: /* frame_bound */ - case 317: /* frame_bound_s */ - case 318: /* frame_bound_e */ + case 317: /* frame_bound */ + case 318: /* frame_bound_s */ + case 319: /* frame_bound_e */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy537).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy509).pExpr); } break; /********* End destructor definitions *****************************************/ @@ -170901,415 +174567,417 @@ static void yy_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 ::= RANDOM nm */ - 207, /* (25) table_option ::= nm */ - 208, /* (26) columnname ::= nm typetoken */ - 210, /* (27) typetoken ::= */ - 210, /* (28) typetoken ::= typename LP signed RP */ - 210, /* (29) typetoken ::= typename LP signed COMMA signed RP */ - 211, /* (30) typename ::= typename ID|STRING */ - 215, /* (31) scanpt ::= */ - 216, /* (32) scantok ::= */ - 217, /* (33) ccons ::= CONSTRAINT nm */ - 217, /* (34) ccons ::= DEFAULT scantok term */ - 217, /* (35) ccons ::= DEFAULT LP expr RP */ - 217, /* (36) ccons ::= DEFAULT PLUS scantok term */ - 217, /* (37) ccons ::= DEFAULT MINUS scantok term */ - 217, /* (38) ccons ::= DEFAULT scantok ID|INDEXED */ - 217, /* (39) ccons ::= NOT NULL onconf */ - 217, /* (40) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - 217, /* (41) ccons ::= UNIQUE onconf */ - 217, /* (42) ccons ::= CHECK LP expr RP */ - 217, /* (43) ccons ::= REFERENCES nm eidlist_opt refargs */ - 217, /* (44) ccons ::= defer_subclause */ - 217, /* (45) ccons ::= COLLATE ID|STRING */ - 226, /* (46) generated ::= LP expr RP */ - 226, /* (47) generated ::= LP expr RP ID */ - 222, /* (48) autoinc ::= */ - 222, /* (49) autoinc ::= AUTOINCR */ - 224, /* (50) refargs ::= */ - 224, /* (51) refargs ::= refargs refarg */ - 227, /* (52) refarg ::= MATCH nm */ - 227, /* (53) refarg ::= ON INSERT refact */ - 227, /* (54) refarg ::= ON DELETE refact */ - 227, /* (55) refarg ::= ON UPDATE refact */ - 228, /* (56) refact ::= SET NULL */ - 228, /* (57) refact ::= SET DEFAULT */ - 228, /* (58) refact ::= CASCADE */ - 228, /* (59) refact ::= RESTRICT */ - 228, /* (60) refact ::= NO ACTION */ - 225, /* (61) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - 225, /* (62) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 229, /* (63) init_deferred_pred_opt ::= */ - 229, /* (64) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - 229, /* (65) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 204, /* (66) conslist_opt ::= */ - 231, /* (67) tconscomma ::= COMMA */ - 232, /* (68) tcons ::= CONSTRAINT nm */ - 232, /* (69) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - 232, /* (70) tcons ::= UNIQUE LP sortlist RP onconf */ - 232, /* (71) tcons ::= CHECK LP expr RP onconf */ - 232, /* (72) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 235, /* (73) defer_subclause_opt ::= */ - 220, /* (74) onconf ::= */ - 220, /* (75) onconf ::= ON CONFLICT resolvetype */ - 236, /* (76) orconf ::= */ - 236, /* (77) orconf ::= OR resolvetype */ - 237, /* (78) resolvetype ::= IGNORE */ - 237, /* (79) resolvetype ::= REPLACE */ - 192, /* (80) cmd ::= DROP TABLE ifexists fullname */ - 239, /* (81) ifexists ::= IF EXISTS */ - 239, /* (82) ifexists ::= */ - 192, /* (83) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - 192, /* (84) cmd ::= DROP VIEW ifexists fullname */ - 192, /* (85) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING */ - 192, /* (86) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB */ - 192, /* (87) cmd ::= DROP FUNCTION ifexists nm */ - 192, /* (88) cmd ::= select */ - 206, /* (89) select ::= WITH wqlist selectnowith */ - 206, /* (90) select ::= WITH RECURSIVE wqlist selectnowith */ - 206, /* (91) select ::= selectnowith */ - 241, /* (92) selectnowith ::= selectnowith multiselect_op oneselect */ - 244, /* (93) multiselect_op ::= UNION */ - 244, /* (94) multiselect_op ::= UNION ALL */ - 244, /* (95) multiselect_op ::= EXCEPT|INTERSECT */ - 242, /* (96) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - 242, /* (97) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - 254, /* (98) values ::= VALUES LP nexprlist RP */ - 254, /* (99) values ::= values COMMA LP nexprlist RP */ - 245, /* (100) distinct ::= DISTINCT */ - 245, /* (101) distinct ::= ALL */ - 245, /* (102) distinct ::= */ - 256, /* (103) sclp ::= */ - 246, /* (104) selcollist ::= sclp scanpt expr scanpt as */ - 246, /* (105) selcollist ::= sclp scanpt STAR */ - 246, /* (106) selcollist ::= sclp scanpt nm DOT STAR */ - 257, /* (107) as ::= AS nm */ - 257, /* (108) as ::= */ - 247, /* (109) from ::= */ - 247, /* (110) from ::= FROM seltablist */ - 259, /* (111) stl_prefix ::= seltablist joinop */ - 259, /* (112) stl_prefix ::= */ - 258, /* (113) seltablist ::= stl_prefix nm dbnm as on_using */ - 258, /* (114) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - 258, /* (115) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - 258, /* (116) seltablist ::= stl_prefix LP select RP as on_using */ - 258, /* (117) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 202, /* (118) dbnm ::= */ - 202, /* (119) dbnm ::= DOT nm */ - 240, /* (120) fullname ::= nm */ - 240, /* (121) fullname ::= nm DOT nm */ - 264, /* (122) xfullname ::= nm */ - 264, /* (123) xfullname ::= nm DOT nm */ - 264, /* (124) xfullname ::= nm DOT nm AS nm */ - 264, /* (125) xfullname ::= nm AS nm */ - 260, /* (126) joinop ::= COMMA|JOIN */ - 260, /* (127) joinop ::= JOIN_KW JOIN */ - 260, /* (128) joinop ::= JOIN_KW nm JOIN */ - 260, /* (129) joinop ::= JOIN_KW nm nm JOIN */ - 261, /* (130) on_using ::= ON expr */ - 261, /* (131) on_using ::= USING LP idlist RP */ - 261, /* (132) on_using ::= */ - 266, /* (133) indexed_opt ::= */ - 262, /* (134) indexed_by ::= INDEXED BY nm */ - 262, /* (135) indexed_by ::= NOT INDEXED */ - 251, /* (136) orderby_opt ::= */ - 251, /* (137) orderby_opt ::= ORDER BY sortlist */ - 233, /* (138) sortlist ::= sortlist COMMA expr sortorder nulls */ - 233, /* (139) sortlist ::= expr sortorder nulls */ - 221, /* (140) sortorder ::= ASC */ - 221, /* (141) sortorder ::= DESC */ - 221, /* (142) sortorder ::= */ - 267, /* (143) nulls ::= NULLS FIRST */ - 267, /* (144) nulls ::= NULLS LAST */ - 267, /* (145) nulls ::= */ - 249, /* (146) groupby_opt ::= */ - 249, /* (147) groupby_opt ::= GROUP BY nexprlist */ - 250, /* (148) having_opt ::= */ - 250, /* (149) having_opt ::= HAVING expr */ - 252, /* (150) limit_opt ::= */ - 252, /* (151) limit_opt ::= LIMIT expr */ - 252, /* (152) limit_opt ::= LIMIT expr OFFSET expr */ - 252, /* (153) limit_opt ::= LIMIT expr COMMA expr */ - 192, /* (154) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 248, /* (155) where_opt ::= */ - 248, /* (156) where_opt ::= WHERE expr */ - 269, /* (157) where_opt_ret ::= */ - 269, /* (158) where_opt_ret ::= WHERE expr */ - 269, /* (159) where_opt_ret ::= RETURNING selcollist */ - 269, /* (160) where_opt_ret ::= WHERE expr RETURNING selcollist */ - 192, /* (161) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - 270, /* (162) setlist ::= setlist COMMA nm EQ expr */ - 270, /* (163) setlist ::= setlist COMMA LP idlist RP EQ expr */ - 270, /* (164) setlist ::= nm EQ expr */ - 270, /* (165) setlist ::= LP idlist RP EQ expr */ - 192, /* (166) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - 192, /* (167) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 273, /* (168) upsert ::= */ - 273, /* (169) upsert ::= RETURNING selcollist */ - 273, /* (170) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - 273, /* (171) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - 273, /* (172) upsert ::= ON CONFLICT DO NOTHING returning */ - 273, /* (173) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - 274, /* (174) returning ::= RETURNING selcollist */ - 271, /* (175) insert_cmd ::= INSERT orconf */ - 271, /* (176) insert_cmd ::= REPLACE */ - 272, /* (177) idlist_opt ::= */ - 272, /* (178) idlist_opt ::= LP idlist RP */ - 265, /* (179) idlist ::= idlist COMMA nm */ - 265, /* (180) idlist ::= nm */ - 219, /* (181) expr ::= LP expr RP */ - 219, /* (182) expr ::= ID|INDEXED */ - 219, /* (183) expr ::= JOIN_KW */ - 219, /* (184) expr ::= nm DOT nm */ - 219, /* (185) expr ::= nm DOT nm DOT nm */ - 218, /* (186) term ::= NULL|FLOAT|BLOB */ - 218, /* (187) term ::= STRING */ - 218, /* (188) term ::= INTEGER */ - 219, /* (189) expr ::= VARIABLE */ - 219, /* (190) expr ::= expr COLLATE ID|STRING */ - 219, /* (191) expr ::= CAST LP expr AS typetoken RP */ - 219, /* (192) expr ::= ID|INDEXED LP distinct exprlist RP */ - 219, /* (193) expr ::= ID|INDEXED LP STAR RP */ - 219, /* (194) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */ - 219, /* (195) expr ::= ID|INDEXED LP STAR RP filter_over */ - 218, /* (196) term ::= CTIME_KW */ - 219, /* (197) expr ::= LP nexprlist COMMA expr RP */ - 219, /* (198) expr ::= expr AND expr */ - 219, /* (199) expr ::= expr OR expr */ - 219, /* (200) expr ::= expr LT|GT|GE|LE expr */ - 219, /* (201) expr ::= expr EQ|NE expr */ - 219, /* (202) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - 219, /* (203) expr ::= expr PLUS|MINUS expr */ - 219, /* (204) expr ::= expr STAR|SLASH|REM expr */ - 219, /* (205) expr ::= expr CONCAT expr */ - 276, /* (206) likeop ::= NOT LIKE_KW|MATCH */ - 219, /* (207) expr ::= expr likeop expr */ - 219, /* (208) expr ::= expr likeop expr ESCAPE expr */ - 219, /* (209) expr ::= expr ISNULL|NOTNULL */ - 219, /* (210) expr ::= expr NOT NULL */ - 219, /* (211) expr ::= expr IS expr */ - 219, /* (212) expr ::= expr IS NOT expr */ - 219, /* (213) expr ::= expr IS NOT DISTINCT FROM expr */ - 219, /* (214) expr ::= expr IS DISTINCT FROM expr */ - 219, /* (215) expr ::= NOT expr */ - 219, /* (216) expr ::= BITNOT expr */ - 219, /* (217) expr ::= PLUS|MINUS expr */ - 219, /* (218) expr ::= expr PTR expr */ - 277, /* (219) between_op ::= BETWEEN */ - 277, /* (220) between_op ::= NOT BETWEEN */ - 219, /* (221) expr ::= expr between_op expr AND expr */ - 278, /* (222) in_op ::= IN */ - 278, /* (223) in_op ::= NOT IN */ - 219, /* (224) expr ::= expr in_op LP exprlist RP */ - 219, /* (225) expr ::= LP select RP */ - 219, /* (226) expr ::= expr in_op LP select RP */ - 219, /* (227) expr ::= expr in_op nm dbnm paren_exprlist */ - 219, /* (228) expr ::= EXISTS LP select RP */ - 219, /* (229) expr ::= CASE case_operand case_exprlist case_else END */ - 281, /* (230) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - 281, /* (231) case_exprlist ::= WHEN expr THEN expr */ - 282, /* (232) case_else ::= ELSE expr */ - 282, /* (233) case_else ::= */ - 280, /* (234) case_operand ::= expr */ - 280, /* (235) case_operand ::= */ - 263, /* (236) exprlist ::= */ - 255, /* (237) nexprlist ::= nexprlist COMMA expr */ - 255, /* (238) nexprlist ::= expr */ - 279, /* (239) paren_exprlist ::= */ - 279, /* (240) paren_exprlist ::= LP exprlist RP */ - 192, /* (241) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - 283, /* (242) uniqueflag ::= UNIQUE */ - 283, /* (243) uniqueflag ::= */ - 223, /* (244) eidlist_opt ::= */ - 223, /* (245) eidlist_opt ::= LP eidlist RP */ - 234, /* (246) eidlist ::= eidlist COMMA nm collate sortorder */ - 234, /* (247) eidlist ::= nm collate sortorder */ - 284, /* (248) collate ::= */ - 284, /* (249) collate ::= COLLATE ID|STRING */ - 192, /* (250) cmd ::= DROP INDEX ifexists fullname */ - 192, /* (251) cmd ::= VACUUM vinto */ - 192, /* (252) cmd ::= VACUUM nm vinto */ - 285, /* (253) vinto ::= INTO expr */ - 285, /* (254) vinto ::= */ - 192, /* (255) cmd ::= PRAGMA nm dbnm */ - 192, /* (256) cmd ::= PRAGMA nm dbnm EQ nmnum */ - 192, /* (257) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - 192, /* (258) cmd ::= PRAGMA nm dbnm EQ minus_num */ - 192, /* (259) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - 213, /* (260) plus_num ::= PLUS INTEGER|FLOAT */ - 214, /* (261) minus_num ::= MINUS INTEGER|FLOAT */ - 192, /* (262) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - 287, /* (263) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - 289, /* (264) trigger_time ::= BEFORE|AFTER */ - 289, /* (265) trigger_time ::= INSTEAD OF */ - 289, /* (266) trigger_time ::= */ - 290, /* (267) trigger_event ::= DELETE|INSERT */ - 290, /* (268) trigger_event ::= UPDATE */ - 290, /* (269) trigger_event ::= UPDATE OF idlist */ - 292, /* (270) when_clause ::= */ - 292, /* (271) when_clause ::= WHEN expr */ - 288, /* (272) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - 288, /* (273) trigger_cmd_list ::= trigger_cmd SEMI */ - 294, /* (274) trnm ::= nm DOT nm */ - 295, /* (275) tridxby ::= INDEXED BY nm */ - 295, /* (276) tridxby ::= NOT INDEXED */ - 293, /* (277) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - 293, /* (278) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - 293, /* (279) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - 293, /* (280) trigger_cmd ::= scanpt select scanpt */ - 219, /* (281) expr ::= RAISE LP IGNORE RP */ - 219, /* (282) expr ::= RAISE LP raisetype COMMA nm RP */ - 238, /* (283) raisetype ::= ROLLBACK */ - 238, /* (284) raisetype ::= ABORT */ - 238, /* (285) raisetype ::= FAIL */ - 192, /* (286) cmd ::= DROP TRIGGER ifexists fullname */ - 192, /* (287) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 192, /* (288) cmd ::= DETACH database_kw_opt expr */ - 297, /* (289) key_opt ::= */ - 297, /* (290) key_opt ::= KEY expr */ - 192, /* (291) cmd ::= REINDEX */ - 192, /* (292) cmd ::= REINDEX nm dbnm */ - 192, /* (293) cmd ::= ANALYZE */ - 192, /* (294) cmd ::= ANALYZE nm dbnm */ - 192, /* (295) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 192, /* (296) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - 192, /* (297) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 298, /* (298) add_column_fullname ::= fullname */ - 192, /* (299) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 192, /* (300) cmd ::= create_vtab */ - 192, /* (301) cmd ::= create_vtab LP vtabarglist RP */ - 300, /* (302) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 302, /* (303) vtabarg ::= */ - 303, /* (304) vtabargtoken ::= ANY */ - 303, /* (305) vtabargtoken ::= lp anylist RP */ - 304, /* (306) lp ::= LP */ - 268, /* (307) with ::= WITH wqlist */ - 268, /* (308) with ::= WITH RECURSIVE wqlist */ - 307, /* (309) wqas ::= AS */ - 307, /* (310) wqas ::= AS MATERIALIZED */ - 307, /* (311) wqas ::= AS NOT MATERIALIZED */ - 306, /* (312) wqitem ::= nm eidlist_opt wqas LP select RP */ - 243, /* (313) wqlist ::= wqitem */ - 243, /* (314) wqlist ::= wqlist COMMA wqitem */ - 308, /* (315) windowdefn_list ::= windowdefn */ - 308, /* (316) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 309, /* (317) windowdefn ::= nm AS LP window RP */ - 310, /* (318) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 310, /* (319) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 310, /* (320) window ::= ORDER BY sortlist frame_opt */ - 310, /* (321) window ::= nm ORDER BY sortlist frame_opt */ - 310, /* (322) window ::= frame_opt */ - 310, /* (323) window ::= nm frame_opt */ - 311, /* (324) frame_opt ::= */ - 311, /* (325) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 311, /* (326) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 315, /* (327) range_or_rows ::= RANGE|ROWS|GROUPS */ - 317, /* (328) frame_bound_s ::= frame_bound */ - 317, /* (329) frame_bound_s ::= UNBOUNDED PRECEDING */ - 318, /* (330) frame_bound_e ::= frame_bound */ - 318, /* (331) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 316, /* (332) frame_bound ::= expr PRECEDING|FOLLOWING */ - 316, /* (333) frame_bound ::= CURRENT ROW */ - 319, /* (334) frame_exclude_opt ::= */ - 319, /* (335) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 320, /* (336) frame_exclude ::= NO OTHERS */ - 320, /* (337) frame_exclude ::= CURRENT ROW */ - 320, /* (338) frame_exclude ::= GROUP|TIES */ - 253, /* (339) window_clause ::= WINDOW windowdefn_list */ - 275, /* (340) filter_over ::= filter_clause over_clause */ - 275, /* (341) filter_over ::= over_clause */ - 275, /* (342) filter_over ::= filter_clause */ - 314, /* (343) over_clause ::= OVER LP window RP */ - 314, /* (344) over_clause ::= OVER nm */ - 313, /* (345) filter_clause ::= FILTER LP WHERE expr RP */ - 187, /* (346) input ::= cmdlist */ - 188, /* (347) cmdlist ::= cmdlist ecmd */ - 188, /* (348) cmdlist ::= ecmd */ - 189, /* (349) ecmd ::= SEMI */ - 189, /* (350) ecmd ::= cmdx SEMI */ - 189, /* (351) ecmd ::= explain cmdx SEMI */ - 194, /* (352) trans_opt ::= */ - 194, /* (353) trans_opt ::= TRANSACTION */ - 194, /* (354) trans_opt ::= TRANSACTION nm */ - 196, /* (355) savepoint_opt ::= SAVEPOINT */ - 196, /* (356) savepoint_opt ::= */ - 192, /* (357) cmd ::= create_table create_table_args */ - 205, /* (358) table_option_set ::= table_option */ - 203, /* (359) columnlist ::= columnlist COMMA columnname carglist */ - 203, /* (360) columnlist ::= columnname carglist */ - 195, /* (361) nm ::= ID|INDEXED */ - 195, /* (362) nm ::= STRING */ - 195, /* (363) nm ::= JOIN_KW */ - 210, /* (364) typetoken ::= typename */ - 211, /* (365) typename ::= ID|STRING */ - 212, /* (366) signed ::= plus_num */ - 212, /* (367) signed ::= minus_num */ - 209, /* (368) carglist ::= carglist ccons */ - 209, /* (369) carglist ::= */ - 217, /* (370) ccons ::= NULL onconf */ - 217, /* (371) ccons ::= GENERATED ALWAYS AS generated */ - 217, /* (372) ccons ::= AS generated */ - 204, /* (373) conslist_opt ::= COMMA conslist */ - 230, /* (374) conslist ::= conslist tconscomma tcons */ - 230, /* (375) conslist ::= tcons */ - 231, /* (376) tconscomma ::= */ - 235, /* (377) defer_subclause_opt ::= defer_subclause */ - 237, /* (378) resolvetype ::= raisetype */ - 241, /* (379) selectnowith ::= oneselect */ - 242, /* (380) oneselect ::= values */ - 256, /* (381) sclp ::= selcollist COMMA */ - 257, /* (382) as ::= ID|STRING */ - 266, /* (383) indexed_opt ::= indexed_by */ - 274, /* (384) returning ::= */ - 219, /* (385) expr ::= term */ - 276, /* (386) likeop ::= LIKE_KW|MATCH */ - 263, /* (387) exprlist ::= nexprlist */ - 286, /* (388) nmnum ::= plus_num */ - 286, /* (389) nmnum ::= nm */ - 286, /* (390) nmnum ::= ON */ - 286, /* (391) nmnum ::= DELETE */ - 286, /* (392) nmnum ::= DEFAULT */ - 213, /* (393) plus_num ::= INTEGER|FLOAT */ - 291, /* (394) foreach_clause ::= */ - 291, /* (395) foreach_clause ::= FOR EACH ROW */ - 294, /* (396) trnm ::= nm */ - 295, /* (397) tridxby ::= */ - 296, /* (398) database_kw_opt ::= DATABASE */ - 296, /* (399) database_kw_opt ::= */ - 299, /* (400) kwcolumn_opt ::= */ - 299, /* (401) kwcolumn_opt ::= COLUMNKW */ - 301, /* (402) vtabarglist ::= vtabarg */ - 301, /* (403) vtabarglist ::= vtabarglist COMMA vtabarg */ - 302, /* (404) vtabarg ::= vtabarg vtabargtoken */ - 305, /* (405) anylist ::= */ - 305, /* (406) anylist ::= anylist LP anylist RP */ - 305, /* (407) anylist ::= anylist ANY */ - 268, /* (408) with ::= */ + 192, /* (0) explain ::= EXPLAIN */ + 192, /* (1) explain ::= EXPLAIN QUERY PLAN */ + 191, /* (2) cmdx ::= cmd */ + 193, /* (3) cmd ::= BEGIN transtype trans_opt */ + 194, /* (4) transtype ::= */ + 194, /* (5) transtype ::= DEFERRED */ + 194, /* (6) transtype ::= IMMEDIATE */ + 194, /* (7) transtype ::= EXCLUSIVE */ + 194, /* (8) transtype ::= READONLY */ + 193, /* (9) cmd ::= COMMIT|END trans_opt */ + 193, /* (10) cmd ::= ROLLBACK trans_opt */ + 193, /* (11) cmd ::= SAVEPOINT nm */ + 193, /* (12) cmd ::= RELEASE savepoint_opt nm */ + 193, /* (13) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + 198, /* (14) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + 200, /* (15) createkw ::= CREATE */ + 202, /* (16) ifnotexists ::= */ + 202, /* (17) ifnotexists ::= IF NOT EXISTS */ + 201, /* (18) temp ::= TEMP */ + 201, /* (19) temp ::= */ + 199, /* (20) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ + 199, /* (21) create_table_args ::= AS select */ + 206, /* (22) table_option_set ::= */ + 206, /* (23) table_option_set ::= table_option_set COMMA table_option */ + 208, /* (24) table_option ::= WITHOUT nm */ + 208, /* (25) table_option ::= RANDOM nm */ + 208, /* (26) table_option ::= nm */ + 209, /* (27) columnname ::= nm typetoken */ + 211, /* (28) typetoken ::= */ + 211, /* (29) typetoken ::= typename LP signed RP */ + 211, /* (30) typetoken ::= typename LP signed COMMA signed RP */ + 212, /* (31) typename ::= typename ID|STRING */ + 216, /* (32) scanpt ::= */ + 217, /* (33) scantok ::= */ + 218, /* (34) ccons ::= CONSTRAINT nm */ + 218, /* (35) ccons ::= DEFAULT scantok term */ + 218, /* (36) ccons ::= DEFAULT LP expr RP */ + 218, /* (37) ccons ::= DEFAULT PLUS scantok term */ + 218, /* (38) ccons ::= DEFAULT MINUS scantok term */ + 218, /* (39) ccons ::= DEFAULT scantok ID|INDEXED */ + 218, /* (40) ccons ::= NOT NULL onconf */ + 218, /* (41) ccons ::= PRIMARY KEY sortorder onconf autoinc */ + 218, /* (42) ccons ::= UNIQUE onconf */ + 218, /* (43) ccons ::= CHECK LP expr RP */ + 218, /* (44) ccons ::= REFERENCES nm eidlist_opt refargs */ + 218, /* (45) ccons ::= defer_subclause */ + 218, /* (46) ccons ::= COLLATE ID|STRING */ + 227, /* (47) generated ::= LP expr RP */ + 227, /* (48) generated ::= LP expr RP ID */ + 223, /* (49) autoinc ::= */ + 223, /* (50) autoinc ::= AUTOINCR */ + 225, /* (51) refargs ::= */ + 225, /* (52) refargs ::= refargs refarg */ + 228, /* (53) refarg ::= MATCH nm */ + 228, /* (54) refarg ::= ON INSERT refact */ + 228, /* (55) refarg ::= ON DELETE refact */ + 228, /* (56) refarg ::= ON UPDATE refact */ + 229, /* (57) refact ::= SET NULL */ + 229, /* (58) refact ::= SET DEFAULT */ + 229, /* (59) refact ::= CASCADE */ + 229, /* (60) refact ::= RESTRICT */ + 229, /* (61) refact ::= NO ACTION */ + 226, /* (62) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + 226, /* (63) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + 230, /* (64) init_deferred_pred_opt ::= */ + 230, /* (65) init_deferred_pred_opt ::= INITIALLY DEFERRED */ + 230, /* (66) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + 205, /* (67) conslist_opt ::= */ + 232, /* (68) tconscomma ::= COMMA */ + 233, /* (69) tcons ::= CONSTRAINT nm */ + 233, /* (70) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + 233, /* (71) tcons ::= UNIQUE LP sortlist RP onconf */ + 233, /* (72) tcons ::= CHECK LP expr RP onconf */ + 233, /* (73) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + 236, /* (74) defer_subclause_opt ::= */ + 221, /* (75) onconf ::= */ + 221, /* (76) onconf ::= ON CONFLICT resolvetype */ + 237, /* (77) orconf ::= */ + 237, /* (78) orconf ::= OR resolvetype */ + 238, /* (79) resolvetype ::= IGNORE */ + 238, /* (80) resolvetype ::= REPLACE */ + 193, /* (81) cmd ::= DROP TABLE ifexists fullname */ + 240, /* (82) ifexists ::= IF EXISTS */ + 240, /* (83) ifexists ::= */ + 193, /* (84) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + 193, /* (85) cmd ::= DROP VIEW ifexists fullname */ + 193, /* (86) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING */ + 193, /* (87) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB */ + 193, /* (88) cmd ::= DROP FUNCTION ifexists nm */ + 193, /* (89) cmd ::= select */ + 207, /* (90) select ::= WITH wqlist selectnowith */ + 207, /* (91) select ::= WITH RECURSIVE wqlist selectnowith */ + 207, /* (92) select ::= selectnowith */ + 242, /* (93) selectnowith ::= selectnowith multiselect_op oneselect */ + 245, /* (94) multiselect_op ::= UNION */ + 245, /* (95) multiselect_op ::= UNION ALL */ + 245, /* (96) multiselect_op ::= EXCEPT|INTERSECT */ + 243, /* (97) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + 243, /* (98) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ + 255, /* (99) values ::= VALUES LP nexprlist RP */ + 255, /* (100) values ::= values COMMA LP nexprlist RP */ + 246, /* (101) distinct ::= DISTINCT */ + 246, /* (102) distinct ::= ALL */ + 246, /* (103) distinct ::= */ + 257, /* (104) sclp ::= */ + 247, /* (105) selcollist ::= sclp scanpt expr scanpt as */ + 247, /* (106) selcollist ::= sclp scanpt STAR */ + 247, /* (107) selcollist ::= sclp scanpt nm DOT STAR */ + 258, /* (108) as ::= AS nm */ + 258, /* (109) as ::= */ + 248, /* (110) from ::= */ + 248, /* (111) from ::= FROM seltablist */ + 260, /* (112) stl_prefix ::= seltablist joinop */ + 260, /* (113) stl_prefix ::= */ + 259, /* (114) seltablist ::= stl_prefix nm dbnm as on_using */ + 259, /* (115) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + 259, /* (116) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + 259, /* (117) seltablist ::= stl_prefix LP select RP as on_using */ + 259, /* (118) seltablist ::= stl_prefix LP seltablist RP as on_using */ + 203, /* (119) dbnm ::= */ + 203, /* (120) dbnm ::= DOT nm */ + 241, /* (121) fullname ::= nm */ + 241, /* (122) fullname ::= nm DOT nm */ + 265, /* (123) xfullname ::= nm */ + 265, /* (124) xfullname ::= nm DOT nm */ + 265, /* (125) xfullname ::= nm DOT nm AS nm */ + 265, /* (126) xfullname ::= nm AS nm */ + 261, /* (127) joinop ::= COMMA|JOIN */ + 261, /* (128) joinop ::= JOIN_KW JOIN */ + 261, /* (129) joinop ::= JOIN_KW nm JOIN */ + 261, /* (130) joinop ::= JOIN_KW nm nm JOIN */ + 262, /* (131) on_using ::= ON expr */ + 262, /* (132) on_using ::= USING LP idlist RP */ + 262, /* (133) on_using ::= */ + 267, /* (134) indexed_opt ::= */ + 263, /* (135) indexed_by ::= INDEXED BY nm */ + 263, /* (136) indexed_by ::= NOT INDEXED */ + 252, /* (137) orderby_opt ::= */ + 252, /* (138) orderby_opt ::= ORDER BY sortlist */ + 234, /* (139) sortlist ::= sortlist COMMA expr sortorder nulls */ + 234, /* (140) sortlist ::= expr sortorder nulls */ + 222, /* (141) sortorder ::= ASC */ + 222, /* (142) sortorder ::= DESC */ + 222, /* (143) sortorder ::= */ + 268, /* (144) nulls ::= NULLS FIRST */ + 268, /* (145) nulls ::= NULLS LAST */ + 268, /* (146) nulls ::= */ + 250, /* (147) groupby_opt ::= */ + 250, /* (148) groupby_opt ::= GROUP BY nexprlist */ + 251, /* (149) having_opt ::= */ + 251, /* (150) having_opt ::= HAVING expr */ + 253, /* (151) limit_opt ::= */ + 253, /* (152) limit_opt ::= LIMIT expr */ + 253, /* (153) limit_opt ::= LIMIT expr OFFSET expr */ + 253, /* (154) limit_opt ::= LIMIT expr COMMA expr */ + 193, /* (155) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + 249, /* (156) where_opt ::= */ + 249, /* (157) where_opt ::= WHERE expr */ + 270, /* (158) where_opt_ret ::= */ + 270, /* (159) where_opt_ret ::= WHERE expr */ + 270, /* (160) where_opt_ret ::= RETURNING selcollist */ + 270, /* (161) where_opt_ret ::= WHERE expr RETURNING selcollist */ + 193, /* (162) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + 271, /* (163) setlist ::= setlist COMMA nm EQ expr */ + 271, /* (164) setlist ::= setlist COMMA LP idlist RP EQ expr */ + 271, /* (165) setlist ::= nm EQ expr */ + 271, /* (166) setlist ::= LP idlist RP EQ expr */ + 193, /* (167) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + 193, /* (168) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + 274, /* (169) upsert ::= */ + 274, /* (170) upsert ::= RETURNING selcollist */ + 274, /* (171) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ + 274, /* (172) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ + 274, /* (173) upsert ::= ON CONFLICT DO NOTHING returning */ + 274, /* (174) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ + 275, /* (175) returning ::= RETURNING selcollist */ + 272, /* (176) insert_cmd ::= INSERT orconf */ + 272, /* (177) insert_cmd ::= REPLACE */ + 273, /* (178) idlist_opt ::= */ + 273, /* (179) idlist_opt ::= LP idlist RP */ + 266, /* (180) idlist ::= idlist COMMA nm */ + 266, /* (181) idlist ::= nm */ + 220, /* (182) expr ::= LP expr RP */ + 220, /* (183) expr ::= ID|INDEXED|JOIN_KW */ + 220, /* (184) expr ::= nm DOT nm */ + 220, /* (185) expr ::= nm DOT nm DOT nm */ + 219, /* (186) term ::= NULL|FLOAT|BLOB */ + 219, /* (187) term ::= STRING */ + 219, /* (188) term ::= INTEGER */ + 220, /* (189) expr ::= VARIABLE */ + 220, /* (190) expr ::= expr COLLATE ID|STRING */ + 220, /* (191) expr ::= CAST LP expr AS typetoken RP */ + 220, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ + 220, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ + 220, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ + 220, /* (195) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ + 220, /* (196) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ + 220, /* (197) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ + 219, /* (198) term ::= CTIME_KW */ + 220, /* (199) expr ::= LP nexprlist COMMA expr RP */ + 220, /* (200) expr ::= expr AND expr */ + 220, /* (201) expr ::= expr OR expr */ + 220, /* (202) expr ::= expr LT|GT|GE|LE expr */ + 220, /* (203) expr ::= expr EQ|NE expr */ + 220, /* (204) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + 220, /* (205) expr ::= expr PLUS|MINUS expr */ + 220, /* (206) expr ::= expr STAR|SLASH|REM expr */ + 220, /* (207) expr ::= expr CONCAT expr */ + 277, /* (208) likeop ::= NOT LIKE_KW|MATCH */ + 220, /* (209) expr ::= expr likeop expr */ + 220, /* (210) expr ::= expr likeop expr ESCAPE expr */ + 220, /* (211) expr ::= expr ISNULL|NOTNULL */ + 220, /* (212) expr ::= expr NOT NULL */ + 220, /* (213) expr ::= expr IS expr */ + 220, /* (214) expr ::= expr IS NOT expr */ + 220, /* (215) expr ::= expr IS NOT DISTINCT FROM expr */ + 220, /* (216) expr ::= expr IS DISTINCT FROM expr */ + 220, /* (217) expr ::= NOT expr */ + 220, /* (218) expr ::= BITNOT expr */ + 220, /* (219) expr ::= PLUS|MINUS expr */ + 220, /* (220) expr ::= expr PTR expr */ + 278, /* (221) between_op ::= BETWEEN */ + 278, /* (222) between_op ::= NOT BETWEEN */ + 220, /* (223) expr ::= expr between_op expr AND expr */ + 279, /* (224) in_op ::= IN */ + 279, /* (225) in_op ::= NOT IN */ + 220, /* (226) expr ::= expr in_op LP exprlist RP */ + 220, /* (227) expr ::= LP select RP */ + 220, /* (228) expr ::= expr in_op LP select RP */ + 220, /* (229) expr ::= expr in_op nm dbnm paren_exprlist */ + 220, /* (230) expr ::= EXISTS LP select RP */ + 220, /* (231) expr ::= CASE case_operand case_exprlist case_else END */ + 282, /* (232) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + 282, /* (233) case_exprlist ::= WHEN expr THEN expr */ + 283, /* (234) case_else ::= ELSE expr */ + 283, /* (235) case_else ::= */ + 281, /* (236) case_operand ::= */ + 264, /* (237) exprlist ::= */ + 256, /* (238) nexprlist ::= nexprlist COMMA expr */ + 256, /* (239) nexprlist ::= expr */ + 280, /* (240) paren_exprlist ::= */ + 280, /* (241) paren_exprlist ::= LP exprlist RP */ + 193, /* (242) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + 284, /* (243) uniqueflag ::= UNIQUE */ + 284, /* (244) uniqueflag ::= */ + 224, /* (245) eidlist_opt ::= */ + 224, /* (246) eidlist_opt ::= LP eidlist RP */ + 235, /* (247) eidlist ::= eidlist COMMA nm collate sortorder */ + 235, /* (248) eidlist ::= nm collate sortorder */ + 285, /* (249) collate ::= */ + 285, /* (250) collate ::= COLLATE ID|STRING */ + 193, /* (251) cmd ::= DROP INDEX ifexists fullname */ + 193, /* (252) cmd ::= VACUUM vinto */ + 193, /* (253) cmd ::= VACUUM nm vinto */ + 286, /* (254) vinto ::= INTO expr */ + 286, /* (255) vinto ::= */ + 193, /* (256) cmd ::= PRAGMA nm dbnm */ + 193, /* (257) cmd ::= PRAGMA nm dbnm EQ nmnum */ + 193, /* (258) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + 193, /* (259) cmd ::= PRAGMA nm dbnm EQ minus_num */ + 193, /* (260) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + 214, /* (261) plus_num ::= PLUS INTEGER|FLOAT */ + 215, /* (262) minus_num ::= MINUS INTEGER|FLOAT */ + 193, /* (263) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + 288, /* (264) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + 290, /* (265) trigger_time ::= BEFORE|AFTER */ + 290, /* (266) trigger_time ::= INSTEAD OF */ + 290, /* (267) trigger_time ::= */ + 291, /* (268) trigger_event ::= DELETE|INSERT */ + 291, /* (269) trigger_event ::= UPDATE */ + 291, /* (270) trigger_event ::= UPDATE OF idlist */ + 293, /* (271) when_clause ::= */ + 293, /* (272) when_clause ::= WHEN expr */ + 289, /* (273) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + 289, /* (274) trigger_cmd_list ::= trigger_cmd SEMI */ + 295, /* (275) trnm ::= nm DOT nm */ + 296, /* (276) tridxby ::= INDEXED BY nm */ + 296, /* (277) tridxby ::= NOT INDEXED */ + 294, /* (278) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + 294, /* (279) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + 294, /* (280) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + 294, /* (281) trigger_cmd ::= scanpt select scanpt */ + 220, /* (282) expr ::= RAISE LP IGNORE RP */ + 220, /* (283) expr ::= RAISE LP raisetype COMMA nm RP */ + 239, /* (284) raisetype ::= ROLLBACK */ + 239, /* (285) raisetype ::= ABORT */ + 239, /* (286) raisetype ::= FAIL */ + 193, /* (287) cmd ::= DROP TRIGGER ifexists fullname */ + 193, /* (288) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + 193, /* (289) cmd ::= DETACH database_kw_opt expr */ + 298, /* (290) key_opt ::= */ + 298, /* (291) key_opt ::= KEY expr */ + 193, /* (292) cmd ::= REINDEX */ + 193, /* (293) cmd ::= REINDEX nm dbnm */ + 193, /* (294) cmd ::= ANALYZE */ + 193, /* (295) cmd ::= ANALYZE nm dbnm */ + 193, /* (296) cmd ::= ALTER TABLE fullname RENAME TO nm */ + 193, /* (297) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + 193, /* (298) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + 299, /* (299) add_column_fullname ::= fullname */ + 193, /* (300) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + 193, /* (301) cmd ::= ALTER TABLE fullname ALTER COLUMNKW columnname TO columnname carglist */ + 193, /* (302) cmd ::= create_vtab */ + 193, /* (303) cmd ::= create_vtab LP vtabarglist RP */ + 301, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 303, /* (305) vtabarg ::= */ + 304, /* (306) vtabargtoken ::= ANY */ + 304, /* (307) vtabargtoken ::= lp anylist RP */ + 305, /* (308) lp ::= LP */ + 269, /* (309) with ::= WITH wqlist */ + 269, /* (310) with ::= WITH RECURSIVE wqlist */ + 308, /* (311) wqas ::= AS */ + 308, /* (312) wqas ::= AS MATERIALIZED */ + 308, /* (313) wqas ::= AS NOT MATERIALIZED */ + 307, /* (314) wqitem ::= nm eidlist_opt wqas LP select RP */ + 244, /* (315) wqlist ::= wqitem */ + 244, /* (316) wqlist ::= wqlist COMMA wqitem */ + 309, /* (317) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 310, /* (318) windowdefn ::= nm AS LP window RP */ + 311, /* (319) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 311, /* (320) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 311, /* (321) window ::= ORDER BY sortlist frame_opt */ + 311, /* (322) window ::= nm ORDER BY sortlist frame_opt */ + 311, /* (323) window ::= nm frame_opt */ + 312, /* (324) frame_opt ::= */ + 312, /* (325) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 312, /* (326) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 316, /* (327) range_or_rows ::= RANGE|ROWS|GROUPS */ + 318, /* (328) frame_bound_s ::= frame_bound */ + 318, /* (329) frame_bound_s ::= UNBOUNDED PRECEDING */ + 319, /* (330) frame_bound_e ::= frame_bound */ + 319, /* (331) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 317, /* (332) frame_bound ::= expr PRECEDING|FOLLOWING */ + 317, /* (333) frame_bound ::= CURRENT ROW */ + 320, /* (334) frame_exclude_opt ::= */ + 320, /* (335) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 321, /* (336) frame_exclude ::= NO OTHERS */ + 321, /* (337) frame_exclude ::= CURRENT ROW */ + 321, /* (338) frame_exclude ::= GROUP|TIES */ + 254, /* (339) window_clause ::= WINDOW windowdefn_list */ + 276, /* (340) filter_over ::= filter_clause over_clause */ + 276, /* (341) filter_over ::= over_clause */ + 276, /* (342) filter_over ::= filter_clause */ + 315, /* (343) over_clause ::= OVER LP window RP */ + 315, /* (344) over_clause ::= OVER nm */ + 314, /* (345) filter_clause ::= FILTER LP WHERE expr RP */ + 188, /* (346) input ::= cmdlist */ + 189, /* (347) cmdlist ::= cmdlist ecmd */ + 189, /* (348) cmdlist ::= ecmd */ + 190, /* (349) ecmd ::= SEMI */ + 190, /* (350) ecmd ::= cmdx SEMI */ + 190, /* (351) ecmd ::= explain cmdx SEMI */ + 195, /* (352) trans_opt ::= */ + 195, /* (353) trans_opt ::= TRANSACTION */ + 195, /* (354) trans_opt ::= TRANSACTION nm */ + 197, /* (355) savepoint_opt ::= SAVEPOINT */ + 197, /* (356) savepoint_opt ::= */ + 193, /* (357) cmd ::= create_table create_table_args */ + 206, /* (358) table_option_set ::= table_option */ + 204, /* (359) columnlist ::= columnlist COMMA columnname carglist */ + 204, /* (360) columnlist ::= columnname carglist */ + 196, /* (361) nm ::= ID|INDEXED|JOIN_KW */ + 196, /* (362) nm ::= STRING */ + 211, /* (363) typetoken ::= typename */ + 212, /* (364) typename ::= ID|STRING */ + 213, /* (365) signed ::= plus_num */ + 213, /* (366) signed ::= minus_num */ + 210, /* (367) carglist ::= carglist ccons */ + 210, /* (368) carglist ::= */ + 218, /* (369) ccons ::= NULL onconf */ + 218, /* (370) ccons ::= GENERATED ALWAYS AS generated */ + 218, /* (371) ccons ::= AS generated */ + 205, /* (372) conslist_opt ::= COMMA conslist */ + 231, /* (373) conslist ::= conslist tconscomma tcons */ + 231, /* (374) conslist ::= tcons */ + 232, /* (375) tconscomma ::= */ + 236, /* (376) defer_subclause_opt ::= defer_subclause */ + 238, /* (377) resolvetype ::= raisetype */ + 242, /* (378) selectnowith ::= oneselect */ + 243, /* (379) oneselect ::= values */ + 257, /* (380) sclp ::= selcollist COMMA */ + 258, /* (381) as ::= ID|STRING */ + 267, /* (382) indexed_opt ::= indexed_by */ + 275, /* (383) returning ::= */ + 220, /* (384) expr ::= term */ + 277, /* (385) likeop ::= LIKE_KW|MATCH */ + 281, /* (386) case_operand ::= expr */ + 264, /* (387) exprlist ::= nexprlist */ + 287, /* (388) nmnum ::= plus_num */ + 287, /* (389) nmnum ::= nm */ + 287, /* (390) nmnum ::= ON */ + 287, /* (391) nmnum ::= DELETE */ + 287, /* (392) nmnum ::= DEFAULT */ + 214, /* (393) plus_num ::= INTEGER|FLOAT */ + 292, /* (394) foreach_clause ::= */ + 292, /* (395) foreach_clause ::= FOR EACH ROW */ + 295, /* (396) trnm ::= nm */ + 296, /* (397) tridxby ::= */ + 297, /* (398) database_kw_opt ::= DATABASE */ + 297, /* (399) database_kw_opt ::= */ + 300, /* (400) kwcolumn_opt ::= */ + 300, /* (401) kwcolumn_opt ::= COLUMNKW */ + 302, /* (402) vtabarglist ::= vtabarg */ + 302, /* (403) vtabarglist ::= vtabarglist COMMA vtabarg */ + 303, /* (404) vtabarg ::= vtabarg vtabargtoken */ + 306, /* (405) anylist ::= */ + 306, /* (406) anylist ::= anylist LP anylist RP */ + 306, /* (407) anylist ::= anylist ANY */ + 269, /* (408) with ::= */ + 309, /* (409) windowdefn_list ::= windowdefn */ + 311, /* (410) window ::= frame_opt */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -171323,182 +174991,182 @@ static const signed char yyRuleInfoNRhs[] = { -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 */ - -2, /* (24) table_option ::= RANDOM nm */ - -1, /* (25) table_option ::= nm */ - -2, /* (26) columnname ::= nm typetoken */ - 0, /* (27) typetoken ::= */ - -4, /* (28) typetoken ::= typename LP signed RP */ - -6, /* (29) typetoken ::= typename LP signed COMMA signed RP */ - -2, /* (30) typename ::= typename ID|STRING */ - 0, /* (31) scanpt ::= */ - 0, /* (32) scantok ::= */ - -2, /* (33) ccons ::= CONSTRAINT nm */ - -3, /* (34) ccons ::= DEFAULT scantok term */ - -4, /* (35) ccons ::= DEFAULT LP expr RP */ - -4, /* (36) ccons ::= DEFAULT PLUS scantok term */ - -4, /* (37) ccons ::= DEFAULT MINUS scantok term */ - -3, /* (38) ccons ::= DEFAULT scantok ID|INDEXED */ - -3, /* (39) ccons ::= NOT NULL onconf */ - -5, /* (40) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - -2, /* (41) ccons ::= UNIQUE onconf */ - -4, /* (42) ccons ::= CHECK LP expr RP */ - -4, /* (43) ccons ::= REFERENCES nm eidlist_opt refargs */ - -1, /* (44) ccons ::= defer_subclause */ - -2, /* (45) ccons ::= COLLATE ID|STRING */ - -3, /* (46) generated ::= LP expr RP */ - -4, /* (47) generated ::= LP expr RP ID */ - 0, /* (48) autoinc ::= */ - -1, /* (49) autoinc ::= AUTOINCR */ - 0, /* (50) refargs ::= */ - -2, /* (51) refargs ::= refargs refarg */ - -2, /* (52) refarg ::= MATCH nm */ - -3, /* (53) refarg ::= ON INSERT refact */ - -3, /* (54) refarg ::= ON DELETE refact */ - -3, /* (55) refarg ::= ON UPDATE refact */ - -2, /* (56) refact ::= SET NULL */ - -2, /* (57) refact ::= SET DEFAULT */ - -1, /* (58) refact ::= CASCADE */ - -1, /* (59) refact ::= RESTRICT */ - -2, /* (60) refact ::= NO ACTION */ - -3, /* (61) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - -2, /* (62) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 0, /* (63) init_deferred_pred_opt ::= */ - -2, /* (64) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - -2, /* (65) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 0, /* (66) conslist_opt ::= */ - -1, /* (67) tconscomma ::= COMMA */ - -2, /* (68) tcons ::= CONSTRAINT nm */ - -7, /* (69) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - -5, /* (70) tcons ::= UNIQUE LP sortlist RP onconf */ - -5, /* (71) tcons ::= CHECK LP expr RP onconf */ - -10, /* (72) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 0, /* (73) defer_subclause_opt ::= */ - 0, /* (74) onconf ::= */ - -3, /* (75) onconf ::= ON CONFLICT resolvetype */ - 0, /* (76) orconf ::= */ - -2, /* (77) orconf ::= OR resolvetype */ - -1, /* (78) resolvetype ::= IGNORE */ - -1, /* (79) resolvetype ::= REPLACE */ - -4, /* (80) cmd ::= DROP TABLE ifexists fullname */ - -2, /* (81) ifexists ::= IF EXISTS */ - 0, /* (82) ifexists ::= */ - -9, /* (83) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - -4, /* (84) cmd ::= DROP VIEW ifexists fullname */ - -8, /* (85) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING */ - -8, /* (86) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB */ - -4, /* (87) cmd ::= DROP FUNCTION ifexists nm */ - -1, /* (88) cmd ::= select */ - -3, /* (89) select ::= WITH wqlist selectnowith */ - -4, /* (90) select ::= WITH RECURSIVE wqlist selectnowith */ - -1, /* (91) select ::= selectnowith */ - -3, /* (92) selectnowith ::= selectnowith multiselect_op oneselect */ - -1, /* (93) multiselect_op ::= UNION */ - -2, /* (94) multiselect_op ::= UNION ALL */ - -1, /* (95) multiselect_op ::= EXCEPT|INTERSECT */ - -9, /* (96) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - -10, /* (97) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - -4, /* (98) values ::= VALUES LP nexprlist RP */ - -5, /* (99) values ::= values COMMA LP nexprlist RP */ - -1, /* (100) distinct ::= DISTINCT */ - -1, /* (101) distinct ::= ALL */ - 0, /* (102) distinct ::= */ - 0, /* (103) sclp ::= */ - -5, /* (104) selcollist ::= sclp scanpt expr scanpt as */ - -3, /* (105) selcollist ::= sclp scanpt STAR */ - -5, /* (106) selcollist ::= sclp scanpt nm DOT STAR */ - -2, /* (107) as ::= AS nm */ - 0, /* (108) as ::= */ - 0, /* (109) from ::= */ - -2, /* (110) from ::= FROM seltablist */ - -2, /* (111) stl_prefix ::= seltablist joinop */ - 0, /* (112) stl_prefix ::= */ - -5, /* (113) seltablist ::= stl_prefix nm dbnm as on_using */ - -6, /* (114) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ - -8, /* (115) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ - -6, /* (116) seltablist ::= stl_prefix LP select RP as on_using */ - -6, /* (117) seltablist ::= stl_prefix LP seltablist RP as on_using */ - 0, /* (118) dbnm ::= */ - -2, /* (119) dbnm ::= DOT nm */ - -1, /* (120) fullname ::= nm */ - -3, /* (121) fullname ::= nm DOT nm */ - -1, /* (122) xfullname ::= nm */ - -3, /* (123) xfullname ::= nm DOT nm */ - -5, /* (124) xfullname ::= nm DOT nm AS nm */ - -3, /* (125) xfullname ::= nm AS nm */ - -1, /* (126) joinop ::= COMMA|JOIN */ - -2, /* (127) joinop ::= JOIN_KW JOIN */ - -3, /* (128) joinop ::= JOIN_KW nm JOIN */ - -4, /* (129) joinop ::= JOIN_KW nm nm JOIN */ - -2, /* (130) on_using ::= ON expr */ - -4, /* (131) on_using ::= USING LP idlist RP */ - 0, /* (132) on_using ::= */ - 0, /* (133) indexed_opt ::= */ - -3, /* (134) indexed_by ::= INDEXED BY nm */ - -2, /* (135) indexed_by ::= NOT INDEXED */ - 0, /* (136) orderby_opt ::= */ - -3, /* (137) orderby_opt ::= ORDER BY sortlist */ - -5, /* (138) sortlist ::= sortlist COMMA expr sortorder nulls */ - -3, /* (139) sortlist ::= expr sortorder nulls */ - -1, /* (140) sortorder ::= ASC */ - -1, /* (141) sortorder ::= DESC */ - 0, /* (142) sortorder ::= */ - -2, /* (143) nulls ::= NULLS FIRST */ - -2, /* (144) nulls ::= NULLS LAST */ - 0, /* (145) nulls ::= */ - 0, /* (146) groupby_opt ::= */ - -3, /* (147) groupby_opt ::= GROUP BY nexprlist */ - 0, /* (148) having_opt ::= */ - -2, /* (149) having_opt ::= HAVING expr */ - 0, /* (150) limit_opt ::= */ - -2, /* (151) limit_opt ::= LIMIT expr */ - -4, /* (152) limit_opt ::= LIMIT expr OFFSET expr */ - -4, /* (153) limit_opt ::= LIMIT expr COMMA expr */ - -6, /* (154) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 0, /* (155) where_opt ::= */ - -2, /* (156) where_opt ::= WHERE expr */ - 0, /* (157) where_opt_ret ::= */ - -2, /* (158) where_opt_ret ::= WHERE expr */ - -2, /* (159) where_opt_ret ::= RETURNING selcollist */ - -4, /* (160) where_opt_ret ::= WHERE expr RETURNING selcollist */ - -9, /* (161) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - -5, /* (162) setlist ::= setlist COMMA nm EQ expr */ - -7, /* (163) setlist ::= setlist COMMA LP idlist RP EQ expr */ - -3, /* (164) setlist ::= nm EQ expr */ - -5, /* (165) setlist ::= LP idlist RP EQ expr */ - -7, /* (166) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - -8, /* (167) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 0, /* (168) upsert ::= */ - -2, /* (169) upsert ::= RETURNING selcollist */ - -12, /* (170) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - -9, /* (171) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - -5, /* (172) upsert ::= ON CONFLICT DO NOTHING returning */ - -8, /* (173) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - -2, /* (174) returning ::= RETURNING selcollist */ - -2, /* (175) insert_cmd ::= INSERT orconf */ - -1, /* (176) insert_cmd ::= REPLACE */ - 0, /* (177) idlist_opt ::= */ - -3, /* (178) idlist_opt ::= LP idlist RP */ - -3, /* (179) idlist ::= idlist COMMA nm */ - -1, /* (180) idlist ::= nm */ - -3, /* (181) expr ::= LP expr RP */ - -1, /* (182) expr ::= ID|INDEXED */ - -1, /* (183) expr ::= JOIN_KW */ + -1, /* (8) transtype ::= READONLY */ + -2, /* (9) cmd ::= COMMIT|END trans_opt */ + -2, /* (10) cmd ::= ROLLBACK trans_opt */ + -2, /* (11) cmd ::= SAVEPOINT nm */ + -3, /* (12) cmd ::= RELEASE savepoint_opt nm */ + -5, /* (13) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + -6, /* (14) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + -1, /* (15) createkw ::= CREATE */ + 0, /* (16) ifnotexists ::= */ + -3, /* (17) ifnotexists ::= IF NOT EXISTS */ + -1, /* (18) temp ::= TEMP */ + 0, /* (19) temp ::= */ + -5, /* (20) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ + -2, /* (21) create_table_args ::= AS select */ + 0, /* (22) table_option_set ::= */ + -3, /* (23) table_option_set ::= table_option_set COMMA table_option */ + -2, /* (24) table_option ::= WITHOUT nm */ + -2, /* (25) table_option ::= RANDOM nm */ + -1, /* (26) table_option ::= nm */ + -2, /* (27) columnname ::= nm typetoken */ + 0, /* (28) typetoken ::= */ + -4, /* (29) typetoken ::= typename LP signed RP */ + -6, /* (30) typetoken ::= typename LP signed COMMA signed RP */ + -2, /* (31) typename ::= typename ID|STRING */ + 0, /* (32) scanpt ::= */ + 0, /* (33) scantok ::= */ + -2, /* (34) ccons ::= CONSTRAINT nm */ + -3, /* (35) ccons ::= DEFAULT scantok term */ + -4, /* (36) ccons ::= DEFAULT LP expr RP */ + -4, /* (37) ccons ::= DEFAULT PLUS scantok term */ + -4, /* (38) ccons ::= DEFAULT MINUS scantok term */ + -3, /* (39) ccons ::= DEFAULT scantok ID|INDEXED */ + -3, /* (40) ccons ::= NOT NULL onconf */ + -5, /* (41) ccons ::= PRIMARY KEY sortorder onconf autoinc */ + -2, /* (42) ccons ::= UNIQUE onconf */ + -4, /* (43) ccons ::= CHECK LP expr RP */ + -4, /* (44) ccons ::= REFERENCES nm eidlist_opt refargs */ + -1, /* (45) ccons ::= defer_subclause */ + -2, /* (46) ccons ::= COLLATE ID|STRING */ + -3, /* (47) generated ::= LP expr RP */ + -4, /* (48) generated ::= LP expr RP ID */ + 0, /* (49) autoinc ::= */ + -1, /* (50) autoinc ::= AUTOINCR */ + 0, /* (51) refargs ::= */ + -2, /* (52) refargs ::= refargs refarg */ + -2, /* (53) refarg ::= MATCH nm */ + -3, /* (54) refarg ::= ON INSERT refact */ + -3, /* (55) refarg ::= ON DELETE refact */ + -3, /* (56) refarg ::= ON UPDATE refact */ + -2, /* (57) refact ::= SET NULL */ + -2, /* (58) refact ::= SET DEFAULT */ + -1, /* (59) refact ::= CASCADE */ + -1, /* (60) refact ::= RESTRICT */ + -2, /* (61) refact ::= NO ACTION */ + -3, /* (62) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + -2, /* (63) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + 0, /* (64) init_deferred_pred_opt ::= */ + -2, /* (65) init_deferred_pred_opt ::= INITIALLY DEFERRED */ + -2, /* (66) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + 0, /* (67) conslist_opt ::= */ + -1, /* (68) tconscomma ::= COMMA */ + -2, /* (69) tcons ::= CONSTRAINT nm */ + -7, /* (70) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + -5, /* (71) tcons ::= UNIQUE LP sortlist RP onconf */ + -5, /* (72) tcons ::= CHECK LP expr RP onconf */ + -10, /* (73) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + 0, /* (74) defer_subclause_opt ::= */ + 0, /* (75) onconf ::= */ + -3, /* (76) onconf ::= ON CONFLICT resolvetype */ + 0, /* (77) orconf ::= */ + -2, /* (78) orconf ::= OR resolvetype */ + -1, /* (79) resolvetype ::= IGNORE */ + -1, /* (80) resolvetype ::= REPLACE */ + -4, /* (81) cmd ::= DROP TABLE ifexists fullname */ + -2, /* (82) ifexists ::= IF EXISTS */ + 0, /* (83) ifexists ::= */ + -9, /* (84) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + -4, /* (85) cmd ::= DROP VIEW ifexists fullname */ + -8, /* (86) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING */ + -8, /* (87) cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB */ + -4, /* (88) cmd ::= DROP FUNCTION ifexists nm */ + -1, /* (89) cmd ::= select */ + -3, /* (90) select ::= WITH wqlist selectnowith */ + -4, /* (91) select ::= WITH RECURSIVE wqlist selectnowith */ + -1, /* (92) select ::= selectnowith */ + -3, /* (93) selectnowith ::= selectnowith multiselect_op oneselect */ + -1, /* (94) multiselect_op ::= UNION */ + -2, /* (95) multiselect_op ::= UNION ALL */ + -1, /* (96) multiselect_op ::= EXCEPT|INTERSECT */ + -9, /* (97) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + -10, /* (98) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ + -4, /* (99) values ::= VALUES LP nexprlist RP */ + -5, /* (100) values ::= values COMMA LP nexprlist RP */ + -1, /* (101) distinct ::= DISTINCT */ + -1, /* (102) distinct ::= ALL */ + 0, /* (103) distinct ::= */ + 0, /* (104) sclp ::= */ + -5, /* (105) selcollist ::= sclp scanpt expr scanpt as */ + -3, /* (106) selcollist ::= sclp scanpt STAR */ + -5, /* (107) selcollist ::= sclp scanpt nm DOT STAR */ + -2, /* (108) as ::= AS nm */ + 0, /* (109) as ::= */ + 0, /* (110) from ::= */ + -2, /* (111) from ::= FROM seltablist */ + -2, /* (112) stl_prefix ::= seltablist joinop */ + 0, /* (113) stl_prefix ::= */ + -5, /* (114) seltablist ::= stl_prefix nm dbnm as on_using */ + -6, /* (115) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + -8, /* (116) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + -6, /* (117) seltablist ::= stl_prefix LP select RP as on_using */ + -6, /* (118) seltablist ::= stl_prefix LP seltablist RP as on_using */ + 0, /* (119) dbnm ::= */ + -2, /* (120) dbnm ::= DOT nm */ + -1, /* (121) fullname ::= nm */ + -3, /* (122) fullname ::= nm DOT nm */ + -1, /* (123) xfullname ::= nm */ + -3, /* (124) xfullname ::= nm DOT nm */ + -5, /* (125) xfullname ::= nm DOT nm AS nm */ + -3, /* (126) xfullname ::= nm AS nm */ + -1, /* (127) joinop ::= COMMA|JOIN */ + -2, /* (128) joinop ::= JOIN_KW JOIN */ + -3, /* (129) joinop ::= JOIN_KW nm JOIN */ + -4, /* (130) joinop ::= JOIN_KW nm nm JOIN */ + -2, /* (131) on_using ::= ON expr */ + -4, /* (132) on_using ::= USING LP idlist RP */ + 0, /* (133) on_using ::= */ + 0, /* (134) indexed_opt ::= */ + -3, /* (135) indexed_by ::= INDEXED BY nm */ + -2, /* (136) indexed_by ::= NOT INDEXED */ + 0, /* (137) orderby_opt ::= */ + -3, /* (138) orderby_opt ::= ORDER BY sortlist */ + -5, /* (139) sortlist ::= sortlist COMMA expr sortorder nulls */ + -3, /* (140) sortlist ::= expr sortorder nulls */ + -1, /* (141) sortorder ::= ASC */ + -1, /* (142) sortorder ::= DESC */ + 0, /* (143) sortorder ::= */ + -2, /* (144) nulls ::= NULLS FIRST */ + -2, /* (145) nulls ::= NULLS LAST */ + 0, /* (146) nulls ::= */ + 0, /* (147) groupby_opt ::= */ + -3, /* (148) groupby_opt ::= GROUP BY nexprlist */ + 0, /* (149) having_opt ::= */ + -2, /* (150) having_opt ::= HAVING expr */ + 0, /* (151) limit_opt ::= */ + -2, /* (152) limit_opt ::= LIMIT expr */ + -4, /* (153) limit_opt ::= LIMIT expr OFFSET expr */ + -4, /* (154) limit_opt ::= LIMIT expr COMMA expr */ + -6, /* (155) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + 0, /* (156) where_opt ::= */ + -2, /* (157) where_opt ::= WHERE expr */ + 0, /* (158) where_opt_ret ::= */ + -2, /* (159) where_opt_ret ::= WHERE expr */ + -2, /* (160) where_opt_ret ::= RETURNING selcollist */ + -4, /* (161) where_opt_ret ::= WHERE expr RETURNING selcollist */ + -9, /* (162) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + -5, /* (163) setlist ::= setlist COMMA nm EQ expr */ + -7, /* (164) setlist ::= setlist COMMA LP idlist RP EQ expr */ + -3, /* (165) setlist ::= nm EQ expr */ + -5, /* (166) setlist ::= LP idlist RP EQ expr */ + -7, /* (167) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + -8, /* (168) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + 0, /* (169) upsert ::= */ + -2, /* (170) upsert ::= RETURNING selcollist */ + -12, /* (171) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ + -9, /* (172) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ + -5, /* (173) upsert ::= ON CONFLICT DO NOTHING returning */ + -8, /* (174) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ + -2, /* (175) returning ::= RETURNING selcollist */ + -2, /* (176) insert_cmd ::= INSERT orconf */ + -1, /* (177) insert_cmd ::= REPLACE */ + 0, /* (178) idlist_opt ::= */ + -3, /* (179) idlist_opt ::= LP idlist RP */ + -3, /* (180) idlist ::= idlist COMMA nm */ + -1, /* (181) idlist ::= nm */ + -3, /* (182) expr ::= LP expr RP */ + -1, /* (183) expr ::= ID|INDEXED|JOIN_KW */ -3, /* (184) expr ::= nm DOT nm */ -5, /* (185) expr ::= nm DOT nm DOT nm */ -1, /* (186) term ::= NULL|FLOAT|BLOB */ @@ -171507,137 +175175,137 @@ static const signed char yyRuleInfoNRhs[] = { -1, /* (189) expr ::= VARIABLE */ -3, /* (190) expr ::= expr COLLATE ID|STRING */ -6, /* (191) expr ::= CAST LP expr AS typetoken RP */ - -5, /* (192) expr ::= ID|INDEXED LP distinct exprlist RP */ - -4, /* (193) expr ::= ID|INDEXED LP STAR RP */ - -6, /* (194) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */ - -5, /* (195) expr ::= ID|INDEXED LP STAR RP filter_over */ - -1, /* (196) term ::= CTIME_KW */ - -5, /* (197) expr ::= LP nexprlist COMMA expr RP */ - -3, /* (198) expr ::= expr AND expr */ - -3, /* (199) expr ::= expr OR expr */ - -3, /* (200) expr ::= expr LT|GT|GE|LE expr */ - -3, /* (201) expr ::= expr EQ|NE expr */ - -3, /* (202) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - -3, /* (203) expr ::= expr PLUS|MINUS expr */ - -3, /* (204) expr ::= expr STAR|SLASH|REM expr */ - -3, /* (205) expr ::= expr CONCAT expr */ - -2, /* (206) likeop ::= NOT LIKE_KW|MATCH */ - -3, /* (207) expr ::= expr likeop expr */ - -5, /* (208) expr ::= expr likeop expr ESCAPE expr */ - -2, /* (209) expr ::= expr ISNULL|NOTNULL */ - -3, /* (210) expr ::= expr NOT NULL */ - -3, /* (211) expr ::= expr IS expr */ - -4, /* (212) expr ::= expr IS NOT expr */ - -6, /* (213) expr ::= expr IS NOT DISTINCT FROM expr */ - -5, /* (214) expr ::= expr IS DISTINCT FROM expr */ - -2, /* (215) expr ::= NOT expr */ - -2, /* (216) expr ::= BITNOT expr */ - -2, /* (217) expr ::= PLUS|MINUS expr */ - -3, /* (218) expr ::= expr PTR expr */ - -1, /* (219) between_op ::= BETWEEN */ - -2, /* (220) between_op ::= NOT BETWEEN */ - -5, /* (221) expr ::= expr between_op expr AND expr */ - -1, /* (222) in_op ::= IN */ - -2, /* (223) in_op ::= NOT IN */ - -5, /* (224) expr ::= expr in_op LP exprlist RP */ - -3, /* (225) expr ::= LP select RP */ - -5, /* (226) expr ::= expr in_op LP select RP */ - -5, /* (227) expr ::= expr in_op nm dbnm paren_exprlist */ - -4, /* (228) expr ::= EXISTS LP select RP */ - -5, /* (229) expr ::= CASE case_operand case_exprlist case_else END */ - -5, /* (230) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - -4, /* (231) case_exprlist ::= WHEN expr THEN expr */ - -2, /* (232) case_else ::= ELSE expr */ - 0, /* (233) case_else ::= */ - -1, /* (234) case_operand ::= expr */ - 0, /* (235) case_operand ::= */ - 0, /* (236) exprlist ::= */ - -3, /* (237) nexprlist ::= nexprlist COMMA expr */ - -1, /* (238) nexprlist ::= expr */ - 0, /* (239) paren_exprlist ::= */ - -3, /* (240) paren_exprlist ::= LP exprlist RP */ - -12, /* (241) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - -1, /* (242) uniqueflag ::= UNIQUE */ - 0, /* (243) uniqueflag ::= */ - 0, /* (244) eidlist_opt ::= */ - -3, /* (245) eidlist_opt ::= LP eidlist RP */ - -5, /* (246) eidlist ::= eidlist COMMA nm collate sortorder */ - -3, /* (247) eidlist ::= nm collate sortorder */ - 0, /* (248) collate ::= */ - -2, /* (249) collate ::= COLLATE ID|STRING */ - -4, /* (250) cmd ::= DROP INDEX ifexists fullname */ - -2, /* (251) cmd ::= VACUUM vinto */ - -3, /* (252) cmd ::= VACUUM nm vinto */ - -2, /* (253) vinto ::= INTO expr */ - 0, /* (254) vinto ::= */ - -3, /* (255) cmd ::= PRAGMA nm dbnm */ - -5, /* (256) cmd ::= PRAGMA nm dbnm EQ nmnum */ - -6, /* (257) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - -5, /* (258) cmd ::= PRAGMA nm dbnm EQ minus_num */ - -6, /* (259) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - -2, /* (260) plus_num ::= PLUS INTEGER|FLOAT */ - -2, /* (261) minus_num ::= MINUS INTEGER|FLOAT */ - -5, /* (262) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - -11, /* (263) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - -1, /* (264) trigger_time ::= BEFORE|AFTER */ - -2, /* (265) trigger_time ::= INSTEAD OF */ - 0, /* (266) trigger_time ::= */ - -1, /* (267) trigger_event ::= DELETE|INSERT */ - -1, /* (268) trigger_event ::= UPDATE */ - -3, /* (269) trigger_event ::= UPDATE OF idlist */ - 0, /* (270) when_clause ::= */ - -2, /* (271) when_clause ::= WHEN expr */ - -3, /* (272) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - -2, /* (273) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (274) trnm ::= nm DOT nm */ - -3, /* (275) tridxby ::= INDEXED BY nm */ - -2, /* (276) tridxby ::= NOT INDEXED */ - -9, /* (277) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - -8, /* (278) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - -6, /* (279) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - -3, /* (280) trigger_cmd ::= scanpt select scanpt */ - -4, /* (281) expr ::= RAISE LP IGNORE RP */ - -6, /* (282) expr ::= RAISE LP raisetype COMMA nm RP */ - -1, /* (283) raisetype ::= ROLLBACK */ - -1, /* (284) raisetype ::= ABORT */ - -1, /* (285) raisetype ::= FAIL */ - -4, /* (286) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (287) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (288) cmd ::= DETACH database_kw_opt expr */ - 0, /* (289) key_opt ::= */ - -2, /* (290) key_opt ::= KEY expr */ - -1, /* (291) cmd ::= REINDEX */ - -3, /* (292) cmd ::= REINDEX nm dbnm */ - -1, /* (293) cmd ::= ANALYZE */ - -3, /* (294) cmd ::= ANALYZE nm dbnm */ - -6, /* (295) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -7, /* (296) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - -6, /* (297) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -1, /* (298) add_column_fullname ::= fullname */ - -8, /* (299) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -1, /* (300) cmd ::= create_vtab */ - -4, /* (301) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (302) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (303) vtabarg ::= */ - -1, /* (304) vtabargtoken ::= ANY */ - -3, /* (305) vtabargtoken ::= lp anylist RP */ - -1, /* (306) lp ::= LP */ - -2, /* (307) with ::= WITH wqlist */ - -3, /* (308) with ::= WITH RECURSIVE wqlist */ - -1, /* (309) wqas ::= AS */ - -2, /* (310) wqas ::= AS MATERIALIZED */ - -3, /* (311) wqas ::= AS NOT MATERIALIZED */ - -6, /* (312) wqitem ::= nm eidlist_opt wqas LP select RP */ - -1, /* (313) wqlist ::= wqitem */ - -3, /* (314) wqlist ::= wqlist COMMA wqitem */ - -1, /* (315) windowdefn_list ::= windowdefn */ - -3, /* (316) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (317) windowdefn ::= nm AS LP window RP */ - -5, /* (318) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (319) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (320) window ::= ORDER BY sortlist frame_opt */ - -5, /* (321) window ::= nm ORDER BY sortlist frame_opt */ - -1, /* (322) window ::= frame_opt */ + -5, /* (192) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ + -8, /* (193) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ + -4, /* (194) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ + -6, /* (195) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ + -9, /* (196) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ + -5, /* (197) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ + -1, /* (198) term ::= CTIME_KW */ + -5, /* (199) expr ::= LP nexprlist COMMA expr RP */ + -3, /* (200) expr ::= expr AND expr */ + -3, /* (201) expr ::= expr OR expr */ + -3, /* (202) expr ::= expr LT|GT|GE|LE expr */ + -3, /* (203) expr ::= expr EQ|NE expr */ + -3, /* (204) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + -3, /* (205) expr ::= expr PLUS|MINUS expr */ + -3, /* (206) expr ::= expr STAR|SLASH|REM expr */ + -3, /* (207) expr ::= expr CONCAT expr */ + -2, /* (208) likeop ::= NOT LIKE_KW|MATCH */ + -3, /* (209) expr ::= expr likeop expr */ + -5, /* (210) expr ::= expr likeop expr ESCAPE expr */ + -2, /* (211) expr ::= expr ISNULL|NOTNULL */ + -3, /* (212) expr ::= expr NOT NULL */ + -3, /* (213) expr ::= expr IS expr */ + -4, /* (214) expr ::= expr IS NOT expr */ + -6, /* (215) expr ::= expr IS NOT DISTINCT FROM expr */ + -5, /* (216) expr ::= expr IS DISTINCT FROM expr */ + -2, /* (217) expr ::= NOT expr */ + -2, /* (218) expr ::= BITNOT expr */ + -2, /* (219) expr ::= PLUS|MINUS expr */ + -3, /* (220) expr ::= expr PTR expr */ + -1, /* (221) between_op ::= BETWEEN */ + -2, /* (222) between_op ::= NOT BETWEEN */ + -5, /* (223) expr ::= expr between_op expr AND expr */ + -1, /* (224) in_op ::= IN */ + -2, /* (225) in_op ::= NOT IN */ + -5, /* (226) expr ::= expr in_op LP exprlist RP */ + -3, /* (227) expr ::= LP select RP */ + -5, /* (228) expr ::= expr in_op LP select RP */ + -5, /* (229) expr ::= expr in_op nm dbnm paren_exprlist */ + -4, /* (230) expr ::= EXISTS LP select RP */ + -5, /* (231) expr ::= CASE case_operand case_exprlist case_else END */ + -5, /* (232) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + -4, /* (233) case_exprlist ::= WHEN expr THEN expr */ + -2, /* (234) case_else ::= ELSE expr */ + 0, /* (235) case_else ::= */ + 0, /* (236) case_operand ::= */ + 0, /* (237) exprlist ::= */ + -3, /* (238) nexprlist ::= nexprlist COMMA expr */ + -1, /* (239) nexprlist ::= expr */ + 0, /* (240) paren_exprlist ::= */ + -3, /* (241) paren_exprlist ::= LP exprlist RP */ + -12, /* (242) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + -1, /* (243) uniqueflag ::= UNIQUE */ + 0, /* (244) uniqueflag ::= */ + 0, /* (245) eidlist_opt ::= */ + -3, /* (246) eidlist_opt ::= LP eidlist RP */ + -5, /* (247) eidlist ::= eidlist COMMA nm collate sortorder */ + -3, /* (248) eidlist ::= nm collate sortorder */ + 0, /* (249) collate ::= */ + -2, /* (250) collate ::= COLLATE ID|STRING */ + -4, /* (251) cmd ::= DROP INDEX ifexists fullname */ + -2, /* (252) cmd ::= VACUUM vinto */ + -3, /* (253) cmd ::= VACUUM nm vinto */ + -2, /* (254) vinto ::= INTO expr */ + 0, /* (255) vinto ::= */ + -3, /* (256) cmd ::= PRAGMA nm dbnm */ + -5, /* (257) cmd ::= PRAGMA nm dbnm EQ nmnum */ + -6, /* (258) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + -5, /* (259) cmd ::= PRAGMA nm dbnm EQ minus_num */ + -6, /* (260) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + -2, /* (261) plus_num ::= PLUS INTEGER|FLOAT */ + -2, /* (262) minus_num ::= MINUS INTEGER|FLOAT */ + -5, /* (263) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + -11, /* (264) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + -1, /* (265) trigger_time ::= BEFORE|AFTER */ + -2, /* (266) trigger_time ::= INSTEAD OF */ + 0, /* (267) trigger_time ::= */ + -1, /* (268) trigger_event ::= DELETE|INSERT */ + -1, /* (269) trigger_event ::= UPDATE */ + -3, /* (270) trigger_event ::= UPDATE OF idlist */ + 0, /* (271) when_clause ::= */ + -2, /* (272) when_clause ::= WHEN expr */ + -3, /* (273) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + -2, /* (274) trigger_cmd_list ::= trigger_cmd SEMI */ + -3, /* (275) trnm ::= nm DOT nm */ + -3, /* (276) tridxby ::= INDEXED BY nm */ + -2, /* (277) tridxby ::= NOT INDEXED */ + -9, /* (278) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + -8, /* (279) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + -6, /* (280) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + -3, /* (281) trigger_cmd ::= scanpt select scanpt */ + -4, /* (282) expr ::= RAISE LP IGNORE RP */ + -6, /* (283) expr ::= RAISE LP raisetype COMMA nm RP */ + -1, /* (284) raisetype ::= ROLLBACK */ + -1, /* (285) raisetype ::= ABORT */ + -1, /* (286) raisetype ::= FAIL */ + -4, /* (287) cmd ::= DROP TRIGGER ifexists fullname */ + -6, /* (288) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + -3, /* (289) cmd ::= DETACH database_kw_opt expr */ + 0, /* (290) key_opt ::= */ + -2, /* (291) key_opt ::= KEY expr */ + -1, /* (292) cmd ::= REINDEX */ + -3, /* (293) cmd ::= REINDEX nm dbnm */ + -1, /* (294) cmd ::= ANALYZE */ + -3, /* (295) cmd ::= ANALYZE nm dbnm */ + -6, /* (296) cmd ::= ALTER TABLE fullname RENAME TO nm */ + -7, /* (297) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + -6, /* (298) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + -1, /* (299) add_column_fullname ::= fullname */ + -8, /* (300) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + -9, /* (301) cmd ::= ALTER TABLE fullname ALTER COLUMNKW columnname TO columnname carglist */ + -1, /* (302) cmd ::= create_vtab */ + -4, /* (303) cmd ::= create_vtab LP vtabarglist RP */ + -8, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 0, /* (305) vtabarg ::= */ + -1, /* (306) vtabargtoken ::= ANY */ + -3, /* (307) vtabargtoken ::= lp anylist RP */ + -1, /* (308) lp ::= LP */ + -2, /* (309) with ::= WITH wqlist */ + -3, /* (310) with ::= WITH RECURSIVE wqlist */ + -1, /* (311) wqas ::= AS */ + -2, /* (312) wqas ::= AS MATERIALIZED */ + -3, /* (313) wqas ::= AS NOT MATERIALIZED */ + -6, /* (314) wqitem ::= nm eidlist_opt wqas LP select RP */ + -1, /* (315) wqlist ::= wqitem */ + -3, /* (316) wqlist ::= wqlist COMMA wqitem */ + -3, /* (317) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + -5, /* (318) windowdefn ::= nm AS LP window RP */ + -5, /* (319) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (320) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (321) window ::= ORDER BY sortlist frame_opt */ + -5, /* (322) window ::= nm ORDER BY sortlist frame_opt */ -2, /* (323) window ::= nm frame_opt */ 0, /* (324) frame_opt ::= */ -3, /* (325) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ @@ -171676,32 +175344,32 @@ static const signed char yyRuleInfoNRhs[] = { -1, /* (358) table_option_set ::= table_option */ -4, /* (359) columnlist ::= columnlist COMMA columnname carglist */ -2, /* (360) columnlist ::= columnname carglist */ - -1, /* (361) nm ::= ID|INDEXED */ + -1, /* (361) nm ::= ID|INDEXED|JOIN_KW */ -1, /* (362) nm ::= STRING */ - -1, /* (363) nm ::= JOIN_KW */ - -1, /* (364) typetoken ::= typename */ - -1, /* (365) typename ::= ID|STRING */ - -1, /* (366) signed ::= plus_num */ - -1, /* (367) signed ::= minus_num */ - -2, /* (368) carglist ::= carglist ccons */ - 0, /* (369) carglist ::= */ - -2, /* (370) ccons ::= NULL onconf */ - -4, /* (371) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (372) ccons ::= AS generated */ - -2, /* (373) conslist_opt ::= COMMA conslist */ - -3, /* (374) conslist ::= conslist tconscomma tcons */ - -1, /* (375) conslist ::= tcons */ - 0, /* (376) tconscomma ::= */ - -1, /* (377) defer_subclause_opt ::= defer_subclause */ - -1, /* (378) resolvetype ::= raisetype */ - -1, /* (379) selectnowith ::= oneselect */ - -1, /* (380) oneselect ::= values */ - -2, /* (381) sclp ::= selcollist COMMA */ - -1, /* (382) as ::= ID|STRING */ - -1, /* (383) indexed_opt ::= indexed_by */ - 0, /* (384) returning ::= */ - -1, /* (385) expr ::= term */ - -1, /* (386) likeop ::= LIKE_KW|MATCH */ + -1, /* (363) typetoken ::= typename */ + -1, /* (364) typename ::= ID|STRING */ + -1, /* (365) signed ::= plus_num */ + -1, /* (366) signed ::= minus_num */ + -2, /* (367) carglist ::= carglist ccons */ + 0, /* (368) carglist ::= */ + -2, /* (369) ccons ::= NULL onconf */ + -4, /* (370) ccons ::= GENERATED ALWAYS AS generated */ + -2, /* (371) ccons ::= AS generated */ + -2, /* (372) conslist_opt ::= COMMA conslist */ + -3, /* (373) conslist ::= conslist tconscomma tcons */ + -1, /* (374) conslist ::= tcons */ + 0, /* (375) tconscomma ::= */ + -1, /* (376) defer_subclause_opt ::= defer_subclause */ + -1, /* (377) resolvetype ::= raisetype */ + -1, /* (378) selectnowith ::= oneselect */ + -1, /* (379) oneselect ::= values */ + -2, /* (380) sclp ::= selcollist COMMA */ + -1, /* (381) as ::= ID|STRING */ + -1, /* (382) indexed_opt ::= indexed_by */ + 0, /* (383) returning ::= */ + -1, /* (384) expr ::= term */ + -1, /* (385) likeop ::= LIKE_KW|MATCH */ + -1, /* (386) case_operand ::= expr */ -1, /* (387) exprlist ::= nexprlist */ -1, /* (388) nmnum ::= plus_num */ -1, /* (389) nmnum ::= nm */ @@ -171724,6 +175392,8 @@ static const signed char yyRuleInfoNRhs[] = { -4, /* (406) anylist ::= anylist LP anylist RP */ -2, /* (407) anylist ::= anylist ANY */ 0, /* (408) with ::= */ + -1, /* (409) windowdefn_list ::= windowdefn */ + -1, /* (410) window ::= frame_opt */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -171766,171 +175436,174 @@ static YYACTIONTYPE yy_reduce( /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* explain ::= EXPLAIN */ -{ pParse->explain = 1; } +{ if( pParse->pReprepare==0 ) pParse->explain = 1; } break; case 1: /* explain ::= EXPLAIN QUERY PLAN */ -{ pParse->explain = 2; } +{ if( pParse->pReprepare==0 ) pParse->explain = 2; } break; case 2: /* cmdx ::= cmd */ { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy436);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy144);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy436 = TK_DEFERRED;} +{yymsp[1].minor.yy144 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); case 327: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==327); -{yymsp[0].minor.yy436 = yymsp[0].major; /*A-overwrites-X*/} +{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/} break; - case 8: /* cmd ::= COMMIT|END trans_opt */ - case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); + case 8: /* transtype ::= READONLY */ +{yymsp[0].minor.yy144 = TK_DEFERRED; /*yymsp[0].minor.yy144-overwrites-X*/} + break; + case 9: /* cmd ::= COMMIT|END trans_opt */ + case 10: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==10); {sqlite3EndTransaction(pParse,yymsp[-1].major);} break; - case 10: /* cmd ::= SAVEPOINT nm */ + case 11: /* cmd ::= SAVEPOINT nm */ { sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0); } break; - case 11: /* cmd ::= RELEASE savepoint_opt nm */ + case 12: /* cmd ::= RELEASE savepoint_opt nm */ { sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0); } break; - case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + case 13: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ { sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0); } break; - case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + case 14: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy436,0,0,yymsp[-2].minor.yy436); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy144,0,0,yymsp[-2].minor.yy144); } break; - case 14: /* createkw ::= CREATE */ + case 15: /* createkw ::= CREATE */ {disableLookaside(pParse);} break; - case 15: /* ifnotexists ::= */ - case 18: /* temp ::= */ yytestcase(yyruleno==18); - case 48: /* autoinc ::= */ yytestcase(yyruleno==48); - case 63: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==63); - case 73: /* defer_subclause_opt ::= */ yytestcase(yyruleno==73); - case 82: /* ifexists ::= */ yytestcase(yyruleno==82); - case 102: /* distinct ::= */ yytestcase(yyruleno==102); - case 248: /* collate ::= */ yytestcase(yyruleno==248); -{yymsp[1].minor.yy436 = 0;} + case 16: /* ifnotexists ::= */ + case 19: /* temp ::= */ yytestcase(yyruleno==19); + case 49: /* autoinc ::= */ yytestcase(yyruleno==49); + case 64: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==64); + case 74: /* defer_subclause_opt ::= */ yytestcase(yyruleno==74); + case 83: /* ifexists ::= */ yytestcase(yyruleno==83); + case 103: /* distinct ::= */ yytestcase(yyruleno==103); + case 249: /* collate ::= */ yytestcase(yyruleno==249); +{yymsp[1].minor.yy144 = 0;} break; - case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy436 = 1;} + case 17: /* ifnotexists ::= IF NOT EXISTS */ +{yymsp[-2].minor.yy144 = 1;} break; - case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy436 = pParse->db->init.busy==0;} + case 18: /* temp ::= TEMP */ +{yymsp[0].minor.yy144 = pParse->db->init.busy==0;} break; - case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ + case 20: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy135,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy391,0); } break; - case 20: /* create_table_args ::= AS select */ + case 21: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy136); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy136); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy555); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); } break; - case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy135 = 0;} + case 22: /* table_option_set ::= */ +{yymsp[1].minor.yy391 = 0;} break; - case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy135 = yymsp[-2].minor.yy135|yymsp[0].minor.yy135;} - yymsp[-2].minor.yy135 = yylhsminor.yy135; + case 23: /* table_option_set ::= table_option_set COMMA table_option */ +{yylhsminor.yy391 = yymsp[-2].minor.yy391|yymsp[0].minor.yy391;} + yymsp[-2].minor.yy391 = yylhsminor.yy391; break; - case 23: /* table_option ::= WITHOUT nm */ + case 24: /* table_option ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy135 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy391 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy135 = 0; + yymsp[-1].minor.yy391 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } break; - case 24: /* table_option ::= RANDOM nm */ + case 25: /* table_option ::= RANDOM nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy135 = TF_RandomRowid; + yymsp[-1].minor.yy391 = TF_RandomRowid; }else{ - yymsp[-1].minor.yy135 = 0; + yymsp[-1].minor.yy391 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } break; - case 25: /* table_option ::= nm */ + case 26: /* table_option ::= nm */ { if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy135 = TF_Strict; + yylhsminor.yy391 = TF_Strict; }else{ - yylhsminor.yy135 = 0; + yylhsminor.yy391 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } - yymsp[0].minor.yy135 = yylhsminor.yy135; + yymsp[0].minor.yy391 = yylhsminor.yy391; break; - case 26: /* columnname ::= nm typetoken */ + case 27: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} break; - case 27: /* typetoken ::= */ - case 66: /* conslist_opt ::= */ yytestcase(yyruleno==66); - case 108: /* as ::= */ yytestcase(yyruleno==108); + case 28: /* typetoken ::= */ + case 67: /* conslist_opt ::= */ yytestcase(yyruleno==67); + case 109: /* as ::= */ yytestcase(yyruleno==109); {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} break; - case 28: /* typetoken ::= typename LP signed RP */ + case 29: /* 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 29: /* typetoken ::= typename LP signed COMMA signed RP */ + case 30: /* 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 30: /* typename ::= typename ID|STRING */ + case 31: /* 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 31: /* scanpt ::= */ + case 32: /* scanpt ::= */ { assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy594 = yyLookaheadToken.z; + yymsp[1].minor.yy168 = yyLookaheadToken.z; } break; - case 32: /* scantok ::= */ + case 33: /* scantok ::= */ { assert( yyLookahead!=YYNOCODE ); yymsp[1].minor.yy0 = yyLookaheadToken; } break; - case 33: /* ccons ::= CONSTRAINT nm */ - case 68: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==68); + case 34: /* ccons ::= CONSTRAINT nm */ + case 69: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==69); {pParse->constraintName = yymsp[0].minor.yy0;} break; - case 34: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy224,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} + case 35: /* ccons ::= DEFAULT scantok term */ +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; - case 35: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy224,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} + case 36: /* ccons ::= DEFAULT LP expr RP */ +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; - case 36: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy224,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} + case 37: /* ccons ::= DEFAULT PLUS scantok term */ +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; - case 37: /* ccons ::= DEFAULT MINUS scantok term */ + case 38: /* ccons ::= DEFAULT MINUS scantok term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy224, 0); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy454, 0); sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); } break; - case 38: /* ccons ::= DEFAULT scantok ID|INDEXED */ + case 39: /* ccons ::= DEFAULT scantok ID|INDEXED */ { Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0); if( p ){ @@ -171940,177 +175613,176 @@ static YYACTIONTYPE yy_reduce( sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); } break; - case 39: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy436);} + case 40: /* ccons ::= NOT NULL onconf */ +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy144);} break; - case 40: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy436,yymsp[0].minor.yy436,yymsp[-2].minor.yy436);} + case 41: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy144,yymsp[0].minor.yy144,yymsp[-2].minor.yy144);} break; - case 41: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy436,0,0,0,0, + case 42: /* ccons ::= UNIQUE onconf */ +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy144,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 42: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy224,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} + case 43: /* ccons ::= CHECK LP expr RP */ +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} break; - case 43: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy586,yymsp[0].minor.yy436);} + case 44: /* ccons ::= REFERENCES nm eidlist_opt refargs */ +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy144);} break; - case 44: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy436);} + case 45: /* ccons ::= defer_subclause */ +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy144);} break; - case 45: /* ccons ::= COLLATE ID|STRING */ + case 46: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; - case 46: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy224,0);} + case 47: /* generated ::= LP expr RP */ +{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy454,0);} break; - case 47: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy224,&yymsp[0].minor.yy0);} + case 48: /* generated ::= LP expr RP ID */ +{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy454,&yymsp[0].minor.yy0);} break; - case 49: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy436 = 1;} + case 50: /* autoinc ::= AUTOINCR */ +{yymsp[0].minor.yy144 = 1;} break; - case 50: /* refargs ::= */ -{ yymsp[1].minor.yy436 = OE_None*0x0101; /* EV: R-19803-45884 */} + case 51: /* refargs ::= */ +{ yymsp[1].minor.yy144 = OE_None*0x0101; /* EV: R-19803-45884 */} break; - case 51: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy436 = (yymsp[-1].minor.yy436 & ~yymsp[0].minor.yy275.mask) | yymsp[0].minor.yy275.value; } + case 52: /* refargs ::= refargs refarg */ +{ yymsp[-1].minor.yy144 = (yymsp[-1].minor.yy144 & ~yymsp[0].minor.yy383.mask) | yymsp[0].minor.yy383.value; } break; - case 52: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy275.value = 0; yymsp[-1].minor.yy275.mask = 0x000000; } + case 53: /* refarg ::= MATCH nm */ +{ yymsp[-1].minor.yy383.value = 0; yymsp[-1].minor.yy383.mask = 0x000000; } break; - case 53: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy275.value = 0; yymsp[-2].minor.yy275.mask = 0x000000; } + case 54: /* refarg ::= ON INSERT refact */ +{ yymsp[-2].minor.yy383.value = 0; yymsp[-2].minor.yy383.mask = 0x000000; } break; - case 54: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy275.value = yymsp[0].minor.yy436; yymsp[-2].minor.yy275.mask = 0x0000ff; } + case 55: /* refarg ::= ON DELETE refact */ +{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144; yymsp[-2].minor.yy383.mask = 0x0000ff; } break; - case 55: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy275.value = yymsp[0].minor.yy436<<8; yymsp[-2].minor.yy275.mask = 0x00ff00; } + case 56: /* refarg ::= ON UPDATE refact */ +{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144<<8; yymsp[-2].minor.yy383.mask = 0x00ff00; } break; - case 56: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy436 = OE_SetNull; /* EV: R-33326-45252 */} + case 57: /* refact ::= SET NULL */ +{ yymsp[-1].minor.yy144 = OE_SetNull; /* EV: R-33326-45252 */} break; - case 57: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy436 = OE_SetDflt; /* EV: R-33326-45252 */} + case 58: /* refact ::= SET DEFAULT */ +{ yymsp[-1].minor.yy144 = OE_SetDflt; /* EV: R-33326-45252 */} break; - case 58: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy436 = OE_Cascade; /* EV: R-33326-45252 */} + case 59: /* refact ::= CASCADE */ +{ yymsp[0].minor.yy144 = OE_Cascade; /* EV: R-33326-45252 */} break; - case 59: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy436 = OE_Restrict; /* EV: R-33326-45252 */} + case 60: /* refact ::= RESTRICT */ +{ yymsp[0].minor.yy144 = OE_Restrict; /* EV: R-33326-45252 */} break; - case 60: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy436 = OE_None; /* EV: R-33326-45252 */} + case 61: /* refact ::= NO ACTION */ +{ yymsp[-1].minor.yy144 = OE_None; /* EV: R-33326-45252 */} break; - case 61: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy436 = 0;} + case 62: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ +{yymsp[-2].minor.yy144 = 0;} break; - case 62: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 77: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==77); - case 175: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==175); -{yymsp[-1].minor.yy436 = yymsp[0].minor.yy436;} + case 63: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 78: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==78); + case 176: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==176); +{yymsp[-1].minor.yy144 = yymsp[0].minor.yy144;} break; - case 64: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ - case 81: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==81); - case 220: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==220); - case 223: /* in_op ::= NOT IN */ yytestcase(yyruleno==223); - case 249: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==249); -{yymsp[-1].minor.yy436 = 1;} + case 65: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ + case 82: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==82); + case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); + case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); + case 250: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==250); +{yymsp[-1].minor.yy144 = 1;} break; - case 65: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy436 = 0;} + case 66: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ +{yymsp[-1].minor.yy144 = 0;} break; - case 67: /* tconscomma ::= COMMA */ + case 68: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; - case 69: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy586,yymsp[0].minor.yy436,yymsp[-2].minor.yy436,0);} + case 70: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy144,yymsp[-2].minor.yy144,0);} break; - case 70: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy586,yymsp[0].minor.yy436,0,0,0,0, + case 71: /* tcons ::= UNIQUE LP sortlist RP onconf */ +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy144,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 71: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy224,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} + case 72: /* tcons ::= CHECK LP expr RP onconf */ +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy454,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} break; - case 72: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + case 73: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy586, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy586, yymsp[-1].minor.yy436); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy436); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy144); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy144); } break; - case 74: /* onconf ::= */ - case 76: /* orconf ::= */ yytestcase(yyruleno==76); -{yymsp[1].minor.yy436 = OE_Default;} + case 75: /* onconf ::= */ + case 77: /* orconf ::= */ yytestcase(yyruleno==77); +{yymsp[1].minor.yy144 = OE_Default;} break; - case 75: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy436 = yymsp[0].minor.yy436;} + case 76: /* onconf ::= ON CONFLICT resolvetype */ +{yymsp[-2].minor.yy144 = yymsp[0].minor.yy144;} break; - case 78: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy436 = OE_Ignore;} + case 79: /* resolvetype ::= IGNORE */ +{yymsp[0].minor.yy144 = OE_Ignore;} break; - case 79: /* resolvetype ::= REPLACE */ - case 176: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==176); -{yymsp[0].minor.yy436 = OE_Replace;} + case 80: /* resolvetype ::= REPLACE */ + case 177: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==177); +{yymsp[0].minor.yy144 = OE_Replace;} break; - case 80: /* cmd ::= DROP TABLE ifexists fullname */ + case 81: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy493, 0, yymsp[-1].minor.yy436); + sqlite3DropTable(pParse, yymsp[0].minor.yy203, 0, yymsp[-1].minor.yy144); } break; - case 83: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + case 84: /* 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.yy586, yymsp[0].minor.yy136, yymsp[-7].minor.yy436, yymsp[-5].minor.yy436); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[0].minor.yy555, yymsp[-7].minor.yy144, yymsp[-5].minor.yy144); } break; - case 84: /* cmd ::= DROP VIEW ifexists fullname */ + case 85: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy493, 1, yymsp[-1].minor.yy436); + sqlite3DropTable(pParse, yymsp[0].minor.yy203, 1, yymsp[-1].minor.yy144); } break; - case 85: /* cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING */ + case 86: /* cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS STRING */ { - libsql_create_function(pParse, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, 0, yymsp[-5].minor.yy436); + libsql_create_function(pParse, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, 0, yymsp[-5].minor.yy144); } break; - case 86: /* cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB */ + case 87: /* cmd ::= createkw FUNCTION ifnotexists nm LANGUAGE nm AS BLOB */ { - libsql_create_function(pParse, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, 1, yymsp[-5].minor.yy436); + libsql_create_function(pParse, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, 1, yymsp[-5].minor.yy144); } break; - case 87: /* cmd ::= DROP FUNCTION ifexists nm */ + case 88: /* cmd ::= DROP FUNCTION ifexists nm */ { - libsql_drop_function(pParse, &yymsp[0].minor.yy0, yymsp[-1].minor.yy436); + libsql_drop_function(pParse, &yymsp[0].minor.yy0, yymsp[-1].minor.yy144); } break; - case 88: /* cmd ::= select */ + case 89: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy136, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy136); + sqlite3Select(pParse, yymsp[0].minor.yy555, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); } break; - case 89: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy136 = attachWithToSelect(pParse,yymsp[0].minor.yy136,yymsp[-1].minor.yy19);} + case 90: /* select ::= WITH wqlist selectnowith */ +{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} break; - case 90: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy136 = attachWithToSelect(pParse,yymsp[0].minor.yy136,yymsp[-1].minor.yy19);} + case 91: /* select ::= WITH RECURSIVE wqlist selectnowith */ +{yymsp[-3].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} break; - case 91: /* select ::= selectnowith */ + case 92: /* select ::= selectnowith */ { - Select *p = yymsp[0].minor.yy136; + Select *p = yymsp[0].minor.yy555; if( p ){ parserDoubleLinkSelect(pParse, p); } - yymsp[0].minor.yy136 = p; /*A-overwrites-X*/ } break; - case 92: /* selectnowith ::= selectnowith multiselect_op oneselect */ + case 93: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy136; - Select *pLhs = yymsp[-2].minor.yy136; + Select *pRhs = yymsp[0].minor.yy555; + Select *pLhs = yymsp[-2].minor.yy555; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -172120,145 +175792,148 @@ static YYACTIONTYPE yy_reduce( pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy436; + pRhs->op = (u8)yymsp[-1].minor.yy144; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy436!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy144!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy136 = pRhs; + yymsp[-2].minor.yy555 = pRhs; } break; - case 93: /* multiselect_op ::= UNION */ - case 95: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==95); -{yymsp[0].minor.yy436 = yymsp[0].major; /*A-overwrites-OP*/} + case 94: /* multiselect_op ::= UNION */ + case 96: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==96); +{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-OP*/} break; - case 94: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy436 = TK_ALL;} + case 95: /* multiselect_op ::= UNION ALL */ +{yymsp[-1].minor.yy144 = TK_ALL;} break; - case 96: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + case 97: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yymsp[-8].minor.yy136 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy586,yymsp[-5].minor.yy493,yymsp[-4].minor.yy224,yymsp[-3].minor.yy586,yymsp[-2].minor.yy224,yymsp[-1].minor.yy586,yymsp[-7].minor.yy436,yymsp[0].minor.yy224); + yymsp[-8].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy203,yymsp[-4].minor.yy454,yymsp[-3].minor.yy14,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[-7].minor.yy144,yymsp[0].minor.yy454); } break; - case 97: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ + case 98: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ { - yymsp[-9].minor.yy136 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy586,yymsp[-6].minor.yy493,yymsp[-5].minor.yy224,yymsp[-4].minor.yy586,yymsp[-3].minor.yy224,yymsp[-1].minor.yy586,yymsp[-8].minor.yy436,yymsp[0].minor.yy224); - if( yymsp[-9].minor.yy136 ){ - yymsp[-9].minor.yy136->pWinDefn = yymsp[-2].minor.yy591; + yymsp[-9].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy14,yymsp[-6].minor.yy203,yymsp[-5].minor.yy454,yymsp[-4].minor.yy14,yymsp[-3].minor.yy454,yymsp[-1].minor.yy14,yymsp[-8].minor.yy144,yymsp[0].minor.yy454); + if( yymsp[-9].minor.yy555 ){ + yymsp[-9].minor.yy555->pWinDefn = yymsp[-2].minor.yy211; }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy591); + sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy211); } } break; - case 98: /* values ::= VALUES LP nexprlist RP */ + case 99: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy136 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy586,0,0,0,0,0,SF_Values,0); + yymsp[-3].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0); } break; - case 99: /* values ::= values COMMA LP nexprlist RP */ + case 100: /* values ::= values COMMA LP nexprlist RP */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy136; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy586,0,0,0,0,0,SF_Values|SF_MultiValue,0); + Select *pRight, *pLeft = yymsp[-4].minor.yy555; + pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values|SF_MultiValue,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; pRight->pPrior = pLeft; - yymsp[-4].minor.yy136 = pRight; + yymsp[-4].minor.yy555 = pRight; }else{ - yymsp[-4].minor.yy136 = pLeft; + yymsp[-4].minor.yy555 = pLeft; } } break; - case 100: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy436 = SF_Distinct;} + case 101: /* distinct ::= DISTINCT */ +{yymsp[0].minor.yy144 = SF_Distinct;} break; - case 101: /* distinct ::= ALL */ -{yymsp[0].minor.yy436 = SF_All;} + case 102: /* distinct ::= ALL */ +{yymsp[0].minor.yy144 = SF_All;} break; - case 103: /* sclp ::= */ - case 136: /* orderby_opt ::= */ yytestcase(yyruleno==136); - case 146: /* groupby_opt ::= */ yytestcase(yyruleno==146); - case 236: /* exprlist ::= */ yytestcase(yyruleno==236); - case 239: /* paren_exprlist ::= */ yytestcase(yyruleno==239); - case 244: /* eidlist_opt ::= */ yytestcase(yyruleno==244); -{yymsp[1].minor.yy586 = 0;} + case 104: /* sclp ::= */ + case 137: /* orderby_opt ::= */ yytestcase(yyruleno==137); + case 147: /* groupby_opt ::= */ yytestcase(yyruleno==147); + case 237: /* exprlist ::= */ yytestcase(yyruleno==237); + case 240: /* paren_exprlist ::= */ yytestcase(yyruleno==240); + case 245: /* eidlist_opt ::= */ yytestcase(yyruleno==245); +{yymsp[1].minor.yy14 = 0;} break; - case 104: /* selcollist ::= sclp scanpt expr scanpt as */ + case 105: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-4].minor.yy586 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy586, yymsp[-2].minor.yy224); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy586, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy586,yymsp[-3].minor.yy594,yymsp[-1].minor.yy594); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy14,yymsp[-3].minor.yy168,yymsp[-1].minor.yy168); } break; - case 105: /* selcollist ::= sclp scanpt STAR */ + case 106: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - yymsp[-2].minor.yy586 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy586, p); + sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); + yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, p); } break; - case 106: /* selcollist ::= sclp scanpt nm DOT STAR */ + case 107: /* selcollist ::= sclp scanpt nm DOT STAR */ { - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - Expr *pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); - Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy586 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy586, pDot); -} - break; - case 107: /* as ::= AS nm */ - case 119: /* dbnm ::= DOT nm */ yytestcase(yyruleno==119); - case 260: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==260); - case 261: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==261); + 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.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, pDot); +} + break; + case 108: /* as ::= AS nm */ + case 120: /* dbnm ::= DOT nm */ yytestcase(yyruleno==120); + case 261: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==261); + case 262: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==262); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; - case 109: /* from ::= */ - case 112: /* stl_prefix ::= */ yytestcase(yyruleno==112); -{yymsp[1].minor.yy493 = 0;} + case 110: /* from ::= */ + case 113: /* stl_prefix ::= */ yytestcase(yyruleno==113); +{yymsp[1].minor.yy203 = 0;} break; - case 110: /* from ::= FROM seltablist */ + case 111: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy493 = yymsp[0].minor.yy493; - sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy493); + yymsp[-1].minor.yy203 = yymsp[0].minor.yy203; + sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy203); } break; - case 111: /* stl_prefix ::= seltablist joinop */ + case 112: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy493 && yymsp[-1].minor.yy493->nSrc>0) ) yymsp[-1].minor.yy493->a[yymsp[-1].minor.yy493->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy436; + if( ALWAYS(yymsp[-1].minor.yy203 && yymsp[-1].minor.yy203->nSrc>0) ) yymsp[-1].minor.yy203->a[yymsp[-1].minor.yy203->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy144; } break; - case 113: /* seltablist ::= stl_prefix nm dbnm as on_using */ + case 114: /* seltablist ::= stl_prefix nm dbnm as on_using */ { - yymsp[-4].minor.yy493 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy493,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy5); + yymsp[-4].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy203,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); } break; - case 114: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + case 115: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ { - yymsp[-5].minor.yy493 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy493,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy5); - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy493, &yymsp[-1].minor.yy0); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy269); + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-1].minor.yy0); } break; - case 115: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + case 116: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ { - yymsp[-7].minor.yy493 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy493,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy5); - sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy493, yymsp[-3].minor.yy586); + yymsp[-7].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy203,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); + sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy203, yymsp[-3].minor.yy14); } break; - case 116: /* seltablist ::= stl_prefix LP select RP as on_using */ + case 117: /* seltablist ::= stl_prefix LP select RP as on_using */ { - yymsp[-5].minor.yy493 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy493,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy136,&yymsp[0].minor.yy5); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy555,&yymsp[0].minor.yy269); } break; - case 117: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ + case 118: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ { - if( yymsp[-5].minor.yy493==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy5.pOn==0 && yymsp[0].minor.yy5.pUsing==0 ){ - yymsp[-5].minor.yy493 = yymsp[-3].minor.yy493; - }else if( yymsp[-3].minor.yy493->nSrc==1 ){ - yymsp[-5].minor.yy493 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy493,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy5); - if( yymsp[-5].minor.yy493 ){ - SrcItem *pNew = &yymsp[-5].minor.yy493->a[yymsp[-5].minor.yy493->nSrc-1]; - SrcItem *pOld = yymsp[-3].minor.yy493->a; + if( yymsp[-5].minor.yy203==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy269.pOn==0 && yymsp[0].minor.yy269.pUsing==0 ){ + yymsp[-5].minor.yy203 = yymsp[-3].minor.yy203; + }else if( ALWAYS(yymsp[-3].minor.yy203!=0) && yymsp[-3].minor.yy203->nSrc==1 ){ + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); + if( yymsp[-5].minor.yy203 ){ + SrcItem *pNew = &yymsp[-5].minor.yy203->a[yymsp[-5].minor.yy203->nSrc-1]; + SrcItem *pOld = yymsp[-3].minor.yy203->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; @@ -172274,153 +175949,153 @@ static YYACTIONTYPE yy_reduce( pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy493); + sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy493); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy493,0,0,0,0,SF_NestedFrom,0); - yymsp[-5].minor.yy493 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy493,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy5); + sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy203); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy203,0,0,0,0,SF_NestedFrom,0); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy269); } } break; - case 118: /* dbnm ::= */ - case 133: /* indexed_opt ::= */ yytestcase(yyruleno==133); + case 119: /* dbnm ::= */ + case 134: /* indexed_opt ::= */ yytestcase(yyruleno==134); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 120: /* fullname ::= nm */ + case 121: /* fullname ::= nm */ { - yylhsminor.yy493 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy493 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy493->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); + if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy493 = yylhsminor.yy493; + yymsp[0].minor.yy203 = yylhsminor.yy203; break; - case 121: /* fullname ::= nm DOT nm */ + case 122: /* fullname ::= nm DOT nm */ { - yylhsminor.yy493 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy493 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy493->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy493 = yylhsminor.yy493; + yymsp[-2].minor.yy203 = yylhsminor.yy203; break; - case 122: /* xfullname ::= nm */ -{yymsp[0].minor.yy493 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} + case 123: /* xfullname ::= nm */ +{yymsp[0].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; - case 123: /* xfullname ::= nm DOT nm */ -{yymsp[-2].minor.yy493 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 124: /* xfullname ::= nm DOT nm */ +{yymsp[-2].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 124: /* xfullname ::= nm DOT nm AS nm */ + case 125: /* xfullname ::= nm DOT nm AS nm */ { - yymsp[-4].minor.yy493 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ - if( yymsp[-4].minor.yy493 ) yymsp[-4].minor.yy493->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-4].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy203 ) yymsp[-4].minor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; - case 125: /* xfullname ::= nm AS nm */ + case 126: /* xfullname ::= nm AS nm */ { - yymsp[-2].minor.yy493 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ - if( yymsp[-2].minor.yy493 ) yymsp[-2].minor.yy493->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-2].minor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy203 ) yymsp[-2].minor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; - case 126: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy436 = JT_INNER; } + case 127: /* joinop ::= COMMA|JOIN */ +{ yymsp[0].minor.yy144 = JT_INNER; } break; - case 127: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy436 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} + case 128: /* joinop ::= JOIN_KW JOIN */ +{yymsp[-1].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; - case 128: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy436 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} + case 129: /* joinop ::= JOIN_KW nm JOIN */ +{yymsp[-2].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; - case 129: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy436 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} + case 130: /* joinop ::= JOIN_KW nm nm JOIN */ +{yymsp[-3].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; - case 130: /* on_using ::= ON expr */ -{yymsp[-1].minor.yy5.pOn = yymsp[0].minor.yy224; yymsp[-1].minor.yy5.pUsing = 0;} + case 131: /* on_using ::= ON expr */ +{yymsp[-1].minor.yy269.pOn = yymsp[0].minor.yy454; yymsp[-1].minor.yy269.pUsing = 0;} break; - case 131: /* on_using ::= USING LP idlist RP */ -{yymsp[-3].minor.yy5.pOn = 0; yymsp[-3].minor.yy5.pUsing = yymsp[-1].minor.yy600;} + case 132: /* on_using ::= USING LP idlist RP */ +{yymsp[-3].minor.yy269.pOn = 0; yymsp[-3].minor.yy269.pUsing = yymsp[-1].minor.yy132;} break; - case 132: /* on_using ::= */ -{yymsp[1].minor.yy5.pOn = 0; yymsp[1].minor.yy5.pUsing = 0;} + case 133: /* on_using ::= */ +{yymsp[1].minor.yy269.pOn = 0; yymsp[1].minor.yy269.pUsing = 0;} break; - case 134: /* indexed_by ::= INDEXED BY nm */ + case 135: /* indexed_by ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 135: /* indexed_by ::= NOT INDEXED */ + case 136: /* indexed_by ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 137: /* orderby_opt ::= ORDER BY sortlist */ - case 147: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==147); -{yymsp[-2].minor.yy586 = yymsp[0].minor.yy586;} + case 138: /* orderby_opt ::= ORDER BY sortlist */ + case 148: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==148); +{yymsp[-2].minor.yy14 = yymsp[0].minor.yy14;} break; - case 138: /* sortlist ::= sortlist COMMA expr sortorder nulls */ + case 139: /* sortlist ::= sortlist COMMA expr sortorder nulls */ { - yymsp[-4].minor.yy586 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy586,yymsp[-2].minor.yy224); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy586,yymsp[-1].minor.yy436,yymsp[0].minor.yy436); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454); + sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); } break; - case 139: /* sortlist ::= expr sortorder nulls */ + case 140: /* sortlist ::= expr sortorder nulls */ { - yymsp[-2].minor.yy586 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy224); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy586,yymsp[-1].minor.yy436,yymsp[0].minor.yy436); + yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy454); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); } break; - case 140: /* sortorder ::= ASC */ -{yymsp[0].minor.yy436 = SQLITE_SO_ASC;} + case 141: /* sortorder ::= ASC */ +{yymsp[0].minor.yy144 = SQLITE_SO_ASC;} break; - case 141: /* sortorder ::= DESC */ -{yymsp[0].minor.yy436 = SQLITE_SO_DESC;} + case 142: /* sortorder ::= DESC */ +{yymsp[0].minor.yy144 = SQLITE_SO_DESC;} break; - case 142: /* sortorder ::= */ - case 145: /* nulls ::= */ yytestcase(yyruleno==145); -{yymsp[1].minor.yy436 = SQLITE_SO_UNDEFINED;} + case 143: /* sortorder ::= */ + case 146: /* nulls ::= */ yytestcase(yyruleno==146); +{yymsp[1].minor.yy144 = SQLITE_SO_UNDEFINED;} break; - case 143: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy436 = SQLITE_SO_ASC;} + case 144: /* nulls ::= NULLS FIRST */ +{yymsp[-1].minor.yy144 = SQLITE_SO_ASC;} break; - case 144: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy436 = SQLITE_SO_DESC;} + case 145: /* nulls ::= NULLS LAST */ +{yymsp[-1].minor.yy144 = SQLITE_SO_DESC;} break; - case 148: /* having_opt ::= */ - case 150: /* limit_opt ::= */ yytestcase(yyruleno==150); - case 155: /* where_opt ::= */ yytestcase(yyruleno==155); - case 157: /* where_opt_ret ::= */ yytestcase(yyruleno==157); - case 233: /* case_else ::= */ yytestcase(yyruleno==233); - case 235: /* case_operand ::= */ yytestcase(yyruleno==235); - case 254: /* vinto ::= */ yytestcase(yyruleno==254); -{yymsp[1].minor.yy224 = 0;} + case 149: /* having_opt ::= */ + case 151: /* limit_opt ::= */ yytestcase(yyruleno==151); + case 156: /* where_opt ::= */ yytestcase(yyruleno==156); + case 158: /* where_opt_ret ::= */ yytestcase(yyruleno==158); + case 235: /* case_else ::= */ yytestcase(yyruleno==235); + case 236: /* case_operand ::= */ yytestcase(yyruleno==236); + case 255: /* vinto ::= */ yytestcase(yyruleno==255); +{yymsp[1].minor.yy454 = 0;} break; - case 149: /* having_opt ::= HAVING expr */ - case 156: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==156); - case 158: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==158); - case 232: /* case_else ::= ELSE expr */ yytestcase(yyruleno==232); - case 253: /* vinto ::= INTO expr */ yytestcase(yyruleno==253); -{yymsp[-1].minor.yy224 = yymsp[0].minor.yy224;} + case 150: /* having_opt ::= HAVING expr */ + case 157: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==157); + case 159: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==159); + case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234); + case 254: /* vinto ::= INTO expr */ yytestcase(yyruleno==254); +{yymsp[-1].minor.yy454 = yymsp[0].minor.yy454;} break; - case 151: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy224 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy224,0);} + case 152: /* limit_opt ::= LIMIT expr */ +{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,0);} break; - case 152: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy224 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy224,yymsp[0].minor.yy224);} + case 153: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} break; - case 153: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy224 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy224,yymsp[-2].minor.yy224);} + case 154: /* limit_opt ::= LIMIT expr COMMA expr */ +{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,yymsp[-2].minor.yy454);} break; - case 154: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + case 155: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy493, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy493,yymsp[0].minor.yy224,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy203, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy203,yymsp[0].minor.yy454,0,0); } break; - case 159: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy586); yymsp[-1].minor.yy224 = 0;} + case 160: /* where_opt_ret ::= RETURNING selcollist */ +{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-1].minor.yy454 = 0;} break; - case 160: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy586); yymsp[-3].minor.yy224 = yymsp[-2].minor.yy224;} + case 161: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ +{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-3].minor.yy454 = yymsp[-2].minor.yy454;} break; - case 161: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + case 162: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy493, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy586,"set list"); - if( yymsp[-1].minor.yy493 ){ - SrcList *pFromClause = yymsp[-1].minor.yy493; + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-4].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy14,"set list"); + if( yymsp[-1].minor.yy203 ){ + SrcList *pFromClause = yymsp[-1].minor.yy203; if( pFromClause->nSrc>1 ){ Select *pSubquery; Token as; @@ -172429,91 +176104,90 @@ static YYACTIONTYPE yy_reduce( as.z = 0; pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); } - yymsp[-5].minor.yy493 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy493, pFromClause); + yymsp[-5].minor.yy203 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy203, pFromClause); } - sqlite3Update(pParse,yymsp[-5].minor.yy493,yymsp[-2].minor.yy586,yymsp[0].minor.yy224,yymsp[-6].minor.yy436,0,0,0); + sqlite3Update(pParse,yymsp[-5].minor.yy203,yymsp[-2].minor.yy14,yymsp[0].minor.yy454,yymsp[-6].minor.yy144,0,0,0); } break; - case 162: /* setlist ::= setlist COMMA nm EQ expr */ + case 163: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy586 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy586, yymsp[0].minor.yy224); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy586, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy454); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, 1); } break; - case 163: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + case 164: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy586 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy586, yymsp[-3].minor.yy600, yymsp[0].minor.yy224); + yymsp[-6].minor.yy14 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy14, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); } break; - case 164: /* setlist ::= nm EQ expr */ + case 165: /* setlist ::= nm EQ expr */ { - yylhsminor.yy586 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy224); - sqlite3ExprListSetName(pParse, yylhsminor.yy586, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy454); + sqlite3ExprListSetName(pParse, yylhsminor.yy14, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy586 = yylhsminor.yy586; + yymsp[-2].minor.yy14 = yylhsminor.yy14; break; - case 165: /* setlist ::= LP idlist RP EQ expr */ + case 166: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy586 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy600, yymsp[0].minor.yy224); + yymsp[-4].minor.yy14 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); } break; - case 166: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + case 167: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy493, yymsp[-1].minor.yy136, yymsp[-2].minor.yy600, yymsp[-5].minor.yy436, yymsp[0].minor.yy6); + sqlite3Insert(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy555, yymsp[-2].minor.yy132, yymsp[-5].minor.yy144, yymsp[0].minor.yy122); } break; - case 167: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + case 168: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ { - sqlite3Insert(pParse, yymsp[-4].minor.yy493, 0, yymsp[-3].minor.yy600, yymsp[-6].minor.yy436, 0); + sqlite3Insert(pParse, yymsp[-4].minor.yy203, 0, yymsp[-3].minor.yy132, yymsp[-6].minor.yy144, 0); } break; - case 168: /* upsert ::= */ -{ yymsp[1].minor.yy6 = 0; } + case 169: /* upsert ::= */ +{ yymsp[1].minor.yy122 = 0; } break; - case 169: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy6 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy586); } + case 170: /* upsert ::= RETURNING selcollist */ +{ yymsp[-1].minor.yy122 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy14); } break; - case 170: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy6 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy586,yymsp[-6].minor.yy224,yymsp[-2].minor.yy586,yymsp[-1].minor.yy224,yymsp[0].minor.yy6);} + case 171: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ +{ yymsp[-11].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy14,yymsp[-6].minor.yy454,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,yymsp[0].minor.yy122);} break; - case 171: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy6 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy586,yymsp[-3].minor.yy224,0,0,yymsp[0].minor.yy6); } + case 172: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ +{ yymsp[-8].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy14,yymsp[-3].minor.yy454,0,0,yymsp[0].minor.yy122); } break; - case 172: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy6 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } + case 173: /* upsert ::= ON CONFLICT DO NOTHING returning */ +{ yymsp[-4].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } break; - case 173: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy6 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy586,yymsp[-1].minor.yy224,0);} + case 174: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ +{ yymsp[-7].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,0);} break; - case 174: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy586);} + case 175: /* returning ::= RETURNING selcollist */ +{sqlite3AddReturning(pParse,yymsp[0].minor.yy14);} break; - case 177: /* idlist_opt ::= */ -{yymsp[1].minor.yy600 = 0;} + case 178: /* idlist_opt ::= */ +{yymsp[1].minor.yy132 = 0;} break; - case 178: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy600 = yymsp[-1].minor.yy600;} + case 179: /* idlist_opt ::= LP idlist RP */ +{yymsp[-2].minor.yy132 = yymsp[-1].minor.yy132;} break; - case 179: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy600 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy600,&yymsp[0].minor.yy0);} + case 180: /* idlist ::= idlist COMMA nm */ +{yymsp[-2].minor.yy132 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy132,&yymsp[0].minor.yy0);} break; - case 180: /* idlist ::= nm */ -{yymsp[0].minor.yy600 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} + case 181: /* idlist ::= nm */ +{yymsp[0].minor.yy132 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; - case 181: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy224 = yymsp[-1].minor.yy224;} + case 182: /* expr ::= LP expr RP */ +{yymsp[-2].minor.yy454 = yymsp[-1].minor.yy454;} break; - case 182: /* expr ::= ID|INDEXED */ - case 183: /* expr ::= JOIN_KW */ yytestcase(yyruleno==183); -{yymsp[0].minor.yy224=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 183: /* expr ::= ID|INDEXED|JOIN_KW */ +{yymsp[0].minor.yy454=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 184: /* 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.yy224 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } - yymsp[-2].minor.yy224 = yylhsminor.yy224; + yymsp[-2].minor.yy454 = yylhsminor.yy454; break; case 185: /* expr ::= nm DOT nm DOT nm */ { @@ -172524,27 +176198,27 @@ static YYACTIONTYPE yy_reduce( if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, 0, temp1); } - yylhsminor.yy224 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } - yymsp[-4].minor.yy224 = yylhsminor.yy224; + yymsp[-4].minor.yy454 = yylhsminor.yy454; break; case 186: /* term ::= NULL|FLOAT|BLOB */ case 187: /* term ::= STRING */ yytestcase(yyruleno==187); -{yymsp[0].minor.yy224=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 188: /* term ::= INTEGER */ { - yylhsminor.yy224 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); - if( yylhsminor.yy224 ) yylhsminor.yy224->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); + yylhsminor.yy454 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + if( yylhsminor.yy454 ) yylhsminor.yy454->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); } - yymsp[0].minor.yy224 = yylhsminor.yy224; + yymsp[0].minor.yy454 = yylhsminor.yy454; break; case 189: /* 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.yy224 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy224, n); + yymsp[0].minor.yy454 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy454, 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 @@ -172553,179 +176227,194 @@ static YYACTIONTYPE yy_reduce( assert( t.n>=2 ); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - yymsp[0].minor.yy224 = 0; + yymsp[0].minor.yy454 = 0; }else{ - yymsp[0].minor.yy224 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy224 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy224->iTable); + yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable); } } } break; case 190: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy224 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy224, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy454 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy454, &yymsp[0].minor.yy0, 1); } break; case 191: /* expr ::= CAST LP expr AS typetoken RP */ { - yymsp[-5].minor.yy224 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy224, yymsp[-3].minor.yy224, 0); + yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy454, yymsp[-3].minor.yy454, 0); +} + break; + case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ +{ + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy144); } + yymsp[-4].minor.yy454 = yylhsminor.yy454; break; - case 192: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ { - yylhsminor.yy224 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy586, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy436); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy14, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy144); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-1].minor.yy14); } - yymsp[-4].minor.yy224 = yylhsminor.yy224; + yymsp[-7].minor.yy454 = yylhsminor.yy454; break; - case 193: /* expr ::= ID|INDEXED LP STAR RP */ + case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ { - yylhsminor.yy224 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); } - yymsp[-3].minor.yy224 = yylhsminor.yy224; + yymsp[-3].minor.yy454 = yylhsminor.yy454; break; - case 194: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */ + case 195: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ { - yylhsminor.yy224 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy586, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy436); - sqlite3WindowAttach(pParse, yylhsminor.yy224, yymsp[0].minor.yy591); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy14, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy144); + sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); } - yymsp[-5].minor.yy224 = yylhsminor.yy224; + yymsp[-5].minor.yy454 = yylhsminor.yy454; break; - case 195: /* expr ::= ID|INDEXED LP STAR RP filter_over */ + case 196: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ { - yylhsminor.yy224 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy224, yymsp[0].minor.yy591); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy14, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy144); + sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-2].minor.yy14); } - yymsp[-4].minor.yy224 = yylhsminor.yy224; + yymsp[-8].minor.yy454 = yylhsminor.yy454; break; - case 196: /* term ::= CTIME_KW */ + case 197: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ { - yylhsminor.yy224 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); + sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); } - yymsp[0].minor.yy224 = yylhsminor.yy224; + yymsp[-4].minor.yy454 = yylhsminor.yy454; break; - case 197: /* expr ::= LP nexprlist COMMA expr RP */ + case 198: /* term ::= CTIME_KW */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy586, yymsp[-1].minor.yy224); - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy224 ){ - yymsp[-4].minor.yy224->x.pList = pList; + yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); +} + yymsp[0].minor.yy454 = yylhsminor.yy454; + break; + case 199: /* expr ::= LP nexprlist COMMA expr RP */ +{ + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy454 ){ + yymsp[-4].minor.yy454->x.pList = pList; if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy224->flags |= pList->a[0].pExpr->flags & EP_Propagate; + yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate; } }else{ sqlite3ExprListDelete(pParse->db, pList); } } break; - case 198: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy224=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy224,yymsp[0].minor.yy224);} + case 200: /* expr ::= expr AND expr */ +{yymsp[-2].minor.yy454=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} break; - case 199: /* expr ::= expr OR expr */ - case 200: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==200); - case 201: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==201); - case 202: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==202); - case 203: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==203); - case 204: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==204); - case 205: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==205); -{yymsp[-2].minor.yy224=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy224,yymsp[0].minor.yy224);} + case 201: /* expr ::= expr OR expr */ + case 202: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==202); + case 203: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==203); + case 204: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==204); + case 205: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==205); + case 206: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==206); + case 207: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==207); +{yymsp[-2].minor.yy454=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} break; - case 206: /* likeop ::= NOT LIKE_KW|MATCH */ + case 208: /* 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 207: /* expr ::= expr likeop expr */ + case 209: /* 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.yy224); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy224); - yymsp[-2].minor.yy224 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy224 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy224, 0); - if( yymsp[-2].minor.yy224 ) yymsp[-2].minor.yy224->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy454); + yymsp[-2].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + if( bNot ) yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy454, 0); + if( yymsp[-2].minor.yy454 ) yymsp[-2].minor.yy454->flags |= EP_InfixFunc; } break; - case 208: /* expr ::= expr likeop expr ESCAPE expr */ + case 210: /* 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.yy224); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy224); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy224); - yymsp[-4].minor.yy224 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy224, 0); - if( yymsp[-4].minor.yy224 ) yymsp[-4].minor.yy224->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); + if( bNot ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[-4].minor.yy454 ) yymsp[-4].minor.yy454->flags |= EP_InfixFunc; } break; - case 209: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy224 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy224,0);} + case 211: /* expr ::= expr ISNULL|NOTNULL */ +{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy454,0);} break; - case 210: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy224 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy224,0);} + case 212: /* expr ::= expr NOT NULL */ +{yymsp[-2].minor.yy454 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy454,0);} break; - case 211: /* expr ::= expr IS expr */ + case 213: /* expr ::= expr IS expr */ { - yymsp[-2].minor.yy224 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy224,yymsp[0].minor.yy224); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy224, yymsp[-2].minor.yy224, TK_ISNULL); + yymsp[-2].minor.yy454 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-2].minor.yy454, TK_ISNULL); } break; - case 212: /* expr ::= expr IS NOT expr */ + case 214: /* expr ::= expr IS NOT expr */ { - yymsp[-3].minor.yy224 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy224,yymsp[0].minor.yy224); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy224, yymsp[-3].minor.yy224, TK_NOTNULL); + yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-3].minor.yy454, TK_NOTNULL); } break; - case 213: /* expr ::= expr IS NOT DISTINCT FROM expr */ + case 215: /* expr ::= expr IS NOT DISTINCT FROM expr */ { - yymsp[-5].minor.yy224 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy224,yymsp[0].minor.yy224); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy224, yymsp[-5].minor.yy224, TK_ISNULL); + yymsp[-5].minor.yy454 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-5].minor.yy454, TK_ISNULL); } break; - case 214: /* expr ::= expr IS DISTINCT FROM expr */ + case 216: /* expr ::= expr IS DISTINCT FROM expr */ { - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy224,yymsp[0].minor.yy224); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy224, yymsp[-4].minor.yy224, TK_NOTNULL); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy454,yymsp[0].minor.yy454); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy454, yymsp[-4].minor.yy454, TK_NOTNULL); } break; - case 215: /* expr ::= NOT expr */ - case 216: /* expr ::= BITNOT expr */ yytestcase(yyruleno==216); -{yymsp[-1].minor.yy224 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy224, 0);/*A-overwrites-B*/} + case 217: /* expr ::= NOT expr */ + case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218); +{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/} break; - case 217: /* expr ::= PLUS|MINUS expr */ + case 219: /* expr ::= PLUS|MINUS expr */ { - yymsp[-1].minor.yy224 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy224, 0); + yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy454, 0); /*A-overwrites-B*/ } break; - case 218: /* expr ::= expr PTR expr */ + case 220: /* expr ::= expr PTR expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy224); - pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy224); - yylhsminor.yy224 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454); + pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy454); + yylhsminor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); } - yymsp[-2].minor.yy224 = yylhsminor.yy224; + yymsp[-2].minor.yy454 = yylhsminor.yy454; break; - case 219: /* between_op ::= BETWEEN */ - case 222: /* in_op ::= IN */ yytestcase(yyruleno==222); -{yymsp[0].minor.yy436 = 0;} + case 221: /* between_op ::= BETWEEN */ + case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); +{yymsp[0].minor.yy144 = 0;} break; - case 221: /* expr ::= expr between_op expr AND expr */ + case 223: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy224); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy224); - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy224, 0); - if( yymsp[-4].minor.yy224 ){ - yymsp[-4].minor.yy224->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0); + if( yymsp[-4].minor.yy454 ){ + yymsp[-4].minor.yy454->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy436 ) yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy224, 0); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } break; - case 224: /* expr ::= expr in_op LP exprlist RP */ + case 226: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy586==0 ){ + if( yymsp[-1].minor.yy14==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -172734,211 +176423,208 @@ static YYACTIONTYPE yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy224); - yymsp[-4].minor.yy224 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy436 ? "true" : "false"); - if( yymsp[-4].minor.yy224 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy224); - }else{ - Expr *pRHS = yymsp[-1].minor.yy586->a[0].pExpr; - if( yymsp[-1].minor.yy586->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy224->op!=TK_VECTOR ){ - yymsp[-1].minor.yy586->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy586); + sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy454 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy144 ? "true" : "false"); + if( yymsp[-4].minor.yy454 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy454); + }else{ + Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr; + if( yymsp[-1].minor.yy14->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy454->op!=TK_VECTOR ){ + yymsp[-1].minor.yy14->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy224, pRHS); - }else if( yymsp[-1].minor.yy586->nExpr==1 && pRHS->op==TK_SELECT ){ - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy224, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy224, pRHS->x.pSelect); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy454, pRHS); + }else if( yymsp[-1].minor.yy14->nExpr==1 && pRHS->op==TK_SELECT ){ + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pRHS->x.pSelect); pRHS->x.pSelect = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy586); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); }else{ - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy224, 0); - if( yymsp[-4].minor.yy224==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy586); - }else if( yymsp[-4].minor.yy224->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy224->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy586); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + if( yymsp[-4].minor.yy454==0 ){ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + }else if( yymsp[-4].minor.yy454->pLeft->op==TK_VECTOR ){ + int nExpr = yymsp[-4].minor.yy454->pLeft->x.pList->nExpr; + Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy14); if( pSelectRHS ){ parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy224, pSelectRHS); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelectRHS); } }else{ - yymsp[-4].minor.yy224->x.pList = yymsp[-1].minor.yy586; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy224); + yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy14; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); } } - if( yymsp[-3].minor.yy436 ) yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy224, 0); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } } break; - case 225: /* expr ::= LP select RP */ + case 227: /* expr ::= LP select RP */ { - yymsp[-2].minor.yy224 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy224, yymsp[-1].minor.yy136); + yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy454, yymsp[-1].minor.yy555); } break; - case 226: /* expr ::= expr in_op LP select RP */ + case 228: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy224, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy224, yymsp[-1].minor.yy136); - if( yymsp[-3].minor.yy436 ) yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy224, 0); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, yymsp[-1].minor.yy555); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } break; - case 227: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 229: /* 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.yy586 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy586); - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy224, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy224, pSelect); - if( yymsp[-3].minor.yy436 ) yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy224, 0); + if( yymsp[0].minor.yy14 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy14); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelect); + if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); } break; - case 228: /* expr ::= EXISTS LP select RP */ + case 230: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy224 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy136); + p = yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy555); } break; - case 229: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 231: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yymsp[-4].minor.yy224 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy224, 0); - if( yymsp[-4].minor.yy224 ){ - yymsp[-4].minor.yy224->x.pList = yymsp[-1].minor.yy224 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy586,yymsp[-1].minor.yy224) : yymsp[-2].minor.yy586; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy224); + yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy454, 0); + if( yymsp[-4].minor.yy454 ){ + yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy454 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454) : yymsp[-2].minor.yy14; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy586); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy224); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); } } break; - case 230: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy586 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy586, yymsp[-2].minor.yy224); - yymsp[-4].minor.yy586 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy586, yymsp[0].minor.yy224); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); + yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[0].minor.yy454); } break; - case 231: /* case_exprlist ::= WHEN expr THEN expr */ + case 233: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy586 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy224); - yymsp[-3].minor.yy586 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy586, yymsp[0].minor.yy224); + yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); + yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, yymsp[0].minor.yy454); } break; - case 234: /* case_operand ::= expr */ -{yymsp[0].minor.yy224 = yymsp[0].minor.yy224; /*A-overwrites-X*/} + case 238: /* nexprlist ::= nexprlist COMMA expr */ +{yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy454);} break; - case 237: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy586 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy586,yymsp[0].minor.yy224);} + case 239: /* nexprlist ::= expr */ +{yymsp[0].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy454); /*A-overwrites-Y*/} break; - case 238: /* nexprlist ::= expr */ -{yymsp[0].minor.yy586 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy224); /*A-overwrites-Y*/} + case 241: /* paren_exprlist ::= LP exprlist RP */ + case 246: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==246); +{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;} break; - case 240: /* paren_exprlist ::= LP exprlist RP */ - case 245: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==245); -{yymsp[-2].minor.yy586 = yymsp[-1].minor.yy586;} - break; - case 241: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 242: /* 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.yy586, yymsp[-10].minor.yy436, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy224, SQLITE_SO_ASC, yymsp[-8].minor.yy436, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy144, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy454, SQLITE_SO_ASC, yymsp[-8].minor.yy144, SQLITE_IDXTYPE_APPDEF); if( IN_RENAME_OBJECT && pParse->pNewIndex ){ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); } } break; - case 242: /* uniqueflag ::= UNIQUE */ - case 284: /* raisetype ::= ABORT */ yytestcase(yyruleno==284); -{yymsp[0].minor.yy436 = OE_Abort;} + case 243: /* uniqueflag ::= UNIQUE */ + case 285: /* raisetype ::= ABORT */ yytestcase(yyruleno==285); +{yymsp[0].minor.yy144 = OE_Abort;} break; - case 243: /* uniqueflag ::= */ -{yymsp[1].minor.yy436 = OE_None;} + case 244: /* uniqueflag ::= */ +{yymsp[1].minor.yy144 = OE_None;} break; - case 246: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 247: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy586 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy586, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy436, yymsp[0].minor.yy436); + yymsp[-4].minor.yy14 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); } break; - case 247: /* eidlist ::= nm collate sortorder */ + case 248: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy586 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy436, yymsp[0].minor.yy436); /*A-overwrites-Y*/ + yymsp[-2].minor.yy14 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); /*A-overwrites-Y*/ } break; - case 250: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy493, yymsp[-1].minor.yy436);} + case 251: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy203, yymsp[-1].minor.yy144);} break; - case 251: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy224);} + case 252: /* cmd ::= VACUUM vinto */ +{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy454);} break; - case 252: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy224);} + case 253: /* cmd ::= VACUUM nm vinto */ +{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy454);} break; - case 255: /* cmd ::= PRAGMA nm dbnm */ + case 256: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 256: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 257: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 257: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 258: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 258: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 259: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 259: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 260: /* 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 262: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 263: /* 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.yy137, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all); } break; - case 263: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 264: /* 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.yy436, yymsp[-4].minor.yy510.a, yymsp[-4].minor.yy510.b, yymsp[-2].minor.yy493, yymsp[0].minor.yy224, yymsp[-10].minor.yy436, yymsp[-8].minor.yy436); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy144, yymsp[-4].minor.yy286.a, yymsp[-4].minor.yy286.b, yymsp[-2].minor.yy203, yymsp[0].minor.yy454, yymsp[-10].minor.yy144, yymsp[-8].minor.yy144); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 264: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy436 = yymsp[0].major; /*A-overwrites-X*/ } + case 265: /* trigger_time ::= BEFORE|AFTER */ +{ yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/ } break; - case 265: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy436 = TK_INSTEAD;} + case 266: /* trigger_time ::= INSTEAD OF */ +{ yymsp[-1].minor.yy144 = TK_INSTEAD;} break; - case 266: /* trigger_time ::= */ -{ yymsp[1].minor.yy436 = TK_BEFORE; } + case 267: /* trigger_time ::= */ +{ yymsp[1].minor.yy144 = TK_BEFORE; } break; - case 267: /* trigger_event ::= DELETE|INSERT */ - case 268: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==268); -{yymsp[0].minor.yy510.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy510.b = 0;} + case 268: /* trigger_event ::= DELETE|INSERT */ + case 269: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==269); +{yymsp[0].minor.yy286.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy286.b = 0;} break; - case 269: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy510.a = TK_UPDATE; yymsp[-2].minor.yy510.b = yymsp[0].minor.yy600;} + case 270: /* trigger_event ::= UPDATE OF idlist */ +{yymsp[-2].minor.yy286.a = TK_UPDATE; yymsp[-2].minor.yy286.b = yymsp[0].minor.yy132;} break; - case 270: /* when_clause ::= */ - case 289: /* key_opt ::= */ yytestcase(yyruleno==289); -{ yymsp[1].minor.yy224 = 0; } + case 271: /* when_clause ::= */ + case 290: /* key_opt ::= */ yytestcase(yyruleno==290); +{ yymsp[1].minor.yy454 = 0; } break; - case 271: /* when_clause ::= WHEN expr */ - case 290: /* key_opt ::= KEY expr */ yytestcase(yyruleno==290); -{ yymsp[-1].minor.yy224 = yymsp[0].minor.yy224; } + case 272: /* when_clause ::= WHEN expr */ + case 291: /* key_opt ::= KEY expr */ yytestcase(yyruleno==291); +{ yymsp[-1].minor.yy454 = yymsp[0].minor.yy454; } break; - case 272: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy137!=0 ); - yymsp[-2].minor.yy137->pLast->pNext = yymsp[-1].minor.yy137; - yymsp[-2].minor.yy137->pLast = yymsp[-1].minor.yy137; + assert( yymsp[-2].minor.yy427!=0 ); + yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427; + yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427; } break; - case 273: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 274: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy137!=0 ); - yymsp[-1].minor.yy137->pLast = yymsp[-1].minor.yy137; + assert( yymsp[-1].minor.yy427!=0 ); + yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427; } break; - case 274: /* trnm ::= nm DOT nm */ + case 275: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -172946,305 +176632,305 @@ static YYACTIONTYPE yy_reduce( "statements within triggers"); } break; - case 275: /* tridxby ::= INDEXED BY nm */ + case 276: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 276: /* tridxby ::= NOT INDEXED */ + case 277: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 277: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy137 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy493, yymsp[-3].minor.yy586, yymsp[-1].minor.yy224, yymsp[-7].minor.yy436, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy594);} - yymsp[-8].minor.yy137 = yylhsminor.yy137; + case 278: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ +{yylhsminor.yy427 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy203, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454, yymsp[-7].minor.yy144, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy168);} + yymsp[-8].minor.yy427 = yylhsminor.yy427; break; - case 278: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + case 279: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - yylhsminor.yy137 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy600,yymsp[-2].minor.yy136,yymsp[-6].minor.yy436,yymsp[-1].minor.yy6,yymsp[-7].minor.yy594,yymsp[0].minor.yy594);/*yylhsminor.yy137-overwrites-yymsp[-6].minor.yy436*/ + yylhsminor.yy427 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy132,yymsp[-2].minor.yy555,yymsp[-6].minor.yy144,yymsp[-1].minor.yy122,yymsp[-7].minor.yy168,yymsp[0].minor.yy168);/*yylhsminor.yy427-overwrites-yymsp[-6].minor.yy144*/ } - yymsp[-7].minor.yy137 = yylhsminor.yy137; + yymsp[-7].minor.yy427 = yylhsminor.yy427; break; - case 279: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ -{yylhsminor.yy137 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy224, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy594);} - yymsp[-5].minor.yy137 = yylhsminor.yy137; + case 280: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +{yylhsminor.yy427 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy454, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy168);} + yymsp[-5].minor.yy427 = yylhsminor.yy427; break; - case 280: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy137 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy136, yymsp[-2].minor.yy594, yymsp[0].minor.yy594); /*yylhsminor.yy137-overwrites-yymsp[-1].minor.yy136*/} - yymsp[-2].minor.yy137 = yylhsminor.yy137; + case 281: /* trigger_cmd ::= scanpt select scanpt */ +{yylhsminor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy555, yymsp[-2].minor.yy168, yymsp[0].minor.yy168); /*yylhsminor.yy427-overwrites-yymsp[-1].minor.yy555*/} + yymsp[-2].minor.yy427 = yylhsminor.yy427; break; - case 281: /* expr ::= RAISE LP IGNORE RP */ + case 282: /* expr ::= RAISE LP IGNORE RP */ { - yymsp[-3].minor.yy224 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy224 ){ - yymsp[-3].minor.yy224->affExpr = OE_Ignore; + yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy454 ){ + yymsp[-3].minor.yy454->affExpr = OE_Ignore; } } break; - case 282: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 283: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yymsp[-5].minor.yy224 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); - if( yymsp[-5].minor.yy224 ) { - yymsp[-5].minor.yy224->affExpr = (char)yymsp[-3].minor.yy436; + yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + if( yymsp[-5].minor.yy454 ) { + yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144; } } break; - case 283: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy436 = OE_Rollback;} + case 284: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy144 = OE_Rollback;} break; - case 285: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy436 = OE_Fail;} + case 286: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy144 = OE_Fail;} break; - case 286: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 287: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy493,yymsp[-1].minor.yy436); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy203,yymsp[-1].minor.yy144); } break; - case 287: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 288: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy224, yymsp[-1].minor.yy224, yymsp[0].minor.yy224); + sqlite3Attach(pParse, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, yymsp[0].minor.yy454); } break; - case 288: /* cmd ::= DETACH database_kw_opt expr */ + case 289: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy224); + sqlite3Detach(pParse, yymsp[0].minor.yy454); } break; - case 291: /* cmd ::= REINDEX */ + case 292: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 292: /* cmd ::= REINDEX nm dbnm */ + case 293: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 293: /* cmd ::= ANALYZE */ + case 294: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 294: /* cmd ::= ANALYZE nm dbnm */ + case 295: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 295: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 296: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy493,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy203,&yymsp[0].minor.yy0); } break; - case 296: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 297: /* 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 297: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + case 298: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ { - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy493, &yymsp[0].minor.yy0); + sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0); } break; - case 298: /* add_column_fullname ::= fullname */ + case 299: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy493); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy203); } break; - case 299: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + case 300: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ { - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy493, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy203, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 300: /* cmd ::= create_vtab */ + case 301: /* cmd ::= ALTER TABLE fullname ALTER COLUMNKW columnname TO columnname carglist */ +{ + libsqlAlterAlterColumn(pParse, yymsp[-6].minor.yy203, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0); +} + break; + case 302: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 301: /* cmd ::= create_vtab LP vtabarglist RP */ + case 303: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 302: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 304: /* 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.yy436); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy144); } break; - case 303: /* vtabarg ::= */ + case 305: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 304: /* vtabargtoken ::= ANY */ - case 305: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==305); - case 306: /* lp ::= LP */ yytestcase(yyruleno==306); + case 306: /* vtabargtoken ::= ANY */ + case 307: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==307); + case 308: /* lp ::= LP */ yytestcase(yyruleno==308); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 307: /* with ::= WITH wqlist */ - case 308: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==308); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy19, 1); } + case 309: /* with ::= WITH wqlist */ + case 310: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==310); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); } break; - case 309: /* wqas ::= AS */ -{yymsp[0].minor.yy480 = M10d_Any;} + case 311: /* wqas ::= AS */ +{yymsp[0].minor.yy462 = M10d_Any;} break; - case 310: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy480 = M10d_Yes;} + case 312: /* wqas ::= AS MATERIALIZED */ +{yymsp[-1].minor.yy462 = M10d_Yes;} break; - case 311: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy480 = M10d_No;} + case 313: /* wqas ::= AS NOT MATERIALIZED */ +{yymsp[-2].minor.yy462 = M10d_No;} break; - case 312: /* wqitem ::= nm eidlist_opt wqas LP select RP */ + case 314: /* wqitem ::= nm eidlist_opt wqas LP select RP */ { - yymsp[-5].minor.yy615 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy586, yymsp[-1].minor.yy136, yymsp[-3].minor.yy480); /*A-overwrites-X*/ + yymsp[-5].minor.yy67 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy555, yymsp[-3].minor.yy462); /*A-overwrites-X*/ } break; - case 313: /* wqlist ::= wqitem */ + case 315: /* wqlist ::= wqitem */ { - yymsp[0].minor.yy19 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy615); /*A-overwrites-X*/ + yymsp[0].minor.yy59 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy67); /*A-overwrites-X*/ } break; - case 314: /* wqlist ::= wqlist COMMA wqitem */ + case 316: /* wqlist ::= wqlist COMMA wqitem */ { - yymsp[-2].minor.yy19 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy19, yymsp[0].minor.yy615); + yymsp[-2].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy59, yymsp[0].minor.yy67); } break; - case 315: /* windowdefn_list ::= windowdefn */ -{ yylhsminor.yy591 = yymsp[0].minor.yy591; } - yymsp[0].minor.yy591 = yylhsminor.yy591; - break; - case 316: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + case 317: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { - assert( yymsp[0].minor.yy591!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy591, yymsp[-2].minor.yy591); - yymsp[0].minor.yy591->pNextWin = yymsp[-2].minor.yy591; - yylhsminor.yy591 = yymsp[0].minor.yy591; + assert( yymsp[0].minor.yy211!=0 ); + sqlite3WindowChain(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy211); + yymsp[0].minor.yy211->pNextWin = yymsp[-2].minor.yy211; + yylhsminor.yy211 = yymsp[0].minor.yy211; } - yymsp[-2].minor.yy591 = yylhsminor.yy591; + yymsp[-2].minor.yy211 = yylhsminor.yy211; break; - case 317: /* windowdefn ::= nm AS LP window RP */ + case 318: /* windowdefn ::= nm AS LP window RP */ { - if( ALWAYS(yymsp[-1].minor.yy591) ){ - yymsp[-1].minor.yy591->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); + if( ALWAYS(yymsp[-1].minor.yy211) ){ + yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); } - yylhsminor.yy591 = yymsp[-1].minor.yy591; + yylhsminor.yy211 = yymsp[-1].minor.yy211; } - yymsp[-4].minor.yy591 = yylhsminor.yy591; + yymsp[-4].minor.yy211 = yylhsminor.yy211; break; - case 318: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + case 319: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { - yymsp[-4].minor.yy591 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy591, yymsp[-2].minor.yy586, yymsp[-1].minor.yy586, 0); + yymsp[-4].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, 0); } break; - case 319: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + case 320: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { - yylhsminor.yy591 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy591, yymsp[-2].minor.yy586, yymsp[-1].minor.yy586, &yymsp[-5].minor.yy0); + yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy591 = yylhsminor.yy591; + yymsp[-5].minor.yy211 = yylhsminor.yy211; break; - case 320: /* window ::= ORDER BY sortlist frame_opt */ + case 321: /* window ::= ORDER BY sortlist frame_opt */ { - yymsp[-3].minor.yy591 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy591, 0, yymsp[-1].minor.yy586, 0); + yymsp[-3].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, 0); } break; - case 321: /* window ::= nm ORDER BY sortlist frame_opt */ + case 322: /* window ::= nm ORDER BY sortlist frame_opt */ { - yylhsminor.yy591 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy591, 0, yymsp[-1].minor.yy586, &yymsp[-4].minor.yy0); + yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy591 = yylhsminor.yy591; - break; - case 322: /* window ::= frame_opt */ - case 341: /* filter_over ::= over_clause */ yytestcase(yyruleno==341); -{ - yylhsminor.yy591 = yymsp[0].minor.yy591; -} - yymsp[0].minor.yy591 = yylhsminor.yy591; + yymsp[-4].minor.yy211 = yylhsminor.yy211; break; case 323: /* window ::= nm frame_opt */ { - yylhsminor.yy591 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy591, 0, 0, &yymsp[-1].minor.yy0); + yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, 0, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy591 = yylhsminor.yy591; + yymsp[-1].minor.yy211 = yylhsminor.yy211; break; case 324: /* frame_opt ::= */ { - yymsp[1].minor.yy591 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); + yymsp[1].minor.yy211 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); } break; case 325: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ { - yylhsminor.yy591 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy436, yymsp[-1].minor.yy537.eType, yymsp[-1].minor.yy537.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy480); + yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy144, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy462); } - yymsp[-2].minor.yy591 = yylhsminor.yy591; + yymsp[-2].minor.yy211 = yylhsminor.yy211; break; case 326: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ { - yylhsminor.yy591 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy436, yymsp[-3].minor.yy537.eType, yymsp[-3].minor.yy537.pExpr, yymsp[-1].minor.yy537.eType, yymsp[-1].minor.yy537.pExpr, yymsp[0].minor.yy480); + yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy144, yymsp[-3].minor.yy509.eType, yymsp[-3].minor.yy509.pExpr, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, yymsp[0].minor.yy462); } - yymsp[-5].minor.yy591 = yylhsminor.yy591; + yymsp[-5].minor.yy211 = yylhsminor.yy211; break; case 328: /* frame_bound_s ::= frame_bound */ case 330: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==330); -{yylhsminor.yy537 = yymsp[0].minor.yy537;} - yymsp[0].minor.yy537 = yylhsminor.yy537; +{yylhsminor.yy509 = yymsp[0].minor.yy509;} + yymsp[0].minor.yy509 = yylhsminor.yy509; break; case 329: /* frame_bound_s ::= UNBOUNDED PRECEDING */ case 331: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==331); case 333: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==333); -{yylhsminor.yy537.eType = yymsp[-1].major; yylhsminor.yy537.pExpr = 0;} - yymsp[-1].minor.yy537 = yylhsminor.yy537; +{yylhsminor.yy509.eType = yymsp[-1].major; yylhsminor.yy509.pExpr = 0;} + yymsp[-1].minor.yy509 = yylhsminor.yy509; break; case 332: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy537.eType = yymsp[0].major; yylhsminor.yy537.pExpr = yymsp[-1].minor.yy224;} - yymsp[-1].minor.yy537 = yylhsminor.yy537; +{yylhsminor.yy509.eType = yymsp[0].major; yylhsminor.yy509.pExpr = yymsp[-1].minor.yy454;} + yymsp[-1].minor.yy509 = yylhsminor.yy509; break; case 334: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy480 = 0;} +{yymsp[1].minor.yy462 = 0;} break; case 335: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy480 = yymsp[0].minor.yy480;} +{yymsp[-1].minor.yy462 = yymsp[0].minor.yy462;} break; case 336: /* frame_exclude ::= NO OTHERS */ case 337: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==337); -{yymsp[-1].minor.yy480 = yymsp[-1].major; /*A-overwrites-X*/} +{yymsp[-1].minor.yy462 = yymsp[-1].major; /*A-overwrites-X*/} break; case 338: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy480 = yymsp[0].major; /*A-overwrites-X*/} +{yymsp[0].minor.yy462 = yymsp[0].major; /*A-overwrites-X*/} break; case 339: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy591 = yymsp[0].minor.yy591; } +{ yymsp[-1].minor.yy211 = yymsp[0].minor.yy211; } break; case 340: /* filter_over ::= filter_clause over_clause */ { - if( yymsp[0].minor.yy591 ){ - yymsp[0].minor.yy591->pFilter = yymsp[-1].minor.yy224; + if( yymsp[0].minor.yy211 ){ + yymsp[0].minor.yy211->pFilter = yymsp[-1].minor.yy454; }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy224); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); } - yylhsminor.yy591 = yymsp[0].minor.yy591; + yylhsminor.yy211 = yymsp[0].minor.yy211; +} + yymsp[-1].minor.yy211 = yylhsminor.yy211; + break; + case 341: /* filter_over ::= over_clause */ +{ + yylhsminor.yy211 = yymsp[0].minor.yy211; } - yymsp[-1].minor.yy591 = yylhsminor.yy591; + yymsp[0].minor.yy211 = yylhsminor.yy211; break; case 342: /* filter_over ::= filter_clause */ { - yylhsminor.yy591 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy591 ){ - yylhsminor.yy591->eFrmType = TK_FILTER; - yylhsminor.yy591->pFilter = yymsp[0].minor.yy224; + yylhsminor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yylhsminor.yy211 ){ + yylhsminor.yy211->eFrmType = TK_FILTER; + yylhsminor.yy211->pFilter = yymsp[0].minor.yy454; }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy224); + sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy454); } } - yymsp[0].minor.yy591 = yylhsminor.yy591; + yymsp[0].minor.yy211 = yylhsminor.yy211; break; case 343: /* over_clause ::= OVER LP window RP */ { - yymsp[-3].minor.yy591 = yymsp[-1].minor.yy591; - assert( yymsp[-3].minor.yy591!=0 ); + yymsp[-3].minor.yy211 = yymsp[-1].minor.yy211; + assert( yymsp[-3].minor.yy211!=0 ); } break; case 344: /* over_clause ::= OVER nm */ { - yymsp[-1].minor.yy591 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy591 ){ - yymsp[-1].minor.yy591->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); + yymsp[-1].minor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yymsp[-1].minor.yy211 ){ + yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); } } break; case 345: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy224 = yymsp[-1].minor.yy224; } +{ yymsp[-4].minor.yy454 = yymsp[-1].minor.yy454; } break; default: /* (346) input ::= cmdlist */ yytestcase(yyruleno==346); @@ -173262,32 +176948,32 @@ static YYACTIONTYPE yy_reduce( /* (358) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=358); /* (359) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==359); /* (360) columnlist ::= columnname carglist */ yytestcase(yyruleno==360); - /* (361) nm ::= ID|INDEXED */ yytestcase(yyruleno==361); + /* (361) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==361); /* (362) nm ::= STRING */ yytestcase(yyruleno==362); - /* (363) nm ::= JOIN_KW */ yytestcase(yyruleno==363); - /* (364) typetoken ::= typename */ yytestcase(yyruleno==364); - /* (365) typename ::= ID|STRING */ yytestcase(yyruleno==365); - /* (366) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=366); - /* (367) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=367); - /* (368) carglist ::= carglist ccons */ yytestcase(yyruleno==368); - /* (369) carglist ::= */ yytestcase(yyruleno==369); - /* (370) ccons ::= NULL onconf */ yytestcase(yyruleno==370); - /* (371) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==371); - /* (372) ccons ::= AS generated */ yytestcase(yyruleno==372); - /* (373) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==373); - /* (374) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==374); - /* (375) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=375); - /* (376) tconscomma ::= */ yytestcase(yyruleno==376); - /* (377) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=377); - /* (378) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=378); - /* (379) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=379); - /* (380) oneselect ::= values */ yytestcase(yyruleno==380); - /* (381) sclp ::= selcollist COMMA */ yytestcase(yyruleno==381); - /* (382) as ::= ID|STRING */ yytestcase(yyruleno==382); - /* (383) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=383); - /* (384) returning ::= */ yytestcase(yyruleno==384); - /* (385) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=385); - /* (386) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==386); + /* (363) typetoken ::= typename */ yytestcase(yyruleno==363); + /* (364) typename ::= ID|STRING */ yytestcase(yyruleno==364); + /* (365) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=365); + /* (366) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=366); + /* (367) carglist ::= carglist ccons */ yytestcase(yyruleno==367); + /* (368) carglist ::= */ yytestcase(yyruleno==368); + /* (369) ccons ::= NULL onconf */ yytestcase(yyruleno==369); + /* (370) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==370); + /* (371) ccons ::= AS generated */ yytestcase(yyruleno==371); + /* (372) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==372); + /* (373) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==373); + /* (374) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=374); + /* (375) tconscomma ::= */ yytestcase(yyruleno==375); + /* (376) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=376); + /* (377) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=377); + /* (378) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=378); + /* (379) oneselect ::= values */ yytestcase(yyruleno==379); + /* (380) sclp ::= selcollist COMMA */ yytestcase(yyruleno==380); + /* (381) as ::= ID|STRING */ yytestcase(yyruleno==381); + /* (382) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=382); + /* (383) returning ::= */ yytestcase(yyruleno==383); + /* (384) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=384); + /* (385) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==385); + /* (386) case_operand ::= expr */ yytestcase(yyruleno==386); /* (387) exprlist ::= nexprlist */ yytestcase(yyruleno==387); /* (388) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=388); /* (389) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=389); @@ -173310,6 +176996,8 @@ static YYACTIONTYPE yy_reduce( /* (406) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==406); /* (407) anylist ::= anylist ANY */ yytestcase(yyruleno==407); /* (408) with ::= */ yytestcase(yyruleno==408); + /* (409) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=409); + /* (410) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=410); break; /********** End reduce actions ************************************************/ }; @@ -173816,8 +177504,8 @@ const unsigned char ebcdicToAscii[] = { ** is substantially reduced. This is important for embedded applications ** on platforms with limited memory. */ -/* Hash score: 236 */ -/* zKWText[] encodes 1032 bytes of keyword text in 687 bytes */ +/* Hash score: 240 */ +/* zKWText[] encodes 1041 bytes of keyword text in 695 bytes */ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ /* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT */ /* IESNOTNULLANGUAGENERATEDETACHAVINGLOBEGINNERAISEXCEPT */ @@ -173829,8 +177517,8 @@ const unsigned char ebcdicToAscii[] = { /* COMMITCONFLICTCROSSCURRENT_TIMESTAMPARTITIONDROPRECEDINGFAIL */ /* ASTFILTERENAMEFIRSTFOLLOWINGFROMFULLIMITFUNCTIONIFORDEREPLACE */ /* OTHERSOVERESTRICTRETURNINGRIGHTROLLBACKROWSUNBOUNDEDUNIONUSING */ -/* VACUUMVIEWINDOWBYINITIALLYPRIMARY */ -static const char zKWText[686] = { +/* VACUUMVIEWINDOWBYINITIALLYPRIMARYREADONLY */ +static const char zKWText[694] = { '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', @@ -173869,40 +177557,40 @@ static const char zKWText[686] = { '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', + 'R','Y','R','E','A','D','O','N','L','Y', }; /* aKWHash[i] is the hash value for the i-th keyword */ static const unsigned char aKWHash[127] = { 86, 93, 137, 84, 116, 29, 0, 0, 95, 0, 88, 74, 0, 60, 35, 64, 15, 0, 49, 98, 61, 90, 138, 19, 40, 0, 143, 0, 87, 134, 0, 22, 106, 0, 9, 0, 0, 124, 82, - 0, 80, 6, 0, 67, 104, 150, 0, 139, 114, 0, 0, 55, + 0, 80, 6, 0, 67, 104, 149, 0, 139, 114, 0, 0, 55, 0, 91, 24, 0, 17, 0, 27, 72, 23, 26, 5, 44, 145, - 109, 123, 0, 75, 92, 73, 148, 45, 121, 76, 0, 56, 0, + 109, 123, 0, 75, 92, 73, 147, 45, 121, 76, 0, 56, 0, 11, 48, 0, 112, 0, 0, 0, 108, 10, 110, 115, 126, 14, - 128, 125, 0, 101, 0, 18, 131, 147, 54, 132, 142, 89, 85, + 128, 125, 0, 101, 0, 18, 131, 146, 54, 132, 142, 89, 85, 37, 30, 127, 0, 0, 107, 58, 133, 130, 0, 34, 0, 0, 135, 0, 99, 38, 39, 0, 20, 52, 118, 94, }; /* 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[150] = { +static const unsigned char aKWNext[152] = {0, 0, 0, 0, 0, 4, 0, 50, 0, 0, 105, 113, 0, 0, - 0, 2, 0, 0, 146, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 2, 0, 0, 151, 0, 0, 0, 13, 0, 0, 0, 0, 144, 0, 0, 120, 59, 0, 0, 140, 12, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 36, 0, 47, 28, 79, 0, 0, 0, 0, 43, 0, 0, 0, 0, - 0, 0, 0, 71, 0, 0, 0, 0, 0, 149, 3, 0, 42, + 0, 0, 0, 71, 0, 0, 0, 0, 0, 148, 3, 0, 42, 0, 1, 77, 0, 0, 0, 31, 0, 141, 103, 0, 129, 0, - 117, 0, 66, 68, 63, 0, 0, 0, 0, 0, 53, 0, 16, + 117, 0, 66, 68, 63, 0, 0, 0, 0, 0, 53, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 102, 0, 8, 0, 111, 21, 7, 0, 0, 81, 97, 119, 0, 57, 0, 70, 69, 0, 100, 0, 51, 0, 62, 0, 78, 0, 96, 32, 33, - 41, 25, 0, 122, 0, 0, 65, + 41, 25, 122, 0, 0, 65, 16, 0, }; /* aKWLen[i] is the length (in bytes) of the i-th keyword */ -static const unsigned char aKWLen[150] = { +static const unsigned char aKWLen[152] = {0, 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, @@ -173914,11 +177602,11 @@ static const unsigned char aKWLen[150] = { 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 9, 4, 9, 4, 4, 6, 6, 5, 9, 4, 4, 5, 8, 2, 5, 7, 6, 4, 8, 9, 5, 8, 4, 3, 9, 5, 5, 6, - 4, 6, 2, 2, 9, 3, 7, + 4, 6, 2, 9, 3, 7, 8, 2, }; /* aKWOffset[i] is the index into zKWText[] of the start of ** the text for the i-th keyword. */ -static const unsigned short int aKWOffset[150] = { +static const unsigned short int aKWOffset[152] = {0, 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, @@ -173930,10 +177618,10 @@ static const unsigned short int aKWOffset[150] = { 447, 449, 451, 460, 464, 470, 476, 484, 489, 489, 489, 505, 514, 517, 526, 529, 533, 538, 544, 549, 558, 562, 565, 570, 578, 580, 584, 591, 597, 600, 608, 617, 622, 630, 630, 634, 643, 648, 653, - 659, 662, 665, 668, 670, 675, 679, + 659, 662, 668, 670, 675, 679, 686, 689, }; /* aKWCode[i] is the parser symbol code for the i-th keyword */ -static const unsigned char aKWCode[150] = { +static const unsigned char aKWCode[152] = {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, @@ -173963,7 +177651,8 @@ static const unsigned char aKWCode[150] = { TK_REPLACE, TK_OTHERS, TK_OVER, TK_RESTRICT, 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, + TK_BY, TK_INITIALLY, TK_ALL, TK_PRIMARY, TK_READONLY, + TK_DO, }; /* Hash table decoded: ** 0: INSERT @@ -174010,7 +177699,7 @@ static const unsigned char aKWCode[150] = { ** 41: EACH ** 42: ** 43: QUERY -** 44: AND ADD +** 44: AND READONLY ADD ** 45: PRIMARY ANALYZE ** 46: ** 47: ROW ASC DETACH @@ -174100,188 +177789,189 @@ static const unsigned char aKWCode[150] = { static int keywordCode(const char *z, int n, int *pType){ int i, j; const char *zKW; - if( n>=2 ){ - i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; - for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){ - if( aKWLen[i]!=n ) continue; - zKW = &zKWText[aKWOffset[i]]; + 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]]; #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); return id; } -#define SQLITE_N_KEYWORD 150 +#define SQLITE_N_KEYWORD 151 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; @@ -174580,7 +178270,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ 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]=='9' ); testcase( z[0]=='.' ); *tokenType = TK_INTEGER; #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ @@ -174652,7 +178342,8 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ return i; } case CC_KYWD0: { - for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} + if( aiClass[z[1]]>CC_KYWD ){ i = 1; break; } + for(i=2; 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 @@ -175431,30 +179122,20 @@ static int sqlite3TestExtInit(sqlite3 *db){ ** Forward declarations of external module initializer functions ** for modules that need them. */ -#ifdef SQLITE_ENABLE_FTS1 -SQLITE_PRIVATE int sqlite3Fts1Init(sqlite3*); -#endif -#ifdef SQLITE_ENABLE_FTS2 -SQLITE_PRIVATE int sqlite3Fts2Init(sqlite3*); -#endif #ifdef SQLITE_ENABLE_FTS5 SQLITE_PRIVATE int sqlite3Fts5Init(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_FTS1 - sqlite3Fts1Init, -#endif -#ifdef SQLITE_ENABLE_FTS2 - sqlite3Fts2Init, -#endif #ifdef SQLITE_ENABLE_FTS3 sqlite3Fts3Init, #endif @@ -175483,6 +179164,9 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { #ifdef SQLITE_ENABLE_BYTECODE_VTAB sqlite3VdbeBytecodeVtabInit, #endif +#ifdef SQLITE_EXTRA_AUTOEXT + SQLITE_EXTRA_AUTOEXT, +#endif }; #ifndef SQLITE_AMALGAMATION @@ -175559,6 +179243,32 @@ SQLITE_API char *sqlite3_temp_directory = 0; */ SQLITE_API char *sqlite3_data_directory = 0; +/* +** Determine whether or not high-precision (long double) floating point +** math works correctly on CPU currently running. +*/ +static SQLITE_NOINLINE int hasHighPrecisionDouble(int rc){ + if( sizeof(LONGDOUBLE_TYPE)<=8 ){ + /* If the size of "long double" is not more than 8, then + ** high-precision math is not possible. */ + return 0; + }else{ + /* Just because sizeof(long double)>8 does not mean that the underlying + ** hardware actually supports high-precision floating point. For example, + ** clearing the 0x100 bit in the floating-point control word on Intel + ** processors will make long double work like double, even though long + ** double takes up more space. The only way to determine if long double + ** actually works is to run an experiment. */ + LONGDOUBLE_TYPE a, b, c; + rc++; + a = 1.0+rc*0.1; + b = 1.0e+18+rc*25.0; + c = a+b; + return b!=c; + } +} + + /* ** Initialize SQLite. ** @@ -175754,6 +179464,12 @@ SQLITE_API int sqlite3_initialize(void){ } #endif + /* Experimentally determine if high-precision floating point is + ** available. */ +#ifndef SQLITE_OMIT_WSD + sqlite3Config.bUseLongDouble = hasHighPrecisionDouble(rc); +#endif + return rc; } @@ -176324,6 +180040,10 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){ 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 ){ @@ -176624,6 +180344,10 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0); } + if (db->xCloseCallback) { + db->xCloseCallback(db->pCloseArg, db); + } + /* Force xDisconnect calls on all virtual tables */ disconnectAllVtab(db); @@ -176653,9 +180377,22 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ } #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; +#ifdef LIBSQL_ENABLE_WASM_RUNTIME + if (db->wasm.engine) { + libsql_wasm_engine_free(db->wasm.engine); + } +#endif sqlite3LeaveMutexAndCloseZombie(db); return SQLITE_OK; } @@ -176824,6 +180561,9 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } + + destroy_wal_manager(db->wal_manager); + sqlite3_free(db); } @@ -177070,9 +180810,9 @@ static int sqliteDefaultBusyCallback( void *ptr, /* Database connection */ int count /* Number of times table has been busy */ ){ -#if SQLITE_OS_WIN || HAVE_USLEEP +#if SQLITE_OS_WIN || !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP /* This case is for systems that have support for sleeping for fractions of - ** a second. Examples: All windows systems, unix systems with usleep() */ + ** a second. Examples: All windows systems, unix systems with nanosleep() */ static const u8 delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; static const u8 totals[] = @@ -177727,6 +181467,12 @@ SQLITE_API void *sqlite3_preupdate_hook( 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; @@ -177736,6 +181482,24 @@ SQLITE_API void *sqlite3_preupdate_hook( } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +/* +** Register a callback to be invoked when the connection is closed. +*/ +void *libsql_close_hook( + sqlite3 *db, /* Attach the hook to this connection */ + void(*xCallback)( /* Callback function */ + void*,sqlite3*), + void *pArg /* First callback argument */ +){ + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pCloseArg; + db->xCloseCallback = xCallback; + db->pCloseArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} + /* ** Register a function to be invoked prior to each autovacuum that ** determines the number of pages to vacuum. @@ -177873,7 +181637,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint ** mode: */ - return SQLITE_MISUSE; + return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); @@ -178307,10 +182071,8 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ return oldLimit; /* IMP: R-53341-35419 */ } -#ifdef SQLITE_OMIT_WAL -libsql_wal_methods* libsql_wal_methods_find(const char *zName) { - return NULL; -} +#ifdef LIBSQL_PRE_VFS_HOOK +void libsql_pre_vfs_hook(const char *zVfs); #endif /* @@ -178343,18 +182105,15 @@ libsql_wal_methods* libsql_wal_methods_find(const char *zName) { */ SQLITE_PRIVATE int sqlite3ParseUri( const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */ - const char *zDefaultWal, /* WAL module to use if no "wal=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 */ - libsql_wal_methods **ppWal, /* OUT: WAL module 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; const char *zVfs = zDefaultVfs; - const char *zWal = zDefaultWal; char *zFile; char c; int nUri = sqlite3Strlen30(zUri); @@ -178485,9 +182244,7 @@ SQLITE_PRIVATE int sqlite3ParseUri( if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){ zVfs = zVal; - }else if( nOpt==3 && memcmp("wal", zOpt, 3)==0 ){ - zWal = zVal; - }else{ + } else { struct OpenMode { const char *z; int mode; @@ -178564,16 +182321,15 @@ SQLITE_PRIVATE int sqlite3ParseUri( flags &= ~SQLITE_OPEN_URI; } +#ifdef LIBSQL_PRE_VFS_HOOK + libsql_pre_vfs_hook(zVfs); +#endif + *ppVfs = sqlite3_vfs_find(zVfs); if( *ppVfs==0 ){ *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs); rc = SQLITE_ERROR; } - *ppWal = libsql_wal_methods_find(zWal); - if( *ppWal==NULL ){ - *pzErrMsg = sqlite3_mprintf("no such WAL module: %s", zWal); - rc = SQLITE_ERROR; - } parse_uri_out: if( rc!=SQLITE_OK ){ sqlite3_free_filename(zFile); @@ -178599,7 +182355,9 @@ static const char *uriParameter(const char *zFilename, const char *zParam){ return 0; } - +#ifdef LIBSQL_EXTRA_URI_PARAMS +int libsql_handle_extra_uri_params(sqlite3 *db, const char *zOpen); +#endif /* ** This routine does the work of opening a database on behalf of @@ -178607,11 +182365,11 @@ static const char *uriParameter(const char *zFilename, const char *zParam){ ** is UTF-8 encoded. */ static int openDatabase( - const char *zFilename, /* Database filename UTF-8 encoded */ - sqlite3 **ppDb, /* OUT: Returned database handle */ - unsigned int flags, /* Operational flags */ - const char *zVfs, /* Name of the VFS to use */ - const char *zWal /* Name of WAL module to use */ + const char *zFilename, /* Database filename UTF-8 encoded */ + sqlite3 **ppDb, /* OUT: Returned database handle */ + unsigned int flags, /* Operational flags */ + const char *zVfs, /* Name of the VFS to use */ + RefCountedWalManager *wal_manager /* wal manager implementation */ ){ sqlite3 *db; /* Store allocated handle here */ int rc; /* Return code */ @@ -178671,6 +182429,7 @@ static int openDatabase( /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; + db->wal_manager = wal_manager; if( isThreadsafe #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS || sqlite3GlobalConfig.bCoreMutex @@ -178678,6 +182437,8 @@ static int openDatabase( ){ db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ + wal_manager->ref.xDestroy(wal_manager->ref.pData); + sqlite3_free(db->wal_manager); sqlite3_free(db); db = 0; goto opendb_out; @@ -178729,7 +182490,7 @@ static int openDatabase( ** 0 off off ** ** Legacy behavior is 3 (double-quoted string literals are allowed anywhere) -** and so that is the default. But developers are encouranged to use +** 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) @@ -178838,7 +182599,7 @@ static int openDatabase( if( ((1<<(flags&7)) & 0x46)==0 ){ rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */ }else{ - rc = sqlite3ParseUri(zVfs, zWal, zFilename, &flags, &db->pVfs, &db->pWalMethods, &zOpen, &zErrMsg); + rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); } if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); @@ -178854,7 +182615,7 @@ static int openDatabase( #endif /* Open the backend database driver */ - rc = sqlite3BtreeOpen(db->pVfs, db->pWalMethods, zOpen, db, &db->aDb[0].pBt, 0, + rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, flags | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ if( rc==SQLITE_IOERR_NOMEM ){ @@ -178932,10 +182693,6 @@ static int openDatabase( setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, sqlite3GlobalConfig.nLookaside); - if (strcmp("default", libsql_wal_methods_name(db->pWalMethods)) != 0) { - sqlite3_exec(db, "pragma journal_mode=wal", NULL, NULL, NULL); - } - sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); opendb_out: @@ -178959,6 +182716,11 @@ static int openDatabase( void *pArg = sqlite3GlobalConfig.pSqllogArg; sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } +#endif +#ifdef LIBSQL_EXTRA_URI_PARAMS + if (rc == SQLITE_OK) { + rc = libsql_handle_extra_uri_params(db, zOpen); + } #endif sqlite3_free_filename(zOpen); return rc; @@ -178973,7 +182735,7 @@ SQLITE_API int sqlite3_open( sqlite3 **ppDb ){ return openDatabase(zFilename, ppDb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL, NULL); + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL, make_sqlite3_wal_manager_rc()); } SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ @@ -178981,9 +182743,10 @@ SQLITE_API int sqlite3_open_v2( int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ){ - return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, NULL); + return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, make_sqlite3_wal_manager_rc()); } +/* deprecated, only works with zWal == NULL */ int libsql_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ @@ -178991,7 +182754,37 @@ int libsql_open( const char *zVfs, /* Name of VFS module to use, NULL for default */ const char *zWal /* Name of WAL module to use */ ) { - return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, zWal); + assert( zWal == NULL ); + return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, make_sqlite3_wal_manager_rc()); +} + +/* deprecated, only works with zWal == NULL */ +int libsql_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs, /* Name of VFS module to use, NULL for default */ + const char *zWal, /* Name of WAL module to use */ + void* pWalMethodsData /* User data, passed to the libsql_wal struct*/ +) { + assert( zWal == NULL ); + return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, make_sqlite3_wal_manager_rc()); +} + +int libsql_open_v3( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs, /* Name of VFS module to use, NULL for default */ + libsql_wal_manager wal_manager /* wal_manager implemetation */ + ) { + RefCountedWalManager *wal_manager_rc; + int rc = make_ref_counted_wal_manager(wal_manager, &wal_manager_rc); + if (rc) { + wal_manager.xDestroy(wal_manager.pData); + return rc; + } + return openDatabase(filename, ppDb, (unsigned int)flags, zVfs, wal_manager_rc); } #ifndef SQLITE_OMIT_UTF16 @@ -179020,7 +182813,7 @@ SQLITE_API int sqlite3_open16( zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zFilename8 ){ rc = openDatabase(zFilename8, ppDb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL, NULL); + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL, make_sqlite3_wal_manager_rc()); assert( *ppDb || rc==SQLITE_NOMEM ); if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; @@ -179143,6 +182936,69 @@ SQLITE_API int sqlite3_collation_needed16( } #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 @@ -179278,7 +183134,7 @@ SQLITE_API int sqlite3_table_column_metadata( /* Find the column for which info is requested */ if( zColumnName==0 ){ - /* Query for existance of table only */ + /* Query for existence of table only */ }else{ for(iCol=0; iColnCol; iCol++){ pCol = &pTab->aCol[iCol]; @@ -179359,7 +183215,7 @@ SQLITE_API int sqlite3_sleep(int ms){ /* This function works in milliseconds, but the underlying OsSleep() ** API uses microseconds. Hence the 1000's. */ - rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); + rc = (sqlite3OsSleep(pVfs, ms<0 ? 0 : 1000*ms)/1000); return rc; } @@ -179497,6 +183353,28 @@ SQLITE_API int sqlite3_test_control(int op, ...){ } #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; + } + break; + } + /* ** sqlite3_test_control(BITVEC_TEST, size, program) ** @@ -179603,10 +183481,12 @@ SQLITE_API int sqlite3_test_control(int op, ...){ 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); @@ -179723,7 +183603,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** 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 demonstrat invariants on well-formed database files. + ** that demonstrate invariants on well-formed database files. */ case SQLITE_TESTCTRL_NEVER_CORRUPT: { sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int); @@ -179877,7 +183757,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** ** op==0 Store the current sqlite3TreeTrace in *ptr ** op==1 Set sqlite3TreeTrace to the value *ptr - ** op==3 Store the current sqlite3WhereTrace in *ptr + ** op==2 Store the current sqlite3WhereTrace in *ptr ** op==3 Set sqlite3WhereTrace to the value *ptr */ case SQLITE_TESTCTRL_TRACEFLAGS: { @@ -179913,6 +183793,23 @@ SQLITE_API int sqlite3_test_control(int op, ...){ break; } +#if !defined(SQLITE_OMIT_WSD) + /* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X); + ** + ** X<0 Make no changes to the bUseLongDouble. Just report value. + ** X==0 Disable bUseLongDouble + ** X==1 Enable bUseLongDouble + ** X>=2 Set bUseLongDouble to its default value for this platform + */ + case SQLITE_TESTCTRL_USELONGDOUBLE: { + int b = va_arg(ap, int); + if( b>=2 ) b = hasHighPrecisionDouble(b); + if( b>=0 ) sqlite3Config.bUseLongDouble = b>0; + rc = sqlite3Config.bUseLongDouble!=0; + break; + } +#endif + #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) @@ -180213,7 +184110,7 @@ SQLITE_API int sqlite3_snapshot_get( } /* -** Open a read-transaction on the snapshot idendified by pSnapshot. +** Open a read-transaction on the snapshot identified by pSnapshot. */ SQLITE_API int sqlite3_snapshot_open( sqlite3 *db, @@ -180320,7 +184217,7 @@ SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ int nOpt; const char **azCompileOpt; -#if SQLITE_ENABLE_API_ARMOR +#ifdef SQLITE_ENABLE_API_ARMOR if( zOptName==0 ){ (void)SQLITE_MISUSE_BKPT; return 0; @@ -180515,6 +184412,9 @@ SQLITE_API int sqlite3_unlock_notify( ){ int rc = SQLITE_OK; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif sqlite3_mutex_enter(db->mutex); enterMutex(); @@ -181536,6 +185436,7 @@ struct Fts3Table { 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 @@ -182279,6 +186180,7 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){ 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]); @@ -185528,6 +189430,8 @@ static int fts3RenameMethod( rc = sqlite3Fts3PendingTermsFlush(p); } + p->bIgnoreSavepoint = 1; + if( p->zContentTbl==0 ){ fts3DbExec(&rc, db, "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", @@ -185555,6 +189459,8 @@ static int fts3RenameMethod( "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", p->zDb, p->zName, zName ); + + p->bIgnoreSavepoint = 0; return rc; } @@ -185565,12 +189471,28 @@ static int fts3RenameMethod( */ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ int rc = SQLITE_OK; - 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); + 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; + } } return rc; } @@ -185581,12 +189503,11 @@ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ ** This is a no-op. */ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(iSavepoint); - UNUSED_PARAMETER(pVtab); - assert( p->inTransaction ); - assert( p->mxSavepoint >= iSavepoint ); - TESTONLY( p->mxSavepoint = iSavepoint-1 ); + Fts3Table *pTab = (Fts3Table*)pVtab; + assert( pTab->inTransaction ); + assert( pTab->mxSavepoint >= iSavepoint ); + TESTONLY( pTab->mxSavepoint = iSavepoint-1 ); + pTab->iSavepoint = iSavepoint; return SQLITE_OK; } @@ -185596,11 +189517,13 @@ static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ ** Discard the contents of the pending terms table. */ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *p = (Fts3Table*)pVtab; + Fts3Table *pTab = (Fts3Table*)pVtab; UNUSED_PARAMETER(iSavepoint); - assert( p->inTransaction ); - TESTONLY( p->mxSavepoint = iSavepoint ); - sqlite3Fts3PendingTermsClear(p); + assert( pTab->inTransaction ); + TESTONLY( pTab->mxSavepoint = iSavepoint ); + if( (iSavepoint+1)<=pTab->iSavepoint ){ + sqlite3Fts3PendingTermsClear(pTab); + } return SQLITE_OK; } @@ -185619,8 +189542,49 @@ static int fts3ShadowName(const char *zName){ return 0; } +/* +** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual +** table. +*/ +static int fts3Integrity( + sqlite3_vtab *pVtab, /* The virtual table to be checked */ + const char *zSchema, /* Name of schema in which pVtab lives */ + const char *zTabname, /* Name of the pVTab table */ + int isQuick, /* True if this is a quick_check */ + char **pzErr /* Write error message here */ +){ + Fts3Table *p = (Fts3Table*)pVtab; + char *zSql; + int rc; + char *zErr = 0; + + assert( pzErr!=0 ); + assert( *pzErr==0 ); + UNUSED_PARAMETER(isQuick); + zSql = sqlite3_mprintf( + "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", + zSchema, zTabname, zTabname); + if( zSql==0 ){ + return SQLITE_NOMEM; + } + rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr); + sqlite3_free(zSql); + if( (rc&0xff)==SQLITE_CORRUPT ){ + *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", + p->bFts4 ? 4 : 3, zSchema, zTabname); + }else if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("unable to validate the inverted index for" + " FTS%d table %s.%s: %s", + p->bFts4 ? 4 : 3, zSchema, zTabname, zErr); + } + sqlite3_free(zErr); + return SQLITE_OK; +} + + + static const sqlite3_module fts3Module = { - /* iVersion */ 3, + /* iVersion */ 4, /* xCreate */ fts3CreateMethod, /* xConnect */ fts3ConnectMethod, /* xBestIndex */ fts3BestIndexMethod, @@ -185644,6 +189608,7 @@ static const sqlite3_module fts3Module = { /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, /* xShadowName */ fts3ShadowName, + /* xIntegrity */ fts3Integrity, }; /* @@ -188319,7 +192284,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; int rc; /* Return code */ @@ -191885,7 +195851,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestr 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; int rc; /* Return code */ @@ -194568,16 +198535,18 @@ static int fts3MsrBufferData( char *pList, i64 nList ){ - if( nList>pMsr->nBuffer ){ + if( (nList+FTS3_NODE_PADDING)>pMsr->nBuffer ){ char *pNew; - pMsr->nBuffer = nList*2; - pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer); + int nNew = nList*2 + FTS3_NODE_PADDING; + pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, nNew); 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; } @@ -195224,7 +199193,6 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ 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 @@ -195246,6 +199214,10 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ rc = sqlite3_reset(pStmt); } } + + if( rc==SQLITE_OK ){ + sqlite3Fts3PendingTermsClear(p); + } return rc; } @@ -195877,6 +199849,8 @@ static int fts3AppendToNode( 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; @@ -195933,9 +199907,13 @@ static int fts3IncrmergeAppend( 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, write this block out to the database. */ - if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){ + ** 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) + ){ rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); pWriter->nWork++; @@ -196246,6 +200224,7 @@ static int fts3IncrmergeLoad( for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ NodeReader reader; + memset(&reader, 0, sizeof(reader)); pNode = &pWriter->aNodeWriter[i]; if( pNode->block.a){ @@ -196266,7 +200245,7 @@ static int fts3IncrmergeLoad( 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; @@ -197116,7 +201095,7 @@ static u64 fts3ChecksumIndex( int rc; u64 cksum = 0; - assert( *pRc==SQLITE_OK ); + if( *pRc ) return 0; memset(&filter, 0, sizeof(filter)); memset(&csr, 0, sizeof(csr)); @@ -197331,8 +201310,11 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ 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{ + else{ int v; if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ v = atoi(&zVal[9]); @@ -197350,8 +201332,8 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v; rc = SQLITE_OK; } -#endif } +#endif return rc; } @@ -200292,25 +204274,51 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ ** 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, + 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) (jsonIsSpace[(unsigned char)x]) +/* +** Characters that are special to JSON. Control charaters, +** '"' and '\\'. +*/ +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 +}; + + #if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) # define VVA(X) #else @@ -200321,6 +204329,7 @@ static const char jsonIsSpace[] = { typedef struct JsonString JsonString; typedef struct JsonNode JsonNode; typedef struct JsonParse JsonParse; +typedef struct JsonCleanup JsonCleanup; /* An instance of this object represents a JSON string ** under construction. Really, this is a generic string accumulator @@ -200336,16 +204345,26 @@ struct JsonString { char zSpace[100]; /* Initial static space */ }; +/* A deferred cleanup task. A list of JsonCleanup objects might be +** run when the JsonParse object is destroyed. +*/ +struct JsonCleanup { + JsonCleanup *pJCNext; /* Next in a list */ + void (*xOp)(void*); /* Routine to run */ + void *pArg; /* Argument to xOp() */ +}; + /* 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 +#define JSON_SUBST 0 /* Special edit node. Uses u.iPrev */ +#define JSON_NULL 1 +#define JSON_TRUE 2 +#define JSON_FALSE 3 +#define JSON_INT 4 +#define JSON_REAL 5 +#define JSON_STRING 6 +#define JSON_ARRAY 7 +#define JSON_OBJECT 8 /* The "subtype" set for JSON values */ #define JSON_SUBTYPE 74 /* Ascii for "J" */ @@ -200354,59 +204373,97 @@ struct JsonString { ** Names of the various JSON types: */ static const char * const jsonType[] = { + "subst", "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 */ +#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 /* Target of a JSON_SUBST node */ +#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */ +#define JNODE_LABEL 0x20 /* Is a label of an object */ +#define JNODE_JSON5 0x40 /* Node contains JSON5 enhancements */ -/* A single node of parsed JSON +/* A single node of parsed JSON. An array of these nodes describes +** a parse of JSON + edits. +** +** Use the json_parse() SQL function (available when compiled with +** -DSQLITE_DEBUG) to see a dump of complete JsonParse objects, including +** a complete listing and decoding of the array of JsonNodes. */ struct JsonNode { u8 eType; /* One of the JSON_ type values */ u8 jnFlags; /* JNODE flags */ u8 eU; /* Which union element to use */ - u32 n; /* Bytes of content, or number of sub-nodes */ + u32 n; /* Bytes of content for INT, REAL or STRING + ** Number of sub-nodes for ARRAY and OBJECT + ** Node that SUBST applies to */ union { const char *zJContent; /* 1: Content for INT, REAL, and STRING */ u32 iAppend; /* 2: More terms for ARRAY and OBJECT */ u32 iKey; /* 3: Key for ARRAY objects in json_tree() */ - u32 iReplace; /* 4: Replacement content for JNODE_REPLACE */ - JsonNode *pPatch; /* 5: Node chain of patch for JNODE_PATCH */ + u32 iPrev; /* 4: Previous SUBST node, or 0 */ } u; }; -/* A completely parsed JSON string + +/* A parsed and possibly edited JSON string. Lifecycle: +** +** 1. JSON comes in and is parsed into an array aNode[]. The original +** JSON text is stored in zJson. +** +** 2. Zero or more changes are made (via json_remove() or json_replace() +** or similar) to the aNode[] array. +** +** 3. A new, edited and mimified JSON string is generated from aNode +** and stored in zAlt. The JsonParse object always owns zAlt. +** +** Step 1 always happens. Step 2 and 3 may or may not happen, depending +** on the operation. +** +** aNode[].u.zJContent entries typically point into zJson. Hence zJson +** must remain valid for the lifespan of the parse. For edits, +** aNode[].u.zJContent might point to malloced space other than zJson. +** Entries in pClup are responsible for freeing that extra malloced space. +** +** When walking the parse tree in aNode[], edits are ignored if useMod is +** false. */ 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 */ + char *zJson; /* Original JSON string (before edits) */ + char *zAlt; /* Revised and/or mimified JSON */ u32 *aUp; /* Index of parent of each node */ - u8 oom; /* Set to true if out of memory */ - u8 nErr; /* Number of errors seen */ + JsonCleanup *pClup;/* Cleanup operations prior to freeing this object */ 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 useMod; /* Actually use the edits contain inside aNode */ + u8 hasMod; /* aNode contains edits from the original zJson */ + u32 nJPRef; /* Number of references to this object */ int nJson; /* Length of the zJson string in bytes */ - u32 iHold; /* Replace cache line with the lowest iHold value */ + int nAlt; /* Length of alternative JSON string zAlt, in bytes */ + u32 iErr; /* Error location in zJson[] */ + u32 iSubst; /* Last JSON_SUBST entry in aNode[] */ + u32 iHold; /* Age of this entry in the cache for LRU replacement */ }; /* ** 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. +** 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 */ -#define JSON_MAX_DEPTH 2000 +#define JSON_MAX_DEPTH 1000 /************************************************************************** ** Utility routines for dealing with JsonString objects @@ -200429,16 +204486,14 @@ static void jsonInit(JsonString *p, sqlite3_context *pCtx){ 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); + if( !p->bStatic ) sqlite3RCStrUnref(p->zBuf); jsonZero(p); } - /* Report an out-of-memory (OOM) condition */ static void jsonOom(JsonString *p){ @@ -200455,7 +204510,7 @@ static int jsonGrow(JsonString *p, u32 N){ char *zNew; if( p->bStatic ){ if( p->bErr ) return 1; - zNew = sqlite3_malloc64(nTotal); + zNew = sqlite3RCStrNew(nTotal); if( zNew==0 ){ jsonOom(p); return SQLITE_NOMEM; @@ -200464,12 +204519,12 @@ static int jsonGrow(JsonString *p, u32 N){ p->zBuf = zNew; p->bStatic = 0; }else{ - zNew = sqlite3_realloc64(p->zBuf, nTotal); - if( zNew==0 ){ - jsonOom(p); + p->zBuf = sqlite3RCStrResize(p->zBuf, nTotal); + if( p->zBuf==0 ){ + p->bErr = 1; + jsonZero(p); return SQLITE_NOMEM; } - p->zBuf = zNew; } p->nAlloc = nTotal; return SQLITE_OK; @@ -200477,12 +204532,35 @@ static int jsonGrow(JsonString *p, u32 N){ /* Append N bytes from zIn onto the end of the JsonString string. */ -static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ - if( N==0 ) return; - if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; +static SQLITE_NOINLINE void jsonAppendExpand( + JsonString *p, + const char *zIn, + u32 N +){ + assert( N>0 ); + if( jsonGrow(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 ){ + jsonAppendExpand(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 ){ + jsonAppendExpand(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. */ @@ -200497,10 +204575,35 @@ static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ /* Append a single character */ -static void jsonAppendChar(JsonString *p, char c){ - if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; +static SQLITE_NOINLINE void jsonAppendCharExpand(JsonString *p, char c){ + if( jsonGrow(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; + } +} + +/* Try to force the string to be a zero-terminated RCStr string. +** +** Return true on success. Return false if an OOM prevents this +** from happening. +*/ +static int jsonForceRCStr(JsonString *p){ + jsonAppendChar(p, 0); + if( p->bErr ) return 0; + p->nUsed--; + if( p->bStatic==0 ) return 1; + p->nAlloc = 0; + p->nUsed++; + jsonGrow(p, p->nUsed); + p->nUsed--; + return p->bStatic==0; +} + /* Append a comma separator to the output buffer, if the previous ** character is not '[' or '{'. @@ -200509,7 +204612,8 @@ static void jsonAppendSeparator(JsonString *p){ char c; if( p->nUsed==0 ) return; c = p->zBuf[p->nUsed-1]; - if( c!='[' && c!='{' ) jsonAppendChar(p, ','); + if( c=='[' || c=='{' ) return; + jsonAppendChar(p, ','); } /* Append the N-byte string in zIn to the end of the JsonString string @@ -200523,11 +204627,16 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ p->zBuf[p->nUsed++] = '"'; for(i=0; izBuf[p->nUsed++] = c; + }else if( c=='"' || c=='\\' ){ json_simple_escape: if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; p->zBuf[p->nUsed++] = '\\'; - }else if( c<=0x1f ){ + p->zBuf[p->nUsed++] = c; + }else if( c=='\'' ){ + p->zBuf[p->nUsed++] = c; + }else{ 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 @@ -200538,6 +204647,7 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ assert( aSpecial['\n']=='n' ); assert( aSpecial['\r']=='r' ); assert( aSpecial['\t']=='t' ); + assert( c>=0 && czBuf[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++] = "0123456789abcdef"[c>>4]; + p->zBuf[p->nUsed++] = "0123456789abcdef"[c&0xf]; } - p->zBuf[p->nUsed++] = c; } p->zBuf[p->nUsed++] = '"'; assert( p->nUsednAlloc ); } +/* +** The zIn[0..N] string is a JSON5 string literal. Append to p a translation +** of the string literal that standard JSON and that omits all JSON5 +** features. +*/ +static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){ + u32 i; + jsonAppendChar(p, '"'); + zIn++; + N -= 2; + while( N>0 ){ + for(i=0; i0 ){ + jsonAppendRawNZ(p, zIn, i); + zIn += i; + N -= i; + if( N==0 ) break; + } + assert( zIn[0]=='\\' ); + switch( (u8)zIn[1] ){ + case '\'': + jsonAppendChar(p, '\''); + break; + case 'v': + jsonAppendRawNZ(p, "\\u0009", 6); + break; + case 'x': + jsonAppendRawNZ(p, "\\u00", 4); + jsonAppendRawNZ(p, &zIn[2], 2); + zIn += 2; + N -= 2; + break; + case '0': + jsonAppendRawNZ(p, "\\u0000", 6); + break; + case '\r': + if( zIn[2]=='\n' ){ + zIn++; + N--; + } + break; + case '\n': + break; + case 0xe2: + assert( N>=4 ); + assert( 0x80==(u8)zIn[2] ); + assert( 0xa8==(u8)zIn[3] || 0xa9==(u8)zIn[3] ); + zIn += 2; + N -= 2; + break; + default: + jsonAppendRawNZ(p, zIn, 2); + break; + } + zIn += 2; + N -= 2; + } + jsonAppendChar(p, '"'); +} + +/* +** The zIn[0..N] string is a JSON5 integer literal. Append to p a translation +** of the string literal that standard JSON and that omits all JSON5 +** features. +*/ +static void jsonAppendNormalizedInt(JsonString *p, const char *zIn, u32 N){ + if( zIn[0]=='+' ){ + zIn++; + N--; + }else if( zIn[0]=='-' ){ + jsonAppendChar(p, '-'); + zIn++; + N--; + } + if( zIn[0]=='0' && (zIn[1]=='x' || zIn[1]=='X') ){ + sqlite3_int64 i = 0; + int rc = sqlite3DecOrHexToI64(zIn, &i); + if( rc<=1 ){ + jsonPrintf(100,p,"%lld",i); + }else{ + assert( rc==2 ); + jsonAppendRawNZ(p, "9.0e999", 7); + } + return; + } + assert( N>0 ); + jsonAppendRawNZ(p, zIn, N); +} + +/* +** The zIn[0..N] string is a JSON5 real literal. Append to p a translation +** of the string literal that standard JSON and that omits all JSON5 +** features. +*/ +static void jsonAppendNormalizedReal(JsonString *p, const char *zIn, u32 N){ + u32 i; + if( zIn[0]=='+' ){ + zIn++; + N--; + }else if( zIn[0]=='-' ){ + jsonAppendChar(p, '-'); + zIn++; + N--; + } + if( zIn[0]=='.' ){ + jsonAppendChar(p, '0'); + } + for(i=0; i0 ){ + jsonAppendRawNZ(p, zIn, N); + } +} + + + /* ** Append a function parameter value to the JSON string under ** construction. @@ -200566,11 +204799,14 @@ static void jsonAppendValue( ){ switch( sqlite3_value_type(pValue) ){ case SQLITE_NULL: { - jsonAppendRaw(p, "null", 4); + jsonAppendRawNZ(p, "null", 4); break; } - case SQLITE_INTEGER: 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); @@ -200599,15 +204835,25 @@ static void jsonAppendValue( /* Make the JSON in p the result of the SQL function. +** +** The JSON string is reset. */ 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); + if( p->bStatic ){ + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + SQLITE_TRANSIENT, SQLITE_UTF8); + }else if( jsonForceRCStr(p) ){ + sqlite3RCStrRef(p->zBuf); + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + sqlite3RCStrUnref, + SQLITE_UTF8); + } + } + if( p->bErr==1 ){ + sqlite3_result_error_nomem(p->pCtx); } - assert( p->bStatic ); + jsonReset(p); } /************************************************************************** @@ -200632,20 +204878,73 @@ static u32 jsonNodeSize(JsonNode *pNode){ ** delete the JsonParse object itself. */ static void jsonParseReset(JsonParse *pParse){ - sqlite3_free(pParse->aNode); - pParse->aNode = 0; + while( pParse->pClup ){ + JsonCleanup *pTask = pParse->pClup; + pParse->pClup = pTask->pJCNext; + pTask->xOp(pTask->pArg); + sqlite3_free(pTask); + } + assert( pParse->nJPRef<=1 ); + if( pParse->aNode ){ + sqlite3_free(pParse->aNode); + pParse->aNode = 0; + } pParse->nNode = 0; pParse->nAlloc = 0; - sqlite3_free(pParse->aUp); - pParse->aUp = 0; + if( pParse->aUp ){ + sqlite3_free(pParse->aUp); + pParse->aUp = 0; + } + if( pParse->bJsonIsRCStr ){ + sqlite3RCStrUnref(pParse->zJson); + pParse->zJson = 0; + pParse->bJsonIsRCStr = 0; + } + if( pParse->zAlt ){ + sqlite3RCStrUnref(pParse->zAlt); + pParse->zAlt = 0; + } } /* ** Free a JsonParse object that was obtained from sqlite3_malloc(). +** +** Note that destroying JsonParse might call sqlite3RCStrUnref() to +** destroy the zJson value. The RCStr object might recursively invoke +** JsonParse to destroy this pParse object again. Take care to ensure +** that this recursive destructor sequence terminates harmlessly. */ static void jsonParseFree(JsonParse *pParse){ - jsonParseReset(pParse); - sqlite3_free(pParse); + if( pParse->nJPRef>1 ){ + pParse->nJPRef--; + }else{ + jsonParseReset(pParse); + sqlite3_free(pParse); + } +} + +/* +** Add a cleanup task to the JsonParse object. +** +** If an OOM occurs, the cleanup operation happens immediately +** and this function returns SQLITE_NOMEM. +*/ +static int jsonParseAddCleanup( + JsonParse *pParse, /* Add the cleanup task to this parser */ + void(*xOp)(void*), /* The cleanup task */ + void *pArg /* Argument to the cleanup */ +){ + JsonCleanup *pTask = sqlite3_malloc64( sizeof(*pTask) ); + if( pTask==0 ){ + pParse->oom = 1; + xOp(pArg); + return SQLITE_ERROR; + } + pTask->pJCNext = pParse->pClup; + pParse->pClup = pTask; + pTask->xOp = xOp; + pTask->pArg = pArg; + return SQLITE_OK; } /* @@ -200654,46 +204953,76 @@ static void jsonParseFree(JsonParse *pParse){ ** the number of JsonNode objects that are encoded. */ static void jsonRenderNode( + JsonParse *pParse, /* the complete parse of the JSON */ JsonNode *pNode, /* The node to render */ - JsonString *pOut, /* Write JSON here */ - sqlite3_value **aReplace /* Replacement values */ + JsonString *pOut /* Write JSON here */ ){ assert( pNode!=0 ); - if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ - if( (pNode->jnFlags & JNODE_REPLACE)!=0 && ALWAYS(aReplace!=0) ){ - assert( pNode->eU==4 ); - jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); - return; + while( (pNode->jnFlags & JNODE_REPLACE)!=0 && pParse->useMod ){ + u32 idx = (u32)(pNode - pParse->aNode); + u32 i = pParse->iSubst; + while( 1 /*exit-by-break*/ ){ + assert( inNode ); + assert( pParse->aNode[i].eType==JSON_SUBST ); + assert( pParse->aNode[i].eU==4 ); + assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ + pNode = &pParse->aNode[i+1]; + break; + } + i = pParse->aNode[i].u.iPrev; } - assert( pNode->eU==5 ); - pNode = pNode->u.pPatch; } switch( pNode->eType ){ default: { assert( pNode->eType==JSON_NULL ); - jsonAppendRaw(pOut, "null", 4); + jsonAppendRawNZ(pOut, "null", 4); break; } case JSON_TRUE: { - jsonAppendRaw(pOut, "true", 4); + jsonAppendRawNZ(pOut, "true", 4); break; } case JSON_FALSE: { - jsonAppendRaw(pOut, "false", 5); + jsonAppendRawNZ(pOut, "false", 5); break; } case JSON_STRING: { + assert( pNode->eU==1 ); if( pNode->jnFlags & JNODE_RAW ){ - assert( pNode->eU==1 ); - jsonAppendString(pOut, pNode->u.zJContent, pNode->n); - break; + if( pNode->jnFlags & JNODE_LABEL ){ + jsonAppendChar(pOut, '"'); + jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + jsonAppendChar(pOut, '"'); + }else{ + jsonAppendString(pOut, pNode->u.zJContent, pNode->n); + } + }else if( pNode->jnFlags & JNODE_JSON5 ){ + jsonAppendNormalizedString(pOut, pNode->u.zJContent, pNode->n); + }else{ + assert( pNode->n>0 ); + jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); } - /* no break */ deliberate_fall_through + break; + } + case JSON_REAL: { + assert( pNode->eU==1 ); + if( pNode->jnFlags & JNODE_JSON5 ){ + jsonAppendNormalizedReal(pOut, pNode->u.zJContent, pNode->n); + }else{ + assert( pNode->n>0 ); + jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); + } + break; } - case JSON_REAL: case JSON_INT: { assert( pNode->eU==1 ); - jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + if( pNode->jnFlags & JNODE_JSON5 ){ + jsonAppendNormalizedInt(pOut, pNode->u.zJContent, pNode->n); + }else{ + assert( pNode->n>0 ); + jsonAppendRawNZ(pOut, pNode->u.zJContent, pNode->n); + } break; } case JSON_ARRAY: { @@ -200701,15 +205030,16 @@ static void jsonRenderNode( jsonAppendChar(pOut, '['); for(;;){ while( j<=pNode->n ){ - if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ + if( (pNode[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ){ jsonAppendSeparator(pOut); - jsonRenderNode(&pNode[j], pOut, aReplace); + jsonRenderNode(pParse, &pNode[j], pOut); } j += jsonNodeSize(&pNode[j]); } if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pNode->eU==2 ); - pNode = &pNode[pNode->u.iAppend]; + pNode = &pParse->aNode[pNode->u.iAppend]; j = 1; } jsonAppendChar(pOut, ']'); @@ -200720,17 +205050,18 @@ static void jsonRenderNode( jsonAppendChar(pOut, '{'); for(;;){ while( j<=pNode->n ){ - if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ + if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ){ jsonAppendSeparator(pOut); - jsonRenderNode(&pNode[j], pOut, aReplace); + jsonRenderNode(pParse, &pNode[j], pOut); jsonAppendChar(pOut, ':'); - jsonRenderNode(&pNode[j+1], pOut, aReplace); + jsonRenderNode(pParse, &pNode[j+1], pOut); } j += 1 + jsonNodeSize(&pNode[j+1]); } if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pNode->eU==2 ); - pNode = &pNode[pNode->u.iAppend]; + pNode = &pParse->aNode[pNode->u.iAppend]; j = 1; } jsonAppendChar(pOut, '}'); @@ -200740,18 +205071,29 @@ static void jsonRenderNode( } /* -** Return a JsonNode and all its descendents as a JSON string. +** Return a JsonNode and all its descendants as a JSON string. */ static void jsonReturnJson( + JsonParse *pParse, /* The complete JSON */ JsonNode *pNode, /* Node to return */ sqlite3_context *pCtx, /* Return value for this function */ - sqlite3_value **aReplace /* Array of replacement values */ + int bGenerateAlt /* Also store the rendered text in zAlt */ ){ JsonString s; - jsonInit(&s, pCtx); - jsonRenderNode(pNode, &s, aReplace); - jsonResult(&s); - sqlite3_result_subtype(pCtx, JSON_SUBTYPE); + if( pParse->oom ){ + sqlite3_result_error_nomem(pCtx); + return; + } + if( pParse->nErr==0 ){ + jsonInit(&s, pCtx); + jsonRenderNode(pParse, pNode, &s); + if( bGenerateAlt && pParse->zAlt==0 && jsonForceRCStr(&s) ){ + pParse->zAlt = sqlite3RCStrRef(s.zBuf); + pParse->nAlt = s.nUsed; + } + jsonResult(&s); + sqlite3_result_subtype(pCtx, JSON_SUBTYPE); + } } /* @@ -200789,9 +205131,9 @@ static u32 jsonHexToInt4(const char *z){ ** Make the JsonNode the return value of the function. */ static void jsonReturn( + JsonParse *pParse, /* Complete JSON parse tree */ JsonNode *pNode, /* Node to return */ - sqlite3_context *pCtx, /* Return value for this function */ - sqlite3_value **aReplace /* Array of replacement values */ + sqlite3_context *pCtx /* Return value for this function */ ){ switch( pNode->eType ){ default: { @@ -200809,59 +205151,40 @@ static void jsonReturn( } case JSON_INT: { sqlite3_int64 i = 0; + int rc; + int bNeg = 0; const char *z; + assert( pNode->eU==1 ); 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( z[0]=='-' ){ z++; bNeg = 1; } + else if( z[0]=='+' ){ z++; } + rc = sqlite3DecOrHexToI64(z, &i); + if( rc<=1 ){ + sqlite3_result_int64(pCtx, bNeg ? -i : i); + }else if( rc==3 && bNeg ){ + sqlite3_result_int64(pCtx, SMALLEST_INT64); + }else{ + goto to_double; } - if( pNode->u.zJContent[0]=='-' ){ i = -i; } - sqlite3_result_int64(pCtx, i); - int_done: break; - int_as_real: ; /* no break */ deliberate_fall_through } case JSON_REAL: { double r; -#ifdef SQLITE_AMALGAMATION const char *z; assert( pNode->eU==1 ); + to_double: z = pNode->u.zJContent; sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); -#else - assert( pNode->eU==1 ); - 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 ){ assert( pNode->eU==1 ); 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 ){ + }else if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){ /* JSON formatted without any backslash-escapes */ assert( pNode->eU==1 ); sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, @@ -200873,18 +205196,17 @@ static void jsonReturn( const char *z; char *zOut; u32 j; + u32 nOut = n; assert( pNode->eU==1 ); z = pNode->u.zJContent; - zOut = sqlite3_malloc( n+1 ); + zOut = sqlite3_malloc( nOut+1 ); if( zOut==0 ){ sqlite3_result_error_nomem(pCtx); break; } for(i=1, j=0; iaNode after first expanding the +** size of the aNode array. Return the index of the new node. +** +** If an OOM error occurs, set pParse->oom and return -1. +*/ static JSON_NOINLINE int jsonParseAddNodeExpand( JsonParse *pParse, /* Append the node to this object */ u32 eType, /* Node type */ @@ -200977,7 +205323,7 @@ static JSON_NOINLINE int jsonParseAddNodeExpand( pParse->oom = 1; return -1; } - pParse->nAlloc = nNew; + pParse->nAlloc = sqlite3_msize(pNew)/sizeof(JsonNode); pParse->aNode = pNew; assert( pParse->nNodenAlloc ); return jsonParseAddNode(pParse, eType, n, zContent); @@ -200995,34 +205341,239 @@ static int jsonParseAddNode( const char *zContent /* Content */ ){ JsonNode *p; - if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){ + assert( pParse->aNode!=0 || pParse->nNode>=pParse->nAlloc ); + if( pParse->nNode>=pParse->nAlloc ){ return jsonParseAddNodeExpand(pParse, eType, n, zContent); } + assert( pParse->aNode!=0 ); p = &pParse->aNode[pParse->nNode]; - p->eType = (u8)eType; - p->jnFlags = 0; + assert( p!=0 ); + p->eType = (u8)(eType & 0xff); + p->jnFlags = (u8)(eType >> 8); VVA( p->eU = zContent ? 1 : 0 ); p->n = n; p->u.zJContent = zContent; return pParse->nNode++; } +/* +** Add an array of new nodes to the current pParse->aNode array. +** Return the index of the first node added. +** +** If an OOM error occurs, set pParse->oom. +*/ +static void jsonParseAddNodeArray( + JsonParse *pParse, /* Append the node to this object */ + JsonNode *aNode, /* Array of nodes to add */ + u32 nNode /* Number of elements in aNew */ +){ + assert( aNode!=0 ); + assert( nNode>=1 ); + if( pParse->nNode + nNode > pParse->nAlloc ){ + u32 nNew = pParse->nNode + nNode; + JsonNode *aNew = sqlite3_realloc64(pParse->aNode, nNew*sizeof(JsonNode)); + if( aNew==0 ){ + pParse->oom = 1; + return; + } + pParse->nAlloc = sqlite3_msize(aNew)/sizeof(JsonNode); + pParse->aNode = aNew; + } + memcpy(&pParse->aNode[pParse->nNode], aNode, nNode*sizeof(JsonNode)); + pParse->nNode += nNode; +} + +/* +** Add a new JSON_SUBST node. The node immediately following +** this new node will be the substitute content for iNode. +*/ +static int jsonParseAddSubstNode( + JsonParse *pParse, /* Add the JSON_SUBST here */ + u32 iNode /* References this node */ +){ + int idx = jsonParseAddNode(pParse, JSON_SUBST, iNode, 0); + if( pParse->oom ) return -1; + pParse->aNode[iNode].jnFlags |= JNODE_REPLACE; + pParse->aNode[idx].eU = 4; + pParse->aNode[idx].u.iPrev = pParse->iSubst; + pParse->iSubst = idx; + pParse->hasMod = 1; + pParse->useMod = 1; + return idx; +} + +/* +** 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){ - int i; - for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0; - return 1; + 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, JSON_REAL, 7, "inf", "9.0e999" }, + { 'i', 'I', 8, JSON_REAL, 7, "infinity", "9.0e999" }, + { 'n', 'N', 3, JSON_NULL, 4, "NaN", "null" }, + { 'q', 'Q', 4, JSON_NULL, 4, "QNaN", "null" }, + { 's', 'S', 4, JSON_NULL, 4, "SNaN", "null" }, +}; + /* ** 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 ']'. +** Special return values: +** +** 0 End of input +** -1 Syntax error +** -2 '}' seen +** -3 ']' seen +** -4 ',' seen +** -5 ':' seen */ static int jsonParseValue(JsonParse *pParse, u32 i){ char c; @@ -201031,175 +205582,457 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ int x; JsonNode *pNode; const char *z = pParse->zJson; - while( fast_isspace(z[i]) ){ i++; } - if( (c = z[i])=='{' ){ +json_parse_restart: + switch( (u8)z[i] ){ + case '{': { /* Parse object */ iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); if( iThis<0 ) return -1; + if( ++pParse->iDepth > JSON_MAX_DEPTH ){ + pParse->iErr = i; + return -1; + } for(j=i+1;;j++){ - while( fast_isspace(z[j]) ){ j++; } - if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; + u32 nNode = pParse->nNode; x = jsonParseValue(pParse, j); - if( x<0 ){ - pParse->iDepth--; - if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1; - return -1; + if( x<=0 ){ + if( x==(-2) ){ + j = pParse->iErr; + if( pParse->nNode!=(u32)iThis+1 ) pParse->hasNonstd = 1; + break; + } + j += json5Whitespace(&z[j]); + if( sqlite3JsonId1(z[j]) + || (z[j]=='\\' && z[j+1]=='u' && jsonIs4Hex(&z[j+2])) + ){ + int k = j+1; + while( (sqlite3JsonId2(z[k]) && json5Whitespace(&z[k])==0) + || (z[k]=='\\' && z[k+1]=='u' && jsonIs4Hex(&z[k+2])) + ){ + k++; + } + jsonParseAddNode(pParse, JSON_STRING | (JNODE_RAW<<8), k-j, &z[j]); + pParse->hasNonstd = 1; + x = k; + }else{ + if( x!=-1 ) pParse->iErr = j; + return -1; + } } if( pParse->oom ) return -1; - pNode = &pParse->aNode[pParse->nNode-1]; - if( pNode->eType!=JSON_STRING ) return -1; + pNode = &pParse->aNode[nNode]; + if( pNode->eType!=JSON_STRING ){ + pParse->iErr = j; + return -1; + } pNode->jnFlags |= JNODE_LABEL; j = x; - while( fast_isspace(z[j]) ){ j++; } - if( z[j]!=':' ) return -1; - j++; + if( z[j]==':' ){ + j++; + }else{ + if( fast_isspace(z[j]) ){ + do{ j++; }while( fast_isspace(z[j]) ); + if( z[j]==':' ){ + j++; + goto parse_object_value; + } + } + x = jsonParseValue(pParse, j); + if( x!=(-5) ){ + if( x!=(-1) ) pParse->iErr = j; + return -1; + } + j = pParse->iErr+1; + } + parse_object_value: x = jsonParseValue(pParse, j); - pParse->iDepth--; - if( x<0 ) return -1; + if( x<=0 ){ + if( x!=(-1) ) pParse->iErr = j; + return -1; + } j = x; - while( fast_isspace(z[j]) ){ j++; } - c = z[j]; - if( c==',' ) continue; - if( c!='}' ) return -1; - break; + if( z[j]==',' ){ + continue; + }else if( z[j]=='}' ){ + break; + }else{ + if( fast_isspace(z[j]) ){ + do{ j++; }while( fast_isspace(z[j]) ); + if( z[j]==',' ){ + continue; + }else if( z[j]=='}' ){ + break; + } + } + x = jsonParseValue(pParse, j); + if( x==(-4) ){ + j = pParse->iErr; + continue; + } + if( x==(-2) ){ + j = pParse->iErr; + break; + } + } + pParse->iErr = j; + return -1; } pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + pParse->iDepth--; return j+1; - }else if( c=='[' ){ + } + case '[': { /* Parse array */ iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); if( iThis<0 ) return -1; + if( ++pParse->iDepth > JSON_MAX_DEPTH ){ + pParse->iErr = i; + return -1; + } memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u)); for(j=i+1;;j++){ - while( fast_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; + if( x<=0 ){ + if( x==(-3) ){ + j = pParse->iErr; + if( pParse->nNode!=(u32)iThis+1 ) pParse->hasNonstd = 1; + break; + } + if( x!=(-1) ) pParse->iErr = j; return -1; } j = x; - while( fast_isspace(z[j]) ){ j++; } - c = z[j]; - if( c==',' ) continue; - if( c!=']' ) return -1; - break; + if( z[j]==',' ){ + continue; + }else if( z[j]==']' ){ + break; + }else{ + if( fast_isspace(z[j]) ){ + do{ j++; }while( fast_isspace(z[j]) ); + if( z[j]==',' ){ + continue; + }else if( z[j]==']' ){ + break; + } + } + x = jsonParseValue(pParse, j); + if( x==(-4) ){ + j = pParse->iErr; + continue; + } + if( x==(-3) ){ + j = pParse->iErr; + break; + } + } + pParse->iErr = j; + return -1; } pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + pParse->iDepth--; return j+1; - }else if( c=='"' ){ + } + case '\'': { + u8 jnFlags; + char cDelim; + pParse->hasNonstd = 1; + jnFlags = JNODE_JSON5; + goto parse_string; + case '"': /* Parse string */ - u8 jnFlags = 0; - j = i+1; - for(;;){ + jnFlags = 0; + parse_string: + cDelim = z[i]; + for(j=i+1; 1; j++){ + if( jsonIsOk[(unsigned char)z[j]] ) continue; c = z[j]; - if( (c & ~0x1f)==0 ){ - /* Control characters are not allowed in strings */ - return -1; - } - if( c=='\\' ){ + 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)) ){ - jnFlags = JNODE_ESCAPE; + || (c=='u' && jsonIs4Hex(&z[j+1])) ){ + jnFlags |= JNODE_ESCAPE; + }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])) ){ + jnFlags |= (JNODE_ESCAPE|JNODE_JSON5); + pParse->hasNonstd = 1; + }else if( c=='\r' ){ + if( z[j+1]=='\n' ) j++; + jnFlags |= (JNODE_ESCAPE|JNODE_JSON5); + pParse->hasNonstd = 1; }else{ + pParse->iErr = j; return -1; } - }else if( c=='"' ){ - break; + }else if( c<=0x1f ){ + /* Control characters are not allowed in strings */ + pParse->iErr = j; + return -1; } - j++; } - jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]); - if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags; + jsonParseAddNode(pParse, JSON_STRING | (jnFlags<<8), j+1-i, &z[i]); return j+1; - }else if( c=='n' - && strncmp(z+i,"null",4)==0 - && !sqlite3Isalnum(z[i+4]) ){ - jsonParseAddNode(pParse, JSON_NULL, 0, 0); - return i+4; - }else if( c=='t' - && strncmp(z+i,"true",4)==0 - && !sqlite3Isalnum(z[i+4]) ){ - jsonParseAddNode(pParse, JSON_TRUE, 0, 0); - return i+4; - }else if( c=='f' - && strncmp(z+i,"false",5)==0 - && !sqlite3Isalnum(z[i+5]) ){ - jsonParseAddNode(pParse, JSON_FALSE, 0, 0); - return i+5; - }else if( c=='-' || (c>='0' && c<='9') ){ + } + case 't': { + if( strncmp(z+i,"true",4)==0 && !sqlite3Isalnum(z[i+4]) ){ + jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + return i+4; + } + pParse->iErr = i; + return -1; + } + case 'f': { + if( strncmp(z+i,"false",5)==0 && !sqlite3Isalnum(z[i+5]) ){ + jsonParseAddNode(pParse, JSON_FALSE, 0, 0); + return i+5; + } + pParse->iErr = i; + return -1; + } + case '+': { + u8 seenDP, seenE, jnFlags; + pParse->hasNonstd = 1; + jnFlags = JNODE_JSON5; + goto parse_number; + case '.': + if( sqlite3Isdigit(z[i+1]) ){ + pParse->hasNonstd = 1; + jnFlags = JNODE_JSON5; + seenE = 0; + seenDP = JSON_REAL; + 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 */ - u8 seenDP = 0; - u8 seenE = 0; + jnFlags = 0; + parse_number: + seenDP = JSON_INT; + seenE = 0; assert( '-' < '0' ); + assert( '+' < '0' ); + assert( '.' < '0' ); + c = z[i]; + if( c<='0' ){ - j = c=='-' ? i+1 : i; - if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1; + if( c=='0' ){ + if( (z[i+1]=='x' || z[i+1]=='X') && sqlite3Isxdigit(z[i+2]) ){ + assert( seenDP==JSON_INT ); + pParse->hasNonstd = 1; + jnFlags |= JNODE_JSON5; + 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]=='-' ){ + jsonParseAddNode(pParse, JSON_REAL, 8, "-9.0e999"); + }else{ + jsonParseAddNode(pParse, JSON_REAL, 7, "9.0e999"); + } + return i + (sqlite3StrNICmp(&z[i+4],"inity",5)==0 ? 9 : 4); + } + if( z[i+1]=='.' ){ + pParse->hasNonstd = 1; + jnFlags |= JNODE_JSON5; + 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; + jnFlags |= JNODE_JSON5; + for(j=i+4; sqlite3Isxdigit(z[j]); j++){} + goto parse_number_finish; + } + } + } } - j = i+1; - for(;; j++){ + parse_number_2: + for(j=i+1;; j++){ c = z[j]; - if( c>='0' && c<='9' ) continue; + if( sqlite3Isdigit(c) ) continue; if( c=='.' ){ - if( z[j-1]=='-' ) return -1; - if( seenDP ) return -1; - seenDP = 1; + if( seenDP==JSON_REAL ){ + pParse->iErr = j; + return -1; + } + seenDP = JSON_REAL; continue; } if( c=='e' || c=='E' ){ - if( z[j-1]<'0' ) return -1; - if( seenE ) return -1; - seenDP = seenE = 1; + if( z[j-1]<'0' ){ + if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ + pParse->hasNonstd = 1; + jnFlags |= JNODE_JSON5; + }else{ + pParse->iErr = j; + return -1; + } + } + if( seenE ){ + pParse->iErr = j; + return -1; + } + seenDP = JSON_REAL; + seenE = 1; c = z[j+1]; if( c=='+' || c=='-' ){ j++; c = z[j+1]; } - if( c<'0' || c>'9' ) return -1; + if( c<'0' || c>'9' ){ + pParse->iErr = j; + return -1; + } continue; } break; } - if( z[j-1]<'0' ) return -1; - jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT, - j - i, &z[i]); + if( z[j-1]<'0' ){ + if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){ + pParse->hasNonstd = 1; + jnFlags |= JNODE_JSON5; + }else{ + pParse->iErr = j; + return -1; + } + } + parse_number_finish: + jsonParseAddNode(pParse, seenDP | (jnFlags<<8), j - i, &z[i]); return j; - }else if( c=='}' ){ + } + case '}': { + pParse->iErr = i; return -2; /* End of {...} */ - }else if( c==']' ){ + } + case ']': { + pParse->iErr = i; return -3; /* End of [...] */ - }else if( c==0 ){ + } + 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 */ - }else{ + } + case 0x09: + case 0x0a: + case 0x0d: + case 0x20: { + do{ + i++; + }while( fast_isspace(z[i]) ); + 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]) ){ + jsonParseAddNode(pParse, JSON_NULL, 0, 0); + return i+4; + } + /* fall-through into the default case that checks for NaN */ + } + 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 associated with -** pParse. +** are any errors. If an error occurs, free all memory held by pParse, +** but not pParse itself. ** -** pParse is uninitialized when this routine is called. +** pParse must be initialized to an empty parse object prior to calling +** this routine. */ 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 */ + sqlite3_context *pCtx /* Report errors here */ ){ int i; - memset(pParse, 0, sizeof(*pParse)); - if( zJson==0 ) return 1; - pParse->zJson = zJson; + const char *zJson = pParse->zJson; i = jsonParseValue(pParse, 0); if( pParse->oom ) i = -1; if( i>0 ){ assert( pParse->iDepth==0 ); while( fast_isspace(zJson[i]) ) i++; - if( zJson[i] ) i = -1; + if( zJson[i] ){ + i += json5Whitespace(&zJson[i]); + if( zJson[i] ){ + jsonParseReset(pParse); + return 1; + } + pParse->hasNonstd = 1; + } } if( i<=0 ){ if( pCtx!=0 ){ @@ -201215,6 +206048,7 @@ static int jsonParse( return 0; } + /* Mark node i of pParse as being a child of iParent. Call recursively ** to fill in all the descendants of node i. */ @@ -201264,26 +206098,49 @@ static int jsonParseFindParents(JsonParse *pParse){ #define JSON_CACHE_SZ 4 /* Max number of cache entries */ /* -** 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 +** Obtain a complete parse of the JSON found in the pJson argument +** +** Use the sqlite3_get_auxdata() cache to find a preexisting 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. +** Also register the new parse so that it will be available for ** future sqlite3_get_auxdata() calls. +** +** If an error occurs and pErrCtx!=0 then report the error on pErrCtx +** and return NULL. +** +** The returned pointer (if it is not NULL) is owned by the cache in +** most cases, not the caller. The caller does NOT need to invoke +** jsonParseFree(), in most cases. +** +** Except, if an error occurs and pErrCtx==0 then return the JsonParse +** object with JsonParse.nErr non-zero and the caller will own the JsonParse +** object. In that case, it will be the responsibility of the caller to +** invoke jsonParseFree(). To summarize: +** +** pErrCtx!=0 || p->nErr==0 ==> Return value p is owned by the +** cache. Call does not need to +** free it. +** +** pErrCtx==0 && p->nErr!=0 ==> Return value is owned by the caller +** and so the caller must free it. */ static JsonParse *jsonParseCached( - sqlite3_context *pCtx, - sqlite3_value **argv, - sqlite3_context *pErrCtx + sqlite3_context *pCtx, /* Context to use for cache search */ + sqlite3_value *pJson, /* Function param containing JSON text */ + sqlite3_context *pErrCtx, /* Write parse errors here if not NULL */ + int bUnedited /* No prior edits allowed */ ){ - const char *zJson = (const char*)sqlite3_value_text(argv[0]); - int nJson = sqlite3_value_bytes(argv[0]); + char *zJson = (char*)sqlite3_value_text(pJson); + int nJson = sqlite3_value_bytes(pJson); JsonParse *p; JsonParse *pMatch = 0; int iKey; int iMinKey = 0; u32 iMinHold = 0xffffffff; u32 iMaxHold = 0; + int bJsonRCStr; + if( zJson==0 ) return 0; for(iKey=0; iKeynJson==nJson - && memcmp(p->zJson,zJson,nJson)==0 + && (p->hasMod==0 || bUnedited==0) + && (p->zJson==zJson || memcmp(p->zJson,zJson,nJson)==0) + ){ + p->nErr = 0; + p->useMod = 0; + pMatch = p; + }else + if( pMatch==0 + && p->zAlt!=0 + && bUnedited==0 + && p->nAlt==nJson + && memcmp(p->zAlt, zJson, nJson)==0 ){ p->nErr = 0; + p->useMod = 1; pMatch = p; }else if( p->iHoldiHold; @@ -201306,24 +206175,44 @@ static JsonParse *jsonParseCached( } } if( pMatch ){ + /* The input JSON text was found in the cache. Use the preexisting + ** parse of this JSON */ pMatch->nErr = 0; pMatch->iHold = iMaxHold+1; + assert( pMatch->nJPRef>0 ); /* pMatch is owned by the cache */ return pMatch; } - p = sqlite3_malloc64( sizeof(*p) + nJson + 1 ); + + /* The input JSON was not found anywhere in the cache. We will need + ** to parse it ourselves and generate a new JsonParse object. + */ + bJsonRCStr = sqlite3ValueIsOfClass(pJson,sqlite3RCStrUnref); + p = sqlite3_malloc64( sizeof(*p) + (bJsonRCStr ? 0 : 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, pErrCtx, p->zJson) ){ - sqlite3_free(p); + if( bJsonRCStr ){ + p->zJson = sqlite3RCStrRef(zJson); + p->bJsonIsRCStr = 1; + }else{ + p->zJson = (char*)&p[1]; + memcpy(p->zJson, zJson, nJson+1); + } + p->nJPRef = 1; + if( jsonParse(p, pErrCtx) ){ + if( pErrCtx==0 ){ + p->nErr = 1; + assert( p->nJPRef==1 ); /* Caller will own the new JsonParse object p */ + return p; + } + jsonParseFree(p); return 0; } p->nJson = nJson; p->iHold = iMaxHold+1; + /* Transfer ownership of the new JsonParse to the cache */ sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p, (void(*)(void*))jsonParseFree); return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey); @@ -201333,7 +206222,7 @@ static JsonParse *jsonParseCached( ** Compare the OBJECT label at pNode against zKey,nKey. Return true on ** a match. */ -static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ +static int jsonLabelCompare(const JsonNode *pNode, const char *zKey, u32 nKey){ assert( pNode->eU==1 ); if( pNode->jnFlags & JNODE_RAW ){ if( pNode->n!=nKey ) return 0; @@ -201343,6 +206232,15 @@ static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; } } +static int jsonSameLabel(const JsonNode *p1, const JsonNode *p2){ + if( p1->jnFlags & JNODE_RAW ){ + return jsonLabelCompare(p2, p1->u.zJContent, p1->n); + }else if( p2->jnFlags & JNODE_RAW ){ + return jsonLabelCompare(p1, p2->u.zJContent, p2->n); + }else{ + return p1->n==p2->n && strncmp(p1->u.zJContent,p2->u.zJContent,p1->n)==0; + } +} /* forward declaration */ static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**); @@ -201365,9 +206263,31 @@ static JsonNode *jsonLookupStep( ){ u32 i, j, nKey; const char *zKey; - JsonNode *pRoot = &pParse->aNode[iRoot]; + JsonNode *pRoot; + if( pParse->oom ) return 0; + pRoot = &pParse->aNode[iRoot]; + if( pRoot->jnFlags & (JNODE_REPLACE|JNODE_REMOVE) && pParse->useMod ){ + while( (pRoot->jnFlags & JNODE_REPLACE)!=0 ){ + u32 idx = (u32)(pRoot - pParse->aNode); + i = pParse->iSubst; + while( 1 /*exit-by-break*/ ){ + assert( inNode ); + assert( pParse->aNode[i].eType==JSON_SUBST ); + assert( pParse->aNode[i].eU==4 ); + assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ + pRoot = &pParse->aNode[i+1]; + iRoot = i+1; + break; + } + i = pParse->aNode[i].u.iPrev; + } + } + if( pRoot->jnFlags & JNODE_REMOVE ){ + return 0; + } + } if( zPath[0]==0 ) return pRoot; - if( pRoot->jnFlags & JNODE_REPLACE ) return 0; if( zPath[0]=='.' ){ if( pRoot->eType!=JSON_OBJECT ) return 0; zPath++; @@ -201401,14 +206321,16 @@ static JsonNode *jsonLookupStep( j += jsonNodeSize(&pRoot[j]); } if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pRoot->eU==2 ); - iRoot += pRoot->u.iAppend; + iRoot = pRoot->u.iAppend; pRoot = &pParse->aNode[iRoot]; j = 1; } if( pApnd ){ u32 iStart, iLabel; JsonNode *pNode; + assert( pParse->useMod ); iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); zPath += i; @@ -201417,7 +206339,7 @@ static JsonNode *jsonLookupStep( if( pNode ){ pRoot = &pParse->aNode[iRoot]; assert( pRoot->eU==0 ); - pRoot->u.iAppend = iStart - iRoot; + pRoot->u.iAppend = iStart; pRoot->jnFlags |= JNODE_APPEND; VVA( pRoot->eU = 2 ); pParse->aNode[iLabel].jnFlags |= JNODE_RAW; @@ -201438,12 +206360,13 @@ static JsonNode *jsonLookupStep( if( pRoot->eType!=JSON_ARRAY ) return 0; for(;;){ while( j<=pBase->n ){ - if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++; + if( (pBase[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ) i++; j += jsonNodeSize(&pBase[j]); } if( (pBase->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pBase->eU==2 ); - iBase += pBase->u.iAppend; + iBase = pBase->u.iAppend; pBase = &pParse->aNode[iBase]; j = 1; } @@ -201471,13 +206394,17 @@ static JsonNode *jsonLookupStep( 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--; + while( j<=pRoot->n + && (i>0 || ((pRoot[j].jnFlags & JNODE_REMOVE)!=0 && pParse->useMod)) + ){ + if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 || pParse->useMod==0 ) i--; j += jsonNodeSize(&pRoot[j]); } + if( i==0 && j<=pRoot->n ) break; if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + if( pParse->useMod==0 ) break; assert( pRoot->eU==2 ); - iRoot += pRoot->u.iAppend; + iRoot = pRoot->u.iAppend; pRoot = &pParse->aNode[iRoot]; j = 1; } @@ -201487,13 +206414,14 @@ static JsonNode *jsonLookupStep( if( i==0 && pApnd ){ u32 iStart; JsonNode *pNode; + assert( pParse->useMod ); iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); if( pParse->oom ) return 0; if( pNode ){ pRoot = &pParse->aNode[iRoot]; assert( pRoot->eU==0 ); - pRoot->u.iAppend = iStart - iRoot; + pRoot->u.iAppend = iStart; pRoot->jnFlags |= JNODE_APPEND; VVA( pRoot->eU = 2 ); } @@ -201620,47 +206548,90 @@ static void jsonRemoveAllNulls(JsonNode *pNode){ ** SQL functions used for testing and debugging ****************************************************************************/ +#if SQLITE_DEBUG +/* +** Print N node entries. +*/ +static void jsonDebugPrintNodeEntries( + JsonNode *aNode, /* First node entry to print */ + int N /* Number of node entries to print */ +){ + int i; + for(i=0; iaNode, p->nNode); +} +static void jsonDebugPrintNode(JsonNode *pNode){ + jsonDebugPrintNodeEntries(pNode, jsonNodeSize(pNode)); +} +#else + /* The usual case */ +# define jsonDebugPrintNode(X) +# define jsonDebugPrintParse(X) +#endif + #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. +** SQL function: json_parse(JSON) +** +** Parse JSON using jsonParseCached(). Then print a dump of that +** parse on standard output. Return the mimified JSON result, just +** like the json() function. */ static void jsonParseFunc( sqlite3_context *ctx, int argc, sqlite3_value **argv ){ - JsonString s; /* Output string - not real JSON */ - JsonParse x; /* The parse */ - u32 i; + JsonParse *p; /* The parse */ assert( argc==1 ); - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - jsonParseFindParents(&x); - jsonInit(&s, ctx); - for(i=0; inNode); + printf("nAlloc = %u\n", p->nAlloc); + printf("nJson = %d\n", p->nJson); + printf("nAlt = %d\n", p->nAlt); + printf("nErr = %u\n", p->nErr); + printf("oom = %u\n", p->oom); + printf("hasNonstd = %u\n", p->hasNonstd); + printf("useMod = %u\n", p->useMod); + printf("hasMod = %u\n", p->hasMod); + printf("nJPRef = %u\n", p->nJPRef); + printf("iSubst = %u\n", p->iSubst); + printf("iHold = %u\n", p->iHold); + jsonDebugPrintNodeEntries(p->aNode, p->nNode); + jsonReturnJson(p, p->aNode, ctx, 1); } /* @@ -201744,7 +206715,7 @@ static void jsonArrayLengthFunc( u32 i; JsonNode *pNode; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv[0], ctx, 0); if( p==0 ) return; assert( p->nNode ); if( argc==2 ){ @@ -201757,9 +206728,16 @@ static void jsonArrayLengthFunc( return; } if( pNode->eType==JSON_ARRAY ){ - assert( (pNode->jnFlags & JNODE_APPEND)==0 ); - for(i=1; i<=pNode->n; n++){ - i += jsonNodeSize(&pNode[i]); + while( 1 /*exit-by-break*/ ){ + i = 1; + while( i<=pNode->n ){ + if( (pNode[i].jnFlags & JNODE_REMOVE)==0 ) n++; + i += jsonNodeSize(&pNode[i]); + } + if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + if( p->useMod==0 ) break; + assert( pNode->eU==2 ); + pNode = &p->aNode[pNode->u.iAppend]; } } sqlite3_result_int64(ctx, n); @@ -201806,14 +206784,14 @@ static void jsonExtractFunc( JsonString jx; if( argc<2 ) return; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv[0], ctx, 0); if( p==0 ) return; if( argc==2 ){ /* With a single PATH argument */ zPath = (const char*)sqlite3_value_text(argv[1]); if( zPath==0 ) return; if( flags & JSON_ABPATH ){ - if( zPath[0]!='$' ){ + if( zPath[0]!='$' || (zPath[1]!='.' && zPath[1]!='[' && zPath[1]!=0) ){ /* The -> and ->> operators accept abbreviated PATH arguments. This ** is mostly for compatibility with PostgreSQL, but also for ** convenience. @@ -201824,11 +206802,11 @@ static void jsonExtractFunc( */ jsonInit(&jx, ctx); if( sqlite3Isdigit(zPath[0]) ){ - jsonAppendRaw(&jx, "$[", 2); + jsonAppendRawNZ(&jx, "$[", 2); jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); - jsonAppendRaw(&jx, "]", 2); + jsonAppendRawNZ(&jx, "]", 2); }else{ - jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='[')); + jsonAppendRawNZ(&jx, "$.", 1 + (zPath[0]!='[')); jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); jsonAppendChar(&jx, 0); } @@ -201839,15 +206817,15 @@ static void jsonExtractFunc( } if( pNode ){ if( flags & JSON_JSON ){ - jsonReturnJson(pNode, ctx, 0); + jsonReturnJson(p, pNode, ctx, 0); }else{ - jsonReturn(pNode, ctx, 0); + jsonReturn(p, pNode, ctx); sqlite3_result_subtype(ctx, 0); } } }else{ pNode = jsonLookup(p, zPath, 0, ctx); - if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0); + if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx); } }else{ /* Two or more PATH arguments results in a JSON array with each @@ -201861,9 +206839,9 @@ static void jsonExtractFunc( if( p->nErr ) break; jsonAppendSeparator(&jx); if( pNode ){ - jsonRenderNode(pNode, &jx, 0); + jsonRenderNode(p, pNode, &jx); }else{ - jsonAppendRaw(&jx, "null", 4); + jsonAppendRawNZ(&jx, "null", 4); } } if( i==argc ){ @@ -201904,51 +206882,42 @@ static JsonNode *jsonMergePatch( assert( pPatch[i].eU==1 ); 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( jsonSameLabel(&pPatch[i], &pTarget[j]) ){ + if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ) 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] ){ - assert( pTarget[j+1].eU==0 - || pTarget[j+1].eU==1 - || pTarget[j+1].eU==2 ); - testcase( pTarget[j+1].eU==1 ); - testcase( pTarget[j+1].eU==2 ); - VVA( pTarget[j+1].eU = 5 ); - pTarget[j+1].u.pPatch = pNew; - pTarget[j+1].jnFlags |= JNODE_PATCH; + if( pNew!=&pParse->aNode[iTarget+j+1] ){ + jsonParseAddSubstNode(pParse, iTarget+j+1); + jsonParseAddNodeArray(pParse, pNew, jsonNodeSize(pNew)); } + pTarget = &pParse->aNode[iTarget]; } break; } } if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ - int iStart, iPatch; - iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); + int iStart; + JsonNode *pApnd; + u32 nApnd; + iStart = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); - iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + pApnd = &pPatch[i+1]; + if( pApnd->eType==JSON_OBJECT ) jsonRemoveAllNulls(pApnd); + nApnd = jsonNodeSize(pApnd); + jsonParseAddNodeArray(pParse, pApnd, jsonNodeSize(pApnd)); if( pParse->oom ) return 0; - jsonRemoveAllNulls(pPatch); - pTarget = &pParse->aNode[iTarget]; - assert( pParse->aNode[iRoot].eU==0 || pParse->aNode[iRoot].eU==2 ); - testcase( pParse->aNode[iRoot].eU==2 ); + pParse->aNode[iStart].n = 1+nApnd; pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; + pParse->aNode[iRoot].u.iAppend = iStart; VVA( pParse->aNode[iRoot].eU = 2 ); - pParse->aNode[iRoot].u.iAppend = iStart - iRoot; iRoot = iStart; - assert( pParse->aNode[iPatch].eU==0 ); - VVA( pParse->aNode[iPatch].eU = 5 ); - pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; - pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; + pTarget = &pParse->aNode[iTarget]; } } return pTarget; @@ -201964,25 +206933,28 @@ static void jsonPatchFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The JSON that is being patched */ - JsonParse y; /* The patch */ + JsonParse *pX; /* The JSON that is being patched */ + JsonParse *pY; /* The patch */ JsonNode *pResult; /* The result of the merge */ UNUSED_PARAMETER(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); + pX = jsonParseCached(ctx, argv[0], ctx, 1); + if( pX==0 ) return; + assert( pX->hasMod==0 ); + pX->hasMod = 1; + pY = jsonParseCached(ctx, argv[1], ctx, 1); + if( pY==0 ) return; + pX->useMod = 1; + pY->useMod = 1; + pResult = jsonMergePatch(pX, 0, pY->aNode); + assert( pResult!=0 || pX->oom ); + if( pResult && pX->oom==0 ){ + jsonDebugPrintParse(pX); + jsonDebugPrintNode(pResult); + jsonReturnJson(pX, pResult, ctx, 0); }else{ sqlite3_result_error_nomem(ctx); } - jsonParseReset(&x); - jsonParseReset(&y); } @@ -202038,26 +207010,120 @@ static void jsonRemoveFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The parse */ + JsonParse *pParse; /* The parse */ JsonNode *pNode; const char *zPath; u32 i; if( argc<1 ) return; - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - assert( x.nNode ); + pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); + if( pParse==0 ) return; for(i=1; i<(u32)argc; i++){ zPath = (const char*)sqlite3_value_text(argv[i]); if( zPath==0 ) goto remove_done; - pNode = jsonLookup(&x, zPath, 0, ctx); - if( x.nErr ) goto remove_done; - if( pNode ) pNode->jnFlags |= JNODE_REMOVE; + pNode = jsonLookup(pParse, zPath, 0, ctx); + if( pParse->nErr ) goto remove_done; + if( pNode ){ + pNode->jnFlags |= JNODE_REMOVE; + pParse->hasMod = 1; + pParse->useMod = 1; + } } - if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ - jsonReturnJson(x.aNode, ctx, 0); + if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){ + jsonReturnJson(pParse, pParse->aNode, ctx, 1); } remove_done: - jsonParseReset(&x); + jsonDebugPrintParse(p); +} + +/* +** Substitute the value at iNode with the pValue parameter. +*/ +static void jsonReplaceNode( + sqlite3_context *pCtx, + JsonParse *p, + int iNode, + sqlite3_value *pValue +){ + int idx = jsonParseAddSubstNode(p, iNode); + if( idx<=0 ){ + assert( p->oom ); + return; + } + switch( sqlite3_value_type(pValue) ){ + case SQLITE_NULL: { + jsonParseAddNode(p, JSON_NULL, 0, 0); + break; + } + case SQLITE_FLOAT: { + char *z = sqlite3_mprintf("%!0.15g", sqlite3_value_double(pValue)); + int n; + if( z==0 ){ + p->oom = 1; + break; + } + n = sqlite3Strlen30(z); + jsonParseAddNode(p, JSON_REAL, n, z); + jsonParseAddCleanup(p, sqlite3_free, z); + break; + } + case SQLITE_INTEGER: { + char *z = sqlite3_mprintf("%lld", sqlite3_value_int64(pValue)); + int n; + if( z==0 ){ + p->oom = 1; + break; + } + n = sqlite3Strlen30(z); + jsonParseAddNode(p, JSON_INT, n, z); + jsonParseAddCleanup(p, sqlite3_free, z); + + break; + } + case SQLITE_TEXT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + if( z==0 ){ + p->oom = 1; + break; + } + if( sqlite3_value_subtype(pValue)!=JSON_SUBTYPE ){ + char *zCopy = sqlite3_malloc64( n+1 ); + int k; + if( zCopy ){ + memcpy(zCopy, z, n); + zCopy[n] = 0; + jsonParseAddCleanup(p, sqlite3_free, zCopy); + }else{ + p->oom = 1; + sqlite3_result_error_nomem(pCtx); + } + k = jsonParseAddNode(p, JSON_STRING, n, zCopy); + assert( k>0 || p->oom ); + if( p->oom==0 ) p->aNode[k].jnFlags |= JNODE_RAW; + }else{ + JsonParse *pPatch = jsonParseCached(pCtx, pValue, pCtx, 1); + if( pPatch==0 ){ + p->oom = 1; + break; + } + jsonParseAddNodeArray(p, pPatch->aNode, pPatch->nNode); + /* The nodes copied out of pPatch and into p likely contain + ** u.zJContent pointers into pPatch->zJson. So preserve the + ** content of pPatch until p is destroyed. */ + assert( pPatch->nJPRef>=1 ); + pPatch->nJPRef++; + jsonParseAddCleanup(p, (void(*)(void*))jsonParseFree, pPatch); + } + break; + } + default: { + jsonParseAddNode(p, JSON_NULL, 0, 0); + sqlite3_result_error(pCtx, "JSON cannot hold BLOB values", -1); + p->nErr++; + break; + } + } } /* @@ -202071,7 +207137,7 @@ static void jsonReplaceFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The parse */ + JsonParse *pParse; /* The parse */ JsonNode *pNode; const char *zPath; u32 i; @@ -202081,28 +207147,22 @@ static void jsonReplaceFunc( jsonWrongNumArgs(ctx, "replace"); return; } - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - assert( x.nNode ); + pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); + if( pParse==0 ) return; + pParse->nJPRef++; 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; + pParse->useMod = 1; + pNode = jsonLookup(pParse, zPath, 0, ctx); + if( pParse->nErr ) goto replace_err; if( pNode ){ - assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 ); - testcase( pNode->eU!=0 && pNode->eU!=1 ); - pNode->jnFlags |= (u8)JNODE_REPLACE; - VVA( pNode->eU = 4 ); - pNode->u.iReplace = i + 1; + jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } - if( x.aNode[0].jnFlags & JNODE_REPLACE ){ - assert( x.aNode[0].eU==4 ); - sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); - }else{ - jsonReturnJson(x.aNode, ctx, argv); - } + jsonReturnJson(pParse, pParse->aNode, ctx, 1); replace_err: - jsonParseReset(&x); + jsonDebugPrintParse(pParse); + jsonParseFree(pParse); } @@ -202123,7 +207183,7 @@ static void jsonSetFunc( int argc, sqlite3_value **argv ){ - JsonParse x; /* The parse */ + JsonParse *pParse; /* The parse */ JsonNode *pNode; const char *zPath; u32 i; @@ -202135,33 +207195,27 @@ static void jsonSetFunc( jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); return; } - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - assert( x.nNode ); + pParse = jsonParseCached(ctx, argv[0], ctx, argc>1); + if( pParse==0 ) return; + pParse->nJPRef++; 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 ){ + pParse->useMod = 1; + pNode = jsonLookup(pParse, zPath, &bApnd, ctx); + if( pParse->oom ){ sqlite3_result_error_nomem(ctx); goto jsonSetDone; - }else if( x.nErr ){ + }else if( pParse->nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ - testcase( pNode->eU!=0 && pNode->eU!=1 ); - assert( pNode->eU!=3 && pNode->eU!=5 ); - VVA( pNode->eU = 4 ); - pNode->jnFlags |= (u8)JNODE_REPLACE; - pNode->u.iReplace = i + 1; + jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]); } } - if( x.aNode[0].jnFlags & JNODE_REPLACE ){ - assert( x.aNode[0].eU==4 ); - sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); - }else{ - jsonReturnJson(x.aNode, ctx, argv); - } + jsonDebugPrintParse(pParse); + jsonReturnJson(pParse, pParse->aNode, ctx, 1); jsonSetDone: - jsonParseReset(&x); + jsonParseFree(pParse); } /* @@ -202180,7 +207234,7 @@ static void jsonTypeFunc( const char *zPath; JsonNode *pNode; - p = jsonParseCached(ctx, argv, ctx); + p = jsonParseCached(ctx, argv[0], ctx, 0); if( p==0 ) return; if( argc==2 ){ zPath = (const char*)sqlite3_value_text(argv[1]); @@ -202196,8 +207250,8 @@ static void jsonTypeFunc( /* ** json_valid(JSON) ** -** Return 1 if JSON is a well-formed JSON string according to RFC-7159. -** Return 0 otherwise. +** Return 1 if JSON is a well-formed canonical JSON string according +** to RFC-7159. Return 0 otherwise. */ static void jsonValidFunc( sqlite3_context *ctx, @@ -202206,8 +207260,75 @@ static void jsonValidFunc( ){ JsonParse *p; /* The parse */ UNUSED_PARAMETER(argc); - p = jsonParseCached(ctx, argv, 0); - sqlite3_result_int(ctx, p!=0); + if( sqlite3_value_type(argv[0])==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; + } + p = jsonParseCached(ctx, argv[0], 0, 0); + if( p==0 || p->oom ){ + sqlite3_result_error_nomem(ctx); + sqlite3_free(p); + }else{ + sqlite3_result_int(ctx, p->nErr==0 && (p->hasNonstd==0 || p->useMod)); + if( p->nErr ) jsonParseFree(p); + } +} + +/* +** json_error_position(JSON) +** +** If the argument is not an interpretable JSON string, then return the 1-based +** character position at which the parser first recognized that the input +** was in error. The left-most character is 1. If the string is valid +** JSON, then return 0. +** +** Note that json_valid() is only true for strictly conforming canonical JSON. +** But this routine returns zero if the input contains extension. Thus: +** +** (1) If the input X is strictly conforming canonical JSON: +** +** json_valid(X) returns true +** json_error_position(X) returns 0 +** +** (2) If the input X is JSON but it includes extension (such as JSON5) that +** are not part of RFC-8259: +** +** json_valid(X) returns false +** json_error_position(X) return 0 +** +** (3) If the input X cannot be interpreted as JSON even taking extensions +** into account: +** +** json_valid(X) return false +** json_error_position(X) returns 1 or more +*/ +static void jsonErrorFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse *p; /* The parse */ + UNUSED_PARAMETER(argc); + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + p = jsonParseCached(ctx, argv[0], 0, 0); + if( p==0 || p->oom ){ + sqlite3_result_error_nomem(ctx); + sqlite3_free(p); + }else if( p->nErr==0 ){ + sqlite3_result_int(ctx, 0); + }else{ + int n = 1; + u32 i; + const char *z = (const char*)sqlite3_value_text(argv[0]); + for(i=0; iiErr && ALWAYS(z[i]); i++){ + if( (z[i]&0xc0)!=0x80 ) n++; + } + sqlite3_result_int(ctx, n); + jsonParseFree(p); + } } @@ -202249,7 +207370,8 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ assert( pStr->bStatic ); }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic ? SQLITE_TRANSIENT : + sqlite3RCStrUnref); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); @@ -202290,7 +207412,7 @@ static void jsonGroupInverse( pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); #ifdef NEVER /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will - ** always have been called to initalize it */ + ** always have been called to initialize it */ if( NEVER(!pStr) ) return; #endif z = pStr->zBuf; @@ -202357,7 +207479,8 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ assert( pStr->bStatic ); }else if( isFinal ){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, - pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic ? SQLITE_TRANSIENT : + sqlite3RCStrUnref); pStr->bStatic = 1; }else{ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); @@ -202468,7 +207591,6 @@ static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ /* 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; @@ -202551,14 +207673,16 @@ static void jsonAppendObjectPathElement( assert( pNode->eU==1 ); z = pNode->u.zJContent; nn = pNode->n; - assert( nn>=2 ); - assert( z[0]=='"' ); - assert( z[nn-1]=='"' ); - if( nn>2 && sqlite3Isalpha(z[1]) ){ - for(jj=2; jjjnFlags & JNODE_RAW)==0 ){ + assert( nn>=2 ); + assert( z[0]=='"' || z[0]=='\'' ); + assert( z[nn-1]=='"' || z[0]=='\'' ); + if( nn>2 && sqlite3Isalpha(z[1]) ){ + for(jj=2; jji==0 ) break; if( p->eType==JSON_OBJECT ){ - jsonReturn(pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); }else if( p->eType==JSON_ARRAY ){ u32 iKey; if( p->bRecursive ){ @@ -202620,7 +207744,7 @@ static int jsonEachColumn( } case JEACH_VALUE: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; - jsonReturn(pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); break; } case JEACH_TYPE: { @@ -202631,7 +207755,7 @@ static int jsonEachColumn( case JEACH_ATOM: { if( pThis->jnFlags & JNODE_LABEL ) pThis++; if( pThis->eType>=JSON_ARRAY ) break; - jsonReturn(pThis, ctx, 0); + jsonReturn(&p->sParse, pThis, ctx); break; } case JEACH_ID: { @@ -202786,11 +207910,19 @@ static int jsonEachFilter( 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) ){ + memset(&p->sParse, 0, sizeof(p->sParse)); + p->sParse.nJPRef = 1; + if( sqlite3ValueIsOfClass(argv[0], sqlite3RCStrUnref) ){ + p->sParse.zJson = sqlite3RCStrRef((char*)z); + }else{ + n = sqlite3_value_bytes(argv[0]); + p->sParse.zJson = sqlite3RCStrNew( n+1 ); + if( p->sParse.zJson==0 ) return SQLITE_NOMEM; + memcpy(p->sParse.zJson, z, (size_t)n+1); + } + p->sParse.bJsonIsRCStr = 1; + p->zJson = p->sParse.zJson; + if( jsonParse(&p->sParse, 0) ){ int rc = SQLITE_NOMEM; if( p->sParse.oom==0 ){ sqlite3_free(cur->pVtab->zErrMsg); @@ -202875,7 +208007,8 @@ static sqlite3_module jsonEachModule = { 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; /* The methods of the json_tree virtual table. */ @@ -202903,7 +208036,8 @@ static sqlite3_module jsonTreeModule = { 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* !defined(SQLITE_OMIT_JSON) */ @@ -202918,6 +208052,7 @@ SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ JFUNCTION(json_array, -1, 0, jsonArrayFunc), JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), + JFUNCTION(json_error_position,1, 0, jsonErrorFunc), JFUNCTION(json_extract, -1, 0, jsonExtractFunc), JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), @@ -203067,6 +208202,11 @@ typedef unsigned int u32; #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 */ @@ -203132,6 +208272,7 @@ struct Rtree { 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 */ u32 nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ u32 nCursor; /* Number of open cursors */ @@ -203144,7 +208285,6 @@ struct Rtree { ** 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; @@ -203441,17 +208581,23 @@ struct RtreeMatchArg { ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined ** at run-time. */ -#ifndef SQLITE_BYTEORDER -#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__arm__) -# 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 +#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 #endif @@ -203472,7 +208618,7 @@ static int readInt16(u8 *p){ return (p[0]<<8) + p[1]; } static void readCoord(u8 *p, RtreeCoord *pCoord){ - assert( (((sqlite3_uint64)p)&3)==0 ); /* p is always 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(p) ); #if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 pCoord->u = _byteswap_ulong(*(u32*)p); #elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 @@ -203526,7 +208672,7 @@ static void writeInt16(u8 *p, int i){ } static int writeCoord(u8 *p, RtreeCoord *pCoord){ u32 i; - assert( (((sqlite3_uint64)p)&3)==0 ); /* p is always 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(p) ); assert( sizeof(RtreeCoord)==4 ); assert( sizeof(u32)==4 ); #if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 @@ -203697,11 +208843,9 @@ static int nodeAcquire( } } if( pRtree->pNodeBlob==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, + rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, pRtree->zNodeName, + "data", iNode, 0, &pRtree->pNodeBlob); - sqlite3_free(zTab); } if( rc ){ nodeBlobReset(pRtree); @@ -204254,7 +209398,7 @@ static void rtreeNonleafConstraint( 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( (((sqlite3_uint64)pCellData)&3)==0 ); /* 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(pCellData) ); switch( p->op ){ case RTREE_TRUE: return; /* Always satisfied */ case RTREE_FALSE: break; /* Never satisfied */ @@ -204307,7 +209451,7 @@ static void rtreeLeafConstraint( || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE || p->op==RTREE_FALSE ); pCellData += 8 + p->iCoord*4; - assert( (((sqlite3_uint64)pCellData)&3)==0 ); /* 4-byte aligned */ + assert( FOUR_BYTE_ALIGNED(pCellData) ); RTREE_DECODE_COORD(eInt, pCellData, xN); switch( p->op ){ case RTREE_TRUE: return; /* Always satisfied */ @@ -204877,7 +210021,20 @@ static int rtreeFilter( p->pInfo->nCoord = pRtree->nDim2; p->pInfo->anQueue = pCsr->anQueue; p->pInfo->mxLevel = pRtree->iDepth + 1; - }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + }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 ){ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); #else @@ -205008,11 +210165,12 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ u8 op; + u8 doOmit = 1; switch( p->op ){ - case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; - case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; + 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; 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; @@ -205021,15 +210179,19 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ zIdxStr[iIdx++] = op; zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0'); pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); - pIdxInfo->aConstraintUsage[ii].omit = 1; + pIdxInfo->aConstraintUsage[ii].omit = doOmit; } } } pIdxInfo->idxNum = 2; pIdxInfo->needToFreeIdxStr = 1; - if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ - return SQLITE_NOMEM; + if( iIdx>0 ){ + pIdxInfo->idxStr = sqlite3_malloc( iIdx+1 ); + if( pIdxInfo->idxStr==0 ){ + return SQLITE_NOMEM; + } + memcpy(pIdxInfo->idxStr, zIdxStr, iIdx+1); } nRow = pRtree->nRowEst >> (iIdx/2); @@ -205108,31 +210270,22 @@ static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ */ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ int ii; - 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; + 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; } } 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, @@ -205179,38 +210332,52 @@ static int ChooseLeaf( for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ int iCell; sqlite3_int64 iBest = 0; - + int bFound = 0; RtreeDValue fMinGrowth = RTREE_ZERO; RtreeDValue fMinArea = RTREE_ZERO; - int nCell = NCELL(pNode); - RtreeCell cell; RtreeNode *pChild = 0; - RtreeCell *aCell = 0; - - /* Select the child node which will be enlarged the least if pCell - ** is inserted into it. Resolve ties by choosing the entry with - ** the smallest area. + /* 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; iCell1 ){ - 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( iLeftnDim; 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 ** subtree iHeight high (leaf nodes have iHeight==0). @@ -205959,12 +210954,7 @@ static int rtreeInsertCell( } } if( nodeInsertCell(pRtree, pNode, pCell) ){ - if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ - rc = SplitNode(pRtree, pNode, pCell, iHeight); - }else{ - pRtree->iReinsertHeight = iHeight; - rc = Reinsert(pRtree, pNode, pCell, iHeight); - } + rc = SplitNode(pRtree, pNode, pCell, iHeight); }else{ rc = AdjustTree(pRtree, pNode, pCell); if( ALWAYS(rc==SQLITE_OK) ){ @@ -206307,7 +211297,6 @@ static int rtreeUpdate( } if( rc==SQLITE_OK ){ int rc2; - pRtree->iReinsertHeight = -1; rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); rc2 = nodeRelease(pRtree, pLeaf); if( rc==SQLITE_OK ){ @@ -206448,8 +211437,11 @@ static int rtreeShadowName(const char *zName){ return 0; } +/* Forward declaration */ +static int rtreeIntegrity(sqlite3_vtab*, const char*, const char*, int, char**); + static sqlite3_module rtreeModule = { - 3, /* iVersion */ + 4, /* iVersion */ rtreeCreate, /* xCreate - create a table */ rtreeConnect, /* xConnect - connect to an existing table */ rtreeBestIndex, /* xBestIndex - Determine search strategy */ @@ -206472,7 +211464,8 @@ static sqlite3_module rtreeModule = { rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - rtreeShadowName /* xShadowName */ + rtreeShadowName, /* xShadowName */ + rtreeIntegrity /* xIntegrity */ }; static int rtreeSqlInit( @@ -206728,22 +211721,27 @@ static int rtreeInit( } 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); + pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); if( !pRtree ){ return SQLITE_NOMEM; } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); + 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 = (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); /* Create/Connect to the underlying relational database schema. If @@ -207240,7 +212238,6 @@ static int rtreeCheckTable( ){ RtreeCheck check; /* Common context for various routines */ sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ - int bEnd = 0; /* True if transaction should be closed */ int nAux = 0; /* Number of extra columns. */ /* Initialize the context object */ @@ -207249,14 +212246,6 @@ static int rtreeCheckTable( check.zDb = zDb; check.zTab = zTab; - /* If there is not already an open transaction, open one now. This is - ** to ensure that the queries run as part of this integrity-check operate - ** on a consistent snapshot. */ - if( sqlite3_get_autocommit(db) ){ - check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0); - bEnd = 1; - } - /* Find the number of auxiliary columns */ if( check.rc==SQLITE_OK ){ pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); @@ -207297,15 +212286,34 @@ static int rtreeCheckTable( sqlite3_finalize(check.aCheckMapping[0]); sqlite3_finalize(check.aCheckMapping[1]); - /* If one was opened, close the transaction */ - if( bEnd ){ - int rc = sqlite3_exec(db, "END", 0, 0, 0); - if( check.rc==SQLITE_OK ) check.rc = rc; - } *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); + } + return rc; +} + /* ** Usage: ** @@ -208627,24 +213635,28 @@ static int geopolyInit( (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); + pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName*2+8); if( !pRtree ){ return SQLITE_NOMEM; } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); + 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 @@ -209058,7 +214070,6 @@ static int geopolyUpdate( } if( rc==SQLITE_OK ){ int rc2; - pRtree->iReinsertHeight = -1; rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); rc2 = nodeRelease(pRtree, pLeaf); if( rc==SQLITE_OK ){ @@ -209155,7 +214166,8 @@ static sqlite3_module geopolyModule = { rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - rtreeShadowName /* xShadowName */ + rtreeShadowName, /* xShadowName */ + rtreeIntegrity /* xIntegrity */ }; static int sqlite3_geopoly_init(sqlite3 *db){ @@ -213996,6 +219008,11 @@ static void rbuCheckpointFrame(sqlite3rbu *p, RbuFrame *pFrame){ 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 @@ -214004,9 +219021,20 @@ static void rbuCheckpointFrame(sqlite3rbu *p, RbuFrame *pFrame){ static int rbuLockDatabase(sqlite3 *db){ int rc = SQLITE_OK; sqlite3_file *fd = 0; - sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd); - if( fd->pMethods ){ + 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); @@ -217153,7 +222181,8 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } @@ -217243,6 +222272,7 @@ static int dbpageConnect( (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 ){ @@ -217326,7 +222356,6 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ){ pIdxInfo->orderByConsumed = 1; } - sqlite3VtabUsesAllSchemas(pIdxInfo); return SQLITE_OK; } @@ -217590,7 +222619,8 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* xShadowName */ + 0 /* xIntegrity */ }; return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); } @@ -217627,6 +222657,8 @@ typedef struct SessionInput SessionInput; # endif #endif +#define SESSIONS_ROWID "_rowid_" + static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; typedef struct SessionHook SessionHook; @@ -217648,6 +222680,7 @@ struct sqlite3_session { 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); @@ -217718,17 +222751,32 @@ struct sqlite3_changeset_iter { ** 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 columns in table zName */ int bStat1; /* True if this is sqlite_stat1 */ + int bRowid; /* True if this table uses rowid for PK */ const char **azCol; /* Column names */ + const char **azDflt; /* Default value expressions */ 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; }; /* @@ -217897,6 +222945,7 @@ struct SessionTable { 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 nRecord; /* Number of bytes in buffer aRecord[] */ u8 *aRecord; /* Buffer containing old.* record */ @@ -217922,7 +222971,7 @@ static int sessionVarintLen(int iVal){ ** Read a varint value from aBuf[] into *piVal. Return the number of ** bytes read. */ -static int sessionVarintGet(u8 *aBuf, int *piVal){ +static int sessionVarintGet(const u8 *aBuf, int *piVal){ return getVarint32(aBuf, *piVal); } @@ -218116,6 +223165,7 @@ static unsigned int sessionHashAppendType(unsigned int h, int eType){ */ static int sessionPreupdateHash( sqlite3_session *pSession, /* Session object that owns pTab */ + i64 iRowid, SessionTable *pTab, /* Session table handle */ int bNew, /* True to hash the new.* PK */ int *piHash, /* OUT: Hash value */ @@ -218124,48 +223174,53 @@ static int sessionPreupdateHash( unsigned int h = 0; /* Hash value to return */ int i; /* Used to iterate through columns */ - 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; + if( pTab->bRowid ){ + assert( pTab->nCol-1==pSession->hook.xCount(pSession->hook.pCtx) ); + h = sessionHashAppendI64(h, iRowid); + }else{ + 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; - 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); + if( bNew ){ + rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); }else{ - double rVal = sqlite3_value_double(pVal); - assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); - memcpy(&iVal, &rVal, 8); + rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); } - 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); + 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{ - z = (const u8 *)sqlite3_value_blob(pVal); + assert( eType==SQLITE_NULL ); + assert( pTab->bStat1==0 || i!=1 ); + *pbNullPK = 1; } - 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; } } } @@ -218179,9 +223234,11 @@ static int sessionPreupdateHash( ** Return the number of bytes of space occupied by the value (including ** the type byte). */ -static int sessionSerialLen(u8 *a){ - int e = *a; +static int sessionSerialLen(const u8 *a){ + int e; int n; + assert( a!=0 ); + e = *a; if( e==0 || e==0xFF ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; @@ -218448,6 +223505,7 @@ static int sessionMergeUpdate( */ 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 */ @@ -218455,6 +223513,11 @@ static int sessionPreupdateEqual( 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] ){ @@ -218477,6 +223540,7 @@ static int sessionPreupdateEqual( 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 */ @@ -218579,13 +223643,14 @@ static int sessionGrowHash( ** ** For example, if the table is declared as: ** -** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); +** CREATE TABLE tbl1(w, x DEFAULT 'abc', y, z, PRIMARY KEY(w, z)); ** -** Then the four output variables are populated as follows: +** Then the five 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 @@ -218599,7 +223664,9 @@ static int sessionTableInfo( int *pnCol, /* OUT: number of columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ - u8 **pabPK /* OUT: Array of booleans - true for PK col */ + const char ***pazDflt, /* OUT: Array of default value expressions */ + u8 **pabPK, /* OUT: Array of booleans - true for PK col */ + int *pbRowid /* OUT: True if only PK is a rowid */ ){ char *zPragma; sqlite3_stmt *pStmt; @@ -218610,10 +223677,18 @@ static int sessionTableInfo( int i; u8 *pAlloc = 0; char **azCol = 0; + char **azDflt = 0; u8 *abPK = 0; + int bRowid = 0; /* Set to true to use rowid as PK */ assert( pazCol && pabPK ); + *pazCol = 0; + *pabPK = 0; + *pnCol = 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); @@ -218627,50 +223702,47 @@ static int sessionTableInfo( }else if( rc==SQLITE_ERROR ){ zPragma = sqlite3_mprintf(""); }else{ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; return rc; } }else{ zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); } if( !zPragma ){ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; return SQLITE_NOMEM; } rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); sqlite3_free(zPragma); if( rc!=SQLITE_OK ){ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; return rc; } nByte = nThis + 1; + bRowid = (pbRowid!=0); while( SQLITE_ROW==sqlite3_step(pStmt) ){ - nByte += sqlite3_column_bytes(pStmt, 1); + nByte += sqlite3_column_bytes(pStmt, 1); /* name */ + nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */ nDbCol++; + if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */ } + if( nDbCol==0 ) bRowid = 0; + nDbCol += bRowid; + nByte += strlen(SESSIONS_ROWID); rc = sqlite3_reset(pStmt); if( rc==SQLITE_OK ){ - nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); + nByte += nDbCol * (sizeof(const char *)*2 + sizeof(u8) + 1 + 1); pAlloc = sessionMalloc64(pSession, nByte); if( pAlloc==0 ){ rc = SQLITE_NOMEM; + }else{ + memset(pAlloc, 0, nByte); } } if( rc==SQLITE_OK ){ azCol = (char **)pAlloc; - pAlloc = (u8 *)&azCol[nDbCol]; + azDflt = (char**)&azCol[nDbCol]; + pAlloc = (u8 *)&azDflt[nDbCol]; abPK = (u8 *)pAlloc; pAlloc = &abPK[nDbCol]; if( pzTab ){ @@ -218680,43 +223752,57 @@ static int sessionTableInfo( } 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; + i++; + } while( SQLITE_ROW==sqlite3_step(pStmt) ){ 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); 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; + *pazCol = (const char**)azCol; + if( pazDflt ) *pazDflt = (const char**)azDflt; *pabPK = abPK; *pnCol = nDbCol; }else{ - *pazCol = 0; - *pabPK = 0; - *pnCol = 0; - if( pzTab ) *pzTab = 0; sessionFree(pSession, azCol); } + if( pbRowid ) *pbRowid = bRowid; sqlite3_finalize(pStmt); return rc; } /* -** 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. +** 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. ** ** 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 @@ -218724,14 +223810,22 @@ static int sessionTableInfo( ** indicate that updates on this table should be ignored. SessionTable.abPK ** is set to NULL in this case. */ -static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ +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; + if( pTab->nCol==0 ){ u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); - pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, - pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK + rc = sessionTableInfo(pSession, db, zDb, + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->azDflt, &abPK, + ((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0) ); - if( pSession->rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ int i; for(i=0; inCol; i++){ if( abPK[i] ){ @@ -218743,14 +223837,321 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ pTab->bStat1 = 1; } - if( pSession->bEnableSize ){ + if( pSession && pSession->bEnableSize ){ pSession->nMaxChangesetSize += ( 1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1 ); } } } - return (pSession->rc || pTab->abPK==0); + + 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; + const char **azCol = 0; + const char **azDflt = 0; + u8 *abPK = 0; + int bRowid = 0; + + assert( pSession->rc==SQLITE_OK ); + + pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, + pTab->zName, &nCol, 0, &azCol, &azDflt, &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->azDflt = azDflt; + pTab->abPK = abPK; + 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; } /* @@ -218801,6 +224202,7 @@ static int sessionUpdateMaxSize( ){ i64 nNew = 2; if( pC->op==SQLITE_INSERT ){ + if( pTab->bRowid ) nNew += 9; if( op!=SQLITE_DELETE ){ int ii; for(ii=0; iinCol; ii++){ @@ -218817,12 +224219,16 @@ static int sessionUpdateMaxSize( }else{ int ii; u8 *pCsr = pC->aRecord; - for(ii=0; iinCol; ii++){ + if( pTab->bRowid ){ + nNew += 9 + 1; + pCsr += 9; + } + for(ii=pTab->bRowid; iinCol; ii++){ int bChanged = 1; int nOld = 0; int eType; sqlite3_value *p = 0; - pSession->hook.xNew(pSession->hook.pCtx, ii, &p); + pSession->hook.xNew(pSession->hook.pCtx, ii-pTab->bRowid, &p); if( p==0 ){ return SQLITE_NOMEM; } @@ -218901,22 +224307,29 @@ static int sessionUpdateMaxSize( */ 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 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) ) return; + if( sessionInitTable(pSession, pTab, pSession->db, pSession->zDb) ) return; /* Check the number of columns in this xPreUpdate call matches the ** number of columns in the table. */ - if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ + nExpect = pSession->hook.xCount(pSession->hook.pCtx); + if( (pTab->nCol-pTab->bRowid)nCol-pTab->bRowid)!=nExpect ){ pSession->rc = SQLITE_SCHEMA; return; } @@ -218949,14 +224362,16 @@ static void sessionPreupdateOneChange( /* 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, pTab, op==SQLITE_INSERT, &iHash, &bNull); + rc = sessionPreupdateHash( + pSession, iRowid, 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, pTab, pC, op) ) break; + if( sessionPreupdateEqual(pSession, iRowid, pTab, pC, op) ) break; } if( pC==0 ){ @@ -218971,7 +224386,7 @@ static void sessionPreupdateOneChange( /* Figure out how large an allocation is required */ nByte = sizeof(SessionChange); - for(i=0; inCol; i++){ + for(i=0; i<(pTab->nCol-pTab->bRowid); i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); @@ -218986,9 +224401,12 @@ static void sessionPreupdateOneChange( 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); + pC = (SessionChange*)sessionMalloc64(pSession, nByte); if( !pC ){ rc = SQLITE_NOMEM; goto error_out; @@ -219002,7 +224420,12 @@ static void sessionPreupdateOneChange( ** required values and encodings have already been cached in memory. ** It is not possible for an OOM to occur in this block. */ nByte = 0; - for(i=0; inCol; i++){ + if( pTab->bRowid ){ + pC->aRecord[0] = SQLITE_INTEGER; + sessionPutI64(&pC->aRecord[1], iRowid); + nByte = 9; + } + for(i=0; i<(pTab->nCol-pTab->bRowid); i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ pSession->hook.xOld(pSession->hook.pCtx, i, &p); @@ -219016,6 +224439,7 @@ static void sessionPreupdateOneChange( if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){ pC->bIndirect = 1; } + pC->nRecordField = pTab->nCol; pC->nRecord = nByte; pC->op = op; pC->pNext = pTab->apChange[iHash]; @@ -219117,9 +224541,10 @@ static void xPreUpdate( pSession->rc = sessionFindTable(pSession, zName, &pTab); if( pTab ){ assert( pSession->rc==SQLITE_OK ); - sessionPreupdateOneChange(op, pSession, pTab); + assert( op==SQLITE_UPDATE || iKey1==iKey2 ); + sessionPreupdateOneChange(op, iKey1, pSession, pTab); if( op==SQLITE_UPDATE ){ - sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); + sessionPreupdateOneChange(SQLITE_INSERT, iKey2, pSession, pTab); } } } @@ -219158,6 +224583,7 @@ static void sessionPreupdateHooks( typedef struct SessionDiffCtx SessionDiffCtx; struct SessionDiffCtx { sqlite3_stmt *pStmt; + int bRowid; int nOldOff; }; @@ -219166,17 +224592,17 @@ struct SessionDiffCtx { */ static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; - *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff); + *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff+p->bRowid); return SQLITE_OK; } static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; - *ppVal = sqlite3_column_value(p->pStmt, iVal); + *ppVal = sqlite3_column_value(p->pStmt, iVal+p->bRowid); return SQLITE_OK; } static int sessionDiffCount(void *pCtx){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; - return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt); + return (p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt)) - p->bRowid; } static int sessionDiffDepth(void *pCtx){ (void)pCtx; @@ -219255,14 +224681,16 @@ static char *sessionExprCompareOther( static char *sessionSelectFindNew( 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 * FROM \"%w\".\"%w\" WHERE NOT EXISTS (" + "SELECT %s FROM \"%w\".\"%w\" WHERE NOT EXISTS (" " SELECT 1 FROM \"%w\".\"%w\" WHERE %s" ")", - zDb1, zTbl, zDb2, zTbl, zExpr + zSel, zDb1, zTbl, zDb2, zTbl, zExpr ); return zRet; } @@ -219276,7 +224704,9 @@ static int sessionDiffFindNew( char *zExpr ){ int rc = SQLITE_OK; - char *zStmt = sessionSelectFindNew(zDb1, zDb2, pTab->zName,zExpr); + char *zStmt = sessionSelectFindNew( + zDb1, zDb2, pTab->bRowid, pTab->zName, zExpr + ); if( zStmt==0 ){ rc = SQLITE_NOMEM; @@ -219287,8 +224717,10 @@ static int sessionDiffFindNew( SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; pDiffCtx->pStmt = pStmt; pDiffCtx->nOldOff = 0; + pDiffCtx->bRowid = pTab->bRowid; while( SQLITE_ROW==sqlite3_step(pStmt) ){ - sessionPreupdateOneChange(op, pSession, pTab); + i64 iRowid = (pTab->bRowid ? sqlite3_column_int64(pStmt, 0) : 0); + sessionPreupdateOneChange(op, iRowid, pSession, pTab); } rc = sqlite3_finalize(pStmt); } @@ -219298,6 +224730,27 @@ static int sessionDiffFindNew( 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, @@ -219312,11 +224765,13 @@ static int sessionDiffFindModified( if( zExpr2==0 ){ rc = SQLITE_NOMEM; }else{ + char *z1 = sessionAllCols(pSession->zDb, pTab); + char *z2 = sessionAllCols(zFrom, pTab); char *zStmt = sqlite3_mprintf( - "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", - pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 + "SELECT %s,%s FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", + z1, z2, pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 ); - if( zStmt==0 ){ + if( zStmt==0 || z1==0 || z2==0 ){ rc = SQLITE_NOMEM; }else{ sqlite3_stmt *pStmt; @@ -219327,12 +224782,15 @@ static int sessionDiffFindModified( pDiffCtx->pStmt = pStmt; pDiffCtx->nOldOff = pTab->nCol; while( SQLITE_ROW==sqlite3_step(pStmt) ){ - sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab); + i64 iRowid = (pTab->bRowid ? sqlite3_column_int64(pStmt, 0) : 0); + sessionPreupdateOneChange(SQLITE_UPDATE, iRowid, pSession, pTab); } rc = sqlite3_finalize(pStmt); } - sqlite3_free(zStmt); } + sqlite3_free(zStmt); + sqlite3_free(z1); + sqlite3_free(z2); } return rc; @@ -219361,7 +224819,7 @@ SQLITE_API int sqlite3session_diff( /* Locate and if necessary initialize the target table object */ rc = sessionFindTable(pSession, zTbl, &pTo); if( pTo==0 ) goto diff_out; - if( sessionInitTable(pSession, pTo) ){ + if( sessionInitTable(pSession, pTo, pSession->db, pSession->zDb) ){ rc = pSession->rc; goto diff_out; } @@ -219371,9 +224829,12 @@ SQLITE_API int sqlite3session_diff( 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, &azCol, &abPK); + rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, 0, &abPK, + pSession->bImplicitPK ? &bRowid : 0 + ); if( rc==SQLITE_OK ){ if( pTo->nCol!=nCol ){ bMismatch = 1; @@ -219486,6 +224947,7 @@ static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){ sessionFree(pSession, p); } } + sqlite3_finalize(pTab->pDfltStmt); sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */ sessionFree(pSession, pTab->apChange); sessionFree(pSession, pTab); @@ -219520,7 +224982,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession){ /* Assert that all allocations have been freed and then free the ** session object itself. */ - assert( pSession->nMalloc==0 ); + // assert( pSession->nMalloc==0 ); sqlite3_free(pSession); } @@ -219591,48 +225053,6 @@ SQLITE_API int sqlite3session_attach( 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, 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); -} - /* ** Append the value passed as the second argument to the buffer passed ** as the first. @@ -219701,27 +225121,6 @@ static void sessionAppendBlob( } } -/* -** 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; - } -} - /* ** 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 @@ -219740,27 +225139,6 @@ static void sessionAppendInteger( sessionAppendStr(p, aBuf, pRc); } -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); - } -} - /* ** 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 @@ -219922,7 +225300,7 @@ static int sessionAppendUpdate( /* If at least one field has been modified, this is not a no-op. */ if( bChanged ) bNoop = 0; - /* Add a field to the old.* record. This is omitted if this modules is + /* Add a field to the old.* record. This is omitted if this module is ** currently generating a patchset. */ if( bPatchset==0 ){ if( bChanged || abPK[i] ){ @@ -220024,6 +225402,7 @@ static int sessionSelectStmt( 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 */ @@ -220032,7 +225411,7 @@ static int sessionSelectStmt( int rc = SQLITE_OK; char *zSql = 0; const char *zSep = ""; - const char *zCols = "*"; + const char *zCols = bRowid ? SESSIONS_ROWID ", *" : "*"; int nSql = -1; int i; @@ -220051,7 +225430,6 @@ static int sessionSelectStmt( zCols = "tbl, ?2, stat"; }else{ for(i=0; ipTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ const char *zName = pTab->zName; - int nCol = 0; /* Number of columns in table */ - u8 *abPK = 0; /* 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 = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK); - if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){ - rc = SQLITE_SCHEMA; + rc = sessionReinitTable(pSession, pTab); + if( rc==SQLITE_OK && pTab->nCol!=nOldCol ){ + rc = sessionUpdateChanges(pSession, pTab); } /* Write a table header */ @@ -220270,8 +225646,8 @@ static int sessionGenerateChangeset( /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ - rc = sessionSelectStmt( - db, 0, pSession->zDb, zName, nCol, azCol, abPK, &pSel + rc = sessionSelectStmt(db, 0, pSession->zDb, + zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel ); } @@ -220280,22 +225656,22 @@ static int sessionGenerateChangeset( SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - rc = sessionSelectBind(pSel, nCol, abPK, p); + rc = sessionSelectBind(pSel, pTab->nCol, pTab->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++){ sessionAppendCol(&buf, pSel, iCol, &rc); } }else{ - assert( abPK!=0 ); /* Because sessionSelectStmt() returned ok */ - rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK); + assert( pTab->abPK!=0 ); + rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, pTab->abPK); } }else if( p->op!=SQLITE_INSERT ){ - rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK); + rc = sessionAppendDelete(&buf, bPatchset, p, pTab->nCol,pTab->abPK); } if( rc==SQLITE_OK ){ rc = sqlite3_reset(pSel); @@ -220320,7 +225696,6 @@ static int sessionGenerateChangeset( if( buf.nBuf==nNoop ){ buf.nBuf = nRewind; } - sqlite3_free((char*)azCol); /* cast works around VC++ bug */ } } @@ -220355,7 +225730,7 @@ SQLITE_API int sqlite3session_changeset( int rc; if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE; - rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset); + rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset); assert( rc || pnChangeset==0 || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize ); @@ -220473,6 +225848,19 @@ SQLITE_API int sqlite3session_object_config(sqlite3_session *pSession, int op, v 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; } @@ -220731,15 +226119,19 @@ static int sessionReadRecord( } } if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ - sqlite3_int64 v = sessionGetI64(aVal); - if( eType==SQLITE_INTEGER ){ - sqlite3VdbeMemSetInt64(apOut[i], v); + if( (pIn->nData-pIn->iNext)<8 ){ + rc = SQLITE_CORRUPT_BKPT; }else{ - double d; - memcpy(&d, &v, 8); - sqlite3VdbeMemSetDouble(apOut[i], d); + 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; } - pIn->iNext += 8; } } } @@ -221462,6 +226854,7 @@ struct SessionApplyCtx { 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. */ @@ -221712,8 +227105,9 @@ static int sessionSelectRow( const char *zTab, /* Table name */ SessionApplyCtx *p /* Session changeset-apply context */ ){ + /* TODO */ return sessionSelectStmt(db, p->bIgnoreNoop, - "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect + "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect ); } @@ -222409,6 +227803,7 @@ static int sessionChangesetApply( 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 @@ -222428,8 +227823,8 @@ static int sessionChangesetApply( int i; sqlite3changeset_pk(pIter, &abPK, 0); - rc = sessionTableInfo(0, - db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK + rc = sessionTableInfo(0, db, "main", zNew, + &sApply.nCol, &zTab, &sApply.azCol, 0, &sApply.abPK, &sApply.bRowid ); if( rc!=SQLITE_OK ) break; for(i=0; iflags & SQLITE_FkNoAction; + + if( flags & SQLITE_CHANGESETAPPLY_FKNOACTION ){ + db->flags |= ((u64)SQLITE_FkNoAction); + db->aDb[0].pSchema->schema_cookie -= 32; + } + if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags ); } + + if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){ + assert( db->flags & SQLITE_FkNoAction ); + db->flags &= ~((u64)SQLITE_FkNoAction); + db->aDb[0].pSchema->schema_cookie -= 32; + } return rc; } @@ -222653,6 +228061,9 @@ struct sqlite3_changegroup { int rc; /* Error code */ int bPatch; /* True to accumulate patchsets */ SessionTable *pList; /* List of tables in current patch */ + + sqlite3 *db; /* Configured by changegroup_schema() */ + char *zDb; /* Configured by changegroup_schema() */ }; /* @@ -222673,6 +228084,7 @@ static int sessionChangeMerge( ){ SessionChange *pNew = 0; int rc = SQLITE_OK; + assert( aRec!=0 ); if( !pExist ){ pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec); @@ -222838,6 +228250,114 @@ static int sessionChangeMerge( 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); + } + 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); + } + 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; +} + /* ** Add all changes in the changeset traversed by the iterator passed as ** the first argument to the changegroup hash tables. @@ -222851,6 +228371,7 @@ static int sessionChangesetToHash( int nRec; int rc = SQLITE_OK; SessionTable *pTab = 0; + SessionBuffer rec = {0, 0, 0}; while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ const char *zNew; @@ -222862,6 +228383,9 @@ static int sessionChangesetToHash( SessionChange *pExist = 0; SessionChange **pp; + /* 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 ){ @@ -222894,18 +228418,38 @@ static int sessionChangesetToHash( pTab->zName = (char*)&pTab->abPK[nCol]; memcpy(pTab->zName, zNew, nNew+1); + if( pGrp->db ){ + pTab->nCol = 0; + rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb); + if( rc ){ + assert( pTab->azCol==0 ); + sqlite3_free(pTab); + break; + } + } + /* 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) ){ + } + + if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){ rc = SQLITE_SCHEMA; break; } } + if( nColnCol ){ + assert( pGrp->db ); + rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, &rec); + if( rc ) break; + aRec = rec.aBuf; + nRec = rec.nBuf; + } + if( sessionGrowHash(0, pIter->bPatchset, pTab) ){ rc = SQLITE_NOMEM; break; @@ -222943,6 +228487,7 @@ static int sessionChangesetToHash( } } + sqlite3_free(rec.aBuf); if( rc==SQLITE_OK ) rc = pIter->rc; return rc; } @@ -223029,6 +228574,31 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp){ 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. @@ -223092,6 +228662,7 @@ SQLITE_API int sqlite3changegroup_output_strm( */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ if( pGrp ){ + sqlite3_free(pGrp->zDb); sessionDeleteTable(0, pGrp->pList); sqlite3_free(pGrp); } @@ -223799,7 +229370,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -224028,8 +229599,8 @@ struct Fts5ExtensionApi { ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (3)) or query +** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; @@ -224077,7 +229648,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -224086,7 +229657,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -224094,7 +229665,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); @@ -224266,6 +229837,10 @@ typedef struct Fts5Config Fts5Config; ** 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: @@ -224300,6 +229875,7 @@ struct Fts5Config { 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) */ char *zContent; /* content table */ char *zContentRowid; /* "content_rowid=" option value */ int bColumnsize; /* "columnsize=" option value (dflt==1) */ @@ -224311,6 +229887,7 @@ struct Fts5Config { int ePattern; /* FTS_PATTERN_XXX constant */ /* 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 */ @@ -224319,6 +229896,8 @@ struct Fts5Config { 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' */ /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */ char **pzErrmsg; @@ -224328,8 +229907,11 @@ struct Fts5Config { #endif }; -/* Current expected value of %_config table 'version' field */ -#define FTS5_CURRENT_VERSION 4 +/* 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 @@ -224495,6 +230077,7 @@ struct Fts5IndexIter { ** above. */ #define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 #define FTS5INDEX_QUERY_NOOUTPUT 0x0020 +#define FTS5INDEX_QUERY_SKIPHASH 0x0040 /* ** Create/destroy an Fts5Index object. @@ -224637,6 +230220,9 @@ 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); + /* ** End of interface to code in fts5_index.c. **************************************************************************/ @@ -224649,7 +230235,7 @@ 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) { \ @@ -224721,6 +230307,11 @@ static int sqlite3Fts5HashWrite( */ 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, @@ -224742,6 +230333,7 @@ static void sqlite3Fts5HashScanEntry(Fts5Hash *, ); + /* ** End of interface to code in fts5_hash.c. **************************************************************************/ @@ -224985,7 +230577,8 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*); #define FTS5_STAR 15 /* This file is automatically generated by Lemon from input grammar -** source file "fts5parse.y". */ +** source file "fts5parse.y". +*/ /* ** 2000-05-29 ** @@ -226575,15 +232168,19 @@ static int fts5CInstIterInit( */ typedef struct HighlightContext HighlightContext; struct HighlightContext { - CInstIter iter; /* Coalesced Instance Iterator */ - int iPos; /* Current token offset in zIn[] */ + /* Constant parameters to fts5HighlightCb() */ 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 */ - int iOff; /* Current offset within zIn[] */ + + /* 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 */ char *zOut; /* Output value */ }; @@ -226616,8 +232213,8 @@ static int fts5HighlightCb( int tflags, /* Mask of FTS5_TOKEN_* flags */ const char *pToken, /* Buffer containing token */ int nToken, /* Size of token in bytes */ - int iStartOff, /* Start offset of token */ - int iEndOff /* End offset of token */ + int iStartOff, /* Start byte offset of token */ + int iEndOff /* End byte offset of token */ ){ HighlightContext *p = (HighlightContext*)pContext; int rc = SQLITE_OK; @@ -226633,30 +232230,47 @@ static int fts5HighlightCb( if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; } - if( iPos==p->iter.iStart ){ + /* 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 ){ 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->iRangeEnd>=0 && p->iter.iStartiRangeStart ){ + if( p->bOpen==0 ){ + assert( p->iRangeEnd>=0 ); 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( p->iRangeEnd>=0 && iPos==p->iRangeEnd ){ + if( 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; @@ -226697,6 +232311,9 @@ static void fts5HighlightFunction( if( rc==SQLITE_OK ){ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } + if( ctx.bOpen ){ + fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); + } fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); if( rc==SQLITE_OK ){ @@ -226975,6 +232592,9 @@ static void fts5SnippetFunction( if( rc==SQLITE_OK ){ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } + if( ctx.bOpen ){ + fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1); + } if( ctx.iRangeEnd>=(nColSize-1) ){ fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); }else{ @@ -227613,6 +233233,8 @@ static void sqlite3Fts5TermsetFree(Fts5Termset *p){ #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) @@ -227943,6 +233565,16 @@ static int fts5ConfigParseSpecial( 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("content_rowid", zCmd, nCmd)==0 ){ if( pConfig->zContentRowid ){ *pzErr = sqlite3_mprintf("multiple content_rowid=... directives"); @@ -228141,6 +233773,7 @@ static int sqlite3Fts5ConfigParse( 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; + } + /* If a tokenizer= option was successfully parsed, the tokenizer has ** already been allocated. Otherwise, allocate an instance of the default ** tokenizer (unicode61) now. */ @@ -228480,6 +234135,18 @@ static int sqlite3Fts5ConfigSetValue( } } + 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; @@ -228494,6 +234161,18 @@ static int sqlite3Fts5ConfigSetValue( 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{ *pbBadkey = 1; } @@ -228516,6 +234195,7 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ 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 ){ @@ -228538,15 +234218,20 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ rc = sqlite3_finalize(p); } - if( rc==SQLITE_OK && iVersion!=FTS5_CURRENT_VERSION ){ + if( rc==SQLITE_OK + && iVersion!=FTS5_CURRENT_VERSION + && iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE + ){ rc = SQLITE_ERROR; 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 + *pConfig->pzErrmsg = sqlite3_mprintf("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( rc==SQLITE_OK ){ @@ -228574,6 +234259,10 @@ static int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ /* #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. */ @@ -228614,11 +234303,17 @@ struct Fts5Expr { ** FTS5_NOT (nChild, apChild valid) ** FTS5_STRING (pNear valid) ** FTS5_TERM (pNear valid) +** +** 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); @@ -228688,6 +234383,31 @@ struct Fts5Parse { 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); @@ -228802,6 +234522,8 @@ static int sqlite3Fts5ExprNew( }while( sParse.rc==SQLITE_OK && t!=FTS5_EOF ); sqlite3Fts5ParserFree(pEngine, fts5ParseFree); + 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( iColnCol && sParse.pExpr && sParse.rc==SQLITE_OK ){ @@ -228964,7 +234686,7 @@ static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ Fts5Parse sParse; memset(&sParse, 0, sizeof(sParse)); - if( *pp1 ){ + if( *pp1 && p2 ){ Fts5Expr *p1 = *pp1; int nPhrase = p1->nPhrase + p2->nPhrase; @@ -228989,7 +234711,7 @@ static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ } sqlite3_free(p2->apExprPhrase); sqlite3_free(p2); - }else{ + }else if( p2 ){ *pp1 = p2; } @@ -230763,6 +236485,7 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ } 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); @@ -230771,6 +236494,9 @@ static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ }else{ p->apChild[p->nChild++] = pSub; } + for( ; iinChild; ii++){ + p->iHeight = MAX(p->iHeight, p->apChild[ii]->iHeight + 1); + } } /* @@ -230801,6 +236527,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd( if( pRet ){ pRet->eType = FTS5_AND; pRet->nChild = nTerm; + pRet->iHeight = 1; fts5ExprAssignXNext(pRet); pParse->nPhrase--; for(ii=0; iiiHeight>SQLITE_FTS5_MAX_EXPR_DEPTH ){ + sqlite3Fts5ParseError(pParse, + "fts5 expression tree is too large (maximum depth %d)", + SQLITE_FTS5_MAX_EXPR_DEPTH + ); + sqlite3_free(pRet); + pRet = 0; + } } } } @@ -230984,7 +236719,7 @@ static Fts5ExprNode *sqlite3Fts5ParseImplicitAnd( return pRet; } -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){ sqlite3_int64 nByte = 0; Fts5ExprTerm *p; @@ -231090,6 +236825,8 @@ static char *fts5ExprPrintTcl( if( zRet==0 ) return 0; } + }else if( pExpr->eType==0 ){ + zRet = sqlite3_mprintf("{}"); }else{ char const *zOp = 0; int i; @@ -231351,14 +237088,14 @@ static void fts5ExprFold( sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics)); } } -#endif /* ifdef SQLITE_TEST */ +#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){ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) struct Fts5ExprFunc { const char *z; void (*x)(sqlite3_context*,int,sqlite3_value**); @@ -232118,7 +237855,6 @@ static int fts5HashEntrySort( pList = fts5HashEntryMerge(pList, ap[i]); } - pHash->nEntry = 0; sqlite3_free(ap); *ppSorted = pList; return SQLITE_OK; @@ -232172,6 +237908,28 @@ static int sqlite3Fts5HashScanInit( 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; @@ -232260,6 +238018,24 @@ static void sqlite3Fts5HashScanEntry( #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: ** @@ -232267,7 +238043,7 @@ static void sqlite3Fts5HashScanEntry( ** ** CREATE TABLE %_data(id INTEGER PRIMARY KEY, block BLOB); ** -** , contains the following 5 types of records. See the comments surrounding +** , contains the following 6 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. ** @@ -232276,12 +238052,12 @@ static void sqlite3Fts5HashScanEntry( ** 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. 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. +** SQLite varints. +** +** If the structure record is a V2 record, the configuration cookie is +** followed by the following 4 bytes: [0xFF 0x00 0x00 0x01]. ** -** Immediately following the configuration cookie, the record begins with -** three varints: +** Next, the record continues with three varints: ** ** + number of levels, ** + total number of segments on all levels, @@ -232296,6 +238072,12 @@ static void sqlite3Fts5HashScanEntry( ** + 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. @@ -232411,6 +238193,38 @@ static void sqlite3Fts5HashScanEntry( ** * 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 */ /* @@ -232444,6 +238258,7 @@ static void sqlite3Fts5HashScanEntry( #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) #ifdef SQLITE_DEBUG static int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; } @@ -232479,6 +238294,12 @@ struct Fts5Data { /* ** 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 */ @@ -232493,6 +238314,8 @@ struct Fts5Index { 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 */ @@ -232506,6 +238329,8 @@ struct Fts5Index { sqlite3_stmt *pIdxSelect; 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) */ @@ -232525,11 +238350,23 @@ struct Fts5DoclistIter { ** The contents of the "structure" record for each index are represented ** 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 */ @@ -232539,6 +238376,7 @@ struct Fts5StructureLevel { 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 */ @@ -232598,9 +238436,6 @@ struct Fts5CResult { ** iLeafOffset: ** 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. @@ -232630,6 +238465,13 @@ struct Fts5CResult { ** ** 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 */ @@ -232638,6 +238480,8 @@ struct Fts5SegIter { Fts5Data *pLeaf; /* Current leaf data */ Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */ i64 iLeafOffset; /* Byte offset within current leaf */ + Fts5Data **apTombstone; /* Array of tombstone pages */ + int nTombstone; /* Next method */ void (*xNext)(Fts5Index*, Fts5SegIter*, int*); @@ -232767,6 +238611,60 @@ 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. ** @@ -232994,10 +238892,17 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){ /* ** Remove all records associated with segment iSegid. */ -static void fts5DataRemoveSegment(Fts5Index *p, int iSegid){ +static void fts5DataRemoveSegment(Fts5Index *p, Fts5StructureSegment *pSeg){ + int iSegid = pSeg->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( @@ -233108,11 +239013,19 @@ static int fts5StructureDecode( int nSegment = 0; sqlite3_int64 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); @@ -233159,9 +239072,18 @@ static int fts5StructureDecode( 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; @@ -233172,6 +239094,9 @@ static int fts5StructureDecode( } } if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT; + if( bStructureV2 ){ + pRet->nOriginCntr = nOriginCntr+1; + } if( rc!=SQLITE_OK ){ fts5StructureRelease(pRet); @@ -233189,6 +239114,7 @@ static int fts5StructureDecode( */ 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; @@ -233383,6 +239309,7 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ 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)); @@ -233391,9 +239318,12 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ iCookie = p->pConfig->iCookie; if( iCookie<0 ) iCookie = 0; - if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, 4+9+9+9) ){ + if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, nHdr) ){ 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); @@ -233407,9 +239337,17 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ assert( pLvl->nMerge<=pLvl->nSeg ); for(iSeg=0; iSegnSeg; iSeg++){ - fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].iSegid); - fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoFirst); - fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoLast); + 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); + } } } @@ -233647,42 +239585,25 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){ pLvl->bEof = 1; }else{ u8 *a = pLvl->pData->p; - 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); + + pLvl->iOff = 0; + fts5DlidxLvlNext(pLvl); + while( 1 ){ + int nZero = 0; + int ii = pLvl->iOff; + u64 delta = 0; + + while( a[ii]==0 ){ + nZero++; + ii++; } - if( bZero==0 ) nZero--; + ii += sqlite3Fts5GetVarint(&a[ii], &delta); + + if( ii>=iOff ) break; + pLvl->iLeafPgno += nZero+1; + pLvl->iRowid += delta; + pLvl->iOff = ii; } - pLvl->iLeafPgno -= nZero; - pLvl->iOff = iOff - nZero; } return pLvl->bEof; @@ -233878,7 +239799,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ i64 iOff = pIter->iLeafOffset; ASSERT_SZLEAF_OK(pIter->pLeaf); - if( iOff>=pIter->pLeaf->szLeaf ){ + while( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; @@ -233949,6 +239870,23 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){ } } +/* +** Allocate a tombstone hash page array (pIter->apTombstone) 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 ){ + Fts5Data **apTomb = 0; + apTomb = (Fts5Data**)sqlite3Fts5MallocZero(&p->rc, sizeof(Fts5Data)*nTomb); + if( apTomb ){ + pIter->apTombstone = apTomb; + pIter->nTombstone = nTomb; + } + } +} + /* ** Initialize the iterator object pIter to iterate through the entries in ** segment pSeg. The iterator is left pointing to the first entry when @@ -233977,10 +239915,12 @@ static void fts5SegIterInit( fts5SegIterSetNext(p, pIter); pIter->pSeg = pSeg; pIter->iLeafPgno = pSeg->pgnoFirst-1; - fts5SegIterNextPage(p, pIter); + do { + fts5SegIterNextPage(p, pIter); + }while( p->rc==SQLITE_OK && pIter->pLeaf && pIter->pLeaf->nn==4 ); } - if( p->rc==SQLITE_OK ){ + if( p->rc==SQLITE_OK && pIter->pLeaf ){ pIter->iLeafOffset = 4; assert( pIter->pLeaf!=0 ); assert_nc( pIter->pLeaf->nn>4 ); @@ -233988,6 +239928,7 @@ static void fts5SegIterInit( pIter->iPgidxOff = pIter->pLeaf->szLeaf+1; fts5SegIterLoadTerm(p, pIter, 0); fts5SegIterLoadNPos(p, pIter); + fts5SegIterAllocTombstone(p, pIter); } } @@ -234174,7 +240115,7 @@ static void fts5SegIterNext_None( iOff = pIter->iLeafOffset; /* Next entry is on the next page */ - if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){ + while( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( p->rc || pIter->pLeaf==0 ) return; pIter->iRowid = 0; @@ -234367,7 +240308,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ Fts5Data *pLast = 0; int pgnoLast = 0; - if( pDlidx ){ + if( pDlidx && p->pConfig->iVersion==FTS5_CURRENT_VERSION ){ int iSegid = pIter->pSeg->iSegid; pgnoLast = fts5DlidxIterPgno(pDlidx); pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast)); @@ -234689,6 +240630,7 @@ static void fts5SegIterSeekInit( } fts5SegIterSetNext(p, pIter); + fts5SegIterAllocTombstone(p, pIter); /* Either: ** @@ -234769,6 +240711,20 @@ static void fts5SegIterHashInit( 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; iiterm); fts5DataRelease(pIter->pLeaf); fts5DataRelease(pIter->pNextLeaf); + fts5IndexFreeArray(pIter->apTombstone, pIter->nTombstone); fts5DlidxIterFree(pIter->pDlidx); sqlite3_free(pIter->aRowidOffset); memset(pIter, 0, sizeof(Fts5SegIter)); @@ -234909,7 +240866,6 @@ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ assert_nc( 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; @@ -234928,7 +240884,8 @@ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ /* ** 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 or contains no rowids. +** 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. */ static void fts5SegIterGotoPage( Fts5Index *p, /* FTS5 backend object */ @@ -234943,21 +240900,23 @@ static void fts5SegIterGotoPage( fts5DataRelease(pIter->pNextLeaf); pIter->pNextLeaf = 0; pIter->iLeafPgno = iLeafPgno-1; - fts5SegIterNextPage(p, pIter); - assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno ); - if( p->rc==SQLITE_OK && ALWAYS(pIter->pLeaf!=0) ){ + while( p->rc==SQLITE_OK ){ int iOff; - u8 *a = pIter->pLeaf->p; - int n = pIter->pLeaf->szLeaf; - + fts5SegIterNextPage(p, pIter); + if( pIter->pLeaf==0 ) break; iOff = fts5LeafFirstRowidOff(pIter->pLeaf); - if( iOff<4 || iOff>=n ){ - p->rc = FTS5_CORRUPT; - }else{ - iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); - pIter->iLeafOffset = iOff; - fts5SegIterLoadNPos(p, pIter); + 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; } } } @@ -235110,6 +241069,84 @@ static void fts5MultiIterSetEof(Fts5Iter *pIter){ 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]; + + if( pSeg->pLeaf && pSeg->nTombstone ){ + /* Figure out which page the rowid might be present on. */ + int iPg = ((u64)pSeg->iRowid) % pSeg->nTombstone; + assert( iPg>=0 ); + + /* If tombstone hash page iPg has not yet been loaded from the + ** database, load it now. */ + if( pSeg->apTombstone[iPg]==0 ){ + pSeg->apTombstone[iPg] = fts5DataRead(pIter->pIndex, + FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg) + ); + if( pSeg->apTombstone[iPg]==0 ) return 0; + } + + return fts5IndexTombstoneQuery( + pSeg->apTombstone[iPg], + pSeg->nTombstone, + pSeg->iRowid + ); + } + + return 0; +} + /* ** Move the iterator to the next entry. ** @@ -235147,7 +241184,9 @@ static void fts5MultiIterNext( fts5AssertMultiIterSetup(p, pIter); assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); - if( pIter->bSkipEmpty==0 || pSeg->nPos ){ + if( (pIter->bSkipEmpty==0 || pSeg->nPos) + && 0==fts5MultiIterIsDeleted(pIter) + ){ pIter->xSetOutputs(pIter, pSeg); return; } @@ -235179,7 +241218,9 @@ static void fts5MultiIterNext2( } fts5AssertMultiIterSetup(p, pIter); - }while( fts5MultiIterIsEmpty(p, pIter) ); + }while( (fts5MultiIterIsEmpty(p, pIter) || fts5MultiIterIsDeleted(pIter)) + && (p->rc==SQLITE_OK) + ); } } @@ -235192,7 +241233,7 @@ static Fts5Iter *fts5MultiIterAlloc( int nSeg ){ Fts5Iter *pNew; - int nSlot; /* Power of two >= nSeg */ + i64 nSlot; /* Power of two >= nSeg */ for(nSlot=2; nSlotnSegment==fts5StructureCountSegments(pStruct) ); nSeg = pStruct->nSegment; - nSeg += (p->pHash ? 1 : 0); + nSeg += (p->pHash && 0==(flags & FTS5INDEX_QUERY_SKIPHASH)); }else{ nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); } @@ -235693,7 +241734,7 @@ static void fts5MultiIterNew( if( p->rc==SQLITE_OK ){ if( iLevel<0 ){ Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; - if( p->pHash ){ + if( p->pHash && 0==(flags & FTS5INDEX_QUERY_SKIPHASH) ){ /* Add a segment iterator for the current contents of the hash table. */ Fts5SegIter *pIter = &pNew->aSeg[iIter++]; fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); @@ -235734,7 +241775,9 @@ static void fts5MultiIterNew( fts5MultiIterSetEof(pNew); fts5AssertMultiIterSetup(p, pNew); - if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ + if( (pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew)) + || fts5MultiIterIsDeleted(pNew) + ){ fts5MultiIterNext(p, pNew, 0, 0); }else if( pNew->base.bEof==0 ){ Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; @@ -235912,7 +241955,9 @@ static void fts5IndexDiscardData(Fts5Index *p){ if( p->pHash ){ sqlite3Fts5HashClear(p->pHash); p->nPendingData = 0; + p->nPendingRow = 0; } + p->nContentlessDelete = 0; } /* @@ -236448,7 +242493,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ 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]); + 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); @@ -236549,6 +242594,12 @@ static void fts5IndexMergeLevel( /* 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); @@ -236608,8 +242659,11 @@ static void fts5IndexMergeLevel( int i; /* Remove the redundant segments from the %_data table */ + assert( pSeg->nEntry==0 ); for(i=0; iaSeg[i].iSegid); + Fts5StructureSegment *pOld = &pLvl->aSeg[i]; + pSeg->nEntry += (pOld->nEntry - pOld->nEntryTombstone); + fts5DataRemoveSegment(p, pOld); } /* Remove the redundant segments from the input level */ @@ -236635,6 +242689,43 @@ static void fts5IndexMergeLevel( 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; + } + } + } + } + return iRet; +} + /* ** Do up to nPg pages of automerge work on the index. ** @@ -236654,14 +242745,15 @@ static int fts5IndexMerge( 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. */ + /* Set iBestLvl to the level to read input segments from. Or to -1 if + ** there is no level suitable to merge 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 = pLvl->nMerge; + nBest = nMin; } break; } @@ -236670,22 +242762,18 @@ static int fts5IndexMerge( iBestLvl = iLvl; } } - - /* If nBest is still 0, then the index must be empty. */ -#ifdef SQLITE_DEBUG - for(iLvl=0; nBest==0 && iLvlnLevel; iLvl++){ - assert( pStruct->aLevel[iLvl].nSeg==0 ); + if( nBestaLevel[iBestLvl].nMerge==0 ){ - break; - } + if( iBestLvl<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; @@ -236726,16 +242814,16 @@ static void fts5IndexCrisismerge( ){ const int nCrisis = p->pConfig->nCrisisMerge; Fts5Structure *pStruct = *ppStruct; - 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++; + 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; } - *ppStruct = pStruct; } static int fts5IndexReturn(Fts5Index *p){ @@ -236769,6 +242857,463 @@ static int fts5PoslistPrefix(const u8 *aBuf, int nMax){ 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; + + /* Set variable bLastInDoclist to true if this entry happens to be + ** the last rowid in the doclist for its term. */ + if( pSeg->bDel==0 ){ + if( iNextOff>=iPgIdx ){ + int pgno = pSeg->iLeafPgno+1; + fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist); + iNextOff = iPgIdx; + }else{ + /* 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, + i64 iRowid +){ + const int f = FTS5INDEX_QUERY_SKIPHASH; + int nTerm = (int)strlen(zTerm); + Fts5Iter *pIter = 0; /* Used to find term instance */ + + 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 ** segment on disk. Also update the corresponding structure record. @@ -236785,143 +243330,198 @@ static void fts5FlushOneHash(Fts5Index *p){ /* Obtain a reference to the index structure and allocate a new segment-id ** for the new level-0 segment. */ pStruct = fts5StructureRead(p); - 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; + 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, &pDoclist, &nDoclist); + nTerm = (int)strlen(zTerm); + 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; + } + } + } - /* 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) ); + if( p->rc==SQLITE_OK && bTermWritten==0 ){ + fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm); + bTermWritten = 1; + assert( p->rc!=SQLITE_OK || writer.bFirstRowidInPage==0 ); + } - /* 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); - if( p->rc!=SQLITE_OK ) break; - - 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; - u64 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); + 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; - }else{ - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta); - } - assert( pBuf->n<=pBuf->nSpace ); + assert( pBuf->n<=pBuf->nSpace ); + iPrev = iRowid; - if( eDetail==FTS5_DETAIL_NONE ){ - if( iOffp[pBuf->n++] = 0; - iOff++; + 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); } - } - 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); + 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; } - if( iPos>=nCopy ) break; } + iOff += nCopy; } - iOff += nCopy; } } - } - /* TODO2: Doclist terminator written here. */ - /* pBuf->p[pBuf->n++] = '\0'; */ - assert( pBuf->n<=pBuf->nSpace ); - if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); - } - sqlite3Fts5HashClear(pHash); - fts5WriteFinish(p, &writer, &pgnoLast); + /* 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); - /* 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++; + 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); + } } - fts5StructurePromote(p, 0, pStruct); } - fts5IndexAutomerge(p, &pStruct, pgnoLast); + fts5IndexAutomerge(p, &pStruct, pgnoLast + p->nContentlessDelete); fts5IndexCrisismerge(p, &pStruct); fts5StructureWrite(p, pStruct); fts5StructureRelease(pStruct); @@ -236932,10 +243532,15 @@ static void fts5FlushOneHash(Fts5Index *p){ */ static void fts5IndexFlush(Fts5Index *p){ /* Unless it is empty, flush the hash table to disk */ - if( p->nPendingData ){ + if( p->nPendingData || p->nContentlessDelete ){ 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; + } } } @@ -236951,17 +243556,22 @@ static Fts5Structure *fts5IndexOptimizeStruct( /* Figure out if this structure requires optimization. A structure does ** not require optimization if either: ** - ** + 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. + ** 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. ** - ** In the first case, return NULL. In the second, increment the ref-count - ** on *pStruct and return a copy of the pointer to it. + ** 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. */ - if( nSeg<2 ) return 0; + if( nSeg==0 ) return 0; for(i=0; inLevel; i++){ int nThis = pStruct->aLevel[i].nSeg; - if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){ + 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; + } fts5StructureRef(pStruct); return pStruct; } @@ -236977,6 +243587,7 @@ static Fts5Structure *fts5IndexOptimizeStruct( pNew->nLevel = MIN(pStruct->nLevel+1, FTS5_MAX_LEVEL); pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; + pNew->nOriginCntr = pStruct->nOriginCntr; pLvl = &pNew->aLevel[pNew->nLevel-1]; pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pLvl->aSeg ){ @@ -237007,6 +243618,7 @@ static int sqlite3Fts5IndexOptimize(Fts5Index *p){ assert( p->rc==SQLITE_OK ); fts5IndexFlush(p); + assert( p->nContentlessDelete==0 ); pStruct = fts5StructureRead(p); fts5StructureInvalidate(p); @@ -237036,7 +243648,10 @@ static int sqlite3Fts5IndexOptimize(Fts5Index *p){ ** INSERT command. */ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ - Fts5Structure *pStruct = fts5StructureRead(p); + Fts5Structure *pStruct = 0; + + fts5IndexFlush(p); + pStruct = fts5StructureRead(p); if( pStruct ){ int nMin = p->pConfig->nUsermerge; fts5StructureInvalidate(p); @@ -237044,7 +243659,7 @@ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct); fts5StructureRelease(pStruct); pStruct = pNew; - nMin = 2; + nMin = 1; nMerge = nMerge*-1; } if( pStruct && pStruct->nLevel ){ @@ -237558,6 +244173,9 @@ static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){ p->iWriteRowid = iRowid; p->bDelete = bDelete; + if( bDelete==0 ){ + p->nPendingRow++; + } return fts5IndexReturn(p); } @@ -237595,6 +244213,9 @@ static int sqlite3Fts5IndexReinit(Fts5Index *p){ 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); @@ -237659,6 +244280,7 @@ static int sqlite3Fts5IndexClose(Fts5Index *p){ sqlite3_finalize(p->pIdxDeleter); sqlite3_finalize(p->pIdxSelect); sqlite3_finalize(p->pDataVersion); + sqlite3_finalize(p->pDeleteFromIdx); sqlite3Fts5HashFree(p->pHash); sqlite3_free(p->zDataTbl); sqlite3_free(p); @@ -237985,6 +244607,347 @@ static int sqlite3Fts5IndexLoadConfig(Fts5Index *p){ 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); +} /************************************************************************* ************************************************************************** @@ -238289,6 +245252,7 @@ static void fts5IndexIntegrityCheckSegment( 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; @@ -238324,7 +245288,19 @@ static void fts5IndexIntegrityCheckSegment( ** is also a rowid pointer within the leaf page header, it points to a ** location before the term. */ if( pLeaf->nn<=pLeaf->szLeaf ){ - p->rc = FTS5_CORRUPT; + + 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; + } + }else{ int iOff; /* Offset of first term on leaf */ int iRowidOff; /* Offset of first rowid on leaf */ @@ -238388,9 +245364,12 @@ static void fts5IndexIntegrityCheckSegment( ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; - }else{ + }else if( bSecureDelete==0 || iRowidOff>0 ){ + i64 iDlRowid = fts5DlidxIterRowid(pDlidx); fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); - if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT; + if( iRowidrc = FTS5_CORRUPT; + } } fts5DataRelease(pLeaf); } @@ -238520,13 +245499,14 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum ** function only. */ -#ifdef SQLITE_TEST +#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 */ @@ -238542,13 +245522,16 @@ static void fts5DecodeRowid( 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 */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){ - int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */ - fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno); + int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */ + fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno); if( iSegid==0 ){ if( iKey==FTS5_AVERAGES_ROWID ){ @@ -238558,14 +245541,16 @@ static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){ } } else{ - sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}", - bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%s%ssegid=%d h=%d pgno=%d}", + bDlidx ? "dlidx " : "", + bTomb ? "tombstone " : "", + iSegid, iHeight, iPgno ); } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) static void fts5DebugStructure( int *pRc, /* IN/OUT: error code */ Fts5Buffer *pBuf, @@ -238580,16 +245565,22 @@ static void fts5DebugStructure( ); 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 */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This is part of the fts5_decode() debugging aid. ** @@ -238614,9 +245605,9 @@ static void fts5DecodeStructure( fts5DebugStructure(pRc, pBuf, p); fts5StructureRelease(p); } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This is part of the fts5_decode() debugging aid. ** @@ -238639,9 +245630,9 @@ static void fts5DecodeAverages( zSpace = " "; } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#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 @@ -238658,9 +245649,9 @@ static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){ } return iOff; } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#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 @@ -238693,9 +245684,9 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){ return iOff; } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** This function is part of the fts5_decode() debugging function. It is ** only ever used with detail=none tables. @@ -238736,9 +245727,9 @@ static void fts5DecodeRowidList( sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp); } } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) /* ** The implementation of user-defined scalar function fts5_decode(). */ @@ -238749,6 +245740,7 @@ static void fts5DecodeFunction( ){ 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 */ @@ -238771,7 +245763,7 @@ static void fts5DecodeFunction( if( a==0 ) goto decode_out; if( n>0 ) memcpy(a, aBlob, n); - fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno); + fts5DecodeRowid(iRowid, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno); fts5DebugRowid(&rc, &s, iRowid); if( bDlidx ){ @@ -238790,6 +245782,28 @@ static void fts5DecodeFunction( " %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); + } iOff = iTermOff; if( iOffestimatedCost = (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 @@ -238994,7 +246239,7 @@ static void fts5RowidFunction( ** SQLite error code is returned instead. */ static int sqlite3Fts5IndexInit(sqlite3 *db){ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG) int rc = sqlite3_create_function( db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0 ); @@ -239011,6 +246256,37 @@ static int sqlite3Fts5IndexInit(sqlite3 *db){ 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; @@ -239146,6 +246422,8 @@ struct Fts5FullTable { Fts5Storage *pStorage; /* Document store */ Fts5Global *pGlobal; /* Global (connection wide) data */ Fts5Cursor *pSortCsr; /* Sort data from this cursor */ + int iSavepoint; /* Successful xSavepoint()+1 */ + int bInSavepoint; #ifdef SQLITE_DEBUG struct Fts5TransactionState ts; #endif @@ -239434,6 +246712,13 @@ static int fts5InitVtab( 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( rc!=SQLITE_OK ){ fts5FreeVtab(pTab); pTab = 0; @@ -240358,6 +247643,9 @@ static int fts5FilterMethod( 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 ** processing for a "... MATCH ORDER BY rank" query (ePlan is @@ -240380,6 +247668,7 @@ static int fts5FilterMethod( pCsr->pExpr = pTab->pSortCsr->pExpr; rc = fts5CursorFirst(pTab, pCsr, bDesc); }else if( pCsr->pExpr ){ + assert( rc==SQLITE_OK ); rc = fts5CursorParseRank(pConfig, pCsr, pRank); if( rc==SQLITE_OK ){ if( bOrderByRank ){ @@ -240551,6 +247840,7 @@ static int fts5SpecialInsert( Fts5Config *pConfig = pTab->p.pConfig; int rc = SQLITE_OK; int bError = 0; + int bLoadConfig = 0; if( 0==sqlite3_stricmp("delete-all", zCmd) ){ if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ @@ -240562,6 +247852,7 @@ static int fts5SpecialInsert( }else{ rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage); } + bLoadConfig = 1; }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){ if( pConfig->eContent==FTS5_CONTENT_NONE ){ fts5SetVtabError(pTab, @@ -240571,6 +247862,7 @@ static int fts5SpecialInsert( }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) ){ @@ -240583,6 +247875,8 @@ static int fts5SpecialInsert( }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 = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); if( rc==SQLITE_OK ){ @@ -240596,6 +247890,12 @@ static int fts5SpecialInsert( } } } + + if( rc==SQLITE_OK && bLoadConfig ){ + pTab->p.pConfig->iCookie--; + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); + } + return rc; } @@ -240652,6 +247952,7 @@ static int fts5UpdateMethod( Fts5Config *pConfig = pTab->p.pConfig; int eType0; /* value_type() of apVal[0] */ int rc = SQLITE_OK; /* Return code */ + int bUpdateOrDelete = 0; /* A transaction must be open when this is called. */ assert( pTab->ts.eState==1 || pTab->ts.eState==2 ); @@ -240662,6 +247963,11 @@ static int fts5UpdateMethod( || sqlite3_value_type(apVal[0])==SQLITE_NULL ); assert( pTab->p.pConfig->pzErrmsg==0 ); + if( pConfig->pgsz==0 ){ + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); + if( rc!=SQLITE_OK ) return rc; + } + pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; /* Put any active cursors into REQUIRE_SEEK state. */ @@ -240676,7 +247982,14 @@ static int fts5UpdateMethod( if( pConfig->eContent!=FTS5_CONTENT_NORMAL && 0==sqlite3_stricmp("delete", z) ){ - rc = fts5SpecialDelete(pTab, apVal); + if( pConfig->bContentlessDelete ){ + fts5SetVtabError(pTab, + "'delete' may not be used with a contentless_delete=1 table" + ); + rc = SQLITE_ERROR; + }else{ + rc = fts5SpecialDelete(pTab, apVal); + } }else{ rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); } @@ -240693,7 +248006,7 @@ static int fts5UpdateMethod( ** Cases 3 and 4 may violate the rowid constraint. */ int eConflict = SQLITE_ABORT; - if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->bContentlessDelete ){ eConflict = sqlite3_vtab_on_conflict(pConfig->db); } @@ -240701,8 +248014,12 @@ static int fts5UpdateMethod( assert( nArg!=1 || eType0==SQLITE_INTEGER ); /* Filter out attempts to run UPDATE or DELETE on contentless tables. - ** This is not suported. */ - if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){ + ** This is not suported. Except - they are both supported if the CREATE + ** VIRTUAL TABLE statement contained "contentless_delete=1". */ + if( eType0==SQLITE_INTEGER + && pConfig->eContent==FTS5_CONTENT_NONE + && pConfig->bContentlessDelete==0 + ){ pTab->p.base.zErrMsg = sqlite3_mprintf( "cannot %s contentless fts5 table: %s", (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName @@ -240714,6 +248031,7 @@ static int fts5UpdateMethod( else if( nArg==1 ){ i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0); + bUpdateOrDelete = 1; } /* INSERT or UPDATE */ @@ -240725,10 +248043,12 @@ static int fts5UpdateMethod( } else if( eType0!=SQLITE_INTEGER ){ - /* If this is a REPLACE, first remove the current entry (if any) */ + /* 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); + bUpdateOrDelete = 1; } fts5StorageInsert(&rc, pTab, apVal, pRowid); } @@ -240757,10 +248077,24 @@ static int fts5UpdateMethod( rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); fts5StorageInsert(&rc, pTab, apVal, pRowid); } + bUpdateOrDelete = 1; } } } + if( rc==SQLITE_OK + && bUpdateOrDelete + && pConfig->bSecureDelete + && pConfig->iVersion==FTS5_CURRENT_VERSION + ){ + rc = sqlite3Fts5StorageConfigValue( + pTab->pStorage, "version", 0, FTS5_CURRENT_VERSION_SECUREDELETE + ); + if( rc==SQLITE_OK ){ + pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE; + } + } + pTab->p.pConfig->pzErrmsg = 0; return rc; } @@ -240773,8 +248107,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; fts5CheckTransactionState(pTab, FTS5_SYNC, 0); pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - fts5TripCursors(pTab); - rc = sqlite3Fts5StorageSync(pTab->pStorage); + rc = sqlite3Fts5FlushToDisk(&pTab->p); pTab->p.pConfig->pzErrmsg = 0; return rc; } @@ -241541,6 +248874,12 @@ static int fts5ColumnMethod( sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); } pConfig->pzErrmsg = 0; + }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){ + char *zErr = sqlite3_mprintf("cannot UPDATE a subset of " + "columns on fts5 contentless-delete table: %s", pConfig->zName + ); + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); } return rc; } @@ -241579,8 +248918,12 @@ static int fts5RenameMethod( sqlite3_vtab *pVtab, /* Virtual table handle */ const char *zName /* New name of table */ ){ + int rc; Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - return sqlite3Fts5StorageRename(pTab->pStorage, zName); + pTab->bInSavepoint = 1; + rc = sqlite3Fts5StorageRename(pTab->pStorage, zName); + pTab->bInSavepoint = 0; + return rc; } static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){ @@ -241594,9 +248937,29 @@ static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){ ** Flush the contents of the pending-terms table to disk. */ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ - fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint); - return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); + Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + int rc = SQLITE_OK; + char *zSql = 0; + fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); + + if( pTab->bInSavepoint==0 ){ + zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')", + pTab->p.pConfig->zDb, pTab->p.pConfig->zName, pTab->p.pConfig->zName + ); + if( zSql ){ + pTab->bInSavepoint = 1; + rc = sqlite3_exec(pTab->p.pConfig->db, zSql, 0, 0, 0); + pTab->bInSavepoint = 0; + sqlite3_free(zSql); + }else{ + rc = SQLITE_NOMEM; + } + if( rc==SQLITE_OK ){ + pTab->iSavepoint = iSavepoint+1; + } + } + + return rc; } /* @@ -241605,9 +248968,16 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ ** This is a no-op. */ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ - fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint); - return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab); + Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + int rc = SQLITE_OK; + fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); + if( (iSavepoint+1)iSavepoint ){ + rc = sqlite3Fts5FlushToDisk(&pTab->p); + if( rc==SQLITE_OK ){ + pTab->iSavepoint = iSavepoint; + } + } + return rc; } /* @@ -241617,10 +248987,14 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; - UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ + int rc = SQLITE_OK; fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); - return sqlite3Fts5StorageRollback(pTab->pStorage); + pTab->p.pConfig->pgsz = 0; + if( (iSavepoint+1)<=pTab->iSavepoint ){ + rc = sqlite3Fts5StorageRollback(pTab->pStorage); + } + return rc; } /* @@ -241822,7 +249196,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2023-03-11 23:21:21 dc9f025dc43cb8008e7d8d644175d8b2d084e602a1513803c40c513d1e99fea4", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301", -1, SQLITE_TRANSIENT); } /* @@ -241840,9 +249214,46 @@ static int fts5ShadowName(const char *zName){ return 0; } +/* +** Run an integrity check on the FTS5 data structures. Return a string +** if anything is found amiss. Return a NULL pointer if everything is +** OK. +*/ +static int fts5Integrity( + sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */ + const char *zSchema, /* Name of schema in which this table lives */ + const char *zTabname, /* Name of the table itself */ + int isQuick, /* True if this is a quick-check */ + char **pzErr /* Write error message here */ +){ + Fts5FullTable *pTab = (Fts5FullTable*)pVtab; + Fts5Config *pConfig = pTab->p.pConfig; + char *zSql; + char *zErr = 0; + int rc; + assert( pzErr!=0 && *pzErr==0 ); + UNUSED_PARAM(isQuick); + zSql = sqlite3_mprintf( + "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", + zSchema, zTabname, pConfig->zName); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr); + sqlite3_free(zSql); + if( (rc&0xff)==SQLITE_CORRUPT ){ + *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s", + zSchema, zTabname); + }else if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("unable to validate the inverted index for" + " FTS5 table %s.%s: %s", + zSchema, zTabname, zErr); + } + sqlite3_free(zErr); + return SQLITE_OK; +} + static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { - /* iVersion */ 3, + /* iVersion */ 4, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, /* xBestIndex */ fts5BestIndexMethod, @@ -241865,7 +249276,8 @@ static int fts5Init(sqlite3 *db){ /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, - /* xShadowName */ fts5ShadowName + /* xShadowName */ fts5ShadowName, + /* xIntegrity */ fts5Integrity }; int rc; @@ -242035,10 +249447,10 @@ static int fts5StorageGetStmt( "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(?,?)", /* REPLACE_DOCSIZE */ + "REPLACE INTO %Q.'%q_docsize' VALUES(?,?%s)", /* REPLACE_DOCSIZE */ "DELETE FROM %Q.'%q_docsize' WHERE id=?", /* DELETE_DOCSIZE */ - "SELECT sz FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ + "SELECT sz%s FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ "REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */ "SELECT %s FROM %s AS T", /* SCAN */ @@ -242086,6 +249498,19 @@ static int fts5StorageGetStmt( 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; + default: zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName); break; @@ -242275,9 +249700,11 @@ static int sqlite3Fts5StorageOpen( } if( rc==SQLITE_OK && pConfig->bColumnsize ){ - rc = sqlite3Fts5CreateTable( - pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr - ); + 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); } if( rc==SQLITE_OK ){ rc = sqlite3Fts5CreateTable( @@ -242354,7 +249781,7 @@ static int fts5StorageDeleteFromIndex( ){ Fts5Config *pConfig = p->pConfig; sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */ - int rc; /* Return code */ + int rc = SQLITE_OK; /* Return code */ int rc2; /* sqlite3_reset() return code */ int iCol; Fts5InsertCtx ctx; @@ -242370,7 +249797,6 @@ static int fts5StorageDeleteFromIndex( 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 ){ const char *zText; @@ -242407,6 +249833,37 @@ static int fts5StorageDeleteFromIndex( return rc; } +/* +** 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 ); + + /* 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; +} /* ** Insert a record into the %_docsize table. Specifically, do: @@ -242427,10 +249884,17 @@ static int fts5StorageInsertDocsize( rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0); if( rc==SQLITE_OK ){ sqlite3_bind_int64(pReplace, 1, iRowid); - sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); - sqlite3_step(pReplace); - rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 2); + 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; @@ -242494,7 +249958,15 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **ap /* Delete the index records */ if( rc==SQLITE_OK ){ - rc = fts5StorageDeleteFromIndex(p, iDel, apVal); + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel); + } + + if( rc==SQLITE_OK ){ + if( p->pConfig->bContentlessDelete ){ + rc = fts5StorageContentlessDelete(p, iDel); + }else{ + rc = fts5StorageDeleteFromIndex(p, iDel, apVal); + } } /* Delete the %_docsize record */ @@ -243082,7 +250554,9 @@ static int sqlite3Fts5StorageSync(Fts5Storage *p){ i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); if( p->bTotalsValid ){ rc = fts5StorageSaveTotals(p); - p->bTotalsValid = 0; + if( rc==SQLITE_OK ){ + p->bTotalsValid = 0; + } } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IndexSync(p->pIndex); @@ -246450,7 +253924,8 @@ static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){ /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, - /* xShadowName */ 0 + /* xShadowName */ 0, + /* xIntegrity */ 0 }; void *p = (void*)pGlobal; @@ -246779,6 +254254,7 @@ static sqlite3_module stmtModule = { 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ + 0 /* xIntegrity */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -246989,6 +254465,9 @@ libsql_wasm_engine_t *libsql_wasm_engine_new() { return NULL; } +void libsql_wasm_engine_free(libsql_wasm_engine_t *eng) { +} + libsql_wasm_module_t *libsql_compile_wasm_module(libsql_wasm_engine_t* engine, const char *pSrcBody, int nBody, void *(*alloc_err_buf)(unsigned long long), char **err_msg_buf) { @@ -247001,7 +254480,6 @@ libsql_wasm_module_t *libsql_compile_wasm_module(libsql_wasm_engine_t* engine, c WasmEdge_ConfigureContext *ConfCxt = WasmEdge_ConfigureCreate(); WasmEdge_ConfigureAddHostRegistration(ConfCxt, WasmEdge_HostRegistration_Wasi); - WasmEdge_ConfigureAddHostRegistration(ConfCxt, WasmEdge_HostRegistration_WasiNN); WasmEdge_VMContext *ctx = WasmEdge_VMCreate(ConfCxt, NULL); WasmEdge_ConfigureDelete(ConfCxt); @@ -247024,6 +254502,7 @@ void libsql_wasm_free_msg_buf(char *err_msg_buf) { } #endif + /************** End of wasmedge_bindings.c ***********************************/ /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } diff --git a/ext/libsql/c/sqlite3.h b/ext/libsql/c/sqlite3.h index a2e8673..2940a5e 100644 --- a/ext/libsql/c/sqlite3.h +++ b/ext/libsql/c/sqlite3.h @@ -149,11 +149,11 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.42.0" -#define SQLITE_VERSION_NUMBER 3042000 -#define SQLITE_SOURCE_ID "2023-03-11 23:21:21 dc9f025dc43cb8008e7d8d644175d8b2d084e602a1513803c40c513d1e99alt1" +#define SQLITE_VERSION "3.44.0" +#define SQLITE_VERSION_NUMBER 3044000 +#define SQLITE_SOURCE_ID "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad8alt1" -#define LIBSQL_VERSION "0.2.1" +#define LIBSQL_VERSION "0.2.3" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -535,6 +535,7 @@ SQLITE_API int sqlite3_exec( #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)) @@ -1204,7 +1205,7 @@ struct sqlite3_io_methods { ** by clients within the current process, only within other processes. ** **
      4. [[SQLITE_FCNTL_CKSM_FILE]] -** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the +** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the ** [checksum VFS shim] only. ** **
      5. [[SQLITE_FCNTL_RESET_CACHE]] @@ -2153,7 +2154,7 @@ struct sqlite3_mem_methods { ** 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 behaviour. +** 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. ** @@ -2169,28 +2170,28 @@ struct sqlite3_mem_methods { ** compile-time option is not set, then the default maximum is 1073741824. ** */ -#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 /* 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_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 */ @@ -2328,7 +2329,7 @@ struct sqlite3_mem_methods { ** 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 +** override this 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 @@ -2425,7 +2426,7 @@ struct sqlite3_mem_methods { **
      ** ** [[SQLITE_DBCONFIG_DQS_DML]] -**
      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 @@ -2434,7 +2435,7 @@ struct sqlite3_mem_methods { **
      ** ** [[SQLITE_DBCONFIG_DQS_DDL]] -**
      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 @@ -2443,7 +2444,7 @@ struct sqlite3_mem_methods { **
      ** ** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] -**
      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 @@ -2463,7 +2464,7 @@ struct sqlite3_mem_methods { **
      ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] -**
      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 @@ -2472,7 +2473,7 @@ struct sqlite3_mem_methods { ** 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 generated database files that are compatible +** 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 @@ -2481,27 +2482,39 @@ struct sqlite3_mem_methods { ** 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 decending indexes. +** either generated columns or descending indexes. **
      ** ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] -**
      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.
      +** 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 change the default order +**
      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 configuration option -** is useful for application testing.
      +** 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. +** ** ** */ @@ -2523,7 +2536,7 @@ struct sqlite3_mem_methods { #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 1080 /* int int* */ +#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */ #define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */ #define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */ @@ -2750,6 +2763,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); ** ** ^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*); @@ -3403,8 +3417,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** -** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides -** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** ^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. ** ** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently @@ -3761,6 +3777,9 @@ SQLITE_API int sqlite3_open_v2( int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); + +typedef struct libsql_wal_manager libsql_wal_manager; + SQLITE_API int libsql_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ @@ -3769,6 +3788,28 @@ SQLITE_API int libsql_open( const char *zWal /* Name of WAL module to use */ ); +/* deprecated, only works with zWal == NULL */ +SQLITE_API int libsql_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs, /* Name of VFS module to use, NULL for default */ + const char *zWal, /* Name of WAL module to use */ + void* pWalMethodsData /* User data, passed to the libsql_wal struct*/ +); + +SQLITE_API int libsql_open_v3( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs, /* Name of VFS module to use, NULL for default */ + libsql_wal_manager wal_manager /* wal_manager instance, in charge of instanciating a wal */ +); + +typedef struct sqlite3_wal sqlite3_wal; +SQLITE_API int sqlite3_wal_backfilled(sqlite3_wal *pWal); +SQLITE_API unsigned int sqlite3_wal_frame_page_no(sqlite3_wal *pWal, unsigned int iFrame); + SQLITE_API LIBSQL_API int libsql_try_initialize_wasm_func_table(sqlite3 *db); /* @@ -3782,7 +3823,7 @@ SQLITE_API LIBSQL_API int libsql_try_initialize_wasm_func_table(sqlite3 *db); ** as F) must be one of: **
        **
      • A database filename pointer created by the SQLite core and -** passed into the xOpen() method of a VFS implemention, or +** 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()]. **
      @@ -3895,7 +3936,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); /* ** CAPI3REF: Create and Destroy VFS Filenames ** -** These interfces are provided for use by [VFS shim] implementations and +** 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 @@ -3975,6 +4016,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. +** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(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 @@ -4442,6 +4484,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); */ 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 @@ -4605,7 +4682,7 @@ typedef struct sqlite3_context sqlite3_context; ** 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 passsed to indicate that +** ^ (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 @@ -5284,20 +5361,33 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S ** back to the beginning of its program. ** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], -** or if [sqlite3_step(S)] has never before been called on S, -** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** ^The return code from [sqlite3_reset(S)] indicates whether or not +** the previous evaluation of prepared statement S completed successfully. +** ^If [sqlite3_step(S)] has never before been called on S or if +** [sqlite3_step(S)] has not been called since the previous call +** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return +** [SQLITE_OK]. ** ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. +** ^The [sqlite3_reset(S)] interface might also return an [error code] +** if there were no prior errors but the process of resetting +** the prepared statement caused a new error. ^For example, if an +** [INSERT] statement with a [RETURNING] clause is only stepped one time, +** that one call to [sqlite3_step(S)] might return SQLITE_ROW but +** the overall statement might still fail and the [sqlite3_reset(S)] call +** might return SQLITE_BUSY if locking constraints prevent the +** database change from committing. Therefore, it is important that +** applications check the return code from [sqlite3_reset(S)] even if +** no prior call to [sqlite3_step(S)] indicated a problem. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} @@ -5508,7 +5598,7 @@ SQLITE_API int sqlite3_create_window_function( ** [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 surreptiously +** into using a database file that has had its schema surreptitiously ** modified to invoke the application-defined function in ways that are ** harmful. **

      @@ -5852,32 +5942,32 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to -** associate metadata with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated metadata may be preserved. An example -** of where this might be useful is in a regular-expression matching -** function. The compiled version of the regular expression can be stored as -** metadata associated with the pattern string. +** associate auxiliary data with argument values. If the same argument +** value is passed to multiple invocations of the same SQL function during +** query execution, under some circumstances the associated auxiliary data +** might be preserved. An example of where this might be useful is in a +** regular-expression matching function. The compiled version of the regular +** expression can be stored as auxiliary data associated with the pattern string. ** Then as long as the pattern string remains the same, ** the compiled regular expression can be reused on multiple ** invocations of the same function. ** -** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata +** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data ** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument ** value to the application-defined function. ^N is zero for the left-most -** function argument. ^If there is no metadata +** function argument. ^If there is no auxiliary data ** associated with the function argument, the sqlite3_get_auxdata(C,N) interface ** returns a NULL pointer. ** -** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th -** argument of the application-defined function. ^Subsequent +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the +** N-th argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent -** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or -** NULL if the metadata has been discarded. +** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or +** NULL if the auxiliary data has been discarded. ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, ** SQLite will invoke the destructor function X with parameter P exactly -** once, when the metadata is discarded. -** SQLite is free to discard the metadata at any time, including:

        +** once, when the auxiliary data is discarded. +** SQLite is free to discard the auxiliary data at any time, including:
          **
        • ^(when the corresponding function parameter changes)^, or **
        • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement)^, or @@ -5893,7 +5983,7 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** function implementation should not make any use of P after ** sqlite3_set_auxdata() has been called. ** -** ^(In practice, metadata is preserved between function calls for +** ^(In practice, auxiliary data is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** @@ -5903,10 +5993,67 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); ** ** These routines must be called from the same thread in which ** the SQL function is running. +** +** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()]. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +/* +** CAPI3REF: Database Connection Client Data +** METHOD: sqlite3 +** +** These functions are used to associate one or more named pointers +** with a [database connection]. +** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P +** to be attached to [database connection] D using name N. Subsequent +** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P +** or a NULL pointer if there were no prior calls to +** sqlite3_set_clientdata() with the same values of D and N. +** Names are compared using strcmp() and are thus case sensitive. +** +** 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 @@ -6279,6 +6426,13 @@ SQLITE_API void sqlite3_activate_cerod( ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. +** +** If a negative argument is passed to sqlite3_sleep() the results vary by +** VFS and operating system. Some system treat a negative argument as an +** instruction to sleep forever. Others understand it to mean do not sleep +** at all. ^In SQLite version 3.42.0 and later, a negative +** argument passed into sqlite3_sleep() is changed to zero before it is relayed +** down into the xSleep method of the VFS. */ SQLITE_API int sqlite3_sleep(int); @@ -6532,7 +6686,7 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); /* -** CAPI3REF: Allowed return values from [sqlite3_txn_state()] +** CAPI3REF: Allowed return values from sqlite3_txn_state() ** KEYWORDS: {transaction state} ** ** These constants define the current transaction state of a database file. @@ -6664,7 +6818,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** ^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 cancelled. The return value +** 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 @@ -7183,8 +7337,14 @@ struct sqlite3_module { /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*); - /* The methods below relate to features contributed by the community and - ** are available for version 700 and greater. */ + /* 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); + + // reserved for sqlite extension + void (*reserved[5])(); + // following methods are added by libsql int (*xPreparedSql)(sqlite3_vtab_cursor*, const char*); }; @@ -7469,9 +7629,9 @@ SQLITE_API int sqlite3_drop_modules( ** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Number of open cursors */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Number of open cursors */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; @@ -7673,7 +7833,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); ** code is returned and the transaction rolled back. ** ** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behaviour. ^Calling this routine +** open blob handle results in undefined behavior. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the @@ -7822,12 +7982,6 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); ** ^Unregister WAL methods with the libsql_wal_methods_unregister() interface. */ typedef struct libsql_wal_methods libsql_wal_methods; -SQLITE_API libsql_wal_methods *libsql_wal_methods_find(const char *zName); -SQLITE_API int libsql_wal_methods_register(libsql_wal_methods*); -SQLITE_API int libsql_wal_methods_unregister(libsql_wal_methods*); - -SQLITE_API libsql_wal_methods *libsql_wal_methods_next(libsql_wal_methods *w); -SQLITE_API const char *libsql_wal_methods_name(libsql_wal_methods *w); /* ** CAPI3REF: Mutexes @@ -7937,9 +8091,9 @@ SQLITE_API const char *libsql_wal_methods_name(libsql_wal_methods *w); ** is undefined if the mutex is not currently entered by the ** calling thread or is not currently allocated. ** -** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or -** sqlite3_mutex_leave() is a NULL pointer, then all three routines -** behave as no-ops. +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), +** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer, +** then any of the four routines behaves as a no-op. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ @@ -8181,6 +8335,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #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_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 @@ -8209,7 +8364,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 -#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_USELONGDOUBLE 34 +#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking @@ -8532,6 +8688,10 @@ SQLITE_API int sqlite3_status64( */ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +#ifdef LIBSQL_CUSTOM_PAGER_CODEC +SQLITE_API void *libsql_leak_pager(sqlite3*); +#endif + /* ** CAPI3REF: Status Parameters for database connections ** KEYWORDS: {SQLITE_DBSTATUS options} @@ -9677,7 +9837,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** [[SQLITE_VTAB_DIRECTONLY]]
          SQLITE_VTAB_DIRECTONLY
          **
          Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** the [xConnect] or [xCreate] methods of a [virtual table] implementation ** prohibits that virtual table from being used from within triggers and ** views. **
          @@ -9685,18 +9845,28 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); ** [[SQLITE_VTAB_INNOCUOUS]]
          SQLITE_VTAB_INNOCUOUS
          **
          Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the -** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** 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 @@ -9857,7 +10027,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); ** 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 postive integer. ^(Then, under +** 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 @@ -10286,7 +10456,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); ** When the [sqlite3_blob_write()] API is used to update a blob column, ** the pre-update hook is invoked with SQLITE_DELETE. This is because the ** in this case the new values are not available. In this case, when a -** callback made with op==SQLITE_DELETE is actuall a write using the +** 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 @@ -10315,6 +10485,22 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *); #endif +/* +** CAPI3REF: The close hook. +** METHOD: sqlite3 +** +** ^The [libsql_close_hook()] interface registers a callback function +** that is invoked prior to closing the database connection. +** ^At most one close hook may be registered at a time on a single +** [database connection]; each call to [libsql_close_hook()] overrides +** the previous setting. +** ^The close hook is disabled by invoking [libsql_close_hook()] +** with a NULL pointer as the second parameter. +** ^The third parameter to [libsql_close_hook()] is passed through as +** the first parameter to callbacks. +*/ +SQLITE_API void *libsql_close_hook(sqlite3 *db, void (*xClose)(void *pCtx, sqlite3 *db), void *arg); + /* ** CAPI3REF: Low-level system error code ** METHOD: sqlite3 @@ -10547,6 +10733,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c ** 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. @@ -10595,6 +10788,9 @@ SQLITE_API unsigned char *sqlite3_serialize( ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** +** Applications must not modify the buffer P or invalidate it before +** the database connection D is closed. +** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. @@ -10603,6 +10799,13 @@ SQLITE_API unsigned char *sqlite3_serialize( ** 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. @@ -10655,8 +10858,9 @@ SQLITE_API int sqlite3_deserialize( #if defined(__wasi__) # undef SQLITE_WASI # define SQLITE_WASI 1 -# undef SQLITE_OMIT_WAL -# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */ +// NOTICE: we do support WAL mode, we just don't support shared memory +//# undef SQLITE_OMIT_WAL +//# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */ # ifndef SQLITE_OMIT_LOAD_EXTENSION # define SQLITE_OMIT_LOAD_EXTENSION # endif @@ -10871,16 +11075,20 @@ SQLITE_API int sqlite3session_create( SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* -** CAPIREF: Conigure a Session Object +** 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 value for the second parameter is -** [SQLITE_SESSION_OBJCONFIG_SIZE]. +** created. At present the only valid values for the second parameter are +** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. ** -** Arguments for sqlite3session_object_config() +*/ +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 4th parameter to +** The following values may passed as the the 2nd parameter to ** sqlite3session_object_config(). ** **
          SQLITE_SESSION_OBJCONFIG_SIZE
          @@ -10896,12 +11104,21 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); ** ** 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. */ -SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); - -/* -*/ -#define SQLITE_SESSION_OBJCONFIG_SIZE 1 +#define SQLITE_SESSION_OBJCONFIG_SIZE 1 +#define SQLITE_SESSION_OBJCONFIG_ROWID 2 /* ** CAPI3REF: Enable Or Disable A Session Object @@ -11662,6 +11879,18 @@ SQLITE_API int sqlite3changeset_concat( ); +/* +** 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 ** @@ -11708,6 +11937,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; */ 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 @@ -11776,13 +12037,18 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the -** case, this function fails with SQLITE_SCHEMA. If the input changeset -** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is -** returned. Or, if an out-of-memory condition occurs during processing, this -** function returns SQLITE_NOMEM. In all cases, if an error occurs the state -** of the final contents of the changegroup is undefined. +** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup +** object has been configured with a database schema using the +** sqlite3changegroup_schema() API, then it is possible to combine changesets +** with different numbers of columns for a single table, provided that +** they are otherwise compatible. +** +** If the input changeset appears to be corrupt and the corruption is +** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition +** occurs during processing, this function returns SQLITE_NOMEM. ** -** If no error occurs, SQLITE_OK is returned. +** In all cases, if an error occurs the state of the final contents of the +** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); @@ -12047,10 +12313,17 @@ SQLITE_API int sqlite3changeset_apply_v2( **
        • 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 @@ -12791,7 +13064,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -13020,8 +13293,8 @@ struct Fts5ExtensionApi { ** as separate queries of the FTS index are required for each synonym. ** ** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is +** provide synonyms when tokenizing document text (method (3)) or query +** text (method (2)), not both. Doing so will not cause any errors, but is ** inefficient. */ typedef struct Fts5Tokenizer Fts5Tokenizer; @@ -13069,7 +13342,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -13078,7 +13351,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -13086,7 +13359,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); @@ -13134,7 +13407,7 @@ struct libsql_pghdr { ** private to pcache.c and should not be accessed by other modules. ** pCache is grouped with the public elements for efficiency. */ - short nRef; /* Number of users of this page */ + unsigned long long 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 @@ -13179,15 +13452,16 @@ typedef struct libsql_pghdr libsql_pghdr; ** There is one object of this type for each pager. */ typedef struct libsql_wal libsql_wal; +typedef struct libsql_wal_manager libsql_wal_manager; +/* Opaque types for wal method data */ +typedef struct wal_impl wal_impl; +typedef struct wal_manager_impl wal_manager_impl; typedef struct libsql_wal_methods { int iVersion; /* Current version is 1, versioning is here for backward compatibility */ - /* Open and close a connection to a write-ahead log. */ - int (*xOpen)(sqlite3_vfs*, sqlite3_file* , const char*, int no_shm_mode, long long max_size, struct libsql_wal_methods*, libsql_wal**); - int (*xClose)(libsql_wal*, sqlite3* db, int sync_flags, int nBuf, unsigned char *zBuf); /* Set the limiting size of a WAL file. */ - void (*xLimit)(libsql_wal*, long long limit); + void (*xLimit)(wal_impl* pWal, long long limit); /* 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 @@ -13196,37 +13470,37 @@ typedef struct libsql_wal_methods { ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the ** transaction and releases the lock. */ - int (*xBeginReadTransaction)(libsql_wal *, int *); - void (*xEndReadTransaction)(libsql_wal *); + int (*xBeginReadTransaction)(wal_impl* pWal, int *); + void (*xEndReadTransaction)(wal_impl *); /* Read a page from the write-ahead log, if it is present. */ - int (*xFindFrame)(libsql_wal *, unsigned int, unsigned int *); - int (*xReadFrame)(libsql_wal *, unsigned int, int, unsigned char *); + int (*xFindFrame)(wal_impl* pWal, unsigned int, unsigned int *); + int (*xReadFrame)(wal_impl* pWal, unsigned int, int, unsigned char *); /* If the WAL is not empty, return the size of the database. */ - unsigned int (*xDbsize)(libsql_wal *pWal); + unsigned int (*xDbsize)(wal_impl* pWal); /* Obtain or release the WRITER lock. */ - int (*xBeginWriteTransaction)(libsql_wal *pWal); - int (*xEndWriteTransaction)(libsql_wal *pWal); + int (*xBeginWriteTransaction)(wal_impl* pWal); + int (*xEndWriteTransaction)(wal_impl* pWal); /* Undo any frames written (but not committed) to the log */ - int (*xUndo)(libsql_wal *pWal, int (*xUndo)(void *, unsigned int), void *pUndoCtx); + int (*xUndo)(wal_impl* pWal, int (*xUndo)(void *, unsigned int), void *pUndoCtx); /* Return an integer that records the current (uncommitted) write ** position in the WAL */ - void (*xSavepoint)(libsql_wal *pWal, unsigned int *aWalData); + void (*xSavepoint)(wal_impl* pWal, unsigned int *aWalData); /* Move the write position of the WAL back to iFrame. Called in ** response to a ROLLBACK TO command. */ - int (*xSavepointUndo)(libsql_wal *pWal, unsigned int *aWalData); + int (*xSavepointUndo)(wal_impl* pWal, unsigned int *aWalData); /* Write a frame or frames to the log. */ - int (*xFrames)(libsql_wal *pWal, int, libsql_pghdr *, unsigned int, int, int); + int (*xFrames)(wal_impl* pWal, int, libsql_pghdr *, unsigned int, int, int, int*); /* Copy pages from the log to the database file */ int (*xCheckpoint)( - libsql_wal *pWal, /* Write-ahead log connection */ + wal_impl* 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 */ @@ -13235,7 +13509,12 @@ typedef struct libsql_wal_methods { int nBuf, /* Size of buffer nBuf */ unsigned char *zBuf, /* Temporary buffer to use */ int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ + int *pnCkpt, /* OUT: Number of backfilled frames in WAL */ + /* + * Called for each page being inserted in the wal, and once if the whole checkpoint operation was successfull with pPage == NULL + */ + int (*xCb)(void* pCbData, int mxSafeFrame, const unsigned char* pPage, int nPage, int page_no, int frame_no), /* called */ + void* pCbData /* user data passed to xCb */ ); /* Return the value to pass to a sqlite3_wal_hook callback, the @@ -13243,66 +13522,42 @@ typedef struct libsql_wal_methods { ** sqlite3WalCallback() was called. If no commits have occurred since ** the last call, then return 0. */ - int (*xCallback)(libsql_wal *pWal); + int (*xCallback)(wal_impl* pWal); /* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released) ** by the pager layer on the database file. */ - int (*xExclusiveMode)(libsql_wal *pWal, int op); + int (*xExclusiveMode)(wal_impl* 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. */ - int (*xHeapMemory)(libsql_wal *pWal); + int (*xHeapMemory)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_SNAPSHOT, but part of the ABI - int (*xSnapshotGet)(libsql_wal *pWal, sqlite3_snapshot **ppSnapshot); - void (*xSnapshotOpen)(libsql_wal *pWal, sqlite3_snapshot *pSnapshot); - int (*xSnapshotRecover)(libsql_wal *pWal); - int (*xSnapshotCheck)(libsql_wal *pWal, sqlite3_snapshot *pSnapshot); - void (*xSnapshotUnlock)(libsql_wal *pWal); + int (*xSnapshotGet)(wal_impl* pWal, sqlite3_snapshot **ppSnapshot); + void (*xSnapshotOpen)(wal_impl* pWal, sqlite3_snapshot *pSnapshot); + int (*xSnapshotRecover)(wal_impl* pWal); + int (*xSnapshotCheck)(void* pWal, sqlite3_snapshot *pSnapshot); + void (*xSnapshotUnlock)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_ZIPVFS, but part of the ABI /* 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). */ - int (*xFramesize)(libsql_wal *pWal); + int (*xFramesize)(wal_impl* pWal); /* Return the sqlite3_file object for the WAL file */ - sqlite3_file *(*xFile)(libsql_wal *pWal); + sqlite3_file *(*xFile)(wal_impl* pWal); // Only needed with SQLITE_ENABLE_SETLK_TIMEOUT - int (*xWriteLock)(libsql_wal *pWal, int bLock); - - void (*xDb)(libsql_wal *pWal, sqlite3 *db); - - /* Return the WAL pathname length based on the owning pager's pathname len. - ** For WAL implementations not based on a single file, 0 should be returned. */ - int (*xPathnameLen)(int origPathname); - - /* Get the WAL pathname to given buffer. Assumes that the buffer can hold - ** at least xPathnameLen bytes. For WAL implementations not based on a single file, - ** this operation can safely be a no-op. - ** */ - void (*xGetWalPathname)(char *buf, const char *orig, int orig_len); + int (*xWriteLock)(wal_impl* pWal, int bLock); - /* - ** This optional callback gets called before the main database file which owns - ** the WAL file is open. It is a good place for initialization routines, as WAL - ** is otherwise open lazily. - */ - int (*xPreMainDbOpen)(libsql_wal_methods *methods, const char *main_db_path); - - /* True if the implementation relies on shared memory routines (e.g. locks) */ - int bUsesShm; - - const char *zName; - struct libsql_wal_methods *pNext; + void (*xDb)(wal_impl* pWal, sqlite3 *db); } libsql_wal_methods; -libsql_wal_methods* libsql_wal_methods_find(const char *zName); /* Object declarations */ typedef struct WalIndexHdr WalIndexHdr; @@ -13337,11 +13592,29 @@ struct WalIndexHdr { unsigned int aCksum[2]; /* Checksum over all prior fields */ }; +struct libsql_wal_manager { + /* True if the implementation relies on shared memory routines (e.g. locks) */ + int bUsesShm; + + /* Open and close a connection to a write-ahead log. */ + int (*xOpen)(wal_manager_impl* pData, sqlite3_vfs*, sqlite3_file*, int no_shm_mode, long long max_size, const char* zMainDbFileName, libsql_wal* out_wal); + int (*xClose)(wal_manager_impl* pData, wal_impl* pWal, sqlite3* db, int sync_flags, int nBuf, unsigned char *zBuf); + + /* destroy resources for this wal */ + int (*xLogDestroy)(wal_manager_impl* pData, sqlite3_vfs *vfs, const char* zMainDbFileName); + /* returns whether this wal exists */ + int (*xLogExists)(wal_manager_impl* pData, sqlite3_vfs *vfs, const char* zMainDbFileName, int* exist); + /* destructor */ + void (*xDestroy)(wal_manager_impl* pData); + + wal_manager_impl* pData; +}; + /* ** An open write-ahead log file is represented by an instance of the ** following object. */ -struct libsql_wal { +typedef struct sqlite3_wal { sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ sqlite3_file *pDbFd; /* File handle for the database file */ sqlite3_file *pWalFd; /* File handle for WAL file */ @@ -13369,11 +13642,29 @@ struct libsql_wal { unsigned char lockError; /* True if a locking error has occurred */ WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ sqlite3 *db; - libsql_wal_methods *pMethods; /* Virtual methods for interacting with WAL */ - void *pMethodsData; /* Optional context for private use of libsql_wal_methods */ +} sqlite3_wal; + +struct libsql_wal { + libsql_wal_methods methods; /* virtual wal methods */ + wal_impl* pData; /* methods receiver */ }; -typedef struct libsql_wal libsql_wal; +typedef struct RefCountedWalManager { + int n; + libsql_wal_manager ref; + int is_static; +} RefCountedWalManager; + +int make_ref_counted_wal_manager(libsql_wal_manager wal_manager, RefCountedWalManager **out); +void destroy_wal_manager(RefCountedWalManager *p); +RefCountedWalManager* clone_wal_manager(RefCountedWalManager *p); + +SQLITE_API int sqlite3_wal_backfilled(sqlite3_wal* pWal); +SQLITE_API unsigned int sqlite3_wal_frame_page_no(sqlite3_wal *pWal, unsigned int iFrame); + +RefCountedWalManager *make_sqlite3_wal_manager_rc(); + +SQLITE_API extern const libsql_wal_manager sqlite3_wal_manager; #endif /* SQLITE_WAL_H */ @@ -13429,6 +13720,7 @@ SQLITE_API void libsql_free_wasm_module(void *module); ** Creates a new wasm engine */ SQLITE_API libsql_wasm_engine_t *libsql_wasm_engine_new(); +SQLITE_API void libsql_wasm_engine_free(libsql_wasm_engine_t *); #endif //LIBSQL_WASM_BINDINGS_H #endif //LIBSQL_ENABLE_WASM_RUNTIME From 86d848af1bf5f581cf7428ab4422c4ca0987cdf4 Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 10:30:33 -0600 Subject: [PATCH 4/8] update version specs --- HISTORY.md | 3 +++ lib/libsql/version.rb | 2 +- spec/sqlite3/libsql_version_spec.rb | 8 ++++---- spec/sqlite3/version_spec.rb | 12 ++++++------ tasks/extension.rake | 1 + 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index ca0d322..7229eb4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,7 @@ # Libsql Changelog +## Version 0.2.0 - 2024-03-XX +* Update to libsql 0.2.3 (from libsql-server-v0.24.2) +* Update CI tooling ## Version 0.1.0 - 2023-05-03 * Use the the [amalgalite](https://github.com/copiousfreetime/amalgalite) codebase to bootstrap libsql. diff --git a/lib/libsql/version.rb b/lib/libsql/version.rb index ad614c8..248580e 100644 --- a/lib/libsql/version.rb +++ b/lib/libsql/version.rb @@ -4,5 +4,5 @@ #++ module Libsql - VERSION = "0.1.0" + VERSION = "0.2.0" end diff --git a/spec/sqlite3/libsql_version_spec.rb b/spec/sqlite3/libsql_version_spec.rb index cbe6325..ea2fbc9 100644 --- a/spec/sqlite3/libsql_version_spec.rb +++ b/spec/sqlite3/libsql_version_spec.rb @@ -8,9 +8,9 @@ expect(::Libsql::SQLite3::LibsqlVersion.runtime_version).to match( /\d+\.\d+\.\d+/ ) expect(::Libsql::SQLite3::LibsqlVersion.compiled_version).to match( /\d+\.\d+\.\d+/ ) - ::Libsql::SQLite3::LIBSQL_VERSION.should be == "0.2.1" - ::Libsql::SQLite3::LibsqlVersion.compiled_version.should be == "0.2.1" - ::Libsql::SQLite3::LibsqlVersion.runtime_version.should be == "0.2.1" - ::Libsql::SQLite3::LibsqlVersion.to_s.should be == "0.2.1" + ::Libsql::SQLite3::LIBSQL_VERSION.should be == "0.2.3" + ::Libsql::SQLite3::LibsqlVersion.compiled_version.should be == "0.2.3" + ::Libsql::SQLite3::LibsqlVersion.runtime_version.should be == "0.2.3" + ::Libsql::SQLite3::LibsqlVersion.to_s.should be == "0.2.3" end end diff --git a/spec/sqlite3/version_spec.rb b/spec/sqlite3/version_spec.rb index 081f11e..d0e3ff3 100644 --- a/spec/sqlite3/version_spec.rb +++ b/spec/sqlite3/version_spec.rb @@ -7,21 +7,21 @@ expect(::Libsql::SQLite3::Version.to_s).to match( /\d+\.\d+\.\d+/ ) expect(::Libsql::SQLite3::Version.runtime_version).to match( /\d+\.\d+\.\d+/ ) - ::Libsql::SQLite3::Version.to_i.should eql(3042000) - ::Libsql::SQLite3::Version.runtime_version_number.should eql(3042000) + ::Libsql::SQLite3::Version.to_i.should eql(3044000) + ::Libsql::SQLite3::Version.runtime_version_number.should eql(3044000) ::Libsql::SQLite3::Version::MAJOR.should eql(3) - ::Libsql::SQLite3::Version::MINOR.should eql(42) + ::Libsql::SQLite3::Version::MINOR.should eql(44) ::Libsql::SQLite3::Version::RELEASE.should eql(0) expect(::Libsql::SQLite3::Version.to_a.size).to eql(3) - ::Libsql::SQLite3::Version.compiled_version.should be == "3.42.0" - ::Libsql::SQLite3::Version.compiled_version_number.should be == 3042000 + ::Libsql::SQLite3::Version.compiled_version.should be == "3.44.0" + ::Libsql::SQLite3::Version.compiled_version_number.should be == 3044000 ::Libsql::SQLite3::Version.compiled_matches_runtime?.should be == true end it "should have the sqlite3 source id" do - source_id = "2023-03-11 23:21:21 dc9f025dc43cb8008e7d8d644175d8b2d084e602a1513803c40c513d1e99alt1" + source_id = "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad8alt1" ::Libsql::SQLite3::Version.compiled_source_id.should be == source_id ::Libsql::SQLite3::Version.runtime_source_id.should be == source_id end diff --git a/tasks/extension.rake b/tasks/extension.rake index aacdc6e..cfdc77a 100644 --- a/tasks/extension.rake +++ b/tasks/extension.rake @@ -7,6 +7,7 @@ begin require 'rake/extensiontask' Rake::ExtensionTask.new( This.name ) do |ext| + ext.name = "#{ This.name }_ext" ext.ext_dir = File.join( 'ext', This.name, "c" ) ext.lib_dir = File.join( 'lib', This.name ) ext.gem_spec = This.ruby_gemspec From 3c28d54aac5c3deed7c8f0665ffe3cf21075adb5 Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 10:55:08 -0600 Subject: [PATCH 5/8] update compiler docker images --- .semaphore/semaphore.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 75643fd..4252174 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -70,12 +70,15 @@ blocks: - Run Linux Tests task: agent: + env_vars: + - name: RUBY_CC_VERSION + value: 3.0.0:3.1.0:3.2.0:3.3.0 machine: type: e1-standard-2 os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "larskanis/rake-compiler-dock-mri-x86-mingw32:1.2.2" + image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.4.0-mri-x86-mingw32" jobs: - name: build x86-mingw32 gem commands: @@ -89,13 +92,16 @@ blocks: dependencies: - Run Linux Tests task: + env_vars: + - name: RUBY_CC_VERSION + value: 3.0.0:3.1.0:3.2.0:3.3.0 agent: machine: type: e1-standard-2 os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "larskanis/rake-compiler-dock-mri-x64-mingw32:1.2.2" + image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.4.0-mri-x64-mingw32" jobs: - name: build x64-mingw32 commands: @@ -109,13 +115,16 @@ blocks: dependencies: - Run Linux Tests task: + env_vars: + - name: RUBY_CC_VERSION + value: 3.0.0:3.1.0:3.2.0:3.3.0 agent: machine: type: e1-standard-2 os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "larskanis/rake-compiler-dock-mri-x64-mingw-ucrt:1.2.2" + image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.4.0-mri-x64-mingw32-ucrt" jobs: - name: build x64-mingw-ucrt commands: From ef8fc12f54dcfb1f29f125815cb83f5fbedeb75a Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 11:04:13 -0600 Subject: [PATCH 6/8] fix yaml parsing --- .semaphore/semaphore.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 4252174..c263f27 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -73,6 +73,7 @@ blocks: env_vars: - name: RUBY_CC_VERSION value: 3.0.0:3.1.0:3.2.0:3.3.0 + agent: machine: type: e1-standard-2 os_image: ubuntu2004 From f6666eb8940cecb5df609c972ef6216ab3824c0d Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 11:09:04 -0600 Subject: [PATCH 7/8] update env vars --- .semaphore/semaphore.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index c263f27..bf82a58 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -69,7 +69,6 @@ blocks: dependencies: - Run Linux Tests task: - agent: env_vars: - name: RUBY_CC_VERSION value: 3.0.0:3.1.0:3.2.0:3.3.0 From 87e37a0a00e0d6550ec741f3650042968895a095 Mon Sep 17 00:00:00 2001 From: copiousfreetime Date: Mon, 18 Mar 2024 11:17:28 -0600 Subject: [PATCH 8/8] fix docker image name --- .semaphore/semaphore.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index bf82a58..cf1bb55 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -124,7 +124,7 @@ blocks: os_image: ubuntu2004 containers: - name: rake-compiler-dock - image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.4.0-mri-x64-mingw32-ucrt" + image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.4.0-mri-x64-mingw-ucrt" jobs: - name: build x64-mingw-ucrt commands: