diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..be006de9a
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,13 @@
+# Keep GitHub Actions up to date with GitHub's Dependabot...
+# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
+# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ groups:
+ github-actions:
+ patterns:
+ - "*" # Group all Actions updates into a single larger pull request
+ schedule:
+ interval: weekly
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 423ac1979..54b10650d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -12,112 +12,171 @@ on:
- released
workflow_dispatch: {}
+env:
+ # See https://github.com/nodejs/release#release-schedule
+ # Node.js v16 EOL = 2023-09-11. v21 EOL = 2024-06-01.
+ NODE_BUILD_CMD: npx --no-install prebuild -r node -t 18.0.0 -t 20.0.0 -t 22.0.0 -t 23.0.0 --include-regex 'better_sqlite3.node$'
+ # Merge with NODE_BUILD_CMD when Node.js v18 is EOL
+ NO_V18_NODE_BUILD_CMD: npx --no-install prebuild -r node -t 20.0.0 -t 22.0.0 -t 23.0.0 --include-regex 'better_sqlite3.node$'
+ # See https://www.electronjs.org/docs/latest/tutorial/electron-timelines#version-support-policy
+ # Electron v25 EOL = 2023-12-05. v26 EOL = 2024-02-20. v27 EOL = 2024-04-16. v28 EOL = 2024-06-11. v29 EOL = 2024-08-20.
+ ELECTRON_BUILD_CMD: npx --no-install prebuild -r electron -t 26.0.0 -t 27.0.0 -t 28.0.0 -t 29.0.0 -t 30.0.0 -t 31.0.0 -t 32.0.0 -t 33.0.0 -t 34.0.0 -t 35.0.0 --include-regex 'better_sqlite3.node$'
+
jobs:
test:
strategy:
matrix:
os:
- - ubuntu-20.04
- - macos-latest
+ - ubuntu-22.04
+ - macos-13
+ - macos-14
- windows-2019
node:
- - 14
- - 16
- 18
- - 19
+ - 20
+ - 22
+ - 23
name: Testing Node ${{ matrix.node }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
+ - if: ${{ startsWith(matrix.os, 'windows') }}
+ run: pip.exe install setuptools
+ - if: ${{ startsWith(matrix.os, 'macos') }}
+ run: brew install python-setuptools
+ - if: ${{ !startsWith(matrix.os, 'windows') && !startsWith(matrix.os, 'macos') }}
+ run: python3 -m pip install setuptools
+ - if: ${{ startsWith(matrix.os, 'ubuntu') }}
+ run: |
+ sudo apt update
+ sudo apt install gcc-10 g++-10 -y
+ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10
- run: npm install --ignore-scripts
- run: npm run build-debug
- run: npm test
+ - name: Test SpatiaLite extension
+ if: ${{ startsWith(matrix.os, 'ubuntu') }}
+ run: |
+ sudo apt update
+ sudo apt install libsqlite3-mod-spatialite -y
+ node -e "require('./lib/index.js')(':memory:').loadExtension('mod_spatialite').exec('SELECT InitSpatialMetaData();')"
publish:
if: ${{ github.event_name == 'release' }}
name: Publishing to NPM
- runs-on: ubuntu-20.04
- needs: test
+ runs-on: ubuntu-22.04
+ needs:
+ - prebuild
+ - prebuild-alpine
+ - prebuild-alpine-arm
+ - prebuild-linux-x64
+ - prebuild-linux-arm
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
with:
- node-version: 16
+ node-version: 18
registry-url: https://registry.npmjs.org
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
prebuild:
+ if: ${{ github.event_name == 'release' }}
strategy:
+ fail-fast: false
matrix:
os:
- - ubuntu-20.04
- - macos-latest
+ - macos-13
+ - macos-14
- windows-2019
name: Prebuild on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
- needs: publish
+ needs: test
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
with:
- node-version: 16
+ node-version: 18
+ - if: ${{ startsWith(matrix.os, 'windows') }}
+ run: pip.exe install setuptools
+ - if: ${{ startsWith(matrix.os, 'macos') }}
+ run: brew install python-setuptools
- run: npm install --ignore-scripts
- - run: npx --no-install prebuild -r node -t 14.0.0 -t 16.0.0 -t 18.0.0 --include-regex 'better_sqlite3.node$' -u ${{ secrets.GITHUB_TOKEN }}
- - run: npx --no-install prebuild -r electron -t 16.0.0 -t 17.0.0 -t 18.0.0 -t 19.0.0 -t 20.0.0 -t 21.0.0 -t 22.0.0 -t 23.0.0 -t 24.0.0 --include-regex 'better_sqlite3.node$' -u ${{ secrets.GITHUB_TOKEN }}
+ - run: ${{ env.NODE_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }}
+ - run: ${{ env.ELECTRON_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }}
- if: matrix.os == 'windows-2019'
- run: npx --no-install prebuild -r electron -t 16.0.0 -t 17.0.0 -t 18.0.0 -t 19.0.0 -t 20.0.0 -t 21.0.0 -t 22.0.0 -t 23.0.0 -t 24.0.0 --include-regex 'better_sqlite3.node$' --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
- - if: matrix.os == 'macos-latest'
- run: npx --no-install prebuild -r electron -t 16.0.0 -t 17.0.0 -t 18.0.0 -t 19.0.0 -t 20.0.0 -t 21.0.0 -t 22.0.0 -t 23.0.0 -t 24.0.0 --include-regex 'better_sqlite3.node$' --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ ${{ env.NODE_BUILD_CMD }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
+ ${{ env.NO_V18_NODE_BUILD_CMD }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
+ ${{ env.ELECTRON_BUILD_CMD }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
+ ${{ env.ELECTRON_BUILD_CMD }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
+
+ prebuild-linux-x64:
+ if: ${{ github.event_name == 'release' }}
+ name: Prebuild on Linux x64
+ runs-on: ubuntu-latest
+ container: node:18-bullseye
+ needs: test
+ steps:
+ - uses: actions/checkout@v4
+ - run: npm install --ignore-scripts
+ - run: ${{ env.NODE_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }}
+ - run: ${{ env.ELECTRON_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }}
prebuild-alpine:
+ if: ${{ github.event_name == 'release' }}
name: Prebuild on alpine
runs-on: ubuntu-latest
- container: node:16-alpine
- needs: publish
+ container: node:18-alpine
+ needs: test
steps:
- - uses: actions/checkout@v3
- - run: apk add build-base git python3 --update-cache
+ - uses: actions/checkout@v4
+ - run: apk add build-base git python3 py3-setuptools --update-cache
- run: npm install --ignore-scripts
- - run: npx --no-install prebuild -r node -t 14.0.0 -t 16.0.0 -t 18.0.0 --include-regex 'better_sqlite3.node$' -u ${{ secrets.GITHUB_TOKEN }}
+ - run: ${{ env.NODE_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }}
prebuild-alpine-arm:
+ if: ${{ github.event_name == 'release' }}
strategy:
+ fail-fast: false
matrix:
arch:
- arm/v7
- arm64
name: Prebuild on alpine (${{ matrix.arch }})
runs-on: ubuntu-latest
- needs: publish
+ needs: test
steps:
- - uses: actions/checkout@v3
- - uses: docker/setup-qemu-action@v1
+ - uses: actions/checkout@v4
+ - uses: docker/setup-qemu-action@v3
- run: |
- docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:16-alpine -c "\
- apk add build-base git python3 --update-cache && \
+ docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:18-alpine -c "\
+ apk add build-base git python3 py3-setuptools --update-cache && \
cd /tmp/project && \
npm install --ignore-scripts && \
- npx --no-install prebuild -r node -t 14.0.0 -t 16.0.0 -t 18.0.0 --include-regex 'better_sqlite3.node$' -u ${{ secrets.GITHUB_TOKEN }}"
+ ${{ env.NODE_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }}"
prebuild-linux-arm:
+ if: ${{ github.event_name == 'release' }}
strategy:
+ fail-fast: false
matrix:
arch:
- arm/v7
- arm64
name: Prebuild on Linux (${{ matrix.arch }})
runs-on: ubuntu-latest
- needs: publish
+ needs: test
steps:
- - uses: actions/checkout@v3
- - uses: docker/setup-qemu-action@v1
+ - uses: actions/checkout@v4
+ - uses: docker/setup-qemu-action@v3
- run: |
- docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:16 -c "\
+ docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:18-bullseye -c "\
cd /tmp/project && \
npm install --ignore-scripts && \
- npx --no-install prebuild -r node -t 14.0.0 -t 16.0.0 -t 18.0.0 --include-regex 'better_sqlite3.node$' -u ${{ secrets.GITHUB_TOKEN }}"
+ ${{ env.NODE_BUILD_CMD }} -u ${{ secrets.GITHUB_TOKEN }} && \
+ if [ '${{ matrix.arch }}' = 'arm64' ]; then ${{ env.ELECTRON_BUILD_CMD }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}; fi"
diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml
index a91b2e4c6..dcb18e0ac 100644
--- a/.github/workflows/bump-version.yml
+++ b/.github/workflows/bump-version.yml
@@ -17,13 +17,13 @@ jobs:
name: Bump to a new version
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
fetch-depth: 0
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@v4
with:
- node-version: 16
+ node-version: 18
- name: Configure user
run: |
git config --local user.name "${{ github.actor }}"
diff --git a/.github/workflows/update-sqlite.yml b/.github/workflows/update-sqlite.yml
index d02a96029..d0fc1c605 100644
--- a/.github/workflows/update-sqlite.yml
+++ b/.github/workflows/update-sqlite.yml
@@ -18,13 +18,13 @@ jobs:
ENV_YEAR: ${{ github.event.inputs.year }}
ENV_VERSION: ${{ github.event.inputs.version }}
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
fetch-depth: 0
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@v4
with:
- node-version: 16
+ node-version: 18
- name: Create new update branch
run: git checkout -b sqlite-update-${{ env.ENV_VERSION }}
- name: Update download script
@@ -35,7 +35,7 @@ jobs:
- name: Download, compile and package SQLite
run: npm run download
- name: Push update branch
- uses: stefanzweifel/git-auto-commit-action@v4
+ uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: Update SQLite to version ${{ env.ENV_TRUE_VERSION }}
branch: sqlite-update-${{ env.ENV_VERSION }}
diff --git a/README.md b/README.md
index b324c5324..2c753185e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# better-sqlite3 [](https://github.com/JoshuaWise/better-sqlite3/actions/workflows/build.yml?query=branch%3Amaster)
-The fastest and simplest library for SQLite3 in Node.js.
+The fastest and simplest library for SQLite in Node.js.
- Full transaction support
- High performance, efficiency, and safety
@@ -32,7 +32,7 @@ The fastest and simplest library for SQLite3 in Node.js.
npm install better-sqlite3
```
-> You must be using Node.js v14.21.1 or above. Prebuilt binaries are available for [LTS versions](https://nodejs.org/en/about/releases/). If you have trouble installing, check the [troubleshooting guide](./docs/troubleshooting.md).
+> Requires Node.js v14.21.1 or later. Prebuilt binaries are available for [LTS versions](https://nodejs.org/en/about/releases/). If you have trouble installing, check the [troubleshooting guide](./docs/troubleshooting.md).
## Usage
@@ -66,7 +66,7 @@ db.pragma('journal_mode = WAL');
#### When is this library not appropriate?
-In most cases, if you're attempting something that cannot be reasonably accomplished with `better-sqlite3`, it probably cannot be reasonably accomplished with SQLite3 in general. For example, if you're executing queries that take one second to complete, and you expect to have many concurrent users executing those queries, no amount of asynchronicity will save you from SQLite3's serialized nature. Fortunately, SQLite3 is very *very* fast. With proper indexing, we've been able to achieve upward of 2000 queries per second with 5-way-joins in a 60 GB database, where each query was handling 5–50 kilobytes of real data.
+In most cases, if you're attempting something that cannot be reasonably accomplished with `better-sqlite3`, it probably cannot be reasonably accomplished with SQLite in general. For example, if you're executing queries that take one second to complete, and you expect to have many concurrent users executing those queries, no amount of asynchronicity will save you from SQLite's serialized nature. Fortunately, SQLite is very *very* fast. With proper indexing, we've been able to achieve upward of 2000 queries per second with 5-way-joins in a 60 GB database, where each query was handling 5–50 kilobytes of real data.
If you have a performance problem, the most likely causes are inefficient queries, improper indexing, or a lack of [WAL mode](./docs/performance.md)—not `better-sqlite3` itself. However, there are some cases where `better-sqlite3` could be inappropriate:
@@ -76,6 +76,13 @@ If you have a performance problem, the most likely causes are inefficient querie
For these situations, you should probably use a full-fledged RDBMS such as [PostgreSQL](https://www.postgresql.org/).
+## Upgrading
+
+Upgrading your `better-sqlite3` dependency can potentially introduce breaking changes, either in the `better-sqlite3` API (if you upgrade to a new [major version](https://semver.org/)), or between your existing database(s) and the underlying version of SQLite. Before upgrading, review:
+
+* [`better-sqlite3` release notes](https://github.com/WiseLibs/better-sqlite3/releases)
+* [SQLite release history](https://www.sqlite.org/changes.html)
+
# Documentation
- [API documentation](./docs/api.md)
@@ -83,7 +90,7 @@ For these situations, you should probably use a full-fledged RDBMS such as [Post
- [64-bit integer support](./docs/integer.md)
- [Worker thread support](./docs/threads.md)
- [Unsafe mode (advanced)](./docs/unsafe.md)
-- [SQLite3 compilation (advanced)](./docs/compilation.md)
+- [SQLite compilation (advanced)](./docs/compilation.md)
- [Contribution rules](./docs/contribution.md)
- [Code of conduct](./docs/conduct.md)
diff --git a/benchmark/drivers.js b/benchmark/drivers.js
index 60e5a1890..d2a43d53f 100644
--- a/benchmark/drivers.js
+++ b/benchmark/drivers.js
@@ -1,7 +1,7 @@
'use strict';
/*
- Every benchmark trial will be executed once for each SQLite3 driver listed
+ Every benchmark trial will be executed once for each SQLite driver listed
below. Each driver has a function to open a new database connection on a
given filename and a list of PRAGMA statements.
*/
diff --git a/binding.gyp b/binding.gyp
index f2a910e43..81a1238c4 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -1,5 +1,5 @@
# ===
-# This is the main GYP file, which builds better-sqlite3 with SQLite3 itself.
+# This is the main GYP file, which builds better-sqlite3 with SQLite itself.
# ===
{
@@ -9,14 +9,14 @@
'target_name': 'better_sqlite3',
'dependencies': ['deps/sqlite3.gyp:sqlite3'],
'sources': ['src/better_sqlite3.cpp'],
- 'cflags_cc': ['-std=c++17'],
+ 'cflags_cc': ['-std=c++20'],
'xcode_settings': {
- 'OTHER_CPLUSPLUSFLAGS': ['-std=c++17', '-stdlib=libc++'],
+ 'OTHER_CPLUSPLUSFLAGS': ['-std=c++20', '-stdlib=libc++'],
},
'msvs_settings': {
'VCCLCompilerTool': {
'AdditionalOptions': [
- '/std:c++17',
+ '/std:c++20',
],
},
},
diff --git a/deps/copy.js b/deps/copy.js
index 42ce4e614..3d2dd56dd 100644
--- a/deps/copy.js
+++ b/deps/copy.js
@@ -18,9 +18,14 @@ if (process.argv[3]) {
}
for (const { filename, optional } of files) {
- if (optional && !fs.existsSync(path.join(source, filename))) {
+ const sourceFilepath = path.join(source, filename);
+ const destFilepath = path.join(dest, filename);
+
+ if (optional && !fs.existsSync(sourceFilepath)) {
continue;
}
- fs.accessSync(path.join(source, filename));
- fs.copyFileSync(path.join(source, filename), path.join(dest, filename));
+
+ fs.accessSync(sourceFilepath);
+ fs.mkdirSync(path.dirname(destFilepath), { recursive: true });
+ fs.copyFileSync(sourceFilepath, destFilepath);
}
diff --git a/deps/defines.gypi b/deps/defines.gypi
index dc956f6ce..51aaafe1e 100644
--- a/deps/defines.gypi
+++ b/deps/defines.gypi
@@ -9,12 +9,14 @@
'HAVE_UINT16_T=1',
'HAVE_UINT32_T=1',
'HAVE_UINT8_T=1',
+ 'HAVE_USLEEP=1',
'SQLITE_DEFAULT_CACHE_SIZE=-16000',
'SQLITE_DEFAULT_FOREIGN_KEYS=1',
'SQLITE_DEFAULT_MEMSTATUS=0',
'SQLITE_DEFAULT_WAL_SYNCHRONOUS=1',
'SQLITE_DQS=0',
'SQLITE_ENABLE_COLUMN_METADATA',
+ 'SQLITE_ENABLE_DBSTAT_VTAB',
'SQLITE_ENABLE_DESERIALIZE',
'SQLITE_ENABLE_FTS3',
'SQLITE_ENABLE_FTS3_PARENTHESIS',
@@ -26,10 +28,8 @@
'SQLITE_ENABLE_RTREE',
'SQLITE_ENABLE_STAT4',
'SQLITE_ENABLE_UPDATE_DELETE_LIMIT',
- 'SQLITE_INTROSPECTION_PRAGMAS',
'SQLITE_LIKE_DOESNT_MATCH_BLOBS',
'SQLITE_OMIT_DEPRECATED',
- 'SQLITE_OMIT_GET_TABLE',
'SQLITE_OMIT_PROGRESS_CALLBACK',
'SQLITE_OMIT_SHARED_CACHE',
'SQLITE_OMIT_TCL_VARIABLE',
diff --git a/deps/download.sh b/deps/download.sh
index 308bdc414..524a756a6 100755
--- a/deps/download.sh
+++ b/deps/download.sh
@@ -1,11 +1,11 @@
#!/usr/bin/env bash
# ===
-# This script defines and generates the bundled SQLite3 unit (sqlite3.c).
+# This script defines and generates the bundled SQLite unit (sqlite3.c).
#
# The following steps are taken:
# 1. populate the shell environment with the defined compile-time options.
-# 2. download and extract the SQLite3 source code into a temporary directory.
+# 2. download and extract the SQLite source code into a temporary directory.
# 3. run "sh configure" and "make sqlite3.c" within the source directory.
# 4. copy the generated amalgamation into the output directory (./sqlite3).
# 5. export the defined compile-time options to a gyp file (./defines.gypi).
@@ -18,8 +18,8 @@
# 4. node-gyp links the two resulting binaries to generate better_sqlite3.node.
# ===
-YEAR="2023"
-VERSION="3410200"
+YEAR="2025"
+VERSION="3490100"
# Defines below are sorted alphabetically
DEFINES="
@@ -30,12 +30,14 @@ HAVE_STDINT_H=1
HAVE_UINT16_T=1
HAVE_UINT32_T=1
HAVE_UINT8_T=1
+HAVE_USLEEP=1
SQLITE_DEFAULT_CACHE_SIZE=-16000
SQLITE_DEFAULT_FOREIGN_KEYS=1
SQLITE_DEFAULT_MEMSTATUS=0
SQLITE_DEFAULT_WAL_SYNCHRONOUS=1
SQLITE_DQS=0
SQLITE_ENABLE_COLUMN_METADATA
+SQLITE_ENABLE_DBSTAT_VTAB
SQLITE_ENABLE_DESERIALIZE
SQLITE_ENABLE_FTS3
SQLITE_ENABLE_FTS3_PARENTHESIS
@@ -47,10 +49,8 @@ SQLITE_ENABLE_MATH_FUNCTIONS
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_STAT4
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-SQLITE_INTROSPECTION_PRAGMAS
SQLITE_LIKE_DOESNT_MATCH_BLOBS
SQLITE_OMIT_DEPRECATED
-SQLITE_OMIT_GET_TABLE
SQLITE_OMIT_PROGRESS_CALLBACK
SQLITE_OMIT_SHARED_CACHE
SQLITE_OMIT_TCL_VARIABLE
@@ -83,11 +83,20 @@ echo "configuring amalgamation..."
sh configure > /dev/null || exit 1
echo "building amalgamation..."
-make sqlite3.c > /dev/null || exit 1
+make OPTIONS="$CFLAGS" sqlite3.c > /dev/null || exit 1
echo "copying amalgamation..."
cp sqlite3.c sqlite3.h sqlite3ext.h "$OUTPUT/" || exit 1
+echo "applying patches..."
+cd "$DEPS" || exit 1
+for patch in patches/*.patch; do
+ # If a patch fails, just skip it an move on.
+ # By default `patch` tries to be clever and reverse the patch, so we have to specify `--forward`.
+ # If the patch fails, we # don't write .orig and .rej files, so we have to specify `--no-backup-if-mismatch` and `--reject-file=-`.
+ patch --batch --forward --no-backup-if-mismatch --reject-file=- -p2 < "$patch"
+done
+
echo "updating gyp configs..."
GYP="$DEPS/defines.gypi"
printf "# THIS FILE IS AUTOMATICALLY GENERATED BY deps/download.sh (DO NOT EDIT)\n\n{\n 'defines': [\n" > "$GYP"
diff --git a/deps/patches/1208.patch b/deps/patches/1208.patch
new file mode 100644
index 000000000..08d88ca56
--- /dev/null
+++ b/deps/patches/1208.patch
@@ -0,0 +1,15 @@
+diff --git a/deps/sqlite3/sqlite3.c b/deps/sqlite3/sqlite3.c
+index b1a807f..38bd1e6 100644
+--- a/deps/sqlite3/sqlite3.c
++++ b/deps/sqlite3/sqlite3.c
+@@ -24887,8 +24887,8 @@ static const struct {
+ /* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
+ /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
+ /* 3 */ { 3, "day", 5373485.0, 86400.0 },
+- /* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
+- /* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
++ /* 4 */ { 5, "month", 176546.0, 2592000.0 },
++ /* 5 */ { 4, "year", 14713.0, 31536000.0 },
+ };
+
+ /*
diff --git a/deps/sqlite3.gyp b/deps/sqlite3.gyp
index d5307b144..7259dfef7 100755
--- a/deps/sqlite3.gyp
+++ b/deps/sqlite3.gyp
@@ -1,5 +1,5 @@
# ===
-# This configuration defines options specific to compiling SQLite3 itself.
+# This configuration defines options specific to compiling SQLite itself.
# Compile-time options are loaded by the auto-generated file "defines.gypi".
# The --sqlite3 option can be provided to use a custom amalgamation instead.
# ===
diff --git a/deps/sqlite3/sqlite3.c b/deps/sqlite3/sqlite3.c
index 0dc11139d..5e4c71e3a 100644
--- a/deps/sqlite3/sqlite3.c
+++ b/deps/sqlite3/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.41.2. By combining all the individual C code files into this
+** version 3.49.1. 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,7 +16,13 @@
** 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
+** 873d4e274b4988d260ba8354a9718324a1c2 with changes in files:
+**
+**
*/
+#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
@@ -51,11 +57,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.
**
@@ -124,6 +130,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 ************************************************/
@@ -250,10 +260,13 @@
/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
-#if GCC_VERSION>=7000000
-# define deliberate_fall_through __attribute__((fallthrough));
-#else
-# define deliberate_fall_through
+#if defined(__has_attribute)
+# if __has_attribute(fallthrough)
+# define deliberate_fall_through __attribute__((fallthrough));
+# endif
+#endif
+#if !defined(deliberate_fall_through)
+# define deliberate_fall_through
#endif
/*
@@ -453,9 +466,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.41.2"
-#define SQLITE_VERSION_NUMBER 3041002
-#define SQLITE_SOURCE_ID "2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69cffde2924203304e8ffc4155597af0c191da"
+#define SQLITE_VERSION "3.49.1"
+#define SQLITE_VERSION_NUMBER 3049001
+#define SQLITE_SOURCE_ID "2025-02-18 13:38:58 873d4e274b4988d260ba8354a9718324a1c26187a4ab4c1cc0227c03d0f10e70"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -727,6 +740,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
**
The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+** The application must not dereference the arrays or string pointers
+** passed as the 3rd and 4th callback parameters after it returns.
**
*/
SQLITE_API int sqlite3_exec(
@@ -835,6 +850,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))
@@ -956,6 +972,13 @@ SQLITE_API int sqlite3_exec(
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
+**
+** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
+** from the database file in amounts that are not a multiple of the
+** page size and that do not begin at a page boundary. Without this
+** property, SQLite is careful to only do full-page reads and write
+** on aligned pages, with the one exception that it will do a sub-page
+** read of the first page to access the database header.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -972,6 +995,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
+#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
/*
** CAPI3REF: File Locking Levels
@@ -1068,16 +1092,16 @@ struct sqlite3_file {
**
** xLock() upgrades the database file lock. In other words, xLock() moves the
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
-** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
+** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
** SQLITE_LOCK_NONE. If the database file lock is already at or above the
** requested lock, then the call to xLock() is a no-op.
** xUnlock() downgrades the database file lock to either SHARED or NONE.
-* If the lock is already at or below the requested lock state, then the call
+** If the lock is already at or below the requested lock state, then the call
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
-** PENDING, or EXCLUSIVE lock on the file. It returns true
-** if such a lock exists and false otherwise.
+** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
+** pointer parameter, true if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
** VFS implementations to directly control an open file using the
@@ -1118,6 +1142,7 @@ struct sqlite3_file {
** [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** [SQLITE_IOCAP_IMMUTABLE]
** [SQLITE_IOCAP_BATCH_ATOMIC]
+** [SQLITE_IOCAP_SUBPAGE_READ]
**
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1395,6 +1420,11 @@ struct sqlite3_io_methods {
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
+** [[SQLITE_FCNTL_NULL_IO]]
+** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor
+** or file handle for the [sqlite3_file] object such that it will no longer
+** read or write to the database file.
+**
** [[SQLITE_FCNTL_WAL_BLOCK]]
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
** be advantageous to block on the next WAL lock if the lock is not immediately
@@ -1497,7 +1527,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]]
@@ -1548,6 +1578,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
+#define SQLITE_FCNTL_NULL_IO 43
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1962,20 +1993,23 @@ SQLITE_API int sqlite3_os_end(void);
** must ensure that no other SQLite interfaces are invoked by other
** threads while sqlite3_config() is running.
**
-** The sqlite3_config() interface
-** may only be invoked prior to library initialization using
-** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
-** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
-** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
-** Note, however, that ^sqlite3_config() can be called as part of the
-** implementation of an application-defined [sqlite3_os_init()].
-**
** The first argument to sqlite3_config() is an integer
** [configuration option] that determines
** what property of SQLite is to be configured. Subsequent arguments
** vary depending on the [configuration option]
** in the first argument.
**
+** For most configuration options, the sqlite3_config() interface
+** may only be invoked prior to library initialization using
+** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
+** The exceptional configuration options that may be invoked at any time
+** are called "anytime configuration options".
+** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
+** [sqlite3_shutdown()] with a first argument that is not an anytime
+** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE.
+** Note, however, that ^sqlite3_config() can be called as part of the
+** implementation of an application-defined [sqlite3_os_init()].
+**
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
** ^If the option is unknown or SQLite is unable to set the option
** then this routine returns a non-zero [error code].
@@ -2083,6 +2117,23 @@ struct sqlite3_mem_methods {
** These constants are the available integer configuration options that
** can be passed as the first argument to the [sqlite3_config()] interface.
**
+** Most of the configuration options for sqlite3_config()
+** will only work if invoked prior to [sqlite3_initialize()] or after
+** [sqlite3_shutdown()]. The few exceptions to this rule are called
+** "anytime configuration options".
+** ^Calling [sqlite3_config()] with a first argument that is not an
+** anytime configuration option in between calls to [sqlite3_initialize()] and
+** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE.
+**
+** The set of anytime configuration options can change (by insertions
+** and/or deletions) from one release of SQLite to the next.
+** As of SQLite version 3.42.0, the complete set of anytime configuration
+** options is:
+**
+** - SQLITE_CONFIG_LOG
+**
- SQLITE_CONFIG_PCACHE_HDRSZ
+**
+**
** New configuration options may be added in future releases of SQLite.
** Existing configuration options might be discontinued. Applications
** should check the return code from [sqlite3_config()] to make sure that
@@ -2413,7 +2464,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.
**
@@ -2427,30 +2478,46 @@ struct sqlite3_mem_methods {
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
** compile-time option is not set, then the default maximum is 1073741824.
+**
+** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
+** SQLITE_CONFIG_ROWID_IN_VIEW
+** The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
+** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
+** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
+** defaults to on. This configuration option queries the current setting or
+** changes the setting to off or on. The argument is a pointer to an integer.
+** If that integer initially holds a value of 1, then the ability for VIEWs to
+** have ROWIDs is activated. If the integer initially holds zero, then the
+** ability is deactivated. Any other initial value for the integer leaves the
+** setting unchanged. After changes, if any, the integer is written with
+** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
+** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
+** recommended case) then the integer is always filled with zero, regardless
+** if its initial value.
**
*/
-#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
-#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
-#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
-#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
-#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
-#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */
-#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
-#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
-#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
-#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
-#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
-#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
-#define SQLITE_CONFIG_PCACHE 14 /* no-op */
-#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
-#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
-#define SQLITE_CONFIG_URI 17 /* int */
-#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
-#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
+#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
+#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
+#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_SCRATCH 6 /* 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 */
@@ -2458,12 +2525,21 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
+#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
-** can be passed as the second argument to the [sqlite3_db_config()] interface.
+** can be passed as the second parameter to the [sqlite3_db_config()] interface.
+**
+** The [sqlite3_db_config()] interface is a var-args functions. It takes a
+** variable number of parameters, though always at least two. The number of
+** parameters passed into sqlite3_db_config() depends on which of these
+** constants is given as the second parameter. This documentation page
+** refers to parameters beyond the second as "arguments". Thus, when this
+** page says "the N-th argument" it means "the N-th parameter past the
+** configuration option" or "the (N+2)-th parameter to sqlite3_db_config()".
**
** New configuration options may be added in future releases of SQLite.
** Existing configuration options might be discontinued. Applications
@@ -2475,8 +2551,14 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** - SQLITE_DBCONFIG_LOOKASIDE
-** - ^This option takes three additional arguments that determine the
-** [lookaside memory allocator] configuration for the [database connection].
+**
- The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the
+** configuration of the lookaside memory allocator within a database
+** connection.
+** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are not
+** in the [DBCONFIG arguments|usual format].
+** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two,
+** so that a call to [sqlite3_db_config()] that uses SQLITE_DBCONFIG_LOOKASIDE
+** should have a total of five parameters.
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
** pointer to a memory buffer to use for lookaside memory.
** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
@@ -2499,7 +2581,8 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
**
- SQLITE_DBCONFIG_ENABLE_FKEY
** - ^This option is used to enable or disable the enforcement of
-** [foreign key constraints]. There should be two additional arguments.
+** [foreign key constraints]. This is the same setting that is
+** enabled or disabled by the [PRAGMA foreign_keys] statement.
** The first argument is an integer which is 0 to disable FK enforcement,
** positive to enable FK enforcement or negative to leave FK enforcement
** unchanged. The second parameter is a pointer to an integer into which
@@ -2521,13 +2604,13 @@ struct sqlite3_mem_methods {
**
Originally this option disabled all triggers. ^(However, since
** SQLite version 3.35.0, TEMP triggers are still allowed even if
** this option is off. So, in other words, this option now only disables
-** triggers in the main database schema or in the schemas of ATTACH-ed
+** triggers in the main database schema or in the schemas of [ATTACH]-ed
** databases.)^
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** - SQLITE_DBCONFIG_ENABLE_VIEW
** - ^This option is used to enable or disable [CREATE VIEW | views].
-** There should be two additional arguments.
+** There must be two additional arguments.
** The first argument is an integer which is 0 to disable views,
** positive to enable views or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
@@ -2546,7 +2629,7 @@ struct sqlite3_mem_methods {
**
- ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
-** There should be two additional arguments.
+** There must be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
@@ -2561,7 +2644,7 @@ struct sqlite3_mem_methods {
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
-** There should be two additional arguments.
+** There must be two additional arguments.
** When the first argument to this interface is 1, then only the C-API is
** enabled and the SQL function remains disabled. If the first argument to
** this interface is 0, then both the C-API and the SQL function are disabled.
@@ -2575,23 +2658,30 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_MAINDBNAME]]
- SQLITE_DBCONFIG_MAINDBNAME
** - ^This option is used to change the name of the "main" database
-** schema. ^The sole argument is a pointer to a constant UTF8 string
-** which will become the new schema name in place of "main". ^SQLite
-** does not make a copy of the new main schema name string, so the application
-** must ensure that the argument passed into this DBCONFIG option is unchanged
-** until after the database connection closes.
+** schema. This option does not follow the
+** [DBCONFIG arguments|usual SQLITE_DBCONFIG argument format].
+** This option takes exactly one additional argument so that the
+** [sqlite3_db_config()] call has a total of three parameters. The
+** extra argument must be a pointer to a constant UTF8 string which
+** will become the new schema name in place of "main". ^SQLite does
+** not make a copy of the new main schema name string, so the application
+** must ensure that the argument passed into SQLITE_DBCONFIG MAINDBNAME
+** is unchanged until after the database connection closes.
**
**
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** - SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
-** - Usually, when a database in wal mode is closed or detached from a
-** database handle, SQLite checks if this will mean that there are now no
-** connections at all to the database. If so, it performs a checkpoint
-** operation before closing the connection. This option may be used to
-** override this behaviour. The first parameter passed to this operation
-** is an integer - positive to disable checkpoints-on-close, or zero (the
-** default) to enable them, and negative to leave the setting unchanged.
-** The second parameter is a pointer to an integer
+**
- Usually, when a database in [WAL mode] is closed or detached from a
+** database handle, SQLite checks if if there are other connections to the
+** same database, and if there are no other database connection (if the
+** connection being closed is the last open connection to the database),
+** then SQLite performs a [checkpoint] before closing the connection and
+** deletes the WAL file. The SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE option can
+** be used to override that behavior. The first argument passed to this
+** operation (the third parameter to [sqlite3_db_config()]) is an integer
+** which is positive to disable checkpoints-on-close, or zero (the default)
+** to enable them, and negative to leave the setting unchanged.
+** The second argument (the fourth parameter) is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
**
@@ -2685,7 +2775,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
@@ -2694,7 +2784,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
@@ -2703,7 +2793,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
@@ -2723,7 +2813,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
@@ -2732,7 +2822,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
@@ -2741,9 +2831,110 @@ 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
+** - The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
+** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
+** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
+** statistics. For statistics to be collected, the flag must be set on
+** the database handle both when the SQL statement is prepared and when it
+** is stepped. The flag is set (collection of statistics is enabled)
+** by default.
This option takes two arguments: an integer and a pointer to
+** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the statement scanstatus option. If the second argument
+** is not NULL, then the value of the statement scanstatus setting after
+** processing the first argument is written into the integer that the second
+** argument points to.
**
+**
+** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]]
+** - SQLITE_DBCONFIG_REVERSE_SCANORDER
+** - The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order
+** in which tables and indexes are scanned so that the scans start at the end
+** and work toward the beginning rather than starting at the beginning and
+** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
+** same as setting [PRAGMA reverse_unordered_selects].
This option takes
+** two arguments which are an integer and a pointer to an integer. The first
+** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
+** reverse scan order flag, respectively. If the second argument is not NULL,
+** then 0 or 1 is written into the integer that the second argument points to
+** depending on if the reverse scan order flag is set after processing the
+** first argument.
+**
+**
+** [[SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]]
+** - SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE
+** - The SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE option enables or disables
+** the ability of the [ATTACH DATABASE] SQL command to create a new database
+** file if the database filed named in the ATTACH command does not already
+** exist. This ability of ATTACH to create a new database is enabled by
+** default. Applications can disable or reenable the ability for ATTACH to
+** create new database files using this DBCONFIG option.
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the attach-create flag, respectively. If the second
+** argument is not NULL, then 0 or 1 is written into the integer that the
+** second argument points to depending on if the attach-create flag is set
+** after processing the first argument.
+**
+**
+** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]]
+** - SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE
+** - The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the
+** ability of the [ATTACH DATABASE] SQL command to open a database for writing.
+** This capability is enabled by default. Applications can disable or
+** reenable this capability using the current DBCONFIG option. If the
+** the this capability is disabled, the [ATTACH] command will still work,
+** but the database will be opened read-only. If this option is disabled,
+** then the ability to create a new database using [ATTACH] is also disabled,
+** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]
+** option.
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the ability to ATTACH another database for writing,
+** respectively. If the second argument is not NULL, then 0 or 1 is written
+** into the integer to which the second argument points, depending on whether
+** the ability to ATTACH a read/write database is enabled or disabled
+** after processing the first argument.
+**
+**
+** [[SQLITE_DBCONFIG_ENABLE_COMMENTS]]
+** - SQLITE_DBCONFIG_ENABLE_COMMENTS
+** - The SQLITE_DBCONFIG_ENABLE_COMMENTS option enables or disables the
+** ability to include comments in SQL text. Comments are enabled by default.
+** An application can disable or reenable comments in SQL text using this
+** DBCONFIG option.
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the ability to use comments in SQL text,
+** respectively. If the second argument is not NULL, then 0 or 1 is written
+** into the integer that the second argument points to depending on if
+** comments are allowed in SQL text after processing the first argument.
+**
+**
**
+**
+** [[DBCONFIG arguments]] Arguments To SQLITE_DBCONFIG Options
+**
+** Most of the SQLITE_DBCONFIG options take two arguments, so that the
+** overall call to [sqlite3_db_config()] has a total of four parameters.
+** The first argument (the third parameter to sqlite3_db_config()) is a integer.
+** The second argument is a pointer to an integer. If the first argument is 1,
+** then the option becomes enabled. If the first integer argument is 0, then the
+** option is disabled. If the first argument is -1, then the option setting
+** is unchanged. The second argument, the pointer to an integer, may be NULL.
+** If the second argument is not NULL, then a value of 0 or 1 is written into
+** the integer to which the second argument points, depending on whether the
+** setting is disabled or enabled after applying any changes specified by
+** the first argument.
+**
+**
While most SQLITE_DBCONFIG options use the argument format
+** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME]
+** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the
+** documentation of those exceptional options for details.
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
@@ -2763,7 +2954,12 @@ 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_MAX 1017 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
+#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -2855,10 +3051,14 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
** The two functions are identical except for the type of the return value
-** and that if the number of rows modified by the most recent INSERT, UPDATE
+** and that if the number of rows modified by the most recent INSERT, UPDATE,
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** type of SQL statement does not modify the value returned by these functions.
+** For the purposes of this interface, a CREATE TABLE AS SELECT statement
+** does not count as an INSERT, UPDATE or DELETE statement and hence the rows
+** added to the new table by the CREATE TABLE AS SELECT statement are not
+** counted.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
@@ -2988,6 +3188,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*);
@@ -3537,8 +3738,8 @@ SQLITE_API int sqlite3_set_authorizer(
#define SQLITE_RECURSIVE 33 /* NULL NULL */
/*
-** CAPI3REF: Tracing And Profiling Functions
-** METHOD: sqlite3
+** CAPI3REF: Deprecated Tracing And Profiling Functions
+** DEPRECATED
**
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
** instead of the routines described here.
@@ -3641,8 +3842,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
@@ -3800,8 +4003,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** [[OPEN_EXRESCODE]] ^(
[SQLITE_OPEN_EXRESCODE]
** The database connection comes up in "extended result code mode".
-** In other words, the database behaves has if
-** [sqlite3_extended_result_codes(db,1)] where called on the database
+** In other words, the database behaves as if
+** [sqlite3_extended_result_codes(db,1)] were called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.
@@ -4011,7 +4214,7 @@ SQLITE_API int sqlite3_open_v2(
** 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()].
**
@@ -4124,7 +4327,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
@@ -4203,14 +4406,17 @@ 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.
+** text that describes the error, as either UTF-8 or UTF-16 respectively,
+** or NULL if no error message is available.
+** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
** ^(Memory to hold the error message string is managed internally.
** The application does not need to worry about freeing the result.
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.)^
**
-** ^The sqlite3_errstr() interface returns the English-language text
-** that describes the [result code], as UTF-8.
+** ^The sqlite3_errstr(E) interface returns the English-language text
+** that describes the [result code] E, as UTF-8, or NULL if E is not an
+** result code for which a text error message is available.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
@@ -4412,11 +4618,22 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
+**
+** [[SQLITE_PREPARE_DONT_LOG]] SQLITE_PREPARE_DONT_LOG
+** The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
+** errors from being sent to the error log defined by
+** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
+** compiles to see if some SQL syntax is well-formed, without generating
+** messages on the global error log when it is not. If the test compile
+** fails, the sqlite3_prepare_v3() call returns the same error indications
+** with or without this flag; it just omits the call to [sqlite3_log()] that
+** logs the error.
**
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
#define SQLITE_PREPARE_NO_VTAB 0x04
+#define SQLITE_PREPARE_DONT_LOG 0x10
/*
** CAPI3REF: Compiling An SQL Statement
@@ -4449,13 +4666,17 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
-** first zero terminator. ^If nByte is positive, then it is the
-** number of bytes read from zSql. ^If nByte is zero, then no prepared
+** first zero terminator. ^If nByte is positive, then it is the maximum
+** number of bytes read from zSql. When nByte is positive, zSql is read
+** up to the first zero terminator or until the nByte bytes have been read,
+** whichever comes first. ^If nByte is zero, then no prepared
** statement is generated.
** If the caller knows that the supplied string is nul-terminated, then
** there is a small performance advantage to passing an nByte parameter that
** is the number of bytes in the input string including
** the nul-terminator.
+** Note that nByte measure the length of the input in bytes, not
+** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -4671,6 +4892,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
@@ -4834,7 +5090,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
@@ -5513,20 +5769,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}
@@ -5737,7 +6006,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.
**
@@ -5773,13 +6042,36 @@ SQLITE_API int sqlite3_create_window_function(
**
**
** [[SQLITE_SUBTYPE]] SQLITE_SUBTYPE
-** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
+** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
-** Specifying this flag makes no difference for scalar or aggregate user
-** functions. However, if it is not specified for a user-defined window
-** function, then any sub-types belonging to arguments passed to the window
-** function may be discarded before the window function is called (i.e.
-** sqlite3_value_subtype() will always return 0).
+** This flag instructs SQLite to omit some corner-case optimizations that
+** might disrupt the operation of the [sqlite3_value_subtype()] function,
+** causing it to return zero rather than the correct subtype().
+** All SQL functions that invoke [sqlite3_value_subtype()] should have this
+** property. If the SQLITE_SUBTYPE property is omitted, then the return
+** value from [sqlite3_value_subtype()] might sometimes be zero even though
+** a non-zero subtype was specified by the function argument expression.
+**
+** [[SQLITE_RESULT_SUBTYPE]] SQLITE_RESULT_SUBTYPE
+** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
+** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
+** result.
+** Every function that invokes [sqlite3_result_subtype()] should have this
+** property. If it does not, then the call to [sqlite3_result_subtype()]
+** might become a no-op if the function is used as term in an
+** [expression index]. On the other hand, SQL functions that never invoke
+** [sqlite3_result_subtype()] should avoid setting this property, as the
+** purpose of this property is to disable certain optimizations that are
+** incompatible with subtypes.
+**
+** [[SQLITE_SELFORDER1]] SQLITE_SELFORDER1
+** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
+** that internally orders the values provided to the first argument. The
+** ordered-set aggregate SQL notation with a single ORDER BY term can be
+** used to invoke this function. If the ordered-set aggregate notation is
+** used on a function that lacks this flag, then an error is raised. Note
+** that the ordered-set aggregate syntax is only available if SQLite is
+** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
**
**
*/
@@ -5787,6 +6079,8 @@ SQLITE_API int sqlite3_create_window_function(
#define SQLITE_DIRECTONLY 0x000080000
#define SQLITE_SUBTYPE 0x000100000
#define SQLITE_INNOCUOUS 0x000200000
+#define SQLITE_RESULT_SUBTYPE 0x001000000
+#define SQLITE_SELFORDER1 0x002000000
/*
** CAPI3REF: Deprecated Functions
@@ -5983,6 +6277,12 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
** information can be used to pass a limited amount of context from
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
+**
+** Every [application-defined SQL function] that invokes this interface
+** should include the [SQLITE_SUBTYPE] property in the text
+** encoding argument when the function is [sqlite3_create_function|registered].
+** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
+** might return zero instead of the upstream subtype in some corner cases.
*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
@@ -6081,48 +6381,56 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** METHOD: sqlite3_context
**
** These functions may be used by (non-aggregate) SQL functions to
-** associate metadata with argument values. If the same value is passed to
-** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. An example
-** of where this might be useful is in a regular-expression matching
-** function. The compiled version of the regular expression can be stored as
-** metadata associated with the pattern string.
+** 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
**
- ^(when sqlite3_set_auxdata() is invoked again on the same
** parameter)^, or
**
- ^(during the original sqlite3_set_auxdata() call when a memory
-** allocation error occurs.)^
+** allocation error occurs.)^
+** - ^(during the original sqlite3_set_auxdata() call if the function
+** is evaluated during query planning instead of during query execution,
+** as sometimes happens with [SQLITE_ENABLE_STAT4].)^
**
-** Note the last bullet in particular. The destructor X in
+** Note the last two bullets in particular. The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
-** sqlite3_set_auxdata() has been called.
-**
-** ^(In practice, metadata is preserved between function calls for
+** sqlite3_set_auxdata() has been called. Furthermore, a call to
+** sqlite3_get_auxdata() that occurs immediately after a corresponding call
+** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
+** condition occurred during the sqlite3_set_auxdata() call or if the
+** function is being evaluated during query planning rather than during
+** query execution.
+**
+** ^(In practice, auxiliary data is preserved between function calls for
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
@@ -6132,10 +6440,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
@@ -6337,6 +6702,20 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.
+**
+** Every [application-defined SQL function] that invokes this interface
+** should include the [SQLITE_RESULT_SUBTYPE] property in its
+** text encoding argument when the SQL function is
+** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE]
+** property is omitted from the function that invokes sqlite3_result_subtype(),
+** then in some cases the sqlite3_result_subtype() might fail to set
+** the result subtype.
+**
+** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
+** SQL function that invokes the sqlite3_result_subtype() interface
+** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
+** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
+** by default.
*/
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
@@ -6508,6 +6887,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);
@@ -6761,7 +7147,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.
@@ -6893,7 +7279,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
@@ -6959,6 +7345,12 @@ SQLITE_API int sqlite3_autovacuum_pages(
** The exceptions defined in this paragraph might change in a future
** release of SQLite.
**
+** Whether the update hook is invoked before or after the
+** corresponding change is currently unspecified and may differ
+** depending on the type of change. Do not rely on the order of the
+** hook call with regards to the final result of the operation which
+** triggers the hook.
+**
** The update hook implementation must not do anything that will modify
** the database connection that invoked the update hook. Any actions
** to modify the database connection must be deferred until after the
@@ -7412,6 +7804,10 @@ struct sqlite3_module {
/* The methods above are in versions 1 and 2 of the sqlite_module object.
** Those below are for version 3 and greater. */
int (*xShadowName)(const char*);
+ /* The methods above are in versions 1 through 3 of the sqlite_module object.
+ ** Those below are for version 4 and greater. */
+ int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
+ const char *zTabName, int mFlags, char **pzErr);
};
/*
@@ -7489,9 +7885,11 @@ struct sqlite3_module {
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
-** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
-** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-** assumes that the strategy may visit at most one row.
+** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
+** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
+** output to show the idxNum has hex instead of as decimal. Another flag is
+** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
+** return at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7555,7 +7953,9 @@ struct sqlite3_index_info {
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
-#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */
+ /* in EXPLAIN QUERY PLAN */
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
@@ -7899,7 +8299,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
@@ -8126,18 +8526,20 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
**
** ^(Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
-** will always return SQLITE_BUSY. The SQLite core only ever uses
-** sqlite3_mutex_try() as an optimization so this is acceptable
-** behavior.)^
+** will always return SQLITE_BUSY. In most cases the SQLite core only uses
+** sqlite3_mutex_try() as an optimization, so this is acceptable
+** behavior. The exceptions are unix builds that set the
+** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working
+** sqlite3_mutex_try() is required.)^
**
** ^The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
** is undefined if the mutex is not currently entered by the
** calling thread or is not currently allocated.
**
-** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
-** sqlite3_mutex_leave() is a NULL pointer, then all three routines
-** behave as no-ops.
+** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),
+** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer,
+** then any of the four routines behaves as a no-op.
**
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
*/
@@ -8379,6 +8781,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
@@ -8386,8 +8789,10 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ASSERT 12
#define SQLITE_TESTCTRL_ALWAYS 13
#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
+#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
+#define SQLITE_TESTCTRL_GETOPT 16
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
@@ -8407,7 +8812,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 /* NOT USED */
+#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -8420,7 +8826,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
** The sqlite3_keyword_count() interface returns the number of distinct
** keywords understood by SQLite.
**
-** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
+** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
** makes *Z point to that keyword expressed as UTF8 and writes the number
** of bytes in the keyword into *L. The string that *Z points to is not
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
@@ -9382,6 +9788,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+**
+** Alternatives To Using The Backup API
+**
+** Other techniques for safely creating a consistent backup of an SQLite
+** database include:
+**
+**
+** - The [VACUUM INTO] command.
+**
- The [sqlite3_rsync] utility program.
+**
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
@@ -9863,7 +10279,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.
**
@@ -9871,18 +10287,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
@@ -9989,24 +10415,45 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
**
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
** that the query planner does not need the rows returned in any particular
-** order, as long as rows with the same values in all "aOrderBy" columns
-** are adjacent.)^ ^(Furthermore, only a single row for each particular
-** combination of values in the columns identified by the "aOrderBy" field
-** needs to be returned.)^ ^It is always ok for two or more rows with the same
-** values in all "aOrderBy" columns to be returned, as long as all such rows
-** are adjacent. ^The virtual table may, if it chooses, omit extra rows
-** that have the same value for all columns identified by "aOrderBy".
-** ^However omitting the extra rows is optional.
+** order, as long as rows with the same values in all columns identified
+** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
+** contain the same values for all columns identified by "colUsed", all but
+** one such row may optionally be omitted from the result.)^
+** The virtual table is not required to omit rows that are duplicates
+** over the "colUsed" columns, but if the virtual table can do that without
+** too much extra effort, it could potentially help the query to run faster.
** This mode is used for a DISTINCT query.
**
-** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
-** that the query planner needs only distinct rows but it does need the
-** rows to be sorted.)^ ^The virtual table implementation is free to omit
-** rows that are identical in all aOrderBy columns, if it wants to, but
-** it is not required to omit any rows. This mode is used for queries
+** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
+** virtual table must return rows in the order defined by "aOrderBy" as
+** if the sqlite3_vtab_distinct() interface had returned 0. However if
+** two or more rows in the result have the same values for all columns
+** identified by "colUsed", then all but one such row may optionally be
+** omitted.)^ Like when the return value is 2, the virtual table
+** is not required to omit rows that are duplicates over the "colUsed"
+** columns, but if the virtual table can do that without
+** too much extra effort, it could potentially help the query to run faster.
+** This mode is used for queries
** that have both DISTINCT and ORDER BY clauses.
**
**
+**
The following table summarizes the conditions under which the
+** virtual table is allowed to set the "orderByConsumed" flag based on
+** the value returned by sqlite3_vtab_distinct(). This table is a
+** restatement of the previous four paragraphs:
+**
+**
+**
+** sqlite3_vtab_distinct() return value
+** | Rows are returned in aOrderBy order
+** | Rows with the same value in all aOrderBy columns are adjacent
+** | Duplicates over all colUsed columns may be omitted
+** |
0 | yes | yes | no
+** |
1 | no | yes | no
+** |
2 | no | yes | yes
+** |
3 | yes | yes | yes
+** |
+**
** ^For the purposes of comparing virtual table output values to see if the
** values are same value for sorting purposes, two NULL values are considered
** to be the same. In other words, the comparison operator is "IS"
@@ -10043,7 +10490,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
@@ -10472,7 +10919,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
@@ -10550,6 +10997,14 @@ typedef struct sqlite3_snapshot {
** If there is not already a read-transaction open on schema S when
** this function is called, one is opened automatically.
**
+** If a read-transaction is opened by this function, then it is guaranteed
+** that the returned snapshot object may not be invalidated by a database
+** writer or checkpointer until after the read-transaction is closed. This
+** is not guaranteed if a read-transaction is already open when this
+** function is called. In that case, any subsequent write or checkpoint
+** operation on the database may invalidate the returned snapshot handle,
+** even while the read-transaction remains open.
+**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
@@ -10707,8 +11162,9 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
/*
** CAPI3REF: Serialize a database
**
-** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
-** that is a serialization of the S database on [database connection] D.
+** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
+** memory that is a serialization of the S database on
+** [database connection] D. If S is a NULL pointer, the main database is used.
** If P is not a NULL pointer, then the size of the database in bytes
** is written into *P.
**
@@ -10733,6 +11189,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.
@@ -10781,6 +11244,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.
@@ -10789,6 +11255,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.
@@ -10841,8 +11314,6 @@ 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 */
# ifndef SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION
# endif
@@ -10854,7 +11325,7 @@ SQLITE_API int sqlite3_deserialize(
#if 0
} /* End of the 'extern "C"' block */
#endif
-#endif /* SQLITE3_H */
+/* #endif for SQLITE3_H will be added by mksqlite3.tcl */
/******** Begin file sqlite3rtree.h *********/
/*
@@ -11057,16 +11528,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
@@ -11082,12 +11557,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
@@ -11848,6 +12332,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
**
@@ -11894,6 +12390,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
@@ -11962,16 +12490,45 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** If the new changeset contains changes to a table that is already present
** in the changegroup, then the number of columns and the position of the
** primary key columns for the table must be consistent. If this is not the
-** case, this function fails with SQLITE_SCHEMA. If the input changeset
-** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
-** returned. Or, if an out-of-memory condition occurs during processing, this
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the 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);
+/*
+** CAPI3REF: Add A Single Change To A Changegroup
+** METHOD: sqlite3_changegroup
+**
+** This function adds the single change currently indicated by the iterator
+** passed as the second argument to the changegroup object. The rules for
+** adding the change are just as described for [sqlite3changegroup_add()].
+**
+** If the change is successfully added to the changegroup, SQLITE_OK is
+** returned. Otherwise, an SQLite error code is returned.
+**
+** The iterator must point to a valid entry when this function is called.
+** If it does not, SQLITE_ERROR is returned and no change is added to the
+** changegroup. Additionally, the iterator must not have been opened with
+** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
+** returned.
+*/
+SQLITE_API int sqlite3changegroup_add_change(
+ sqlite3_changegroup*,
+ sqlite3_changeset_iter*
+);
+
+
+
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
** METHOD: sqlite3_changegroup
@@ -12220,9 +12777,30 @@ SQLITE_API int sqlite3changeset_apply_v2(
** Invert the changeset before applying it. This is equivalent to inverting
** a changeset using sqlite3changeset_invert() before applying it. It is
** an error to specify this flag with a patchset.
+**
+** SQLITE_CHANGESETAPPLY_IGNORENOOP
+** Do not invoke the conflict handler callback for any changes that
+** would not actually modify the database even if they were applied.
+** Specifically, this means that the conflict handler is not invoked
+** for:
+**
+** - a delete change if the row being deleted cannot be found,
+**
- an update change if the modified fields are already set to
+** their new values in the conflicting row, or
+**
- an insert change if all fields of the conflicting row match
+** the row being inserted.
+**
+**
+** SQLITE_CHANGESETAPPLY_FKNOACTION
+** If this flag it set, then all foreign key constraints in the target
+** database behave as if they were declared with "ON UPDATE NO ACTION ON
+** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
+** or SET DEFAULT.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
+#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
+#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -12755,8 +13333,8 @@ struct Fts5PhraseIter {
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
-** Return a copy of the context pointer the extension function was
-** registered with.
+** Return a copy of the pUserData pointer passed to the xCreateFunction()
+** API when the extension function was registered.
**
** xColumnTotalSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
@@ -12788,8 +13366,11 @@ struct Fts5PhraseIter {
** created with the "columnsize=0" option.
**
** xColumnText:
-** This function attempts to retrieve the text of column iCol of the
-** current document. If successful, (*pz) is set to point to a buffer
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the text of column iCol of
+** the current document. If successful, (*pz) is set to point to a buffer
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
** if an error occurs, an SQLite error code is returned and the final values
@@ -12799,8 +13380,10 @@ struct Fts5PhraseIter {
** Returns the number of phrases in the current query expression.
**
** xPhraseSize:
-** Returns the number of tokens in phrase iPhrase of the query. Phrases
-** are numbered starting from zero.
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of phrases in the current query, as returned by xPhraseCount,
+** 0 is returned. Otherwise, this function returns the number of tokens in
+** phrase iPhrase of the query. Phrases are numbered starting from zero.
**
** xInstCount:
** Set *pnInst to the total number of occurrences of all phrases within
@@ -12816,12 +13399,13 @@ struct Fts5PhraseIter {
** Query for the details of phrase match iIdx within the current row.
** Phrase matches are numbered starting from zero, so the iIdx argument
** should be greater than or equal to zero and smaller than the value
-** output by xInstCount().
+** output by xInstCount(). If iIdx is less than zero or greater than
+** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
**
-** Usually, output parameter *piPhrase is set to the phrase number, *piCol
+** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. Returns SQLITE_OK if successful, or an error
-** code (i.e. SQLITE_NOMEM) if an error occurs.
+** first token of the phrase. SQLITE_OK is returned if successful, or an
+** error code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -12847,6 +13431,10 @@ struct Fts5PhraseIter {
** Invoking Api.xUserData() returns a copy of the pointer passed as
** the third argument to pUserData.
**
+** If parameter iPhrase is less than zero, or greater than or equal to
+** the number of phrases in the query, as returned by xPhraseCount(),
+** this function returns SQLITE_RANGE.
+**
** If the callback function returns any value other than SQLITE_OK, the
** query is abandoned and the xQueryPhrase function returns immediately.
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
@@ -12928,6 +13516,10 @@ struct Fts5PhraseIter {
** (i.e. if it is a contentless table), then this API always iterates
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+** In all cases, matches are visited in (column ASC, offset ASC) order.
+** i.e. all those in column 0, sorted by offset, followed by those in
+** column 1, etc.
+**
** xPhraseNext()
** See xPhraseFirst above.
**
@@ -12961,9 +13553,80 @@ struct Fts5PhraseIter {
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
+**
+** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
+** This is used to access token iToken of phrase iPhrase of the current
+** query. Before returning, output parameter *ppToken is set to point
+** to a buffer containing the requested token, and *pnToken to the
+** size of this buffer in bytes.
+**
+** If iPhrase or iToken are less than zero, or if iPhrase is greater than
+** or equal to the number of phrases in the query as reported by
+** xPhraseCount(), or if iToken is equal to or greater than the number of
+** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
+ are both zeroed.
+**
+** The output text is not a copy of the query text that specified the
+** token. It is the output of the tokenizer module. For tokendata=1
+** tables, this includes any embedded 0x00 and trailing data.
+**
+** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
+** This is used to access token iToken of phrase hit iIdx within the
+** current row. If iIdx is less than zero or greater than or equal to the
+** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
+** output variable (*ppToken) is set to point to a buffer containing the
+** matching document token, and (*pnToken) to the size of that buffer in
+** bytes.
+**
+** The output text is not a copy of the document text that was tokenized.
+** It is the output of the tokenizer module. For tokendata=1 tables, this
+** includes any embedded 0x00 and trailing data.
+**
+** This API may be slow in some cases if the token identified by parameters
+** iIdx and iToken matched a prefix token in the query. In most cases, the
+** first call to this API for each prefix token in the query is forced
+** to scan the portion of the full-text index that matches the prefix
+** token to collect the extra data required by this API. If the prefix
+** token matches a large number of token instances in the document set,
+** this may be a performance problem.
+**
+** If the user knows in advance that a query may use this API for a
+** prefix token, FTS5 may be configured to collect all required data as part
+** of the initial querying of the full-text index, avoiding the second scan
+** entirely. This also causes prefix queries that do not use this API to
+** run more slowly and use more memory. FTS5 may be configured in this way
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
+** option, or on a per-query basis using the
+** [fts5_insttoken | fts5_insttoken()] user function.
+**
+** This API can be quite slow if used with an FTS5 table created with the
+** "detail=none" or "detail=column" option.
+**
+** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the locale associated
+** with column iCol of the current row. Usually, there is no associated
+** locale, and output parameters (*pzLocale) and (*pnLocale) are set
+** to NULL and 0, respectively. However, if the fts5_locale() function
+** was used to associate a locale with the value when it was inserted
+** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+** is set to the size in bytes of the buffer, not including the
+** nul-terminator.
+**
+** If successful, SQLITE_OK is returned. Or, if an error occurs, an
+** SQLite error code is returned. The final value of the output parameters
+** is undefined in this case.
+**
+** xTokenize_v2:
+** Tokenize text using the tokenizer belonging to the FTS5 table. This
+** API is the same as the xTokenize() API, except that it allows a tokenizer
+** locale to be specified.
*/
struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
+ int iVersion; /* Currently always set to 4 */
void *(*xUserData)(Fts5Context*);
@@ -12998,6 +13661,22 @@ struct Fts5ExtensionApi {
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
+
+ /* Below this point are iVersion>=3 only */
+ int (*xQueryToken)(Fts5Context*,
+ int iPhrase, int iToken,
+ const char **ppToken, int *pnToken
+ );
+ int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+
+ /* Below this point are iVersion>=4 only */
+ int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+ int (*xTokenize_v2)(Fts5Context*,
+ const char *pText, int nText, /* Text to tokenize */
+ const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
+ void *pCtx, /* Context passed to xToken() */
+ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
+ );
};
/*
@@ -13018,7 +13697,7 @@ struct Fts5ExtensionApi {
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
-** pointer provided by the application when the fts5_tokenizer object
+** pointer provided by the application when the fts5_tokenizer_v2 object
** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
@@ -13042,7 +13721,7 @@ struct Fts5ExtensionApi {
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
**
-** The second argument indicates the reason that FTS5 is requesting
+** The third argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
@@ -13066,6 +13745,13 @@ struct Fts5ExtensionApi {
** on a columnsize=0 database.
**
**
+** The sixth and seventh arguments passed to xTokenize() - pLocale and
+** nLocale - are a pointer to a buffer containing the locale to use for
+** tokenization (e.g. "en_US") and its size in bytes, respectively. The
+** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+** which case nLocale is always 0) to indicate that the tokenizer should
+** use its default locale.
+**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
@@ -13089,6 +13775,30 @@ struct Fts5ExtensionApi {
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
+** If the tokenizer is registered using an fts5_tokenizer_v2 object,
+** then the xTokenize() method has two additional arguments - pLocale
+** and nLocale. These specify the locale that the tokenizer should use
+** for the current request. If pLocale and nLocale are both 0, then the
+** tokenizer should use its default locale. Otherwise, pLocale points to
+** an nLocale byte buffer containing the name of the locale to use as utf-8
+** text. pLocale is not nul-terminated.
+**
+** FTS5_TOKENIZER
+**
+** There is also an fts5_tokenizer object. This is an older, deprecated,
+** version of fts5_tokenizer_v2. It is similar except that:
+**
+**
+** - There is no "iVersion" field, and
+**
- The xTokenize() method does not take a locale argument.
+**
+**
+** Legacy fts5_tokenizer tokenizers must be registered using the
+** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+**
+** Tokenizer implementations registered using either API may be retrieved
+** using both xFindTokenizer() and xFindTokenizer_v2().
+**
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
@@ -13192,11 +13902,38 @@ 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;
+typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+struct fts5_tokenizer_v2 {
+ int iVersion; /* Currently always 2 */
+
+ int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+ void (*xDelete)(Fts5Tokenizer*);
+ int (*xTokenize)(Fts5Tokenizer*,
+ void *pCtx,
+ int flags, /* Mask of FTS5_TOKENIZE_* flags */
+ const char *pText, int nText,
+ const char *pLocale, int nLocale,
+ int (*xToken)(
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
+ const char *pToken, /* Pointer to buffer containing token */
+ int nToken, /* Size of token in bytes */
+ int iStart, /* Byte offset of token within input text */
+ int iEnd /* Byte offset of end of token within input text */
+ )
+ );
+};
+
+/*
+** New code should use the fts5_tokenizer_v2 type to define tokenizer
+** implementations. The following type is included for legacy applications
+** that still use it.
+*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -13216,6 +13953,7 @@ struct fts5_tokenizer {
);
};
+
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
@@ -13235,13 +13973,13 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
- int iVersion; /* Currently always set to 2 */
+ int iVersion; /* Currently always set to 3 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
fts5_api *pApi,
const char *zName,
- void *pContext,
+ void *pUserData,
fts5_tokenizer *pTokenizer,
void (*xDestroy)(void*)
);
@@ -13250,7 +13988,7 @@ struct fts5_api {
int (*xFindTokenizer)(
fts5_api *pApi,
const char *zName,
- void **ppContext,
+ void **ppUserData,
fts5_tokenizer *pTokenizer
);
@@ -13258,10 +13996,29 @@ struct fts5_api {
int (*xCreateFunction)(
fts5_api *pApi,
const char *zName,
- void *pContext,
+ void *pUserData,
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
+
+ /* APIs below this point are only available if iVersion>=3 */
+
+ /* Create a new tokenizer */
+ int (*xCreateTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void *pUserData,
+ fts5_tokenizer_v2 *pTokenizer,
+ void (*xDestroy)(void*)
+ );
+
+ /* Find an existing tokenizer */
+ int (*xFindTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void **ppUserData,
+ fts5_tokenizer_v2 **ppTokenizer
+ );
};
/*
@@ -13275,6 +14032,7 @@ struct fts5_api {
#endif /* _FTS5_H */
/******** End of fts5.h *********/
+#endif /* SQLITE3_H */
/************** End of sqlite3.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -13320,6 +14078,7 @@ struct fts5_api {
#ifndef SQLITE_MAX_LENGTH
# define SQLITE_MAX_LENGTH 1000000000
#endif
+#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
/*
** This is the maximum number of
@@ -13369,7 +14128,7 @@ struct fts5_api {
** 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
@@ -13385,9 +14144,13 @@ struct fts5_api {
/*
** The maximum number of arguments to an SQL function.
+**
+** This value has a hard upper limit of 32767 due to storage
+** constraints (it needs to fit inside a i16). We keep it
+** lower than that to prevent abuse.
*/
#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
+# define SQLITE_MAX_FUNCTION_ARG 1000
#endif
/*
@@ -13484,7 +14247,7 @@ struct fts5_api {
** max_page_count macro.
*/
#ifndef SQLITE_MAX_PAGE_COUNT
-# define SQLITE_MAX_PAGE_COUNT 1073741823
+# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */
#endif
/*
@@ -13519,8 +14282,8 @@ struct fts5_api {
#endif
/*
-** WAL mode depends on atomic aligned 32-bit loads and stores in a few
-** places. The following macros try to make this explicit.
+** A few places in the code require atomic load/store of aligned
+** integer values.
*/
#ifndef __has_extension
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
@@ -13576,15 +14339,22 @@ struct fts5_api {
#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
/*
@@ -13606,6 +14376,29 @@ struct fts5_api {
# endif
#endif
+/*
+** Enable SQLITE_USE_SEH by default on MSVC builds. Only omit
+** SEH support if the -DSQLITE_OMIT_SEH option is given.
+*/
+#if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH)
+# define SQLITE_USE_SEH 1
+#else
+# undef SQLITE_USE_SEH
+#endif
+
+/*
+** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly
+** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0
+*/
+#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1
+ /* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */
+# undef SQLITE_DIRECT_OVERFLOW_READ
+#else
+ /* In all other cases, enable */
+# define SQLITE_DIRECT_OVERFLOW_READ 1
+#endif
+
+
/*
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
** 0 means mutexes are permanently disable and the library is never
@@ -13874,6 +14667,8 @@ struct fts5_api {
# define SQLITE_OMIT_ALTERTABLE
#endif
+#define SQLITE_DIGIT_SEPARATOR '_'
+
/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
@@ -14039,135 +14834,135 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_OR 43
#define TK_AND 44
#define TK_IS 45
-#define TK_MATCH 46
-#define TK_LIKE_KW 47
-#define TK_BETWEEN 48
-#define TK_IN 49
-#define TK_ISNULL 50
-#define TK_NOTNULL 51
-#define TK_NE 52
-#define TK_EQ 53
-#define TK_GT 54
-#define TK_LE 55
-#define TK_LT 56
-#define TK_GE 57
-#define TK_ESCAPE 58
-#define TK_ID 59
-#define TK_COLUMNKW 60
-#define TK_DO 61
-#define TK_FOR 62
-#define TK_IGNORE 63
-#define TK_INITIALLY 64
-#define TK_INSTEAD 65
-#define TK_NO 66
-#define TK_KEY 67
-#define TK_OF 68
-#define TK_OFFSET 69
-#define TK_PRAGMA 70
-#define TK_RAISE 71
-#define TK_RECURSIVE 72
-#define TK_REPLACE 73
-#define TK_RESTRICT 74
-#define TK_ROW 75
-#define TK_ROWS 76
-#define TK_TRIGGER 77
-#define TK_VACUUM 78
-#define TK_VIEW 79
-#define TK_VIRTUAL 80
-#define TK_WITH 81
-#define TK_NULLS 82
-#define TK_FIRST 83
-#define TK_LAST 84
-#define TK_CURRENT 85
-#define TK_FOLLOWING 86
-#define TK_PARTITION 87
-#define TK_PRECEDING 88
-#define TK_RANGE 89
-#define TK_UNBOUNDED 90
-#define TK_EXCLUDE 91
-#define TK_GROUPS 92
-#define TK_OTHERS 93
-#define TK_TIES 94
-#define TK_GENERATED 95
-#define TK_ALWAYS 96
-#define TK_MATERIALIZED 97
-#define TK_REINDEX 98
-#define TK_RENAME 99
-#define TK_CTIME_KW 100
-#define TK_ANY 101
-#define TK_BITAND 102
-#define TK_BITOR 103
-#define TK_LSHIFT 104
-#define TK_RSHIFT 105
-#define TK_PLUS 106
-#define TK_MINUS 107
-#define TK_STAR 108
-#define TK_SLASH 109
-#define TK_REM 110
-#define TK_CONCAT 111
-#define TK_PTR 112
-#define TK_COLLATE 113
-#define TK_BITNOT 114
-#define TK_ON 115
-#define TK_INDEXED 116
-#define TK_STRING 117
-#define TK_JOIN_KW 118
-#define TK_CONSTRAINT 119
-#define TK_DEFAULT 120
-#define TK_NULL 121
-#define TK_PRIMARY 122
-#define TK_UNIQUE 123
-#define TK_CHECK 124
-#define TK_REFERENCES 125
-#define TK_AUTOINCR 126
-#define TK_INSERT 127
-#define TK_DELETE 128
-#define TK_UPDATE 129
-#define TK_SET 130
-#define TK_DEFERRABLE 131
-#define TK_FOREIGN 132
-#define TK_DROP 133
-#define TK_UNION 134
-#define TK_ALL 135
-#define TK_EXCEPT 136
-#define TK_INTERSECT 137
-#define TK_SELECT 138
-#define TK_VALUES 139
-#define TK_DISTINCT 140
-#define TK_DOT 141
-#define TK_FROM 142
-#define TK_JOIN 143
-#define TK_USING 144
-#define TK_ORDER 145
-#define TK_GROUP 146
-#define TK_HAVING 147
-#define TK_LIMIT 148
-#define TK_WHERE 149
-#define TK_RETURNING 150
-#define TK_INTO 151
-#define TK_NOTHING 152
-#define TK_FLOAT 153
-#define TK_BLOB 154
-#define TK_INTEGER 155
-#define TK_VARIABLE 156
-#define TK_CASE 157
-#define TK_WHEN 158
-#define TK_THEN 159
-#define TK_ELSE 160
-#define TK_INDEX 161
-#define TK_ALTER 162
-#define TK_ADD 163
-#define TK_WINDOW 164
-#define TK_OVER 165
-#define TK_FILTER 166
-#define TK_COLUMN 167
-#define TK_AGG_FUNCTION 168
-#define TK_AGG_COLUMN 169
-#define TK_TRUEFALSE 170
-#define TK_ISNOT 171
+#define TK_ISNOT 46
+#define TK_MATCH 47
+#define TK_LIKE_KW 48
+#define TK_BETWEEN 49
+#define TK_IN 50
+#define TK_ISNULL 51
+#define TK_NOTNULL 52
+#define TK_NE 53
+#define TK_EQ 54
+#define TK_GT 55
+#define TK_LE 56
+#define TK_LT 57
+#define TK_GE 58
+#define TK_ESCAPE 59
+#define TK_ID 60
+#define TK_COLUMNKW 61
+#define TK_DO 62
+#define TK_FOR 63
+#define TK_IGNORE 64
+#define TK_INITIALLY 65
+#define TK_INSTEAD 66
+#define TK_NO 67
+#define TK_KEY 68
+#define TK_OF 69
+#define TK_OFFSET 70
+#define TK_PRAGMA 71
+#define TK_RAISE 72
+#define TK_RECURSIVE 73
+#define TK_REPLACE 74
+#define TK_RESTRICT 75
+#define TK_ROW 76
+#define TK_ROWS 77
+#define TK_TRIGGER 78
+#define TK_VACUUM 79
+#define TK_VIEW 80
+#define TK_VIRTUAL 81
+#define TK_WITH 82
+#define TK_NULLS 83
+#define TK_FIRST 84
+#define TK_LAST 85
+#define TK_CURRENT 86
+#define TK_FOLLOWING 87
+#define TK_PARTITION 88
+#define TK_PRECEDING 89
+#define TK_RANGE 90
+#define TK_UNBOUNDED 91
+#define TK_EXCLUDE 92
+#define TK_GROUPS 93
+#define TK_OTHERS 94
+#define TK_TIES 95
+#define TK_GENERATED 96
+#define TK_ALWAYS 97
+#define TK_MATERIALIZED 98
+#define TK_REINDEX 99
+#define TK_RENAME 100
+#define TK_CTIME_KW 101
+#define TK_ANY 102
+#define TK_BITAND 103
+#define TK_BITOR 104
+#define TK_LSHIFT 105
+#define TK_RSHIFT 106
+#define TK_PLUS 107
+#define TK_MINUS 108
+#define TK_STAR 109
+#define TK_SLASH 110
+#define TK_REM 111
+#define TK_CONCAT 112
+#define TK_PTR 113
+#define TK_COLLATE 114
+#define TK_BITNOT 115
+#define TK_ON 116
+#define TK_INDEXED 117
+#define TK_STRING 118
+#define TK_JOIN_KW 119
+#define TK_CONSTRAINT 120
+#define TK_DEFAULT 121
+#define TK_NULL 122
+#define TK_PRIMARY 123
+#define TK_UNIQUE 124
+#define TK_CHECK 125
+#define TK_REFERENCES 126
+#define TK_AUTOINCR 127
+#define TK_INSERT 128
+#define TK_DELETE 129
+#define TK_UPDATE 130
+#define TK_SET 131
+#define TK_DEFERRABLE 132
+#define TK_FOREIGN 133
+#define TK_DROP 134
+#define TK_UNION 135
+#define TK_ALL 136
+#define TK_EXCEPT 137
+#define TK_INTERSECT 138
+#define TK_SELECT 139
+#define TK_VALUES 140
+#define TK_DISTINCT 141
+#define TK_DOT 142
+#define TK_FROM 143
+#define TK_JOIN 144
+#define TK_USING 145
+#define TK_ORDER 146
+#define TK_GROUP 147
+#define TK_HAVING 148
+#define TK_LIMIT 149
+#define TK_WHERE 150
+#define TK_RETURNING 151
+#define TK_INTO 152
+#define TK_NOTHING 153
+#define TK_FLOAT 154
+#define TK_BLOB 155
+#define TK_INTEGER 156
+#define TK_VARIABLE 157
+#define TK_CASE 158
+#define TK_WHEN 159
+#define TK_THEN 160
+#define TK_ELSE 161
+#define TK_INDEX 162
+#define TK_ALTER 163
+#define TK_ADD 164
+#define TK_WINDOW 165
+#define TK_OVER 166
+#define TK_FILTER 167
+#define TK_COLUMN 168
+#define TK_AGG_FUNCTION 169
+#define TK_AGG_COLUMN 170
+#define TK_TRUEFALSE 171
#define TK_FUNCTION 172
-#define TK_UMINUS 173
-#define TK_UPLUS 174
+#define TK_UPLUS 173
+#define TK_UMINUS 174
#define TK_TRUTH 175
#define TK_REGISTER 176
#define TK_VECTOR 177
@@ -14176,8 +14971,10 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_ASTERISK 180
#define TK_SPAN 181
#define TK_ERROR 182
-#define TK_SPACE 183
-#define TK_ILLEGAL 184
+#define TK_QNUMBER 183
+#define TK_SPACE 184
+#define TK_COMMENT 185
+#define TK_ILLEGAL 186
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -14186,6 +14983,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include
#include
#include
+#include
/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
@@ -14206,7 +15004,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define float sqlite_int64
-# define LONGDOUBLE_TYPE sqlite_int64
+# define fabs(X) ((X)<0?-(X):(X))
+# define sqlite3IsOverflow(X) 0
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
# endif
@@ -14381,9 +15180,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define INT8_TYPE signed char
# endif
#endif
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
-#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
@@ -14430,6 +15226,8 @@ typedef u64 tRowcnt;
** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
*/
typedef INT16_TYPE LogEst;
+#define LOGEST_MIN (-32768)
+#define LOGEST_MAX (32767)
/*
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
@@ -14439,7 +15237,7 @@ typedef INT16_TYPE LogEst;
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
- (defined(__APPLE__) && defined(__POWERPC__)) || \
+ (defined(__APPLE__) && defined(__ppc__)) || \
(defined(__TOS_AIX__) && !defined(__64BIT__))
# define SQLITE_PTRSIZE 4
# else
@@ -14465,8 +15263,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,
@@ -14476,16 +15297,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
@@ -14636,6 +15474,7 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace;
** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
** 0x00020000 Transform DISTINCT into GROUP BY
** 0x00040000 SELECT tree dump after all code has been generated
+** 0x00080000 NOT NULL strength reduction
*/
/*
@@ -14659,14 +15498,14 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace;
** 0xFFFF---- Low-level debug messages
**
** 0x00000001 Code generation
-** 0x00000002 Solver
+** 0x00000002 Solver (Use 0x40000 for less detail)
** 0x00000004 Solver costs
** 0x00000008 WhereLoop inserts
**
** 0x00000010 Display sqlite3_index_info xBestIndex calls
** 0x00000020 Range an equality scan metrics
** 0x00000040 IN operator decisions
-** 0x00000080 WhereLoop cost adjustements
+** 0x00000080 WhereLoop cost adjustments
** 0x00000100
** 0x00000200 Covering index decisions
** 0x00000400 OR optimization
@@ -14678,6 +15517,8 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace;
**
** 0x00010000 Show more detail when printing WHERE terms
** 0x00020000 Show WHERE terms returned from whereScanNext()
+** 0x00040000 Solver overview messages
+** 0x00080000 Star-query heuristic
*/
@@ -14700,7 +15541,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
@@ -14809,11 +15650,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;
@@ -14832,6 +15675,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;
@@ -14839,6 +15683,7 @@ typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct Subquery Subquery;
typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
@@ -15312,6 +16157,22 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
+#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL)
+
+/*
+** The argument to this macro is a file descriptor (type sqlite3_file*).
+** Return 0 if it is not open, or non-zero (but not 1) if it is.
+**
+** This is so that expressions can be written as:
+**
+** if( isOpen(pPager->jfd) ){ ...
+**
+** instead of
+**
+** if( pPager->jfd->pMethods ){ ...
+*/
+#define isOpen(pFd) ((pFd)->pMethods!=0)
+
/*
** Flags that make up the mask passed to sqlite3PagerGet().
*/
@@ -15445,7 +16306,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
-SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
+SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*);
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
@@ -15469,6 +16330,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 ***********************************************/
@@ -15717,6 +16582,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursor(
);
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*);
+#endif
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -15798,9 +16666,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*);
@@ -15810,6 +16676,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
Pgno *aRoot, /* An array of root pages numbers for individual trees */
+ sqlite3_value *aCnt, /* OUT: entry counts for each btree in aRoot[] */
int nRoot, /* Number of entries in aRoot[] */
int mxErr, /* Stop reporting errors after this many */
int *pnErr, /* OUT: Write number of errors seen to this variable */
@@ -15936,6 +16803,20 @@ typedef struct Vdbe Vdbe;
*/
typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
+typedef struct SubrtnSig SubrtnSig;
+
+/*
+** A signature for a reusable subroutine that materializes the RHS of
+** an IN operator.
+*/
+struct SubrtnSig {
+ int selId; /* SELECT-id for the SELECT statement on the RHS */
+ u8 bComplete; /* True if fully coded and available for reusable */
+ char *zAff; /* Affinity of the overall IN expression */
+ int iTable; /* Ephemeral table generated by the subroutine */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+};
/*
** A single instruction of the virtual machine has an opcode
@@ -15964,6 +16845,7 @@ struct VdbeOp {
u32 *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
+ SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
@@ -16030,6 +16912,8 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
+#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
+#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -16079,12 +16963,12 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Vacuum 5
#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */
#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */
-#define OP_Init 8 /* jump, synopsis: Start at P2 */
+#define OP_Init 8 /* jump0, synopsis: Start at P2 */
#define OP_Goto 9 /* jump */
#define OP_Gosub 10 /* jump */
-#define OP_InitCoroutine 11 /* jump */
-#define OP_Yield 12 /* jump */
-#define OP_MustBeInt 13 /* jump */
+#define OP_InitCoroutine 11 /* jump0 */
+#define OP_Yield 12 /* jump0 */
+#define OP_MustBeInt 13 /* jump0 */
#define OP_Jump 14 /* jump */
#define OP_Once 15 /* jump */
#define OP_If 16 /* jump */
@@ -16092,22 +16976,22 @@ typedef struct VdbeOpList VdbeOpList;
#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_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] */
-#define OP_SeekGT 24 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekLT 21 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_SeekLE 22 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_SeekGE 23 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_SeekGT 24 /* jump0, synopsis: key=r[P3@P4] */
#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */
#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
+#define OP_SeekRowid 30 /* jump0, synopsis: intkey=r[P3] */
#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
-#define OP_Last 32 /* jump */
-#define OP_IfSmaller 33 /* jump */
+#define OP_Last 32 /* jump0 */
+#define OP_IfSizeBetween 33 /* jump */
#define OP_SorterSort 34 /* jump */
#define OP_Sort 35 /* jump */
-#define OP_Rewind 36 /* jump */
+#define OP_Rewind 36 /* jump0 */
#define OP_SorterNext 37 /* jump */
#define OP_Prev 38 /* jump */
#define OP_Next 39 /* jump */
@@ -16119,18 +17003,18 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 48 /* jump */
+#define OP_Program 48 /* jump0 */
#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
-#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
-#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
-#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
-#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
-#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
+#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
+#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
#define OP_IncrVacuum 62 /* jump */
@@ -16149,7 +17033,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */
#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */
#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1) */
#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */
#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */
@@ -16173,23 +17057,23 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_ReadCookie 99
#define OP_SetCookie 100
#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
-#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
+#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_OpenDup 115
+#define OP_OpenDup 114
+#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
-#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */
+#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
#define OP_SorterOpen 119
#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
@@ -16224,8 +17108,8 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_LoadAnalysis 150
#define OP_DropTable 151
#define OP_DropIndex 152
-#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_DropTrigger 154
+#define OP_DropTrigger 153
+#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
#define OP_IntegrityCk 155
#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
#define OP_Param 157
@@ -16245,19 +17129,22 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_VCreate 171
#define OP_VDestroy 172
#define OP_VOpen 173
-#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */
-#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 176
-#define OP_Pagecount 177
-#define OP_MaxPgcnt 178
-#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */
-#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */
-#define OP_Trace 181
-#define OP_CursorHint 182
-#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */
-#define OP_Noop 184
-#define OP_Explain 185
-#define OP_Abortable 186
+#define OP_VCheck 174
+#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */
+#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 177
+#define OP_Pagecount 178
+#define OP_MaxPgcnt 179
+#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */
+#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */
+#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */
+#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */
+#define OP_Trace 184
+#define OP_CursorHint 185
+#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 187
+#define OP_Explain 188
+#define OP_Abortable 189
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -16270,31 +17157,32 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */
+#define OPFLG_JUMP0 0x80 /* jump0: P2 might be zero */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\
-/* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\
-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\
-/* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\
-/* 32 */ 0x41, 0x01, 0x01, 0x01, 0x41, 0x01, 0x41, 0x41,\
+/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
+/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
+/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
+/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
-/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
+/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
-/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
+/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
+/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\
/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
-/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,\
+/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
+/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x40,\
-/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\
-/* 184 */ 0x00, 0x00, 0x00,}
+/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
+/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
+/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
/* The resolve3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -16311,7 +17199,7 @@ typedef struct VdbeOpList VdbeOpList;
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
+#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
/*
** Prototypes for the VDBE interface. See comments on the implementation
@@ -16437,6 +17325,8 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
+SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val);
+
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
@@ -16469,7 +17359,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.
**
@@ -16487,7 +17377,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
@@ -16497,7 +17387,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.
@@ -16545,6 +17435,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 ************************************************/
@@ -16832,7 +17726,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
@@ -16871,7 +17765,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.
**
@@ -16982,7 +17876,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 */
@@ -16999,7 +17893,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
@@ -17020,43 +17914,11 @@ struct FuncDefHash {
};
#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** Information held in the "sqlite3" database connection object and used
-** to manage user authentication.
-*/
-typedef struct sqlite3_userauth sqlite3_userauth;
-struct sqlite3_userauth {
- u8 authLevel; /* Current authentication level */
- int nAuthPW; /* Size of the zAuthPW in bytes */
- char *zAuthPW; /* Password used to authenticate */
- char *zAuthUser; /* User name used to authenticate */
-};
-
-/* Allowed values for sqlite3_userauth.authLevel */
-#define UAUTH_Unknown 0 /* Authentication not yet checked */
-#define UAUTH_Fail 1 /* User authentication failed */
-#define UAUTH_User 2 /* Authenticated as a normal user */
-#define UAUTH_Admin 3 /* Authenticated as an administrator */
-
-/* Functions used only by user authorization logic */
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char*);
-SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
-SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*);
-SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
-
-#endif /* SQLITE_USER_AUTHENTICATION */
-
/*
** typedef for the authorization callback function.
*/
-#ifdef SQLITE_USER_AUTHENTICATION
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*, const char*);
-#else
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*);
-#endif
+typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+ const char*);
#ifndef SQLITE_OMIT_DEPRECATED
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
@@ -17199,6 +18061,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.
@@ -17216,9 +18079,6 @@ struct sqlite3 {
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- sqlite3_userauth auth; /* User authentication information */
-#endif
};
/*
@@ -17254,7 +18114,7 @@ struct sqlite3 {
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_StmtScanStatus 0x00000400 /* Enable stmt_scanstats() counters */
#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
@@ -17280,6 +18140,11 @@ struct sqlite3 {
/* DELETE, or UPDATE and return */
/* the count using a callback. */
#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
+#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */
+#define SQLITE_AttachCreate HI(0x00010) /* ATTACH allowed to create new dbs */
+#define SQLITE_AttachWrite HI(0x00020) /* ATTACH allowed to open for write */
+#define SQLITE_Comments HI(0x00040) /* Enable SQL comments */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@@ -17320,7 +18185,7 @@ struct sqlite3 {
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
-#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
+#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
@@ -17336,6 +18201,10 @@ struct sqlite3 {
/* TH3 expects this value ^^^^^^^^^^ See flatten04.test */
#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
+#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
+#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
+#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */
+#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ -17372,7 +18241,7 @@ struct sqlite3 {
** field is used by per-connection app-def functions.
*/
struct FuncDef {
- i8 nArg; /* Number of arguments. -1 means unlimited */
+ i16 nArg; /* Number of arguments. -1 means unlimited */
u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
@@ -17418,6 +18287,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!!!
@@ -17425,7 +18295,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.
*/
@@ -17436,6 +18306,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 */
@@ -17444,14 +18315,15 @@ struct FuncDestructor {
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
-/* 0x8000 -- available for reuse */
+#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
-#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
+/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */
+/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */
#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
/* Identifier numbers for each in-line function */
@@ -17543,10 +18415,11 @@ struct FuncDestructor {
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
-#define JFUNCTION(zName, nArg, iArg, xFunc) \
- {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\
- SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\
+ SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\
+ ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \
+ SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
@@ -17807,6 +18680,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) */
@@ -17886,8 +18760,7 @@ struct Table {
#define TF_HasStored 0x00000040 /* Has one or more STORED columns */
#define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
#define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
-#define TF_StatsUsed 0x00000100 /* Query planner decisions affected by
- ** Index.aiRowLogEst[] values */
+#define TF_MaybeReanalyze 0x00000100 /* Maybe run ANALYZE on this table */
#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
@@ -17943,6 +18816,15 @@ struct Table {
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
+/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
+** available. By default, this macro is false
+*/
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+# define ViewCanHaveRowid 0
+#else
+# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0)
+#endif
+
/*
** Each foreign key constraint is an instance of the following structure.
**
@@ -18014,7 +18896,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.
@@ -18180,6 +19062,7 @@ struct Index {
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
+ unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
@@ -18187,6 +19070,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 */
@@ -18289,6 +19173,10 @@ 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 */
+ u8 bUseSubtype; /* Transfer subtype info through sorter */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
@@ -18304,9 +19192,15 @@ struct AggInfo {
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
** The assert()s that are part of this macro verify that constraint.
*/
+#ifndef NDEBUG
#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I) \
(assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
+#else
+#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I))
+#define AggInfoFuncReg(A,I) \
+ ((A)->iFirstReg+(A)->nColumn+(I))
+#endif
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
@@ -18427,7 +19321,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.
@@ -18473,7 +19367,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 */
@@ -18487,7 +19381,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
- /* 0x80000000 // Available */
+#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
@@ -18503,12 +19397,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)
@@ -18618,6 +19515,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,
@@ -18636,13 +19534,8 @@ struct ExprList {
*/
struct IdList {
int nId; /* Number of identifiers on the list */
- u8 eU4; /* Which element of a.u4 is valid */
struct IdList_item {
char *zName; /* Name of the identifier */
- union {
- int idx; /* Index in some Table.aCol[] of a column named zName */
- Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */
- } u4;
} a[1];
};
@@ -18654,6 +19547,16 @@ struct IdList {
#define EU4_IDX 1 /* Uses IdList.a.u4.idx */
#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
+/*
+** Details of the implementation of a subquery.
+*/
+struct Subquery {
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to initialize a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+};
+
/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
@@ -18666,27 +19569,40 @@ struct IdList {
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
-** Union member validity:
+** Aggressive use of "union" helps keep the size of the object small. This
+** has been shown to boost performance, in addition to saving memory.
+** Access to union elements is gated by the following rules which should
+** always be checked, either by an if-statement or by an assert().
+**
+** Field Only access if this is true
+** --------------- -----------------------------------
+** u1.zIndexedBy fg.isIndexedBy
+** u1.pFuncArg fg.isTabFunc
+** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
+**
+** u2.pIBIndex fg.isIndexedBy
+** u2.pCteUse fg.isCte
**
-** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
-** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
-** u2.pIBIndex fg.isIndexedBy && !fg.isCte
-** u2.pCteUse fg.isCte && !fg.isIndexedBy
+** u3.pOn !fg.isUsing
+** u3.pUsing fg.isUsing
+**
+** u4.zDatabase !fg.fixedSchema && !fg.isSubquery
+** u4.pSchema fg.fixedSchema
+** u4.pSubq fg.isSubquery
+**
+** See also the sqlite3SrcListDelete() routine for assert() statements that
+** check invariants on the fields of this object, especially the flags
+** inside the fg struct.
*/
struct SrcItem {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
+ Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */
struct {
u8 jointype; /* Type of join between this table and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isSubquery :1; /* True if this term is a subquery */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned isMaterialized:1; /* This is a materialized view */
@@ -18697,23 +19613,32 @@ 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 */
+ unsigned rowidUsed :1; /* The ROWID of this table is referenced */
+ unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */
+ unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
- union {
- Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
- IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
- } u3;
Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY " clause */
ExprList *pFuncArg; /* Arguments to table-valued-function */
+ u32 nRow; /* Number of rows in a VALUES clause */
} u1;
union {
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
} u2;
+ union {
+ Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
+ IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
+ } u3;
+ union {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ Subquery *pSubq; /* Description of a subquery */
+ } u4;
};
/*
@@ -18773,7 +19698,7 @@ struct SrcList {
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
- /* 0x2000 not currently used */
+#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -18818,6 +19743,7 @@ struct NameContext {
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
+ u32 nNestedSelect; /* Number of nested selects using this NC */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -18844,13 +19770,14 @@ struct NameContext {
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x002000 /* True if a function or subquery seen */
+/* 0x002000 // available for reuse */
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
#define NC_HasWin 0x008000 /* One or more window functions seen */
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
+#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
@@ -18874,6 +19801,7 @@ struct Upsert {
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
+ u8 isDup; /* True if 2nd or later with same pUpsertIdx */
/* Above this point is the parse tree for the ON CONFLICT clauses.
** The next group of fields stores intermediate data. */
void *pToFree; /* Free memory when deleting the Upsert object */
@@ -18963,14 +19891,17 @@ struct Select {
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
-#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
+#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
+#define SF_Correlated 0x20000000 /* True if references the outer context */
-/* True if S exists and has SF_NestedFrom */
-#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
+/* True if SrcItem X is a subquery that has SF_NestedFrom */
+#define IsNestedFrom(X) \
+ ((X)->fg.isSubquery && \
+ ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -19000,7 +19931,11 @@ struct Select {
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
-** results. Used to implement "IN (SELECT ...)".
+** results. if pDest->iSDParm2 is positive, then it is
+** a register holding a Bloom filter for the IN operator
+** that should be populated in addition to the
+** pDest->iSDParm table. This SRT is used to
+** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
** the result there. The cursor is left open after
@@ -19207,6 +20142,8 @@ struct Parse {
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
+ u8 bHasWith; /* True if statement contains WITH */
+ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
@@ -19226,6 +20163,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 */
@@ -19233,6 +20171,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 */
@@ -19246,12 +20187,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 */
@@ -19284,9 +20222,7 @@ struct Parse {
int nVtabLock; /* Number of virtual tables to lock */
#endif
int nHeight; /* Expression tree height of current sub-select */
-#ifndef SQLITE_OMIT_EXPLAIN
int addrExplain; /* Address of current OP_Explain opcode */
-#endif
VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
@@ -19375,6 +20311,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 */
@@ -19496,10 +20433,11 @@ 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" */
};
/*
-** An objected used to accumulate the text of a string where we
+** An object used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct sqlite3_str {
@@ -19513,10 +20451,32 @@ struct sqlite3_str {
};
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
-#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
+#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
+/*
+** The following object is the header for an "RCStr" or "reference-counted
+** string". An RCStr is passed around and used like any other char*
+** that has been dynamically allocated. The important interface
+** differences:
+**
+** 1. RCStr strings are reference counted. They are deallocated
+** when the reference count reaches zero.
+**
+** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than
+** sqlite3_free()
+**
+** 3. Make a (read-only) copy of a read-only RCStr string using
+** sqlite3RCStrRef().
+**
+** "String" is in the name, but an RCStr object can also be used to hold
+** binary data.
+*/
+struct RCStr {
+ u64 nRCRef; /* Number of references */
+ /* Total structure size should be a multiple of 8 bytes for alignment */
+};
/*
** A pointer to this structure is used to communicate information
@@ -19543,7 +20503,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.
**
@@ -19569,6 +20529,9 @@ 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 */
+#ifdef SQLITE_DEBUG
+ u8 bJsonSelfcheck; /* Double-check JSON parsing */
+#endif
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ -19615,6 +20578,11 @@ struct Sqlite3Config {
#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
+#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
+ ** feature is disabled. 0 if rowids can
+ ** occur in views. */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
@@ -19655,6 +20623,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 */
@@ -19673,6 +20642,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;
};
@@ -19693,6 +20663,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*);
@@ -19773,6 +20744,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
@@ -19839,6 +20820,9 @@ struct Window {
** due to the SQLITE_SUBTYPE flag */
};
+SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow);
+SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal);
+
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*);
SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*);
@@ -19919,15 +20903,6 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_ENABLE_FTS3 1
#endif
-/*
-** The ctype.h header is needed for non-ASCII systems. It is also
-** needed by FTS3 when FTS3 is included in the amalgamation.
-*/
-#if !defined(SQLITE_ASCII) || \
- (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
-# include
-#endif
-
/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
@@ -19942,6 +20917,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))
@@ -19951,6 +20928,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);
@@ -20054,10 +21033,13 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
# define EXP754 (((u64)0x7ff)<<52)
# define MAN754 ((((u64)1)<<52)-1)
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
+# define IsOvfl(X) (((X)&EXP754)==EXP754)
SQLITE_PRIVATE int sqlite3IsNaN(double);
+SQLITE_PRIVATE int sqlite3IsOverflow(double);
#else
-# define IsNaN(X) 0
-# define sqlite3IsNaN(X) 0
+# define IsNaN(X) 0
+# define sqlite3IsNaN(X) 0
+# define sqlite3IsOVerflow(X) 0
#endif
/*
@@ -20070,6 +21052,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)
@@ -20135,6 +21131,7 @@ SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
SQLITE_PRIVATE void sqlite3Dequote(char*);
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
SQLITE_PRIVATE void sqlite3DequoteToken(Token*);
+SQLITE_PRIVATE void sqlite3DequoteNumber(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*);
@@ -20144,6 +21141,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
@@ -20155,10 +21156,13 @@ 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*);
-SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*);
+SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
@@ -20167,6 +21171,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
+SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
@@ -20257,6 +21262,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask);
SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
+SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*);
SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*);
#ifndef SQLITE_OMIT_AUTOINCREMENT
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
@@ -20275,6 +21281,9 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*);
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*);
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
@@ -20293,8 +21302,9 @@ SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
+SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*);
SQLITE_PRIVATE 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*);
@@ -20323,6 +21333,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
@@ -20356,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*);
@@ -20378,19 +21389,18 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*);
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
-SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
-SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
+SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
-SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
-SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*);
+SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
#endif
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int 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);
@@ -20505,6 +21515,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*);
@@ -20513,10 +21524,11 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
-SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar);
#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
+SQLITE_PRIVATE int sqlite3Utf8ReadLimited(const u8*, int, u32*);
SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
@@ -20565,7 +21577,9 @@ SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
+#if !defined(SQLITE_OMIT_BLOB_LITERAL)
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
+#endif
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
@@ -20609,6 +21623,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*));
@@ -20660,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*);
@@ -20716,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*);
@@ -20831,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 *);
@@ -20859,6 +21877,7 @@ SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*);
SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*);
SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*);
+SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3*,void*);
SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
#else
# define sqlite3CteNew(P,T,E,S) ((void*)0)
@@ -20871,7 +21890,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*);
SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
-SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
+SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*);
@@ -20970,6 +21989,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);
@@ -21081,6 +22101,12 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void);
SQLITE_PRIVATE sqlite3_uint64 sqlite3Hwtime(void);
#endif
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+# define IS_STMT_SCANSTATUS(db) (db->flags & SQLITE_StmtScanStatus)
+#else
+# define IS_STMT_SCANSTATUS(db) 0
+#endif
+
#endif /* SQLITEINT_H */
/************** End of sqliteInt.h *******************************************/
@@ -21249,14 +22275,14 @@ 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),
# endif
#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ "ALLOW_ROWID_IN_VIEW",
+#endif
#ifdef SQLITE_ALLOW_URI_AUTHORITY
"ALLOW_URI_AUTHORITY",
#endif
@@ -21484,6 +22510,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
"ENABLE_OFFSET_SQL_FUNC",
#endif
+#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
+ "ENABLE_ORDERED_SET_AGGREGATES",
+#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
@@ -21547,6 +22576,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
@@ -21588,6 +22620,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
@@ -21825,6 +22860,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
@@ -21944,9 +22982,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_UNTESTABLE
"UNTESTABLE",
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
@@ -22076,7 +23111,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
@@ -22222,6 +23257,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
+#ifdef SQLITE_DEBUG
+ 0, /* bJsonSelfcheck */
+#endif
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
@@ -22263,6 +23301,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
#endif
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
+#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
#endif
0, /* bLocaltimeFault */
0, /* xAltLocaltime */
@@ -22270,7 +23311,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
0, /* iPrngSeed */
#ifdef SQLITE_DEBUG
- {0,0,0,0,0,0} /* aTune */
+ {0,0,0,0,0,0}, /* aTune */
#endif
};
@@ -22451,6 +23492,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
@@ -22482,6 +23526,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 */
@@ -22522,6 +23567,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
@@ -22534,12 +23580,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
@@ -22621,6 +23680,7 @@ struct sqlite3_value {
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
+ u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */
#endif
};
@@ -22770,7 +23830,7 @@ struct sqlite3_context {
int isError; /* Error code returned by the function. */
u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
- u8 argc; /* Number of arguments */
+ u16 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
@@ -22860,16 +23920,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() */
@@ -22915,9 +23977,11 @@ struct PreUpdate {
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
+ Mem oldipk; /* Memory cell holding "old" IPK value */
Mem *aNew; /* Array of new.* values */
- Table *pTab; /* Schema object being upated */
+ Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
+ sqlite3_value **apDflt; /* Array of default values, if required */
};
/*
@@ -23006,6 +24070,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);
@@ -23453,7 +24518,7 @@ SQLITE_API int sqlite3_db_status(
case SQLITE_DBSTATUS_CACHE_MISS:
case SQLITE_DBSTATUS_CACHE_WRITE:{
int i;
- int nRet = 0;
+ u64 nRet = 0;
assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
@@ -23466,7 +24531,7 @@ SQLITE_API int sqlite3_db_status(
*pHighwater = 0; /* IMP: R-42420-56072 */
/* IMP: R-54100-20147 */
/* IMP: R-29431-39229 */
- *pCurrent = nRet;
+ *pCurrent = (int)nRet & 0x7fffffff;
break;
}
@@ -23563,12 +24628,14 @@ struct DateTime {
int tz; /* Timezone offset in minutes */
double s; /* Seconds */
char validJD; /* True (1) if iJD is valid */
- char rawS; /* Raw numeric value stored in s */
char validYMD; /* True (1) if Y,M,D are valid */
char validHMS; /* True (1) if h,m,s are valid */
- char validTZ; /* True (1) if tz is valid */
- char tzSet; /* Timezone was set explicitly */
- char isError; /* An overflow has occurred */
+ char nFloor; /* Days to implement "floor" */
+ unsigned rawS : 1; /* Raw numeric value stored in s */
+ unsigned isError : 1; /* An overflow has occurred */
+ unsigned useSubsec : 1; /* Display subsecond precision */
+ unsigned isUtc : 1; /* Time is known to be UTC */
+ unsigned isLocal : 1; /* Time is known to be localtime */
};
@@ -23601,8 +24668,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;
@@ -23666,6 +24733,8 @@ static int parseTimezone(const char *zDate, DateTime *p){
sgn = +1;
}else if( c=='Z' || c=='z' ){
zDate++;
+ p->isLocal = 0;
+ p->isUtc = 1;
goto zulu_time;
}else{
return c!=0;
@@ -23678,7 +24747,6 @@ static int parseTimezone(const char *zDate, DateTime *p){
p->tz = sgn*(nMn + nHr*60);
zulu_time:
while( sqlite3Isspace(*zDate) ){ zDate++; }
- p->tzSet = 1;
return *zDate!=0;
}
@@ -23711,6 +24779,9 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
zDate++;
}
ms /= rScale;
+ /* Truncate to avoid problems with sub-milliseconds
+ ** rounding. https://sqlite.org/forum/forumpost/766a2c9231 */
+ if( ms>0.999 ) ms = 0.999;
}
}else{
s = 0;
@@ -23722,7 +24793,6 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
p->m = m;
p->s = s + ms;
if( parseTimezone(zDate, p) ) return 1;
- p->validTZ = (p->tz!=0)?1:0;
return 0;
}
@@ -23761,23 +24831,48 @@ static void computeJD(DateTime *p){
Y--;
M += 12;
}
- A = Y/100;
- B = 2 - A + (A/4);
+ A = (Y+4800)/100;
+ B = 38 - A + (A/4);
X1 = 36525*(Y+4716)/100;
X2 = 306001*(M+1)/10000;
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
p->validJD = 1;
if( p->validHMS ){
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
- if( p->validTZ ){
+ if( p->tz ){
p->iJD -= p->tz*60000;
p->validYMD = 0;
p->validHMS = 0;
- p->validTZ = 0;
+ p->tz = 0;
+ p->isUtc = 1;
+ p->isLocal = 0;
}
}
}
+/*
+** Given the YYYY-MM-DD information current in p, determine if there
+** is day-of-month overflow and set nFloor to the number of days that
+** would need to be subtracted from the date in order to bring the
+** date back to the end of the month.
+*/
+static void computeFloor(DateTime *p){
+ assert( p->validYMD || p->isError );
+ assert( p->D>=0 && p->D<=31 );
+ assert( p->M>=0 && p->M<=12 );
+ if( p->D<=28 ){
+ p->nFloor = 0;
+ }else if( (1<M) & 0x15aa ){
+ p->nFloor = 0;
+ }else if( p->M!=2 ){
+ p->nFloor = (p->D==31);
+ }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){
+ p->nFloor = p->D - 28;
+ }else{
+ p->nFloor = p->D - 29;
+ }
+}
+
/*
** Parse dates of the form
**
@@ -23816,12 +24911,16 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
p->Y = neg ? -Y : Y;
p->M = M;
p->D = D;
- if( p->validTZ ){
+ computeFloor(p);
+ if( p->tz ){
computeJD(p);
}
return 0;
}
+
+static void clearYMD_HMS_TZ(DateTime *p); /* Forward declaration */
+
/*
** Set the time to the current time reported by the VFS.
**
@@ -23831,6 +24930,9 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
p->iJD = sqlite3StmtCurrentTime(context);
if( p->iJD>0 ){
p->validJD = 1;
+ p->isUtc = 1;
+ p->isLocal = 0;
+ clearYMD_HMS_TZ(p);
return 0;
}else{
return 1;
@@ -23883,6 +24985,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;
}
@@ -23909,7 +25016,7 @@ static int validJulianDay(sqlite3_int64 iJD){
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
- int Z, A, B, C, D, E, X1;
+ int Z, alpha, A, B, C, D, E, X1;
if( p->validYMD ) return;
if( !p->validJD ){
p->Y = 2000;
@@ -23920,8 +25027,8 @@ static void computeYMD(DateTime *p){
return;
}else{
Z = (int)((p->iJD + 43200000)/86400000);
- A = (int)((Z - 1867216.25)/36524.25);
- A = Z + 1 + A - (A/4);
+ alpha = (int)((Z + 32044.75)/36524.25) - 52;
+ A = Z + 1 + alpha - ((alpha+100)/4) + 25;
B = A + 1524;
C = (int)((B - 122.1)/365.25);
D = (36525*(C&32767))/100;
@@ -23938,17 +25045,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;
}
@@ -23967,7 +25071,7 @@ static void computeYMD_HMS(DateTime *p){
static void clearYMD_HMS_TZ(DateTime *p){
p->validYMD = 0;
p->validHMS = 0;
- p->validTZ = 0;
+ p->tz = 0;
}
#ifndef SQLITE_OMIT_LOCALTIME
@@ -24099,7 +25203,7 @@ static int toLocaltime(
p->validHMS = 1;
p->validJD = 0;
p->rawS = 0;
- p->validTZ = 0;
+ p->tz = 0;
p->isError = 0;
return SQLITE_OK;
}
@@ -24119,14 +25223,33 @@ static const struct {
float rLimit; /* Maximum NNN value for this transform */
float rXform; /* Constant used for this transform */
} aXformType[] = {
- { 6, "second", 4.6427e+14, 1.0 },
- { 6, "minute", 7.7379e+12, 60.0 },
- { 4, "hour", 1.2897e+11, 3600.0 },
- { 3, "day", 5373485.0, 86400.0 },
- { 5, "month", 176546.0, 2592000.0 },
- { 4, "year", 14713.0, 31536000.0 },
+ /* 0 */ { 6, "second", 4.6427e+14, 1.0 },
+ /* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
+ /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
+ /* 3 */ { 3, "day", 5373485.0, 86400.0 },
+ /* 4 */ { 5, "month", 176546.0, 2592000.0 },
+ /* 5 */ { 4, "year", 14713.0, 31536000.0 },
};
+/*
+** If the DateTime p is raw number, try to figure out if it is
+** a julian day number of a unix timestamp. Set the p value
+** appropriately.
+*/
+static void autoAdjustDate(DateTime *p){
+ if( !p->rawS || p->validJD ){
+ p->rawS = 0;
+ }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
+ && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
+ ){
+ double r = p->s*1000.0 + 210866760000000.0;
+ clearYMD_HMS_TZ(p);
+ p->iJD = (sqlite3_int64)(r + 0.5);
+ p->validJD = 1;
+ p->rawS = 0;
+ }
+}
+
/*
** Process a modifier to a date-time stamp. The modifiers are
** as follows:
@@ -24137,14 +25260,20 @@ static const struct {
** NNN.NNNN seconds
** NNN months
** NNN years
+** +/-YYYY-MM-DD HH:MM:SS.SSS
+** ceiling
+** floor
** start of month
** start of year
** start of week
** start of day
** weekday N
** unixepoch
+** auto
** localtime
** utc
+** subsec
+** subsecond
**
** Return 0 on success and 1 if there is any kind of error. If the error
** is in a system call (i.e. localtime()), then an error message is written
@@ -24170,19 +25299,39 @@ 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;
+ }
+ case 'c': {
+ /*
+ ** ceiling
+ **
+ ** Resolve day-of-month overflow by rolling forward into the next
+ ** month. As this is the default action, this modifier is really
+ ** a no-op that is only included for symmetry. See "floor".
+ */
+ if( sqlite3_stricmp(z, "ceiling")==0 ){
+ computeJD(p);
+ clearYMD_HMS_TZ(p);
+ rc = 0;
+ p->nFloor = 0;
+ }
+ break;
+ }
+ case 'f': {
+ /*
+ ** floor
+ **
+ ** Resolve day-of-month overflow by rolling back to the end of the
+ ** previous month.
+ */
+ if( sqlite3_stricmp(z, "floor")==0 ){
+ computeJD(p);
+ p->iJD -= p->nFloor*86400000;
+ clearYMD_HMS_TZ(p);
+ rc = 0;
}
break;
}
@@ -24212,7 +25361,9 @@ static int parseModifier(
** show local time.
*/
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
- rc = toLocaltime(p, pCtx);
+ rc = p->isLocal ? SQLITE_OK : toLocaltime(p, pCtx);
+ p->isUtc = 0;
+ p->isLocal = 1;
}
break;
}
@@ -24237,7 +25388,7 @@ static int parseModifier(
}
#ifndef SQLITE_OMIT_LOCALTIME
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
- if( p->tzSet==0 ){
+ if( p->isUtc==0 ){
i64 iOrigJD; /* Original localtime */
i64 iGuess; /* Guess at the corresponding utc time */
int cnt = 0; /* Safety to prevent infinite loop */
@@ -24260,7 +25411,8 @@ static int parseModifier(
memset(p, 0, sizeof(*p));
p->iJD = iGuess;
p->validJD = 1;
- p->tzSet = 1;
+ p->isUtc = 1;
+ p->isLocal = 0;
}
rc = SQLITE_OK;
}
@@ -24280,7 +25432,7 @@ static int parseModifier(
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
sqlite3_int64 Z;
computeYMD_HMS(p);
- p->validTZ = 0;
+ p->tz = 0;
p->validJD = 0;
computeJD(p);
Z = ((p->iJD + 129600000)/86400000) % 7;
@@ -24297,8 +25449,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);
@@ -24306,7 +25472,7 @@ static int parseModifier(
p->h = p->m = 0;
p->s = 0.0;
p->rawS = 0;
- p->validTZ = 0;
+ p->tz = 0;
p->validJD = 0;
if( sqlite3_stricmp(z,"month")==0 ){
p->D = 1;
@@ -24334,18 +25500,74 @@ 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;
+ computeFloor(p);
+ computeJD(p);
+ p->validHMS = 0;
+ p->validYMD = 0;
+ p->iJD += (i64)D*86400000;
+ if( z[11]==0 ){
+ rc = 0;
+ break;
+ }
+ if( sqlite3Isspace(z[11])
+ && getDigits(&z[12], "20c:20e", &h, &m)==2
+ ){
+ z2 = &z[12];
+ n = 2;
+ }else{
+ break;
+ }
+ }
+ if( z2[n]==':' ){
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
** specified number of hours, minutes, seconds, and fractional seconds
** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
** omitted.
*/
- const char *z2 = z;
+
DateTime tx;
sqlite3_int64 day;
if( !sqlite3Isdigit(*z2) ) z2++;
@@ -24355,7 +25577,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;
@@ -24368,11 +25590,12 @@ static int parseModifier(
z += n;
while( sqlite3Isspace(*z) ) z++;
n = sqlite3Strlen30(z);
- if( n>10 || n<3 ) break;
+ if( n<3 || n>10 ) break;
if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
computeJD(p);
- rc = 1;
+ assert( rc==1 );
rRounder = r<0 ? -0.5 : +0.5;
+ p->nFloor = 0;
for(i=0; iM += (int)r;
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
p->Y += x;
p->M -= x*12;
+ computeFloor(p);
p->validJD = 0;
r -= (int)r;
break;
}
case 5: { /* Special processing to add years */
int y = (int)r;
- assert( strcmp(aXformType[i].zName,"year")==0 );
+ assert( strcmp(aXformType[5].zName,"year")==0 );
computeYMD_HMS(p);
+ assert( p->M>=0 && p->M<=12 );
p->Y += y;
+ computeFloor(p);
p->validJD = 0;
r -= (int)r;
break;
@@ -24456,6 +25681,12 @@ static int isDate(
}
computeJD(p);
if( p->isError || !validJulianDay(p->iJD) ) return 1;
+ if( argc==1 && p->validYMD && p->D>28 ){
+ /* Make sure a YYYY-MM-DD is normalized.
+ ** Example: 2023-02-31 -> 2023-03-03 */
+ assert( p->validJD );
+ p->validYMD = 0;
+ }
return 0;
}
@@ -24496,7 +25727,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);
+ }
}
}
@@ -24512,8 +25747,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;
@@ -24534,15 +25769,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);
}
}
}
@@ -24559,7 +25807,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;
@@ -24568,11 +25816,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);
}
}
@@ -24613,22 +25874,83 @@ static void dateFunc(
}
}
+/*
+** Compute the number of days after the most recent January 1.
+**
+** In other words, compute the zero-based day number for the
+** current year:
+**
+** Jan01 = 0, Jan02 = 1, ..., Jan31 = 30, Feb01 = 31, ...
+** Dec31 = 364 or 365.
+*/
+static int daysAfterJan01(DateTime *pDate){
+ DateTime jan01 = *pDate;
+ assert( jan01.validYMD );
+ assert( jan01.validHMS );
+ assert( pDate->validJD );
+ jan01.validJD = 0;
+ jan01.M = 1;
+ jan01.D = 1;
+ computeJD(&jan01);
+ return (int)((pDate->iJD-jan01.iJD+43200000)/86400000);
+}
+
+/*
+** Return the number of days after the most recent Monday.
+**
+** In other words, return the day of the week according
+** to this code:
+**
+** 0=Monday, 1=Tuesday, 2=Wednesday, ..., 6=Sunday.
+*/
+static int daysAfterMonday(DateTime *pDate){
+ assert( pDate->validJD );
+ return (int)((pDate->iJD+43200000)/86400000) % 7;
+}
+
+/*
+** Return the number of days after the most recent Sunday.
+**
+** In other words, return the day of the week according
+** to this code:
+**
+** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday
+*/
+static int daysAfterSunday(DateTime *pDate){
+ assert( pDate->validJD );
+ return (int)((pDate->iJD+129600000)/86400000) % 7;
+}
+
/*
** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
**
** Return a string described by FORMAT. Conversions as follows:
**
-** %d day of month
+** %d day of month 01-31
+** %e day of month 1-31
** %f ** fractional seconds SS.SSS
+** %F ISO date. YYYY-MM-DD
+** %G ISO year corresponding to %V 0000-9999.
+** %g 2-digit ISO year corresponding to %V 00-99
** %H hour 00-24
-** %j day of year 000-366
+** %k hour 0-24 (leading zero converted to space)
+** %I hour 01-12
+** %j day of year 001-366
** %J ** julian day number
+** %l hour 1-12 (leading zero converted to space)
** %m month 01-12
** %M minute 00-59
+** %p "am" or "pm"
+** %P "AM" or "PM"
+** %R time as HH:MM
** %s seconds since 1970-01-01
** %S seconds 00-59
-** %w day of week 0-6 sunday==0
-** %W week of year 00-53
+** %T time as HH:MM:SS
+** %u day of week 1-7 Monday==1, Sunday==7
+** %w day of week 0-6 Sunday==0, Monday==1
+** %U week of year 00-53 (First Sunday is start of week 01)
+** %V week of year 01-53 (First week containing Thursday is week 01)
+** %W week of year 00-53 (First Monday is start of week 01)
** %Y year 0000-9999
** %% %
*/
@@ -24653,44 +25975,61 @@ static void strftimeFunc(
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
+ char cf;
if( zFmt[i]!='%' ) continue;
if( j59.999 ) s = 59.999;
+ if( NEVER(s>59.999) ) s = 59.999;
sqlite3_str_appendf(&sRes, "%06.3f", s);
break;
}
- case 'H': {
- sqlite3_str_appendf(&sRes, "%02d", x.h);
+ case 'F': {
+ sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
break;
}
- case 'W': /* Fall thru */
- case 'j': {
- int nDay; /* Number of days since 1st day of year */
+ case 'G': /* Fall thru */
+ case 'g': {
DateTime y = x;
- y.validJD = 0;
- y.M = 1;
- y.D = 1;
- computeJD(&y);
- nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
- if( zFmt[i]=='W' ){
- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
- wd = (int)(((x.iJD+43200000)/86400000)%7);
- sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
+ assert( y.validJD );
+ /* Move y so that it is the Thursday in the same week as x */
+ y.iJD += (3 - daysAfterMonday(&x))*86400000;
+ y.validYMD = 0;
+ computeYMD(&y);
+ if( cf=='g' ){
+ sqlite3_str_appendf(&sRes, "%02d", y.Y%100);
}else{
- sqlite3_str_appendf(&sRes,"%03d",nDay+1);
+ sqlite3_str_appendf(&sRes, "%04d", y.Y);
}
break;
}
- case 'J': {
+ case 'H':
+ case 'k': {
+ sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
+ break;
+ }
+ case 'I': /* Fall thru */
+ case 'l': {
+ int h = x.h;
+ if( h>12 ) h -= 12;
+ if( h==0 ) h = 12;
+ sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
+ break;
+ }
+ case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */
+ sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1);
+ break;
+ }
+ case 'J': { /* Julian day number. (Non-standard) */
sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
break;
}
@@ -24702,18 +26041,62 @@ 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 'w': {
- sqlite3_str_appendchar(&sRes, 1,
- (char)(((x.iJD+129600000)/86400000) % 7) + '0');
+ case 'T': {
+ sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
+ break;
+ }
+ case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */
+ case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */
+ char c = (char)daysAfterSunday(&x) + '0';
+ if( c=='0' && cf=='u' ) c = '7';
+ sqlite3_str_appendchar(&sRes, 1, c);
+ break;
+ }
+ case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */
+ sqlite3_str_appendf(&sRes,"%02d",
+ (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7);
+ break;
+ }
+ case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */
+ DateTime y = x;
+ /* Adjust y so that is the Thursday in the same week as x */
+ assert( y.validJD );
+ y.iJD += (3 - daysAfterMonday(&x))*86400000;
+ y.validYMD = 0;
+ computeYMD(&y);
+ sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1);
+ break;
+ }
+ case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */
+ sqlite3_str_appendf(&sRes,"%02d",
+ (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7);
break;
}
case 'Y': {
@@ -24762,6 +26145,115 @@ 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;
+ }
+ clearYMD_HMS_TZ(&d1);
+ computeYMD_HMS(&d1);
+ sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
+ sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
+ sign, Y, M, d1.D-1, d1.h, d1.m, d1.s);
+ sqlite3ResultStrAccum(context, &sRes);
+}
+
+
/*
** current_timestamp()
**
@@ -24822,6 +26314,36 @@ static void currentTimeFunc(
}
#endif
+#if !defined(SQLITE_OMIT_DATETIME_FUNCS) && defined(SQLITE_DEBUG)
+/*
+** datedebug(...)
+**
+** This routine returns JSON that describes the internal DateTime object.
+** Used for debugging and testing only. Subject to change.
+*/
+static void datedebugFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ char *zJson;
+ zJson = sqlite3_mprintf(
+ "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d,"
+ "s:%.3f,validJD:%d,validYMS:%d,validHMS:%d,"
+ "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d,"
+ "isUtc:%d,isLocal:%d}",
+ x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz,
+ x.s, x.validJD, x.validYMD, x.validHMS,
+ x.nFloor, x.rawS, x.isError, x.useSubsec,
+ x.isUtc, x.isLocal);
+ sqlite3_result_text(context, zJson, -1, sqlite3_free);
+ }
+}
+#endif /* !SQLITE_OMIT_DATETIME_FUNCS && SQLITE_DEBUG */
+
+
/*
** This function registered all of the above C functions as SQL
** functions. This should be the only routine in this file with
@@ -24836,6 +26358,10 @@ 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 ),
+#ifdef SQLITE_DEBUG
+ PURE_DATE(datedebug, -1, 0, 0, datedebugFunc ),
+#endif
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
@@ -24989,7 +26515,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(),
@@ -25610,7 +27136,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){
@@ -25698,7 +27224,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 */
@@ -27690,7 +29216,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
{
@@ -27904,16 +29430,29 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
+**
+** Because these routines raise false-positive alerts in TSAN, disable
+** them (make them always return 1) when compiling with TSAN.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
-#endif
+#endif /* NDEBUG */
#endif /* !defined(SQLITE_MUTEX_OMIT) */
@@ -28165,7 +29704,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)
@@ -28362,7 +29901,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
{
@@ -28666,7 +30205,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
@@ -28715,7 +30254,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
-#elif MSVC_VERSION>=1300
+#elif MSVC_VERSION>=1400
_ReadWriteBarrier();
#elif defined(MemoryBarrier)
MemoryBarrier();
@@ -29251,6 +30790,24 @@ static void sqlite3MallocAlarm(int nByte){
sqlite3_mutex_enter(mem0.mutex);
}
+#ifdef SQLITE_DEBUG
+/*
+** This routine is called whenever an out-of-memory condition is seen,
+** It's only purpose to to serve as a breakpoint for gdb or similar
+** code debuggers when working on out-of-memory conditions, for example
+** caused by PRAGMA hard_heap_limit=N.
+*/
+static SQLITE_NOINLINE void test_oom_breakpoint(u64 n){
+ static u64 nOomFault = 0;
+ nOomFault += n;
+ /* The assert() is never reached in a human lifetime. It is here mostly
+ ** to prevent code optimizers from optimizing out this function. */
+ assert( (nOomFault>>32) < 0xffffffff );
+}
+#else
+# define test_oom_breakpoint(X) /* No-op for production builds */
+#endif
+
/*
** Do a memory allocation with statistics and alarms. Assume the
** lock is already held.
@@ -29277,6 +30834,7 @@ static void mallocWithAlarm(int n, void **pp){
if( mem0.hardLimit ){
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
if( nUsed >= mem0.hardLimit - nFull ){
+ test_oom_breakpoint(1);
*pp = 0;
return;
}
@@ -29565,6 +31123,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3MallocAlarm(nDiff);
if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
sqlite3_mutex_leave(mem0.mutex);
+ test_oom_breakpoint(1);
return 0;
}
}
@@ -29926,7 +31485,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 **********************************************/
@@ -30038,43 +31597,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 */
-
/*
** Set the StrAccum object to an error mode.
*/
@@ -30166,18 +31688,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 */
+ 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 */
@@ -30452,74 +31971,69 @@ 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 = '-';
- }else{
- prefix = flag_prefix;
- }
- if( xtype==etGENERIC && precision>0 ) precision--;
- testcase( precision>0xfff );
- 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;
- }
- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
- exp = 0;
- if( sqlite3IsNaN((double)realvalue) ){
- bufpt = "NaN";
- length = 3;
- break;
+ iRound = -precision;
+ }else if( xtype==etGENERIC ){
+ if( precision==0 ) precision = 1;
+ iRound = precision;
+ }else{
+ iRound = precision+1;
}
- if( realvalue>0.0 ){
- LONGDOUBLE_TYPE scale = 1.0;
- while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
- while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; }
- while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
- realvalue /= scale;
- while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
- while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
- if( exp>350 ){
+ sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
+ if( s.isSpecial ){
+ if( s.isSpecial==2 ){
+ bufpt = flag_zeropad ? "null" : "NaN";
+ length = sqlite3Strlen30(bufpt);
+ break;
+ }else if( flag_zeropad ){
+ s.z[0] = '9';
+ s.iDP = 1000;
+ s.n = 1;
+ }else{
+ memcpy(buf, "-Inf", 5);
bufpt = buf;
- buf[0] = prefix;
- memcpy(buf+(prefix!=0),"Inf",4);
- length = 3+(prefix!=0);
+ if( s.sign=='-' ){
+ /* no-op */
+ }else if( flag_prefix ){
+ buf[0] = flag_prefix;
+ }else{
+ bufpt++;
+ }
+ length = sqlite3Strlen30(bufpt);
break;
}
}
- bufpt = buf;
+ if( s.sign=='-' ){
+ prefix = '-';
+ }else{
+ prefix = flag_prefix;
+ }
+
+ exp = s.iDP-1;
+
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
- if( xtype!=etFLOAT ){
- realvalue += rounder;
- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
- }
if( xtype==etGENERIC ){
+ assert( precision>0 );
+ precision--;
flag_rtz = !flag_alternateform;
if( exp<-4 || exp>precision ){
xtype = etEXP;
@@ -30533,29 +32047,32 @@ SQLITE_API void sqlite3_str_vappendf(
if( xtype==etEXP ){
e2 = 0;
}else{
- e2 = exp;
+ e2 = s.iDP - 1;
}
+ bufpt = buf;
{
i64 szBufNeeded; /* Size of a temporary buffer needed */
szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
+ if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
if( szBufNeeded > etBUFSIZE ){
bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
if( bufpt==0 ) return;
}
}
zOut = bufpt;
- nsd = 16 + flag_altform2*10;
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
+ j = 0;
if( e2<0 ){
*(bufpt++) = '0';
}else{
for(; e2>=0; e2--){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ *(bufpt++) = j1 ) *(bufpt++) = ',';
}
}
/* The decimal point */
@@ -30564,13 +32081,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 */
while( (precision--)>0 ){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ *(bufpt++) = jcharset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
@@ -30619,8 +32136,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;
@@ -30823,18 +32340,25 @@ SQLITE_API void sqlite3_str_vappendf(
if( pItem->zAlias && !flag_altform2 ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else if( pItem->zName ){
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ if( pItem->fg.fixedSchema==0
+ && pItem->fg.isSubquery==0
+ && pItem->u4.zDatabase!=0
+ ){
+ sqlite3_str_appendall(pAccum, pItem->u4.zDatabase);
sqlite3_str_append(pAccum, ".", 1);
}
sqlite3_str_appendall(pAccum, pItem->zName);
}else if( pItem->zAlias ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
- }else{
- Select *pSel = pItem->pSelect;
+ }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */
+ Select *pSel = pItem->u4.pSubq->pSelect;
assert( pSel!=0 );
if( pSel->selFlags & SF_NestedFrom ){
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
+ }else if( pSel->selFlags & SF_MultiValue ){
+ assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
+ sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
+ pItem->u1.nRow);
}else{
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
}
@@ -30906,6 +32430,7 @@ SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExp
pExpr = pExpr->pLeft;
}
if( pExpr==0 ) return;
+ if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
db->errByteOffset = pExpr->w.iOfst;
}
@@ -31251,12 +32776,22 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li
return zBuf;
}
SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
- char *z;
+ StrAccum acc;
va_list ap;
+ if( n<=0 ) return zBuf;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( zBuf==0 || zFormat==0 ) {
+ (void)SQLITE_MISUSE_BKPT;
+ if( zBuf ) zBuf[0] = 0;
+ return zBuf;
+ }
+#endif
+ sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
va_start(ap,zFormat);
- z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
+ sqlite3_str_vappendf(&acc, zFormat, ap);
va_end(ap);
- return z;
+ zBuf[acc.nChar] = 0;
+ return zBuf;
}
/*
@@ -31334,6 +32869,75 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
va_end(ap);
}
+
+/*****************************************************************************
+** Reference counted string/blob storage
+*****************************************************************************/
+
+/*
+** Increase the reference count of the string by one.
+**
+** The input parameter is returned.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){
+ RCStr *p = (RCStr*)z;
+ assert( p!=0 );
+ p--;
+ p->nRCRef++;
+ return z;
+}
+
+/*
+** Decrease the reference count by one. Free the string when the
+** reference count reaches zero.
+*/
+SQLITE_PRIVATE void sqlite3RCStrUnref(void *z){
+ RCStr *p = (RCStr*)z;
+ assert( p!=0 );
+ p--;
+ assert( p->nRCRef>0 );
+ if( p->nRCRef>=2 ){
+ p->nRCRef--;
+ }else{
+ sqlite3_free(p);
+ }
+}
+
+/*
+** Create a new string that is capable of holding N bytes of text, not counting
+** the zero byte at the end. The string is uninitialized.
+**
+** The reference count is initially 1. Call sqlite3RCStrUnref() to free the
+** newly allocated string.
+**
+** This routine returns 0 on an OOM.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){
+ RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 );
+ if( p==0 ) return 0;
+ p->nRCRef = 1;
+ return (char*)&p[1];
+}
+
+/*
+** Change the size of the string so that it is able to hold N bytes.
+** The string might be reallocated, so return the new allocation.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){
+ RCStr *p = (RCStr*)z;
+ RCStr *pNew;
+ assert( p!=0 );
+ p--;
+ assert( p->nRCRef==1 );
+ pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1);
+ if( pNew==0 ){
+ sqlite3_free(p);
+ return 0;
+ }else{
+ return (char*)&pNew[1];
+ }
+}
+
/************** End of printf.c **********************************************/
/************** Begin file treeview.c ****************************************/
/*
@@ -31531,9 +33135,11 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
- if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
- pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
+ if( pItem->pSTab ){
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
+ pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab,
+ pItem->colUsed,
+ pItem->fg.rowidUsed ? "+rowid" : "");
}
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
@@ -31551,10 +33157,13 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3_str_appendf(&x, " DDL");
}
if( pItem->fg.isCte ){
- sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ static const char *aMat[] = {",MAT", "", ",NO-MAT"};
+ sqlite3_str_appendf(&x, " CteUse=%d%s",
+ pItem->u2.pCteUse->nUse,
+ aMat[pItem->u2.pCteUse->eM10d]);
}
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
- sqlite3_str_appendf(&x, " ON");
+ sqlite3_str_appendf(&x, " isOn");
}
if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
@@ -31562,23 +33171,27 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
+ if( pItem->fg.fixedSchema ) sqlite3_str_appendf(&x, " fixedSchema");
+ if( pItem->fg.hadSchema ) sqlite3_str_appendf(&x, " hadSchema");
+ if( pItem->fg.isSubquery ) sqlite3_str_appendf(&x, " isSubquery");
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, inSrc-1);
n = 0;
- if( pItem->pSelect ) n++;
+ if( pItem->fg.isSubquery ) n++;
if( pItem->fg.isTabFunc ) n++;
if( pItem->fg.isUsing ) n++;
if( pItem->fg.isUsing ){
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
}
- if( pItem->pSelect ){
- if( pItem->pTab ){
- Table *pTab = pItem->pTab;
+ if( pItem->fg.isSubquery ){
+ assert( n==1 );
+ if( pItem->pSTab ){
+ Table *pTab = pItem->pSTab;
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
}
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
- sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
+ sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
@@ -31620,7 +33233,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
n = 1000;
}else{
n = 0;
- if( p->pSrc && p->pSrc->nSrc ) n++;
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
@@ -31646,7 +33259,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPop(&pView);
}
#endif
- if( p->pSrc && p->pSrc->nSrc ){
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){
sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, p->pSrc);
@@ -31682,7 +33295,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
if( p->pLimit->pRight ){
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
+ sqlite3TreeViewItem(pView, "OFFSET", 0);
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
sqlite3TreeViewPop(&pView);
}
@@ -31750,6 +33363,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 ){
@@ -31759,7 +33373,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);
@@ -31772,7 +33386,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";
@@ -31981,7 +33595,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;
@@ -32019,7 +33634,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
@@ -32045,7 +33660,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 ){
@@ -32054,6 +33675,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) );
@@ -32107,7 +33732,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
assert( pExpr->x.pList->nExpr==2 );
pY = pExpr->x.pList->a[0].pExpr;
pZ = pExpr->x.pList->a[1].pExpr;
- sqlite3TreeViewLine(pView, "BETWEEN");
+ sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
@@ -32142,7 +33767,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case OE_Ignore: zType = "ignore"; break;
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
+ sqlite3TreeViewLine(pView, "RAISE %s", zType);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif
@@ -32222,9 +33848,10 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; inExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
+ u8 sortFlags = pList->a[i].fg.sortFlags;
char *zName = pList->a[i].zEName;
int moreToFollow = inExpr - 1;
- if( j || zName ){
+ if( j || zName || sortFlags ){
sqlite3TreeViewPush(&pView, moreToFollow);
moreToFollow = 0;
sqlite3TreeViewLine(pView, 0);
@@ -32245,13 +33872,18 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
}
}
if( j ){
- fprintf(stdout, "iOrderByCol=%d", j);
+ fprintf(stdout, "iOrderByCol=%d ", j);
+ }
+ if( sortFlags & KEYINFO_ORDER_DESC ){
+ fprintf(stdout, "DESC ");
+ }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
+ fprintf(stdout, "NULLS-LAST");
}
fprintf(stdout, "\n");
fflush(stdout);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
- if( j || zName ){
+ if( j || zName || sortFlags ){
sqlite3TreeViewPop(&pView);
}
}
@@ -32288,21 +33920,7 @@ SQLITE_PRIVATE void sqlite3TreeViewBareIdList(
if( zName==0 ) zName = "(null)";
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewLine(pView, 0);
- if( pList->eU4==EU4_NONE ){
- fprintf(stdout, "%s\n", zName);
- }else if( pList->eU4==EU4_IDX ){
- fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
- }else{
- assert( pList->eU4==EU4_EXPR );
- if( pList->a[i].u4.pExpr==0 ){
- fprintf(stdout, "%s (pExpr=NULL)\n", zName);
- }else{
- fprintf(stdout, "%s\n", zName);
- sqlite3TreeViewPush(&pView, inId-1);
- sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
- sqlite3TreeViewPop(&pView);
- }
- }
+ fprintf(stdout, "%s\n", zName);
sqlite3TreeViewPop(&pView);
}
}
@@ -32612,6 +34230,10 @@ SQLITE_PRIVATE void sqlite3TreeViewTrigger(
** accessible to the debugging, and to avoid warnings about unused
** functions. But these routines only exist in debugging builds, so they
** do not contaminate the interface.
+**
+** See Also:
+**
+** sqlite3ShowWhereTerm() in where.c
*/
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
@@ -33214,7 +34836,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIn0 );
+ c = z[0];
+ if( c>=0xc0 ){
+ c = sqlite3Utf8Trans1[c-0xc0];
+ if( n>4 ) n = 4;
+ while( i=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
+ if( c>=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
n++;
}
return (int)(z-(unsigned char const *)zIn)
@@ -33640,7 +35295,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.
@@ -33684,6 +35339,19 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** Return true if the floating point value is NaN or +Inf or -Inf.
+*/
+SQLITE_PRIVATE int sqlite3IsOverflow(double x){
+ int rc; /* The value return */
+ u64 y;
+ memcpy(&y,&x,sizeof(y));
+ rc = IsOvfl(y);
+ return rc;
+}
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
@@ -33757,6 +35425,23 @@ SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){
*/
SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){
if( rc==SQLITE_IOERR_NOMEM ) return;
+#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
+ if( rc==SQLITE_IOERR_IN_PAGE ){
+ int ii;
+ int iErr;
+ sqlite3BtreeEnterAll(db);
+ for(ii=0; iinDb; ii++){
+ if( db->aDb[ii].pBt ){
+ iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt));
+ if( iErr ){
+ db->iSysErrno = iErr;
+ }
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+ return;
+ }
+#endif
rc &= 0xff;
if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
@@ -33801,12 +35486,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
}
@@ -33906,6 +35595,44 @@ SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
sqlite3Dequote(p->u.zToken);
}
+/*
+** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken
+** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those
+** that contain '_' characters that must be removed before further processing.
+*/
+SQLITE_PRIVATE void sqlite3DequoteNumber(Parse *pParse, Expr *p){
+ assert( p!=0 || pParse->db->mallocFailed );
+ if( p ){
+ const char *pIn = p->u.zToken;
+ char *pOut = p->u.zToken;
+ int bHex = (pIn[0]=='0' && (pIn[1]=='x' || pIn[1]=='X'));
+ int iValue;
+ assert( p->op==TK_QNUMBER );
+ p->op = TK_INTEGER;
+ do {
+ if( *pIn!=SQLITE_DIGIT_SEPARATOR ){
+ *pOut++ = *pIn;
+ if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT;
+ }else{
+ if( (bHex==0 && (!sqlite3Isdigit(pIn[-1]) || !sqlite3Isdigit(pIn[1])))
+ || (bHex==1 && (!sqlite3Isxdigit(pIn[-1]) || !sqlite3Isxdigit(pIn[1])))
+ ){
+ sqlite3ErrorMsg(pParse, "unrecognized token: \"%s\"", p->u.zToken);
+ }
+ }
+ }while( *pIn++ );
+ if( bHex ) p->op = TK_INTEGER;
+
+ /* tag-20240227-a: If after dequoting, the number is an integer that
+ ** fits in 32 bits, then it must be converted into EP_IntValue. Other
+ ** parts of the code expect this. See also tag-20240227-b. */
+ if( p->op==TK_INTEGER && sqlite3GetInt32(p->u.zToken, &iValue) ){
+ p->u.iValue = iValue;
+ p->flags |= EP_IntValue;
+ }
+ }
+}
+
/*
** If the input token p is quoted, try to adjust the token to remove
** the quotes. This is not always possible:
@@ -34002,43 +35729,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;
}
/*
@@ -34079,14 +35803,15 @@ 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 */
+ u64 s2; /* round-tripped significand */
+ double rr[2];
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
@@ -34124,7 +35849,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-0x7ff)/10) ){
+ s *= 10;
+ e--;
+ }
+ while( e<0 && (s%10)==0 ){
+ s /= 10;
+ e++;
+ }
- if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
- result = (double)s;
- }else{
- /* attempt to handle extremely small/large numbers better */
- if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
- if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
- if( esign<0 ){
- result = s / scale;
- result /= 1.0e+308;
- }else{
- result = s * scale;
- result *= 1.0e+308;
- }
- }else{ assert( e>=342 );
- if( esign<0 ){
- result = 0.0*s;
- }else{
-#ifdef INFINITY
- result = INFINITY*s;
-#else
- result = 1e308*1e308*s; /* Infinity */
+ rr[0] = (double)s;
+ assert( sizeof(s2)==sizeof(rr[0]) );
+#ifdef SQLITE_DEBUG
+ rr[1] = 18446744073709549568.0;
+ memcpy(&s2, &rr[1], sizeof(s2));
+ assert( s2==0x43efffffffffffffLL );
#endif
- }
- }
- }else{
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
- if( esign<0 ){
- result = s / scale;
- }else{
- result = s * scale;
- }
- }
- }
+ /* Largest double that can be safely converted to u64
+ ** vvvvvvvvvvvvvvvvvvvvvv */
+ if( rr[0]<=18446744073709549568.0 ){
+ s2 = (u64)rr[0];
+ rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
+ }else{
+ rr[1] = 0.0;
}
+ assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
- /* store the result */
- *pResult = result;
+ 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) );
- /* 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 ){
@@ -34286,13 +36008,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;
}
/*
@@ -34385,7 +36109,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;
@@ -34457,11 +36181,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);
}
}
@@ -34493,7 +36221,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 ){
@@ -34540,6 +36268,142 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
return x;
}
+/*
+** Decode a floating-point value into an approximate decimal
+** representation.
+**
+** If iRound<=0 then round to -iRound significant digits to the
+** the left of the decimal point, or to a maximum of mxRound total
+** significant digits.
+**
+** If iRound>0 round to min(iRound,mxRound) significant digits total.
+**
+** mxRound must be positive.
+**
+** The significant digits of the decimal representation are
+** stored in p->z[] which is a often (but not always) a pointer
+** into the middle of p->zBuf[]. There are p->n significant digits.
+** The p->z[] array is *not* zero-terminated.
+*/
+SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
+ int i;
+ u64 v;
+ int e, exp = 0;
+ double rr[2];
+
+ p->isSpecial = 0;
+ p->z = p->zBuf;
+ assert( mxRound>0 );
+
+ /* Convert negative numbers to positive. Deal with Infinity, 0.0, and
+ ** NaN. */
+ if( r<0.0 ){
+ p->sign = '-';
+ r = -r;
+ }else if( r==0.0 ){
+ p->sign = '+';
+ p->n = 1;
+ p->iDP = 1;
+ p->z = "0";
+ return;
+ }else{
+ p->sign = '+';
+ }
+ memcpy(&v,&r,8);
+ e = v>>52;
+ if( (e&0x7ff)==0x7ff ){
+ p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
+ p->n = 0;
+ p->iDP = 0;
+ return;
+ }
+
+ /* Multiply r by powers of ten until it lands somewhere in between
+ ** 1.0e+19 and 1.0e+17.
+ **
+ ** Use Dekker-style double-double computation to increase the
+ ** precision.
+ **
+ ** The error terms on constants like 1.0e+100 computed using the
+ ** decimal extension, for example as follows:
+ **
+ ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
+ */
+ rr[0] = r;
+ rr[1] = 0.0;
+ if( rr[0]>9.223372036854774784e+18 ){
+ while( rr[0]>9.223372036854774784e+118 ){
+ exp += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( rr[0]>9.223372036854774784e+28 ){
+ exp += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( rr[0]>9.223372036854774784e+18 ){
+ exp += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
+ }
+ }else{
+ while( rr[0]<9.223372036854774784e-83 ){
+ exp -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( rr[0]<9.223372036854774784e+07 ){
+ exp -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( rr[0]<9.22337203685477478e+17 ){
+ exp -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
+ }
+ }
+ v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
+
+ /* Extract significant digits. */
+ i = sizeof(p->zBuf)-1;
+ assert( v>0 );
+ while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; }
+ assert( i>=0 && izBuf)-1 );
+ p->n = sizeof(p->zBuf) - 1 - i;
+ assert( p->n>0 );
+ assert( p->nzBuf) );
+ p->iDP = p->n + exp;
+ if( iRound<=0 ){
+ iRound = p->iDP - iRound;
+ if( iRound==0 && p->zBuf[i+1]>='5' ){
+ iRound = 1;
+ p->zBuf[i--] = '0';
+ p->n++;
+ p->iDP++;
+ }
+ }
+ if( iRound>0 && (iRoundn || p->n>mxRound) ){
+ char *z = &p->zBuf[i+1];
+ if( iRound>mxRound ) iRound = mxRound;
+ p->n = iRound;
+ if( z[iRound]>='5' ){
+ int j = iRound-1;
+ while( 1 /*exit-by-break*/ ){
+ z[j]++;
+ if( z[j]<='9' ) break;
+ z[j] = '0';
+ if( j==0 ){
+ p->z[i--] = '1';
+ p->n++;
+ p->iDP++;
+ break;
+ }else{
+ j--;
+ }
+ }
+ }
+ }
+ p->z = &p->zBuf[i+1];
+ assert( i+p->n < sizeof(p->zBuf) );
+ while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
+}
+
/*
** Try to convert z into an unsigned 32-bit integer. Return true on
** success and false if there is an error.
@@ -34803,121 +36667,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;
}
/*
@@ -35068,7 +36843,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.
@@ -35354,104 +37129,6 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam
return 0;
}
-/*
-** High-resolution hardware timer used for debugging and testing only.
-*/
-#if defined(VDBE_PROFILE) \
- || defined(SQLITE_PERFORMANCE_TRACE) \
- || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-/************** Include hwtime.h in the middle of util.c *********************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if !defined(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlite3Hwtime() routine.
- **
- ** sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in util.c ***********************/
-#endif
-
/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
@@ -35553,7 +37230,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.
@@ -35772,7 +37449,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
/* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
/* 32 */ "Last" OpHelp(""),
- /* 33 */ "IfSmaller" OpHelp(""),
+ /* 33 */ "IfSizeBetween" OpHelp(""),
/* 34 */ "SorterSort" OpHelp(""),
/* 35 */ "Sort" OpHelp(""),
/* 36 */ "Rewind" OpHelp(""),
@@ -35789,16 +37466,16 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
/* 48 */ "Program" OpHelp(""),
/* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
- /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
- /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
- /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
- /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
- /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
- /* 56 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
- /* 58 */ "ElseEq" OpHelp(""),
- /* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
+ /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
+ /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
+ /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
+ /* 57 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
+ /* 59 */ "ElseEq" OpHelp(""),
/* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 62 */ "IncrVacuum" OpHelp(""),
@@ -35817,7 +37494,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 75 */ "Null" OpHelp("r[P2..P3]=NULL"),
/* 76 */ "SoftNull" OpHelp("r[P1]=NULL"),
/* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1)"),
/* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
/* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
/* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"),
@@ -35841,23 +37518,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 99 */ "ReadCookie" OpHelp(""),
/* 100 */ "SetCookie" OpHelp(""),
/* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
- /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
+ /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
/* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 115 */ "OpenDup" OpHelp(""),
+ /* 114 */ "OpenDup" OpHelp(""),
+ /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
/* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 117 */ "String8" OpHelp("r[P2]='P4'"),
- /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 118 */ "String8" OpHelp("r[P2]='P4'"),
/* 119 */ "SorterOpen" OpHelp(""),
/* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
/* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
@@ -35892,8 +37569,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 150 */ "LoadAnalysis" OpHelp(""),
/* 151 */ "DropTable" OpHelp(""),
/* 152 */ "DropIndex" OpHelp(""),
- /* 153 */ "Real" OpHelp("r[P2]=P4"),
- /* 154 */ "DropTrigger" OpHelp(""),
+ /* 153 */ "DropTrigger" OpHelp(""),
+ /* 154 */ "Real" OpHelp("r[P2]=P4"),
/* 155 */ "IntegrityCk" OpHelp(""),
/* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
/* 157 */ "Param" OpHelp(""),
@@ -35913,19 +37590,22 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 171 */ "VCreate" OpHelp(""),
/* 172 */ "VDestroy" OpHelp(""),
/* 173 */ "VOpen" OpHelp(""),
- /* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
- /* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 176 */ "VRename" OpHelp(""),
- /* 177 */ "Pagecount" OpHelp(""),
- /* 178 */ "MaxPgcnt" OpHelp(""),
- /* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
- /* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
- /* 181 */ "Trace" OpHelp(""),
- /* 182 */ "CursorHint" OpHelp(""),
- /* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
- /* 184 */ "Noop" OpHelp(""),
- /* 185 */ "Explain" OpHelp(""),
- /* 186 */ "Abortable" OpHelp(""),
+ /* 174 */ "VCheck" OpHelp(""),
+ /* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
+ /* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 177 */ "VRename" OpHelp(""),
+ /* 178 */ "Pagecount" OpHelp(""),
+ /* 179 */ "MaxPgcnt" OpHelp(""),
+ /* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
+ /* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
+ /* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
+ /* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
+ /* 184 */ "Trace" OpHelp(""),
+ /* 185 */ "CursorHint" OpHelp(""),
+ /* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 187 */ "Noop" OpHelp(""),
+ /* 188 */ "Explain" OpHelp(""),
+ /* 189 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -36939,7 +38619,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:
**
@@ -36989,7 +38669,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
@@ -37130,7 +38810,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){
# endif
#else /* !SQLITE_WASI */
# ifndef HAVE_FCHMOD
-# define HAVE_FCHMOD
+# define HAVE_FCHMOD 1
# endif
#endif /* SQLITE_WASI */
@@ -37239,7 +38919,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-#ifndef SQLITE_DISABLE_DIRSYNC
+#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX)
# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
#else
# define UNIXFILE_DIRSYNC 0x00
@@ -37526,7 +39206,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.
*/
@@ -38048,7 +39728,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.
@@ -38062,7 +39742,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
@@ -38212,8 +39892,12 @@ static int unixLogErrorAtLine(
** available, the error message will often be an empty string. Not a
** huge problem. Incorrectly concluding that the GNU version is available
** could lead to a segfault though.
+ **
+ ** Forum post 3f13857fa4062301 reports that the Android SDK may use
+ ** int-type return, depending on its version.
*/
-#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
+#if (defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)) \
+ && !defined(ANDROID) && !defined(__ANDROID__)
zErr =
# endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
@@ -38264,7 +39948,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;
@@ -38577,7 +40261,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
if( pInode->bProcessLock==0 ){
struct flock lock;
- assert( pInode->nLock==0 );
+ /* assert( pInode->nLock==0 ); <-- Not true if unix-excl READONLY used */
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
@@ -38627,7 +40311,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.
**
@@ -38635,7 +40319,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
@@ -38656,7 +40340,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.
*/
@@ -38684,7 +40368,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 );
@@ -39192,26 +40876,22 @@ static int nolockClose(sqlite3_file *id) {
/*
** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-**
-** In dotfile locking, either a lock exists or it does not. So in this
-** variation of CheckReservedLock(), *pResOut is set to true if any lock
-** is held on the file and false if the file is unlocked.
+** file by this or any other process. If the caller holds a SHARED
+** or greater lock when it is called, then it is assumed that no other
+** client may hold RESERVED. Or, if the caller holds no lock, then it
+** is assumed another client holds RESERVED if the lock-file exists.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
unixFile *pFile = (unixFile*)id;
-
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
- assert( pFile );
- reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
- *pResOut = reserved;
- return rc;
+ if( pFile->eFileLock>=SHARED_LOCK ){
+ *pResOut = 0;
+ }else{
+ *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
+ return SQLITE_OK;
}
/*
@@ -39381,54 +41061,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+#ifdef SQLITE_DEBUG
unixFile *pFile = (unixFile*)id;
+#else
+ UNUSED_PARAMETER(id);
+#endif
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
+ assert( pFile->eFileLock<=SHARED_LOCK );
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
+ /* The flock VFS only ever takes exclusive locks (see function flockLock).
+ ** Therefore, if this connection is holding any lock at all, no other
+ ** connection may be holding a RESERVED lock. So set *pResOut to 0
+ ** in this case.
+ **
+ ** Or, this connection may be holding no lock. In that case, set *pResOut to
+ ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
+ ** db in order to roll the hot journal back. If there is another connection
+ ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
+ ** the user. With other VFS, we try to avoid this, in order to allow a reader
+ ** to proceed while a writer is preparing its transaction. But that won't
+ ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
+ ** not a problem in this case. */
+ *pResOut = 0;
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
+ return SQLITE_OK;
}
/*
@@ -39902,7 +41561,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 );
@@ -40018,7 +41677,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,
@@ -40067,9 +41726,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,
@@ -40085,9 +41741,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
@@ -40136,9 +41789,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);
}
@@ -40239,12 +41889,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.
*/
@@ -40319,7 +41963,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 ){
@@ -40471,7 +42115,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 ){
@@ -40593,7 +42237,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
{
@@ -40915,7 +42559,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
static int unixFcntlExternalReader(unixFile*, int*);
#endif
@@ -40940,6 +42584,11 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+ case SQLITE_FCNTL_NULL_IO: {
+ osClose(pFile->h);
+ pFile->h = -1;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -40986,7 +42635,13 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
int iOld = pFile->iBusyTimeout;
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
pFile->iBusyTimeout = *(int*)pArg;
+#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
+ pFile->iBusyTimeout = !!(*(int*)pArg);
+#else
+# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
+#endif
*(int*)pArg = iOld;
return SQLITE_OK;
}
@@ -41036,7 +42691,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
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
#else
*(int*)pArg = 0;
@@ -41075,6 +42730,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
+ pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ;
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
@@ -41125,7 +42781,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -41133,7 +42789,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -41209,7 +42865,7 @@ static int unixGetpagesize(void){
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
/*
** Object used to represent an shared memory buffer.
@@ -41239,6 +42895,25 @@ static int unixGetpagesize(void){
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
+**
+** aLock[SQLITE_SHM_NLOCK]:
+** This array records the various locks held by clients on each of the
+** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no
+** locks are held by the process on this slot. If it is set to -1, then
+** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[]
+** value is set to a positive value, then it is the number of shared
+** locks currently held on the slot.
+**
+** aMutex[SQLITE_SHM_NLOCK]:
+** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex
+** pShmMutex is used to protect the aLock[] array and the right to
+** call fcntl() on unixShmNode.hShm to obtain or release locks.
+**
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array
+** of mutexes - one for each locking slot. To read or write locking
+** slot aLock[iSlot], the caller must hold the corresponding mutex
+** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a
+** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
@@ -41252,10 +42927,11 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK];
+#endif
int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
- u8 exclMask; /* Mask of exclusive locks held */
- u8 sharedMask; /* Mask of shared locks held */
u8 nextShmId; /* Next available unixShm.id value */
#endif
};
@@ -41338,16 +43014,35 @@ static int unixShmSystemLock(
struct flock f; /* The posix advisory locking structure */
int rc = SQLITE_OK; /* Result code form fcntl() */
- /* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
- assert( pShmNode->nRef>0 || unixMutexHeld() );
+
+ /* Assert that the parameters are within expected range and that the
+ ** correct mutex or mutexes are held. */
+ assert( pShmNode->nRef>=0 );
+ assert( (ofst==UNIX_SHM_DMS && n==1)
+ || (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK))
+ );
+ if( ofst==UNIX_SHM_DMS ){
+ assert( pShmNode->nRef>0 || unixMutexHeld() );
+ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
+ }else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int ii;
+ for(ii=ofst-UNIX_SHM_BASE; iiaMutex[ii]) );
+ }
+#else
+ assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
+ assert( pShmNode->nRef>0 );
+#endif
+ }
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
+ assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) );
if( pShmNode->hShm>=0 ){
int res;
@@ -41358,7 +43053,7 @@ static int unixShmSystemLock(
f.l_len = n;
res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
if( res==-1 ){
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1
rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
#else
rc = SQLITE_BUSY;
@@ -41366,39 +43061,28 @@ static int unixShmSystemLock(
}
}
- /* Update the global lock state and do debug tracing */
+ /* Do debug tracing */
#ifdef SQLITE_DEBUG
- { u16 mask;
OSTRACE(("SHM-LOCK "));
- mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<exclMask &= ~mask;
- pShmNode->sharedMask &= ~mask;
+ OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1));
}else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock %d ok", ofst));
- pShmNode->exclMask &= ~mask;
- pShmNode->sharedMask |= mask;
+ OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1));
}else{
assert( lockType==F_WRLCK );
- OSTRACE(("write-lock %d ok", ofst));
- pShmNode->exclMask |= mask;
- pShmNode->sharedMask &= ~mask;
+ OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1));
}
}else{
if( lockType==F_UNLCK ){
- OSTRACE(("unlock %d failed", ofst));
+ OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1));
}else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock failed"));
+ OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1));
}else{
assert( lockType==F_WRLCK );
- OSTRACE(("write-lock %d failed", ofst));
+ OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1));
}
}
- OSTRACE((" - afterwards %03x,%03x\n",
- pShmNode->sharedMask, pShmNode->exclMask));
- }
#endif
return rc;
@@ -41435,6 +43119,11 @@ static void unixShmPurge(unixFile *pFd){
int i;
assert( p->pInode==pFd->pInode );
sqlite3_mutex_free(p->pShmMutex);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ for(i=0; iaMutex[i]);
+ }
+#endif
for(i=0; inRegion; i+=nShmPerMap){
if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
@@ -41494,7 +43183,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
pShmNode->isUnlocked = 1;
rc = SQLITE_READONLY_CANTINIT;
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* Do not use a blocking lock here. If the lock cannot be obtained
+ ** immediately, it means some other connection is truncating the
+ ** *-shm file. And after it has done so, it will not release its
+ ** lock, but only downgrade it to a shared lock. So no point in
+ ** blocking here. The call below to obtain the shared DMS lock may
+ ** use a blocking lock. */
+ int iSaveTimeout = pDbFd->iBusyTimeout;
+ pDbFd->iBusyTimeout = 0;
+#endif
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ pDbFd->iBusyTimeout = iSaveTimeout;
+#endif
/* The first connection to attach must truncate the -shm file. We
** truncate to 3 bytes (an arbitrary small number, less than the
** -shm header size) rather than 0 as a system debugging aid, to
@@ -41615,6 +43317,18 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ {
+ int ii;
+ for(ii=0; iiaMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->aMutex[ii]==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ goto shm_open_err;
+ }
+ }
+ }
+#endif
}
if( pInode->bProcessLock==0 ){
@@ -41836,9 +43550,11 @@ static int unixShmMap(
*/
#ifdef SQLITE_DEBUG
static int assertLockingArrayOk(unixShmNode *pShmNode){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ return 1;
+#else
unixShm *pX;
int aLock[SQLITE_SHM_NLOCK];
- assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
memset(aLock, 0, sizeof(aLock));
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
@@ -41856,13 +43572,14 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){
assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
+#endif
}
#endif
/*
** Change the lock state for a shared-memory segment.
**
-** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
+** Note that the relationship between SHARED and EXCLUSIVE locks is a little
** different here than in posix. In xShmLock(), one can go from unlocked
** to shared and back or from unlocked to exclusive and back. But one may
** not go from shared to exclusive or from exclusive to shared.
@@ -41877,7 +43594,7 @@ static int unixShmLock(
unixShm *p; /* The shared memory being locked */
unixShmNode *pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
+ u16 mask = (1<<(ofst+n)) - (1<pShm;
@@ -41912,88 +43629,151 @@ static int unixShmLock(
** It is not permitted to block on the RECOVER lock.
*/
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
- (ofst!=2) /* not RECOVER */
- && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
- && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
- && (ofst<3 || (p->exclMask|p->sharedMask)<(1<exclMask|p->sharedMask);
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
+ (ofst!=2) /* not RECOVER */
+ && (ofst!=1 || lockMask==0 || lockMask==2)
+ && (ofst!=0 || lockMask<3)
+ && (ofst<3 || lockMask<(1<1 || mask==(1<pShmMutex);
- assert( assertLockingArrayOk(pShmNode) );
- if( flags & SQLITE_SHM_UNLOCK ){
- if( (p->exclMask|p->sharedMask) & mask ){
- int ii;
- int bUnlock = 1;
+ /* Check if there is any work to do. There are three cases:
+ **
+ ** a) An unlock operation where there are locks to unlock,
+ ** b) An shared lock where the requested lock is not already held
+ ** c) An exclusive lock where the requested lock is not already held
+ **
+ ** The SQLite core never requests an exclusive lock that it already holds.
+ ** This is assert()ed below.
+ */
+ assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
+ || 0==(p->exclMask & mask)
+ );
+ if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
+ || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
+ || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
+ ){
- for(ii=ofst; ii((p->sharedMask & (1<aMutex[iMutex]);
+ if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes;
+ }else{
+ sqlite3_mutex_enter(pShmNode->aMutex[iMutex]);
}
+ }
+#else
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
+#endif
- if( bUnlock ){
- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
- if( rc==SQLITE_OK ){
- memset(&aLock[ofst], 0, sizeof(int)*n);
+ if( ALWAYS(rc==SQLITE_OK) ){
+ if( flags & SQLITE_SHM_UNLOCK ){
+ /* Case (a) - unlock. */
+ int bUnlock = 1;
+ assert( (p->exclMask & p->sharedMask)==0 );
+ assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
+ assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
+
+ /* If this is a SHARED lock being unlocked, it is possible that other
+ ** clients within this process are holding the same SHARED lock. In
+ ** this case, set bUnlock to 0 so that the posix lock is not removed
+ ** from the file-descriptor below. */
+ if( flags & SQLITE_SHM_SHARED ){
+ assert( n==1 );
+ assert( aLock[ofst]>=1 );
+ if( aLock[ofst]>1 ){
+ bUnlock = 0;
+ aLock[ofst]--;
+ p->sharedMask &= ~mask;
+ }
}
- }else if( ALWAYS(p->sharedMask & (1<1 );
- aLock[ofst]--;
- }
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- assert( n==1 );
- assert( (p->exclMask & (1<sharedMask & mask)==0 ){
- if( aLock[ofst]<0 ){
- rc = SQLITE_BUSY;
- }else if( aLock[ofst]==0 ){
- rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
- }
+ if( bUnlock ){
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ memset(&aLock[ofst], 0, sizeof(int)*n);
+ p->sharedMask &= ~mask;
+ p->exclMask &= ~mask;
+ }
+ }
+ }else if( flags & SQLITE_SHM_SHARED ){
+ /* Case (b) - a shared lock. */
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- aLock[ofst]++;
- }
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away. */
- int ii;
- for(ii=ofst; iisharedMask & mask)==0 );
- if( ALWAYS((p->exclMask & (1<sharedMask |= mask;
+ aLock[ofst]++;
+ }
+ }else{
+ /* Case (c) - an exclusive lock. */
+ int ii;
+
+ assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) );
assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
+ assert( (p->exclMask & mask)==0 );
+
+ /* Make sure no sibling connections hold locks that will block this
+ ** lock. If any do, return SQLITE_BUSY right away. */
for(ii=ofst; iiexclMask |= mask;
+ for(ii=ofst; ii=ofst; iMutex--){
+ sqlite3_mutex_leave(pShmNode->aMutex[iMutex]);
+ }
+#else
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
+#endif
}
- assert( assertLockingArrayOk(pShmNode) );
- sqlite3_mutex_leave(pShmNode->pShmMutex);
+
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
@@ -42243,11 +44023,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->mmapSizeMax>0 ){
+ /* Ensure that there is always at least a 256 byte buffer of addressable
+ ** memory following the returned page. If the database is corrupt,
+ ** SQLite may overread the page slightly (in practice only a few bytes,
+ ** but 256 is safe, round, number). */
+ const int nEofBuffer = 256;
if( pFd->pMapRegion==0 ){
int rc = unixMapfile(pFd, -1);
if( rc!=SQLITE_OK ) return rc;
}
- if( pFd->mmapSize >= iOff+nAmt ){
+ if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
}
@@ -43191,12 +44976,19 @@ static int unixOpen(
rc = SQLITE_READONLY_DIRECTORY;
}else if( errno!=EISDIR && isReadWrite ){
/* Failed to open the file for read/write access. Try read-only. */
+ UnixUnusedFd *pReadonly = 0;
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
- fd = robust_open(zName, openFlags, openMode);
+ pReadonly = findReusableFd(zName, flags);
+ if( pReadonly ){
+ fd = pReadonly->fd;
+ sqlite3_free(pReadonly);
+ }else{
+ fd = robust_open(zName, openFlags, openMode);
+ }
}
}
if( fd<0 ){
@@ -43638,12 +45430,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
@@ -46233,7 +48030,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.
*/
@@ -47813,7 +49610,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 ){
@@ -47891,7 +49688,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 ){
@@ -48001,7 +49798,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;
@@ -48060,7 +49857,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;
@@ -48417,7 +50214,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 ){
@@ -48673,6 +50470,11 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
#endif
+ case SQLITE_FCNTL_NULL_IO: {
+ (void)osCloseHandle(pFile->h);
+ pFile->h = NULL;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
@@ -48734,7 +50536,7 @@ static int winSectorSize(sqlite3_file *id){
*/
static int winDeviceCharacteristics(sqlite3_file *id){
winFile *p = (winFile*)id;
- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ |
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
@@ -49595,6 +51397,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->mmapSizeMax>0 ){
+ /* Ensure that there is always at least a 256 byte buffer of addressable
+ ** memory following the returned page. If the database is corrupt,
+ ** SQLite may overread the page slightly (in practice only a few bytes,
+ ** but 256 is safe, round, number). */
+ const int nEofBuffer = 256;
if( pFd->pMapRegion==0 ){
int rc = winMapfile(pFd, -1);
if( rc!=SQLITE_OK ){
@@ -49603,7 +51410,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
return rc;
}
}
- if( pFd->mmapSize >= iOff+nAmt ){
+ if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
assert( pFd->pMapRegion!=0 );
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
@@ -49821,6 +51628,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;
@@ -50033,7 +51841,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;
@@ -50113,7 +51924,7 @@ static int winOpen(
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
- int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int eType = flags&0x0FFF00; /* Type of file to open */
#endif
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
@@ -50271,7 +52082,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;
}
@@ -50288,7 +52099,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;
}
@@ -50308,7 +52119,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;
}
@@ -50531,6 +52342,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));
@@ -52071,6 +53889,14 @@ SQLITE_API unsigned char *sqlite3_serialize(
pOut = 0;
}else{
sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ if( sz==0 ){
+ sqlite3_reset(pStmt);
+ sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
+ rc = sqlite3_step(pStmt);
+ if( rc==SQLITE_ROW ){
+ sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ }
+ }
if( piSize ) *piSize = sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
pOut = 0;
@@ -52391,7 +54217,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;
@@ -52687,11 +54513,15 @@ struct PCache {
PgHdr *pPg;
unsigned char *a;
int j;
- pPg = (PgHdr*)pLower->pExtra;
- printf("%3lld: 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;
@@ -52704,9 +54534,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);
}
}
@@ -52721,7 +54550,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){
@@ -52729,6 +54558,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
/*
@@ -52749,7 +54588,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 );
@@ -52885,7 +54724,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. */
@@ -53116,6 +54955,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, 8);
+ assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) );
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
@@ -53373,7 +55213,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.
**
@@ -53613,7 +55453,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
@@ -53647,7 +55487,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.
**
@@ -53862,7 +55702,8 @@ static int pcache1InitBulk(PCache1 *pCache){
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
- pX->page.pExtra = &pX[1];
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
@@ -53999,7 +55840,8 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
if( pPg==0 ) return 0;
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
p->page.pBuf = pPg;
- p->page.pExtra = &p[1];
+ p->page.pExtra = (u8*)p + ROUND8(sizeof(*p));
+ assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) );
p->isBulkLocal = 0;
p->isAnchor = 0;
p->pLruPrev = 0; /* Initializing this saves a valgrind error */
@@ -54867,7 +56709,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.
@@ -55399,6 +57241,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
# define sqlite3WalFramesize(z) 0
# define sqlite3WalFindFrame(x,y,z) 0
# define sqlite3WalFile(x) 0
+# undef SQLITE_USE_SEH
#else
#define WAL_SAVEPOINT_NDATA 4
@@ -55505,6 +57348,10 @@ SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
#endif
+#ifdef SQLITE_USE_SEH
+SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*);
+#endif
+
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* SQLITE_WAL_H */
@@ -55790,7 +57637,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.
@@ -56177,7 +58024,7 @@ struct Pager {
char *zJournal; /* Name of the journal file */
int (*xBusyHandler)(void*); /* Function to call when busy */
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
- int aStat[4]; /* Total cache hits, misses, writes, spills */
+ u32 aStat[4]; /* Total cache hits, misses, writes, spills */
#ifdef SQLITE_TEST
int nRead; /* Database pages read */
#endif
@@ -56278,40 +58125,33 @@ static const unsigned char aJournalMagic[] = {
# define USEFETCH(x) 0
#endif
-/*
-** The argument to this macro is a file descriptor (type sqlite3_file*).
-** Return 0 if it is not open, or non-zero (but not 1) if it is.
-**
-** This is so that expressions can be written as:
-**
-** if( isOpen(pPager->jfd) ){ ...
-**
-** instead of
-**
-** if( pPager->jfd->pMethods ){ ...
-*/
-#define isOpen(pFd) ((pFd)->pMethods!=0)
-
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
** Return true if page pgno can be read directly from the database file
** by the b-tree layer. This is the case if:
**
-** * the database file is open,
-** * there are no dirty pages in the cache, and
-** * the desired page is not currently in the wal file.
+** (1) the database file is open
+** (2) the VFS for the database is able to do unaligned sub-page reads
+** (3) there are no dirty pages in the cache, and
+** (4) the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
- if( pPager->fd->pMethods==0 ) return 0;
- if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
+ assert( pPager!=0 );
+ assert( pPager->fd!=0 );
+ if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
- int rc;
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return (rc==SQLITE_OK && iRead==0);
+ (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ if( iRead ) return 0; /* Case (4) */
}
#endif
+ assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
+ if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
+ & SQLITE_IOCAP_SUBPAGE_READ)==0 ){
+ return 0; /* Case (2) */
+ }
return 1;
}
#endif
@@ -56981,9 +58821,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 */
@@ -57163,7 +59026,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),
@@ -57216,7 +59079,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
@@ -57386,7 +59249,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.
@@ -57547,7 +59410,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
}
pPager->journalOff = 0;
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
+ || (pPager->exclusiveMode && pPager->journalModetempFile);
pPager->journalOff = 0;
@@ -57627,6 +59490,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.
@@ -57655,13 +59521,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
@@ -58094,6 +59975,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)
@@ -58625,7 +60508,7 @@ static int pagerWalFrames(
assert( pPager->pWal );
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 );
}
@@ -58756,7 +60639,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
@@ -59511,6 +61394,7 @@ static int pagerAcquireMapPage(
return SQLITE_NOMEM_BKPT;
}
p->pExtra = (void *)&p[1];
+ assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) );
p->flags = PGHDR_MMAP;
p->nRef = 1;
p->pPager = pPager;
@@ -60166,11 +62050,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 */
@@ -60289,12 +62169,13 @@ 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 */
@@ -60315,7 +62196,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
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 */
@@ -60369,9 +62250,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,
@@ -60508,15 +62387,18 @@ 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){
Pager *pPager;
+ const char *p;
while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
zName--;
}
- pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
+ p = zName - 4 - sizeof(Pager*);
+ assert( EIGHT_BYTE_ALIGNMENT(p) );
+ pPager = *(Pager**)p;
return pPager->fd;
}
@@ -61011,6 +62893,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 ){
@@ -61146,8 +63032,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
}
/*
@@ -61175,10 +63073,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
@@ -61194,7 +63094,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,6 +63921,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);
}
@@ -62255,11 +64162,11 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
a[4] = pPager->eState;
a[5] = pPager->errCode;
- a[6] = pPager->aStat[PAGER_STAT_HIT];
- a[7] = pPager->aStat[PAGER_STAT_MISS];
+ a[6] = (int)pPager->aStat[PAGER_STAT_HIT] & 0x7fffffff;
+ a[7] = (int)pPager->aStat[PAGER_STAT_MISS] & 0x7fffffff;
a[8] = 0; /* Used to be pPager->nOvfl */
a[9] = pPager->nRead;
- a[10] = pPager->aStat[PAGER_STAT_WRITE];
+ a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff;
return a;
}
#endif
@@ -62275,7 +64182,7 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
** reset parameter is non-zero, the cache hit or miss count is zeroed before
** returning.
*/
-SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
+SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){
assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
|| eStat==SQLITE_DBSTATUS_CACHE_MISS
@@ -62511,7 +64418,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
** This will be either the rollback journal or the WAL file.
*/
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
-#if SQLITE_OMIT_WAL
+#ifdef SQLITE_OMIT_WAL
return pPager->jfd;
#else
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
@@ -62787,7 +64694,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.
*/
@@ -62832,7 +64739,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);
}
}
@@ -62954,13 +64861,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;
@@ -63213,6 +65122,12 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
}
#endif
+#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
+SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){
+ return sqlite3WalSystemErrno(pPager->pWal);
+}
+#endif
+
#endif /* SQLITE_OMIT_DISKIO */
/************** End of pager.c ***********************************************/
@@ -63263,7 +65178,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
**
** Immediately following the wal-header are zero or more frames. Each
-** frame consists of a 24-byte frame-header followed by a bytes
+** frame consists of a 24-byte frame-header followed by bytes
** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
@@ -63503,7 +65418,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
@@ -63579,7 +65494,7 @@ struct WalIndexHdr {
** 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.
**
@@ -63747,11 +65662,20 @@ struct Wal {
u32 iReCksum; /* On commit, recalculate checksums from here */
const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
+#ifdef SQLITE_USE_SEH
+ u32 lockMask; /* Mask of locks held */
+ void *pFree; /* Pointer to sqlite3_free() if exception thrown */
+ u32 *pWiValue; /* Value to write into apWiData[iWiPg] */
+ int iWiPg; /* Write pWiValue into apWiData[iWiPg] */
+ int iSysErrno; /* System error code following exception */
+#endif
#ifdef SQLITE_DEBUG
+ int nSehTry; /* Number of nested SEH_TRY{} blocks */
u8 lockError; /* True if a locking error has occurred */
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
+ int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3 *db;
@@ -63829,6 +65753,113 @@ 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
+#include
+
+/* Beginning of a block of code in which an exception might occur */
+# define SEH_TRY __try { \
+ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \
+ VVA_ONLY(pWal->nSehTry++);
+
+/* The end of a block of code in which an exception might occur */
+# define SEH_EXCEPT(X) \
+ VVA_ONLY(pWal->nSehTry--); \
+ assert( pWal->nSehTry==0 ); \
+ } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X }
+
+/* Simulate a memory-mapping fault in the -shm file for testing purposes */
+# define SEH_INJECT_FAULT sehInjectFault(pWal)
+
+/*
+** The second argument is the return value of GetExceptionCode() for the
+** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code
+** indicates that the exception may have been caused by accessing the *-shm
+** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise.
+*/
+static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){
+ VVA_ONLY(pWal->nSehTry--);
+ if( eCode==EXCEPTION_IN_PAGE_ERROR ){
+ if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){
+ /* From MSDN: For this type of exception, the first element of the
+ ** ExceptionInformation[] array is a read-write flag - 0 if the exception
+ ** was thrown while reading, 1 if while writing. The second element is
+ ** the virtual address being accessed. The "third array element specifies
+ ** the underlying NTSTATUS code that resulted in the exception". */
+ pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2];
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/*
+** If one is configured, invoke the xTestCallback callback with 650 as
+** the argument. If it returns true, throw the same exception that is
+** thrown by the system if the *-shm file mapping is accessed after it
+** has been invalidated.
+*/
+static void sehInjectFault(Wal *pWal){
+ int res;
+ assert( pWal->nSehTry>0 );
+
+ res = sqlite3FaultSim(650);
+ if( res!=0 ){
+ ULONG_PTR aArg[3];
+ aArg[0] = 0;
+ aArg[1] = 0;
+ aArg[2] = (ULONG_PTR)res;
+ RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg);
+ }
+}
+
+/*
+** There are two ways to use this macro. To set a pointer to be freed
+** if an exception is thrown:
+**
+** SEH_FREE_ON_ERROR(0, pPtr);
+**
+** and to cancel the same:
+**
+** SEH_FREE_ON_ERROR(pPtr, 0);
+**
+** In the first case, there must not already be a pointer registered to
+** be freed. In the second case, pPtr must be the registered pointer.
+*/
+#define SEH_FREE_ON_ERROR(X,Y) \
+ assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y
+
+/*
+** There are two ways to use this macro. To arrange for pWal->apWiData[iPg]
+** to be set to pValue if an exception is thrown:
+**
+** SEH_SET_ON_ERROR(iPg, pValue);
+**
+** and to cancel the same:
+**
+** SEH_SET_ON_ERROR(0, 0);
+*/
+#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y
+
+#else
+# define SEH_TRY VVA_ONLY(pWal->nSehTry++);
+# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 );
+# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 );
+# define SEH_FREE_ON_ERROR(X,Y)
+# define SEH_SET_ON_ERROR(X,Y)
+#endif /* ifdef SQLITE_USE_SEH */
+
+
/*
** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
@@ -63901,6 +65932,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);
}
@@ -63912,6 +65944,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]);
}
@@ -63920,6 +65953,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];
}
@@ -63965,19 +65999,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( aDatalockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
+#ifdef SQLITE_USE_SEH
+ if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx);
+#endif
return rc;
}
static void walUnlockShared(Wal *pWal, int lockIdx){
if( pWal->exclusiveMode ) return;
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
+#ifdef SQLITE_USE_SEH
+ pWal->lockMask &= ~(1 << lockIdx);
+#endif
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
@@ -64172,12 +66233,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
walLockName(lockIdx), n, rc ? "failed" : "ok"));
VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
+#ifdef SQLITE_USE_SEH
+ if( rc==SQLITE_OK ){
+ pWal->lockMask |= (((1<exclusiveMode ) return;
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
+#ifdef SQLITE_USE_SEH
+ pWal->lockMask &= ~(((1<apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
}
@@ -64528,6 +66598,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;
@@ -64546,6 +66617,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++){
@@ -64573,6 +66645,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
@@ -64603,9 +66676,11 @@ static int walIndexRecover(Wal *pWal){
}
}
#endif
+ SEH_INJECT_FAULT;
if( iFrame<=iLast ) break;
}
+ SEH_FREE_ON_ERROR(aFrame, 0);
sqlite3_free(aFrame);
}
@@ -64633,6 +66708,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;
@@ -64790,7 +66866,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
}
/*
-** 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.
*/
SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
if( pWal ) pWal->mxWalSize = iLimit;
@@ -65016,23 +67092,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;
}
@@ -65071,6 +67139,19 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+
+
+/*
+** Attempt to enable blocking locks that block for nMs ms. Return 1 if
+** blocking locks are successfully enabled, or 0 otherwise.
+*/
+static int walEnableBlockingMs(Wal *pWal, int nMs){
+ int rc = sqlite3OsFileControl(
+ pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs
+ );
+ return (rc==SQLITE_OK);
+}
+
/*
** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
** they are supported by the VFS, and (b) the database handle is configured
@@ -65082,11 +67163,7 @@ static int walEnableBlocking(Wal *pWal){
if( pWal->db ){
int tmout = pWal->db->busyTimeout;
if( tmout ){
- int rc;
- rc = sqlite3OsFileControl(
- pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
- );
- res = (rc==SQLITE_OK);
+ res = walEnableBlockingMs(pWal, tmout);
}
}
return res;
@@ -65135,20 +67212,10 @@ SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
pWal->db = db;
}
-/*
-** Take an exclusive WRITE lock. Blocking if so configured.
-*/
-static int walLockWriter(Wal *pWal){
- int rc;
- walEnableBlocking(pWal);
- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
- walDisableBlocking(pWal);
- return rc;
-}
#else
# define walEnableBlocking(x) 0
# define walDisableBlocking(x)
-# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
+# define walEnableBlockingMs(pWal, ms) 0
# define sqlite3WalDb(pWal, db)
#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
@@ -65288,13 +67355,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;
@@ -65315,8 +67382,7 @@ static int walCheckpoint(
&& (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));
@@ -65347,6 +67413,7 @@ static int walCheckpoint(
while( rc==SQLITE_OK && 0==walIteratorNext(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;
@@ -65376,7 +67443,7 @@ static int walCheckpoint(
}
}
if( rc==SQLITE_OK ){
- AtomicStore(&pInfo->nBackfill, mxSafeFrame);
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
}
}
@@ -65398,6 +67465,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 ){
@@ -65429,6 +67497,7 @@ static int walCheckpoint(
}
walcheckpoint_out:
+ SEH_FREE_ON_ERROR(pIter, 0);
walIteratorFree(pIter);
return rc;
}
@@ -65451,6 +67520,93 @@ static void walLimitSize(Wal *pWal, i64 nMax){
}
}
+#ifdef SQLITE_USE_SEH
+/*
+** This is the "standard" exception handler used in a few places to handle
+** an exception thrown by reading from the *-shm mapping after it has become
+** invalid in SQLITE_USE_SEH builds. It is used as follows:
+**
+** SEH_TRY { ... }
+** SEH_EXCEPT( rc = walHandleException(pWal); )
+**
+** This function does three things:
+**
+** 1) Determines the locks that should be held, based on the contents of
+** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other
+** held locks are assumed to be transient locks that would have been
+** released had the exception not been thrown and are dropped.
+**
+** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free().
+**
+** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL
+**
+** 4) Returns SQLITE_IOERR.
+*/
+static int walHandleException(Wal *pWal){
+ if( pWal->exclusiveMode==0 ){
+ static const int S = 1;
+ static const int E = (1<lockMask & ~(
+ (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
+ | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
+ | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
+ );
+ for(ii=0; iipFree);
+ pWal->pFree = 0;
+ if( pWal->pWiValue ){
+ pWal->apWiData[pWal->iWiPg] = pWal->pWiValue;
+ pWal->pWiValue = 0;
+ }
+ return SQLITE_IOERR_IN_PAGE;
+}
+
+/*
+** Assert that the Wal.lockMask mask, which indicates the locks held
+** by the connection, is consistent with the Wal.readLock, Wal.writeLock
+** and Wal.ckptLock variables. To be used as:
+**
+** assert( walAssertLockmask(pWal) );
+*/
+static int walAssertLockmask(Wal *pWal){
+ if( pWal->exclusiveMode==0 ){
+ static const int S = 1;
+ static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
+ | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
+ | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0)
+#endif
+ );
+ assert( mExpect==pWal->lockMask );
+ }
+ return 1;
+}
+
+/*
+** Return and zero the "system error" field set when an
+** EXCEPTION_IN_PAGE_ERROR exception is caught.
+*/
+SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){
+ int iRet = 0;
+ if( pWal ){
+ iRet = pWal->iSysErrno;
+ pWal->iSysErrno = 0;
+ }
+ return iRet;
+}
+
+#else
+# define walAssertLockmask(x) 1
+#endif /* ifdef SQLITE_USE_SEH */
+
/*
** Close a connection to a log file.
*/
@@ -65465,6 +67621,8 @@ SQLITE_PRIVATE 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
@@ -65489,7 +67647,7 @@ SQLITE_PRIVATE 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 ){
@@ -65556,7 +67714,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);
@@ -65658,7 +67816,9 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
}
}else{
int bWriteLock = pWal->writeLock;
- if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
+ if( bWriteLock
+ || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
+ ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
@@ -65666,7 +67826,8 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
- */
+ ** Disable blocking locks first. */
+ walDisableBlocking(pWal);
rc = walIndexRecover(pWal);
*pChanged = 1;
}
@@ -65876,6 +68037,37 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
return rc;
}
+/*
+** The final argument passed to walTryBeginRead() is of type (int*). The
+** caller should invoke walTryBeginRead as follows:
+**
+** int cnt = 0;
+** do {
+** rc = walTryBeginRead(..., &cnt);
+** }while( rc==WAL_RETRY );
+**
+** The final value of "cnt" is of no use to the caller. It is used by
+** the implementation of walTryBeginRead() as follows:
+**
+** + Each time walTryBeginRead() is called, it is incremented. Once
+** it reaches WAL_RETRY_PROTOCOL_LIMIT - indicating that walTryBeginRead()
+** has many times been invoked and failed with WAL_RETRY - walTryBeginRead()
+** returns SQLITE_PROTOCOL.
+**
+** + If SQLITE_ENABLE_SETLK_TIMEOUT is defined and walTryBeginRead() failed
+** because a blocking lock timed out (SQLITE_BUSY_TIMEOUT from the OS
+** layer), the WAL_RETRY_BLOCKED_MASK bit is set in "cnt". In this case
+** the next invocation of walTryBeginRead() may omit an expected call to
+** sqlite3OsSleep(). There has already been a delay when the previous call
+** waited on a lock.
+*/
+#define WAL_RETRY_PROTOCOL_LIMIT 100
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+# define WAL_RETRY_BLOCKED_MASK 0x10000000
+#else
+# define WAL_RETRY_BLOCKED_MASK 0
+#endif
+
/*
** Attempt to start a read transaction. This might fail due to a race or
** other transient condition. When that happens, it returns WAL_RETRY to
@@ -65926,13 +68118,12 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
** so it takes care to hold an exclusive lock on the corresponding
** WAL_READ_LOCK() while changing values.
*/
-static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
+static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
- u32 mxReadMark; /* Largest aReadMark[] value */
- int mxI; /* Index of largest aReadMark[] value */
- int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
- u32 mxFrame; /* Wal frame to lock to */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int nBlockTmout = 0;
+#endif
assert( pWal->readLock<0 ); /* Not currently locked */
@@ -65956,14 +68147,34 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** so that on the 100th (and last) RETRY we delay for 323 milliseconds.
** The total delay time before giving up is less than 10 seconds.
*/
- if( cnt>5 ){
+ (*pCnt)++;
+ if( *pCnt>5 ){
int nDelay = 1; /* Pause time in microseconds */
- if( cnt>100 ){
+ int cnt = (*pCnt & ~WAL_RETRY_BLOCKED_MASK);
+ if( cnt>WAL_RETRY_PROTOCOL_LIMIT ){
VVA_ONLY( pWal->lockError = 1; )
return SQLITE_PROTOCOL;
}
- if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
+ if( *pCnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor
+ ** to block for locks for approximately nDelay us. This affects three
+ ** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if
+ ** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the
+ ** first attempted read fails, and (c) the shared lock taken on the
+ ** read-mark.
+ **
+ ** If the previous call failed due to an SQLITE_BUSY_TIMEOUT error,
+ ** then sleep for the minimum of 1us. The previous call already provided
+ ** an extra delay while it was blocking on the lock.
+ */
+ nBlockTmout = (nDelay+998) / 1000;
+ if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){
+ if( *pCnt & WAL_RETRY_BLOCKED_MASK ) nDelay = 1;
+ }
+#endif
sqlite3OsSleep(pWal->pVfs, nDelay);
+ *pCnt &= ~WAL_RETRY_BLOCKED_MASK;
}
if( !useWal ){
@@ -65971,6 +68182,13 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
if( pWal->bShmUnreliable==0 ){
rc = walIndexReadHdr(pWal, pChanged);
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ walDisableBlocking(pWal);
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ rc = SQLITE_BUSY;
+ *pCnt |= WAL_RETRY_BLOCKED_MASK;
+ }
+#endif
if( rc==SQLITE_BUSY ){
/* If there is not a recovery running in another thread or process
** then convert BUSY errors to WAL_RETRY. If recovery is known to
@@ -66007,136 +68225,201 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
assert( pWal->nWiData>0 );
assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
- if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
+ SEH_INJECT_FAULT;
+ {
+ u32 mxReadMark; /* Largest aReadMark[] value */
+ int mxI; /* Index of largest aReadMark[] value */
+ int i; /* Loop counter */
+ u32 mxFrame; /* Wal frame to lock to */
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
- && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
+ && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
#endif
- ){
- /* The WAL has been completely backfilled (or it is empty).
- ** and can be safely ignored.
- */
- rc = walLockShared(pWal, WAL_READ_LOCK(0));
- walShmBarrier(pWal);
- if( rc==SQLITE_OK ){
- if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
- /* It is not safe to allow the reader to continue here if frames
- ** may have been appended to the log before READ_LOCK(0) was obtained.
- ** When holding READ_LOCK(0), the reader ignores the entire log file,
- ** which implies that the database file contains a trustworthy
- ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
- ** happening, this is usually correct.
- **
- ** However, if frames have been appended to the log (or if the log
- ** is wrapped and written for that matter) before the READ_LOCK(0)
- ** is obtained, that is not necessarily true. A checkpointer may
- ** have started to backfill the appended frames but crashed before
- ** it finished. Leaving a corrupt image in the database file.
- */
- walUnlockShared(pWal, WAL_READ_LOCK(0));
- return WAL_RETRY;
+ ){
+ /* The WAL has been completely backfilled (or it is empty).
+ ** and can be safely ignored.
+ */
+ rc = walLockShared(pWal, WAL_READ_LOCK(0));
+ walShmBarrier(pWal);
+ if( rc==SQLITE_OK ){
+ if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){
+ /* It is not safe to allow the reader to continue here if frames
+ ** may have been appended to the log before READ_LOCK(0) was obtained.
+ ** When holding READ_LOCK(0), the reader ignores the entire log file,
+ ** which implies that the database file contains a trustworthy
+ ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
+ ** happening, this is usually correct.
+ **
+ ** However, if frames have been appended to the log (or if the log
+ ** is wrapped and written for that matter) before the READ_LOCK(0)
+ ** is obtained, that is not necessarily true. A checkpointer may
+ ** have started to backfill the appended frames but crashed before
+ ** it finished. Leaving a corrupt image in the database file.
+ */
+ walUnlockShared(pWal, WAL_READ_LOCK(0));
+ return WAL_RETRY;
+ }
+ pWal->readLock = 0;
+ return SQLITE_OK;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
}
- pWal->readLock = 0;
- return SQLITE_OK;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
}
- }
- /* If we get this far, it means that the reader will want to use
- ** the WAL to get at content from recent commits. The job now is
- ** to select one of the aReadMark[] entries that is closest to
- ** but not exceeding pWal->hdr.mxFrame and lock that entry.
- */
- mxReadMark = 0;
- mxI = 0;
- mxFrame = pWal->hdr.mxFrame;
+ /* If we get this far, it means that the reader will want to use
+ ** the WAL to get at content from recent commits. The job now is
+ ** to select one of the aReadMark[] entries that is closest to
+ ** but not exceeding pWal->hdr.mxFrame and lock that entry.
+ */
+ mxReadMark = 0;
+ mxI = 0;
+ mxFrame = pWal->hdr.mxFrame;
#ifdef SQLITE_ENABLE_SNAPSHOT
- if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame;
- }
-#endif
- for(i=1; iaReadMark+i);
- if( mxReadMark<=thisMark && thisMark<=mxFrame ){
- assert( thisMark!=READMARK_NOT_USED );
- mxReadMark = thisMark;
- mxI = i;
+ if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame;
}
- }
- if( (pWal->readOnly & WAL_SHM_RDONLY)==0
- && (mxReadMarkaReadMark+i,mxFrame);
- mxReadMark = mxFrame;
+ u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT;
+ if( mxReadMark<=thisMark && thisMark<=mxFrame ){
+ assert( thisMark!=READMARK_NOT_USED );
+ mxReadMark = thisMark;
mxI = i;
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- break;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
}
}
- }
- if( mxI==0 ){
- assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
- }
+ if( (pWal->readOnly & WAL_SHM_RDONLY)==0
+ && (mxReadMarkaReadMark+i,mxFrame);
+ mxReadMark = mxFrame;
+ mxI = i;
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ break;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ }
+ if( mxI==0 ){
+ assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
+ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
+ }
- rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
- if( rc ){
- return rc==SQLITE_BUSY ? WAL_RETRY : rc;
- }
- /* Now that the read-lock has been obtained, check that neither the
- ** value in the aReadMark[] array or the contents of the wal-index
- ** header have changed.
- **
- ** It is necessary to check that the wal-index header did not change
- ** between the time it was read and when the shared-lock was obtained
- ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
- ** that the log file may have been wrapped by a writer, or that frames
- ** that occur later in the log than pWal->hdr.mxFrame may have been
- ** copied into the database by a checkpointer. If either of these things
- ** happened, then reading the database with the current value of
- ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
- ** instead.
- **
- ** Before checking that the live wal-index header has not changed
- ** since it was read, set Wal.minFrame to the first frame in the wal
- ** file that has not yet been checkpointed. This client will not need
- ** to read any frames earlier than minFrame from the wal file - they
- ** can be safely read directly from the database file.
- **
- ** Because a ShmBarrier() call is made between taking the copy of
- ** nBackfill and checking that the wal-header in shared-memory still
- ** matches the one cached in pWal->hdr, it is guaranteed that the
- ** checkpointer that set nBackfill was not working with a wal-index
- ** header newer than that cached in pWal->hdr. If it were, that could
- ** cause a problem. The checkpointer could omit to checkpoint
- ** a version of page X that lies before pWal->minFrame (call that version
- ** A) on the basis that there is a newer version (version B) of the same
- ** page later in the wal file. But if version B happens to like past
- ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
- ** that it can read version A from the database file. However, since
- ** we can guarantee that the checkpointer that set nBackfill could not
- ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
- */
- pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1;
- walShmBarrier(pWal);
- if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
- || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
- ){
- walUnlockShared(pWal, WAL_READ_LOCK(mxI));
- return WAL_RETRY;
- }else{
- assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = (i16)mxI;
+ (void)walEnableBlockingMs(pWal, nBlockTmout);
+ rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
+ walDisableBlocking(pWal);
+ if( rc ){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ *pCnt |= WAL_RETRY_BLOCKED_MASK;
+ }
+#else
+ assert( rc!=SQLITE_BUSY_TIMEOUT );
+#endif
+ assert((rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT);
+ return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
+ }
+ /* Now that the read-lock has been obtained, check that neither the
+ ** value in the aReadMark[] array or the contents of the wal-index
+ ** header have changed.
+ **
+ ** It is necessary to check that the wal-index header did not change
+ ** between the time it was read and when the shared-lock was obtained
+ ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
+ ** that the log file may have been wrapped by a writer, or that frames
+ ** that occur later in the log than pWal->hdr.mxFrame may have been
+ ** copied into the database by a checkpointer. If either of these things
+ ** happened, then reading the database with the current value of
+ ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
+ ** instead.
+ **
+ ** Before checking that the live wal-index header has not changed
+ ** since it was read, set Wal.minFrame to the first frame in the wal
+ ** file that has not yet been checkpointed. This client will not need
+ ** to read any frames earlier than minFrame from the wal file - they
+ ** can be safely read directly from the database file.
+ **
+ ** Because a ShmBarrier() call is made between taking the copy of
+ ** nBackfill and checking that the wal-header in shared-memory still
+ ** matches the one cached in pWal->hdr, it is guaranteed that the
+ ** checkpointer that set nBackfill was not working with a wal-index
+ ** header newer than that cached in pWal->hdr. If it were, that could
+ ** cause a problem. The checkpointer could omit to checkpoint
+ ** a version of page X that lies before pWal->minFrame (call that version
+ ** A) on the basis that there is a newer version (version B) of the same
+ ** page later in the wal file. But if version B happens to like past
+ ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
+ ** that it can read version A from the database file. However, since
+ ** we can guarantee that the checkpointer that set nBackfill could not
+ ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
+ */
+ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
+ walShmBarrier(pWal);
+ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
+ || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
+ ){
+ walUnlockShared(pWal, WAL_READ_LOCK(mxI));
+ return WAL_RETRY;
+ }else{
+ assert( mxReadMark<=pWal->hdr.mxFrame );
+ pWal->readLock = (i16)mxI;
+ }
}
return rc;
}
#ifdef SQLITE_ENABLE_SNAPSHOT
+/*
+** This function does the work of sqlite3WalSnapshotRecover().
+*/
+static int walSnapshotRecover(
+ Wal *pWal, /* WAL handle */
+ void *pBuf1, /* Temp buffer pWal->szPage bytes in size */
+ void *pBuf2 /* Temp buffer pWal->szPage bytes in size */
+){
+ int szPage = (int)pWal->szPage;
+ int rc;
+ i64 szDb; /* Size of db file in bytes */
+
+ rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
+ if( rc==SQLITE_OK ){
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ u32 i = pInfo->nBackfillAttempted;
+ for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
+ WalHashLoc sLoc; /* Hash table location */
+ u32 pgno; /* Page number in db file */
+ i64 iDbOff; /* Offset of db file entry */
+ i64 iWalOff; /* Offset of wal file entry */
+
+ rc = walHashGet(pWal, walFramePage(i), &sLoc);
+ if( rc!=SQLITE_OK ) break;
+ assert( i - sLoc.iZero - 1 >=0 );
+ pgno = sLoc.aPgno[i-sLoc.iZero-1];
+ iDbOff = (i64)(pgno-1) * szPage;
+
+ if( iDbOff+szPage<=szDb ){
+ iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
+ rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
+
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
+ }
+
+ if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
+ break;
+ }
+ }
+
+ pInfo->nBackfillAttempted = i-1;
+ }
+ }
+
+ return rc;
+}
+
/*
** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
** variable so that older snapshots can be accessed. To do this, loop
@@ -66162,50 +68445,21 @@ SQLITE_PRIVATE 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);
}
@@ -66214,28 +68468,20 @@ SQLITE_PRIVATE 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.
*/
-SQLITE_PRIVATE 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
assert( pWal->ckptLock==0 );
+ assert( pWal->nSehTry>0 );
#ifdef SQLITE_ENABLE_SNAPSHOT
if( pSnapshot ){
@@ -66258,12 +68504,12 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
if( rc!=SQLITE_OK ){
return rc;
}
- pWal->ckptLock = 1;
+ ckptLock = 1;
}
#endif
do{
- rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
+ rc = walTryBeginRead(pWal, pChanged, 0, &cnt);
}while( rc==WAL_RETRY );
testcase( (rc&0xff)==SQLITE_BUSY );
testcase( (rc&0xff)==SQLITE_IOERR );
@@ -66322,15 +68568,37 @@ SQLITE_PRIVATE 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.
+*/
+SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
+ int rc;
+ SEH_TRY {
+ rc = walBeginReadTransaction(pWal, pChanged);
+ }
+ SEH_EXCEPT( rc = walHandleException(pWal); )
+ return rc;
+}
+
/*
** Finish with a read transaction. All this does is release the
** read-lock.
@@ -66351,7 +68619,7 @@ SQLITE_PRIVATE 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.
*/
-SQLITE_PRIVATE int sqlite3WalFindFrame(
+static int walFindFrame(
Wal *pWal, /* WAL handle */
Pgno pgno, /* Database page number to read data for */
u32 *piRead /* OUT: Frame number (or zero) */
@@ -66414,6 +68682,7 @@ SQLITE_PRIVATE 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 ){
@@ -66421,6 +68690,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
iRead = iFrame;
}
if( (nCollide--)==0 ){
+ *piRead = 0;
return SQLITE_CORRUPT_BKPT;
}
iKey = walNextHash(iKey);
@@ -66450,6 +68720,30 @@ SQLITE_PRIVATE 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, 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
@@ -66531,12 +68825,17 @@ SQLITE_PRIVATE 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;
}
@@ -66572,30 +68871,33 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
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;
}
@@ -66639,7 +68941,10 @@ SQLITE_PRIVATE 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;
@@ -66689,7 +68994,7 @@ static int walRestartLog(Wal *pWal){
cnt = 0;
do{
int notUsed;
- rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt);
+ rc = walTryBeginRead(pWal, ¬Used, 1, &cnt);
}while( rc==WAL_RETRY );
assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */
testcase( (rc&0xff)==SQLITE_IOERR );
@@ -66820,7 +69125,7 @@ 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()).
*/
-SQLITE_PRIVATE 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 */
@@ -66908,7 +69213,9 @@ SQLITE_PRIVATE 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;
@@ -66929,7 +69236,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
** checksums must be recomputed when the transaction is committed. */
if( iFirst && (p->pDirty || isCommit==0) ){
u32 iWrite = 0;
- VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
+ VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite);
assert( rc==SQLITE_OK || iWrite==0 );
if( iWrite>=iFirst ){
i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
@@ -67048,6 +69355,29 @@ SQLITE_PRIVATE 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 rc;
+ SEH_TRY {
+ rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags);
+ }
+ SEH_EXCEPT( rc = walHandleException(pWal); )
+ return rc;
+}
+
/*
** This routine is called to implement sqlite3_wal_checkpoint() and
** related interfaces.
@@ -67085,10 +69415,9 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
if( pWal->readOnly ) return SQLITE_READONLY;
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
- /* Enable blocking locks, if possible. If blocking locks are successfully
- ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
+ /* Enable blocking locks, if possible. */
sqlite3WalDb(pWal, db);
- (void)walEnableBlocking(pWal);
+ if( xBusy2 ) (void)walEnableBlocking(pWal);
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
** "checkpoint" lock on the database file.
@@ -67127,30 +69456,38 @@ SQLITE_PRIVATE 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 ){
+ /* For a passive checkpoint, do not re-enable blocking locks after
+ ** reading the wal-index header. A passive checkpoint should not block
+ ** or invoke the busy handler. The only lock such a checkpoint may
+ ** attempt to obtain is a lock on a read-slot, and it should give up
+ ** immediately and do a partial checkpoint if it cannot obtain it. */
+ walDisableBlocking(pWal);
+ rc = walIndexReadHdr(pWal, &isChanged);
+ if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
+ if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
+ sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
+ }
}
- }
-
- /* Copy data from the log to the database file. */
- if( rc==SQLITE_OK ){
- if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
- }
+ /* Copy data from the log to the database file. */
+ if( rc==SQLITE_OK ){
+ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf);
+ }
- /* If no error occurred, set the output variables. */
- if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
- if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
- if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
+ /* If 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
@@ -67227,7 +69564,9 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
** locks are taken in this case). Nor should the pager attempt to
** upgrade to exclusive-mode following such an error.
*/
+#ifndef SQLITE_USE_SEH
assert( pWal->readLock>=0 || pWal->lockError );
+#endif
assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
if( op==0 ){
@@ -67295,7 +69634,20 @@ SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
Wal *pWal,
sqlite3_snapshot *pSnapshot
){
- pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+ if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){
+ /* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In
+ ** this case set the bGetSnapshot flag so that if the call to
+ ** sqlite3_snapshot_get() is about to read transaction on this wal
+ ** file, it does not take read-lock 0 if the wal file has been completely
+ ** checkpointed. Taking read-lock 0 would work, but then it would be
+ ** possible for a subsequent writer to destroy the snapshot even while
+ ** this connection is holding its read-transaction open. This is contrary
+ ** to user expectations, so we avoid it by not taking read-lock 0. */
+ pWal->bGetSnapshot = 1;
+ }else{
+ pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+ pWal->bGetSnapshot = 0;
+ }
}
/*
@@ -67328,16 +69680,19 @@ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
*/
SQLITE_PRIVATE 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;
}
@@ -67460,7 +69815,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
** 22 1 Min embedded payload fraction (must be 32)
** 23 1 Min leaf payload fraction (must be 32)
** 24 4 File change counter
-** 28 4 Reserved for future use
+** 28 4 The size of the database in pages
** 32 4 First freelist page
** 36 4 Number of freelist pages in the file
** 40 60 15 4-byte meta values passed to higher layers
@@ -67568,7 +69923,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
** 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
@@ -67576,7 +69931,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
** 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
@@ -67659,7 +70014,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.)
**
@@ -67952,7 +70307,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 */
@@ -68091,17 +70446,19 @@ 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 */
+ i64 nRow; /* Number of rows visited in current tree */
};
/*
@@ -68114,7 +70471,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
@@ -68291,7 +70648,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.
@@ -68561,8 +70918,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 ){
@@ -68576,8 +70933,47 @@ int corruptPageError(int lineno, MemPage *p){
# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno)
#endif
+/* Default value for SHARED_LOCK_TRACE macro if shared-cache is disabled
+** or if the lock tracking is disabled. This is always the value for
+** release builds.
+*/
+#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) /*no-op*/
+
#ifndef SQLITE_OMIT_SHARED_CACHE
+#if 0
+/* ^---- Change to 1 and recompile to enable shared-lock tracing
+** for debugging purposes.
+**
+** Print all shared-cache locks on a BtShared. Debugging use only.
+*/
+static void sharedLockTrace(
+ BtShared *pBt,
+ const char *zMsg,
+ int iRoot,
+ int eLockType
+){
+ BtLock *pLock;
+ if( iRoot>0 ){
+ printf("%s-%p %u%s:", zMsg, pBt, iRoot, eLockType==READ_LOCK?"R":"W");
+ }else{
+ printf("%s-%p:", zMsg, pBt);
+ }
+ for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
+ printf(" %p/%u%s", pLock->pBtree, pLock->iTable,
+ pLock->eLock==READ_LOCK ? "R" : "W");
+ while( pLock->pNext && pLock->pBtree==pLock->pNext->pBtree ){
+ pLock = pLock->pNext;
+ printf(",%u%s", pLock->iTable, pLock->eLock==READ_LOCK ? "R" : "W");
+ }
+ }
+ printf("\n");
+ fflush(stdout);
+}
+#undef SHARED_LOCK_TRACE
+#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) sharedLockTrace(X,MSG,TAB,TYPE)
+#endif /* Shared-lock tracing */
+
#ifdef SQLITE_DEBUG
/*
**** This function is only used as part of an assert() statement. ***
@@ -68654,6 +71050,8 @@ static int hasSharedCacheTableLock(
iTab = iRoot;
}
+ SHARED_LOCK_TRACE(pBtree->pBt,"hasLock",iRoot,eLockType);
+
/* Search for the required lock. Either a write-lock on root-page iTab, a
** write-lock on the schema table, or (if the client is reading) a
** read-lock on iTab will suffice. Return 1 if any of these are found. */
@@ -68787,6 +71185,8 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
BtLock *pLock = 0;
BtLock *pIter;
+ SHARED_LOCK_TRACE(pBt,"setLock", iTable, eLock);
+
assert( sqlite3BtreeHoldsMutex(p) );
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
@@ -68854,6 +71254,8 @@ static void clearAllSharedCacheTableLocks(Btree *p){
assert( p->sharable || 0==*ppIter );
assert( p->inTrans>0 );
+ SHARED_LOCK_TRACE(pBt, "clearAllLocks", 0, 0);
+
while( *ppIter ){
BtLock *pLock = *ppIter;
assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree );
@@ -68892,6 +71294,9 @@ static void clearAllSharedCacheTableLocks(Btree *p){
*/
static void downgradeAllSharedCacheTableLocks(Btree *p){
BtShared *pBt = p->pBt;
+
+ SHARED_LOCK_TRACE(pBt, "downgradeLocks", 0, 0);
+
if( pBt->pWriter==p ){
BtLock *pLock;
pBt->pWriter = 0;
@@ -69371,8 +71776,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.
@@ -69457,7 +71879,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;
@@ -69656,27 +72078,31 @@ static void btreeParseCellPtr(
iKey = *pIter;
if( iKey>=0x80 ){
u8 x;
- iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<7) | ((x =*++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ 0x10204000 ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter);
if( x>=0x80 ){
- iKey = (iKey<<8) | (*++pIter);
+ iKey = (iKey<<8) ^ 0x8000 ^ (*++pIter);
}
}
}
}
}
+ }else{
+ iKey ^= 0x204000;
}
+ }else{
+ iKey ^= 0x4000;
}
}
pIter++;
@@ -69753,10 +72179,53 @@ static void btreeParseCell(
**
** cellSizePtrNoPayload() => table internal nodes
** cellSizePtrTableLeaf() => table leaf nodes
-** cellSizePtr() => all index nodes & table leaf nodes
+** cellSizePtr() => index internal nodes
+** cellSizeIdxLeaf() => index leaf nodes
*/
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
- u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */
+ u8 *pIter = pCell + 4; /* For looping over bytes of pCell */
+ u8 *pEnd; /* End mark for a varint */
+ u32 nSize; /* Size value to return */
+
+#ifdef SQLITE_DEBUG
+ /* The value returned by this function should always be the same as
+ ** the (CellInfo.nSize) value found by doing a full parse of the
+ ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
+ ** this function verifies that this invariant is not violated. */
+ CellInfo debuginfo;
+ pPage->xParseCell(pPage, pCell, &debuginfo);
+#endif
+
+ assert( pPage->childPtrSize==4 );
+ nSize = *pIter;
+ if( nSize>=0x80 ){
+ pEnd = &pIter[8];
+ nSize &= 0x7f;
+ do{
+ nSize = (nSize<<7) | (*++pIter & 0x7f);
+ }while( *(pIter)>=0x80 && pItermaxLocal );
+ testcase( nSize==(u32)pPage->maxLocal+1 );
+ if( nSize<=pPage->maxLocal ){
+ nSize += (u32)(pIter - pCell);
+ assert( nSize>4 );
+ }else{
+ int minLocal = pPage->minLocal;
+ nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
+ testcase( nSize==pPage->maxLocal );
+ testcase( nSize==(u32)pPage->maxLocal+1 );
+ if( nSize>pPage->maxLocal ){
+ nSize = minLocal;
+ }
+ nSize += 4 + (u16)(pIter - pCell);
+ }
+ assert( nSize==debuginfo.nSize || CORRUPT_DB );
+ return (u16)nSize;
+}
+static u16 cellSizePtrIdxLeaf(MemPage *pPage, u8 *pCell){
+ u8 *pIter = pCell; /* For looping over bytes of pCell */
u8 *pEnd; /* End mark for a varint */
u32 nSize; /* Size value to return */
@@ -69769,6 +72238,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
pPage->xParseCell(pPage, pCell, &debuginfo);
#endif
+ assert( pPage->childPtrSize==0 );
nSize = *pIter;
if( nSize>=0x80 ){
pEnd = &pIter[8];
@@ -69893,7 +72363,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;
@@ -69994,7 +72464,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; iiCellLast ){
+ if( pc>iCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( pc>=iCellStart && pc<=iCellLast );
+ assert( pc>=0 && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrkusableSize ){
@@ -70123,7 +72593,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
** allocation is being made in order to insert a new cell, so we will
** also end up needing a new cell pointer.
*/
-static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
+static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */
u8 * const data = pPage->aData; /* Local cache of pPage->aData */
int top; /* First byte of cell content area */
@@ -70149,13 +72619,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,
@@ -70217,7 +72688,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.
*/
@@ -70238,7 +72709,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.
@@ -70295,6 +72766,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
@@ -70306,14 +72782,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;
}
@@ -70350,14 +72821,14 @@ static int decodeFlags(MemPage *pPage, int flagByte){
}else if( flagByte==(PTF_ZERODATA | PTF_LEAF) ){
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
- pPage->xCellSize = cellSizePtr;
+ pPage->xCellSize = cellSizePtrIdxLeaf;
pPage->xParseCell = btreeParseCellPtrIndex;
pPage->maxLocal = pBt->maxLocal;
pPage->minLocal = pBt->minLocal;
}else{
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
- pPage->xCellSize = cellSizePtr;
+ pPage->xCellSize = cellSizePtrIdxLeaf;
pPage->xParseCell = btreeParseCellPtrIndex;
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -70676,68 +73147,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;
}
/*
@@ -70820,7 +73264,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);
}
}
@@ -70999,6 +73443,9 @@ 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;
@@ -71215,7 +73662,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.
**
@@ -71450,7 +73897,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
@@ -71697,7 +74144,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
@@ -71717,6 +74163,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);
@@ -71736,6 +74183,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
@@ -71914,7 +74362,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;
@@ -72086,6 +74538,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
@@ -72223,7 +74697,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 ){
@@ -73054,6 +75528,25 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
return ROUND8(sizeof(BtCursor));
}
+#ifdef SQLITE_DEBUG
+/*
+** Return true if and only if the Btree object will be automatically
+** closed with the BtCursor closes. This is used within assert() statements
+** only.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(
+ Btree *pBtree, /* the btree object */
+ BtCursor *pCur /* Corresponding cursor */
+){
+ BtShared *pBt = pBtree->pBt;
+ if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0;
+ if( pBt->pCursor!=pCur ) return 0;
+ if( pCur->pNext!=0 ) return 0;
+ if( pCur->pBtree!=pBtree ) return 0;
+ return 1;
+}
+#endif
+
/*
** Initialize memory that will be converted into a BtCursor object.
**
@@ -73181,7 +75674,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.
@@ -73193,7 +75685,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
@@ -73219,7 +75710,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.
@@ -73438,9 +75929,12 @@ static int accessPayload(
if( pCur->aOverflow==0
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
){
- Pgno *aNew = (Pgno*)sqlite3Realloc(
- pCur->aOverflow, nOvfl*2*sizeof(Pgno)
- );
+ Pgno *aNew;
+ if( sqlite3FaultSim(413) ){
+ aNew = 0;
+ }else{
+ aNew = (Pgno*)sqlite3Realloc(pCur->aOverflow, nOvfl*2*sizeof(Pgno));
+ }
if( aNew==0 ){
return SQLITE_NOMEM_BKPT;
}else{
@@ -73450,6 +75944,12 @@ static int accessPayload(
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
}else{
+ /* Sanity check the validity of the overflow page cache */
+ assert( pCur->aOverflow[0]==nextPage
+ || pCur->aOverflow[0]==0
+ || CORRUPT_DB );
+ assert( pCur->aOverflow[0]!=0 || pCur->aOverflow[offset/ovflSize]==0 );
+
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
@@ -73519,7 +76019,6 @@ static int accessPayload(
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
- if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
@@ -73681,6 +76180,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
@@ -73802,7 +76312,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;
@@ -73914,13 +76424,30 @@ 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;
}
return rc;
}
+#ifdef SQLITE_DEBUG
+/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
+** this flags are true for a consistent database.
+**
+** This routine is is called from within assert() statements only.
+** It is an internal verification routine and does not appear in production
+** builds.
+*/
+static int cursorIsAtLastEntry(BtCursor *pCur){
+ int ii;
+ for(ii=0; iiiPage; ii++){
+ if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
+ }
+ return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
+}
+#endif
+
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
@@ -73949,18 +76476,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
-#ifdef SQLITE_DEBUG
- /* This block serves to assert() that the cursor really does point
- ** to the last entry in the b-tree. */
- int ii;
- for(ii=0; iiiPage; ii++){
- assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
- }
- assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
- testcase( pCur->ix!=pCur->pPage->nCell-1 );
- /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
- assert( pCur->pPage->leaf );
-#endif
+ assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = 0;
return SQLITE_OK;
}
@@ -74013,13 +76529,14 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
}
if( pCur->info.nKeycurFlags & BTCF_AtLast)!=0 ){
+ assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = -1;
return SQLITE_OK;
}
/* If the requested key is one more than the previous key, then
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
- ** is still obtained without this case, only a little more slowely */
+ ** is still obtained without this case, only a little more slowly. */
if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
@@ -74273,7 +76790,7 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
- pCur->curFlags &= ~BTCF_ValidOvfl;
+ pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
@@ -74415,10 +76932,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 );
@@ -74453,10 +76996,10 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- /* Currently this interface is only called by the OP_IfSmaller
- ** opcode, and it that case the cursor will always be valid and
- ** will always point to a leaf node. */
- if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
+ /* Currently this interface is only called by the OP_IfSizeBetween
+ ** opcode and the OP_Count opcode with P3=1. In either case,
+ ** the cursor will always be valid unless the btree is empty. */
+ if( pCur->eState!=CURSOR_VALID ) return 0;
if( NEVER(pCur->pPage->leaf==0) ) return -1;
n = pCur->pPage->nCell;
@@ -74509,7 +77052,8 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
pPage = pCur->pPage;
idx = ++pCur->ix;
- if( !pPage->isInit || sqlite3FaultSim(412) ){
+ if( sqlite3FaultSim(412) ) pPage->isInit = 0;
+ if( !pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
@@ -74601,7 +77145,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
}
pPage = pCur->pPage;
- assert( pPage->isInit );
+ if( sqlite3FaultSim(412) ) pPage->isInit = 0;
+ if( !pPage->isInit ){
+ return SQLITE_CORRUPT_BKPT;
+ }
if( !pPage->leaf ){
int idx = pCur->ix;
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
@@ -74772,7 +77319,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);
@@ -74838,7 +77385,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 */
@@ -74883,8 +77430,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;
@@ -74940,7 +77487,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 ){
@@ -74963,7 +77510,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) );
@@ -75091,7 +77638,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;
}
}
@@ -75112,7 +77659,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 ){
@@ -75201,7 +77748,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.
*/
@@ -75274,7 +77821,10 @@ static int fillInCell(
n = nHeader + nPayload;
testcase( n==3 );
testcase( n==4 );
- if( n<4 ) n = 4;
+ if( n<4 ){
+ n = 4;
+ pPayload[nPayload] = 0;
+ }
*pnSize = n;
assert( nSrc<=nPayload );
testcase( nSrcaCell[] 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 */
@@ -75493,14 +78051,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
@@ -75532,17 +78179,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);
@@ -75725,12 +78362,14 @@ 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[NB*2-1]>i );
+ for(k=0; pCArray->ixNx[k]<=i; k++){}
pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
@@ -75793,7 +78432,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(
@@ -75813,7 +78452,8 @@ 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[NB*2-1]>i );
+ for(k=0; pCArray->ixNx[k]<=i ; k++){}
pEnd = pCArray->apEnd[k];
while( 1 /*Exit by break*/ ){
int sz, rc;
@@ -75871,42 +78511,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( iNewaDataEnd;
b.ixNx[0] = 2;
+ b.ixNx[NB*2-1] = 0x7fffffff;
rc = rebuildPage(&b, 0, 1, pNew);
if( NEVER(rc) ){
releasePage(pNew);
@@ -76100,7 +78750,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
** with entries for the new page, and any pointer from the
** cell on the page to an overflow page. If either of these
** operations fails, the return code is set, but the contents
- ** of the parent page are still manipulated by thh code below.
+ ** of the parent page are still manipulated by the code below.
** That is Ok, at this point the parent page is guaranteed to
** be marked as dirty. Returning an error code will cause a
** rollback, undoing any changes made to the parent page.
@@ -76324,7 +78974,9 @@ static int balance_nonroot(
CellArray b; /* Parsed information on cells being balanced */
memset(abDone, 0, sizeof(abDone));
- memset(&b, 0, sizeof(b));
+ assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
+ memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
+ b.ixNx[NB*2-1] = 0x7fffffff;
pBt = pParent->pBt;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -76376,7 +79028,7 @@ static int balance_nonroot(
pgno = get4byte(pRight);
while( 1 ){
if( rc==SQLITE_OK ){
- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ rc = getAndInitPage(pBt, pgno, &apOld[i], 0);
}
if( rc ){
memset(apOld, 0, (i+1)*sizeof(MemPage*));
@@ -76483,7 +79135,7 @@ static int balance_nonroot(
** table-interior, index-leaf, or index-interior).
*/
if( pOld->aData[0]!=apOld[0]->aData[0] ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pOld);
goto balance_cleanup;
}
@@ -76507,7 +79159,7 @@ static int balance_nonroot(
memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
if( pOld->nOverflow>0 ){
if( NEVER(limitaiOvfl[0]) ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pOld);
goto balance_cleanup;
}
limit = pOld->aiOvfl[0];
@@ -76690,7 +79342,7 @@ static int balance_nonroot(
}
}
- /* Sanity check: For a non-corrupt database file one of the follwing
+ /* Sanity check: For a non-corrupt database file one of the following
** must be true:
** (1) We found one or more cells (cntNew[0])>0), or
** (2) pPage is a virtual root page. A virtual root page is when
@@ -76698,7 +79350,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
@@ -76782,8 +79434,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,
@@ -76915,9 +79567,10 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
- for(k=0; b.ixNx[k]<=j && ALWAYS(kj );
+ for(k=0; b.ixNx[k]<=j; k++){}
pSrcEnd = b.apEnd[k];
- if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
+ if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
@@ -76951,6 +79604,8 @@ static int balance_nonroot(
for(i=1-nNew; i=0 && iPg=1 || i>=0 );
+ assert( iPg=0 /* On the upwards pass, or... */
|| cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */
@@ -77028,7 +79683,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.
@@ -77113,7 +79768,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,
@@ -77148,7 +79803,7 @@ static int anotherValidCursor(BtCursor *pCur){
&& pOther->eState==CURSOR_VALID
&& pOther->pPage==pCur->pPage
){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pCur->pPage);
}
}
return SQLITE_OK;
@@ -77208,7 +79863,7 @@ static int balance(BtCursor *pCur){
/* The page being written is not a root page, and there is currently
** more than one reference to it. This only happens if the page is one
** of its own ancestor pages. Corruption. */
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pPage);
}else{
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
@@ -77307,7 +79962,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 */
@@ -77372,7 +80027,7 @@ static SQLITE_NOINLINE int btreeOverwriteOverflowCell(
rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
if( rc ) return rc;
if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pPage);
}else{
if( iOffset+ovflPageSize<(u32)nTotal ){
ovflPgno = get4byte(pPage->aData);
@@ -77400,7 +80055,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
|| pCur->info.pPayload < pPage->aData + pPage->cellOffset
){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
if( pCur->info.nLocal==nTotal ){
/* The entire cell is local */
@@ -77481,7 +80136,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** Which can only happen if the SQLITE_NoSchemaError flag was set when
** the schema was loaded. This cannot be asserted though, as a user might
** set the flag, load the schema, and then unset the flag. */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot);
}
}
@@ -77596,7 +80251,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) );
@@ -77604,14 +80259,14 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( pPage->nFree<0 ){
if( NEVER(pCur->eState>CURSOR_INVALID) ){
/* ^^^^^--- due to the moveToRoot() call above */
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pPage);
}else{
rc = btreeComputeFreeSpace(pPage);
}
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 );
@@ -77621,7 +80276,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( flags & BTREE_PREFORMAT ){
rc = SQLITE_OK;
szNew = p->pBt->nPreformatSize;
- if( szNew<4 ) szNew = 4;
+ if( szNew<4 ){
+ szNew = 4;
+ newCell[3] = 0;
+ }
if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
CellInfo info;
pPage->xParseCell(pPage, newCell, &info);
@@ -77643,7 +80301,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
CellInfo info;
assert( idx>=0 );
if( idx>=pPage->nCell ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
@@ -77670,10 +80328,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
if( oldCell+szNew > pPage->aDataEnd ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
memcpy(oldCell, newCell, szNew);
return SQLITE_OK;
@@ -77683,11 +80341,11 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->ix;
- pCur->curFlags &= ~BTCF_ValidNKey;
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}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 );
@@ -77713,7 +80371,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
*/
if( pPage->nOverflow ){
assert( rc==SQLITE_OK );
- pCur->curFlags &= ~(BTCF_ValidNKey);
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
@@ -77775,7 +80433,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
nIn = pSrc->info.nLocal;
aIn = pSrc->info.pPayload;
if( aIn+nIn>pSrc->pPage->aDataEnd ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pSrc->pPage);
}
nRem = pSrc->info.nPayload;
if( nIn==nRem && nInpPage->maxLocal ){
@@ -77800,7 +80458,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
if( nRem>nIn ){
if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pSrc->pPage);
}
ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
}
@@ -77896,7 +80554,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}else{
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot);
}
}
assert( pCur->eState==CURSOR_VALID );
@@ -77905,11 +80563,14 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
iCellIdx = pCur->ix;
pPage = pCur->pPage;
if( pPage->nCell<=iCellIdx ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
pCell = findCell(pPage, iCellIdx);
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ if( pCell<&pPage->aCellIdx[pPage->nCell] ){
+ return SQLITE_CORRUPT_PAGE(pPage);
}
/* If the BTREE_SAVEPOSITION bit is on, then the cursor position must
@@ -78000,7 +80661,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
n = pCur->pPage->pgno;
}
pCell = findCell(pLeaf, pLeaf->nCell-1);
- if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
+ if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_PAGE(pLeaf);
nCell = pLeaf->xCellSize(pLeaf, pCell);
assert( MX_CELL_SIZE(pBt) >= nCell );
pTmp = pBt->pTmpSpace;
@@ -78087,7 +80748,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 );
@@ -78116,7 +80777,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
*/
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
if( pgnoRoot>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pgnoRoot);
}
pgnoRoot++;
@@ -78164,7 +80825,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
}
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pgnoRoot);
}
if( rc!=SQLITE_OK ){
releasePage(pRoot);
@@ -78254,14 +80915,14 @@ static int clearDatabasePage(
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(pgno);
}
- 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))
){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pPage);
goto cleardatabasepage_out;
}
hdr = pPage->hdrOffset;
@@ -78365,7 +81026,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
assert( p->inTrans==TRANS_WRITE );
assert( iTable>=2 );
if( iTable>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PGNO(iTable);
}
rc = sqlite3BtreeClearTable(p, iTable, 0);
@@ -78659,7 +81320,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);
@@ -78676,7 +81338,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)));
}
@@ -78684,7 +81347,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));
}
@@ -78698,12 +81362,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);
@@ -78729,13 +81393,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);
}
}
@@ -78760,7 +81424,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);
@@ -78773,7 +81437,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++){
@@ -78805,7 +81469,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);
}
@@ -78920,11 +81584,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;
}
@@ -78947,7 +81612,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() */
@@ -78955,6 +81620,9 @@ static int checkTreePage(
** number of cells on the page. */
nCell = get2byte(&data[hdr+3]);
assert( pPage->nCell==nCell );
+ if( pPage->leaf || pPage->intKey==0 ){
+ pCheck->nRow += nCell;
+ }
/* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
** immediately follows the b-tree page header. */
@@ -78967,7 +81635,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
@@ -78991,7 +81659,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;
@@ -79066,6 +81734,7 @@ static int checkTreePage(
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
}
}
+ assert( heap!=0 );
/* Add the freeblocks to the min-heap
**
** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
@@ -79123,7 +81792,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);
}
}
@@ -79165,6 +81834,7 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
Pgno *aRoot, /* An array of root pages numbers for individual trees */
+ Mem *aCnt, /* Memory cells to write counts for each tree to */
int nRoot, /* Number of entries in aRoot[] */
int mxErr, /* Stop reporting errors after this many */
int *pnErr, /* OUT: Write number of errors seen to this variable */
@@ -79178,7 +81848,9 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
int bPartial = 0; /* True if not checking all btrees */
int bCkFreelist = 1; /* True to scan the freelist */
VVA_ONLY( int nRef );
+
assert( nRoot>0 );
+ assert( aCnt!=0 );
/* aRoot[0]==0 means this is a partial check */
if( aRoot[0]==0 ){
@@ -79195,15 +81867,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;
@@ -79215,12 +81887,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;
@@ -79237,7 +81909,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
);
}
@@ -79251,24 +81923,28 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
testcase( pBt->db->flags & SQLITE_CellSizeCk );
pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
for(i=0; (int)iautoVacuum && aRoot[i]>1 && !bPartial ){
- checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
- }
+ if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
+ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
+ }
#endif
- checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
+ sCheck.v0 = aRoot[i];
+ checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
+ }
+ sqlite3MemSetArrayInt64(aCnt, i, sCheck.nRow);
}
pBt->db->flags = savedDbFlags;
/* 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
@@ -79276,11 +81952,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
}
@@ -79842,13 +82518,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
@@ -79981,7 +82651,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;
}
@@ -80530,6 +83203,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 */
@@ -80686,6 +83360,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.
@@ -80812,7 +83520,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);
@@ -80947,36 +83655,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.
@@ -81003,7 +83681,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{
@@ -81065,7 +83743,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
**
@@ -81133,8 +83811,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;
}
@@ -81205,6 +83883,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;
@@ -81212,7 +83891,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;
@@ -81308,6 +83989,13 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
}
}
+/*
+** Set the iIdx'th entry of array aMem[] to contain integer value val.
+*/
+SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val){
+ sqlite3VdbeMemSetInt64(&aMem[iIdx], val);
+}
+
/* A no-op destructor */
SQLITE_PRIVATE void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
@@ -81404,27 +84092,30 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
int i;
Mem *pX;
- for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){
- if( pX->pScopyFrom==pMem ){
- u16 mFlags;
- if( pVdbe->db->flags & SQLITE_VdbeTrace ){
- sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
- (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
- }
- /* If pX is marked as a shallow copy of pMem, then try to verify that
- ** no significant changes have been made to pX since the OP_SCopy.
- ** A significant change would indicated a missed call to this
- ** function for pX. Minor changes, such as adding or removing a
- ** dual type, are allowed, as long as the underlying value is the
- ** same. */
- mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
- assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
-
- /* pMem is the register that is changing. But also mark pX as
- ** undefined so that we can quickly detect the shallow-copy error */
- pX->flags = MEM_Undefined;
- pX->pScopyFrom = 0;
- }
+ if( pMem->bScopy ){
+ for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){
+ if( pX->pScopyFrom==pMem ){
+ u16 mFlags;
+ if( pVdbe->db->flags & SQLITE_VdbeTrace ){
+ sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
+ (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
+ }
+ /* If pX is marked as a shallow copy of pMem, then try to verify that
+ ** no significant changes have been made to pX since the OP_SCopy.
+ ** A significant change would indicated a missed call to this
+ ** function for pX. Minor changes, such as adding or removing a
+ ** dual type, are allowed, as long as the underlying value is the
+ ** same. */
+ mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
+ assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
+
+ /* pMem is the register that is changing. But also mark pX as
+ ** undefined so that we can quickly detect the shallow-copy error */
+ pX->flags = MEM_Undefined;
+ pX->pScopyFrom = 0;
+ }
+ }
+ pMem->bScopy = 0;
}
pMem->pScopyFrom = 0;
}
@@ -81736,6 +84427,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.
*/
@@ -81803,6 +84512,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
@@ -81856,9 +84566,12 @@ 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)
+ || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0
){
return SQLITE_OK;
}
@@ -81870,7 +84583,8 @@ static int valueFromFunction(
goto value_from_function_out;
}
for(i=0; ia[i].pExpr, enc, aff, &apVal[i]);
+ rc = sqlite3Stat4ValueFromExpr(pCtx->pParse, pList->a[i].pExpr, aff,
+ &apVal[i]);
if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
}
}
@@ -81892,16 +84606,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:
@@ -81965,6 +84674,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);
}
@@ -81972,14 +84688,20 @@ static int valueFromExpr(
}
/* Handle negative integers in a single step. This is needed in the
- ** case when the value is -9223372036854775808.
- */
- if( op==TK_UMINUS
- && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
- pExpr = pExpr->pLeft;
- op = pExpr->op;
- negInt = -1;
- zNeg = "-";
+ ** case when the value is -9223372036854775808. Except - do not do this
+ ** for hexadecimal literals. */
+ if( op==TK_UMINUS ){
+ Expr *pLeft = pExpr->pLeft;
+ if( (pLeft->op==TK_INTEGER || pLeft->op==TK_FLOAT) ){
+ if( ExprHasProperty(pLeft, EP_IntValue)
+ || pLeft->u.zToken[0]!='0' || (pLeft->u.zToken[1] & ~0x20)!='X'
+ ){
+ pExpr = pLeft;
+ op = pExpr->op;
+ negInt = -1;
+ zNeg = "-";
+ }
+ }
}
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
@@ -81988,12 +84710,26 @@ static int valueFromExpr(
if( ExprHasProperty(pExpr, EP_IntValue) ){
sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
}else{
- zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
- if( zVal==0 ) goto no_mem;
- sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
+ i64 iVal;
+ if( op==TK_INTEGER && 0==sqlite3DecOrHexToI64(pExpr->u.zToken, &iVal) ){
+ sqlite3VdbeMemSetInt64(pVal, iVal*negInt);
+ }else{
+ zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
+ if( zVal==0 ) goto no_mem;
+ sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
+ }
}
- if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
- sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
+ if( affinity==SQLITE_AFF_BLOB ){
+ if( op==TK_FLOAT ){
+ assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) );
+ sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8);
+ pVal->flags = MEM_Real;
+ }else if( op==TK_INTEGER ){
+ /* This case is required by -9223372036854775808 and other strings
+ ** that look like integers but cannot be handled by the
+ ** sqlite3DecOrHexToI64() call above. */
+ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
+ }
}else{
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
}
@@ -82057,6 +84793,7 @@ static int valueFromExpr(
if( pVal ){
pVal->flags = MEM_Int;
pVal->u.i = pExpr->u.zToken[4]==0;
+ sqlite3ValueApplyAffinity(pVal, affinity, enc);
}
}
@@ -82262,17 +84999,17 @@ SQLITE_PRIVATE int sqlite3Stat4Column(
sqlite3_value **ppVal /* OUT: Extracted value */
){
u32 t = 0; /* a column type code */
- int nHdr; /* Size of the header in the record */
- int iHdr; /* Next unread header byte */
- int iField; /* Next unread data byte */
- int szField = 0; /* Size of the current data field */
+ u32 nHdr; /* Size of the header in the record */
+ u32 iHdr; /* Next unread header byte */
+ i64 iField; /* Next unread data byte */
+ u32 szField = 0; /* Size of the current data field */
int i; /* Column index */
u8 *a = (u8*)pRec; /* Typecast byte array */
Mem *pMem = *ppVal; /* Write result into this Mem object */
assert( iCol>0 );
iHdr = getVarint32(a, nHdr);
- if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
+ if( nHdr>(u32)nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
iField = nHdr;
for(i=0; i<=iCol; i++){
iHdr += getVarint32(&a[iHdr], t);
@@ -82579,13 +85316,43 @@ static int growOpArray(Vdbe *v, int nOp){
** sqlite3CantopenError(lineno)
*/
static void test_addop_breakpoint(int pc, Op *pOp){
- static int n = 0;
+ static u64 n = 0;
(void)pc;
(void)pOp;
n++;
+ if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */
}
#endif
+/*
+** Slow paths for sqlite3VdbeAddOp3() and sqlite3VdbeAddOp4Int() for the
+** unusual case when we need to increase the size of the Vdbe.aOp[] array
+** before adding the new opcode.
+*/
+static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
+ assert( p->nOpAlloc<=p->nOp );
+ if( growOpArray(p, 1) ) return 1;
+ assert( p->nOpAlloc>p->nOp );
+ return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
+}
+static SQLITE_NOINLINE int addOp4IntSlow(
+ Vdbe *p, /* Add the opcode to this VM */
+ int op, /* The new opcode */
+ int p1, /* The P1 operand */
+ int p2, /* The P2 operand */
+ int p3, /* The P3 operand */
+ int p4 /* The P4 operand as an integer */
+){
+ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
+ if( p->db->mallocFailed==0 ){
+ VdbeOp *pOp = &p->aOp[addr];
+ pOp->p4type = P4_INT32;
+ pOp->p4.i = p4;
+ }
+ return addr;
+}
+
+
/*
** Add a new instruction to the list of instructions current in the
** VDBE. Return the address of the new instruction.
@@ -82596,17 +85363,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;
@@ -82629,6 +85395,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
@@ -82645,16 +85414,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
@@ -82811,10 +85623,10 @@ SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
*/
SQLITE_PRIVATE int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
int addr = 0;
-#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+#if !defined(SQLITE_DEBUG)
/* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined.
** But omit them (for performance) during production builds */
- if( pParse->explain==2 )
+ if( pParse->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
char *zMsg;
@@ -82832,7 +85644,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;
}
@@ -82862,26 +85674,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){
@@ -83188,11 +85980,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
@@ -83247,8 +86041,18 @@ 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)];
}
+
+ /* OPFLG_JUMP opcodes never have P2==0, though OPFLG_JUMP0 opcodes
+ ** might */
+ assert( pOp->p2>0
+ || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP0)!=0 );
+
+ /* Jumps never go off the end of the bytecode array */
+ assert( pOp->p2nOp
+ || (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)==0 );
break;
}
}
@@ -83313,6 +86117,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 );
@@ -83490,18 +86298,20 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(
LogEst nEst, /* Estimated number of output rows */
const char *zName /* Name of table or index being scanned */
){
- sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
- ScanStatus *aNew;
- aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
- if( aNew ){
- ScanStatus *pNew = &aNew[p->nScan++];
- memset(pNew, 0, sizeof(ScanStatus));
- pNew->addrExplain = addrExplain;
- pNew->addrLoop = addrLoop;
- pNew->addrVisit = addrVisit;
- pNew->nEst = nEst;
- pNew->zName = sqlite3DbStrDup(p->db, zName);
- p->aScan = aNew;
+ if( IS_STMT_SCANSTATUS(p->db) ){
+ sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
+ ScanStatus *aNew;
+ aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
+ if( aNew ){
+ ScanStatus *pNew = &aNew[p->nScan++];
+ memset(pNew, 0, sizeof(ScanStatus));
+ pNew->addrExplain = addrExplain;
+ pNew->addrLoop = addrLoop;
+ pNew->addrVisit = addrVisit;
+ pNew->nEst = nEst;
+ pNew->zName = sqlite3DbStrDup(p->db, zName);
+ p->aScan = aNew;
+ }
}
}
@@ -83518,20 +86328,22 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatusRange(
int addrStart,
int addrEnd
){
- ScanStatus *pScan = 0;
- int ii;
- for(ii=p->nScan-1; ii>=0; ii--){
- pScan = &p->aScan[ii];
- if( pScan->addrExplain==addrExplain ) break;
- pScan = 0;
- }
- if( pScan ){
- if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1;
- for(ii=0; iiaAddrRange); ii+=2){
- if( pScan->aAddrRange[ii]==0 ){
- pScan->aAddrRange[ii] = addrStart;
- pScan->aAddrRange[ii+1] = addrEnd;
- break;
+ if( IS_STMT_SCANSTATUS(p->db) ){
+ ScanStatus *pScan = 0;
+ int ii;
+ for(ii=p->nScan-1; ii>=0; ii--){
+ pScan = &p->aScan[ii];
+ if( pScan->addrExplain==addrExplain ) break;
+ pScan = 0;
+ }
+ if( pScan ){
+ if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1;
+ for(ii=0; iiaAddrRange); ii+=2){
+ if( pScan->aAddrRange[ii]==0 ){
+ pScan->aAddrRange[ii] = addrStart;
+ pScan->aAddrRange[ii+1] = addrEnd;
+ break;
+ }
}
}
}
@@ -83548,19 +86360,21 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters(
int addrLoop,
int addrVisit
){
- ScanStatus *pScan = 0;
- int ii;
- for(ii=p->nScan-1; ii>=0; ii--){
- pScan = &p->aScan[ii];
- if( pScan->addrExplain==addrExplain ) break;
- pScan = 0;
- }
- if( pScan ){
- pScan->addrLoop = addrLoop;
- pScan->addrVisit = addrVisit;
+ if( IS_STMT_SCANSTATUS(p->db) ){
+ ScanStatus *pScan = 0;
+ int ii;
+ for(ii=p->nScan-1; ii>=0; ii--){
+ pScan = &p->aScan[ii];
+ if( pScan->addrExplain==addrExplain ) break;
+ pScan = 0;
+ }
+ if( pScan ){
+ if( addrLoop>0 ) pScan->addrLoop = addrLoop;
+ if( addrVisit>0 ) pScan->addrVisit = addrVisit;
+ }
}
}
-#endif
+#endif /* defined(SQLITE_ENABLE_STMT_SCANSTATUS) */
/*
@@ -83639,7 +86453,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 );
@@ -83700,6 +86514,16 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
}
+ case P4_TABLEREF: {
+ if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
+ break;
+ }
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = (SubrtnSig*)p4;
+ sqlite3DbFree(db, pSig->zAff);
+ sqlite3DbFree(db, pSig);
+ break;
+ }
}
}
@@ -83803,7 +86627,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
@@ -83828,7 +86651,7 @@ static void SQLITE_NOINLINE vdbeChangeP4Full(
int n
){
if( pOp->p4type ){
- freeP4(p->db, pOp->p4type, pOp->p4.p);
+ assert( pOp->p4type > P4_FREE_IF_LE );
pOp->p4type = 0;
pOp->p4.p = 0;
}
@@ -83984,7 +86807,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);
}
@@ -84280,6 +87103,11 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
zP4 = pOp->p4.pTab->zName;
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = pOp->p4.pSubrtnSig;
+ sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff);
+ break;
+ }
default: {
zP4 = pOp->p4.z;
}
@@ -84421,6 +87249,7 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
** will be initialized before use.
*/
static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
+ assert( db!=0 );
if( N>0 ){
do{
p->flags = flags;
@@ -84428,6 +87257,7 @@ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
p->szMalloc = 0;
#ifdef SQLITE_DEBUG
p->pScopyFrom = 0;
+ p->bScopy = 0;
#endif
p++;
}while( (--N)>0 );
@@ -84446,6 +87276,7 @@ static void releaseMemArray(Mem *p, int N){
if( p && N ){
Mem *pEnd = &p[N];
sqlite3 *db = p->db;
+ assert( db!=0 );
if( db->pnBytesFreed ){
do{
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
@@ -84724,7 +87555,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),
@@ -84743,7 +87574,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 ){
@@ -84926,6 +87757,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( pParse!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( pParse==p->pParse );
+ assert( pParse->db==p->db );
p->pVList = pParse->pVList;
pParse->pVList = 0;
db = p->db;
@@ -84957,26 +87789,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;
@@ -85028,7 +87843,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);
@@ -85129,12 +87960,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);
@@ -85159,14 +87990,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;
@@ -85644,7 +88475,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
/* Check for immediate foreign key violations. */
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
- sqlite3VdbeCheckFk(p, 0);
+ (void)sqlite3VdbeCheckFk(p, 0);
}
/* If the auto-commit flag is set and this is the only active writer
@@ -85679,6 +88510,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;
@@ -85688,6 +88520,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;
@@ -85988,7 +88822,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){
@@ -86006,9 +88840,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);
}
}
@@ -86355,6 +89189,23 @@ static void serialGet(
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
}
}
+static int serialGet7(
+ const unsigned char *buf, /* Buffer to deserialize from */
+ Mem *pMem /* Memory cell to write value into */
+){
+ u64 x = FOUR_BYTE_UINT(buf);
+ u32 y = FOUR_BYTE_UINT(buf+4);
+ x = (x<<32) + y;
+ assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
+ swapMixedEndianFloat(x);
+ memcpy(&pMem->u.r, &x, sizeof(x));
+ if( IsNaN(x) ){
+ pMem->flags = MEM_Null;
+ return 1;
+ }
+ pMem->flags = MEM_Real;
+ return 0;
+}
SQLITE_PRIVATE void sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
@@ -86588,6 +89439,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;
}
@@ -86756,32 +89616,37 @@ 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 ){
- 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 */
+ if( sqlite3IsNaN(r) ){
+ /* SQLite considers NaN to be a NULL. And all integer values are greater
+ ** than NULL */
+ return 1;
}else{
i64 y;
- double s;
if( r<-9223372036854775808.0 ) return +1;
if( r>=9223372036854775808.0 ) return -1;
y = (i64)r;
if( iy ) return +1;
- s = (double)i;
- if( sr ) return +1;
- return 0;
+ testcase( doubleLt(((double)i),r) );
+ testcase( doubleLt(r,((double)i)) );
+ testcase( doubleEq(r,((double)i)) );
+ return (((double)i)r);
}
}
@@ -87011,7 +89876,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else if( serial_type==7 ){
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+ serialGet7(&aKey1[d1], &mem1);
rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
}else{
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
@@ -87031,19 +89896,23 @@ 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;
}else{
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( serial_type==7 ){
- if( mem1.u.ru.r ){
+ if( serialGet7(&aKey1[d1], &mem1) ){
+ rc = -1; /* mem1 is a NaN */
+ }else if( mem1.u.ru.r ){
rc = -1;
}else if( mem1.u.r>pRhs->u.r ){
rc = +1;
+ }else{
+ assert( rc==0 );
}
}else{
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
}
}
@@ -87113,7 +89982,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
/* RHS is null */
else{
serial_type = aKey1[idx1];
- rc = (serial_type!=0 && serial_type!=10);
+ if( serial_type==0
+ || serial_type==10
+ || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0)
+ ){
+ assert( rc==0 );
+ }else{
+ rc = 1;
+ }
}
if( rc!=0 ){
@@ -87573,7 +90449,8 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0
+ || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
if( 0==(pMem->flags & MEM_Null) ){
sqlite3_value *pRet = sqlite3ValueNew(v->db);
if( pRet ){
@@ -87593,7 +90470,8 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
*/
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
assert( iVar>0 );
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0
+ || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
if( iVar>=32 ){
v->expmask |= 0x80000000;
}else{
@@ -87635,6 +90513,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
@@ -87697,6 +90589,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));
@@ -87713,8 +90615,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;
@@ -87736,6 +90638,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
sqlite3DbFree(db, preupdate.aRecord);
vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
+ sqlite3VdbeMemRelease(&preupdate.oldipk);
if( preupdate.aNew ){
int i;
for(i=0; inField; i++){
@@ -87743,6 +90646,13 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
}
sqlite3DbNNFreeNN(db, preupdate.aNew);
}
+ if( preupdate.apDflt ){
+ int i;
+ for(i=0; inCol; i++){
+ sqlite3ValueFree(preupdate.apDflt[i]);
+ }
+ sqlite3DbFree(db, preupdate.apDflt);
+ }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -87813,7 +90723,6 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
- assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
@@ -87902,7 +90811,15 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
+ sqlite3_mutex *mutex;
+#endif
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( pStmt==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+#if SQLITE_THREADSAFE
+ mutex = p->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
for(i=0; inVar; i++){
@@ -88021,7 +90938,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) */
@@ -88125,7 +91042,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 */
@@ -88155,7 +91072,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 ){
@@ -88165,7 +91082,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(
@@ -88174,6 +91098,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);
@@ -88184,8 +91114,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{
@@ -88193,30 +91129,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);
}
@@ -88226,14 +91180,37 @@ 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
+#if defined(SQLITE_STRICT_SUBTYPE) && SQLITE_STRICT_SUBTYPE+0!=0
+ if( pCtx->pFunc!=0
+ && (pCtx->pFunc->funcFlags & SQLITE_RESULT_SUBTYPE)==0
+ ){
+ char zErr[200];
+ sqlite3_snprintf(sizeof(zErr), zErr,
+ "misuse of sqlite3_result_subtype() by %s()",
+ pCtx->pFunc->zName);
+ sqlite3_result_error(pCtx, zErr, -1);
+ return;
+ }
+#endif /* SQLITE_STRICT_SUBTYPE */
+ pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
pOut->eSubtype = eSubtype & 0xff;
pOut->flags |= MEM_Subtype;
@@ -88244,6 +91221,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);
}
@@ -88254,6 +91237,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 ){
@@ -88264,6 +91253,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
@@ -88296,7 +91286,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);
@@ -88308,7 +91307,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);
@@ -88322,6 +91326,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;
@@ -88334,6 +91341,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,
@@ -88342,6 +91352,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;
@@ -88429,7 +91442,7 @@ static int sqlite3Step(Vdbe *p){
}
assert( db->nVdbeWrite>0 || db->autoCommit==0
- || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+ || ((db->nDeferredCons + db->nDeferredImmCons)==0)
);
#ifndef SQLITE_OMIT_TRACE
@@ -88594,6 +91607,9 @@ 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;
+#endif
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
@@ -88609,7 +91625,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;
}
@@ -88628,7 +91648,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);
}
@@ -88636,7 +91660,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){
@@ -88656,7 +91680,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{
@@ -88787,6 +91811,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;
@@ -88819,8 +91846,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;
@@ -88876,7 +91907,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;
}
/*
@@ -88921,6 +91953,7 @@ static const Mem *columnNullValue(void){
#ifdef SQLITE_DEBUG
/* .pScopyFrom = */ (Mem*)0,
/* .mScopyFlags= */ 0,
+ /* .bScopy = */ 0,
#endif
};
return &nullMem;
@@ -88962,10 +91995,10 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
** sqlite3_column_int64()
** sqlite3_column_text()
** sqlite3_column_text16()
-** sqlite3_column_real()
+** sqlite3_column_double()
** sqlite3_column_bytes()
** sqlite3_column_bytes16()
-** sqiite3_column_blob()
+** sqlite3_column_blob()
*/
static void columnMallocFailure(sqlite3_stmt *pStmt)
{
@@ -89049,6 +92082,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.
@@ -89081,15 +92140,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]);
@@ -89101,12 +92174,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;
}
@@ -89199,13 +92274,24 @@ 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.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
+**
+** (tag-20240917-01) If vdbeUnbind(p,(u32)(i-1)) returns SQLITE_OK,
+** that means all of the the following will be true:
+**
+** p!=0
+** p->pVar!=0
+** i>0
+** i<=p->nVar
+**
+** An assert() is normally added after vdbeUnbind() to help static analyzers
+** realize this.
*/
static int vdbeUnbind(Vdbe *p, unsigned int i){
Mem *pVar;
@@ -89214,7 +92300,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);
@@ -89263,6 +92349,7 @@ static int bindText(
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
if( zData!=0 ){
pVar = &p->aVar[i-1];
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
@@ -89312,6 +92399,7 @@ SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
sqlite3_mutex_leave(p->db->mutex);
}
@@ -89325,6 +92413,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
sqlite3_mutex_leave(p->db->mutex);
}
@@ -89335,6 +92424,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
@@ -89350,6 +92440,7 @@ SQLITE_API int sqlite3_bind_pointer(
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
sqlite3_mutex_leave(p->db->mutex);
}else if( xDestructor ){
@@ -89431,6 +92522,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
@@ -89443,6 +92535,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;
@@ -89563,6 +92658,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.
*/
@@ -89702,10 +92833,17 @@ static UnpackedRecord *vdbeUnpackRecord(
** a field of the row currently being updated or deleted.
*/
SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
- PreUpdate *p = db->pPreUpdate;
+ PreUpdate *p;
Mem *pMem;
int rc = SQLITE_OK;
+ int iStore = 0;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( db==0 || ppValue==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+ p = db->pPreUpdate;
/* Test that this call is being made from within an SQLITE_DELETE or
** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
if( !p || p->op==SQLITE_INSERT ){
@@ -89713,44 +92851,73 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_old_out;
}
if( p->pPk ){
- iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ }else{
+ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
+ if( iStore>=p->pCsr->nField || iStore<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
}
- /* If the old.* record has not yet been loaded into memory, do so now. */
- if( p->pUnpacked==0 ){
- u32 nRec;
- u8 *aRec;
+ if( iIdx==p->pTab->iPKey ){
+ *ppValue = pMem = &p->oldipk;
+ sqlite3VdbeMemSetInt64(pMem, p->iKey1);
+ }else{
- assert( p->pCsr->eCurType==CURTYPE_BTREE );
- nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
- aRec = sqlite3DbMallocRaw(db, nRec);
- if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
- if( rc==SQLITE_OK ){
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
- if( !p->pUnpacked ) rc = SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, aRec);
- goto preupdate_old_out;
+ /* If the old.* record has not yet been loaded into memory, do so now. */
+ if( p->pUnpacked==0 ){
+ u32 nRec;
+ u8 *aRec;
+
+ assert( p->pCsr->eCurType==CURTYPE_BTREE );
+ nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
+ aRec = sqlite3DbMallocRaw(db, nRec);
+ if( !aRec ) goto preupdate_old_out;
+ rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
+ if( rc==SQLITE_OK ){
+ p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
+ if( !p->pUnpacked ) rc = SQLITE_NOMEM;
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, aRec);
+ goto preupdate_old_out;
+ }
+ p->aRecord = aRec;
}
- p->aRecord = aRec;
- }
- pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else if( iIdx>=p->pUnpacked->nField ){
- *ppValue = (sqlite3_value *)columnNullValue();
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & (MEM_Int|MEM_IntReal) ){
- testcase( pMem->flags & MEM_Int );
- testcase( pMem->flags & MEM_IntReal );
- sqlite3VdbeMemRealify(pMem);
+ pMem = *ppValue = &p->pUnpacked->aMem[iStore];
+ if( iStore>=p->pUnpacked->nField ){
+ /* This occurs when the table has been extended using ALTER TABLE
+ ** ADD COLUMN. The value to return is the default value of the column. */
+ Column *pCol = &p->pTab->aCol[iIdx];
+ if( pCol->iDflt>0 ){
+ if( p->apDflt==0 ){
+ int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
+ p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
+ if( p->apDflt==0 ) goto preupdate_old_out;
+ }
+ if( p->apDflt[iIdx]==0 ){
+ sqlite3_value *pVal = 0;
+ Expr *pDflt;
+ assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
+ pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
+ rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
+ if( rc==SQLITE_OK && pVal==0 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ p->apDflt[iIdx] = pVal;
+ }
+ *ppValue = p->apDflt[iIdx];
+ }else{
+ *ppValue = (sqlite3_value *)columnNullValue();
+ }
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
+ if( pMem->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_IntReal );
+ sqlite3VdbeMemRealify(pMem);
+ }
}
}
@@ -89766,7 +92933,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 */
@@ -89784,7 +92956,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 */
@@ -89795,7 +92972,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
@@ -89806,18 +92988,28 @@ 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;
+ int iStore = 0;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( db==0 || ppValue==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+ p = db->pPreUpdate;
if( !p || p->op==SQLITE_DELETE ){
rc = SQLITE_MISUSE_BKPT;
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
- iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ }else{
+ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
+
+ if( iStore>=p->pCsr->nField || iStore<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
}
@@ -89837,14 +93029,14 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
}
p->pNewUnpacked = pUnpack;
}
- pMem = &pUnpack->aMem[iIdx];
+ pMem = &pUnpack->aMem[iStore];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }else if( iIdx>=pUnpack->nField ){
+ }else if( iStore>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
}
}else{
- /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
+ /* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required
** value. Make a copy of the cell contents and return a pointer to it.
** It is not safe to return a pointer to the memory cell itself as the
** caller may modify the value text encoding.
@@ -89857,13 +93049,13 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_new_out;
}
}
- assert( iIdx>=0 && iIdxpCsr->nField );
- pMem = &p->aNew[iIdx];
+ assert( iStore>=0 && iStorepCsr->nField );
+ pMem = &p->aNew[iStore];
if( pMem->flags==0 ){
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}else{
- rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
+ rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iStore]);
if( rc!=SQLITE_OK ) goto preupdate_new_out;
}
}
@@ -89888,15 +93080,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; iiaScan[idx];
}else{
/* If the COMPLEX flag is clear, then this function must ignore any
** ScanStatus structures with ScanStatus.addrLoop set to 0. */
@@ -89918,11 +93127,13 @@ SQLITE_API int sqlite3_stmt_scanstatus_v2(
}
}
if( idx>=p->nScan ) return 1;
+ assert( pScan==0 || pScan==&p->aScan[idx] );
+ pScan = &p->aScan[idx];
switch( iScanStatusOp ){
case SQLITE_SCANSTAT_NLOOP: {
if( pScan->addrLoop>0 ){
- *(sqlite3_int64*)pOut = p->aOp[pScan->addrLoop].nExec;
+ *(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec;
}else{
*(sqlite3_int64*)pOut = -1;
}
@@ -89930,7 +93141,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;
}
@@ -89952,7 +93163,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;
}
@@ -89960,7 +93171,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;
}
@@ -89968,7 +93179,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;
}
@@ -89986,18 +93197,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;
}
}
}
@@ -90030,7 +93241,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;
@@ -90258,6 +93469,104 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
+/*
+** High-resolution hardware timer used for debugging and testing only.
+*/
+#if defined(VDBE_PROFILE) \
+ || defined(SQLITE_PERFORMANCE_TRACE) \
+ || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+/************** Include hwtime.h in the middle of vdbe.c *********************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 and x86_64 class CPUs.
+*/
+#ifndef SQLITE_HWTIME_H
+#define SQLITE_HWTIME_H
+
+/*
+** The following routine only works on Pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value. This can be used for high-res
+** profiling.
+*/
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+ #if defined(__GNUC__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+ #elif defined(_MSC_VER)
+
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
+
+ #endif
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
+ }
+
+#else
+
+ /*
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(SQLITE_HWTIME_H) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in vdbe.c ***********************/
+#endif
+
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
@@ -90369,11 +93678,12 @@ SQLITE_API int sqlite3_found_count = 0;
** sqlite3CantopenError(lineno)
*/
static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
- static int n = 0;
+ static u64 n = 0;
(void)pc;
(void)pOp;
(void)v;
n++;
+ if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */
}
#endif
@@ -90793,6 +94103,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
@@ -90831,6 +94144,7 @@ static void registerTrace(int iReg, Mem *p){
printf("R[%d] = ", iReg);
memTracePrint(p);
if( p->pScopyFrom ){
+ assert( p->pScopyFrom->bScopy );
printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
}
printf("\n");
@@ -90920,12 +94234,102 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){
}else if( p->flags & MEM_Real ){
h += sqlite3VdbeIntValue(p);
}else if( p->flags & (MEM_Str|MEM_Blob) ){
- /* no-op */
+ /* All strings have the same hash and all blobs have the same hash,
+ ** though, at least, those hashes are different from each other and
+ ** from NULL. */
+ h += 4093 + (p->flags & (MEM_Str|MEM_Blob));
}
}
return h;
}
+
+/*
+** For OP_Column, factor out the case where content is loaded from
+** overflow pages, so that the code to implement this case is separate
+** the common case where all content fits on the page. Factoring out
+** the code reduces register pressure and helps the common case
+** to run faster.
+*/
+static SQLITE_NOINLINE int vdbeColumnFromOverflow(
+ VdbeCursor *pC, /* The BTree cursor from which we are reading */
+ int iCol, /* The column to read */
+ int t, /* The serial-type code for the column value */
+ i64 iOffset, /* Offset to the start of the content value */
+ u32 cacheStatus, /* Current Vdbe.cacheCtr value */
+ u32 colCacheCtr, /* Current value of the column cache counter */
+ Mem *pDest /* Store the value into this register. */
+){
+ int rc;
+ sqlite3 *db = pDest->db;
+ int encoding = pDest->enc;
+ int len = sqlite3VdbeSerialTypeLen(t);
+ assert( pC->eCurType==CURTYPE_BTREE );
+ if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) return SQLITE_TOOBIG;
+ if( len > 4000 && pC->pKeyInfo==0 ){
+ /* Cache large column values that are on overflow pages using
+ ** an RCStr (reference counted string) so that if they are reloaded,
+ ** that do not have to be copied a second time. The overhead of
+ ** creating and managing the cache is such that this is only
+ ** profitable for larger TEXT and BLOB values.
+ **
+ ** Only do this on table-btrees so that writes to index-btrees do not
+ ** need to clear the cache. This buys performance in the common case
+ ** in exchange for generality.
+ */
+ VdbeTxtBlbCache *pCache;
+ char *pBuf;
+ if( pC->colCache==0 ){
+ pC->pCache = sqlite3DbMallocZero(db, sizeof(VdbeTxtBlbCache) );
+ if( pC->pCache==0 ) return SQLITE_NOMEM;
+ pC->colCache = 1;
+ }
+ pCache = pC->pCache;
+ if( pCache->pCValue==0
+ || pCache->iCol!=iCol
+ || pCache->cacheStatus!=cacheStatus
+ || pCache->colCacheCtr!=colCacheCtr
+ || pCache->iOffset!=sqlite3BtreeOffset(pC->uc.pCursor)
+ ){
+ if( pCache->pCValue ) sqlite3RCStrUnref(pCache->pCValue);
+ pBuf = pCache->pCValue = sqlite3RCStrNew( len+3 );
+ if( pBuf==0 ) return SQLITE_NOMEM;
+ rc = sqlite3BtreePayload(pC->uc.pCursor, iOffset, len, pBuf);
+ if( rc ) return rc;
+ pBuf[len] = 0;
+ pBuf[len+1] = 0;
+ pBuf[len+2] = 0;
+ pCache->iCol = iCol;
+ pCache->cacheStatus = cacheStatus;
+ pCache->colCacheCtr = colCacheCtr;
+ pCache->iOffset = sqlite3BtreeOffset(pC->uc.pCursor);
+ }else{
+ pBuf = pCache->pCValue;
+ }
+ assert( t>=12 );
+ sqlite3RCStrRef(pBuf);
+ if( t&1 ){
+ rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, encoding,
+ sqlite3RCStrUnref);
+ pDest->flags |= MEM_Term;
+ }else{
+ rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, 0,
+ sqlite3RCStrUnref);
+ }
+ }else{
+ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, iOffset, len, pDest);
+ if( rc ) return rc;
+ sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
+ if( (t&1)!=0 && encoding==SQLITE_UTF8 ){
+ pDest->z[len] = 0;
+ pDest->flags |= MEM_Term;
+ }
+ }
+ pDest->flags &= ~MEM_Ephem;
+ return rc;
+}
+
+
/*
** Return the symbolic name for the data type of a pMem
*/
@@ -90968,8 +94372,10 @@ 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;
#endif
/*** INSERT STACK UNION HERE ***/
@@ -91034,13 +94440,17 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( pOp>=aOp && pOp<&aOp[p->nOp]);
nVmStep++;
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
+
+#if defined(VDBE_PROFILE)
pOp->nExec++;
pnCycle = &pOp->nCycle;
-# ifdef VDBE_PROFILE
- if( sqlite3NProfileCnt==0 )
-# endif
+ if( sqlite3NProfileCnt==0 ) *pnCycle -= sqlite3Hwtime();
+#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+ if( bStmtScanStatus ){
+ pOp->nExec++;
+ pnCycle = &pOp->nCycle;
*pnCycle -= sqlite3Hwtime();
+ }
#endif
/* Only allow tracing if SQLITE_DEBUG is defined.
@@ -91158,8 +94568,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) );
@@ -91266,7 +94676,7 @@ case OP_Return: { /* in1 */
**
** See also: EndCoroutine
*/
-case OP_InitCoroutine: { /* jump */
+case OP_InitCoroutine: { /* jump0 */
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
assert( pOp->p2>=0 && pOp->p2nOp );
assert( pOp->p3>=0 && pOp->p3nOp );
@@ -91289,7 +94699,9 @@ case OP_InitCoroutine: { /* jump */
**
** The instruction at the address in register P1 is a Yield.
** Jump to the P2 parameter of that Yield.
-** After the jump, register P1 becomes undefined.
+** After the jump, the value register P1 is left with a value
+** such that subsequent OP_Yields go back to the this same
+** OP_EndCoroutine instruction.
**
** See also: InitCoroutine
*/
@@ -91301,8 +94713,8 @@ case OP_EndCoroutine: { /* in1 */
pCaller = &aOp[pIn1->u.i];
assert( pCaller->opcode==OP_Yield );
assert( pCaller->p2>=0 && pCaller->p2nOp );
+ pIn1->u.i = (int)(pOp - p->aOp) - 1;
pOp = &aOp[pCaller->p2 - 1];
- pIn1->flags = MEM_Undefined;
break;
}
@@ -91319,7 +94731,7 @@ case OP_EndCoroutine: { /* in1 */
**
** See also: InitCoroutine
*/
-case OP_Yield: { /* in1, jump */
+case OP_Yield: { /* in1, jump0 */
int pcDest;
pIn1 = &aMem[pOp->p1];
assert( VdbeMemDynamic(pIn1)==0 );
@@ -91349,7 +94761,7 @@ case OP_HaltIfNull: { /* in3 */
/* no break */ deliberate_fall_through
}
-/* Opcode: Halt P1 P2 * P4 P5
+/* Opcode: Halt P1 P2 P3 P4 P5
**
** Exit immediately. All open cursors, etc are closed
** automatically.
@@ -91362,18 +94774,22 @@ case OP_HaltIfNull: { /* in3 */
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
-** If P4 is not null then it is an error message string.
+** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
+** text of an error message.
**
-** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
+** If P3 is zero and P4 is not null then the error message string is held
+** in P4.
**
-** 0: (no change)
-** 1: NOT NULL contraint failed: P4
+** P5 is a value between 1 and 4, inclusive, then the P4 error message
+** string is modified as follows:
+**
+** 1: NOT NULL constraint failed: P4
** 2: UNIQUE constraint failed: P4
** 3: CHECK constraint failed: P4
** 4: FOREIGN KEY constraint failed: P4
**
-** If P5 is not zero and P4 is NULL, then everything after the ":" is
-** omitted.
+** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
+** the ":" is omitted.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
@@ -91386,6 +94802,9 @@ case OP_Halt: {
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
+ assert( pOp->p4type==P4_NOTUSED
+ || pOp->p4type==P4_STATIC
+ || pOp->p4type==P4_DYNAMIC );
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
** something is wrong with the code generator. Raise an assertion in order
@@ -91416,7 +94835,12 @@ case OP_Halt: {
p->errorAction = (u8)pOp->p2;
assert( pOp->p5<=4 );
if( p->rc ){
- if( pOp->p5 ){
+ if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
+ const char *zErr;
+ assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
+ zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
+ sqlite3VdbeError(p, "%s", zErr);
+ }else if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
"FOREIGN KEY" };
testcase( pOp->p5==1 );
@@ -91649,19 +95073,15 @@ case OP_Blob: { /* out2 */
break;
}
-/* Opcode: Variable P1 P2 * P4 *
-** Synopsis: r[P2]=parameter(P1,P4)
+/* Opcode: Variable P1 P2 * * *
+** Synopsis: r[P2]=parameter(P1)
**
** Transfer the values of bound parameter P1 into register P2
-**
-** If the parameter is named, then its name appears in P4.
-** The P4 value is used by sqlite3_bind_parameter_name().
*/
case OP_Variable: { /* out2 */
Mem *pVar; /* Value being transferred */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
- assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
pVar = &p->aVar[pOp->p1 - 1];
if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
@@ -91708,6 +95128,7 @@ case OP_Move: {
{ int i;
for(i=1; inMem; i++){
if( aMem[i].pScopyFrom==pIn1 ){
+ assert( aMem[i].bScopy );
aMem[i].pScopyFrom = pOut;
}
}
@@ -91780,6 +95201,7 @@ case OP_SCopy: { /* out2 */
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = pIn1;
pOut->mScopyFlags = pIn1->flags;
+ pIn1->bScopy = 1;
#endif
break;
}
@@ -92171,7 +95593,7 @@ case OP_AddImm: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
sqlite3VdbeMemIntegerify(pIn1);
- pIn1->u.i += pOp->p2;
+ *(u64*)&pIn1->u.i += (u64)pOp->p2;
break;
}
@@ -92182,7 +95604,7 @@ case OP_AddImm: { /* in1 */
** without data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE_MISMATCH exception.
*/
-case OP_MustBeInt: { /* jump, in1 */
+case OP_MustBeInt: { /* jump0, in1 */
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Int)==0 ){
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
@@ -92223,7 +95645,7 @@ case OP_RealAffinity: { /* in1 */
}
#endif
-#ifndef SQLITE_OMIT_CAST
+#if !defined(SQLITE_OMIT_CAST) || !defined(SQLITE_OMIT_ANALYZE)
/* Opcode: Cast P1 P2 * * *
** Synopsis: affinity(r[P1])
**
@@ -92438,7 +95860,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}
}
}else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){
- if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
+ if( (flags1 & MEM_Str)!=0 ){
+ pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
+ }else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_Real );
testcase( pIn1->flags & MEM_IntReal );
@@ -92447,7 +95871,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
}
- if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
+ if( (flags3 & MEM_Str)!=0 ){
+ pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
+ }else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_Real );
testcase( pIn3->flags & MEM_IntReal );
@@ -92498,10 +95924,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 */
@@ -92628,7 +96054,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.
@@ -92855,6 +96281,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.
@@ -92925,7 +96357,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.
*/
@@ -92968,7 +96400,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;
}
@@ -93279,11 +96711,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,
@@ -93300,11 +96737,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;
+ }
}
}
@@ -93463,7 +96902,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);
@@ -93766,7 +97205,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));
@@ -93774,12 +97212,22 @@ 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;
+ /* no break */ deliberate_fall_through
+ case 6: zPayload[5] = (u8)(v&0xff); v >>= 8;
+ zPayload[4] = (u8)(v&0xff); v >>= 8;
+ /* no break */ deliberate_fall_through
+ case 4: zPayload[3] = (u8)(v&0xff); v >>= 8;
+ /* no break */ deliberate_fall_through
+ case 3: zPayload[2] = (u8)(v&0xff); v >>= 8;
+ /* no break */ deliberate_fall_through
+ case 2: zPayload[1] = (u8)(v&0xff); v >>= 8;
+ /* no break */ deliberate_fall_through
+ case 1: zPayload[0] = (u8)(v&0xff);
}
zPayload += len;
}
@@ -94437,23 +97885,23 @@ case OP_OpenWrite:
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
}
+ if( pOp->p5 & OPFLAG_P2ISREG ){
+ assert( p2>0 );
+ assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
+ pIn2 = &aMem[p2];
+ assert( memIsValid(pIn2) );
+ assert( (pIn2->flags & MEM_Int)!=0 );
+ sqlite3VdbeMemIntegerify(pIn2);
+ p2 = (int)pIn2->u.i;
+ /* The p2 value always comes from a prior OP_CreateBtree opcode and
+ ** that opcode will always set the p2 value to 2 or more or else fail.
+ ** If there were a failure, the prepared statement would have halted
+ ** before reaching this instruction. */
+ assert( p2>=2 );
+ }
}else{
wrFlag = 0;
- }
- if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( p2>0 );
- assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
- assert( pOp->opcode==OP_OpenWrite );
- pIn2 = &aMem[p2];
- assert( memIsValid(pIn2) );
- assert( (pIn2->flags & MEM_Int)!=0 );
- sqlite3VdbeMemIntegerify(pIn2);
- p2 = (int)pIn2->u.i;
- /* The p2 value always comes from a prior OP_CreateBtree opcode and
- ** that opcode will always set the p2 value to 2 or more or else fail.
- ** If there were a failure, the prepared statement would have halted
- ** before reaching this instruction. */
- assert( p2>=2 );
+ assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
}
if( pOp->p4type==P4_KEYINFO ){
pKeyInfo = pOp->p4.pKeyInfo;
@@ -94588,7 +98036,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 );
@@ -94630,8 +98078,13 @@ case OP_OpenEphemeral: { /* ncycle */
}
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ assert( p->apCsr[pOp->p1]==pCx );
if( rc ){
+ assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
sqlite3BtreeClose(pCx->ub.pBtx);
+ p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */
+ }else{
+ assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
}
}
}
@@ -94697,7 +98150,8 @@ case OP_SequenceTest: {
** is the only cursor opcode that works with a pseudo-table.
**
** P3 is the number of fields in the records that will be stored by
-** the pseudo-table.
+** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
+** will return NULL for every column.
*/
case OP_OpenPseudo: {
VdbeCursor *pCx;
@@ -94840,10 +98294,10 @@ case OP_ColumnsUsed: {
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
-case OP_SeekLT: /* jump, in3, group, ncycle */
-case OP_SeekLE: /* jump, in3, group, ncycle */
-case OP_SeekGE: /* jump, in3, group, ncycle */
-case OP_SeekGT: { /* jump, in3, group, ncycle */
+case OP_SeekLT: /* jump0, in3, group, ncycle */
+case OP_SeekLE: /* jump0, in3, group, ncycle */
+case OP_SeekGE: /* jump0, in3, group, ncycle */
+case OP_SeekGT: { /* jump0, in3, group, ncycle */
int res; /* Comparison result */
int oc; /* Opcode */
VdbeCursor *pC; /* The cursor to seek */
@@ -95079,7 +98533,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
@@ -95087,7 +98541,7 @@ case OP_SeekGT: { /* jump, in3, group, ncycle */
**
** Possible outcomes from this opcode:
**
-** - If the cursor is initally not pointed to any valid row, then
+**
- If the cursor is initially not pointed to any valid row, then
** fall through into the subsequent OP_SeekGE opcode.
**
**
- If the cursor is left pointing to a row that is before the target
@@ -95202,6 +98656,7 @@ case OP_SeekScan: { /* ncycle */
break;
}
nStep--;
+ pC->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
if( rc ){
if( rc==SQLITE_DONE ){
@@ -95318,13 +98773,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.
**
@@ -95407,6 +98862,7 @@ case OP_Found: { /* jump, in3, ncycle */
r.pKeyInfo = pC->pKeyInfo;
r.default_rc = 0;
#ifdef SQLITE_DEBUG
+ (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
for(ii=0; iideferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
+ colCacheCtr++;
/* Invoke the update-hook if required. */
if( rc ) goto abort_due_to_error;
@@ -95889,13 +99346,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 (0x01) flag of P2 (NB: P2 not P5) is set, then
+** the row change count is incremented (otherwise not).
**
-** 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_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.
@@ -95996,6 +99458,7 @@ 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;
@@ -96063,13 +99526,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];
@@ -96261,7 +99724,7 @@ case OP_NullRow: {
** configured to use Prev, not Next.
*/
case OP_SeekEnd: /* ncycle */
-case OP_Last: { /* jump, ncycle */
+case OP_Last: { /* jump0, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
@@ -96295,28 +99758,38 @@ case OP_Last: { /* jump, ncycle */
break;
}
-/* Opcode: IfSmaller P1 P2 P3 * *
+/* Opcode: IfSizeBetween P1 P2 P3 P4 *
**
-** Estimate the number of rows in the table P1. Jump to P2 if that
-** estimate is less than approximately 2**(0.1*P3).
+** Let N be the approximate number of rows in the table or index
+** with cursor P1 and let X be 10*log2(N) if N is positive or -1
+** if N is zero.
+**
+** Jump to P2 if X is in between P3 and P4, inclusive.
*/
-case OP_IfSmaller: { /* jump */
+case OP_IfSizeBetween: { /* jump */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
i64 sz;
assert( pOp->p1>=0 && pOp->p1nCursor );
+ assert( pOp->p4type==P4_INT32 );
+ assert( pOp->p3>=-1 && pOp->p3<=640*2 );
+ assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->uc.pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
if( rc ) goto abort_due_to_error;
- if( res==0 ){
+ if( res!=0 ){
+ sz = -1; /* -Infinity encoding */
+ }else{
sz = sqlite3BtreeRowCountEst(pCrsr);
- if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)p3 ) res = 1;
+ assert( sz>0 );
+ sz = sqlite3LogEst((u64)sz);
}
+ res = sz>=pOp->p3 && sz<=pOp->p4.i;
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
break;
@@ -96344,8 +99817,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--;
@@ -96369,7 +99842,7 @@ case OP_Sort: { /* jump */
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
*/
-case OP_Rewind: { /* jump, ncycle */
+case OP_Rewind: { /* jump0, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
@@ -96872,7 +100345,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
@@ -96932,8 +100405,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
@@ -97016,16 +100489,57 @@ case OP_CreateBtree: { /* out2 */
break;
}
-/* Opcode: SqlExec * * * P4 *
+/* Opcode: SqlExec P1 P2 * P4 *
**
** Run the SQL statement or statements specified in the P4 string.
+**
+** The P1 parameter is a bitmask of options:
+**
+** 0x0001 Disable Auth and Trace callbacks while the statements
+** in P4 are running.
+**
+** 0x0002 Set db->nAnalysisLimit to P2 while the statements in
+** P4 are running.
+**
*/
case OP_SqlExec: {
+ char *zErr;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth;
+#endif
+ u8 mTrace;
+ int savedAnalysisLimit;
+
sqlite3VdbeIncrWriteCounter(p, 0);
db->nSqlExec++;
- rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
+ zErr = 0;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ xAuth = db->xAuth;
+#endif
+ mTrace = db->mTrace;
+ savedAnalysisLimit = db->nAnalysisLimit;
+ if( pOp->p1 & 0x0001 ){
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = 0;
+#endif
+ db->mTrace = 0;
+ }
+ if( pOp->p1 & 0x0002 ){
+ db->nAnalysisLimit = pOp->p2;
+ }
+ rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr);
db->nSqlExec--;
- if( rc ) goto abort_due_to_error;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+ db->mTrace = mTrace;
+ db->nAnalysisLimit = savedAnalysisLimit;
+ if( zErr || rc ){
+ sqlite3VdbeError(p, "%s", zErr);
+ sqlite3_free(zErr);
+ if( rc==SQLITE_NOMEM ) goto no_mem;
+ goto abort_due_to_error;
+ }
break;
}
@@ -97171,11 +100685,11 @@ case OP_DropTrigger: {
/* Opcode: IntegrityCk P1 P2 P3 P4 P5
**
** Do an analysis of the currently open database. Store in
-** register P1 the text of an error message describing any problems.
-** If no problems are found, store a NULL in register P1.
+** register (P1+1) the text of an error message describing any problems.
+** If no problems are found, store a NULL in register (P1+1).
**
-** The register P3 contains one less than the maximum number of allowed errors.
-** At most reg(P3) errors will be reported.
+** The register (P1) contains one less than the maximum number of allowed
+** errors. At most reg(P1) errors will be reported.
** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
**
@@ -97195,19 +100709,21 @@ case OP_IntegrityCk: {
Mem *pnErr; /* Register keeping track of errors remaining */
assert( p->bIsReader );
+ assert( pOp->p4type==P4_INTARRAY );
nRoot = pOp->p2;
aRoot = pOp->p4.ai;
assert( nRoot>0 );
+ assert( aRoot!=0 );
assert( aRoot[0]==(Pgno)nRoot );
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- pnErr = &aMem[pOp->p3];
+ assert( pOp->p1>0 && (pOp->p1+1)<=(p->nMem+1 - p->nCursor) );
+ pnErr = &aMem[pOp->p1];
assert( (pnErr->flags & MEM_Int)!=0 );
assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
- pIn1 = &aMem[pOp->p1];
+ pIn1 = &aMem[pOp->p1+1];
assert( pOp->p5nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
- rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
- (int)pnErr->u.i+1, &nErr, &z);
+ rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1],
+ &aMem[pOp->p3], nRoot, (int)pnErr->u.i+1, &nErr, &z);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
@@ -97334,7 +100850,9 @@ case OP_RowSetTest: { /* jump, in1, in3 */
** P1 contains the address of the memory cell that contains the first memory
** cell in an array of values used as arguments to the sub-program. P2
** contains the address to jump to if the sub-program throws an IGNORE
-** exception using the RAISE() function. Register P3 contains the address
+** exception using the RAISE() function. P2 might be zero, if there is
+** no possibility that an IGNORE exception will be raised.
+** Register P3 contains the address
** of a memory cell in this (the parent) VM that is used to allocate the
** memory required by the sub-vdbe at runtime.
**
@@ -97342,7 +100860,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
**
** If P5 is non-zero, then recursive program invocation is enabled.
*/
-case OP_Program: { /* jump */
+case OP_Program: { /* jump0 */
int nMem; /* Number of memory registers for sub-program */
int nByte; /* Bytes of runtime space required for sub-program */
Mem *pRt; /* Register to allocate runtime space */
@@ -97707,18 +101225,29 @@ case OP_AggInverse:
case OP_AggStep: {
int n;
sqlite3_context *pCtx;
+ u64 nAlloc;
assert( pOp->p4type==P4_FUNCDEF );
n = pOp->p5;
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
assert( pOp->p3p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
- (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
+
+ /* Allocate space for (a) the context object and (n-1) extra pointers
+ ** to append to the sqlite3_context.argv[1] array, and (b) a memory
+ ** cell in which to store the accumulation. Be careful that the memory
+ ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
+ **
+ ** Note: We could avoid this by using a regular memory cell from aMem[] for
+ ** the accumulator, instead of allocating one here. */
+ nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) );
+ pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
if( pCtx==0 ) goto no_mem;
- pCtx->pMem = 0;
- pCtx->pOut = (Mem*)&(pCtx->argv[n]);
+ pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
+ assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
+
sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
+ pCtx->pMem = 0;
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
@@ -97759,7 +101288,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];
@@ -97854,6 +101383,7 @@ case OP_AggFinal: {
}
sqlite3VdbeChangeEncoding(pMem, encoding);
UPDATE_MAX_BLOBSIZE(pMem);
+ REGISTER_TRACE((int)(pMem-aMem), pMem);
break;
}
@@ -98245,6 +101775,52 @@ 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_TABLEREF );
+ pTab = pOp->p4.pTab;
+ assert( pTab!=0 );
+ assert( pTab->nTabRef>0 );
+ assert( IsVirtual(pTab) );
+ if( pTab->u.vtab.p==0 ) break;
+ pVtab = pTab->u.vtab.p->pVtab;
+ assert( pVtab!=0 );
+ pModule = pVtab->pModule;
+ assert( pModule!=0 );
+ assert( pModule->iVersion>=4 );
+ assert( pModule->xIntegrity!=0 );
+ sqlite3VtabLock(pTab->u.vtab.p);
+ assert( pOp->p1>=0 && pOp->p1nDb );
+ rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName,
+ pOp->p3, &zErr);
+ sqlite3VtabUnlock(pTab->u.vtab.p);
+ if( rc ){
+ sqlite3_free(zErr);
+ goto abort_due_to_error;
+ }
+ if( zErr ){
+ sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free);
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VInitIn P1 P2 P3 * *
** Synopsis: r[P2]=ValueList(P1,P3)
@@ -98358,6 +101934,7 @@ case OP_VColumn: { /* ncycle */
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
+ FuncDef nullFunc;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
@@ -98375,6 +101952,9 @@ case OP_VColumn: { /* ncycle */
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
sContext.enc = encoding;
+ nullFunc.pUserData = 0;
+ nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE;
+ sContext.pFunc = &nullFunc;
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
@@ -98636,7 +102216,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.
@@ -98654,7 +102234,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;
@@ -98707,6 +102287,42 @@ case OP_ClrSubtype: { /* in1 */
break;
}
+/* Opcode: GetSubtype P1 P2 * * *
+** Synopsis: r[P2] = r[P1].subtype
+**
+** Extract the subtype value from register P1 and write that subtype
+** into register P2. If P1 has no subtype, then P1 gets a NULL.
+*/
+case OP_GetSubtype: { /* in1 out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
+ if( pIn1->flags & MEM_Subtype ){
+ sqlite3VdbeMemSetInt64(pOut, pIn1->eSubtype);
+ }else{
+ sqlite3VdbeMemSetNull(pOut);
+ }
+ break;
+}
+
+/* Opcode: SetSubtype P1 P2 * * *
+** Synopsis: r[P2].subtype = r[P1]
+**
+** Set the subtype value of register P2 to the integer from register P1.
+** If P1 is NULL, clear the subtype from p2.
+*/
+case OP_SetSubtype: { /* in1 out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
+ if( pIn1->flags & MEM_Null ){
+ pOut->flags &= ~MEM_Subtype;
+ }else{
+ assert( pIn1->flags & MEM_Int );
+ pOut->flags |= MEM_Subtype;
+ pOut->eSubtype = (u8)(pIn1->u.i & 0xff);
+ }
+ break;
+}
+
/* Opcode: FilterAdd P1 * P3 P4 *
** Synopsis: filter(P1) += key(P3@P4)
**
@@ -98730,7 +102346,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;
}
@@ -98766,7 +102382,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]++;
@@ -98804,7 +102420,7 @@ case OP_Filter: { /* jump */
** error is encountered.
*/
case OP_Trace:
-case OP_Init: { /* jump */
+case OP_Init: { /* jump0 */
int i;
#ifndef SQLITE_OMIT_TRACE
char *zTrace;
@@ -98965,14 +102581,29 @@ case OP_ReleaseReg: {
/* Opcode: Noop * * * * *
**
-** Do nothing. This instruction is often useful as a jump
-** destination.
+** Do nothing. Continue downward to the next opcode.
*/
-/*
-** The magic Explain opcode are only inserted when explain==2 (which
-** is to say when the EXPLAIN QUERY PLAN syntax is used.)
-** This opcode records information from the optimizer. It is the
-** the same as a no-op. This opcodesnever appears in a real VM program.
+/* Opcode: Explain P1 P2 P3 P4 *
+**
+** This is the same as OP_Noop during normal query execution. The
+** purpose of this opcode is to hold information about the query
+** plan for the purpose of EXPLAIN QUERY PLAN output.
+**
+** The P4 value is human-readable text that describes the query plan
+** element. Something like "SCAN t1" or "SEARCH t2 USING INDEX t2x1".
+**
+** The P1 value is the ID of the current element and P2 is the parent
+** element for the case of nested query plan elements. If P2 is zero
+** then this element is a top-level element.
+**
+** For loop elements, P3 is the estimated code of each invocation of this
+** element.
+**
+** As with all opcodes, the meanings of the parameters for OP_Explain
+** are subject to change from one release to the next. Applications
+** should not attempt to interpret or use any of the information
+** contained in the OP_Explain opcode. The information provided by this
+** opcode is intended for testing and debugging use only.
*/
default: { /* This is really OP_Noop, OP_Explain */
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
@@ -98992,8 +102623,10 @@ default: { /* This is really OP_Noop, OP_Explain */
*pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
pnCycle = 0;
#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
- *pnCycle += sqlite3Hwtime();
- pnCycle = 0;
+ if( pnCycle ){
+ *pnCycle += sqlite3Hwtime();
+ pnCycle = 0;
+ }
#endif
/* The following code adds nothing to the actual functionality
@@ -99016,7 +102649,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);
}
@@ -99189,8 +102822,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
@@ -99273,7 +102905,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
@@ -99298,6 +102930,11 @@ SQLITE_API int sqlite3_blob_open(
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
+ if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
+ pTab = 0;
+ sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
+ zTable);
+ }
#ifndef SQLITE_OMIT_VIEW
if( pTab && IsView(pTab) ){
pTab = 0;
@@ -99472,7 +103109,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);
@@ -99631,7 +103268,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 );
@@ -99734,7 +103371,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
@@ -99757,7 +103394,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.
**
@@ -99835,7 +103472,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 */
};
/*
@@ -99920,7 +103557,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,
@@ -99944,10 +103581,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 */
@@ -99992,7 +103629,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.
*/
@@ -100205,13 +103842,14 @@ static int vdbePmaReadBlob(
while( nRem>0 ){
int rc; /* vdbePmaReadBlob() return code */
int nCopy; /* Number of bytes to copy */
- u8 *aNext; /* Pointer to buffer to copy data from */
+ u8 *aNext = 0; /* Pointer to buffer to copy data from */
nCopy = nRem;
if( nRem>p->nBuffer ) nCopy = p->nBuffer;
rc = vdbePmaReadBlob(p, nCopy, &aNext);
if( rc!=SQLITE_OK ) return rc;
assert( aNext!=p->aAlloc );
+ assert( aNext!=0 );
memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
nRem -= nCopy;
}
@@ -101363,7 +105001,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;
@@ -101421,8 +105059,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 );
@@ -101847,7 +105485,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 ){
@@ -102487,6 +106125,8 @@ static int bytecodevtabConnect(
"p5 INT,"
"comment TEXT,"
"subprog TEXT,"
+ "nexec INT,"
+ "ncycle INT,"
"stmt HIDDEN"
");",
@@ -102649,7 +106289,7 @@ static int bytecodevtabColumn(
}
}
}
- i += 10;
+ i += 20;
}
}
switch( i ){
@@ -102699,16 +106339,31 @@ static int bytecodevtabColumn(
}
break;
}
- case 10: /* tables_used.type */
+
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+ case 9: /* nexec */
+ sqlite3_result_int64(ctx, pOp->nExec);
+ break;
+ case 10: /* ncycle */
+ sqlite3_result_int64(ctx, pOp->nCycle);
+ break;
+#else
+ case 9: /* nexec */
+ case 10: /* ncycle */
+ sqlite3_result_int(ctx, 0);
+ break;
+#endif
+
+ case 20: /* tables_used.type */
sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
break;
- case 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;
}
@@ -102782,7 +106437,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;
@@ -102829,7 +106484,8 @@ static sqlite3_module bytecodevtabModule = {
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
- /* xShadowName */ 0
+ /* xShadowName */ 0,
+ /* xIntegrity */ 0
};
@@ -103353,7 +107009,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) );
@@ -103362,7 +107018,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;
@@ -103386,7 +107044,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;
}
/*
@@ -103461,7 +107119,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
pSrc = p->pSrc;
if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ if( pItem->fg.isSubquery
+ && sqlite3WalkSelect(pWalker, pItem->u4.pSubq->pSelect)
+ ){
return WRC_Abort;
}
if( pItem->fg.isTabFunc
@@ -103512,7 +107172,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);
@@ -103631,6 +107291,8 @@ static void resolveAlias(
assert( iCol>=0 && iColnExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
+ assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
+ if( pExpr->pAggInfo ) return;
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( db->mallocFailed ){
@@ -103656,21 +107318,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) ){
@@ -103682,9 +107359,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;
}
@@ -103717,6 +107396,7 @@ SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){
assert( ExprUseYTab(pExpr) );
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
+ assert( n < pExTab->nCol );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
){
@@ -103747,7 +107427,7 @@ static void extendFJMatch(
if( pNew ){
pNew->iTable = pMatch->iCursor;
pNew->iColumn = iColumn;
- pNew->y.pTab = pMatch->pTab;
+ pNew->y.pTab = pMatch->pSTab;
assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
ExprSetProperty(pNew, EP_CanBeNull);
*ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
@@ -103760,7 +107440,7 @@ static void extendFJMatch(
static SQLITE_NOINLINE int isValidSchemaTableName(
const char *zTab, /* Name as it appears in the SQL */
Table *pTab, /* The schema table we are trying to match */
- Schema *pSchema /* non-NULL if a database qualifier is present */
+ const char *zDb /* non-NULL if a database qualifier is present */
){
const char *zLegacy;
assert( pTab!=0 );
@@ -103771,7 +107451,7 @@ static SQLITE_NOINLINE int isValidSchemaTableName(
if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
return 1;
}
- if( pSchema==0 ) return 0;
+ if( zDb==0 ) return 0;
if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
}else{
@@ -103811,13 +107491,13 @@ static int lookupName(
Parse *pParse, /* The parsing context */
const char *zDb, /* Name of the database containing table, or NULL */
const char *zTab, /* Name of table containing column, or NULL */
- const char *zCol, /* Name of the column. */
+ const Expr *pRight, /* Name of the column. */
NameContext *pNC, /* The name context used to resolve the name */
Expr *pExpr /* Make this EXPR node point to the selected column */
){
int i, j; /* Loop counters */
int cnt = 0; /* Number of matching column names */
- int cntTab = 0; /* Number of 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 */
@@ -103828,6 +107508,7 @@ static int lookupName(
Table *pTab = 0; /* Table holding the row */
Column *pCol; /* A column of pTab */
ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */
+ const char *zCol = pRight->u.zToken;
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
@@ -103877,10 +107558,10 @@ static int lookupName(
if( pSrcList ){
for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){
u8 hCol;
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 || pParse->nErr );
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem));
if( pItem->fg.isNestedFrom ){
/* In this case, pItem is a subquery that has been formed from a
** parenthesized subset of the FROM clause terms. Example:
@@ -103889,44 +107570,58 @@ static int lookupName(
** This pItem -------------^
*/
int hit = 0;
- assert( pItem->pSelect!=0 );
- pEList = pItem->pSelect->pEList;
+ Select *pSel;
+ assert( pItem->fg.isSubquery );
+ assert( pItem->u4.pSubq!=0 );
+ pSel = pItem->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ pEList = pSel->pEList;
assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol );
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;
@@ -103943,7 +107638,7 @@ static int lookupName(
}
}else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
if( pTab->tnum!=1 ) continue;
- if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
+ if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue;
}
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT && pItem->zAlias ){
@@ -103990,14 +107685,43 @@ static int lookupName(
}
}
if( 0==cnt && VisibleRowid(pTab) ){
+ /* pTab is a potential ROWID match. Keep track of it and match
+ ** the ROWID later if that seems appropriate. (Search for "cntTab"
+ ** to find related code.) Only allow a ROWID match if there is
+ ** a single ROWID match candidate.
+ */
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ /* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match
+ ** if there is a single VIEW candidate or if there is a single
+ ** non-VIEW candidate plus multiple VIEW candidates. In other
+ ** words non-VIEW candidate terms take precedence over VIEWs.
+ */
+ if( cntTab==0
+ || (cntTab==1
+ && pMatch!=0
+ && ALWAYS(pMatch->pSTab!=0)
+ && (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0
+ && (pTab->tabFlags & TF_Ephemeral)==0)
+ ){
+ cntTab = 1;
+ pMatch = pItem;
+ }else{
+ cntTab++;
+ }
+#else
+ /* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is
+ ** simpler since we require exactly one candidate, which will
+ ** always be a non-VIEW
+ */
cntTab++;
pMatch = pItem;
+#endif
}
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
assert( ExprUseYTab(pExpr) );
- pExpr->y.pTab = pMatch->pTab;
+ pExpr->y.pTab = pMatch->pSTab;
if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
@@ -104019,7 +107743,9 @@ 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
+ || isValidSchemaTableName(zTab, pParse->pTriggerTab, 0))
){
pExpr->iTable = op!=TK_DELETE;
pTab = pParse->pTriggerTab;
@@ -104037,7 +107763,7 @@ static int lookupName(
if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
- pTab = pUpsert->pUpsertSrc->a[0].pTab;
+ pTab = pUpsert->pUpsertSrc->a[0].pSTab;
pExpr->iTable = EXCLUDED_TABLE_NUMBER;
}
}
@@ -104116,14 +107842,19 @@ static int lookupName(
** Perhaps the name is a reference to the ROWID
*/
if( cnt==0
- && cntTab==1
+ && cntTab>=1
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol)
- && ALWAYS(VisibleRowid(pMatch->pTab))
+ && ALWAYS(VisibleRowid(pMatch->pSTab) || pMatch->fg.isNestedFrom)
){
- cnt = 1;
- pExpr->iColumn = -1;
+ cnt = cntTab;
+#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
+ if( pMatch->pSTab!=0 && IsView(pMatch->pSTab) ){
+ eNewExprOp = TK_NULL;
+ }
+#endif
+ if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
@@ -104276,12 +108007,17 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
}else if( zTab ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+ }else if( cnt==0 && ExprHasProperty(pRight,EP_DblQuoted) ){
+ sqlite3ErrorMsg(pParse, "%s: \"%s\" - should this be a"
+ " string literal in single-quotes?",
+ zErr, zCol);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
pParse->checkSchema = 1;
pTopNC->nNcErr++;
+ eNewExprOp = TK_NULL;
}
assert( pFJMatch==0 );
@@ -104308,8 +108044,12 @@ static int lookupName(
** If a generated column is referenced, set bits for every column
** of the table.
*/
- if( pExpr->iColumn>=0 && pMatch!=0 ){
- pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
+ if( pMatch ){
+ if( pExpr->iColumn>=0 ){
+ pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
+ }else{
+ pMatch->fg.rowidUsed = 1;
+ }
}
pExpr->op = eNewExprOp;
@@ -104347,7 +108087,7 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
SrcItem *pItem = &pSrc->a[iSrc];
Table *pTab;
assert( ExprUseYTab(p) );
- pTab = p->y.pTab = pItem->pTab;
+ pTab = p->y.pTab = pItem->pSTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
@@ -104466,7 +108206,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
assert( ExprUseYTab(pExpr) );
- pExpr->y.pTab = pItem->pTab;
+ pExpr->y.pTab = pItem->pSTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn--;
pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -104486,6 +108226,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** resolved. This prevents "column" from being counted as having been
** referenced, which might prevent a SELECT from being erroneously
** marked as correlated.
+ **
+ ** 2024-03-28: Beware of aggregates. A bare column of aggregated table
+ ** can still evaluate to NULL even though it is marked as NOT NULL.
+ ** Example:
+ **
+ ** CREATE TABLE t1(a INT NOT NULL);
+ ** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1;
+ **
+ ** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized
+ ** here because at the time this case is hit, we do not yet know whether
+ ** or not t1 is being aggregated. We have to assume the worst and omit
+ ** the optimization. The only time it is safe to apply this optimization
+ ** is within the WHERE clause.
*/
case TK_NOTNULL:
case TK_ISNULL: {
@@ -104496,19 +108249,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
- if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
- testcase( ExprHasProperty(pExpr, EP_OuterON) );
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
- pExpr->flags |= EP_IntValue;
- pExpr->op = TK_INTEGER;
+ if( IN_RENAME_OBJECT ) return WRC_Prune;
+ if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
+ /* The expression can be NULL. So the optimization does not apply */
+ return WRC_Prune;
+ }
- for(i=0, p=pNC; p && ipNext, i++){
- p->nRef = anRef[i];
+ for(i=0, p=pNC; p; p=p->pNext, i++){
+ if( (p->ncFlags & NC_Where)==0 ){
+ return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */
}
- sqlite3ExprDelete(pParse->db, pExpr->pLeft);
- pExpr->pLeft = 0;
}
+ testcase( ExprHasProperty(pExpr, EP_OuterON) );
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+#if TREETRACE_ENABLED
+ if( sqlite3TreeTrace & 0x80000 ){
+ sqlite3DebugPrintf(
+ "NOT NULL strength reduction converts the following to %d:\n",
+ pExpr->op==TK_NOTNULL
+ );
+ sqlite3ShowExpr(pExpr);
+ }
+#endif /* TREETRACE_ENABLED */
+ pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
+ pExpr->flags |= EP_IntValue;
+ pExpr->op = TK_INTEGER;
+ for(i=0, p=pNC; p && ipNext, i++){
+ p->nRef = anRef[i];
+ }
+ sqlite3ExprDelete(pParse->db, pExpr->pLeft);
+ pExpr->pLeft = 0;
return WRC_Prune;
}
@@ -104522,7 +108292,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
*/
case TK_ID:
case TK_DOT: {
- const char *zColumn;
const char *zTable;
const char *zDb;
Expr *pRight;
@@ -104531,7 +108300,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zDb = 0;
zTable = 0;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- zColumn = pExpr->u.zToken;
+ pRight = pExpr;
}else{
Expr *pLeft = pExpr->pLeft;
testcase( pNC->ncFlags & NC_IdxExpr );
@@ -104550,21 +108319,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
assert( ExprUseUToken(pLeft) && ExprUseUToken(pRight) );
zTable = pLeft->u.zToken;
- zColumn = pRight->u.zToken;
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
}
}
- return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
+ return lookupName(pParse, zDb, zTable, pRight, pNC, pExpr);
}
/* Resolve function names
*/
case TK_FUNCTION: {
- ExprList *pList = pExpr->x.pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ ExprList *pList; /* The argument list */
+ int n; /* Number of arguments */
int no_such_func = 0; /* True if no such function exists */
int wrong_num_args = 0; /* True if wrong number of arguments */
int is_agg = 0; /* True if is an aggregate function */
@@ -104576,6 +108344,9 @@ 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 );
+ pList = pExpr->x.pList;
+ n = pList ? pList->nExpr : 0;
zId = pExpr->u.zToken;
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
if( pDef==0 ){
@@ -104624,6 +108395,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}
#endif
+
+ /* If the function may call sqlite3_value_subtype(), then set the
+ ** EP_SubtArg flag on all of its argument expressions. This prevents
+ ** where.c from replacing the expression with a value read from an
+ ** index on the same expression, which will not have the correct
+ ** subtype. Also set the flag if the function expression itself is
+ ** an EP_SubtArg expression. In this case subtypes are required as
+ ** the function may return a value with a subtype back to its
+ ** caller using sqlite3_result_value(). */
+ if( (pDef->funcFlags & SQLITE_SUBTYPE)
+ || ExprHasProperty(pExpr, EP_SubtArg)
+ ){
+ int ii;
+ for(ii=0; iia[ii].pExpr, EP_SubtArg);
+ }
+ }
+
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions and other functions that change slowly are considered
@@ -104717,6 +108506,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
@@ -104728,17 +108521,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
}
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- else if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ else if( ExprHasProperty(pExpr, EP_WinFunc) || pExpr->pLeft ){
is_agg = 1;
}
-#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 ){
+ if( pWin && pParse->nErr==0 ){
Select *pSel = pNC->pWinSelect;
- assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
+ assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
if( pParse->db->mallocFailed ) break;
@@ -104763,11 +108559,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
- pExpr->op2++;
+ pExpr->op2 += (1 + pNC2->nNestedSelect);
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
+ pExpr->op2 += pNC2->nNestedSelect;
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
@@ -104796,6 +108593,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
+ assert( pExpr->x.pSelect );
if( pNC->ncFlags & NC_SelfRef ){
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
}else{
@@ -104804,6 +108602,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
+ pExpr->x.pSelect->selFlags |= SF_Correlated;
}
pNC->ncFlags |= NC_Subquery;
}
@@ -104942,7 +108741,7 @@ static int resolveOrderByTermToExprList(
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
+ assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
pEList = pSelect->pEList;
/* Resolve all names in the ORDER BY term expression
@@ -105041,7 +108840,7 @@ static int resolveCompoundOrderBy(
if( pItem->fg.done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( NEVER(pE==0) ) continue;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
return 1;
@@ -105226,7 +109025,7 @@ static int resolveOrderGroupBy(
continue;
}
}
- if( sqlite3ExprIsInteger(pE2, &iCol) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -105245,7 +109044,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);
@@ -105298,10 +109097,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.
*/
@@ -105319,7 +109116,11 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** moves the pOrderBy down to the sub-query. It will be moved back
** after the names have been resolved. */
if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
+ Select *pSub;
+ assert( p->pSrc->a[0].fg.isSubquery );
+ assert( p->pSrc->a[0].u4.pSubq!=0 );
+ pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+ assert( pSub!=0 );
assert( p->pSrc->nSrc==1 && p->pOrderBy );
assert( pSub->pPrior && pSub->pOrderBy==0 );
pSub->pOrderBy = p->pOrderBy;
@@ -105328,14 +109129,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Recursively resolve names in all subqueries in the FROM clause
*/
+ if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; ipSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
- if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
+ assert( pItem->zName!=0
+ || pItem->fg.isSubquery ); /* Test of tag-20240424-1*/
+ if( pItem->fg.isSubquery
+ && (pItem->u4.pSubq->pSelect->selFlags & SF_Resolved)==0
+ ){
int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
- sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
+ sqlite3ResolveSelectNames(pParse, pItem->u4.pSubq->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr ) return WRC_Abort;
assert( db->mallocFailed==0 );
@@ -105352,6 +109158,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
}
+ if( pOuterNC && ALWAYS(pOuterNC->nNestedSelect>0) ){
+ pOuterNC->nNestedSelect--;
+ }
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
@@ -105395,7 +109204,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
}
+ sNC.ncFlags |= NC_Where;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
+ sNC.ncFlags &= ~NC_Where;
/* Resolve names in table-valued-function arguments */
for(i=0; ipSrc->nSrc; i++){
@@ -105432,7 +109243,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** These integers will be replaced by copies of the corresponding result
** set expressions by the call to resolveOrderGroupBy() below. */
if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
+ Select *pSub;
+ assert( p->pSrc->a[0].fg.isSubquery );
+ pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+ assert( pSub!=0 );
p->pOrderBy = pSub->pOrderBy;
pSub->pOrderBy = 0;
}
@@ -105568,7 +109382,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
@@ -105585,6 +109400,9 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames(
** Resolve all names for all expression in an expression list. This is
** just like sqlite3ResolveExprNames() except that it works for an expression
** list rather than a single expression.
+**
+** The return value is SQLITE_OK (0) for success or SQLITE_ERROR (1) for a
+** failure.
*/
SQLITE_PRIVATE int sqlite3ResolveExprListNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
@@ -105593,7 +109411,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
int i;
int savedHasAgg = 0;
Walker w;
- if( pList==0 ) return WRC_Continue;
+ if( pList==0 ) return SQLITE_OK;
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
@@ -105607,10 +109425,10 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight += pExpr->nHeight;
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
- return WRC_Abort;
+ return SQLITE_ERROR;
}
#endif
- sqlite3WalkExpr(&w, pExpr);
+ sqlite3WalkExprNN(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight -= pExpr->nHeight;
#endif
@@ -105624,15 +109442,15 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
}
- if( w.pParse->nErr>0 ) return WRC_Abort;
+ if( w.pParse->nErr>0 ) return SQLITE_ERROR;
}
pNC->ncFlags |= savedHasAgg;
- return WRC_Continue;
+ return SQLITE_OK;
}
/*
** 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.
**
@@ -105695,7 +109513,7 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
if( pTab ){
sSrc.nSrc = 1;
sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pTab = pTab;
+ sSrc.a[0].pSTab = pTab;
sSrc.a[0].iCursor = -1;
if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
/* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
@@ -105782,6 +109600,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
@@ -105799,7 +109618,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
op = pExpr->op;
continue;
}
- if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
+ if( op!=TK_REGISTER ) break;
+ op = pExpr->op2;
+ if( NEVER( op==TK_REGISTER ) ) break;
}
return pExpr->affExpr;
}
@@ -105932,9 +109753,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
assert( pExpr->x.pList->nExpr>0 );
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
- }else{
- assert( pExpr->op==TK_COLLATE );
+ }else if( pExpr->op==TK_COLLATE ){
pExpr = pExpr->pLeft;
+ }else{
+ break;
}
}
return pExpr;
@@ -105993,11 +109815,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;
@@ -106019,7 +109840,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()
**
@@ -106149,7 +109970,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().
@@ -106191,7 +110012,7 @@ static int codeCompare(
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
- sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
+ sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5);
return addr;
}
@@ -106306,6 +110127,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;
@@ -106605,6 +110427,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.
**
@@ -106619,11 +110450,12 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
** appear to be quoted. If the quotes were of the form "..." (double-quotes)
** then the EP_DblQuoted flag is set on the expression node.
**
-** Special case: If op==TK_INTEGER and pToken points to a string that
-** can be translated into a 32-bit integer, then the token is not
-** stored in u.zToken. Instead, the integer values is written
-** into u.iValue and the EP_IntValue flag is set. No extra storage
+** Special case (tag-20240227-a): If op==TK_INTEGER and pToken points to
+** a string that can be translated into a 32-bit integer, then the token is
+** not stored in u.zToken. Instead, the integer values is written
+** into u.iValue and the EP_IntValue flag is set. No extra storage
** is allocated to hold the integer text and the dequote flag is ignored.
+** See also tag-20240227-b.
*/
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */
@@ -106639,7 +110471,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
if( pToken ){
if( op!=TK_INTEGER || pToken->z==0
|| sqlite3GetInt32(pToken->z, &iValue)==0 ){
- nExtra = pToken->n+1;
+ nExtra = pToken->n+1; /* tag-20240227-a */
assert( iValue>=0 );
}
}
@@ -106829,9 +110661,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;
@@ -106839,14 +110671,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);
+ }
}
}
@@ -106884,6 +110719,67 @@ 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, sqlite3ExprListDeleteGeneric, pOrderBy);
+ return;
+ }
+ if( IsWindowFunc(pExpr) ){
+ sqlite3ExprOrderByAggregateError(pParse, pExpr);
+ sqlite3ExprListDelete(db, pOrderBy);
+ return;
+ }
+
+ pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0);
+ if( pOB==0 ){
+ sqlite3ExprListDelete(db, pOrderBy);
+ return;
+ }
+ pOB->x.pList = pOrderBy;
+ assert( ExprUseXList(pOB) );
+ pExpr->pLeft = pOB;
+ ExprSetProperty(pOB, EP_FullSize);
+}
+
/*
** Check to see if a function is usable according to current access
** rules:
@@ -107007,6 +110903,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
assert( db!=0 );
+exprDeleteRestart:
assert( !ExprUseUValue(p) || p->u.iValue>=0 );
assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
@@ -107022,7 +110919,6 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
- if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
if( p->pRight ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlite3ExprDeleteNN(db, p->pRight);
@@ -107037,6 +110933,19 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}
#endif
}
+ if( p->pLeft && p->op!=TK_SELECT_COLUMN ){
+ Expr *pLeft = p->pLeft;
+ if( !ExprHasProperty(p, EP_Static)
+ && !ExprHasProperty(pLeft, EP_Static)
+ ){
+ /* Avoid unnecessary recursion on unary operators */
+ sqlite3DbNNFreeNN(db, p);
+ p = pLeft;
+ goto exprDeleteRestart;
+ }else{
+ sqlite3ExprDeleteNN(db, pLeft);
+ }
+ }
}
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbNNFreeNN(db, p);
@@ -107045,6 +110954,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
+SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3 *db, void *p){
+ if( ALWAYS(p) ) sqlite3ExprDeleteNN(db, (Expr*)p);
+}
/*
** Clear both elements of an OnOrUsing object
@@ -107062,17 +110974,15 @@ 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.
**
-** The deferred delete is (currently) implemented by adding the
-** pExpr to the pParse->pConstExpr list with a register number of 0.
+** Return 0 if the delete was successfully deferred. Return non-zero
+** if the delete happened immediately because of an OOM.
*/
-SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
- sqlite3ParserAddCleanup(pParse,
- (void(*)(sqlite3*,void*))sqlite3ExprDelete,
- pExpr);
+SQLITE_PRIVATE int sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
+ return 0==sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
}
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
@@ -107137,11 +111047,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) );
@@ -107172,56 +111078,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.
*/
-static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){
+typedef struct EdupBuf EdupBuf;
+struct EdupBuf {
+ u8 *zAlloc; /* Memory space available for storage */
+#ifdef SQLITE_DEBUG
+ u8 *zEnd; /* First byte past the end of memory */
+#endif
+};
+
+/*
+** This function is similar to sqlite3ExprDup(), except that if pEdupBuf
+** is not NULL then it points to memory that can be used to store a copy
+** of the input Expr p together with its p->u.zToken (if any). pEdupBuf
+** is updated with the new buffer tail prior to returning.
+*/
+static Expr *exprDup(
+ sqlite3 *db, /* Database connection (for memory allocation) */
+ const Expr *p, /* Expr tree to be duplicated */
+ int dupFlags, /* EXPRDUP_REDUCE for compression. 0 if not */
+ EdupBuf *pEdupBuf /* Preallocated storage space, or NULL */
+){
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
@@ -107230,22 +111173,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);
}
@@ -107303,6 +111257,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;
}
@@ -107454,30 +111410,46 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla
SrcItem *pNewItem = &pNew->a[i];
const SrcItem *pOldItem = &p->a[i];
Table *pTab;
- pNewItem->pSchema = pOldItem->pSchema;
- pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
+ pNewItem->fg = pOldItem->fg;
+ if( pOldItem->fg.isSubquery ){
+ Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery));
+ if( pNewSubq==0 ){
+ assert( db->mallocFailed );
+ pNewItem->fg.isSubquery = 0;
+ }else{
+ memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq));
+ pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags);
+ if( pNewSubq->pSelect==0 ){
+ sqlite3DbFree(db, pNewSubq);
+ pNewSubq = 0;
+ pNewItem->fg.isSubquery = 0;
+ }
+ }
+ pNewItem->u4.pSubq = pNewSubq;
+ }else if( pOldItem->fg.fixedSchema ){
+ pNewItem->u4.pSchema = pOldItem->u4.pSchema;
+ }else{
+ pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase);
+ }
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
- pNewItem->fg = pOldItem->fg;
pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->addrFillSub = pOldItem->addrFillSub;
- pNewItem->regReturn = pOldItem->regReturn;
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
+ }else if( pNewItem->fg.isTabFunc ){
+ pNewItem->u1.pFuncArg =
+ sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
+ }else{
+ pNewItem->u1.nRow = pOldItem->u1.nRow;
}
pNewItem->u2 = pOldItem->u2;
if( pNewItem->fg.isCte ){
pNewItem->u2.pCteUse->nUse++;
}
- if( pNewItem->fg.isTabFunc ){
- pNewItem->u1.pFuncArg =
- sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
- }
- pTab = pNewItem->pTab = pOldItem->pTab;
+ pTab = pNewItem->pSTab = pOldItem->pSTab;
if( pTab ){
pTab->nTabRef++;
}
- pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
if( pOldItem->fg.isUsing ){
assert( pNewItem->fg.isUsing );
pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
@@ -107493,16 +111465,13 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
int i;
assert( db!=0 );
if( p==0 ) return 0;
- assert( p->eU4!=EU4_EXPR );
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
if( pNew==0 ) return 0;
pNew->nId = p->nId;
- pNew->eU4 = p->eU4;
for(i=0; inId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
const struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pNewItem->u4 = pOldItem->u4;
}
return pNew;
}
@@ -107551,7 +111520,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla
pp = &pNew->pPrior;
pNext = pNew;
}
-
return pRet;
}
#else
@@ -107567,11 +111535,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
@@ -107836,6 +111800,9 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
}
+SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3 *db, void *pList){
+ if( ALWAYS(pList) ) exprListDeleteNN(db, (ExprList*)pList);
+}
/*
** Return the bitwise-OR of all Expr.flags fields in the given
@@ -107904,7 +111871,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
@@ -107939,6 +111906,54 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
return pExpr;
}
+/*
+** pExpr is a TK_FUNCTION node. Try to determine whether or not the
+** function is a constant function. A function is constant if all of
+** the following are true:
+**
+** (1) It is a scalar function (not an aggregate or window function)
+** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG
+** property.
+** (3) All of its arguments are constants
+**
+** This routine sets pWalker->eCode to 0 if pExpr is not a constant.
+** It makes no changes to pWalker->eCode if pExpr is constant. In
+** every case, it returns WRC_Abort.
+**
+** Called as a service subroutine from exprNodeIsConstant().
+*/
+static SQLITE_NOINLINE int exprNodeIsConstantFunction(
+ Walker *pWalker,
+ Expr *pExpr
+){
+ int n; /* Number of arguments */
+ ExprList *pList; /* List of arguments */
+ FuncDef *pDef; /* The function */
+ sqlite3 *db; /* The database */
+
+ assert( pExpr->op==TK_FUNCTION );
+ if( ExprHasProperty(pExpr, EP_TokenOnly)
+ || (pList = pExpr->x.pList)==0
+ ){;
+ n = 0;
+ }else{
+ n = pList->nExpr;
+ sqlite3WalkExprList(pWalker, pList);
+ if( pWalker->eCode==0 ) return WRC_Abort;
+ }
+ db = pWalker->pParse->db;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+ if( pDef==0
+ || pDef->xFinalize!=0
+ || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
+ || ExprHasProperty(pExpr, EP_WinFunc)
+ ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+ return WRC_Prune;
+}
+
/*
** These routines are Walker callbacks used to check expressions to
@@ -107967,6 +111982,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
** malformed schema error.
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
+ assert( pWalker->eCode>0 );
/* If pWalker->eCode is 2 then any term of the expression that comes from
** the ON or USING clauses of an outer join disqualifies the expression
@@ -107986,6 +112002,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
){
if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
return WRC_Continue;
+ }else if( pWalker->pParse ){
+ return exprNodeIsConstantFunction(pWalker, pExpr);
}else{
pWalker->eCode = 0;
return WRC_Abort;
@@ -108014,9 +112032,11 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
case TK_IF_NULL_ROW:
case TK_REGISTER:
case TK_DOT:
+ case TK_RAISE:
testcase( pExpr->op==TK_REGISTER );
testcase( pExpr->op==TK_IF_NULL_ROW );
testcase( pExpr->op==TK_DOT );
+ testcase( pExpr->op==TK_RAISE );
pWalker->eCode = 0;
return WRC_Abort;
case TK_VARIABLE:
@@ -108038,15 +112058,15 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
}
-static int exprIsConst(Expr *p, int initFlag, int iCur){
+static int exprIsConst(Parse *pParse, Expr *p, int initFlag){
Walker w;
w.eCode = initFlag;
+ w.pParse = pParse;
w.xExprCallback = exprNodeIsConstant;
w.xSelectCallback = sqlite3SelectWalkFail;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
- w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
@@ -108058,9 +112078,15 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
+**
+** The pParse parameter may be NULL. But if it is NULL, there is no way
+** to determine if function calls are constant or not, and hence all
+** function calls will be considered to be non-constant. If pParse is
+** not NULL, then a function call might be constant, depending on the
+** function and on its parameters.
*/
-SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
- return exprIsConst(p, 1, 0);
+SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
+ return exprIsConst(pParse, p, 1);
}
/*
@@ -108076,8 +112102,24 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
** can be added to the pParse->pConstExpr list and evaluated once when
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
*/
-SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
- return exprIsConst(p, 2, 0);
+static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
+ return exprIsConst(pParse, p, 2);
+}
+
+/*
+** This routine examines sub-SELECT statements as an expression is being
+** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
+** constant as long as they are uncorrelated - meaning that they do not
+** contain any terms from outer contexts.
+*/
+static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
+ assert( pSelect!=0 );
+ assert( pWalker->eCode==3 || pWalker->eCode==0 );
+ if( (pSelect->selFlags & SF_Correlated)!=0 ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+ return WRC_Prune;
}
/*
@@ -108085,35 +112127,79 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
+**
+** Consider uncorrelated subqueries to be constants if the bAllowSubq
+** parameter is true.
*/
-SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
- return exprIsConst(p, 3, iCur);
+static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
+ Walker w;
+ w.eCode = 3;
+ w.pParse = 0;
+ w.xExprCallback = exprNodeIsConstant;
+ if( bAllowSubq ){
+ w.xSelectCallback = exprSelectWalkTableConstant;
+ }else{
+ w.xSelectCallback = sqlite3SelectWalkFail;
+#ifdef SQLITE_DEBUG
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
+#endif
+ }
+ w.u.iCur = iCur;
+ sqlite3WalkExpr(&w, p);
+ return w.eCode;
}
/*
-** Check pExpr to see if it is an 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.
**
-** (2) pExpr cannot use subqueries or non-deterministic functions.
+** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
+** true and the subquery is non-correlated
+**
+** (2b) pExpr cannot use non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
- (4b) and specifically the ON clause associated with the LEFT JOIN.
+** (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
+** (5) If pSrc is the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
+**
+** (6) Either:
+**
+** (6a) pExpr does not originate in an ON or USING clause, or
+**
+** (6b) The ON or USING clause from which pExpr is derived is
+** not to the left of a RIGHT JOIN (or FULL JOIN).
+**
+** Without this restriction, accepting pExpr as a single-table
+** constraint might move the the ON/USING filter expression
+** from the left side of a RIGHT JOIN over to the right side,
+** which leads to incorrect answers. See also restriction (9)
+** on push-down.
*/
-SQLITE_PRIVATE int 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 */
+ int bAllowSubq /* Allow non-correlated subqueries */
+){
+ const SrcItem *pSrc = &pSrcList->a[iSrc];
if( pSrc->fg.jointype & JT_LTORJ ){
return 0; /* rule (3) */
}
@@ -108123,7 +112209,21 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc
}else{
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */
}
- return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) /* (6a) */
+ && (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (6b) */
+ ){
+ int jj;
+ for(jj=0; jjw.iJoin==pSrcList->a[jj].iCursor ){
+ if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){
+ return 0; /* restriction (6) */
+ }
+ break;
+ }
+ }
+ }
+ /* Rules (1), (2a), and (2b) handled by the following: */
+ return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor, bAllowSubq);
}
@@ -108208,7 +112308,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprLi
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
assert( isInit==0 || isInit==1 );
- return exprIsConst(p, 4+isInit, 0);
+ return exprIsConst(0, p, 4+isInit);
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -108234,8 +112334,12 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
+**
+** If the pParse pointer is provided, then allow the expression p to be
+** a parameter (TK_VARIABLE) that is bound to an integer.
+** But if pParse is NULL, then p must be a pure integer literal.
*/
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
int rc = 0;
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
@@ -108250,18 +112354,38 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
}
switch( p->op ){
case TK_UPLUS: {
- rc = sqlite3ExprIsInteger(p->pLeft, pValue);
+ rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
break;
}
case TK_UMINUS: {
int v = 0;
- if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
assert( ((unsigned int)v)!=0x80000000 );
*pValue = -v;
rc = 1;
}
break;
}
+ case TK_VARIABLE: {
+ sqlite3_value *pVal;
+ if( pParse==0 ) break;
+ if( NEVER(pParse->pVdbe==0) ) break;
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
+ pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
+ SQLITE_AFF_BLOB);
+ if( pVal ){
+ if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
+ sqlite3_int64 vv = sqlite3_value_int64(pVal);
+ if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
+ *pValue = (int)vv;
+ rc = 1;
+ }
+ }
+ sqlite3ValueFree(pVal);
+ }
+ break;
+ }
default: break;
}
return rc;
@@ -108298,10 +112422,14 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
return 0;
case TK_COLUMN:
assert( ExprUseYTab(p) );
- return ExprHasProperty(p, EP_CanBeNull) ||
- p->y.pTab==0 || /* Reference to column of index on expression */
- (p->iColumn>=0
+ return ExprHasProperty(p, EP_CanBeNull)
+ || NEVER(p->y.pTab==0) /* Reference to column of index on expr */
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ || (p->iColumn==XN_ROWID && IsView(p->y.pTab))
+#endif
+ || (p->iColumn>=0
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
+ && ALWAYS(p->iColumny.pTab->nCol)
&& p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
@@ -108361,11 +112489,32 @@ 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
** a pointer to the SELECT statement. If pX is not a SELECT statement,
-** or if the SELECT statement needs to be manifested into a transient
+** or if the SELECT statement needs to be materialized into a transient
** table, then return NULL.
*/
#ifndef SQLITE_OMIT_SUBQUERY
@@ -108390,8 +112539,8 @@ static Select *isCandidateForInOpt(const Expr *pX){
pSrc = p->pSrc;
assert( pSrc!=0 );
if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
- if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
- pTab = pSrc->a[0].pTab;
+ if( pSrc->a[0].fg.isSubquery) return 0;/* FROM is not a subquery or view */
+ pTab = pSrc->a[0].pSTab;
assert( pTab!=0 );
assert( !IsView(pTab) ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
@@ -108431,13 +112580,13 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
** The argument is an IN operator with a list (not a subquery) on the
** right-hand side. Return TRUE if that list is constant.
*/
-static int sqlite3InRhsIsConstant(Expr *pIn){
+static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){
Expr *pLHS;
int res;
assert( !ExprHasProperty(pIn, EP_xIsSelect) );
pLHS = pIn->pLeft;
pIn->pLeft = 0;
- res = sqlite3ExprIsConstant(pIn);
+ res = sqlite3ExprIsConstant(pParse, pIn);
pIn->pLeft = pLHS;
return res;
}
@@ -108461,7 +112610,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.
**
@@ -108474,7 +112623,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.
**
@@ -108486,12 +112635,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.
**
@@ -108574,7 +112723,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
- pTab = p->pSrc->a[0].pTab;
+ pTab = p->pSrc->a[0].pSTab;
/* Code an OP_Transaction and OP_TableLock for
. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -108651,7 +112800,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] );
@@ -108667,6 +112815,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
if( aiMap ) aiMap[i] = j;
}
+ assert( nExpr>0 && nExprx.pList->nExpr<=2)
+ && (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2)
){
pParse->nTab--; /* Back out the allocation of the unused cursor */
iTab = -1; /* Cursor is not allocated */
@@ -108815,6 +112964,50 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
}
}
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** Scan all previously generated bytecode looking for an OP_BeginSubrtn
+** that is compatible with pExpr. If found, add the y.sub values
+** to pExpr and return true. If not found, return false.
+*/
+static int findCompatibleInRhsSubrtn(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* IN operator with RHS that we want to reuse */
+ SubrtnSig *pNewSig /* Signature for the IN operator */
+){
+ VdbeOp *pOp, *pEnd;
+ SubrtnSig *pSig;
+ Vdbe *v;
+
+ if( pNewSig==0 ) return 0;
+ if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0;
+ assert( pExpr->op==TK_IN );
+ assert( !ExprUseYSub(pExpr) );
+ assert( ExprUseXSelect(pExpr) );
+ assert( pExpr->x.pSelect!=0 );
+ assert( (pExpr->x.pSelect->selFlags & SF_All)==0 );
+ v = pParse->pVdbe;
+ assert( v!=0 );
+ pOp = sqlite3VdbeGetOp(v, 1);
+ pEnd = sqlite3VdbeGetLastOp(v);
+ for(; pOpp4type!=P4_SUBRTNSIG ) continue;
+ assert( pOp->opcode==OP_BeginSubrtn );
+ pSig = pOp->p4.pSubrtnSig;
+ assert( pSig!=0 );
+ if( !pSig->bComplete ) continue;
+ if( pNewSig->selId!=pSig->selId ) continue;
+ if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue;
+ pExpr->y.sub.iAddr = pSig->iAddr;
+ pExpr->y.sub.regReturn = pSig->regReturn;
+ pExpr->iTable = pSig->iTable;
+ ExprSetProperty(pExpr, EP_Subrtn);
+ return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code that will construct an ephemeral table containing all terms
@@ -108825,7 +113018,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.
@@ -108849,6 +113042,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
KeyInfo *pKeyInfo = 0; /* Key information */
int nVal; /* Size of vector pLeft */
Vdbe *v; /* The prepared statement under construction */
+ SubrtnSig *pSig = 0; /* Signature for this subroutine */
v = pParse->pVdbe;
assert( v!=0 );
@@ -108864,11 +113058,27 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
** and reuse it many names.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
- /* Reuse of the RHS is allowed */
- /* If this routine has already been coded, but the previous code
- ** might not have been invoked yet, so invoke it now as a subroutine.
+ /* Reuse of the RHS is allowed
+ **
+ ** Compute a signature for the RHS of the IN operator to facility
+ ** finding and reusing prior instances of the same IN operator.
*/
- if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 );
+ if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){
+ pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0]));
+ if( pSig ){
+ pSig->selId = pExpr->x.pSelect->selId;
+ pSig->zAff = exprINAffinity(pParse, pExpr);
+ }
+ }
+
+ /* Check to see if there is a prior materialization of the RHS of
+ ** this IN operator. If there is, then make use of that prior
+ ** materialization rather than recomputing it.
+ */
+ if( ExprHasProperty(pExpr, EP_Subrtn)
+ || findCompatibleInRhsSubrtn(pParse, pExpr, pSig)
+ ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
@@ -108880,6 +113090,10 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
+ if( pSig ){
+ sqlite3DbFree(pParse->db, pSig->zAff);
+ sqlite3DbFree(pParse->db, pSig);
+ }
return;
}
@@ -108890,7 +113104,14 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
-
+ if( pSig ){
+ pSig->bComplete = 0;
+ pSig->iAddr = pExpr->y.sub.iAddr;
+ pSig->regReturn = pExpr->y.sub.regReturn;
+ pSig->iTable = iTab;
+ pParse->mSubrtnSig = 1 << (pSig->selId&7);
+ sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG);
+ }
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -108931,15 +113152,30 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
SelectDest dest;
int i;
int rc;
+ int addrBloom = 0;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
+ if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+ int regBloom = ++pParse->nMem;
+ addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
+ VdbeComment((v, "Bloom filter"));
+ dest.iSDParm2 = regBloom;
+ }
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
sqlite3DbFree(pParse->db, dest.zAffSdst);
+ if( addrBloom ){
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+ if( dest.iSDParm2==0 ){
+ sqlite3VdbeChangeToNoop(v, addrBloom);
+ }else{
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+ }
+ }
if( rc ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
@@ -108990,7 +113226,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
** this code only executes once. Because for a non-constant
** expression we need to rerun this code each time.
*/
- if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
+ if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){
sqlite3VdbeChangeToNoop(v, addrOnce-1);
sqlite3VdbeChangeToNoop(v, addrOnce);
ExprClearProperty(pExpr, EP_Subrtn);
@@ -109005,6 +113241,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
+ if( pSig ) pSig->bComplete = 1;
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
@@ -109237,9 +113474,7 @@ static void sqlite3ExprCodeIN(
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr);
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(
- pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
- );
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int));
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
@@ -109382,6 +113617,15 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
if( destIfFalse==destIfNull ){
/* Combine Step 3 and Step 5 into a single opcode */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
+ assert( pOp->opcode==OP_Once || pParse->nErr );
+ if( pOp->opcode==OP_Once && pOp->p3>0 ){
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
+ sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
+ rLhs, nVector); VdbeCoverage(v);
+ }
+ }
sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
goto sqlite3ExprCodeIN_finished;
@@ -109640,10 +113884,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;
}
@@ -109661,18 +113908,22 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
** register iReg. The caller must ensure that iReg already contains
** the correct value for the expression.
*/
-static void exprToRegister(Expr *pExpr, int iReg){
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
if( NEVER(p==0) ) return;
- p->op2 = p->op;
- p->op = TK_REGISTER;
- p->iTable = iReg;
- ExprClearProperty(p, EP_Skip);
+ if( p->op==TK_REGISTER ){
+ assert( p->iTable==iReg );
+ }else{
+ p->op2 = p->op;
+ p->op = TK_REGISTER;
+ p->iTable = iReg;
+ ExprClearProperty(p, EP_Skip);
+ }
}
/*
** 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
@@ -109712,7 +113963,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 */
}
}
@@ -109802,13 +114053,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);
@@ -109837,6 +114088,59 @@ static int exprCodeInlineFunction(
return target;
}
+/*
+** Expression Node callback for sqlite3ExprCanReturnSubtype().
+**
+** Only a function call is able to return a subtype. So if the node
+** is not a function call, return WRC_Prune immediately.
+**
+** A function call is able to return a subtype if it has the
+** SQLITE_RESULT_SUBTYPE property.
+**
+** Assume that every function is able to pass-through a subtype from
+** one of its argument (using sqlite3_result_value()). Most functions
+** are not this way, but we don't have a mechanism to distinguish those
+** that are from those that are not, so assume they all work this way.
+** That means that if one of its arguments is another function and that
+** other function is able to return a subtype, then this function is
+** able to return a subtype.
+*/
+static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
+ int n;
+ FuncDef *pDef;
+ sqlite3 *db;
+ if( pExpr->op!=TK_FUNCTION ){
+ return WRC_Prune;
+ }
+ assert( ExprUseXList(pExpr) );
+ db = pWalker->pParse->db;
+ n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+ if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+ pWalker->eCode = 1;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return TRUE if expression pExpr is able to return a subtype.
+**
+** A TRUE return does not guarantee that a subtype will be returned.
+** It only indicates that a subtype return is possible. False positives
+** are acceptable as they only disable an optimization. False negatives,
+** on the other hand, can lead to incorrect answers.
+*/
+static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = exprNodeCanReturnSubtype;
+ sqlite3WalkExpr(&w, pExpr);
+ return w.eCode;
+}
+
+
/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
@@ -109869,6 +114173,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
continue;
}
+
+ /* Functions that might set a subtype should not be replaced by the
+ ** value taken from an expression index if they are themselves an
+ ** argument to another scalar function or aggregate.
+ ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
+ if( ExprHasProperty(pExpr, EP_SubtArg)
+ && sqlite3ExprCanReturnSubtype(pParse, pExpr)
+ ){
+ continue;
+ }
+
v = pParse->pVdbe;
assert( v!=0 );
if( p->bMaybeNullRow ){
@@ -109896,6 +114211,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".
@@ -109932,12 +114282,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);
@@ -109972,7 +114335,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.
*/
@@ -110041,6 +114404,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,
@@ -110098,12 +114466,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
assert( pExpr->u.zToken!=0 );
assert( pExpr->u.zToken[0]!=0 );
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
- if( pExpr->u.zToken[1]!=0 ){
- const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
- assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) );
- pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
- sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
- }
return target;
}
case TK_REGISTER: {
@@ -110112,11 +114474,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));
@@ -110280,7 +114639,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
#endif
- if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
+ if( ConstFactorOk(pParse)
+ && sqlite3ExprIsConstantNotJoin(pParse,pExpr)
+ ){
/* SQL functions can be expensive. So try to avoid running them
** multiple times if we know they always give the same result */
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
@@ -110301,7 +114662,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,
@@ -110311,7 +114672,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
for(i=0; ia[i].pExpr) ){
+ if( i<32 && sqlite3ExprIsConstant(pParse, pFarg->a[i].pExpr) ){
testcase( i==31 );
constMask |= MASKBIT32(i);
}
@@ -110327,10 +114688,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;
@@ -110340,14 +114701,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;
}
@@ -110451,17 +114814,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
if( !ExprHasProperty(pExpr, EP_Collate) ){
/* A TK_COLLATE Expr node without the EP_Collate tag is a so-called
** "SOFT-COLLATE" that is added to constraints that are pushed down
- ** from outer queries into sub-queries by the push-down optimization.
- ** Clear subtypes as subtypes may not cross a subquery boundary.
+ ** from outer queries into sub-queries by the WHERE-clause push-down
+ ** optimization. Clear subtypes as subtypes may not cross a subquery
+ ** boundary.
*/
assert( pExpr->pLeft );
- 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. */
@@ -110571,12 +114931,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;
}
@@ -110628,7 +114985,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
testcase( pX->op==TK_COLUMN );
- exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
testcase( regFree1==0 );
memset(&opCompare, 0, sizeof(opCompare));
opCompare.op = TK_EQ;
@@ -110682,15 +115039,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->affExpr==OE_Ignore ){
- sqlite3VdbeAddOp4(
- v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
VdbeCoverage(v);
}else{
- sqlite3HaltConstraint(pParse,
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ sqlite3VdbeAddOp3(v, OP_Halt,
pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
- pExpr->affExpr, pExpr->u.zToken, 0, 0);
+ pExpr->affExpr, r1);
}
-
break;
}
#endif
@@ -110709,9 +115065,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
@@ -110724,6 +115080,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(
){
ExprList *p;
assert( ConstFactorOk(pParse) );
+ assert( regDest!=0 );
p = pParse->pConstExpr;
if( regDest<0 && p ){
struct ExprList_item *pItem;
@@ -110782,7 +115139,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
if( ConstFactorOk(pParse)
&& ALWAYS(pExpr!=0)
&& pExpr->op!=TK_REGISTER
- && sqlite3ExprIsConstantNotJoin(pExpr)
+ && sqlite3ExprIsConstantNotJoin(pParse, pExpr)
){
*pReg = 0;
r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
@@ -110814,7 +115171,11 @@ 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) ){
+ Expr *pX = sqlite3ExprSkipCollateAndLikely(pExpr);
+ testcase( pX!=pExpr );
+ if( ALWAYS(pX)
+ && (ExprHasProperty(pX,EP_Subquery) || pX->op==TK_REGISTER)
+ ){
op = OP_Copy;
}else{
op = OP_SCopy;
@@ -110842,7 +115203,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
** might choose to code the expression at initialization time.
*/
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
- if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
+ if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
}else{
sqlite3ExprCodeCopy(pParse, pExpr, target);
@@ -110901,7 +115262,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
}
}else if( (flags & SQLITE_ECEL_FACTOR)!=0
- && sqlite3ExprIsConstantNotJoin(pExpr)
+ && sqlite3ExprIsConstantNotJoin(pParse,pExpr)
){
sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
}else{
@@ -110974,7 +115335,7 @@ static void exprCodeBetween(
compRight.op = TK_LE;
compRight.pLeft = pDel;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
- exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
@@ -111353,16 +115714,23 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
+**
+** If the SQLITE_EnableQPSG flag is set on the database connection, then
+** this routine always returns false.
*/
-static int exprCompareVariable(
+static SQLITE_NOINLINE int exprCompareVariable(
const Parse *pParse,
const Expr *pVar,
const Expr *pExpr
){
- int res = 0;
+ int res = 2;
int iVar;
sqlite3_value *pL, *pR = 0;
+ if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){
+ return 0;
+ }
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2;
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
if( pR ){
iVar = pVar->iColumn;
@@ -111372,12 +115740,11 @@ static int exprCompareVariable(
if( sqlite3_value_type(pL)==SQLITE_TEXT ){
sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
}
- res = 0==sqlite3MemCompare(pL, pR, 0);
+ res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0;
}
sqlite3ValueFree(pR);
sqlite3ValueFree(pL);
}
-
return res;
}
@@ -111403,12 +115770,10 @@ static int exprCompareVariable(
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
**
-** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
-** pParse->pReprepare can be matched against literals in pB. The
-** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
-** If pParse is NULL (the normal case) then any TK_VARIABLE term in
-** Argument pParse should normally be NULL. If it is not NULL and pA or
-** pB causes a return value of 2.
+** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE
+** terms in pA with bindings in pParse->pReprepare can be matched against
+** literals in pB. The pParse->pVdbe->expmask bitmask is updated for
+** each variable referenced.
*/
SQLITE_PRIVATE int sqlite3ExprCompare(
const Parse *pParse,
@@ -111420,8 +115785,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
- if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
- return 0;
+ if( pParse && pA->op==TK_VARIABLE ){
+ return exprCompareVariable(pParse, pA, pB);
}
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
@@ -111533,8 +115898,8 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB
*/
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){
return sqlite3ExprCompare(0,
- sqlite3ExprSkipCollateAndLikely(pA),
- sqlite3ExprSkipCollateAndLikely(pB),
+ sqlite3ExprSkipCollate(pA),
+ sqlite3ExprSkipCollate(pB),
iTab);
}
@@ -111616,18 +115981,70 @@ static int exprImpliesNotNull(
return 0;
}
+/*
+** Return true if the boolean value of the expression is always either
+** FALSE or NULL.
+*/
+static int sqlite3ExprIsNotTrue(Expr *pExpr){
+ int v;
+ if( pExpr->op==TK_NULL ) return 1;
+ if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1;
+ v = 1;
+ if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1;
+ return 0;
+}
+
+/*
+** Return true if the expression is one of the following:
+**
+** CASE WHEN x THEN y END
+** CASE WHEN x THEN y ELSE NULL END
+** CASE WHEN x THEN y ELSE false END
+** iif(x,y)
+** iif(x,y,NULL)
+** iif(x,y,false)
+*/
+static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){
+ ExprList *pList;
+ if( pExpr->op==TK_FUNCTION ){
+ const char *z = pExpr->u.zToken;
+ FuncDef *pDef;
+ if( (z[0]!='i' && z[0]!='I') ) return 0;
+ if( pExpr->x.pList==0 ) return 0;
+ pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0);
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ if( pDef==0 ) return 0;
+#else
+ if( NEVER(pDef==0) ) return 0;
+#endif
+ if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0;
+ if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0;
+ }else if( pExpr->op==TK_CASE ){
+ if( pExpr->pLeft!=0 ) return 0;
+ }else{
+ return 0;
+ }
+ pList = pExpr->x.pList;
+ assert( pList!=0 );
+ if( pList->nExpr==2 ) return 1;
+ if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1;
+ return 0;
+}
+
/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
** be false. Examples:
**
-** pE1: x==5 pE2: x==5 Result: true
-** pE1: x>0 pE2: x==5 Result: false
-** pE1: x=21 pE2: x=21 OR y=43 Result: true
-** pE1: x!=123 pE2: x IS NOT NULL Result: true
-** pE1: x!=?1 pE2: x IS NOT NULL Result: true
-** pE1: x IS NULL pE2: x IS NOT NULL Result: false
-** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
+** pE1: iif(x,y) pE2: x Result: true
+** PE1: iif(x,y,0) pE2: x Result: true
**
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
@@ -111661,14 +116078,35 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(
){
return 1;
}
+ if( sqlite3ExprIsIIF(pParse->db, pE1) ){
+ return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab);
+ }
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.
@@ -111677,28 +116115,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;
@@ -111706,21 +116149,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
@@ -111782,7 +116242,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;
@@ -111790,7 +116250,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;
}
}
@@ -111798,6 +116258,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;
@@ -111858,7 +116319,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 {
@@ -111965,6 +116426,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);
@@ -111999,23 +116466,24 @@ 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 ){
+ if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
- sqlite3ExprDeferredDelete(pParse, 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 ){
+ if( pExpr && !sqlite3ExprDeferredDelete(pParse, pExpr) ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
- sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
@@ -112071,7 +116539,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 */
@@ -112084,6 +116552,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
@@ -112161,7 +116630,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
@@ -112172,6 +116646,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;
@@ -112195,18 +116672,19 @@ 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
&& pWalker->walkerDepth==pExpr->op2
+ && pExpr->pAggInfo==0
){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; inFunc; i++, pItem++){
- if( pItem->pFExpr==pExpr ) break;
+ if( NEVER(pItem->pFExpr==pExpr) ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
@@ -112217,14 +116695,44 @@ 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;
+ }
+ pItem->bUseSubtype =
+ (pItem->pFunc->funcFlags & SQLITE_SUBTYPE)!=0;
+ }else{
+ pItem->iOBTab = -1;
+ }
+ if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){
pItem->iDistinct = pParse->nTab++;
}else{
pItem->iDistinct = -1;
@@ -112348,6 +116856,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()
@@ -112367,6 +116906,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 */
@@ -112821,14 +117368,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
);
}
@@ -112917,7 +117469,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);
@@ -113422,7 +117974,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
@@ -113654,6 +118206,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
@@ -113677,7 +118242,7 @@ static int renameResolveTrigger(Parse *pParse){
/* ALWAYS() because if the table of the trigger does not exist, the
** error would have been hit before this point */
if( ALWAYS(pParse->pTriggerTab) ){
- rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
+ rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab)!=0;
}
/* Resolve symbols in WHEN clause */
@@ -113701,7 +118266,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 );
@@ -113713,8 +118288,9 @@ static int renameResolveTrigger(Parse *pParse){
int i;
for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pStep->pFrom->a[i];
- if( p->pSelect ){
- sqlite3SelectPrep(pParse, p->pSelect, 0);
+ if( p->fg.isSubquery ){
+ assert( p->u4.pSubq!=0 );
+ sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0);
}
}
}
@@ -113782,8 +118358,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
}
if( pStep->pFrom ){
int i;
- for(i=0; ipFrom->nSrc; i++){
- sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+ SrcList *pFrom = pStep->pFrom;
+ for(i=0; inSrc; i++){
+ if( pFrom->a[i].fg.isSubquery ){
+ assert( pFrom->a[i].u4.pSubq!=0 );
+ sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect);
+ }
}
}
}
@@ -114030,7 +118610,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
}
for(i=0; inSrc; i++){
SrcItem *pItem = &pSrc->a[i];
- if( pItem->pTab==p->pTab ){
+ if( pItem->pSTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
@@ -114609,7 +119189,12 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T
if( i==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
}else{
+ char aff = pTab->aCol[i].affinity;
+ if( aff==SQLITE_AFF_REAL ){
+ pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
+ }
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
+ pTab->aCol[i].affinity = aff;
}
nField++;
}
@@ -114920,9 +119505,9 @@ static void openStatTable(
typedef struct StatAccum StatAccum;
typedef struct StatSample StatSample;
struct StatSample {
- tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
#ifdef SQLITE_ENABLE_STAT4
+ tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anLt; /* sqlite_stat4.nLt */
union {
i64 iRowid; /* Rowid in main table of the key */
@@ -115080,9 +119665,9 @@ static void statInit(
/* Allocate the space required for the StatAccum object */
n = sizeof(*p)
- + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
- + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
+ + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
#ifdef SQLITE_ENABLE_STAT4
+ n += sizeof(tRowcnt)*nColUp; /* StatAccum.anEq */
if( mxSample ){
n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
+ sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
@@ -115103,9 +119688,9 @@ static void statInit(
p->nKeyCol = nKeyCol;
p->nSkipAhead = 0;
p->current.anDLt = (tRowcnt*)&p[1];
- p->current.anEq = &p->current.anDLt[nColUp];
#ifdef SQLITE_ENABLE_STAT4
+ p->current.anEq = &p->current.anDLt[nColUp];
p->mxSample = p->nLimit==0 ? mxSample : 0;
if( mxSample ){
u8 *pSpace; /* Allocated space not yet assigned */
@@ -115372,7 +119957,9 @@ static void statPush(
if( p->nRow==0 ){
/* This is the first call to this function. Do initialization. */
+#ifdef SQLITE_ENABLE_STAT4
for(i=0; inCol; i++) p->current.anEq[i] = 1;
+#endif
}else{
/* Second and subsequent calls get processed here */
#ifdef SQLITE_ENABLE_STAT4
@@ -115381,15 +119968,17 @@ static void statPush(
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
** to the current row of the index. */
+#ifdef SQLITE_ENABLE_STAT4
for(i=0; icurrent.anEq[i]++;
}
+#endif
for(i=iChng; inCol; i++){
p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT4
if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
-#endif
p->current.anEq[i] = 1;
+#endif
}
}
@@ -115523,7 +120112,9 @@ static void statGet(
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
sqlite3_str_appendf(&sStat, " %llu", iVal);
- assert( p->current.anEq[i] );
+#ifdef SQLITE_ENABLE_STAT4
+ assert( p->current.anEq[i] || p->nRow==0 );
+#endif
}
sqlite3ResultStrAccum(context, &sStat);
}
@@ -115650,11 +120241,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;
@@ -115703,7 +120298,7 @@ static void analyzeOneTable(
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int nCol; /* Number of columns in pIdx. "N" */
- int addrRewind; /* Address of "OP_Rewind iIdxCur" */
+ int addrGotoEnd; /* Address of "OP_Rewind iIdxCur" */
int addrNextRow; /* Address of "next_row:" */
const char *zIdxName; /* Name of the index */
int nColTest; /* Number of columns to test for changes */
@@ -115727,9 +120322,14 @@ static void analyzeOneTable(
/*
** Pseudo-code for loop that calls stat_push():
**
- ** Rewind csr
- ** if eof(csr) goto end_of_scan;
** regChng = 0
+ ** Rewind csr
+ ** if eof(csr){
+ ** stat_init() with count = 0;
+ ** goto end_of_scan;
+ ** }
+ ** count()
+ ** stat_init()
** goto chng_addr_0;
**
** next_row:
@@ -115760,7 +120360,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) );
@@ -115768,41 +120368,36 @@ static void analyzeOneTable(
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "%s", pIdx->zName));
- /* Invoke the stat_init() function. The arguments are:
+ /* Implementation of the following:
**
+ ** regChng = 0
+ ** Rewind csr
+ ** if eof(csr){
+ ** stat_init() with count = 0;
+ ** goto end_of_scan;
+ ** }
+ ** count()
+ ** stat_init()
+ ** goto chng_addr_0;
+ */
+ assert( regTemp2==regStat+4 );
+ sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
+
+ /* Arguments to stat_init():
** (1) the number of columns in the index including the rowid
** (or for a WITHOUT ROWID table, the number of PK columns),
** (2) the number of columns in the key without the rowid/pk
- ** (3) estimated number of rows in the index,
- */
+ ** (3) estimated number of rows in the index. */
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
assert( regRowid==regStat+2 );
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
-#ifdef SQLITE_ENABLE_STAT4
- if( OptimizationEnabled(db, SQLITE_Stat4) ){
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
- addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
- VdbeCoverage(v);
- }else
-#endif
- {
- addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
- }
- assert( regTemp2==regStat+4 );
- sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
+ sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp,
+ OptimizationDisabled(db, SQLITE_Stat4));
sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
&statInitFuncdef, 0);
+ addrGotoEnd = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
+ VdbeCoverage(v);
- /* Implementation of the following:
- **
- ** Rewind csr
- ** if eof(csr) goto end_of_scan;
- ** regChng = 0
- ** goto next_push_0;
- **
- */
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
addrNextRow = sqlite3VdbeCurrentAddr(v);
@@ -115909,6 +120504,12 @@ static void analyzeOneTable(
}
/* Add the entry to the stat1 table. */
+ if( pIdx->pPartIdxWhere ){
+ /* Partial indexes might get a zero-entry in sqlite_stat1. But
+ ** an empty table is omitted from sqlite_stat1. */
+ sqlite3VdbeJumpHere(v, addrGotoEnd);
+ addrGotoEnd = 0;
+ }
callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
assert( "BBB"[0]==SQLITE_AFF_TEXT );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
@@ -115932,7 +120533,42 @@ static void analyzeOneTable(
int addrIsNull;
u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
- pParse->nMem = MAX(pParse->nMem, regCol+nCol);
+ /* No STAT4 data is generated if the number of rows is zero */
+ if( addrGotoEnd==0 ){
+ sqlite3VdbeAddOp2(v, OP_Cast, regStat1, SQLITE_AFF_INTEGER);
+ addrGotoEnd = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
+ VdbeCoverage(v);
+ }
+
+ if( doOnce ){
+ int mxCol = nCol;
+ Index *pX;
+
+ /* Compute the maximum number of columns in any index */
+ for(pX=pTab->pIndex; pX; pX=pX->pNext){
+ int nColX; /* Number of columns in pX */
+ if( !HasRowid(pTab) && IsPrimaryKeyIndex(pX) ){
+ nColX = pX->nKeyCol;
+ }else{
+ nColX = pX->nColumn;
+ }
+ if( nColX>mxCol ) mxCol = nColX;
+ }
+
+ /* Allocate space to compute results for the largest index */
+ sqlite3TouchRegister(pParse, regCol+mxCol);
+ doOnce = 0;
+#ifdef SQLITE_DEBUG
+ /* Verify that the call to sqlite3ClearTempRegCache() below
+ ** really is needed.
+ ** https://sqlite.org/forum/forumpost/83cb4a95a0 (2023-03-25)
+ */
+ testcase( !sqlite3NoTempsInRange(pParse, regEq, regCol+mxCol) );
+#endif
+ sqlite3ClearTempRegCache(pParse); /* tag-20230325-1 */
+ assert( sqlite3NoTempsInRange(pParse, regEq, regCol+mxCol) );
+ }
+ assert( sqlite3NoTempsInRange(pParse, regEq, regCol+nCol) );
addrNext = sqlite3VdbeCurrentAddr(v);
callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
@@ -115956,7 +120592,7 @@ static void analyzeOneTable(
#endif /* SQLITE_ENABLE_STAT4 */
/* End of analysis */
- sqlite3VdbeJumpHere(v, addrRewind);
+ if( addrGotoEnd ) sqlite3VdbeJumpHere(v, addrGotoEnd);
}
@@ -116013,6 +120649,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);
}
@@ -116175,6 +120816,16 @@ static void decodeIntArray(
while( z[0]!=0 && z[0]!=' ' ) z++;
while( z[0]==' ' ) z++;
}
+
+ /* Set the bLowQual flag if the peak number of rows obtained
+ ** from a full equality match is so large that a full table scan
+ ** seems likely to be faster than using the index.
+ */
+ if( aLog[0] > 66 /* Index has more than 100 rows */
+ && aLog[0] <= aLog[nOut-1] /* And only a single value seen */
+ ){
+ pIndex->bLowQual = 1;
+ }
}
}
@@ -116387,12 +121038,13 @@ static int loadStatTbl(
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int nIdxCol = 1; /* Number of columns in stat4 records */
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
- int nSample; /* Number of samples */
- int nByte; /* Bytes of space required */
- int i; /* Bytes of space required */
- tRowcnt *pSpace;
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int nSample; /* Number of samples */
+ i64 nByte; /* Bytes of space required */
+ i64 i; /* Bytes of space required */
+ tRowcnt *pSpace; /* Available allocated memory space */
+ u8 *pPtr; /* Available memory as a u8 for easier manipulation */
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
@@ -116400,6 +121052,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;
@@ -116407,7 +121063,8 @@ static int loadStatTbl(
nIdxCol = pIdx->nColumn;
}
pIdx->nSampleCol = nIdxCol;
- nByte = sizeof(IndexSample) * nSample;
+ pIdx->mxSample = nSample;
+ nByte = ROUND8(sizeof(IndexSample) * nSample);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
@@ -116416,7 +121073,10 @@ static int loadStatTbl(
sqlite3_finalize(pStmt);
return SQLITE_NOMEM_BKPT;
}
- pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+ pPtr = (u8*)pIdx->aSample;
+ pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
+ pSpace = (tRowcnt*)pPtr;
+ assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; inSample>=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;
@@ -116458,14 +121123,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;
@@ -116489,11 +121155,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
);
@@ -116773,6 +121440,12 @@ static void attachFunc(
sqlite3_free(zErr);
return;
}
+ if( (db->flags & SQLITE_AttachWrite)==0 ){
+ flags &= ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE);
+ flags |= SQLITE_OPEN_READONLY;
+ }else if( (db->flags & SQLITE_AttachCreate)==0 ){
+ flags &= ~SQLITE_OPEN_CREATE;
+ }
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
@@ -116825,15 +121498,6 @@ static void attachFunc(
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
-#ifdef SQLITE_USER_AUTHENTICATION
- if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){
- u8 newAuth = 0;
- rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
- if( newAuthauth.authLevel ){
- rc = SQLITE_AUTH_USER;
- }
- }
-#endif
if( rc ){
if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){
int iDb = db->nDb - 1;
@@ -117077,20 +121741,21 @@ static int fixSelectCb(Walker *p, Select *pSelect){
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
- if( pFix->bTemp==0 ){
- if( pItem->zDatabase ){
- if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+ if( pFix->bTemp==0 && pItem->fg.isSubquery==0 ){
+ if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+ if( iDb!=sqlite3FindDbName(db, pItem->u4.zDatabase) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
+ pFix->zType, pFix->pName, pItem->u4.zDatabase);
return WRC_Abort;
}
- sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
+ sqlite3DbFree(db, pItem->u4.zDatabase);
pItem->fg.notCte = 1;
+ pItem->fg.hadSchema = 1;
}
- pItem->pSchema = pFix->pSchema;
+ pItem->u4.pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
+ pItem->fg.fixedSchema = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( pList->a[i].fg.isUsing==0
@@ -117330,11 +121995,7 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(
int rc; /* Auth callback return code */
if( db->init.busy ) return SQLITE_OK;
- rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
+ rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
if( rc==SQLITE_DENY ){
char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
@@ -117383,7 +122044,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
assert( pTabList );
for(iSrc=0; iSrcnSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
- pTab = pTabList->a[iSrc].pTab;
+ pTab = pTabList->a[iSrc].pSTab;
break;
}
}
@@ -117422,7 +122083,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 );
@@ -117441,11 +122102,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
testcase( zArg3==0 );
testcase( pParse->zAuthContext==0 );
- rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
+ rc = db->xAuth(db->pAuthArg,code,zArg1,zArg2,zArg3,pParse->zAuthContext);
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
@@ -117678,17 +122335,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
sqlite3VdbeAddOp0(v, OP_Halt);
-#if SQLITE_USER_AUTHENTICATION
- if( pParse->nTableLock>0 && db->init.busy==0 ){
- sqlite3UserAuthInit(db);
- if( db->auth.authLevelrc = SQLITE_AUTH_USER;
- return;
- }
- }
-#endif
-
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
@@ -117723,29 +122369,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);
}
}
@@ -117820,16 +122463,6 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
pParse->nested--;
}
-#if SQLITE_USER_AUTHENTICATION
-/*
-** Return TRUE if zTable is the name of the system table that stores the
-** list of users and their access credentials.
-*/
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){
- return sqlite3_stricmp(zTable, "sqlite_user")==0;
-}
-#endif
-
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@@ -117848,13 +122481,6 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
-#if SQLITE_USER_AUTHENTICATION
- /* Only the admin user is allowed to know that the sqlite_user table
- ** exists */
- if( db->auth.authLevelnDb; i++){
if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
@@ -117989,12 +122615,12 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
SrcItem *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
- if( p->pSchema ){
- int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ if( p->fg.fixedSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
- zDb = p->zDatabase;
+ assert( !p->fg.isSubquery );
+ zDb = p->u4.zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
@@ -118212,7 +122838,7 @@ SQLITE_PRIVATE void sqlite3ColumnSetExpr(
*/
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0;
- if( NEVER(!IsOrdinaryTable(pTab)) ) return 0;
+ if( !IsOrdinaryTable(pTab) ) return 0;
if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
if( NEVER(pTab->u.tab.pDfltList->nExpriDflt) ) return 0;
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
@@ -118244,7 +122870,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;
@@ -118337,7 +122963,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);
}
@@ -118365,6 +122991,9 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
deleteTable(db, pTable);
}
+SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){
+ sqlite3DeleteTable(db, (Table*)pTable);
+}
/*
@@ -118899,20 +123528,14 @@ 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){
+static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){
+ Returning *pRet = (Returning*)pArg;
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);
}
@@ -118951,11 +123574,12 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){
pParse->u1.pReturning = pRet;
pRet->pParse = pParse;
pRet->pReturnEL = pList;
- sqlite3ParserAddCleanup(pParse,
- (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
+ sqlite3ParserAddCleanup(pParse, 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;
@@ -118966,9 +123590,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
+ assert( sqlite3HashFind(pHash, pRet->zName)==0
|| pParse->nErr || pParse->ifNotExists );
- if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+ if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig)
==&pRet->retTrig ){
sqlite3OomFault(db);
}
@@ -119002,7 +123626,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. */
@@ -119149,7 +123773,8 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){
assert( zIn!=0 );
while( zIn[0] ){
- h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
+ u8 x = *(u8*)zIn;
+ h = (h<<8) + sqlite3UpperToLower[x];
zIn++;
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
aff = SQLITE_AFF_TEXT;
@@ -119223,7 +123848,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;
@@ -119571,7 +124196,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.
@@ -119723,7 +124348,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);
}
@@ -120321,20 +124946,20 @@ SQLITE_PRIVATE void sqlite3EndTable(
int regRowid; /* Rowid of the next row to insert */
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
+ int iCsr; /* Write cursor on the new table */
if( IN_SPECIAL_PARSE ){
pParse->rc = SQLITE_ERROR;
pParse->nErr++;
return;
}
+ iCsr = pParse->nTab++;
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
- assert(pParse->nTab==1);
sqlite3MayAbort(pParse);
- sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
- pParse->nTab = 2;
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
if( pParse->nErr ) return;
@@ -120355,11 +124980,11 @@ SQLITE_PRIVATE void sqlite3EndTable(
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
sqlite3TableAffinity(v, p, 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid);
sqlite3VdbeGoto(v, addrInsLoop);
sqlite3VdbeJumpHere(v, addrInsLoop);
- sqlite3VdbeAddOp1(v, OP_Close, 1);
+ sqlite3VdbeAddOp1(v, OP_Close, iCsr);
}
/* Compute the complete text of the CREATE statement */
@@ -120412,6 +125037,14 @@ 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, 0x0001, 0, 0,
+ sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
+ db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
+ }
}
/* Add the table to the in-memory representation of the database.
@@ -120488,9 +125121,12 @@ SQLITE_PRIVATE void sqlite3CreateView(
** on a view, even though views do not have rowids. The following flag
** setting fixes this problem. But the fix can be disabled by compiling
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
- ** depend upon the old buggy behavior. */
-#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
- p->tabFlags |= TF_NoVisibleRowid;
+ ** depend upon the old buggy behavior. The ability can also be toggled
+ ** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */
+#else
+ p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */
#endif
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
@@ -120546,8 +125182,9 @@ SQLITE_PRIVATE void sqlite3CreateView(
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** The Table structure pTable is really a VIEW. Fill in the names of
-** the columns of the view in the pTable structure. Return the number
-** of errors. If an error is seen leave an error message in pParse->zErrMsg.
+** the columns of the view in the pTable structure. Return non-zero if
+** there are errors. If an error is seen an error message is left
+** in pParse->zErrMsg.
*/
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
Table *pSelTab; /* A fake table from which we get the result set */
@@ -120670,7 +125307,7 @@ static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3DeleteColumnNames(db, pTable);
}
#endif /* SQLITE_OMIT_VIEW */
- return nErr;
+ return nErr + pParse->nErr;
}
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable!=0 );
@@ -120968,6 +125605,8 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
+ assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
@@ -120976,7 +125615,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
if( pTab==0 ){
if( noErr ){
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
goto exit_drop_table;
@@ -121461,7 +126100,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);
@@ -121500,9 +126139,6 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
-#if SQLITE_USER_AUTHENTICATION
- && sqlite3UserAuthTable(pTab->zName)==0
-#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
@@ -122067,15 +126703,17 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
}
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
+ assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
}
- pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
+ pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].u4.zDatabase);
if( pIndex==0 ){
if( !ifExists ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
@@ -122199,7 +126837,6 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
assert( db!=0 );
if( pList==0 ) return;
- assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
for(i=0; inId; i++){
sqlite3DbFree(db, pList->a[i].zName);
}
@@ -122372,12 +127009,14 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
if( pDatabase && pDatabase->z==0 ){
pDatabase = 0;
}
+ assert( pItem->fg.fixedSchema==0 );
+ assert( pItem->fg.isSubquery==0 );
if( pDatabase ){
pItem->zName = sqlite3NameFromToken(db, pDatabase);
- pItem->zDatabase = sqlite3NameFromToken(db, pTable);
+ pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable);
}else{
pItem->zName = sqlite3NameFromToken(db, pTable);
- pItem->zDatabase = 0;
+ pItem->u4.zDatabase = 0;
}
return pList;
}
@@ -122393,13 +127032,40 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
- if( pItem->pSelect ){
- sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+ if( pItem->fg.isSubquery ){
+ assert( pItem->u4.pSubq!=0 );
+ assert( pItem->u4.pSubq->pSelect!=0 );
+ assert( pItem->u4.pSubq->pSelect->pSrc!=0 );
+ sqlite3SrcListAssignCursors(pParse, pItem->u4.pSubq->pSelect->pSrc);
}
}
}
}
+/*
+** Delete a Subquery object and its substructure.
+*/
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3 *db, Subquery *pSubq){
+ assert( pSubq!=0 && pSubq->pSelect!=0 );
+ sqlite3SelectDelete(db, pSubq->pSelect);
+ sqlite3DbFree(db, pSubq);
+}
+
+/*
+** Remove a Subquery from a SrcItem. Return the associated Select object.
+** The returned Select becomes the responsibility of the caller.
+*/
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3 *db, SrcItem *pItem){
+ Select *pSel;
+ assert( pItem!=0 );
+ assert( pItem->fg.isSubquery );
+ pSel = pItem->u4.pSubq->pSelect;
+ sqlite3DbFree(db, pItem->u4.pSubq);
+ pItem->u4.pSubq = 0;
+ pItem->fg.isSubquery = 0;
+ return pSel;
+}
+
/*
** Delete an entire SrcList including all its substructure.
*/
@@ -122409,13 +127075,24 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
assert( db!=0 );
if( pList==0 ) return;
for(pItem=pList->a, i=0; inSrc; i++, pItem++){
- if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase);
+
+ /* Check invariants on SrcItem */
+ assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc );
+ assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy );
+ assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery );
+ assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 &&
+ pItem->u4.pSubq->pSelect!=0) );
+
if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
+ if( pItem->fg.isSubquery ){
+ sqlite3SubqueryDelete(db, pItem->u4.pSubq);
+ }else if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+ sqlite3DbNNFreeNN(db, pItem->u4.zDatabase);
+ }
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
- sqlite3DeleteTable(db, pItem->pTab);
- if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ sqlite3DeleteTable(db, pItem->pSTab);
if( pItem->fg.isUsing ){
sqlite3IdListDelete(db, pItem->u3.pUsing);
}else if( pItem->u3.pOn ){
@@ -122425,6 +127102,54 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3DbNNFreeNN(db, pList);
}
+/*
+** Attach a Subquery object to pItem->uv.pSubq. Set the
+** pSelect value but leave all the other values initialized
+** to zero.
+**
+** A copy of the Select object is made if dupSelect is true, and the
+** SrcItem takes responsibility for deleting the copy. If dupSelect is
+** false, ownership of the Select passes to the SrcItem. Either way,
+** the SrcItem will take responsibility for deleting the Select.
+**
+** When dupSelect is zero, that means the Select might get deleted right
+** away if there is an OOM error. Beware.
+**
+** Return non-zero on success. Return zero on an OOM error.
+*/
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(
+ Parse *pParse, /* Parsing context */
+ SrcItem *pItem, /* Item to which the subquery is to be attached */
+ Select *pSelect, /* The subquery SELECT. Must be non-NULL */
+ int dupSelect /* If true, attach a copy of pSelect, not pSelect itself.*/
+){
+ Subquery *p;
+ assert( pSelect!=0 );
+ assert( pItem->fg.isSubquery==0 );
+ if( pItem->fg.fixedSchema ){
+ pItem->u4.pSchema = 0;
+ pItem->fg.fixedSchema = 0;
+ }else if( pItem->u4.zDatabase!=0 ){
+ sqlite3DbFree(pParse->db, pItem->u4.zDatabase);
+ pItem->u4.zDatabase = 0;
+ }
+ if( dupSelect ){
+ pSelect = sqlite3SelectDup(pParse->db, pSelect, 0);
+ if( pSelect==0 ) return 0;
+ }
+ p = pItem->u4.pSubq = sqlite3DbMallocRawNN(pParse->db, sizeof(Subquery));
+ if( p==0 ){
+ sqlite3SelectDelete(pParse->db, pSelect);
+ return 0;
+ }
+ pItem->fg.isSubquery = 1;
+ p->pSelect = pSelect;
+ assert( offsetof(Subquery, pSelect)==0 );
+ memset(((char*)p)+sizeof(p->pSelect), 0, sizeof(*p)-sizeof(p->pSelect));
+ return 1;
+}
+
+
/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause. The "p" parameter is the part of
@@ -122474,10 +127199,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
if( pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
+ assert( pSubquery==0 || pDatabase==0 );
if( pSubquery ){
- pItem->pSelect = pSubquery;
- if( pSubquery->selFlags & SF_NestedFrom ){
- pItem->fg.isNestedFrom = 1;
+ if( sqlite3SrcItemAttachSubquery(pParse, pItem, pSubquery, 0) ){
+ if( pSubquery->selFlags & SF_NestedFrom ){
+ pItem->fg.isNestedFrom = 1;
+ }
}
}
assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
@@ -123003,7 +127730,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
if( iDb<0 ) return;
z = sqlite3NameFromToken(db, pObjName);
if( z==0 ) return;
- zDb = db->aDb[iDb].zDbSName;
+ zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
pTab = sqlite3FindTable(db, z, zDb);
if( pTab ){
reindexTable(pParse, pTab, 0);
@@ -123013,6 +127740,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
pIndex = sqlite3FindIndex(db, z, zDb);
sqlite3DbFree(db, z);
if( pIndex ){
+ iDb = sqlite3SchemaToIndex(db, pIndex->pTable->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
return;
@@ -123118,7 +127846,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.
*/
@@ -123178,6 +127906,9 @@ SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){
sqlite3DbFree(db, pWith);
}
}
+SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){
+ sqlite3WithDelete(db, (With*)pWith);
+}
#endif /* !defined(SQLITE_OMIT_CTE) */
/************** End of build.c ***********************************************/
@@ -123369,6 +128100,7 @@ SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){
** strings is BINARY.
*/
db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0);
+ sqlite3ExpirePreparedStatements(db, 1);
}
/*
@@ -123485,12 +128217,18 @@ static int matchQuality(
u8 enc /* Desired text encoding */
){
int match;
- assert( p->nArg>=-1 );
+ assert( p->nArg>=(-4) && p->nArg!=(-2) );
+ assert( nArg>=(-2) );
/* Wrong number of arguments means "no match" */
if( p->nArg!=nArg ){
- if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
+ if( nArg==(-2) ) return p->xSFunc==0 ? 0 : FUNC_PERFECT_MATCH;
if( p->nArg>=0 ) return 0;
+ /* Special p->nArg values available to built-in functions only:
+ ** -3 1 or more arguments required
+ ** -4 2 or more arguments required
+ */
+ if( p->nArg<(-2) && nArg<(-2-p->nArg) ) return 0;
}
/* Give a better score to a function with a specific number of arguments
@@ -123750,8 +128488,8 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
**
** The following fields are initialized appropriate in pSrc:
**
-** pSrc->a[0].pTab Pointer to the Table object
-** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
+** pSrc->a[0].spTab Pointer to the Table object
+** pSrc->a[0].u2.pIBIndex Pointer to the INDEXED BY index, if there is one
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
@@ -123759,8 +128497,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);
- pItem->pTab = pTab;
+ if( pItem->pSTab ) sqlite3DeleteTable(pParse->db, pItem->pSTab);
+ pItem->pSTab = pTab;
+ pItem->fg.notCte = 1;
if( pTab ){
pTab->nTabRef++;
if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){
@@ -123800,6 +128539,7 @@ SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *
** is for a top-level SQL statement.
*/
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
+ assert( IsVirtual(pTab) );
if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
return 1;
}
@@ -123840,13 +128580,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;
}
@@ -123879,7 +128621,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
- pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 );
+ pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
assert( pFrom->a[0].fg.isUsing==0 );
assert( pFrom->a[0].u3.pOn==0 );
}
@@ -123911,7 +128654,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;
@@ -123941,7 +128684,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
** );
*/
- pTab = pSrc->a[0].pTab;
+ pTab = pSrc->a[0].pSTab;
if( HasRowid(pTab) ){
pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
pEList = sqlite3ExprListAppend(
@@ -123949,14 +128692,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);
@@ -123968,9 +128717,9 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
- pSrc->a[0].pTab = 0;
+ pSrc->a[0].pSTab = 0;
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
- pSrc->a[0].pTab = pTab;
+ pSrc->a[0].pSTab = pTab;
if( pSrc->a[0].fg.isIndexedBy ){
assert( pSrc->a[0].fg.isCte==0 );
pSrc->a[0].u2.pIBIndex = 0;
@@ -123985,7 +128734,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;
@@ -124100,7 +128849,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);
@@ -124214,7 +128963,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
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{
@@ -124242,7 +128991,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);
@@ -124579,9 +129329,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
@@ -124894,6 +129646,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.
**
@@ -125063,7 +129851,6 @@ static void substrFunc(
int len;
int p0type;
i64 p1, p2;
- int negP2 = 0;
assert( argc==3 || argc==2 );
if( sqlite3_value_type(argv[1])==SQLITE_NULL
@@ -125072,7 +129859,7 @@ static void substrFunc(
return;
}
p0type = sqlite3_value_type(argv[0]);
- p1 = sqlite3_value_int(argv[1]);
+ p1 = sqlite3_value_int64(argv[1]);
if( p0type==SQLITE_BLOB ){
len = sqlite3_value_bytes(argv[0]);
z = sqlite3_value_blob(argv[0]);
@@ -125097,19 +129884,18 @@ static void substrFunc(
if( p1==0 ) p1 = 1; /* */
#endif
if( argc==3 ){
- p2 = sqlite3_value_int(argv[2]);
- if( p2<0 ){
- p2 = -p2;
- negP2 = 1;
- }
+ p2 = sqlite3_value_int64(argv[2]);
}else{
p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
}
if( p1<0 ){
p1 += len;
if( p1<0 ){
- p2 += p1;
- if( p2<0 ) p2 = 0;
+ if( p2<0 ){
+ p2 = 0;
+ }else{
+ p2 += p1;
+ }
p1 = 0;
}
}else if( p1>0 ){
@@ -125117,12 +129903,13 @@ static void substrFunc(
}else if( p2>0 ){
p2--;
}
- if( negP2 ){
- p1 -= p2;
- if( p1<0 ){
- p2 += p1;
- p1 = 0;
+ if( p2<0 ){
+ if( p2<-p1 ){
+ p2 = p1;
+ }else{
+ p2 = -p2;
}
+ p1 -= p2;
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
@@ -125136,9 +129923,11 @@ static void substrFunc(
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
}else{
- if( p1+p2>len ){
+ if( p1>=len ){
+ p1 = p2 = 0;
+ }else if( p2>len-p1 ){
p2 = len-p1;
- if( p2<0 ) p2 = 0;
+ assert( p2>0 );
}
sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
}
@@ -125149,13 +129938,13 @@ static void substrFunc(
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- int n = 0;
+ i64 n = 0;
double r;
char *zBuf;
assert( argc==1 || argc==2 );
if( argc==2 ){
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
- n = sqlite3_value_int(argv[1]);
+ n = sqlite3_value_int64(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
@@ -125170,7 +129959,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",(int)n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
@@ -125370,7 +130159,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.
*/
@@ -125603,7 +130392,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
@@ -125810,13 +130599,13 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
double r1, r2;
const char *zVal;
r1 = sqlite3_value_double(pValue);
- sqlite3_str_appendf(pStr, "%!.15g", r1);
+ sqlite3_str_appendf(pStr, "%!0.15g", r1);
zVal = sqlite3_str_value(pStr);
if( zVal ){
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
if( r1!=r2 ){
sqlite3_str_reset(pStr);
- sqlite3_str_appendf(pStr, "%!.20e", r1);
+ sqlite3_str_appendf(pStr, "%!0.20e", r1);
}
}
break;
@@ -125936,6 +130725,7 @@ static void charFunc(
*zOut++ = 0x80 + (u8)(c & 0x3F);
} \
}
+ *zOut = 0;
sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
}
@@ -125964,7 +130754,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);
}
}
@@ -125989,7 +130780,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
@@ -126116,7 +130907,7 @@ static void replaceFunc(
}
if( zPattern[0]==0 ){
assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
- sqlite3_result_value(context, argv[0]);
+ sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT);
return;
}
nPattern = sqlite3_value_bytes(argv[1]);
@@ -126258,12 +131049,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
@@ -126379,13 +131245,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.
**
@@ -126405,15 +131326,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]));
+ }
}
}
}
@@ -126430,13 +131365,21 @@ 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 ){
+ if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
+ p->ovrfl = 1;
+ p->approx = 1;
+ }
+ }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]));
}
}
}
@@ -126447,10 +131390,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( !sqlite3IsOverflow(p->rErr) ){
+ sqlite3_result_double(context, p->rSum+p->rErr);
+ }else{
+ sqlite3_result_double(context, p->rSum);
+ }
}else{
sqlite3_result_int64(context, p->iSum);
}
@@ -126460,14 +131407,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( !sqlite3IsOverflow(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( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
+ }else{
+ r = (double)(p->iSum);
+ }
+ }
+ sqlite3_result_double(context, r);
}
/*
@@ -126586,8 +131548,13 @@ static void minMaxFinalize(sqlite3_context *context){
/*
** group_concat(EXPR, ?SEPARATOR?)
+** string_agg(EXPR, SEPARATOR)
+**
+** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
+** coming before the EXPR value, except for the first entry which
+** omits the SEPARATOR.
**
-** The SEPARATOR goes before the EXPR string. This is tragic. The
+** It is tragic that the SEPARATOR goes before the EXPR string. The
** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR. And the order is undocumented,
** so we could change it, in theory. But the old behavior has been
@@ -126689,9 +131656,9 @@ 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;
+ int nVS; /* Number of characters to remove */
/* Must call sqlite3_value_text() to convert the argument into text prior
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
(void)sqlite3_value_text(argv[0]);
@@ -126744,6 +131711,8 @@ static void groupConcatValue(sqlite3_context *context){
sqlite3_result_error_toobig(context);
}else if( pAccum->accError==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
+ }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
+ sqlite3_result_text(context, "", 1, SQLITE_STATIC);
}else{
const char *zText = sqlite3_str_value(pAccum);
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
@@ -126773,8 +131742,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;
@@ -126782,10 +131753,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;
+ }
}
/*
@@ -127057,6 +132031,120 @@ static void signFunc(
sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
}
+#ifdef SQLITE_DEBUG
+/*
+** Implementation of fpdecode(x,y,z) function.
+**
+** x is a real number that is to be decoded. y is the precision.
+** z is the maximum real precision. Return a string that shows the
+** results of the sqlite3FpDecode() function.
+**
+** Used for testing and debugging only, specifically testing and debugging
+** of the sqlite3FpDecode() function. This SQL function does not appear
+** in production builds. This function is not an API and is subject to
+** modification or removal in future versions of SQLite.
+*/
+static void fpdecodeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ FpDecode s;
+ double x;
+ int y, z;
+ char zBuf[100];
+ UNUSED_PARAMETER(argc);
+ assert( argc==3 );
+ x = sqlite3_value_double(argv[0]);
+ y = sqlite3_value_int(argv[1]);
+ z = sqlite3_value_int(argv[2]);
+ if( z<=0 ) z = 1;
+ sqlite3FpDecode(&s, x, y, z);
+ if( s.isSpecial==2 ){
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
+ }else{
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP);
+ }
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+}
+#endif /* SQLITE_DEBUG */
+
+#ifdef SQLITE_DEBUG
+/*
+** Implementation of parseuri(uri,flags) function.
+**
+** Required Arguments:
+** "uri" The URI to parse.
+** "flags" Bitmask of flags, as if to sqlite3_open_v2().
+**
+** Additional arguments beyond the first two make calls to
+** sqlite3_uri_key() for integers and sqlite3_uri_parameter for
+** anything else.
+**
+** The result is a string showing the results of calling sqlite3ParseUri().
+**
+** Used for testing and debugging only, specifically testing and debugging
+** of the sqlite3ParseUri() function. This SQL function does not appear
+** in production builds. This function is not an API and is subject to
+** modification or removal in future versions of SQLite.
+*/
+static void parseuriFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_str *pResult;
+ const char *zVfs;
+ const char *zUri;
+ unsigned int flgs;
+ int rc;
+ sqlite3_vfs *pVfs = 0;
+ char *zFile = 0;
+ char *zErr = 0;
+
+ if( argc<2 ) return;
+ pVfs = sqlite3_vfs_find(0);
+ assert( pVfs );
+ zVfs = pVfs->zName;
+ zUri = (const char*)sqlite3_value_text(argv[0]);
+ if( zUri==0 ) return;
+ flgs = (unsigned int)sqlite3_value_int(argv[1]);
+ rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
+ pResult = sqlite3_str_new(0);
+ if( pResult ){
+ int i;
+ sqlite3_str_appendf(pResult, "rc=%d", rc);
+ sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
+ sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
+ sqlite3_str_appendf(pResult, ", err=%Q", zErr);
+ sqlite3_str_appendf(pResult, ", file=%Q", zFile);
+ if( zFile ){
+ const char *z = zFile;
+ z += sqlite3Strlen30(z)+1;
+ while( z[0] ){
+ sqlite3_str_appendf(pResult, ", %Q", z);
+ z += sqlite3Strlen30(z)+1;
+ }
+ for(i=2; iapTrigger[0] && pFKey->aAction[0]==OE_SetNull)
|| (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull)
){
+ assert( (pTop->db->flags & SQLITE_FkNoAction)==0 );
return 1;
}
}
@@ -128291,9 +133384,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
SrcItem *pItem = pSrc->a;
- pItem->pTab = pFKey->pFrom;
+ pItem->pSTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
- pItem->pTab->nTabRef++;
+ pItem->pSTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
if( regNew!=0 ){
@@ -128301,6 +133394,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
@@ -128416,7 +133511,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;
}
}
@@ -128466,6 +133565,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;
}
@@ -128566,22 +133666,24 @@ 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");
+ pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
+ pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
+ if( pSrc ){
+ assert( pSrc->nSrc==1 );
+ pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom);
+ assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 );
+ pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ }
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
- sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom),
+ pSrc,
pWhere,
0, 0, 0, 0, 0
);
@@ -128697,9 +133799,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;
@@ -128762,8 +133863,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));
@@ -128797,46 +133900,48 @@ SQLITE_PRIVATE void sqlite3OpenTable(
** is managed along with the rest of the Index structure. It will be
** released when sqlite3DeleteIndex() is called.
*/
-SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
+static SQLITE_NOINLINE const char *computeIndexAffStr(sqlite3 *db, Index *pIdx){
+ /* The first time a column affinity string for a particular index is
+ ** required, it is allocated and populated here. It is then stored as
+ ** a member of the Index structure for subsequent use.
+ **
+ ** The column affinity string will eventually be deleted by
+ ** sqliteDeleteIndex() when the Index structure itself is cleaned
+ ** up.
+ */
+ int n;
+ Table *pTab = pIdx->pTable;
+ pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
if( !pIdx->zColAff ){
- /* The first time a column affinity string for a particular index is
- ** required, it is allocated and populated here. It is then stored as
- ** a member of the Index structure for subsequent use.
- **
- ** The column affinity string will eventually be deleted by
- ** sqliteDeleteIndex() when the Index structure itself is cleaned
- ** up.
- */
- int n;
- Table *pTab = pIdx->pTable;
- pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
- if( !pIdx->zColAff ){
- sqlite3OomFault(db);
- return 0;
- }
- for(n=0; nnColumn; n++){
- i16 x = pIdx->aiColumn[n];
- char aff;
- if( x>=0 ){
- aff = pTab->aCol[x].affinity;
- }else if( x==XN_ROWID ){
- aff = SQLITE_AFF_INTEGER;
- }else{
- assert( x==XN_EXPR );
- assert( pIdx->bHasExpr );
- assert( pIdx->aColExpr!=0 );
- aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
- }
- if( affSQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC;
- pIdx->zColAff[n] = aff;
+ sqlite3OomFault(db);
+ return 0;
+ }
+ for(n=0; nnColumn; n++){
+ i16 x = pIdx->aiColumn[n];
+ char aff;
+ if( x>=0 ){
+ aff = pTab->aCol[x].affinity;
+ }else if( x==XN_ROWID ){
+ aff = SQLITE_AFF_INTEGER;
+ }else{
+ assert( x==XN_EXPR );
+ assert( pIdx->bHasExpr );
+ assert( pIdx->aColExpr!=0 );
+ aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
}
- pIdx->zColAff[n] = 0;
+ if( affSQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC;
+ pIdx->zColAff[n] = aff;
}
-
+ pIdx->zColAff[n] = 0;
+ return pIdx->zColAff;
+}
+SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
+ if( !pIdx->zColAff ) return computeIndexAffStr(db, pIdx);
return pIdx->zColAff;
}
+
/*
** Compute an affinity string for a table. Space is obtained
** from sqlite3DbMalloc(). The caller is responsible for freeing
@@ -128890,7 +133995,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
@@ -129300,6 +134405,210 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
# define autoIncStep(A,B,C)
#endif /* SQLITE_OMIT_AUTOINCREMENT */
+/*
+** If argument pVal is a Select object returned by an sqlite3MultiValues()
+** that was able to use the co-routine optimization, finish coding the
+** co-routine.
+*/
+SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
+ if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){
+ SrcItem *pItem = &pVal->pSrc->a[0];
+ assert( (pItem->fg.isSubquery && pItem->u4.pSubq!=0) || pParse->nErr );
+ if( pItem->fg.isSubquery ){
+ sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->u4.pSubq->regReturn);
+ sqlite3VdbeJumpHere(pParse->pVdbe, pItem->u4.pSubq->addrFillSub - 1);
+ }
+ }
+}
+
+/*
+** Return true if all expressions in the expression-list passed as the
+** only argument are constant.
+*/
+static int exprListIsConstant(Parse *pParse, ExprList *pRow){
+ int ii;
+ for(ii=0; iinExpr; ii++){
+ if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0;
+ }
+ return 1;
+}
+
+/*
+** Return true if all expressions in the expression-list passed as the
+** only argument are both constant and have no affinity.
+*/
+static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
+ int ii;
+ if( exprListIsConstant(pParse,pRow)==0 ) return 0;
+ for(ii=0; iinExpr; ii++){
+ Expr *pExpr = pRow->a[ii].pExpr;
+ assert( pExpr->op!=TK_RAISE );
+ assert( pExpr->affExpr==0 );
+ if( 0!=sqlite3ExprAffinity(pExpr) ) return 0;
+ }
+ return 1;
+
+}
+
+/*
+** This function is called by the parser for the second and subsequent
+** rows of a multi-row VALUES clause. Argument pLeft is the part of
+** the VALUES clause already parsed, argument pRow is the vector of values
+** for the new row. The Select object returned represents the complete
+** VALUES clause, including the new row.
+**
+** There are two ways in which this may be achieved - by incremental
+** coding of a co-routine (the "co-routine" method) or by returning a
+** Select object equivalent to the following (the "UNION ALL" method):
+**
+** "pLeft UNION ALL SELECT pRow"
+**
+** If the VALUES clause contains a lot of rows, this compound Select
+** object may consume a lot of memory.
+**
+** When the co-routine method is used, each row that will be returned
+** by the VALUES clause is coded into part of a co-routine as it is
+** passed to this function. The returned Select object is equivalent to:
+**
+** SELECT * FROM (
+** Select object to read co-routine
+** )
+**
+** The co-routine method is used in most cases. Exceptions are:
+**
+** a) If the current statement has a WITH clause. This is to avoid
+** statements like:
+**
+** WITH cte AS ( VALUES('x'), ('y') ... )
+** SELECT * FROM cte AS a, cte AS b;
+**
+** This will not work, as the co-routine uses a hard-coded register
+** for its OP_Yield instructions, and so it is not possible for two
+** cursors to iterate through it concurrently.
+**
+** b) The schema is currently being parsed (i.e. the VALUES clause is part
+** of a schema item like a VIEW or TRIGGER). In this case there is no VM
+** being generated when parsing is taking place, and so generating
+** a co-routine is not possible.
+**
+** c) There are non-constant expressions in the VALUES clause (e.g.
+** the VALUES clause is part of a correlated sub-query).
+**
+** d) One or more of the values in the first row of the VALUES clause
+** has an affinity (i.e. is a CAST expression). This causes problems
+** because the complex rules SQLite uses (see function
+** sqlite3SubqueryColumnTypes() in select.c) to determine the effective
+** affinity of such a column for all rows require access to all values in
+** the column simultaneously.
+*/
+SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
+
+ if( pParse->bHasWith /* condition (a) above */
+ || pParse->db->init.busy /* condition (b) above */
+ || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */
+ || (pLeft->pSrc->nSrc==0 &&
+ exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */
+ || IN_SPECIAL_PARSE
+ ){
+ /* The co-routine method cannot be used. Fall back to UNION ALL. */
+ Select *pSelect = 0;
+ int f = SF_Values | SF_MultiValue;
+ if( pLeft->pSrc->nSrc ){
+ sqlite3MultiValuesEnd(pParse, pLeft);
+ f = SF_Values;
+ }else if( pLeft->pPrior ){
+ /* In this case set the SF_MultiValue flag only if it was set on pLeft */
+ f = (f & pLeft->selFlags);
+ }
+ pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
+ pLeft->selFlags &= ~SF_MultiValue;
+ if( pSelect ){
+ pSelect->op = TK_ALL;
+ pSelect->pPrior = pLeft;
+ pLeft = pSelect;
+ }
+ }else{
+ SrcItem *p = 0; /* SrcItem that reads from co-routine */
+
+ if( pLeft->pSrc->nSrc==0 ){
+ /* Co-routine has not yet been started and the special Select object
+ ** that accesses the co-routine has not yet been created. This block
+ ** does both those things. */
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ /* Ensure the database schema has been read. This is to ensure we have
+ ** the correct text encoding. */
+ if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){
+ sqlite3ReadSchema(pParse);
+ }
+
+ if( pRet ){
+ SelectDest dest;
+ Subquery *pSubq;
+ pRet->pSrc->nSrc = 1;
+ pRet->pPrior = pLeft->pPrior;
+ pRet->op = pLeft->op;
+ if( pRet->pPrior ) pRet->selFlags |= SF_Values;
+ pLeft->pPrior = 0;
+ pLeft->op = TK_SELECT;
+ assert( pLeft->pNext==0 );
+ assert( pRet->pNext==0 );
+ p = &pRet->pSrc->a[0];
+ p->fg.viaCoroutine = 1;
+ p->iCursor = -1;
+ assert( !p->fg.isIndexedBy && !p->fg.isTabFunc );
+ p->u1.nRow = 2;
+ if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){
+ pSubq = p->u4.pSubq;
+ pSubq->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
+ pSubq->regReturn = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine,
+ pSubq->regReturn, 0, pSubq->addrFillSub);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
+
+ /* Allocate registers for the output of the co-routine. Do so so
+ ** that there are two unused registers immediately before those
+ ** used by the co-routine. This allows the code in sqlite3Insert()
+ ** to use these registers directly, instead of copying the output
+ ** of the co-routine to a separate array for processing. */
+ dest.iSdst = pParse->nMem + 3;
+ dest.nSdst = pLeft->pEList->nExpr;
+ pParse->nMem += 2 + dest.nSdst;
+
+ pLeft->selFlags |= SF_MultiValue;
+ sqlite3Select(pParse, pLeft, &dest);
+ pSubq->regResult = dest.iSdst;
+ assert( pParse->nErr || dest.iSdst>0 );
+ }
+ pLeft = pRet;
+ }
+ }else{
+ p = &pLeft->pSrc->a[0];
+ assert( !p->fg.isTabFunc && !p->fg.isIndexedBy );
+ p->u1.nRow++;
+ }
+
+ if( pParse->nErr==0 ){
+ Subquery *pSubq;
+ assert( p!=0 );
+ assert( p->fg.isSubquery );
+ pSubq = p->u4.pSubq;
+ assert( pSubq!=0 );
+ assert( pSubq->pSelect!=0 );
+ assert( pSubq->pSelect->pEList!=0 );
+ if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){
+ sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect);
+ }else{
+ sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0);
+ sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn);
+ }
+ }
+ sqlite3ExprListDelete(pParse->db, pRow);
+ }
+
+ return pLeft;
+}
/* Forward declaration */
static int xferOptimization(
@@ -129446,6 +134755,7 @@ SQLITE_PRIVATE void sqlite3Insert(
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int *aRegIdx = 0; /* One register allocated to each index */
+ int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
@@ -129521,7 +134831,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;
}
@@ -129590,15 +134900,15 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
- assert( pColumn->eU4!=EU4_EXPR );
- pColumn->eU4 = EU4_IDX;
- for(i=0; inId; i++){
- pColumn->a[i].u4.idx = -1;
- }
+ aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int));
+ if( aTabColMap==0 ) goto insert_cleanup;
for(i=0; inId; i++){
+ const char *zCName = pColumn->a[i].zName;
+ u8 hName = sqlite3StrIHash(zCName);
for(j=0; jnCol; j++){
- if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
- pColumn->a[i].u4.idx = j;
+ if( pTab->aCol[j].hName!=hName ) continue;
+ if( sqlite3StrICmp(zCName, pTab->aCol[j].zCnName)==0 ){
+ if( aTabColMap[j]==0 ) aTabColMap[j] = i+1;
if( i!=j ) bIdListInOrder = 0;
if( j==pTab->iPKey ){
ipkColumn = i; assert( !withoutRowid );
@@ -129636,25 +134946,45 @@ SQLITE_PRIVATE void sqlite3Insert(
if( pSelect ){
/* Data is coming from a SELECT or from a multi-row VALUES clause.
** Generate a co-routine to run the SELECT. */
- int regYield; /* Register holding co-routine entry-point */
- int addrTop; /* Top of the co-routine */
int rc; /* Result code */
- regYield = ++pParse->nMem;
- addrTop = sqlite3VdbeCurrentAddr(v) + 1;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
- sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
- dest.iSdst = bIdListInOrder ? regData : 0;
- dest.nSdst = pTab->nCol;
- rc = sqlite3Select(pParse, pSelect, &dest);
- regFromSelect = dest.iSdst;
- assert( db->pParse==pParse );
- if( rc || pParse->nErr ) goto insert_cleanup;
- assert( db->mallocFailed==0 );
- sqlite3VdbeEndCoroutine(v, regYield);
- sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
- assert( pSelect->pEList );
- nColumn = pSelect->pEList->nExpr;
+ if( pSelect->pSrc->nSrc==1
+ && pSelect->pSrc->a[0].fg.viaCoroutine
+ && pSelect->pPrior==0
+ ){
+ SrcItem *pItem = &pSelect->pSrc->a[0];
+ Subquery *pSubq;
+ assert( pItem->fg.isSubquery );
+ pSubq = pItem->u4.pSubq;
+ dest.iSDParm = pSubq->regReturn;
+ regFromSelect = pSubq->regResult;
+ assert( pSubq->pSelect!=0 );
+ assert( pSubq->pSelect->pEList!=0 );
+ nColumn = pSubq->pSelect->pEList->nExpr;
+ ExplainQueryPlan((pParse, 0, "SCAN %S", pItem));
+ if( bIdListInOrder && nColumn==pTab->nCol ){
+ regData = regFromSelect;
+ regRowid = regData - 1;
+ regIns = regRowid - (IsVirtual(pTab) ? 1 : 0);
+ }
+ }else{
+ int addrTop; /* Top of the co-routine */
+ int regYield = ++pParse->nMem;
+ addrTop = sqlite3VdbeCurrentAddr(v) + 1;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
+ dest.iSdst = bIdListInOrder ? regData : 0;
+ dest.nSdst = pTab->nCol;
+ rc = sqlite3Select(pParse, pSelect, &dest);
+ regFromSelect = dest.iSdst;
+ assert( db->pParse==pParse );
+ if( rc || pParse->nErr ) goto insert_cleanup;
+ assert( db->mallocFailed==0 );
+ sqlite3VdbeEndCoroutine(v, regYield);
+ sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
+ assert( pSelect->pEList );
+ nColumn = pSelect->pEList->nExpr;
+ }
/* Set useTempTable to TRUE if the result of the SELECT statement
** should be written into a temporary table (template 4). Set to
@@ -129809,7 +135139,7 @@ SQLITE_PRIVATE void sqlite3Insert(
pNx->iDataCur = iDataCur;
pNx->iIdxCur = iIdxCur;
if( pNx->pUpsertTarget ){
- if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
+ if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){
goto insert_cleanup;
}
}
@@ -129900,9 +135230,9 @@ SQLITE_PRIVATE void sqlite3Insert(
}
}
if( pColumn ){
- assert( pColumn->eU4==EU4_IDX );
- for(j=0; jnId && pColumn->a[j].u4.idx!=i; j++){}
- if( j>=pColumn->nId ){
+ j = aTabColMap[i];
+ assert( j>=0 && j<=pColumn->nId );
+ if( j==0 ){
/* A column not named in the insert column list gets its
** default value */
sqlite3ExprCodeFactorable(pParse,
@@ -129910,7 +135240,7 @@ SQLITE_PRIVATE void sqlite3Insert(
iRegStore);
continue;
}
- k = j;
+ k = j - 1;
}else if( nColumn==0 ){
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
sqlite3ExprCodeFactorable(pParse,
@@ -129968,7 +135298,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
@@ -130155,7 +135485,10 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3ExprListDelete(db, pList);
sqlite3UpsertDelete(db, pUpsert);
sqlite3SelectDelete(db, pSelect);
- sqlite3IdListDelete(db, pColumn);
+ if( pColumn ){
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3DbFree(db, aTabColMap);
+ }
if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx);
}
@@ -130182,7 +135515,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 ){
@@ -130405,7 +135738,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 */
@@ -130888,7 +136221,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 */
@@ -131383,6 +136716,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
@@ -131395,18 +136730,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] ){
@@ -131548,7 +136883,7 @@ static int xferOptimization(
if( pSelect->pSrc->nSrc!=1 ){
return 0; /* FROM clause must have exactly one term */
}
- if( pSelect->pSrc->a[0].pSelect ){
+ if( pSelect->pSrc->a[0].fg.isSubquery ){
return 0; /* FROM clause cannot contain a subquery */
}
if( pSelect->pWhere ){
@@ -131699,12 +137034,15 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
- if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
+ if( pDest->pCheck
+ && (db->mDbFlags & DBFLAG_Vacuum)==0
+ && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
+ ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
- /* Disallow the transfer optimization if the destination table 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
@@ -132414,6 +137752,11 @@ 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*));
};
/*
@@ -132742,6 +138085,11 @@ 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
+/* Version 3.43.0 and later */
+#define sqlite3_stmt_explain sqlite3_api->stmt_explain
+/* Version 3.44.0 and later */
+#define sqlite3_get_clientdata sqlite3_api->get_clientdata
+#define sqlite3_set_clientdata sqlite3_api->set_clientdata
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -133258,7 +138606,12 @@ 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
};
/* True if x is the directory separator character
@@ -133331,15 +138684,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;
@@ -133513,6 +138879,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 ){
@@ -133565,6 +138934,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 ){
@@ -134340,6 +139712,34 @@ static const PragmaName aPragmaName[] = {
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
+/*
+** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands
+** will be run with an analysis_limit set to the lessor of the value of
+** the following macro or to the actual analysis_limit if it is non-zero,
+** in order to prevent PRAGMA optimize from running for too long.
+**
+** The value of 2000 is chosen emperically so that the worst-case run-time
+** for PRAGMA optimize does not exceed 100 milliseconds against a variety
+** of test databases on a RaspberryPI-4 compiled using -Os and without
+** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
+** this paragraph, "worst-case" means that ANALYZE ends up being
+** run on every table in the database. The worst case typically only
+** happens if PRAGMA optimize is run on a database file for which ANALYZE
+** has not been previously run and the 0x10000 flag is included so that
+** all tables are analyzed. The usual case for PRAGMA optimize is that
+** no ANALYZE commands will be run at all, or if any ANALYZE happens it
+** will be against a single table, so that expected timing for PRAGMA
+** optimize on a PI-4 is more like 1 millisecond or less with the 0x10000
+** flag or less than 100 microseconds without the 0x10000 flag.
+**
+** An analysis limit of 2000 is almost always sufficient for the query
+** planner to fully characterize an index. The additional accuracy from
+** a larger analysis is not usually helpful.
+*/
+#ifndef SQLITE_DEFAULT_OPTIMIZE_LIMIT
+# define SQLITE_DEFAULT_OPTIMIZE_LIMIT 2000
+#endif
+
/*
** Interpret the given string as a safety level. Return 0 for OFF,
** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or
@@ -135164,7 +140564,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
@@ -135426,15 +140826,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
** in auto-commit mode. */
mask &= ~(SQLITE_ForeignKeys);
}
-#if SQLITE_USER_AUTHENTICATION
- if( db->auth.authLevel==UAUTH_User ){
- /* Do not allow non-admin users to modify the schema arbitrarily */
- mask &= ~(SQLITE_WriteSchema);
- }
-#endif
if( sqlite3GetBoolean(zRight, 0) ){
- 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;
@@ -135563,7 +140961,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
if( zSql ){
sqlite3_stmt *pDummy = 0;
- (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
+ (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG,
+ &pDummy, 0);
(void)sqlite3_finalize(pDummy);
sqlite3DbFree(db, zSql);
}
@@ -135834,7 +141233,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) );
@@ -135875,7 +141274,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);
@@ -135942,9 +141341,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
@@ -135981,7 +141380,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Set the maximum error count */
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
if( zRight ){
- if( sqlite3GetInt32(zRight, &mxErr) ){
+ if( sqlite3GetInt32(pValue->z, &mxErr) ){
if( mxErr<=0 ){
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
@@ -135998,12 +141397,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
Hash *pTbls; /* Set of all tables in the schema */
int *aRoot; /* Array of root page numbers of all btrees */
int cnt = 0; /* Number of entries in aRoot[] */
- int mxIdx = 0; /* Maximum number of indexes for any table */
if( OMIT_TEMPDB && i==1 ) continue;
if( iDb>=0 && i!=iDb ) continue;
sqlite3CodeVerifySchema(pParse, i);
+ pParse->okConstFactor = 0; /* tag-20230327-1 */
/* Do an integrity check of the B-Tree
**
@@ -136019,7 +141418,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( pObjTab && pObjTab!=pTab ) continue;
if( HasRowid(pTab) ) cnt++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
- if( nIdx>mxIdx ) mxIdx = nIdx;
}
if( cnt==0 ) continue;
if( pObjTab ) cnt++;
@@ -136039,12 +141437,13 @@ 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+cnt);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
- sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
- sqlite3VdbeChangeP5(v, (u8)i);
+ sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY);
+ sqlite3VdbeChangeP5(v, (u16)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
@@ -136053,6 +141452,36 @@ SQLITE_PRIVATE void sqlite3Pragma(
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, addr);
+ /* Check that the indexes all have the right number of rows */
+ cnt = pObjTab ? 1 : 0;
+ sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
+ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ int iTab = 0;
+ Table *pTab = sqliteHashData(x);
+ Index *pIdx;
+ if( pObjTab && pObjTab!=pTab ) continue;
+ if( HasRowid(pTab) ){
+ iTab = cnt++;
+ }else{
+ iTab = cnt;
+ for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){
+ if( IsPrimaryKeyIndex(pIdx) ) break;
+ iTab++;
+ }
+ }
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->pPartIdxWhere==0 ){
+ addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+cnt, 0, 8+iTab);
+ VdbeCoverageNeverNull(v);
+ sqlite3VdbeLoadString(v, 4, pIdx->zName);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
+ integrityCheckResultRow(v);
+ sqlite3VdbeJumpHere(v, addr);
+ }
+ cnt++;
+ }
+ }
+
/* Make sure all the indices are constructed correctly.
*/
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
@@ -136066,8 +141495,8 @@ 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) ) continue;
if( isQuick || HasRowid(pTab) ){
pPk = 0;
r2 = 0;
@@ -136189,15 +141618,30 @@ 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);
+ sqlite3ColumnDefault(v, pTab, j, 3);
+ jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk);
+ VdbeCoverage(v);
+ }
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pCol->zCnName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
if( doTypeCheck ){
sqlite3VdbeGoto(v, labelError);
sqlite3VdbeJumpHere(v, jmp2);
+ sqlite3VdbeJumpHere(v, jmp3);
}else{
/* VDBE byte code will fall thru */
}
@@ -136305,7 +141749,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int jmp7;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur+j, 3);
jmp7 = sqlite3VdbeAddOp3(v, OP_Eq, 3, 0, r1+pIdx->nColumn-1);
- VdbeCoverage(v);
+ VdbeCoverageNeverNull(v);
sqlite3VdbeLoadString(v, 3,
"rowid not at end-of-record for row ");
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
@@ -136361,23 +141805,43 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
- if( !isQuick ){
- sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- if( pPk==pIdx ) continue;
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
- addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- sqlite3VdbeLoadString(v, 4, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
- integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, addr);
- }
- if( pPk ){
- sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
- }
+ if( pPk ){
+ assert( !isQuick );
+ sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
}
}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Second pass to invoke the xIntegrity method on all virtual
+ ** tables.
+ */
+ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ Table *pTab = sqliteHashData(x);
+ sqlite3_vtab *pVTab;
+ int a1;
+ if( pObjTab && pObjTab!=pTab ) continue;
+ if( IsOrdinaryTable(pTab) ) continue;
+ if( !IsVirtual(pTab) ) continue;
+ if( pTab->nCol<=0 ){
+ const char *zMod = pTab->u.vtab.azArg[0];
+ if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
+ }
+ sqlite3ViewGetColumnNames(pParse, pTab);
+ if( pTab->u.vtab.p==0 ) continue;
+ pVTab = pTab->u.vtab.p->pVtab;
+ if( NEVER(pVTab==0) ) continue;
+ if( NEVER(pVTab->pModule==0) ) continue;
+ if( pVTab->pModule->iVersion<4 ) continue;
+ if( pVTab->pModule->xIntegrity==0 ) continue;
+ sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
+ pTab->nTabRef++;
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
+ a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
+ integrityCheckResultRow(v);
+ sqlite3VdbeJumpHere(v, a1);
+ continue;
+ }
+#endif
}
{
static const int iLn = VDBE_OFFSET_LINENO(2);
@@ -136641,44 +142105,63 @@ SQLITE_PRIVATE void sqlite3Pragma(
**
** The optional argument is a bitmask of optimizations to perform:
**
- ** 0x0001 Debugging mode. Do not actually perform any optimizations
- ** but instead return one line of text for each optimization
- ** that would have been done. Off by default.
+ ** 0x00001 Debugging mode. Do not actually perform any optimizations
+ ** but instead return one line of text for each optimization
+ ** that would have been done. Off by default.
**
- ** 0x0002 Run ANALYZE on tables that might benefit. On by default.
- ** See below for additional information.
+ ** 0x00002 Run ANALYZE on tables that might benefit. On by default.
+ ** See below for additional information.
**
- ** 0x0004 (Not yet implemented) Record usage and performance
- ** information from the current session in the
- ** database file so that it will be available to "optimize"
- ** pragmas run by future database connections.
+ ** 0x00010 Run all ANALYZE operations using an analysis_limit that
+ ** is the lessor of the current analysis_limit and the
+ ** SQLITE_DEFAULT_OPTIMIZE_LIMIT compile-time option.
+ ** The default value of SQLITE_DEFAULT_OPTIMIZE_LIMIT is
+ ** currently (2024-02-19) set to 2000, which is such that
+ ** the worst case run-time for PRAGMA optimize on a 100MB
+ ** database will usually be less than 100 milliseconds on
+ ** a RaspberryPI-4 class machine. On by default.
**
- ** 0x0008 (Not yet implemented) Create indexes that might have
- ** been helpful to recent queries
+ ** 0x10000 Look at tables to see if they need to be reanalyzed
+ ** due to growth or shrinkage even if they have not been
+ ** queried during the current connection. Off by default.
**
- ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all
- ** of the optimizations listed above except Debug Mode, including new
- ** optimizations that have not yet been invented. If new optimizations are
- ** ever added that should be off by default, those off-by-default
- ** optimizations will have bitmasks of 0x10000 or larger.
+ ** The default MASK is and always shall be 0x0fffe. In the current
+ ** implementation, the default mask only covers the 0x00002 optimization,
+ ** though additional optimizations that are covered by 0x0fffe might be
+ ** added in the future. Optimizations that are off by default and must
+ ** be explicitly requested have masks of 0x10000 or greater.
**
** DETERMINATION OF WHEN TO RUN ANALYZE
**
** In the current implementation, a table is analyzed if only if all of
** the following are true:
**
- ** (1) MASK bit 0x02 is set.
+ ** (1) MASK bit 0x00002 is set.
**
- ** (2) The query planner used sqlite_stat1-style statistics for one or
- ** more indexes of the table at some point during the lifetime of
- ** the current connection.
+ ** (2) The table is an ordinary table, not a virtual table or view.
**
- ** (3) One or more indexes of the table are currently unanalyzed OR
- ** the number of rows in the table has increased by 25 times or more
- ** since the last time ANALYZE was run.
+ ** (3) The table name does not begin with "sqlite_".
+ **
+ ** (4) One or more of the following is true:
+ ** (4a) The 0x10000 MASK bit is set.
+ ** (4b) One or more indexes on the table lacks an entry
+ ** in the sqlite_stat1 table.
+ ** (4c) The query planner used sqlite_stat1-style statistics for one
+ ** or more indexes of the table at some point during the lifetime
+ ** of the current connection.
+ **
+ ** (5) One or more of the following is true:
+ ** (5a) One or more indexes on the table lacks an entry
+ ** in the sqlite_stat1 table. (Same as 4a)
+ ** (5b) The number of rows in the table has increased or decreased by
+ ** 10-fold. In other words, the current size of the table is
+ ** 10 times larger than the size in sqlite_stat1 or else the
+ ** current size is less than 1/10th the size in sqlite_stat1.
**
** The rules for when tables are analyzed are likely to change in
- ** future releases.
+ ** future releases. Future versions of SQLite might accept a string
+ ** literal argument to this pragma that contains a mnemonic description
+ ** of the options rather than a bitmap.
*/
case PragTyp_OPTIMIZE: {
int iDbLast; /* Loop termination point for the schema loop */
@@ -136687,9 +142170,13 @@ 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 */
+ int nLimit; /* Analysis limit to use */
+ int nCheck = 0; /* Number of tables to be optimized */
+ int nBtree = 0; /* Number of btrees to scan */
+ int nIndex; /* Number of indexes on the current table */
if( zRight ){
opMask = (u32)sqlite3Atoi(zRight);
@@ -136697,6 +142184,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
opMask = 0xfffe;
}
+ if( (opMask & 0x10)==0 ){
+ nLimit = 0;
+ }else if( db->nAnalysisLimit>0
+ && db->nAnalysisLimitnTab++;
for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){
if( iDb==1 ) continue;
@@ -136705,23 +142200,61 @@ SQLITE_PRIVATE void sqlite3Pragma(
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
pTab = (Table*)sqliteHashData(k);
- /* If table pTab has not been used in a way that would benefit from
- ** having analysis statistics during the current session, then skip it.
- ** This also has the effect of skipping virtual tables and views */
- if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue;
+ /* This only works for ordinary tables */
+ if( !IsOrdinaryTable(pTab) ) continue;
+
+ /* Do not scan system tables */
+ if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue;
- /* Reanalyze if the table is 25 times larger than the last analysis */
- szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 );
+ /* Find the size of the table as last recorded in sqlite_stat1.
+ ** If any index is unanalyzed, then the threshold is -1 to
+ ** indicate a new, unanalyzed index
+ */
+ szThreshold = pTab->nRowLogEst;
+ nIndex = 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ nIndex++;
if( !pIdx->hasStat1 ){
- szThreshold = 0; /* Always analyze if any index lacks statistics */
- break;
+ szThreshold = -1; /* Always analyze if any index lacks statistics */
}
}
- if( szThreshold ){
- sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
- sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur,
- sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold);
+
+ /* If table pTab has not been used in a way that would benefit from
+ ** having analysis statistics during the current session, then skip it,
+ ** unless the 0x10000 MASK bit is set. */
+ if( (pTab->tabFlags & TF_MaybeReanalyze)!=0 ){
+ /* Check for size change if stat1 has been used for a query */
+ }else if( opMask & 0x10000 ){
+ /* Check for size change if 0x10000 is set */
+ }else if( pTab->pIndex!=0 && szThreshold<0 ){
+ /* Do analysis if unanalyzed indexes exists */
+ }else{
+ /* Otherwise, we can skip this table */
+ continue;
+ }
+
+ nCheck++;
+ if( nCheck==2 ){
+ /* If ANALYZE might be invoked two or more times, hold a write
+ ** transaction for efficiency */
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ }
+ nBtree += nIndex+1;
+
+ /* Reanalyze if the table is 10 times larger or smaller than
+ ** the last analysis. Unconditional reanalysis if there are
+ ** unanalyzed indexes. */
+ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
+ if( szThreshold>=0 ){
+ const LogEst iRange = 33; /* 10x size change */
+ sqlite3VdbeAddOp4Int(v, OP_IfSizeBetween, iTabCur,
+ sqlite3VdbeCurrentAddr(v)+2+(opMask&1),
+ szThreshold>=iRange ? szThreshold-iRange : -1,
+ szThreshold+iRange);
+ VdbeCoverage(v);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Rewind, iTabCur,
+ sqlite3VdbeCurrentAddr(v)+2+(opMask&1));
VdbeCoverage(v);
}
zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"",
@@ -136731,11 +142264,27 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1);
}else{
- sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC);
+ sqlite3VdbeAddOp4(v, OP_SqlExec, nLimit ? 0x02 : 00, nLimit, 0,
+ zSubSql, P4_DYNAMIC);
}
}
}
sqlite3VdbeAddOp0(v, OP_Expire);
+
+ /* In a schema with a large number of tables and indexes, scale back
+ ** the analysis_limit to avoid excess run-time in the worst case.
+ */
+ if( !db->mallocFailed && nLimit>0 && nBtree>100 ){
+ int iAddr, iEnd;
+ VdbeOp *aOp;
+ nLimit = 100*nLimit/nBtree;
+ if( nLimit<100 ) nLimit = 100;
+ aOp = sqlite3VdbeGetOp(v, 0);
+ iEnd = sqlite3VdbeCurrentAddr(v);
+ for(iAddr=0; iAddrnConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->iColumn < pTab->iHidden ) continue;
+ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+ if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT;
j = pConstraint->iColumn - pTab->iHidden;
assert( j < 2 );
seen[j] = i+1;
@@ -137014,12 +142563,13 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
j = seen[0]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
pIdxInfo->aConstraintUsage[j].omit = 1;
- if( seen[1]==0 ) return SQLITE_OK;
pIdxInfo->estimatedCost = (double)20;
pIdxInfo->estimatedRows = 20;
- j = seen[1]-1;
- pIdxInfo->aConstraintUsage[j].argvIndex = 2;
- pIdxInfo->aConstraintUsage[j].omit = 1;
+ if( seen[1] ){
+ j = seen[1]-1;
+ pIdxInfo->aConstraintUsage[j].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[j].omit = 1;
+ }
return SQLITE_OK;
}
@@ -137039,6 +142589,7 @@ static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
int i;
sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
+ pCsr->iRowid = 0;
for(i=0; iazArg); i++){
sqlite3_free(pCsr->azArg[i]);
pCsr->azArg[i] = 0;
@@ -137179,7 +142730,8 @@ static const sqlite3_module pragmaVtabModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
- 0 /* xShadowName */
+ 0, /* xShadowName */
+ 0 /* xIntegrity */
};
/*
@@ -137511,12 +143063,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
#else
encoding = SQLITE_UTF8;
#endif
- if( db->nVdbeActive>0 && encoding!=ENC(db) ){
- rc = SQLITE_LOCKED;
- goto initone_error_out;
- }else{
- sqlite3SetTextEncoding(db, encoding);
- }
+ sqlite3SetTextEncoding(db, encoding);
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
@@ -137801,8 +143348,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;
}
/*
@@ -137811,7 +143356,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.
@@ -137838,7 +143383,13 @@ SQLITE_PRIVATE void *sqlite3ParserAddCleanup(
void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
void *pPtr /* Pointer to object to be cleaned up */
){
- ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ ParseCleanup *pCleanup;
+ if( sqlite3FaultSim(300) ){
+ pCleanup = 0;
+ sqlite3OomFault(pParse->db);
+ }else{
+ pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ }
if( pCleanup ){
pCleanup->pNext = pParse->pCleanup;
pParse->pCleanup = pCleanup;
@@ -137903,9 +143454,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
@@ -138064,6 +143624,7 @@ static int sqlite3LockAndPrepare(
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
+ assert( rc==SQLITE_OK || (*ppStmt)==0 );
return rc;
}
@@ -138196,12 +143757,24 @@ static int sqlite3Prepare16(
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
return SQLITE_MISUSE_BKPT;
}
+
+ /* Make sure nBytes is non-negative and correct. It should be the
+ ** number of bytes until the end of the input buffer or until the first
+ ** U+0000 character. If the input nBytes is odd, convert it into
+ ** an even number. If the input nBytes is negative, then the input
+ ** must be terminated by at least one U+0000 character */
if( nBytes>=0 ){
int sz;
const char *z = (const char*)zSql;
for(sz=0; szmutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
@@ -138215,7 +143788,7 @@ static int sqlite3Prepare16(
** the same number of characters into the UTF-16 string.
*/
int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
- *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
+ *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed);
}
sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
@@ -138461,6 +144034,9 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
+SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3 *db, void *p){
+ if( ALWAYS(p) ) clearSelect(db, (Select*)p, 1);
+}
/*
** Return a pointer to the right-most SELECT statement in a compound.
@@ -138509,7 +144085,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:
@@ -138606,11 +144182,13 @@ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
*/
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
assert( pItem!=0 );
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
if( pItem->fg.isNestedFrom ){
ExprList *pResults;
- assert( pItem->pSelect!=0 );
- pResults = pItem->pSelect->pEList;
+ assert( pItem->fg.isSubquery );
+ assert( pItem->u4.pSubq!=0 );
+ assert( pItem->u4.pSubq->pSelect!=0 );
+ pResults = pItem->u4.pSubq->pSelect->pEList;
assert( pResults!=0 );
assert( iCol>=0 && iColnExpr );
pResults->a[iCol].fg.bUsed = 1;
@@ -138644,9 +144222,9 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=iStart; i<=iEnd; i++){
- iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
+ iCol = sqlite3ColumnIndex(pSrc->a[i].pSTab, zCol);
if( iCol>=0
- && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pSTab->aCol[iCol])==0)
){
if( piTab ){
sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
@@ -138731,6 +144309,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++){
@@ -138774,13 +144353,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; inSrc-1; i++, pRight++, pLeft++){
- Table *pRightTab = pRight->pTab;
+ Table *pRightTab = pRight->pSTab;
u32 joinType;
- if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
+ if( NEVER(pLeft->pSTab==0 || pRightTab==0) ) continue;
joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;
- /* If this is a NATURAL join, synthesize an 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 ){
@@ -138994,9 +144573,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.
*/
@@ -139052,7 +144631,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);
@@ -139146,7 +144725,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,
@@ -139575,6 +145154,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
@@ -139640,12 +145229,18 @@ static void selectInnerLoop(
** case the order does matter */
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+ pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
+ if( pDest->iSDParm2 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ regResult, nResultCol);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -139936,9 +145531,16 @@ static void generateSortTail(
int addrExplain; /* Address of OP_Explain instruction */
#endif
- ExplainQueryPlan2(addrExplain, (pParse, 0,
- "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"")
- );
+ nKey = pOrderBy->nExpr - pSort->nOBSat;
+ if( pSort->nOBSat==0 || nKey==1 ){
+ ExplainQueryPlan2(addrExplain, (pParse, 0,
+ "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":""
+ ));
+ }else{
+ ExplainQueryPlan2(addrExplain, (pParse, 0,
+ "USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey
+ ));
+ }
sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd);
sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush);
@@ -139976,7 +145578,6 @@ static void generateSortTail(
regRow = sqlite3GetTempRange(pParse, nColumn);
}
}
- nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->sortFlags & SORTFLAG_UseSorter ){
int regSortOut = ++pParse->nMem;
iSortTab = pParse->nTab++;
@@ -140181,8 +145782,12 @@ static const char *columnTypeImpl(
SrcList *pTabList = pNC->pSrcList;
for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
if( jnSrc ){
- pTab = pTabList->a[j].pTab;
- pS = pTabList->a[j].pSelect;
+ pTab = pTabList->a[j].pSTab;
+ if( pTabList->a[j].fg.isSubquery ){
+ pS = pTabList->a[j].u4.pSubq->pSelect;
+ }else{
+ pS = 0;
+ }
}else{
pNC = pNC->pNext;
}
@@ -140216,11 +145821,7 @@ static const char *columnTypeImpl(
** data for the result-set column of the sub-select.
*/
if( iColpEList->nExpr
-#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
- && iCol>=0
-#else
- && ALWAYS(iCol>=0)
-#endif
+ && (!ViewCanHaveRowid || iCol>=0)
){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
@@ -140378,13 +145979,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;
@@ -140571,7 +146165,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
@@ -140595,7 +146189,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));
@@ -140603,17 +146197,22 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(
for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){
const char *zType;
i64 n;
+ int m = 0;
+ Select *pS2 = pSelect;
pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
/* pCol->szEst = ... // Column size est for SELECT tables never used */
pCol->affinity = sqlite3ExprAffinity(p);
+ while( pCol->affinity<=SQLITE_AFF_NONE && pS2->pNext!=0 ){
+ m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
+ pS2 = pS2->pNext;
+ pCol->affinity = sqlite3ExprAffinity(pS2->pEList->a[i].pExpr);
+ }
if( pCol->affinity<=SQLITE_AFF_NONE ){
pCol->affinity = aff;
}
- if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){
- int m = 0;
- Select *pS2;
- for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){
+ if( pCol->affinity>=SQLITE_AFF_TEXT && (pS2->pNext || pS2!=pSelect) ){
+ for(pS2=pS2->pNext; pS2; pS2=pS2->pNext){
m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr);
}
if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){
@@ -140640,18 +146239,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 ){
+ const i64 k = sqlite3Strlen30(zType);
+ n = sqlite3Strlen30(pCol->zCnName);
+ pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2);
+ pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
+ if( pCol->zCnName ){
+ memcpy(&pCol->zCnName[n+1], zType, k+1);
+ pCol->colFlags |= COLFLAG_HASTYPE;
}
}
pColl = sqlite3ExprCollSeq(pParse, p);
@@ -140757,7 +146354,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
+ if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
@@ -140902,7 +146499,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 */
@@ -141237,7 +146834,7 @@ static int multiSelect(
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( p->pLimit
- && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -141478,9 +147075,7 @@ static int multiSelect(
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
if( pDelete ){
- sqlite3ParserAddCleanup(pParse,
- (void(*)(sqlite3*,void*))sqlite3SelectDelete,
- pDelete);
+ sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete);
}
return rc;
}
@@ -141502,7 +147097,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
@@ -141583,6 +147178,11 @@ static int generateOutputSubroutine(
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
+ if( pDest->iSDParm2>0 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ pIn->iSdst, pIn->nSdst);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -141724,7 +147324,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
@@ -141761,7 +147361,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 */
@@ -142031,8 +147631,7 @@ static int multiSelectOrderBy(
/* Make arrangements to free the 2nd and subsequent arms of the compound
** after the parse has finished */
if( pSplit->pPrior ){
- sqlite3ParserAddCleanup(pParse,
- (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior);
+ sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior);
}
pSplit->pPrior = pPrior;
pPrior->pNext = pSplit;
@@ -142130,11 +147729,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{
@@ -142159,32 +147761,32 @@ static Expr *substExpr(
if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
- if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
- sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
- pExpr->flags & (EP_OuterON|EP_InnerON));
- }
- sqlite3ExprDelete(db, pExpr);
- pExpr = pNew;
- if( pExpr->op==TK_TRUEFALSE ){
- pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
- pExpr->op = TK_INTEGER;
- ExprSetProperty(pExpr, EP_IntValue);
+ if( pNew->op==TK_TRUEFALSE ){
+ pNew->u.iValue = sqlite3ExprTruthValue(pNew);
+ pNew->op = TK_INTEGER;
+ ExprSetProperty(pNew, EP_IntValue);
}
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
{
- CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew);
CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
pSubst->pCList->a[iColumn].pExpr
);
- if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){
+ pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew,
(pColl ? pColl->zName : "BINARY")
);
}
}
- ExprClearProperty(pExpr, EP_Collate);
+ ExprClearProperty(pNew, EP_Collate);
+ if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
+ sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
+ pExpr->flags & (EP_OuterON|EP_InnerON));
+ }
+ sqlite3ExprDelete(db, pExpr);
+ pExpr = pNew;
}
}
}else{
@@ -142237,7 +147839,9 @@ static void substSelect(
pSrc = p->pSrc;
assert( pSrc!=0 );
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(pSubst, pItem->pSelect, 1);
+ if( pItem->fg.isSubquery ){
+ substSelect(pSubst, pItem->u4.pSubq->pSelect, 1);
+ }
if( pItem->fg.isTabFunc ){
substExprList(pSubst, pItem->u1.pFuncArg);
}
@@ -142268,7 +147872,7 @@ static void recomputeColumnsUsed(
SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
- if( NEVER(pSrcItem->pTab==0) ) return;
+ if( NEVER(pSrcItem->pSTab==0) ) return;
memset(&w, 0, sizeof(w));
w.xExprCallback = recomputeColumnsUsedExpr;
w.xSelectCallback = sqlite3SelectWalkNoop;
@@ -142308,8 +147912,10 @@ static void srclistRenumberCursors(
aCsrMap[pItem->iCursor+1] = pParse->nTab++;
}
pItem->iCursor = aCsrMap[pItem->iCursor+1];
- for(p=pItem->pSelect; p; p=p->pPrior){
- srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ if( pItem->fg.isSubquery ){
+ for(p=pItem->u4.pSubq->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
}
}
}
@@ -142483,7 +148089,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."
**
@@ -142518,8 +148124,7 @@ static int compoundHasDifferentAffinities(Select *p){
** query or there are no RIGHT or FULL JOINs in any arm
** of the subquery. (This is a duplicate of condition (27b).)
** (17h) The corresponding result set expressions in all arms of the
-** compound must have the same affinity. (See restriction (9)
-** on the push-down optimization.)
+** compound must have the same affinity.
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -142576,7 +148181,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.
@@ -142620,7 +148226,8 @@ static int flattenSubquery(
assert( pSrc && iFrom>=0 && iFromnSrc );
pSubitem = &pSrc->a[iFrom];
iParent = pSubitem->iCursor;
- pSub = pSubitem->pSelect;
+ assert( pSubitem->fg.isSubquery );
+ pSub = pSubitem->u4.pSubq->pSelect;
assert( pSub!=0 );
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -142673,7 +148280,7 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
- || IsVirtual(pSubSrc->a[0].pTab) /* (3b) */
+ || IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
@@ -142686,9 +148293,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
@@ -142758,15 +148365,19 @@ static int flattenSubquery(
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
- /* Delete the transient structures associated with thesubquery */
- pSub1 = pSubitem->pSelect;
- sqlite3DbFree(db, pSubitem->zDatabase);
+ /* Delete the transient structures associated with the subquery */
+
+ if( ALWAYS(pSubitem->fg.isSubquery) ){
+ pSub1 = sqlite3SubqueryDetach(db, pSubitem);
+ }else{
+ pSub1 = 0;
+ }
+ assert( pSubitem->fg.isSubquery==0 );
+ assert( pSubitem->fg.fixedSchema==0 );
sqlite3DbFree(db, pSubitem->zName);
sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 );
/* If the sub-query is a compound SELECT statement, then (by restrictions
@@ -142807,8 +148418,8 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
- Table *pItemTab = pSubitem->pTab;
- pSubitem->pTab = 0;
+ Table *pItemTab = pSubitem->pSTab;
+ pSubitem->pSTab = 0;
p->pOrderBy = 0;
p->pPrior = 0;
p->pLimit = 0;
@@ -142816,7 +148427,7 @@ static int flattenSubquery(
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->op = TK_ALL;
- pSubitem->pTab = pItemTab;
+ pSubitem->pSTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
@@ -142831,11 +148442,14 @@ static int flattenSubquery(
TREETRACE(0x4,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- assert( pSubitem->pSelect==0 );
+ assert( pSubitem->fg.isSubquery==0 );
}
sqlite3DbFree(db, aCsrMap);
if( db->mallocFailed ){
- pSubitem->pSelect = pSub1;
+ assert( pSubitem->fg.fixedSchema==0 );
+ assert( pSubitem->fg.isSubquery==0 );
+ assert( pSubitem->u4.zDatabase==0 );
+ sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0);
return 1;
}
@@ -142846,18 +148460,16 @@ static int flattenSubquery(
**
** pSubitem->pTab is always non-NULL by test restrictions and tests above.
*/
- if( ALWAYS(pSubitem->pTab!=0) ){
- Table *pTabToDel = pSubitem->pTab;
+ if( ALWAYS(pSubitem->pSTab!=0) ){
+ Table *pTabToDel = pSubitem->pSTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- sqlite3ParserAddCleanup(pToplevel,
- (void(*)(sqlite3*,void*))sqlite3DeleteTable,
- pTabToDel);
+ sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
- pSubitem->pTab = 0;
+ pSubitem->pSTab = 0;
}
/* The following loop runs once for each term in a compound-subquery
@@ -142911,13 +148523,16 @@ static int flattenSubquery(
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
+ iNewParent = pSubSrc->a[0].iCursor;
for(i=0; ia[i+iFrom];
- if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
assert( pItem->fg.isTabFunc==0 );
+ assert( pItem->fg.isSubquery
+ || pItem->fg.fixedSchema
+ || pItem->u4.zDatabase==0 );
+ if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
*pItem = pSubSrc->a[i];
pItem->fg.jointype |= ltorj;
- iNewParent = pSubSrc->a[i].iCursor;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
@@ -142940,7 +148555,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
@@ -142957,6 +148572,7 @@ static int flattenSubquery(
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isOuterJoin>0 ){
+ assert( pSubSrc->nSrc==1 );
sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
}
if( pWhere ){
@@ -143000,8 +148616,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);
@@ -143036,7 +148651,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
@@ -143050,7 +148665,7 @@ static void constInsert(
){
int i;
assert( pColumn->op==TK_COLUMN );
- assert( sqlite3ExprIsConstant(pValue) );
+ assert( sqlite3ExprIsConstant(pConst->pParse, pValue) );
if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
if( sqlite3ExprAffinity(pValue)!=0 ) return;
@@ -143108,10 +148723,10 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
pLeft = pExpr->pLeft;
assert( pRight!=0 );
assert( pLeft!=0 );
- if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
+ if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){
constInsert(pConst,pRight,pLeft,pExpr);
}
- if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
+ if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){
constInsert(pConst,pLeft,pRight,pExpr);
}
}
@@ -143222,7 +148837,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
@@ -143306,7 +148921,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 );
@@ -143332,6 +148947,19 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
** The hope is that the terms added to the inner query will make it more
** efficient.
**
+** NAME AMBIGUITY
+**
+** This optimization is called the "WHERE-clause push-down optimization"
+** or sometimes the "predicate push-down optimization".
+**
+** Do not confuse this optimization with another unrelated optimization
+** with a similar name: The "MySQL push-down optimization" causes WHERE
+** clause terms that can be evaluated using only the index and without
+** reference to the table are run first, so that if they are false,
+** unnecessary table seeks are avoided.
+**
+** RULES
+**
** Do not attempt this optimization if:
**
** (1) (** This restriction was removed on 2017-09-29. We used to
@@ -143387,10 +149015,28 @@ 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) If the subquery is a compound, then all arms of the compound must
-** have the same affinity. (This is the same as restriction (17h)
-** for query flattening.)
+** (9) All three of the following are true:
+**
+** (9a) The WHERE clause expression originates in the ON or USING clause
+** of a join (either an INNER or an OUTER join), and
+**
+** (9b) The subquery is to the right of the ON/USING clause
+**
+** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING
+** clause and the subquery.
**
+** Without this restriction, the WHERE-clause push-down optimization
+** might move the ON/USING filter expression from the left side of a
+** RIGHT JOIN over to the right side, which leads to incorrect answers.
+** See also restriction (6) in sqlite3ExprIsSingleTableConstraint().
+**
+** (10) The inner query is not the right-hand table of a RIGHT JOIN.
+**
+** (11) The subquery is not a VALUES clause
+**
+** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This
+** case only comes up if SQLite is compiled using
+** SQLITE_ALLOW_ROWID_IN_VIEW.
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -143399,13 +149045,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;
@@ -143421,9 +149074,6 @@ static int pushDownWhereTerms(
if( pSel->pWin ) return 0; /* restriction (6b) */
#endif
}
- if( compoundHasDifferentAffinities(pSubq) ){
- return 0; /* restriction (9) */
- }
if( notUnionAll ){
/* If any of the compound arms are connected using UNION, INTERSECT,
** or EXCEPT, then we must ensure that none of the columns use a
@@ -143463,11 +149113,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)
@@ -143481,7 +149148,19 @@ static int pushDownWhereTerms(
}
#endif
- if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){
+ Expr *pLeft = pWhere->pLeft;
+ if( ALWAYS(pLeft)
+ && pLeft->op==TK_COLUMN
+ && pLeft->iColumn < 0
+ ){
+ return 0; /* Restriction (12) */
+ }
+ }
+#endif
+
+ if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc, 1) ){
nChng++;
pSubq->selFlags |= SF_PushDown;
while( pSubq ){
@@ -143515,6 +149194,78 @@ static int pushDownWhereTerms(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+/*
+** Check to see if a subquery contains result-set columns that are
+** never used. If it does, change the value of those result-set columns
+** to NULL so that they do not cause unnecessary work to compute.
+**
+** Return the number of column that were changed to NULL.
+*/
+static int disableUnusedSubqueryResultColumns(SrcItem *pItem){
+ int nCol;
+ Select *pSub; /* The subquery to be simplified */
+ Select *pX; /* For looping over compound elements of pSub */
+ Table *pTab; /* The table that describes the subquery */
+ int j; /* Column number */
+ int nChng = 0; /* Number of columns converted to NULL */
+ Bitmask colUsed; /* Columns that may not be NULLed out */
+
+ assert( pItem!=0 );
+ if( pItem->fg.isCorrelated || pItem->fg.isCte ){
+ return 0;
+ }
+ assert( pItem->pSTab!=0 );
+ pTab = pItem->pSTab;
+ assert( pItem->fg.isSubquery );
+ pSub = pItem->u4.pSubq->pSelect;
+ assert( pSub->pEList->nExpr==pTab->nCol );
+ for(pX=pSub; pX; pX=pX->pPrior){
+ if( (pX->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){
+ testcase( pX->selFlags & SF_Distinct );
+ testcase( pX->selFlags & SF_Aggregate );
+ return 0;
+ }
+ if( pX->pPrior && pX->op!=TK_ALL ){
+ /* This optimization does not work for compound subqueries that
+ ** use UNION, INTERSECT, or EXCEPT. Only UNION ALL is allowed. */
+ return 0;
+ }
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pX->pWin ){
+ /* This optimization does not work for subqueries that use window
+ ** functions. */
+ return 0;
+ }
+#endif
+ }
+ colUsed = pItem->colUsed;
+ if( pSub->pOrderBy ){
+ ExprList *pList = pSub->pOrderBy;
+ for(j=0; jnExpr; j++){
+ u16 iCol = pList->a[j].u.x.iOrderByCol;
+ if( iCol>0 ){
+ iCol--;
+ colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
+ }
+ }
+ }
+ nCol = pTab->nCol;
+ for(j=0; jpPrior) {
+ Expr *pY = pX->pEList->a[j].pExpr;
+ if( pY->op==TK_NULL ) continue;
+ pY->op = TK_NULL;
+ ExprClearProperty(pY, EP_Skip|EP_Unlikely);
+ pX->selFlags |= SF_PushDown;
+ nChng++;
+ }
+ }
+ return nChng;
+}
+
+
/*
** The pFunc is the only aggregate function in the query. Check to see
** if the query is a candidate for the min/max optimization.
@@ -143595,13 +149346,13 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( p->pWhere
|| p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1
- || p->pSrc->a[0].pSelect
+ || p->pSrc->a[0].fg.isSubquery
|| pAggInfo->nFunc!=1
|| p->pHaving
){
return 0;
}
- pTab = p->pSrc->a[0].pTab;
+ pTab = p->pSrc->a[0].pSTab;
assert( pTab!=0 );
assert( !IsView(pTab) );
if( !IsOrdinaryTable(pTab) ) return 0;
@@ -143626,7 +149377,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** pFrom->pIndex and return SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
- Table *pTab = pFrom->pTab;
+ Table *pTab = pFrom->pSTab;
char *zIndexedBy = pFrom->u1.zIndexedBy;
Index *pIdx;
assert( pTab!=0 );
@@ -143703,7 +149454,11 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
if( pNew==0 ) return WRC_Abort;
memset(&dummy, 0, sizeof(dummy));
pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0);
- if( pNewSrc==0 ) return WRC_Abort;
+ assert( pNewSrc!=0 || pParse->nErr );
+ if( pParse->nErr ){
+ sqlite3SrcListDelete(db, pNewSrc);
+ return WRC_Abort;
+ }
*pNew = *p;
p->pSrc = pNewSrc;
p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
@@ -143758,7 +149513,7 @@ static struct Cte *searchWith(
){
const char *zName = pItem->zName;
With *p;
- assert( pItem->zDatabase==0 );
+ assert( pItem->fg.fixedSchema || pItem->u4.zDatabase==0 );
assert( zName!=0 );
for(p=pWith; p; p=p->pOuter){
int i;
@@ -143793,8 +149548,7 @@ static struct Cte *searchWith(
SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
if( bFree ){
- pWith = (With*)sqlite3ParserAddCleanup(pParse,
- (void(*)(sqlite3*,void*))sqlite3WithDelete,
+ pWith = (With*)sqlite3ParserAddCleanup(pParse, sqlite3WithDeleteGeneric,
pWith);
if( pWith==0 ) return 0;
}
@@ -143829,7 +149583,7 @@ static int resolveFromTermToCte(
Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* The matching WITH */
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
if( pParse->pWith==0 ){
/* There are no WITH clauses in the stack. No match is possible */
return 0;
@@ -143839,7 +149593,8 @@ static int resolveFromTermToCte(
** go no further. */
return 0;
}
- if( pFrom->zDatabase!=0 ){
+ assert( pFrom->fg.hadSchema==0 || pFrom->fg.notCte!=0 );
+ if( pFrom->fg.fixedSchema==0 && pFrom->u4.zDatabase!=0 ){
/* The FROM term contains a schema qualifier (ex: main.t1) and so
** it cannot possibly be a CTE reference. */
return 0;
@@ -143875,7 +149630,7 @@ static int resolveFromTermToCte(
}
if( cannotBeFunction(pParse, pFrom) ) return 2;
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return 2;
pCteUse = pCte->pUse;
@@ -143889,26 +149644,29 @@ static int resolveFromTermToCte(
}
pCteUse->eM10d = pCte->eM10d;
}
- pFrom->pTab = pTab;
+ pFrom->pSTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
- pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
+ sqlite3SrcItemAttachSubquery(pParse, pFrom, pCte->pSelect, 1);
if( db->mallocFailed ) return 2;
- pFrom->pSelect->selFlags |= SF_CopyCte;
- assert( pFrom->pSelect );
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+ pSel = pFrom->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ pSel->selFlags |= SF_CopyCte;
if( pFrom->fg.isIndexedBy ){
sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
return 2;
}
+ assert( !pFrom->fg.isIndexedBy );
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
/* Check if this is a recursive CTE. */
- pRecTerm = pSel = pFrom->pSelect;
+ pRecTerm = pSel;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
@@ -143916,11 +149674,13 @@ static int resolveFromTermToCte(
assert( pRecTerm->pPrior!=0 );
for(i=0; inSrc; i++){
SrcItem *pItem = &pSrc->a[i];
- if( pItem->zDatabase==0
- && pItem->zName!=0
+ if( pItem->zName!=0
+ && !pItem->fg.hadSchema
+ && ALWAYS( !pItem->fg.isSubquery )
+ && (pItem->fg.fixedSchema || pItem->u4.zDatabase==0)
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
){
- pItem->pTab = pTab;
+ pItem->pSTab = pTab;
pTab->nTabRef++;
pItem->fg.isRecursive = 1;
if( pRecTerm->selFlags & SF_Recursive ){
@@ -144022,11 +149782,14 @@ SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){
** SQLITE_NOMEM.
*/
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
- Select *pSel = pFrom->pSelect;
+ Select *pSel;
Table *pTab;
+ assert( pFrom->fg.isSubquery );
+ assert( pFrom->u4.pSubq!=0 );
+ pSel = pFrom->u4.pSubq->pSelect;
assert( pSel );
- pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
+ pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
if( pTab==0 ) return SQLITE_NOMEM;
pTab->nTabRef = 1;
if( pFrom->zAlias ){
@@ -144037,12 +149800,14 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
+ pTab->eTabType = TABTYP_VIEW;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
/* The usual case - do not allow ROWID on a subquery */
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
- pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
+ /* Legacy compatibility mode */
+ pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid;
#endif
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
@@ -144144,33 +149909,35 @@ static int selectExpander(Walker *pWalker, Select *p){
*/
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
Table *pTab;
- assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
- if( pFrom->pTab ) continue;
+ assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 );
+ if( pFrom->pSTab ) continue;
assert( pFrom->fg.isRecursive==0 );
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
- Select *pSel = pFrom->pSelect;
+ Select *pSel;
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 );
+ pSel = pFrom->u4.pSubq->pSelect;
/* A sub-query in the FROM clause of a SELECT */
assert( pSel!=0 );
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
#ifndef SQLITE_OMIT_CTE
}else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
if( rc>1 ) return WRC_Abort;
- pTab = pFrom->pTab;
+ pTab = pFrom->pSTab;
assert( pTab!=0 );
#endif
}else{
/* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
+ assert( pFrom->pSTab==0 );
+ pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
if( pTab->nTabRef>=0xffff ){
sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
pTab->zName);
- pFrom->pTab = 0;
+ pFrom->pSTab = 0;
return WRC_Abort;
}
pTab->nTabRef++;
@@ -144182,7 +149949,7 @@ static int selectExpander(Walker *pWalker, Select *p){
i16 nCol;
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
- assert( pFrom->pSelect==0 );
+ assert( pFrom->fg.isSubquery==0 );
if( IsView(pTab) ){
if( (db->flags & SQLITE_EnableView)==0
&& pTab->pSchema!=db->aDb[1].pSchema
@@ -144190,7 +149957,7 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
- pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
+ sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( ALWAYS(IsVirtual(pTab))
@@ -144206,7 +149973,9 @@ static int selectExpander(Walker *pWalker, Select *p){
nCol = pTab->nCol;
pTab->nCol = -1;
pWalker->eCode = 1; /* Turn on Select.selId renumbering */
- sqlite3WalkSelect(pWalker, pFrom->pSelect);
+ if( pFrom->fg.isSubquery ){
+ sqlite3WalkSelect(pWalker, pFrom->u4.pSubq->pSelect);
+ }
pWalker->eCode = eCodeOrig;
pTab->nCol = nCol;
}
@@ -144279,13 +150048,21 @@ 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++){
- Table *pTab = pFrom->pTab; /* Table for this data source */
+ int nAdd; /* Number of cols including rowid */
+ Table *pTab = pFrom->pSTab; /* Table for this data source */
ExprList *pNestedFrom; /* Result-set of a nested FROM clause */
char *zTabName; /* AS name for this data source */
const char *zSchemaName = 0; /* Schema name for this data source */
@@ -144296,12 +150073,14 @@ static int selectExpander(Walker *pWalker, Select *p){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
- assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
+ assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom) );
if( pFrom->fg.isNestedFrom ){
- assert( pFrom->pSelect!=0 );
- pNestedFrom = pFrom->pSelect->pEList;
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+ assert( pFrom->u4.pSubq->pSelect!=0 );
+ pNestedFrom = pFrom->u4.pSubq->pSelect->pEList;
assert( pNestedFrom!=0 );
assert( pNestedFrom->nExpr==pTab->nCol );
+ assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
}else{
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
continue;
@@ -144319,6 +150098,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];
@@ -144331,33 +150111,49 @@ static int selectExpander(Walker *pWalker, Select *p){
}else{
pUsing = 0;
}
- for(j=0; jnCol; j++){
- char *zName = pTab->aCol[j].zCnName;
+
+ nAdd = pTab->nCol;
+ if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++;
+ 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 ){
@@ -144391,6 +150187,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}else{
pExpr = pRight;
}
+ sqlite3ExprSetErrorOffset(pExpr, iErrOfst);
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
if( pNew==0 ){
break; /* OOM */
@@ -144398,7 +150195,8 @@ static int selectExpander(Walker *pWalker, Select *p){
pX = &pNew->a[pNew->nExpr-1];
assert( pX->zEName==0 );
if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
- if( pNestedFrom ){
+ if( pNestedFrom && (!ViewCanHaveRowid || jnExpr) ){
+ assert( jnExpr );
pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
testcase( pX->zEName==0 );
}else{
@@ -144406,11 +150204,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;
}
@@ -144512,20 +150310,18 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
SrcList *pTabList;
SrcItem *pFrom;
- assert( p->selFlags & SF_Resolved );
if( p->selFlags & SF_HasTypeInfo ) return;
p->selFlags |= SF_HasTypeInfo;
pParse = pWalker->pParse;
+ assert( (p->selFlags & SF_Resolved) );
pTabList = p->pSrc;
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
+ Table *pTab = pFrom->pSTab;
assert( pTab!=0 );
- if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 && pFrom->fg.isSubquery ){
/* A sub-query in the FROM clause of a SELECT */
- Select *pSel = pFrom->pSelect;
- if( pSel ){
- sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
- }
+ Select *pSel = pFrom->u4.pSubq->pSelect;
+ sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
}
}
}
@@ -144585,6 +150381,8 @@ SQLITE_PRIVATE void sqlite3SelectPrep(
*/
static void printAggInfo(AggInfo *pAggInfo){
int ii;
+ sqlite3DebugPrintf("AggInfo %d/%p:\n",
+ pAggInfo->selId, pAggInfo);
for(ii=0; iinColumn; ii++){
struct AggInfo_col *pCol = &pAggInfo->aCol[ii];
sqlite3DebugPrintf(
@@ -144631,8 +150429,14 @@ static void analyzeAggFuncArgs(
pNC->ncFlags |= NC_InAggFunc;
for(i=0; i